Browse files

implement __new__

git-svn-id: https://svn.parrot.org/parrot/trunk@7318 d31e2699-5ff4-0310-a27c-f18f2fbe73fe
  • Loading branch information...
1 parent 768098f commit ab2d681ae2fcb36b41f91b1d32ed3e6c4612adc3 @rubys rubys committed Dec 20, 2004
View
51 dynclasses/pybuiltin.pmc
@@ -31,13 +31,15 @@ static INTVAL dynclass_PyFloat;
static INTVAL dynclass_PyList;
static INTVAL dynclass_PyLong;
static INTVAL dynclass_PyNone;
+static INTVAL dynclass_PyProxyType;
static INTVAL dynclass_PyString;
static INTVAL dynclass_PyTuple;
+static STRING *BASES;
static STRING *HEX;
+static STRING *NAME;
static STRING *OCT;
static STRING *PYOBJECT;
-static STRING *BASES;
extern PMC* Parrot_Hash_get_iter(Interp* interpreter, PMC* pmc);
@@ -46,12 +48,37 @@ extern PMC* Parrot_Hash_get_iter(Interp* interpreter, PMC* pmc);
PMC* Parrot_lib_python_group_init(Interp* interpreter, PMC *lib_pmc);
void Parrot_PyBuiltin___load__(Interp* interpreter, PMC* pmc);
-PMC*
-Parrot_lib_python_group_init(Interp* interpreter, PMC *lib_pmc)
-{
+PMC* Parrot_lib_python_group_init(Interp* interpreter, PMC *lib_pmc) {
Parrot_PyBuiltin___load__(interpreter, NULL);
return lib_pmc;
}
+
+static PMC* make_type(Interp* interpreter, INTVAL class, STRING* name) {
+ STRING *pmcname = Parrot_base_vtables[class]->whoami;
+ PMC *type = pmc_new(interpreter, dynclass_PyProxyType);
+ PMC *nameprop = pmc_new(interpreter, dynclass_PyString);
+ PMC *stash, *iter, *item;
+ STRING *key;
+ INTVAL n, j;
+
+ stash = Parrot_find_global(interpreter, pmcname, NULL);
+ if (!stash) internal_exception(1, "Can't find methods");
+
+ /* For each, extract the key and item, and store in the scratchpad */
+ iter = Parrot_Hash_get_iter(interpreter, stash);
+ n = VTABLE_elements(interpreter, stash);
+ for (j = 0; j < n; ++j) {
+ key = VTABLE_shift_string(interpreter, iter);
+ item = VTABLE_get_pmc_keyed_str(interpreter, stash, key);
+ VTABLE_add_method(interpreter, type, key, item);
+ }
+
+ VTABLE_set_string_native(interpreter, nameprop, name);
+ VTABLE_setprop(interpreter, type, NAME, nameprop);
+
+ return type;
+}
+
pmclass PyBuiltin dynpmc group python_group {
/*
@@ -76,11 +103,13 @@ they will be used frequently here.
dynclass_PyList = Parrot_PMC_typenum(INTERP, "PyList");
dynclass_PyLong = Parrot_PMC_typenum(INTERP, "PyLong");
dynclass_PyNone = Parrot_PMC_typenum(INTERP, "PyNone");
+ dynclass_PyProxyType = Parrot_PMC_typenum(INTERP, "PyProxyType");
dynclass_PyString = Parrot_PMC_typenum(INTERP, "PyString");
dynclass_PyTuple = Parrot_PMC_typenum(INTERP, "PyTuple");
BASES = const_string(INTERP, "__bases__");
HEX = const_string(INTERP, "__hex__");
+ NAME = const_string(INTERP, "__name__");
OCT = const_string(INTERP, "__oct__");
PYOBJECT = const_string(INTERP, "PyObject");
}
@@ -107,7 +136,7 @@ enter_nci_method should create these as locals to begin with.
METHOD void __load__() {
STRING *name, *key;
- PMC *stash, *iter, *item, *pad, *temp;
+ PMC *stash, *iter, *item, *pad, *temp, *parent;
INTVAL j, n;
/* Already init'ed? */
@@ -173,15 +202,17 @@ enter_nci_method should create these as locals to begin with.
scratchpad_store_by_name(INTERP, pad, 0, key, item);
/* Class objects */
- /* TODO: convert this to instances of <type> */
+ key = const_string(INTERP, "object");
+ parent = make_type(INTERP, dynclass_PyObject, key);
+
key = const_string(INTERP, "dict");
- item = pmc_new(INTERP, dynclass_PyDict);
+ item = make_type(INTERP, dynclass_PyDict, key);
+ VTABLE_setprop(INTERP, item, BASES, parent);
scratchpad_store_by_name(INTERP, pad, 0, key, item);
- /* TODO: convert this to instances of <type> */
key = const_string(INTERP, "int");
- item = pmc_new(INTERP, dynclass_PyInt);
- VTABLE_set_integer_native(INTERP, item, 15);
+ item = make_type(INTERP, dynclass_PyInt, key);
+ VTABLE_setprop(INTERP, item, BASES, parent);
scratchpad_store_by_name(INTERP, pad, 0, key, item);
/* TODO: convert this to instances of <type> */
View
5 dynclasses/pyclass.pmc
@@ -30,7 +30,10 @@ static STRING *NAME;
static STRING *REPR;
static STRING *STR;
-static struct parrot_regs_t *
+struct parrot_regs_t *
+Parrot_PyClass_runops_fromc(Parrot_Interp interpreter, PMC *sub);
+
+struct parrot_regs_t *
Parrot_PyClass_runops_fromc(Parrot_Interp interpreter, PMC *sub)
{
opcode_t offset, *dest;
View
16 dynclasses/pydict.pmc
@@ -375,27 +375,20 @@ Returns the big number value for the element at C<*key>.
/*
-=item C<void* invoke(void *next)>
+=item C<PMC* "__new__"(PMC *cls, PMC *source)>
Create a new dictionary from a sequence
=cut
-TODO: move this to the dict type as this is meant to be a class method
-not an instance method.
-
*/
- void* invoke(void *next) {
+ METHOD PMC* __new__(PMC *cls, PMC *source) {
PMC *dict = pmc_new(INTERP, dynclass_PyDict);
- PMC *source = REG_PMC(5);
PMC *iter;
INTVAL argc = REG_INT(3);
- REG_INT(3) = 1;
- REG_PMC(5) = dict;
-
- if (argc == 0) return next;
+ if (argc == 1) return dict;
if (source->vtable->base_type == dynclass_PyDict) {
iter = VTABLE_get_iter(INTERP, source);
@@ -426,8 +419,7 @@ not an instance method.
}
}
-
- return next;
+ return dict;
}
/*
View
44 dynclasses/pyint.pmc
@@ -27,8 +27,6 @@ static INTVAL dynclass_PyFloat;
static INTVAL dynclass_PyLong;
static INTVAL dynclass_PyString;
-static PMC* base_class;
-
static void
overflow(Interp *interpreter, PMC *self, INTVAL b, PMC *dest, int mmd)
{
@@ -82,9 +80,6 @@ they will be used frequently here.
dynclass_PyFloat = Parrot_PMC_typenum(INTERP, "PyFloat");
dynclass_PyLong = Parrot_PMC_typenum(INTERP, "PyLong");
dynclass_PyString = Parrot_PMC_typenum(INTERP, "PyString");
-
- /* TODO: make Int have a real base class */
- base_class = pmc_new(INTERP, dynclass_PyInt);
}
}
@@ -584,20 +579,6 @@ Returns the boolean value of the integer.
/*
-=item C<PMC *get_class()>
-
-Return the class of this object.
-
-=cut
-
-*/
-
- PMC* get_class() {
- return base_class;
- }
-
-/*
-
=item C<INTVAL get_integer()>
Returns the integer value of the integer.
@@ -654,32 +635,28 @@ Returns a unique hash for this value
/*
-=item C<void* invoke(void *next)>
+=item C<PMC* "__new__"(PMC *class, PMC *source)>
Create a new integer
=cut
-TODO: move this to the int type as this is meant to be a class method
-not an instance method.
-
*/
- void* invoke(void *next) {
+ METHOD PMC* __new__(PMC *class, PMC *source) {
INTVAL argc = REG_INT(3);
- PMC *source = REG_PMC(5);
PMC * ret = pmc_new(INTERP, dynclass_PyInt);
- REG_INT(3) = 1;
- REG_PMC(5) = ret;
+ /* XXX: quick hack: class method called directly */
+ if (argc == 3 && class == SELF) source = REG_PMC(7);
- if (argc > 0) {
+ if (argc > 1) {
INTVAL ivalue = VTABLE_get_integer(INTERP, source);
VTABLE_set_integer_native(INTERP, ret, ivalue);
}
- return next;
+ return ret;
}
/*
@@ -693,8 +670,13 @@ The C<==> operation.
*/
INTVAL is_equal (PMC* value) {
- return (INTVAL)(PMC_int_val(SELF) ==
- VTABLE_get_integer(INTERP, value));
+MMD_PyNone: {
+ return 0;
+ }
+MMD_DEFAULT: {
+ return (INTVAL)(PMC_int_val(SELF) ==
+ VTABLE_get_integer(INTERP, value));
+ }
}
/*
View
6 dynclasses/pylist.pmc
@@ -68,7 +68,7 @@ Initializes the PMC by calling the underlying C<list_new()> function.
/*
-=item C<void "append" (PMC* value)>
+=item C<void "append" (PMC* self, PMC* value)>
Extends the array by adding an element of value C<*value> to the end of
the array.
@@ -77,8 +77,8 @@ the array.
*/
- METHOD void append (PMC* value) {
- VTABLE_push_pmc(INTERP, SELF, value);
+ METHOD void append (PMC* self, PMC* value) {
+ VTABLE_push_pmc(INTERP, self, value);
}
/*
View
19 dynclasses/pynone.pmc
@@ -57,6 +57,25 @@ Return "None"
/*
+=item C<INTVAL is_equal (PMC* value)>
+
+The C<==> operation.
+
+=cut
+
+*/
+
+ INTVAL is_equal (PMC* value) {
+MMD_PyNone: {
+ return 1;
+ }
+MMD_DEFAULT: {
+ return 0;
+ }
+ }
+
+/*
+
=back
=cut
View
61 dynclasses/pyobject.pmc
@@ -762,67 +762,6 @@ according to the type of C<*value>.
/*
-=item C<PMC *find_method(STRING *method_name)>
-
-Looks up the method for C<*method_name> and returns it. If no method is
-found then lookup an attribute by this name, and return it. If all else
-fails, return null.
-
-=cut
-
-TODO: create separate type objects for each builtin type which has
-direct pointer to the global hash for this particular class.
-
-*/
-
- PMC* find_method(STRING* method_name) {
- return Parrot_default_find_method(INTERP, SELF, method_name);
- }
-
-/*
-
-=item C<PMC* subclass(STRING *name)>
-
-Create a subclass of the builtin class. In additon to creating a
-new class (of type PyProxyType), an instance of PyProxyClass is also
-created and defined as the base class for the new class.
-
-See the description of PyProxyType and PyProxyClass to see how
-new instances are created and how methods are forwarded respectively.
-
-=cut
-
-TODO: create separate type objects for each builtin type and replace
-this logic with a TypeError.
-
-*/
-
- PMC* subclass(STRING* name) {
- INTVAL dynclass_PyProxyType, dynclass_PyProxyClass;
- PMC *proxy_type, *proxy_class, *nameprop;
- STRING *NAME, *BASES;
-
- dynclass_PyProxyClass = Parrot_PMC_typenum(INTERP, "PyProxyClass");
- proxy_class = pmc_new(INTERP, dynclass_PyProxyClass);
-
- BASES = const_string(INTERP, "__bases__");
- VTABLE_setprop(INTERP, proxy_class, BASES, SELF);
-
- dynclass_PyProxyType = Parrot_PMC_typenum(INTERP, "PyProxyType");
- proxy_type = pmc_new(INTERP, dynclass_PyProxyType);
-
- NAME = const_string(INTERP, "__name__");
- nameprop = pmc_new(INTERP, dynclass_PyString);
- VTABLE_setprop(INTERP, proxy_type, NAME, nameprop);
- VTABLE_set_string_native(INTERP, nameprop, name);
-
- VTABLE_setprop(INTERP, proxy_type, BASES, proxy_class);
-
- return proxy_type;
- }
-
-/*
-
=back
=cut
View
2 dynclasses/pyproxyclass.pmc
@@ -26,7 +26,7 @@ TODO: handle attributes.
static INTVAL dynclass_PyProxyClass;
static STRING *PROXY;
-pmclass PyProxyClass extends PyObject dynpmc group python_group {
+pmclass PyProxyClass extends PyType dynpmc group python_group {
/*
View
90 dynclasses/pyproxytype.pmc
@@ -65,13 +65,18 @@ While this seems like a lot of work, lets consider all the cases:
static INTVAL dynclass_PyClass;
static INTVAL dynclass_PyString;
+static INTVAL dynclass_PyProxyClass;
static INTVAL dynclass_PyProxyType;
static STRING *BASES;
static STRING *CLASS;
static STRING *INIT;
static STRING *NAME;
+static STRING *NEW;
static STRING *PROXY;
+struct parrot_regs_t *
+Parrot_PyClass_runops_fromc(Parrot_Interp interpreter, PMC *sub);
+
pmclass PyProxyType extends PyType dynpmc group python_group {
/*
@@ -87,13 +92,15 @@ they will be used frequently here.
void class_init() {
if (pass) {
+ dynclass_PyProxyClass = Parrot_PMC_typenum(INTERP, "PyProxyClass");
dynclass_PyProxyType = Parrot_PMC_typenum(INTERP, "PyProxyType");
dynclass_PyClass = Parrot_PMC_typenum(INTERP, "PyClass");
dynclass_PyString = Parrot_PMC_typenum(INTERP, "PyString");
BASES = const_string(INTERP, "__bases__");
CLASS = const_string(INTERP, "__class__");
INIT = const_string(INTERP, "__init__");
NAME = const_string(INTERP, "__name__");
+ NEW = const_string(INTERP, "__new__");
PROXY = const_string(INTERP, "__proxy__");
}
}
@@ -109,39 +116,55 @@ initializers with arguments to be run.
=cut
-TODO: reconcile this with Parrot's instantiate VTABLE entry.
-
*/
void* invoke(void *next) {
- PMC *proxy_class, *object_class, *proxy, *object, *init;
-
- proxy_class = VTABLE_getprop(INTERP, SELF, BASES);
- object_class = VTABLE_getprop(INTERP, proxy_class, BASES);
- while (1) {
- PMC *parent_class = VTABLE_getprop(INTERP, object_class, BASES);
- if (!parent_class || !VTABLE_defined(INTERP, parent_class))
- break;
- object_class = parent_class;
+ PMC *object_class, *proxy, *object, *init, *new;
+
+ object_class = VTABLE_getprop(INTERP, SELF, PROXY);
+ if (!object_class || !VTABLE_defined(INTERP, object_class))
+ object_class = SELF;
+
+ new = VTABLE_find_method(INTERP, SELF, NEW);
+ init = VTABLE_find_method(INTERP, SELF, INIT);
+ if (new || init) {
+ int i = REG_INT(3)++;
+ while (i--)
+ REG_PMC(6+i)=REG_PMC(5+i);
}
- object = pmc_new(INTERP, object_class->vtable->base_type);
+ if (new) {
+ struct parrot_regs_t *bp;
+ struct Parrot_Context ctx;
+ save_context(interpreter, &ctx);
+ INTERP->ctx.current_object = SELF;
+ REG_PMC(5) = SELF;
+ bp = Parrot_PyClass_runops_fromc(INTERP, new);
+ object = BP_REG_PMC(bp,5);
+ restore_context(interpreter, &ctx);
+ }
+ else {
+ object = pmc_new(INTERP, object_class->vtable->base_type);
+ }
- proxy = pmc_new(interpreter, dynclass_PyClass);
- VTABLE_setprop(INTERP, proxy, CLASS, REG_PMC(0));
+ if (object_class == SELF)
+ proxy = object;
+ else {
+ proxy = pmc_new(interpreter, dynclass_PyClass);
+ VTABLE_setprop(INTERP, proxy, CLASS, REG_PMC(0));
+ VTABLE_setprop(INTERP, proxy, PROXY, object);
+ }
- init = VTABLE_find_method(INTERP, proxy, INIT);
if (init) {
+ struct Parrot_Context ctx;
+ save_context(interpreter, &ctx);
INTERP->ctx.current_object = proxy;
- Parrot_runops_fromc(INTERP, init);
- }
- else {
- VTABLE_invoke(INTERP, object, next);
- object = REG_PMC(5);
+ REG_PMC(5) = proxy;
+ Parrot_PyClass_runops_fromc(INTERP, init);
+ restore_context(interpreter, &ctx);
}
- VTABLE_setprop(INTERP, proxy, PROXY, object);
-
+ REG_INT(3) = 1;
REG_PMC(5) = proxy;
return next;
}
@@ -159,12 +182,27 @@ need to be filled in.
*/
PMC* subclass(STRING* name) {
- PMC *ret = pmc_new(INTERP, dynclass_PyProxyType);
+ PMC *newclass = pmc_new(INTERP, dynclass_PyProxyType);
+ PMC *proxy = VTABLE_getprop(INTERP, SELF, PROXY);
PMC *nameprop = pmc_new(INTERP, dynclass_PyString);
+
+ if (proxy && VTABLE_defined(INTERP, proxy)) {
+ /* proxy is already set up */
+ VTABLE_setprop(INTERP, newclass, BASES, SELF);
+ VTABLE_setprop(INTERP, newclass, PROXY, proxy);
+ }
+ else {
+ /* need to create a proxy class */
+ PMC *proxy_class = pmc_new(INTERP, dynclass_PyProxyClass);
+ VTABLE_setprop(INTERP, proxy_class, BASES, SELF);
+ VTABLE_setprop(INTERP, newclass, BASES, proxy_class);
+ VTABLE_setprop(INTERP, newclass, PROXY, SELF);
+ }
+
VTABLE_set_string_native(INTERP, nameprop, name);
- VTABLE_setprop(INTERP, ret, NAME, nameprop);
- VTABLE_setprop(INTERP, ret, BASES, SELF);
- return ret;
+ VTABLE_setprop(INTERP, newclass, NAME, nameprop);
+
+ return newclass;
}
/*
View
71 dynclasses/pytype.pmc
@@ -25,11 +25,14 @@ methods you would expect to see on Python Classes
static INTVAL dynclass_PyClass;
static INTVAL dynclass_PyString;
static INTVAL dynclass_PyType;
+static STRING *BASES;
static STRING *CLASS;
static STRING *INIT;
static STRING *NAME;
-static STRING *BASES;
-static STRING *PYTYPE;
+static STRING *NEW;
+
+struct parrot_regs_t *
+Parrot_PyClass_runops_fromc(Parrot_Interp interpreter, PMC *sub);
pmclass PyType dynpmc group python_group {
@@ -49,16 +52,30 @@ they will be used frequently here.
dynclass_PyClass = Parrot_PMC_typenum(INTERP, "PyClass");
dynclass_PyString = Parrot_PMC_typenum(INTERP, "PyString");
dynclass_PyType = Parrot_PMC_typenum(INTERP, "PyType");
- CLASS = const_string(INTERP, "__class__");
- INIT = const_string(INTERP, "__init__");
- NAME = const_string(INTERP, "__name__");
BASES = const_string(INTERP, "__bases__");
- PYTYPE = const_string(INTERP, "PyType");
+ CLASS = const_string(INTERP, "__class__");
+ INIT = const_string(INTERP, "__init__");
+ NAME = const_string(INTERP, "__name__");
+ NEW = const_string(INTERP, "__new__");
}
}
/*
+=item C<void add_method(STRING *method_name, PMC *sub)>
+
+Store the method as a property of this class.
+
+=cut
+
+*/
+
+ void add_method(STRING *method_name, PMC *sub_pmc) {
+ VTABLE_setprop(INTERP, SELF, method_name, sub_pmc);
+ }
+
+/*
+
=item C<PMC *find_method(STRING *method_name)>
Looks up the method for C<*method_name> and returns it.
@@ -74,7 +91,7 @@ Looks up the method for C<*method_name> and returns it.
if (method && VTABLE_defined(INTERP, method)) return method;
parent = VTABLE_getprop(INTERP, SELF, BASES);
- if (parent) {
+ if (parent && VTABLE_defined(INTERP, parent)) {
return VTABLE_find_method(INTERP, parent, method_name);
}
@@ -98,7 +115,7 @@ Return attribute named C<name>.
if (attr && VTABLE_defined(INTERP, attr)) return attr;
parent = VTABLE_getprop(INTERP, SELF, BASES);
- if (parent) {
+ if (parent && VTABLE_defined(INTERP, parent)) {
attr = VTABLE_get_attr_str(INTERP, parent, idx);
}
@@ -124,21 +141,43 @@ Pythonic object constructor.
*/
void* invoke(void* next) {
- PMC *object, *init;
+ PMC *object, *init, *new;
+
+ new = VTABLE_find_method(INTERP, SELF, NEW);
+ init = VTABLE_find_method(INTERP, SELF, INIT);
+
+ if (new || init) {
+ int i = REG_INT(3)++;
+ while (i--)
+ REG_PMC(6+i)=REG_PMC(5+i);
+ }
+
+ if (new) {
+ struct parrot_regs_t *bp;
+ struct Parrot_Context ctx;
+ save_context(interpreter, &ctx);
+ INTERP->ctx.current_object = SELF;
+ REG_PMC(5) = SELF;
+ bp = Parrot_PyClass_runops_fromc(INTERP, new);
+ object = BP_REG_PMC(bp,5);
+ restore_context(interpreter, &ctx);
+ }
+ else {
+ object = pmc_new(interpreter, dynclass_PyClass);
+ }
- object = pmc_new(interpreter, dynclass_PyClass);
VTABLE_setprop(INTERP, object, CLASS, REG_PMC(0));
- init = VTABLE_find_method(INTERP, object, INIT);
if (init) {
- int i = REG_INT(3)++;
- for (i=REG_INT(3); i>0; i--)
- REG_PMC(5+i)=REG_PMC(4+i);
- REG_PMC(5) = object;
+ struct Parrot_Context ctx;
+ save_context(interpreter, &ctx);
INTERP->ctx.current_object = object;
- Parrot_runops_fromc(INTERP, init);
+ REG_PMC(5) = object;
+ Parrot_PyClass_runops_fromc(INTERP, init);
+ restore_context(interpreter, &ctx);
}
+ REG_INT(3) = 1;
REG_PMC(5) = object;
return next;
}
View
2 languages/python/README
@@ -23,7 +23,7 @@ Benchmark status/issues:
b1: passes.
b2: passes.
- b3: need to implement __new__
+ b3: need to implement list.sort
b4: there is no b4!
b5: awaiting completion of float, complex, ...
b6: requires a dictionary with integer keys.

0 comments on commit ab2d681

Please sign in to comment.