--- ceval.00.c 2008-10-20 18:47:46.625188000 -0700 +++ ceval.c 2008-10-20 15:35:29.459550000 -0700 @@ -19,6 +19,77 @@ #include + + + + + + + + + + + + + + +//////////////////////////////////////////////////////////////// py3k beg - header +// README - ALL EDITS MARKED W/ TAG: "// py3k" + +// backported opcodes +// standard python-2.6 codeobj should never contain any of these opcodes +#define SET_ADD_py3k 17 // 17 in py3k +#define STORE_LOCALS_py3k 69 // 69 in py3k +#define LOAD_BUILD_CLASS_py3k 34 // 71 in py3k +#define MAKE_BYTES_py3k 35 // 85 in py3k +#define POP_EXCEPT_py3k 36 // 89 in py3k +#define UNPACK_EX_py3k 94 // 94 in py3k +#define BUILD_SET_py3k 192 // 104 in py3k +#define MAKE_FUNCTION_py3k 193 // 132 in py3k - override MAKE_FUNCTION + +// user-defined opcodes +#define LOAD_ATTR_py3k 194 // enable object.__curry__ feature - override LOAD_ATTR +#define INIT_BUILTINS_py3k 37 // init & add builtins_py3k module to builtins + +// macros +#define PyCode_ISPY3K(co) ((co)->co_argcount & 0xffff0000) // check if py3k codeobj +#define PyCode_GETARGCOUNT(co) ((co)->co_argcount & 0xffff) // retrieve co_argcount w/ metaflag removed +#define PyCode_GETKWONLYARGCOUNT(co) (((co)->co_argcount >> 16) & 0xff) // get kwonlyargcount from metaflag + +// prototypes +static PyObject * // init & add builtins_py3k module to builtins +init_builtins_py3k(void); + +static int // from python-3.0rc1/Python/ceval.c +unpack_iterable_py3k(PyObject *v, int argcnt, int argcntafter, PyObject **sp); + +static PyObject *PyEval_GetBuiltins_py3k(void); + +static PyObject * // patched w/ PEP 3102 Keyword-Only Arguments +PyEval_EvalCodeEx_py3k(PyCodeObject *co, PyObject *globals, PyObject *locals, + PyObject **args, int argcount, PyObject **kws, int kwcount, + PyObject **defs, int defcount, PyObject *kwdefs, PyObject *closure); + +static PyTypeObject PyCurry_Type; + +static PyObject * // func(arg1, ...) -> func(self, ...) +curry_new(PyObject *self); +//////////////////////////////////////////////////////////////// py3k end + + + + + + + + + + + + + + + #ifndef WITH_TSC #define READ_TIMESTAMP(var) @@ -534,6 +605,7 @@ PyObject * PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) { + PyObject *builtins_py3k = PyCode_ISPY3K(f->f_code) ? PyEval_GetBuiltins_py3k() : f->f_builtins; // py3k #ifdef DXPAIRS int lastopcode = 0; #endif @@ -1880,7 +1952,7 @@ if (x == NULL) { x = PyDict_GetItem(f->f_globals, w); if (x == NULL) { - x = PyDict_GetItem(f->f_builtins, w); + x = PyDict_GetItem(builtins_py3k, w); if (x == NULL) { format_exc_check_arg( PyExc_NameError, @@ -1915,7 +1987,7 @@ PUSH(x); continue; } - d = (PyDictObject *)(f->f_builtins); + d = (PyDictObject *)(builtins_py3k); e = d->ma_lookup(d, w, hash); if (e == NULL) { x = NULL; @@ -1933,7 +2005,7 @@ /* This is the un-inlined version of the code above */ x = PyDict_GetItem(f->f_globals, w); if (x == NULL) { - x = PyDict_GetItem(f->f_builtins, w); + x = PyDict_GetItem(builtins_py3k, w); if (x == NULL) { load_global_error: format_exc_check_arg( @@ -2087,7 +2159,7 @@ case IMPORT_NAME: w = GETITEM(names, oparg); - x = PyDict_GetItemString(f->f_builtins, "__import__"); + x = PyDict_GetItemString(builtins_py3k, "__import__"); if (x == NULL) { PyErr_SetString(PyExc_ImportError, "__import__ not found"); @@ -2492,6 +2564,173 @@ oparg = oparg<<16 | NEXTARG(); goto dispatch_opcode; +//////////////////////////////////////////////////////////////// py3k beg - add new opcodes here + if (PyCode_ISPY3K(f->f_code)) { + + case SET_ADD_py3k: + w = POP(); + v = POP(); + err = PySet_Add(v, w); + Py_DECREF(v); + Py_DECREF(w); + if (err == 0) { + PREDICT(JUMP_ABSOLUTE); + continue; + } + break; + + case STORE_LOCALS_py3k: + x = POP(); + v = f->f_locals; + Py_XDECREF(v); + f->f_locals = x; + continue; + + case LOAD_BUILD_CLASS_py3k: + x = PyDict_GetItemString(builtins_py3k, + "__build_class__"); + if (x == NULL) { + PyErr_SetString(PyExc_ImportError, + "__build_class__ not found"); + break; + } + Py_INCREF(x); + PUSH(x); + break; + + // case MAKE_BYTES_py3k - unused + + // case POP_EXCEPT_py3k - unused + + case UNPACK_EX_py3k: + { + int totalargs = 1 + (oparg & 0xFF) + (oparg >> 8); + v = POP(); + + if (unpack_iterable_py3k(v, oparg & 0xFF, oparg >> 8, + stack_pointer + totalargs)) { + stack_pointer += totalargs; + } else { + why = WHY_EXCEPTION; + } + Py_DECREF(v); + break; + } + + case BUILD_SET_py3k: + x = PySet_New(NULL); + if (x != NULL) { + for (; --oparg >= 0;) { + w = POP(); + if (err == 0) + err = PySet_Add(x, w); + Py_DECREF(w); + } + if (err != 0) { + Py_DECREF(x); + break; + } + PUSH(x); + continue; + } + break; + + case MAKE_FUNCTION_py3k: + { + int posdefaults = oparg & 0xff; + int kwdefaults = (oparg>>8) & 0xff; + int num_annotations = (oparg >> 16) & 0x7fff; + + v = POP(); /* code object */ + x = PyFunction_New(v, f->f_globals); + Py_DECREF(v); + + if (x != NULL && opcode == MAKE_CLOSURE) { + v = POP(); + err = PyFunction_SetClosure(x, v); + Py_DECREF(v); + } + + if (x != NULL && num_annotations > 0) { + Py_ssize_t name_ix; + u = POP(); /* names of args with annotations */ + v = PyDict_New(); + if (v == NULL) { + Py_DECREF(x); + x = NULL; + break; + } + name_ix = PyTuple_Size(u); + assert(num_annotations == name_ix+1); + while (name_ix > 0) { + --name_ix; + t = PyTuple_GET_ITEM(u, name_ix); + w = POP(); + /* XXX(nnorwitz): check for errors */ + PyDict_SetItem(v, t, w); + Py_DECREF(w); + } + + err = PyObject_SetAttrString(x, "__annotations__", v); // py3k + // err = PyFunction_SetAnnotations(x, v); + Py_DECREF(v); + Py_DECREF(u); + } + + /* XXX Maybe this should be a separate opcode? */ + if (x != NULL && posdefaults > 0) { + v = PyTuple_New(posdefaults); + if (v == NULL) { + Py_DECREF(x); + x = NULL; + break; + } + while (--posdefaults >= 0) { + w = POP(); + PyTuple_SET_ITEM(v, posdefaults, w); + } + err = PyFunction_SetDefaults(x, v); + Py_DECREF(v); + } + if (x != NULL && kwdefaults > 0) { + v = PyDict_New(); + if (v == NULL) { + Py_DECREF(x); + x = NULL; + break; + } + while (--kwdefaults >= 0) { + w = POP(); /* default value */ + u = POP(); /* kw only arg name */ + /* XXX(nnorwitz): check for errors */ + PyDict_SetItem(v, u, w); + Py_DECREF(w); + Py_DECREF(u); + } + err = PyObject_SetAttrString(x, "__kwdefaults__", v); // py3k + // err = PyFunction_SetKwDefaults(x, v); + Py_DECREF(v); + } + PUSH(x); + break; + } + + case LOAD_ATTR_py3k: + w = GETITEM(names, oparg); + v = TOP(); + x = strcmp(PyString_AsString(w), "__curry__") == 0 ? curry_new(v) : PyObject_GetAttr(v, w); // obj.__curry__.foo(...) -> foo(obj, ...) + Py_DECREF(v); + SET_TOP(x); + if (x != NULL) continue; + break; + + case INIT_BUILTINS_py3k: + if (init_builtins_py3k() != NULL) continue; + break; + + } +//////////////////////////////////////////////////////////////// py3k end + default: fprintf(stderr, "XXX lineno: %d, opcode: %d\n", @@ -2712,6 +2951,19 @@ PyObject **args, int argcount, PyObject **kws, int kwcount, PyObject **defs, int defcount, PyObject *closure) { +// py3k beg + if PyCode_ISPY3K(co) { + PyObject *kwdefs = NULL; + if PyCode_GETKWONLYARGCOUNT(co) { // recall fast_function replaced globals w/ func + kwdefs = PyObject_GetAttrString(globals, "__kwdefaults__"); // get kwdefs from func + globals = PyFunction_GET_GLOBALS(globals); // get globals from func + } + PyObject *retval = PyEval_EvalCodeEx_py3k(co, globals, locals, + args, argcount, kws, kwcount, + defs, defcount, kwdefs, closure); + Py_XDECREF(kwdefs); return retval; + } +// py3k end register PyFrameObject *f; register PyObject *retval = NULL; register PyObject **fastlocals, **freevars; @@ -3736,7 +3988,8 @@ PCALL(PCALL_FUNCTION); PCALL(PCALL_FAST_FUNCTION); - if (argdefs == NULL && co->co_argcount == n && nk==0 && + if (argdefs == NULL && PyCode_GETARGCOUNT(co) == n && nk==0 && // py3k + PyCode_GETKWONLYARGCOUNT(co) == 0 && // py3k co->co_flags == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE)) { PyFrameObject *f; PyObject *retval = NULL; @@ -3772,7 +4025,7 @@ d = &PyTuple_GET_ITEM(argdefs, 0); nd = Py_SIZE(argdefs); } - return PyEval_EvalCodeEx(co, globals, + return PyEval_EvalCodeEx(co, PyCode_GETKWONLYARGCOUNT(co) ? func : globals, // py3k - replace globals argument w/ func - globals can always be retrieved from func (PyObject *)NULL, (*pp_stack)-n, na, (*pp_stack)-2*nk, nk, d, nd, PyFunction_GET_CLOSURE(func)); @@ -4543,3 +4796,1336 @@ } #endif + + + + + + + + + + + + + + + +//////////////////////////////////////////////////////////////// py3k beg - footer +//////// py3k - prototypes flesh +static int +unpack_iterable_py3k(PyObject *v, int argcnt, int argcntafter, PyObject **sp) +{ + int i = 0, j = 0; + Py_ssize_t ll = 0; + PyObject *it; /* iter(v) */ + PyObject *w; + PyObject *l = NULL; /* variable list */ + + assert(v != NULL); + + it = PyObject_GetIter(v); + if (it == NULL) + goto Error; + + for (; i < argcnt; i++) { + w = PyIter_Next(it); + if (w == NULL) { + /* Iterator done, via error or exhaustion. */ + if (!PyErr_Occurred()) { + PyErr_Format(PyExc_ValueError, + "need more than %d value%s to unpack", + i, i == 1 ? "" : "s"); + } + goto Error; + } + *--sp = w; + } + + if (argcntafter == -1) { + /* We better have exhausted the iterator now. */ + w = PyIter_Next(it); + if (w == NULL) { + if (PyErr_Occurred()) + goto Error; + Py_DECREF(it); + return 1; + } + Py_DECREF(w); + PyErr_SetString(PyExc_ValueError, "too many values to unpack"); + goto Error; + } + + l = PySequence_List(it); + if (l == NULL) + goto Error; + *--sp = l; + i++; + + ll = PyList_GET_SIZE(l); + if (ll < argcntafter) { + PyErr_Format(PyExc_ValueError, "need more than %zd values to unpack", + argcnt + ll); + goto Error; + } + + /* Pop the "after-variable" args off the list. */ + for (j = argcntafter; j > 0; j--, i++) { + *--sp = PyList_GET_ITEM(l, ll - j); + } + /* Resize the list. */ + Py_SIZE(l) = ll - argcntafter; + Py_DECREF(it); + return 1; + +Error: + for (; i > 0; i--, sp++) + Py_DECREF(*sp); + Py_XDECREF(it); + return 0; +} + +static PyObject *PyEval_GetBuiltins_py3k(void) { + PyObject *m = PyDict_GetItemString( PyEval_GetBuiltins(), "builtins_py3k" ); + if (m == NULL) return NULL; + return PyModule_GetDict(m); +} + +static PyObject * +PyEval_EvalCodeEx_py3k(PyCodeObject *co, PyObject *globals, PyObject *locals, + PyObject **args, int argcount, PyObject **kws, int kwcount, + PyObject **defs, int defcount, PyObject *kwdefs, PyObject *closure) +{ +// py3k beg + int co_argcount = PyCode_GETARGCOUNT(co); + int co_kwonlyargcount = PyCode_GETKWONLYARGCOUNT(co); + int co_argcount_py3k = co_argcount + co_kwonlyargcount; +// py3k beg + register PyFrameObject *f; + register PyObject *retval = NULL; + register PyObject **fastlocals, **freevars; + PyThreadState *tstate = PyThreadState_GET(); + PyObject *x, *u; + + if (globals == NULL) { + PyErr_SetString(PyExc_SystemError, + "PyEval_EvalCodeEx_py3k: NULL globals"); + return NULL; + } + + assert(tstate != NULL); + assert(globals != NULL); + f = PyFrame_New(tstate, co, globals, locals); + if (f == NULL) + return NULL; + + fastlocals = f->f_localsplus; + freevars = f->f_localsplus + co->co_nlocals; + + if (co_argcount > 0 || + co_kwonlyargcount > 0 || // py3k + co->co_flags & (CO_VARARGS | CO_VARKEYWORDS)) { + int i; + int n = argcount; + PyObject *kwdict = NULL; + if (co->co_flags & CO_VARKEYWORDS) { + kwdict = PyDict_New(); + if (kwdict == NULL) + goto fail; + i = co_argcount_py3k; // py3k + if (co->co_flags & CO_VARARGS) + i++; + SETLOCAL(i, kwdict); + } + if (argcount > co_argcount) { + if (!(co->co_flags & CO_VARARGS)) { + PyErr_Format(PyExc_TypeError, + "%.200s() takes %s %d " + "%sargument%s (%d given)", + PyString_AsString(co->co_name), + defcount ? "at most" : "exactly", + co_argcount, + kwcount ? "non-keyword " : "", + co_argcount == 1 ? "" : "s", + argcount); + goto fail; + } + n = co_argcount; + } + for (i = 0; i < n; i++) { + x = args[i]; + Py_INCREF(x); + SETLOCAL(i, x); + } + if (co->co_flags & CO_VARARGS) { + u = PyTuple_New(argcount - n); + if (u == NULL) + goto fail; + SETLOCAL(co_argcount_py3k, u); // py3k + for (i = n; i < argcount; i++) { + x = args[i]; + Py_INCREF(x); + PyTuple_SET_ITEM(u, i-n, x); + } + } + for (i = 0; i < kwcount; i++) { + PyObject **co_varnames; + PyObject *keyword = kws[2*i]; + PyObject *value = kws[2*i + 1]; + int j; + if (keyword == NULL || !PyString_Check(keyword)) { + PyErr_Format(PyExc_TypeError, + "%.200s() keywords must be strings", + PyString_AsString(co->co_name)); + goto fail; + } + /* Speed hack: do raw pointer compares. As names are + normally interned this should almost always hit. */ + co_varnames = PySequence_Fast_ITEMS(co->co_varnames); + for (j = 0; j < co_argcount_py3k; j++) { // py3k + PyObject *nm = co_varnames[j]; + if (nm == keyword) + goto kw_found; + } + /* Slow fallback, just in case */ + for (j = 0; j < co_argcount_py3k; j++) { // py3k + PyObject *nm = co_varnames[j]; + int cmp = PyObject_RichCompareBool( + keyword, nm, Py_EQ); + if (cmp > 0) + goto kw_found; + else if (cmp < 0) + goto fail; + } + /* Check errors from Compare */ + if (PyErr_Occurred()) + goto fail; + if (j >= co_argcount_py3k) { // py3k + if (kwdict == NULL) { + PyErr_Format(PyExc_TypeError, + "%.200s() got an unexpected " + "keyword argument '%.400s'", + PyString_AsString(co->co_name), + PyString_AsString(keyword)); + goto fail; + } + PyDict_SetItem(kwdict, keyword, value); + continue; + } +kw_found: + if (GETLOCAL(j) != NULL) { + PyErr_Format(PyExc_TypeError, + "%.200s() got multiple " + "values for keyword " + "argument '%.400s'", + PyString_AsString(co->co_name), + PyString_AsString(keyword)); + goto fail; + } + Py_INCREF(value); + SETLOCAL(j, value); + } +// py3k beg - PEP 3102 Keyword-Only Arguments + if (co_kwonlyargcount > 0) { + for (i = co_argcount; + i < co_argcount_py3k; // py3k + i++) { + PyObject *name, *def; + if (GETLOCAL(i) != NULL) + continue; + name = PyTuple_GET_ITEM(co->co_varnames, i); + def = NULL; + if (kwdefs != NULL) + def = PyDict_GetItem(kwdefs, name); + if (def != NULL) { + Py_INCREF(def); + SETLOCAL(i, def); + continue; + } + PyErr_Format(PyExc_TypeError, + "%.200s() needs keyword-only argument %s", // py3k + PyString_AsString(co->co_name), PyString_AsString(name)); // py3k + goto fail; + } + } +// py3k end + if (argcount < co_argcount) { + int m = co_argcount - defcount; + for (i = argcount; i < m; i++) { + if (GETLOCAL(i) == NULL) { + PyErr_Format(PyExc_TypeError, + "%.200s() takes %s %d " + "%spositional argument%s (%d given)", // py3k + PyString_AsString(co->co_name), + ((co->co_flags & CO_VARARGS) || + defcount) ? "at least" + : "exactly", + m, kwcount ? "non-keyword " : "", + m == 1 ? "" : "s", i); + goto fail; + } + } + if (n > m) + i = n - m; + else + i = 0; + for (; i < defcount; i++) { + if (GETLOCAL(m+i) == NULL) { + PyObject *def = defs[i]; + Py_INCREF(def); + SETLOCAL(m+i, def); + } + } + } + } + else { + if (argcount > 0 || kwcount > 0) { + PyErr_Format(PyExc_TypeError, + "%.200s() takes no arguments (%d given)", + PyString_AsString(co->co_name), + argcount + kwcount); + goto fail; + } + } + /* Allocate and initialize storage for cell vars, and copy free + vars into frame. This isn't too efficient right now. */ + if (PyTuple_GET_SIZE(co->co_cellvars)) { + int i, j, nargs, found; + char *cellname, *argname; + PyObject *c; + + nargs = co_argcount_py3k; // py3k + if (co->co_flags & CO_VARARGS) + nargs++; + if (co->co_flags & CO_VARKEYWORDS) + nargs++; + + /* Initialize each cell var, taking into account + cell vars that are initialized from arguments. + + Should arrange for the compiler to put cellvars + that are arguments at the beginning of the cellvars + list so that we can march over it more efficiently? + */ + for (i = 0; i < PyTuple_GET_SIZE(co->co_cellvars); ++i) { + cellname = PyString_AS_STRING( + PyTuple_GET_ITEM(co->co_cellvars, i)); + found = 0; + for (j = 0; j < nargs; j++) { + argname = PyString_AS_STRING( + PyTuple_GET_ITEM(co->co_varnames, j)); + if (strcmp(cellname, argname) == 0) { + c = PyCell_New(GETLOCAL(j)); + if (c == NULL) + goto fail; + GETLOCAL(co->co_nlocals + i) = c; + found = 1; + break; + } + } + if (found == 0) { + c = PyCell_New(NULL); + if (c == NULL) + goto fail; + SETLOCAL(co->co_nlocals + i, c); + } + } + } + if (PyTuple_GET_SIZE(co->co_freevars)) { + int i; + for (i = 0; i < PyTuple_GET_SIZE(co->co_freevars); ++i) { + PyObject *o = PyTuple_GET_ITEM(closure, i); + Py_INCREF(o); + freevars[PyTuple_GET_SIZE(co->co_cellvars) + i] = o; + } + } + + if (co->co_flags & CO_GENERATOR) { + /* Don't need to keep the reference to f_back, it will be set + * when the generator is resumed. */ + Py_XDECREF(f->f_back); + f->f_back = NULL; + + PCALL(PCALL_GENERATOR); + + /* Create a new generator that owns the ready to run frame + * and return that as the value. */ + return PyGen_New(f); + } + + retval = PyEval_EvalFrameEx(f,0); + +fail: /* Jump here from prelude on failure */ + + /* decref'ing the frame can cause __del__ methods to get invoked, + which can call back into Python. While we're done with the + current Python frame (f), the associated C stack is still in use, + so recursion_depth must be boosted for the duration. + */ + assert(tstate != NULL); + ++tstate->recursion_depth; + Py_DECREF(f); + --tstate->recursion_depth; + return retval; +} + +//////// py3k - curry object +typedef struct { + PyObject_HEAD + PyObject *self; + PyObject *func; +} PyCurryObject; + +static void curry_dealloc(PyCurryObject *curry) { + Py_DECREF(curry->self); + Py_XDECREF(curry->func); + PyObject_DEL(curry); + // PyObject_GC_Del(curry); +} + +static PyObject *curry_new(PyObject *self) { + PyCurryObject *curry = PyObject_NEW(PyCurryObject, &PyCurry_Type); + curry->self = self; Py_INCREF(self); + curry->func = NULL; + return (PyObject *)curry; +} + +static PyObject *curry_getattro(PyObject *curry, PyObject *fname) { + if (!PyString_Check(fname)) { + PyErr_SetString(PyExc_TypeError, "fname is not a string"); return NULL; + } + PyObject *func = NULL, *globals = NULL; + if ((globals = PyEval_GetLocals()) != NULL) {func = PyDict_GetItem(globals, fname); + if (func == NULL) if ((globals = PyEval_GetGlobals()) != NULL) {func = PyDict_GetItem(globals, fname); + if (func == NULL) if ((globals = PyEval_GetBuiltins_py3k()) != NULL) {func = PyDict_GetItem(globals, fname); + if (func == NULL) { + PyErr_SetString(PyExc_NameError, "fname not defined"); return NULL; + }}}} + if (!PyCallable_Check(func)) { + PyErr_SetString(PyExc_TypeError, "func to be curried is not callable"); + return NULL; + } + ((PyCurryObject *)curry)->func = func; Py_INCREF(func); + Py_INCREF(curry); return curry; +} + +static PyObject *curry_call(PyCurryObject *curry, PyObject *args, PyObject *kwds) { + PyObject* args_ = PyTuple_New(PyTuple_Size(args) + 1); + Py_INCREF(curry->self); PyTuple_SetItem(args_, 0, curry->self); + int i = 0; PyObject *x; + while (i < PyTuple_Size(args)) { + x = PyTuple_GetItem(args, i); i++; + Py_INCREF(x); PyTuple_SetItem(args_, i, x); + } + x = PyEval_CallObjectWithKeywords(curry->func, args_, kwds); + Py_DECREF(args_); return x; +} + +static PyTypeObject PyCurry_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) /* ob_type */ + "curry", /* ob_size */ + sizeof(PyCurryObject), /* tp_name */ + 0, /* tp_itemsize */ + (destructor)curry_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + (ternaryfunc)curry_call, /* tp_call */ + 0, /* tp_str */ + curry_getattro, /* tp_getattro */ +}; + +//////// py3k - PySuper_Type_py3k + +typedef struct { + PyObject_HEAD + PyTypeObject *type; + PyObject *obj; + PyTypeObject *obj_type; +} superobject; + +static PyMemberDef super_members[] = { + {"__thisclass__", T_OBJECT, offsetof(superobject, type), READONLY, + "the class invoking super()"}, + {"__self__", T_OBJECT, offsetof(superobject, obj), READONLY, + "the instance invoking super(); may be None"}, + {"__self_class__", T_OBJECT, offsetof(superobject, obj_type), READONLY, + "the type of the instance invoking super(); may be None"}, + {0} +}; + +static void +super_dealloc(PyObject *self) +{ + superobject *su = (superobject *)self; + + _PyObject_GC_UNTRACK(self); + Py_XDECREF(su->obj); + Py_XDECREF(su->type); + Py_XDECREF(su->obj_type); + Py_TYPE(self)->tp_free(self); +} + +static PyObject * +super_repr(PyObject *self) +{ + superobject *su = (superobject *)self; + + if (su->obj_type) + return PyString_FromFormat( + ", <%s object>>", + su->type ? su->type->tp_name : "NULL", + su->obj_type->tp_name); + else + return PyString_FromFormat( + ", NULL>", + su->type ? su->type->tp_name : "NULL"); +} + +static PyObject * +super_getattro(PyObject *self, PyObject *name) +{ + superobject *su = (superobject *)self; + int skip = su->obj_type == NULL; + + if (!skip) { + /* We want __class__ to return the class of the super object + (i.e. super, or a subclass), not the class of su->obj. */ + skip = (PyString_Check(name) && + PyString_GET_SIZE(name) == 9 && + strcmp(PyString_AS_STRING(name), "__class__") == 0); + } + + if (!skip) { + PyObject *mro, *res, *tmp, *dict; + PyTypeObject *starttype; + descrgetfunc f; + Py_ssize_t i, n; + + starttype = su->obj_type; + mro = starttype->tp_mro; + + if (mro == NULL) + n = 0; + else { + assert(PyTuple_Check(mro)); + n = PyTuple_GET_SIZE(mro); + } + for (i = 0; i < n; i++) { + if ((PyObject *)(su->type) == PyTuple_GET_ITEM(mro, i)) + break; + } + i++; + res = NULL; + for (; i < n; i++) { + tmp = PyTuple_GET_ITEM(mro, i); + if (PyType_Check(tmp)) + dict = ((PyTypeObject *)tmp)->tp_dict; + else if (PyClass_Check(tmp)) + dict = ((PyClassObject *)tmp)->cl_dict; + else + continue; + res = PyDict_GetItem(dict, name); + if (res != NULL) { + Py_INCREF(res); + f = Py_TYPE(res)->tp_descr_get; + if (f != NULL) { + tmp = f(res, + /* Only pass 'obj' param if + this is instance-mode super + (See SF ID #743627) + */ + (su->obj == (PyObject *) + su->obj_type + ? (PyObject *)NULL + : su->obj), + (PyObject *)starttype); + Py_DECREF(res); + res = tmp; + } + return res; + } + } + } + return PyObject_GenericGetAttr(self, name); +} + +static PyTypeObject * +supercheck(PyTypeObject *type, PyObject *obj) +{ + /* Check that a super() call makes sense. Return a type object. + + obj can be a new-style class, or an instance of one: + + - If it is a class, it must be a subclass of 'type'. This case is + used for class methods; the return value is obj. + + - If it is an instance, it must be an instance of 'type'. This is + the normal case; the return value is obj.__class__. + + But... when obj is an instance, we want to allow for the case where + Py_TYPE(obj) is not a subclass of type, but obj.__class__ is! + This will allow using super() with a proxy for obj. + */ + + /* Check for first bullet above (special case) */ + if (PyType_Check(obj) && PyType_IsSubtype((PyTypeObject *)obj, type)) { + Py_INCREF(obj); + return (PyTypeObject *)obj; + } + + /* Normal case */ + if (PyType_IsSubtype(Py_TYPE(obj), type)) { + Py_INCREF(Py_TYPE(obj)); + return Py_TYPE(obj); + } + else { + /* Try the slow way */ + static PyObject *class_str = NULL; + PyObject *class_attr; + + if (class_str == NULL) { + class_str = PyString_FromString("__class__"); + if (class_str == NULL) + return NULL; + } + + class_attr = PyObject_GetAttr(obj, class_str); + + if (class_attr != NULL && + PyType_Check(class_attr) && + (PyTypeObject *)class_attr != Py_TYPE(obj)) + { + int ok = PyType_IsSubtype( + (PyTypeObject *)class_attr, type); + if (ok) + return (PyTypeObject *)class_attr; + } + + if (class_attr == NULL) + PyErr_Clear(); + else + Py_DECREF(class_attr); + } + + PyErr_SetString(PyExc_TypeError, + "super(type, obj): " + "obj must be an instance or subtype of type"); + return NULL; +} + +static PyObject * +super_descr_get(PyObject *self, PyObject *obj, PyObject *type) +{ + superobject *su = (superobject *)self; + superobject *newobj; + + if (obj == NULL || obj == Py_None || su->obj != NULL) { + /* Not binding to an object, or already bound */ + Py_INCREF(self); + return self; + } + if (Py_TYPE(su) != &PySuper_Type) + /* If su is an instance of a (strict) subclass of super, + call its type */ + return PyObject_CallFunctionObjArgs((PyObject *)Py_TYPE(su), + su->type, obj, NULL); + else { + /* Inline the common case */ + PyTypeObject *obj_type = supercheck(su->type, obj); + if (obj_type == NULL) + return NULL; + newobj = (superobject *)PySuper_Type.tp_new(&PySuper_Type, + NULL, NULL); + if (newobj == NULL) + return NULL; + Py_INCREF(su->type); + Py_INCREF(obj); + newobj->type = su->type; + newobj->obj = obj; + newobj->obj_type = obj_type; + return (PyObject *)newobj; + } +} + +// static int +// super_init(PyObject *self, PyObject *args, PyObject *kwds) +// { + // superobject *su = (superobject *)self; + // PyTypeObject *type; + // PyObject *obj = NULL; + // PyTypeObject *obj_type = NULL; + + // if (!_PyArg_NoKeywords("super", kwds)) + // return -1; + // if (!PyArg_ParseTuple(args, "O!|O:super", &PyType_Type, &type, &obj)) + // return -1; + // if (obj == Py_None) + // obj = NULL; + // if (obj != NULL) { + // obj_type = supercheck(type, obj); + // if (obj_type == NULL) + // return -1; + // Py_INCREF(obj); + // } + // Py_INCREF(type); + // su->type = type; + // su->obj = obj; + // su->obj_type = obj_type; + // return 0; +// } + +// PyDoc_STRVAR(super_doc, +// "super(type) -> unbound super object\n" +// "super(type, obj) -> bound super object; requires isinstance(obj, type)\n" +// "super(type, type2) -> bound super object; requires issubclass(type2, type)\n" +// "Typical use to call a cooperative superclass method:\n" +// "class C(B):\n" +// " def meth(self, arg):\n" +// " super(C, self).meth(arg)"); + +static int // from Python-3.0rc1/Objects/typeobject.c +super_init(PyObject *self, PyObject *args, PyObject *kwds) +{ + superobject *su = (superobject *)self; + PyTypeObject *type = NULL; + PyObject *obj = NULL; + PyTypeObject *obj_type = NULL; + + if (!_PyArg_NoKeywords("super", kwds)) + return -1; + if (!PyArg_ParseTuple(args, "|O!O:super", &PyType_Type, &type, &obj)) + return -1; + + if (type == NULL) { + /* Call super(), without args -- fill in from __class__ + and first local variable on the stack. */ + PyFrameObject *f = PyThreadState_GET()->frame; + PyCodeObject *co = f->f_code; + int i, n; + if (co == NULL) { + PyErr_SetString(PyExc_SystemError, + "super(): no code object"); + return -1; + } + if (co->co_argcount == 0) { + PyErr_SetString(PyExc_SystemError, + "super(): no arguments"); + return -1; + } + obj = f->f_localsplus[0]; + if (obj == NULL) { + PyErr_SetString(PyExc_SystemError, + "super(): arg[0] deleted"); + return -1; + } + if (co->co_freevars == NULL) + n = 0; + else { + assert(PyTuple_Check(co->co_freevars)); + n = PyTuple_GET_SIZE(co->co_freevars); + } + for (i = 0; i < n; i++) { + PyObject *name = PyTuple_GET_ITEM(co->co_freevars, i); +// py3k beg + assert(PyString_Check(name)); + if (!strcmp(PyString_AS_STRING(name), "__class__")) { +// py3k end + // assert(PyUnicode_Check(name)); + // if (!PyUnicode_CompareWithASCIIString(name, + // "__class__")) { + PyObject *cell = + f->f_localsplus[co->co_nlocals + i]; + if (cell == NULL || !PyCell_Check(cell)) { + PyErr_SetString(PyExc_SystemError, + "super(): bad __class__ cell"); + return -1; + } + type = (PyTypeObject *) PyCell_GET(cell); + if (type == NULL) { + PyErr_SetString(PyExc_SystemError, + "super(): empty __class__ cell"); + return -1; + } + if (!PyType_Check(type)) { + PyErr_Format(PyExc_SystemError, + "super(): __class__ is not a type (%s)", + Py_TYPE(type)->tp_name); + return -1; + } + break; + } + } + if (type == NULL) { + PyErr_SetString(PyExc_SystemError, + "super(): __class__ cell not found"); + return -1; + } + } + + if (obj == Py_None) + obj = NULL; + if (obj != NULL) { + obj_type = supercheck(type, obj); + if (obj_type == NULL) + return -1; + Py_INCREF(obj); + } + Py_INCREF(type); + su->type = type; + su->obj = obj; + su->obj_type = obj_type; + return 0; +} + +PyDoc_STRVAR(super_doc, +"super() -> same as super(__class__, )\n" +"super(type) -> unbound super object\n" +"super(type, obj) -> bound super object; requires isinstance(obj, type)\n" +"super(type, type2) -> bound super object; requires issubclass(type2, type)\n" +"Typical use to call a cooperative superclass method:\n" +"class C(B):\n" +" def meth(self, arg):\n" +" super().meth(arg)\n" +"This works for class methods too:\n" +"class C(B):\n" +" @classmethod\n" +" def cmeth(cls, arg):\n" +" super().cmeth(arg)\n"); + +static int +super_traverse(PyObject *self, visitproc visit, void *arg) +{ + superobject *su = (superobject *)self; + + Py_VISIT(su->obj); + Py_VISIT(su->type); + Py_VISIT(su->obj_type); + + return 0; +} + +PyTypeObject PySuper_Type_py3k = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "super", /* tp_name */ + sizeof(superobject), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + super_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + super_repr, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + super_getattro, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_BASETYPE, /* tp_flags */ + super_doc, /* tp_doc */ + super_traverse, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + super_members, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + super_descr_get, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + super_init, /* tp_init */ + PyType_GenericAlloc, /* tp_alloc */ + PyType_GenericNew, /* tp_new */ + PyObject_GC_Del, /* tp_free */ +}; + +//////// py3k - builtins_py3k methods +// class func(bases, metaclass = None, **kwds): ... -> __build_class__(func, name, *bases, metaclass = None, **kwds) +static PyObject * +builtins___build_class__(PyObject *self, PyObject *args, PyObject *kwds) +{ + PyObject *func, *name, *bases, *mkw, *meta, *prep, *ns, *cell; + PyObject *cls = NULL; + Py_ssize_t nargs, nbases; + + assert(args != NULL); + if (!PyTuple_Check(args)) { + PyErr_SetString(PyExc_TypeError, + "__build_class__: args is not a tuple"); + return NULL; + } + nargs = PyTuple_GET_SIZE(args); + if (nargs < 2) { + PyErr_SetString(PyExc_TypeError, + "__build_class__: not enough arguments"); + return NULL; + } + func = PyTuple_GET_ITEM(args, 0); /* Better be callable */ + name = PyTuple_GET_ITEM(args, 1); + if (!PyString_Check(name)) { // py3k + PyErr_SetString(PyExc_TypeError, + "__build_class__: name is not a string"); + return NULL; + } + bases = PyTuple_GetSlice(args, 2, nargs); + if (bases == NULL) + return NULL; + nbases = nargs - 2; + + if (kwds == NULL) { + meta = NULL; + mkw = NULL; + } + else { + mkw = PyDict_Copy(kwds); /* Don't modify kwds passed in! */ + if (mkw == NULL) { + Py_DECREF(bases); + return NULL; + } + meta = PyDict_GetItemString(mkw, "metaclass"); + if (meta != NULL) { + Py_INCREF(meta); + if (PyDict_DelItemString(mkw, "metaclass") < 0) { + Py_DECREF(meta); + Py_DECREF(mkw); + Py_DECREF(bases); + return NULL; + } + } + } + if (meta == NULL) { + if (PyTuple_GET_SIZE(bases) == 0) + meta = (PyObject *) (&PyType_Type); + else { + PyObject *base0 = PyTuple_GET_ITEM(bases, 0); + meta = (PyObject *) (base0->ob_type); + } + Py_INCREF(meta); + } + prep = PyObject_GetAttrString(meta, "__prepare__"); + if (prep == NULL) { + PyErr_Clear(); + ns = PyDict_New(); + } + else { + PyObject *pargs = Py_BuildValue("OO", name, bases); + if (pargs == NULL) { + Py_DECREF(prep); + Py_DECREF(meta); + Py_XDECREF(mkw); + Py_DECREF(bases); + return NULL; + } + ns = PyEval_CallObjectWithKeywords(prep, pargs, mkw); + Py_DECREF(pargs); + Py_DECREF(prep); + if (ns == NULL) { + Py_DECREF(meta); + Py_XDECREF(mkw); + Py_DECREF(bases); + return NULL; + } + } + cell = PyObject_CallFunctionObjArgs(func, ns, NULL); + if (cell != NULL) { + PyObject *margs; + margs = Py_BuildValue("OOO", name, bases, ns); + if (margs != NULL) { + cls = PyEval_CallObjectWithKeywords(meta, margs, mkw); + Py_DECREF(margs); + } + if (cls != NULL && PyCell_Check(cell)) { + Py_INCREF(cls); + PyCell_SET(cell, cls); + } + Py_DECREF(cell); + } + Py_DECREF(ns); + Py_DECREF(meta); + Py_XDECREF(mkw); + Py_DECREF(bases); + return cls; +} + +PyDoc_STRVAR(build_class_doc, +"__build_class__(func, name, *bases, metaclass=None, **kwds) -> class\n\ +\n\ +Internal helper function used by the class statement."); + +static PyObject * +builtins_compile(PyObject *self, PyObject *args, PyObject *kwds) +{ + // char *str; + char *filename; + char *startstr; + int mode = -1; + int dont_inherit = 0; + int supplied_flags = 0; + PyCompilerFlags cf; + PyObject *cmd; // py3k + // PyObject *result = NULL, *cmd, *tmp = NULL; + // Py_ssize_t length; + static char *kwlist[] = {"source", "filename", "mode", "flags", + "dont_inherit", NULL}; + // int start[] = {Py_file_input, Py_eval_input, Py_single_input}; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "Oss|ii:compile", + kwlist, &cmd, &filename, &startstr, + &supplied_flags, &dont_inherit)) + return NULL; + + cf.cf_flags = supplied_flags; + + if (supplied_flags & + ~(PyCF_MASK | PyCF_MASK_OBSOLETE | PyCF_DONT_IMPLY_DEDENT | PyCF_ONLY_AST)) + { + PyErr_SetString(PyExc_ValueError, + "compile(): unrecognised flags"); + return NULL; + } + /* XXX Warn if (supplied_flags & PyCF_MASK_OBSOLETE) != 0? */ + + if (!dont_inherit) { + PyEval_MergeCompilerFlags(&cf); + } + + if (strcmp(startstr, "exec") == 0) + mode = 0; + else if (strcmp(startstr, "eval") == 0) + mode = 1; + else if (strcmp(startstr, "single") == 0) + mode = 2; + else { + PyErr_SetString(PyExc_ValueError, + "compile() arg 3 must be 'exec', 'eval' or 'single'"); + return NULL; + } +// py3k beg + if (!PyString_CheckExact(cmd)) { + PyErr_SetString(PyExc_TypeError, "compile() source must be a string"); + return NULL; + } + PyObject *func = PyDict_GetItemString(PyEval_GetBuiltins(), "compile_py3k"); // get function + if (!(func && PyCallable_Check(func))) {PyErr_SetString(PyExc_NotImplementedError, "compile_py3k"); return NULL;} + return PyEval_CallObjectWithKeywords(func, args, kwds); +// py3k end + // if (PyAST_Check(cmd)) { + // if (supplied_flags & PyCF_ONLY_AST) { + // Py_INCREF(cmd); + // result = cmd; + // } + // else { + // PyArena *arena; + // mod_ty mod; + + // arena = PyArena_New(); + // mod = PyAST_obj2mod(cmd, arena, mode); + // if (mod == NULL) { + // PyArena_Free(arena); + // return NULL; + // } + // result = (PyObject*)PyAST_Compile(mod, filename, + // &cf, arena); + // PyArena_Free(arena); + // } + // return result; + // } + +// #ifdef Py_USING_UNICODE + // if (PyUnicode_Check(cmd)) { + // tmp = PyUnicode_AsUTF8String(cmd); + // if (tmp == NULL) + // return NULL; + // cmd = tmp; + // cf.cf_flags |= PyCF_SOURCE_IS_UTF8; + // } +// #endif + + // if (PyObject_AsReadBuffer(cmd, (const void **)&str, &length)) + // goto cleanup; + // if ((size_t)length != strlen(str)) { + // PyErr_SetString(PyExc_TypeError, + // "compile() expected string without null bytes"); + // goto cleanup; + // } + // result = Py_CompileStringFlags(str, filename, start[mode], &cf); +// cleanup: + // Py_XDECREF(tmp); + // return result; +} + +PyDoc_STRVAR(compile_doc, +"compile(source, filename, mode[, flags[, dont_inherit]]) -> code object\n\ +\n\ +Compile the source string (a Python module, statement or expression)\n\ +into a code object that can be executed by the exec statement or eval().\n\ +The filename will be used for run-time error messages.\n\ +The mode must be 'exec' to compile a module, 'single' to compile a\n\ +single (interactive) statement, or 'eval' to compile an expression.\n\ +The flags argument, if present, controls which future statements influence\n\ +the compilation of the code.\n\ +The dont_inherit argument, if non-zero, stops the compilation inheriting\n\ +the effects of any future statements in effect in the code calling\n\ +compile; if absent or zero these statements do influence the compilation,\n\ +in addition to any features explicitly specified."); + +static PyObject * +builtins_exec(PyObject *self, PyObject *args) +{ + PyObject *v; + PyObject *prog, *globals = Py_None, *locals = Py_None; + int plain = 0; + + if (!PyArg_ParseTuple(args, "O|OO:exec", &prog, &globals, &locals)) + return NULL; + + if (globals == Py_None) { + globals = PyEval_GetGlobals(); + if (locals == Py_None) { + locals = PyEval_GetLocals(); + plain = 1; + } + if (!globals || !locals) { + PyErr_SetString(PyExc_SystemError, + "globals and locals cannot be NULL"); + return NULL; + } + } + else if (locals == Py_None) + locals = globals; + if (!PyUnicode_Check(prog) && + !PyString_Check(prog) && // py3k + !PyCode_Check(prog)) { + PyErr_Format(PyExc_TypeError, + "exec() arg 1 must be a string, file, or code " + "object, not %.100s", prog->ob_type->tp_name); + return NULL; + } + if (!PyDict_Check(globals)) { + PyErr_Format(PyExc_TypeError, "exec() arg 2 must be a dict, not %.100s", + globals->ob_type->tp_name); + return NULL; + } + if (!PyMapping_Check(locals)) { + PyErr_Format(PyExc_TypeError, + "arg 3 must be a mapping or None, not %.100s", + locals->ob_type->tp_name); + return NULL; + } + if (PyDict_GetItemString(globals, "__builtins__") == NULL) { + if (PyDict_SetItemString(globals, "__builtins__", + PyEval_GetBuiltins()) != 0) + return NULL; + } + +// py3k beg + if (!PyCode_Check(prog)) { + args = Py_BuildValue("(Oss)", prog, "", "exec"); Py_INCREF(prog); PyObject *kwds = PyDict_New(); + prog = builtins_compile(self, args, kwds); Py_DECREF(args); Py_DECREF(kwds); + if (prog == NULL) return NULL; + } + if (!PyCode_ISPY3K((PyCodeObject *)prog)) { + PyErr_SetString(PyExc_ValueError, "codeobj not in py3k format"); return NULL; + } +// py3k end + + // if (PyCode_Check(prog)) { + if (PyCode_GetNumFree((PyCodeObject *)prog) > 0) { + PyErr_SetString(PyExc_TypeError, + "code object passed to exec() may not " + "contain free variables"); + return NULL; + } + v = PyEval_EvalCode((PyCodeObject *) prog, globals, locals); + // } + // else { + // char *str = source_as_string(prog); + // PyCompilerFlags cf; + // if (str == NULL) + // return NULL; + // cf.cf_flags = PyCF_SOURCE_IS_UTF8; + // if (PyEval_MergeCompilerFlags(&cf)) + // v = PyRun_StringFlags(str, Py_file_input, globals, + // locals, &cf); + // else + // v = PyRun_String(str, Py_file_input, globals, locals); + // } + if (v == NULL) + return NULL; + Py_DECREF(v); + Py_RETURN_NONE; +} + +PyDoc_STRVAR(exec_doc, +"exec(object[, globals[, locals]])\n\ +\n\ +Read and execute code from a object, which can be a string, a code\n\ +object or a file object.\n\ +The globals and locals are dictionaries, defaulting to the current\n\ +globals and locals. If only globals is given, locals defaults to it."); + +static PyObject * +builtins_eval(PyObject *self, PyObject *args) +{ + PyObject *cmd; //, *result, *tmp = NULL; // py3k + PyObject *globals = Py_None, *locals = Py_None; + // char *str; + // PyCompilerFlags cf; + + if (!PyArg_UnpackTuple(args, "eval", 1, 3, &cmd, &globals, &locals)) + return NULL; + if (locals != Py_None && !PyMapping_Check(locals)) { + PyErr_SetString(PyExc_TypeError, "locals must be a mapping"); + return NULL; + } + if (globals != Py_None && !PyDict_Check(globals)) { + PyErr_SetString(PyExc_TypeError, PyMapping_Check(globals) ? + "globals must be a real dict; try eval(expr, {}, mapping)" + : "globals must be a dict"); + return NULL; + } + if (globals == Py_None) { + globals = PyEval_GetGlobals(); + if (locals == Py_None) + locals = PyEval_GetLocals(); + } + else if (locals == Py_None) + locals = globals; + + if (globals == NULL || locals == NULL) { + PyErr_SetString(PyExc_TypeError, + "eval must be given globals and locals " + "when called without a frame"); + return NULL; + } + + if (PyDict_GetItemString(globals, "__builtins__") == NULL) { + if (PyDict_SetItemString(globals, "__builtins__", + PyEval_GetBuiltins()) != 0) + return NULL; + } + +// py3k beg + if (!PyCode_Check(cmd)) { + args = Py_BuildValue("(Oss)", cmd, "", "eval"); Py_INCREF(cmd); PyObject *kwds = PyDict_New(); + cmd = builtins_compile(self, args, kwds); Py_DECREF(args); Py_DECREF(kwds); + if (cmd == NULL) return NULL; + } + if (!PyCode_ISPY3K((PyCodeObject *)cmd)) { + PyErr_SetString(PyExc_ValueError, "codeobj not in py3k format"); return NULL; + } +// py3k end + + // if (PyCode_Check(cmd)) { + if (PyCode_GetNumFree((PyCodeObject *)cmd) > 0) { + PyErr_SetString(PyExc_TypeError, + "code object passed to eval() may not contain free variables"); + return NULL; + } + return PyEval_EvalCode((PyCodeObject *) cmd, globals, locals); + // } + + // if (!PyString_Check(cmd) && + // !PyUnicode_Check(cmd)) { + // PyErr_SetString(PyExc_TypeError, + // "eval() arg 1 must be a string or code object"); + // return NULL; + // } + // cf.cf_flags = 0; + +// #ifdef Py_USING_UNICODE + // if (PyUnicode_Check(cmd)) { + // tmp = PyUnicode_AsUTF8String(cmd); + // if (tmp == NULL) + // return NULL; + // cmd = tmp; + // cf.cf_flags |= PyCF_SOURCE_IS_UTF8; + // } +// #endif + // if (PyString_AsStringAndSize(cmd, &str, NULL)) { + // Py_XDECREF(tmp); + // return NULL; + // } + // while (*str == ' ' || *str == '\t') + // str++; + + // (void)PyEval_MergeCompilerFlags(&cf); + // result = PyRun_StringFlags(str, Py_eval_input, globals, locals, &cf); + // Py_XDECREF(tmp); + // return result; +} + +PyDoc_STRVAR(eval_doc, +"eval(source[, globals[, locals]]) -> value\n\ +\n\ +Evaluate the source in the context of globals and locals.\n\ +The source may be a string representing a Python expression\n\ +or a code object as returned by compile().\n\ +The globals must be a dictionary and locals can be any mapping,\n\ +defaulting to the current globals and locals.\n\ +If only globals is given, locals defaults to it.\n"); + +//////// py3k - builtins_py3k init +static PyMethodDef builtins_methods[] = { + {"__build_class__", (PyCFunction)builtins___build_class__, METH_VARARGS | METH_KEYWORDS, build_class_doc}, + {"compile", (PyCFunction)builtins_compile, METH_VARARGS, compile_doc}, + {"eval", (PyCFunction)builtins_eval, METH_VARARGS, eval_doc}, + {"exec", (PyCFunction)builtins_exec, METH_VARARGS, exec_doc}, + {NULL} /* Sentinel */ +}; + +PyDoc_STRVAR(builtins_doc, +"Built-in functions, exceptions, and other objects.\n\ +\n\ +Noteworthy: None is the `nil' object; Ellipsis represents `...' in slices."); + +static PyObject * +init_builtins_py3k(void) +{ + PyObject *mod, *dict; + mod = Py_InitModule4("builtins_py3k", builtins_methods, + builtins_doc, (PyObject *)NULL, + PYTHON_API_VERSION); + if (mod == NULL) + return NULL; + dict = PyModule_GetDict(mod); + +#ifdef Py_TRACE_REFS + /* __builtin__ exposes a number of statically allocated objects + * that, before this code was added in 2.3, never showed up in + * the list of "all objects" maintained by Py_TRACE_REFS. As a + * result, programs leaking references to None and False (etc) + * couldn't be diagnosed by examining sys.getobjects(0). + */ +#define ADD_TO_ALL(OBJECT) _Py_AddToAllObjects((PyObject *)(OBJECT), 0) +#else +#define ADD_TO_ALL(OBJECT) (void)0 +#endif + +#define SETBUILTIN(NAME, OBJECT) \ + if (PyDict_SetItemString(dict, NAME, (PyObject *)OBJECT) < 0) \ + return NULL; \ + ADD_TO_ALL(OBJECT) + + SETBUILTIN("super", &PySuper_Type_py3k); + + if (PyDict_SetItemString(PyEval_GetBuiltins(), "builtins_py3k", mod) == -1) return NULL; // add module to __builtins__ + return mod; +} +//////////////////////////////////////////////////////////////// py3k end