Commit ee448c5f authored by Kevin Modzelewski's avatar Kevin Modzelewski

Merge pull request #285 from tjhance/builtin-functions

builtin functions
parents 5cc8ea87 128cb7c7
...@@ -83,7 +83,7 @@ public: ...@@ -83,7 +83,7 @@ public:
return rtn; return rtn;
} }
static Box* callInternal(BoxedFunction* func, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, static Box* callInternal(BoxedFunctionBase* func, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1,
Box* arg2, Box* arg3, Box** args, const std::vector<const std::string*>* keyword_names); Box* arg2, Box* arg3, Box** args, const std::vector<const std::string*>* keyword_names);
}; };
......
...@@ -121,7 +121,7 @@ typedef ValuedCompilerVariable<llvm::Value*> ConcreteCompilerVariable; ...@@ -121,7 +121,7 @@ typedef ValuedCompilerVariable<llvm::Value*> ConcreteCompilerVariable;
class Box; class Box;
class BoxedClass; class BoxedClass;
class BoxedModule; class BoxedModule;
class BoxedFunction; class BoxedFunctionBase;
class ICGetattr; class ICGetattr;
struct ICSlotInfo; struct ICSlotInfo;
...@@ -277,7 +277,7 @@ public: ...@@ -277,7 +277,7 @@ public:
// of the normal dispatch through the functionlist. // of the normal dispatch through the functionlist.
// This can be used to implement functions which know how to rewrite themselves, // This can be used to implement functions which know how to rewrite themselves,
// such as typeCall. // such as typeCall.
typedef Box* (*InternalCallable)(BoxedFunction*, CallRewriteArgs*, ArgPassSpec, Box*, Box*, Box*, Box**, typedef Box* (*InternalCallable)(BoxedFunctionBase*, CallRewriteArgs*, ArgPassSpec, Box*, Box*, Box*, Box**,
const std::vector<const std::string*>*); const std::vector<const std::string*>*);
InternalCallable internal_callable = NULL; InternalCallable internal_callable = NULL;
......
This diff is collapsed.
...@@ -40,9 +40,9 @@ static Box* enable() { ...@@ -40,9 +40,9 @@ static Box* enable() {
void setupGC() { void setupGC() {
BoxedModule* gc_module = createModule("gc", "__builtin__"); BoxedModule* gc_module = createModule("gc", "__builtin__");
gc_module->giveAttr("__hex__", new BoxedFunction(boxRTFunction((void*)gcCollect, NONE, 0))); gc_module->giveAttr("__hex__", new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)gcCollect, NONE, 0)));
gc_module->giveAttr("isenabled", new BoxedFunction(boxRTFunction((void*)isEnabled, BOXED_BOOL, 0))); gc_module->giveAttr("isenabled", new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)isEnabled, BOXED_BOOL, 0)));
gc_module->giveAttr("disable", new BoxedFunction(boxRTFunction((void*)disable, NONE, 0))); gc_module->giveAttr("disable", new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)disable, NONE, 0)));
gc_module->giveAttr("enable", new BoxedFunction(boxRTFunction((void*)enable, NONE, 0))); gc_module->giveAttr("enable", new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)enable, NONE, 0)));
} }
} }
...@@ -225,9 +225,11 @@ void setupSys() { ...@@ -225,9 +225,11 @@ void setupSys() {
sys_module->giveAttr("stdin", new BoxedFile(stdin, "<stdin>", "r")); sys_module->giveAttr("stdin", new BoxedFile(stdin, "<stdin>", "r"));
sys_module->giveAttr("stderr", new BoxedFile(stderr, "<stderr>", "w")); sys_module->giveAttr("stderr", new BoxedFile(stderr, "<stderr>", "w"));
sys_module->giveAttr("exc_info", new BoxedFunction(boxRTFunction((void*)sysExcInfo, BOXED_TUPLE, 0))); sys_module->giveAttr("exc_info",
sys_module->giveAttr("exc_clear", new BoxedFunction(boxRTFunction((void*)sysExcClear, NONE, 0))); new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)sysExcInfo, BOXED_TUPLE, 0)));
sys_module->giveAttr("exit", new BoxedFunction(boxRTFunction((void*)sysExit, NONE, 1, 1, false, false), { None })); sys_module->giveAttr("exc_clear", new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)sysExcClear, NONE, 0)));
sys_module->giveAttr(
"exit", new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)sysExit, NONE, 1, 1, false, false), { None }));
sys_module->giveAttr("warnoptions", new BoxedList()); sys_module->giveAttr("warnoptions", new BoxedList());
sys_module->giveAttr("py3kwarning", False); sys_module->giveAttr("py3kwarning", False);
......
...@@ -139,10 +139,14 @@ Box* stackSize() { ...@@ -139,10 +139,14 @@ Box* stackSize() {
void setupThread() { void setupThread() {
thread_module = createModule("thread", "__builtin__"); thread_module = createModule("thread", "__builtin__");
thread_module->giveAttr("start_new_thread", new BoxedFunction(boxRTFunction((void*)startNewThread, BOXED_INT, 2))); thread_module->giveAttr("start_new_thread",
thread_module->giveAttr("allocate_lock", new BoxedFunction(boxRTFunction((void*)allocateLock, UNKNOWN, 0))); new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)startNewThread, BOXED_INT, 2)));
thread_module->giveAttr("get_ident", new BoxedFunction(boxRTFunction((void*)getIdent, BOXED_INT, 0))); thread_module->giveAttr("allocate_lock",
thread_module->giveAttr("stack_size", new BoxedFunction(boxRTFunction((void*)stackSize, BOXED_INT, 0))); new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)allocateLock, UNKNOWN, 0)));
thread_module->giveAttr("get_ident",
new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)getIdent, BOXED_INT, 0)));
thread_module->giveAttr("stack_size",
new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)stackSize, BOXED_INT, 0)));
thread_lock_cls = new BoxedHeapClass(object_cls, NULL, 0, sizeof(BoxedThreadLock), false, "lock"); thread_lock_cls = new BoxedHeapClass(object_cls, NULL, 0, sizeof(BoxedThreadLock), false, "lock");
thread_lock_cls->giveAttr("__module__", boxStrConstant("thread")); thread_lock_cls->giveAttr("__module__", boxStrConstant("thread"));
......
...@@ -1452,8 +1452,8 @@ BoxedModule* importTestExtension(const std::string& name) { ...@@ -1452,8 +1452,8 @@ BoxedModule* importTestExtension(const std::string& name) {
return m; return m;
} }
Box* BoxedCApiFunction::callInternal(BoxedFunction* func, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* BoxedCApiFunction::callInternal(BoxedFunctionBase* func, CallRewriteArgs* rewrite_args, ArgPassSpec argspec,
Box* arg2, Box* arg3, Box** args, Box* arg1, Box* arg2, Box* arg3, Box** args,
const std::vector<const std::string*>* keyword_names) { const std::vector<const std::string*>* keyword_names) {
if (argspec != ArgPassSpec(2)) if (argspec != ArgPassSpec(2))
return callFunc(func, rewrite_args, argspec, arg1, arg2, arg3, args, keyword_names); return callFunc(func, rewrite_args, argspec, arg1, arg2, arg3, args, keyword_names);
......
...@@ -49,7 +49,7 @@ static void generatorEntry(BoxedGenerator* g) { ...@@ -49,7 +49,7 @@ static void generatorEntry(BoxedGenerator* g) {
try { try {
// call body of the generator // call body of the generator
BoxedFunction* func = g->function; BoxedFunctionBase* func = g->function;
Box** args = g->args ? &g->args->elts[0] : nullptr; Box** args = g->args ? &g->args->elts[0] : nullptr;
callCLFunc(func->f, nullptr, func->f->numReceivedArgs(), func->closure, g, g->arg1, g->arg2, g->arg3, args); callCLFunc(func->f, nullptr, func->f->numReceivedArgs(), func->closure, g, g->arg1, g->arg2, g->arg3, args);
...@@ -138,14 +138,14 @@ extern "C" Box* yield(BoxedGenerator* obj, Box* value) { ...@@ -138,14 +138,14 @@ extern "C" Box* yield(BoxedGenerator* obj, Box* value) {
} }
extern "C" BoxedGenerator* createGenerator(BoxedFunction* function, Box* arg1, Box* arg2, Box* arg3, Box** args) { extern "C" BoxedGenerator* createGenerator(BoxedFunctionBase* function, Box* arg1, Box* arg2, Box* arg3, Box** args) {
assert(function); assert(function);
assert(function->cls == function_cls); assert(function->cls == function_cls);
return new BoxedGenerator(function, arg1, arg2, arg3, args); return new BoxedGenerator(function, arg1, arg2, arg3, args);
} }
extern "C" BoxedGenerator::BoxedGenerator(BoxedFunction* function, Box* arg1, Box* arg2, Box* arg3, Box** args) extern "C" BoxedGenerator::BoxedGenerator(BoxedFunctionBase* function, Box* arg1, Box* arg2, Box* arg3, Box** args)
: function(function), arg1(arg1), arg2(arg2), arg3(arg3), args(nullptr), entryExited(false), running(false), : function(function), arg1(arg1), arg2(arg2), arg3(arg3), args(nullptr), entryExited(false), running(false),
returnValue(nullptr), exception(nullptr, nullptr, nullptr) { returnValue(nullptr), exception(nullptr, nullptr, nullptr) {
......
...@@ -25,7 +25,7 @@ extern BoxedClass* generator_cls; ...@@ -25,7 +25,7 @@ extern BoxedClass* generator_cls;
void setupGenerator(); void setupGenerator();
extern "C" Box* yield(BoxedGenerator* obj, Box* value); extern "C" Box* yield(BoxedGenerator* obj, Box* value);
extern "C" BoxedGenerator* createGenerator(BoxedFunction* function, Box* arg1, Box* arg2, Box* arg3, Box** args); extern "C" BoxedGenerator* createGenerator(BoxedFunctionBase* function, Box* arg1, Box* arg2, Box* arg3, Box** args);
} }
#endif #endif
...@@ -102,12 +102,13 @@ static Box* (*runtimeCallInternal2)(Box*, CallRewriteArgs*, ArgPassSpec, Box*, B ...@@ -102,12 +102,13 @@ static Box* (*runtimeCallInternal2)(Box*, CallRewriteArgs*, ArgPassSpec, Box*, B
static Box* (*runtimeCallInternal3)(Box*, CallRewriteArgs*, ArgPassSpec, Box*, Box*, Box*) static Box* (*runtimeCallInternal3)(Box*, CallRewriteArgs*, ArgPassSpec, Box*, Box*, Box*)
= (Box * (*)(Box*, CallRewriteArgs*, ArgPassSpec, Box*, Box*, Box*))runtimeCallInternal; = (Box * (*)(Box*, CallRewriteArgs*, ArgPassSpec, Box*, Box*, Box*))runtimeCallInternal;
static Box* (*typeCallInternal1)(BoxedFunction*, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box*) static Box* (*typeCallInternal1)(BoxedFunctionBase*, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box*)
= (Box * (*)(BoxedFunction*, CallRewriteArgs*, ArgPassSpec, Box*))typeCallInternal; = (Box * (*)(BoxedFunctionBase*, CallRewriteArgs*, ArgPassSpec, Box*))typeCallInternal;
static Box* (*typeCallInternal2)(BoxedFunction*, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box*, Box*) static Box* (*typeCallInternal2)(BoxedFunctionBase*, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box*, Box*)
= (Box * (*)(BoxedFunction*, CallRewriteArgs*, ArgPassSpec, Box*, Box*))typeCallInternal; = (Box * (*)(BoxedFunctionBase*, CallRewriteArgs*, ArgPassSpec, Box*, Box*))typeCallInternal;
static Box* (*typeCallInternal3)(BoxedFunction*, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box*, Box*, Box*) static Box* (*typeCallInternal3)(BoxedFunctionBase*, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box*, Box*,
= (Box * (*)(BoxedFunction*, CallRewriteArgs*, ArgPassSpec, Box*, Box*, Box*))typeCallInternal; Box*)
= (Box * (*)(BoxedFunctionBase*, CallRewriteArgs*, ArgPassSpec, Box*, Box*, Box*))typeCallInternal;
bool checkClass(LookupScope scope) { bool checkClass(LookupScope scope) {
return (scope & CLASS_ONLY) != 0; return (scope & CLASS_ONLY) != 0;
...@@ -2098,7 +2099,8 @@ extern "C" Box* callattrInternal(Box* obj, const std::string* attr, LookupScope ...@@ -2098,7 +2099,8 @@ extern "C" Box* callattrInternal(Box* obj, const std::string* attr, LookupScope
Box* rtn; Box* rtn;
// I *think* this check is here to limit the recursion nesting for rewriting, and originates // I *think* this check is here to limit the recursion nesting for rewriting, and originates
// from a time when we didn't have silent-abort-when-patchpoint-full. // from a time when we didn't have silent-abort-when-patchpoint-full.
if (val->cls != function_cls && val->cls != instancemethod_cls && val->cls != capifunc_cls) { if (val->cls != function_cls && val->cls != builtin_function_or_method_cls && val->cls != instancemethod_cls
&& val->cls != capifunc_cls) {
rewrite_args = NULL; rewrite_args = NULL;
REWRITE_ABORTED(""); REWRITE_ABORTED("");
} }
...@@ -2308,8 +2310,8 @@ static void placeKeyword(const std::vector<AST_expr*>& arg_names, std::vector<bo ...@@ -2308,8 +2310,8 @@ static void placeKeyword(const std::vector<AST_expr*>& arg_names, std::vector<bo
} }
} }
Box* callFunc(BoxedFunction* func, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3, Box* callFunc(BoxedFunctionBase* func, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2,
Box** args, const std::vector<const std::string*>* keyword_names) { Box* arg3, Box** args, const std::vector<const std::string*>* keyword_names) {
/* /*
* Procedure: * Procedure:
...@@ -2341,8 +2343,8 @@ Box* callFunc(BoxedFunction* func, CallRewriteArgs* rewrite_args, ArgPassSpec ar ...@@ -2341,8 +2343,8 @@ Box* callFunc(BoxedFunction* func, CallRewriteArgs* rewrite_args, ArgPassSpec ar
REWRITE_ABORTED(""); REWRITE_ABORTED("");
} }
// TODO Should we guard on the CLFunction or the BoxedFunction? // TODO Should we guard on the CLFunction or the BoxedFunctionBase?
// A single CLFunction could end up forming multiple BoxedFunctions, and we // A single CLFunction could end up forming multiple BoxedFunctionBases, and we
// could emit assembly that handles any of them. But doing this involves some // could emit assembly that handles any of them. But doing this involves some
// extra indirection, and it's not clear if that's worth it, since it seems like // extra indirection, and it's not clear if that's worth it, since it seems like
// the common case will be functions only ever getting a single set of default arguments. // the common case will be functions only ever getting a single set of default arguments.
...@@ -2354,7 +2356,7 @@ Box* callFunc(BoxedFunction* func, CallRewriteArgs* rewrite_args, ArgPassSpec ar ...@@ -2354,7 +2356,7 @@ Box* callFunc(BoxedFunction* func, CallRewriteArgs* rewrite_args, ArgPassSpec ar
if (!rewrite_args->func_guarded) { if (!rewrite_args->func_guarded) {
if (guard_clfunc) { if (guard_clfunc) {
rewrite_args->obj->addAttrGuard(offsetof(BoxedFunction, f), (intptr_t)f); rewrite_args->obj->addAttrGuard(offsetof(BoxedFunctionBase, f), (intptr_t)f);
} else { } else {
rewrite_args->obj->addGuard((intptr_t)func); rewrite_args->obj->addGuard((intptr_t)func);
} }
...@@ -2532,7 +2534,7 @@ Box* callFunc(BoxedFunction* func, CallRewriteArgs* rewrite_args, ArgPassSpec ar ...@@ -2532,7 +2534,7 @@ Box* callFunc(BoxedFunction* func, CallRewriteArgs* rewrite_args, ArgPassSpec ar
RewriterVar* r_defaults_array = NULL; RewriterVar* r_defaults_array = NULL;
if (guard_clfunc) { if (guard_clfunc) {
r_defaults_array = rewrite_args->obj->getAttr(offsetof(BoxedFunction, defaults), Location::any()); r_defaults_array = rewrite_args->obj->getAttr(offsetof(BoxedFunctionBase, defaults), Location::any());
} }
for (int i = f->num_args - f->num_defaults; i < f->num_args; i++) { for (int i = f->num_args - f->num_defaults; i < f->num_args; i++) {
...@@ -2543,7 +2545,7 @@ Box* callFunc(BoxedFunction* func, CallRewriteArgs* rewrite_args, ArgPassSpec ar ...@@ -2543,7 +2545,7 @@ Box* callFunc(BoxedFunction* func, CallRewriteArgs* rewrite_args, ArgPassSpec ar
Box* default_obj = func->defaults->elts[default_idx]; Box* default_obj = func->defaults->elts[default_idx];
if (rewrite_args) { if (rewrite_args) {
int offset = offsetof(std::remove_pointer<decltype(BoxedFunction::defaults)>::type, elts) int offset = offsetof(std::remove_pointer<decltype(BoxedFunctionBase::defaults)>::type, elts)
+ sizeof(Box*) * default_idx; + sizeof(Box*) * default_idx;
if (guard_clfunc) { if (guard_clfunc) {
// If we just guarded on the CLFunction, then we have to emit assembly // If we just guarded on the CLFunction, then we have to emit assembly
...@@ -2561,7 +2563,7 @@ Box* callFunc(BoxedFunction* func, CallRewriteArgs* rewrite_args, ArgPassSpec ar ...@@ -2561,7 +2563,7 @@ Box* callFunc(BoxedFunction* func, CallRewriteArgs* rewrite_args, ArgPassSpec ar
rewrite_args->args->setAttr((i - 3) * sizeof(Box*), r_default); rewrite_args->args->setAttr((i - 3) * sizeof(Box*), r_default);
} }
} else { } else {
// If we guarded on the BoxedFunction, which has a constant set of defaults, // If we guarded on the BoxedFunctionBase, which has a constant set of defaults,
// we can embed the default arguments directly into the instructions. // we can embed the default arguments directly into the instructions.
if (i < 3) { if (i < 3) {
RewriterVar* r_default = rewrite_args->rewriter->loadConst((intptr_t)default_obj, Location::any()); RewriterVar* r_default = rewrite_args->rewriter->loadConst((intptr_t)default_obj, Location::any());
...@@ -2638,7 +2640,7 @@ Box* runtimeCallInternal(Box* obj, CallRewriteArgs* rewrite_args, ArgPassSpec ar ...@@ -2638,7 +2640,7 @@ Box* runtimeCallInternal(Box* obj, CallRewriteArgs* rewrite_args, ArgPassSpec ar
Box** args, const std::vector<const std::string*>* keyword_names) { Box** args, const std::vector<const std::string*>* keyword_names) {
int npassed_args = argspec.totalPassed(); int npassed_args = argspec.totalPassed();
if (obj->cls != function_cls && obj->cls != instancemethod_cls) { if (obj->cls != function_cls && obj->cls != builtin_function_or_method_cls && obj->cls != instancemethod_cls) {
Box* rtn; Box* rtn;
if (rewrite_args) { if (rewrite_args) {
// TODO is this ok? // TODO is this ok?
...@@ -2672,11 +2674,12 @@ Box* runtimeCallInternal(Box* obj, CallRewriteArgs* rewrite_args, ArgPassSpec ar ...@@ -2672,11 +2674,12 @@ Box* runtimeCallInternal(Box* obj, CallRewriteArgs* rewrite_args, ArgPassSpec ar
rewrite_args->args_guarded = true; rewrite_args->args_guarded = true;
} }
rewrite_args->rewriter->addDecision(obj->cls == function_cls ? 1 : 0); rewrite_args->rewriter->addDecision(obj->cls == function_cls || obj->cls == builtin_function_or_method_cls ? 1
: 0);
} }
if (obj->cls == function_cls) { if (obj->cls == function_cls || obj->cls == builtin_function_or_method_cls) {
BoxedFunction* f = static_cast<BoxedFunction*>(obj); BoxedFunctionBase* f = static_cast<BoxedFunctionBase*>(obj);
// Some functions are sufficiently important that we want them to be able to patchpoint themselves; // Some functions are sufficiently important that we want them to be able to patchpoint themselves;
// they can do this by setting the "internal_callable" field: // they can do this by setting the "internal_callable" field:
...@@ -3464,7 +3467,7 @@ Box* typeNew(Box* _cls, Box* arg1, Box* arg2, Box** _args) { ...@@ -3464,7 +3467,7 @@ Box* typeNew(Box* _cls, Box* arg1, Box* arg2, Box** _args) {
return made; return made;
} }
Box* typeCallInternal(BoxedFunction* f, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* typeCallInternal(BoxedFunctionBase* f, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2,
Box* arg3, Box** args, const std::vector<const std::string*>* keyword_names) { Box* arg3, Box** args, const std::vector<const std::string*>* keyword_names) {
int npassed_args = argspec.totalPassed(); int npassed_args = argspec.totalPassed();
......
...@@ -100,11 +100,11 @@ struct BinopRewriteArgs; ...@@ -100,11 +100,11 @@ struct BinopRewriteArgs;
extern "C" Box* binopInternal(Box* lhs, Box* rhs, int op_type, bool inplace, BinopRewriteArgs* rewrite_args); extern "C" Box* binopInternal(Box* lhs, Box* rhs, int op_type, bool inplace, BinopRewriteArgs* rewrite_args);
struct CallRewriteArgs; struct CallRewriteArgs;
Box* typeCallInternal(BoxedFunction* f, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* typeCallInternal(BoxedFunctionBase* f, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2,
Box* arg3, Box** args, const std::vector<const std::string*>* keyword_names); Box* arg3, Box** args, const std::vector<const std::string*>* keyword_names);
Box* callFunc(BoxedFunction* func, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3, Box* callFunc(BoxedFunctionBase* func, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2,
Box** args, const std::vector<const std::string*>* keyword_names); Box* arg3, Box** args, const std::vector<const std::string*>* keyword_names);
enum LookupScope { enum LookupScope {
CLASS_ONLY = 1, CLASS_ONLY = 1,
......
...@@ -268,7 +268,7 @@ void BoxIterator::gcHandler(GCVisitor* v) { ...@@ -268,7 +268,7 @@ void BoxIterator::gcHandler(GCVisitor* v) {
std::string builtinStr("__builtin__"); std::string builtinStr("__builtin__");
extern "C" BoxedFunction::BoxedFunction(CLFunction* f) extern "C" BoxedFunctionBase::BoxedFunctionBase(CLFunction* f)
: f(f), closure(NULL), isGenerator(false), ndefaults(0), defaults(NULL) { : f(f), closure(NULL), isGenerator(false), ndefaults(0), defaults(NULL) {
if (f->source) { if (f->source) {
this->modname = f->source->parent_module->getattr("__name__", NULL); this->modname = f->source->parent_module->getattr("__name__", NULL);
...@@ -281,8 +281,8 @@ extern "C" BoxedFunction::BoxedFunction(CLFunction* f) ...@@ -281,8 +281,8 @@ extern "C" BoxedFunction::BoxedFunction(CLFunction* f)
assert(f->num_defaults == ndefaults); assert(f->num_defaults == ndefaults);
} }
extern "C" BoxedFunction::BoxedFunction(CLFunction* f, std::initializer_list<Box*> defaults, BoxedClosure* closure, extern "C" BoxedFunctionBase::BoxedFunctionBase(CLFunction* f, std::initializer_list<Box*> defaults,
bool isGenerator) BoxedClosure* closure, bool isGenerator)
: f(f), closure(closure), isGenerator(isGenerator), ndefaults(0), defaults(NULL) { : f(f), closure(closure), isGenerator(isGenerator), ndefaults(0), defaults(NULL) {
if (defaults.size()) { if (defaults.size()) {
// make sure to initialize defaults first, since the GC behavior is triggered by ndefaults, // make sure to initialize defaults first, since the GC behavior is triggered by ndefaults,
...@@ -307,13 +307,13 @@ extern "C" BoxedFunction::BoxedFunction(CLFunction* f, std::initializer_list<Box ...@@ -307,13 +307,13 @@ extern "C" BoxedFunction::BoxedFunction(CLFunction* f, std::initializer_list<Box
extern "C" void functionGCHandler(GCVisitor* v, Box* b) { extern "C" void functionGCHandler(GCVisitor* v, Box* b) {
boxGCHandler(v, b); boxGCHandler(v, b);
BoxedFunction* f = (BoxedFunction*)b; BoxedFunctionBase* f = (BoxedFunctionBase*)b;
if (f->closure) if (f->closure)
v->visit(f->closure); v->visit(f->closure);
// It's ok for f->defaults to be NULL here even if f->ndefaults isn't, // It's ok for f->defaults to be NULL here even if f->ndefaults isn't,
// since we could be collecting from inside a BoxedFunction constructor // since we could be collecting from inside a BoxedFunctionBase constructor
if (f->ndefaults) { if (f->ndefaults) {
assert(f->defaults); assert(f->defaults);
v->visit(f->defaults); v->visit(f->defaults);
...@@ -498,8 +498,7 @@ extern "C" { ...@@ -498,8 +498,7 @@ extern "C" {
BoxedClass* object_cls, *type_cls, *none_cls, *bool_cls, *int_cls, *float_cls, BoxedClass* object_cls, *type_cls, *none_cls, *bool_cls, *int_cls, *float_cls,
* str_cls = NULL, *function_cls, *instancemethod_cls, *list_cls, *slice_cls, *module_cls, *dict_cls, *tuple_cls, * str_cls = NULL, *function_cls, *instancemethod_cls, *list_cls, *slice_cls, *module_cls, *dict_cls, *tuple_cls,
*file_cls, *member_cls, *closure_cls, *generator_cls, *complex_cls, *basestring_cls, *unicode_cls, *property_cls, *file_cls, *member_cls, *closure_cls, *generator_cls, *complex_cls, *basestring_cls, *unicode_cls, *property_cls,
*staticmethod_cls, *classmethod_cls, *attrwrapper_cls, *getset_cls; *staticmethod_cls, *classmethod_cls, *attrwrapper_cls, *getset_cls, *builtin_function_or_method_cls;
BoxedTuple* EmptyTuple; BoxedTuple* EmptyTuple;
} }
...@@ -578,7 +577,7 @@ extern "C" Box* noneNonzero(Box* v) { ...@@ -578,7 +577,7 @@ extern "C" Box* noneNonzero(Box* v) {
return False; return False;
} }
extern "C" BoxedString* functionRepr(BoxedFunction* v) { extern "C" BoxedString* builtinFunctionOrMethodRepr(BoxedBuiltinFunctionOrMethod* v) {
// TODO there has to be a better way // TODO there has to be a better way
if (v == repr_obj) if (v == repr_obj)
return boxStrConstant("<built-in function repr>"); return boxStrConstant("<built-in function repr>");
...@@ -602,6 +601,10 @@ extern "C" BoxedString* functionRepr(BoxedFunction* v) { ...@@ -602,6 +601,10 @@ extern "C" BoxedString* functionRepr(BoxedFunction* v) {
return boxStrConstant("<built-in function chr>"); return boxStrConstant("<built-in function chr>");
if (v == ord_obj) if (v == ord_obj)
return boxStrConstant("<built-in function ord>"); return boxStrConstant("<built-in function ord>");
RELEASE_ASSERT(false, "builtinFunctionOrMethodRepr not properly implemented");
}
extern "C" BoxedString* functionRepr(BoxedFunction* v) {
return new BoxedString("function"); return new BoxedString("function");
} }
...@@ -1088,6 +1091,9 @@ void setupRuntime() { ...@@ -1088,6 +1091,9 @@ void setupRuntime() {
float_cls = new BoxedHeapClass(object_cls, NULL, 0, sizeof(BoxedFloat), false, "float"); float_cls = new BoxedHeapClass(object_cls, NULL, 0, sizeof(BoxedFloat), false, "float");
function_cls = new BoxedHeapClass(object_cls, &functionGCHandler, offsetof(BoxedFunction, attrs), function_cls = new BoxedHeapClass(object_cls, &functionGCHandler, offsetof(BoxedFunction, attrs),
sizeof(BoxedFunction), false, "function"); sizeof(BoxedFunction), false, "function");
builtin_function_or_method_cls
= new BoxedHeapClass(object_cls, &functionGCHandler, offsetof(BoxedBuiltinFunctionOrMethod, attrs),
sizeof(BoxedBuiltinFunctionOrMethod), false, "builtin_function_or_method");
instancemethod_cls = new BoxedHeapClass(object_cls, &instancemethodGCHandler, 0, sizeof(BoxedInstanceMethod), false, instancemethod_cls = new BoxedHeapClass(object_cls, &instancemethodGCHandler, 0, sizeof(BoxedInstanceMethod), false,
"instancemethod"); "instancemethod");
list_cls = new BoxedHeapClass(object_cls, &listGCHandler, 0, sizeof(BoxedList), false, "list"); list_cls = new BoxedHeapClass(object_cls, &listGCHandler, 0, sizeof(BoxedList), false, "list");
...@@ -1181,6 +1187,13 @@ void setupRuntime() { ...@@ -1181,6 +1187,13 @@ void setupRuntime() {
function_cls->giveAttr("__nonzero__", new BoxedFunction(boxRTFunction((void*)functionNonzero, BOXED_BOOL, 1))); function_cls->giveAttr("__nonzero__", new BoxedFunction(boxRTFunction((void*)functionNonzero, BOXED_BOOL, 1)));
function_cls->freeze(); function_cls->freeze();
builtin_function_or_method_cls->giveAttr(
"__module__",
new BoxedMemberDescriptor(BoxedMemberDescriptor::OBJECT, offsetof(BoxedBuiltinFunctionOrMethod, modname)));
builtin_function_or_method_cls->giveAttr(
"__repr__", new BoxedFunction(boxRTFunction((void*)builtinFunctionOrMethodRepr, STR, 1)));
builtin_function_or_method_cls->freeze();
instancemethod_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)instancemethodRepr, STR, 1))); instancemethod_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)instancemethodRepr, STR, 1)));
instancemethod_cls->giveAttr("__eq__", new BoxedFunction(boxRTFunction((void*)instancemethodEq, UNKNOWN, 2))); instancemethod_cls->giveAttr("__eq__", new BoxedFunction(boxRTFunction((void*)instancemethodEq, UNKNOWN, 2)));
instancemethod_cls->giveAttr( instancemethod_cls->giveAttr(
......
...@@ -79,7 +79,8 @@ extern "C" { ...@@ -79,7 +79,8 @@ extern "C" {
extern BoxedClass* object_cls, *type_cls, *bool_cls, *int_cls, *long_cls, *float_cls, *str_cls, *function_cls, extern BoxedClass* object_cls, *type_cls, *bool_cls, *int_cls, *long_cls, *float_cls, *str_cls, *function_cls,
*none_cls, *instancemethod_cls, *list_cls, *slice_cls, *module_cls, *dict_cls, *tuple_cls, *file_cls, *none_cls, *instancemethod_cls, *list_cls, *slice_cls, *module_cls, *dict_cls, *tuple_cls, *file_cls,
*enumerate_cls, *xrange_cls, *member_cls, *method_cls, *closure_cls, *generator_cls, *complex_cls, *basestring_cls, *enumerate_cls, *xrange_cls, *member_cls, *method_cls, *closure_cls, *generator_cls, *complex_cls, *basestring_cls,
*unicode_cls, *property_cls, *staticmethod_cls, *classmethod_cls, *attrwrapper_cls, *getset_cls; *unicode_cls, *property_cls, *staticmethod_cls, *classmethod_cls, *attrwrapper_cls, *getset_cls,
*builtin_function_or_method_cls;
} }
extern "C" { extern "C" {
extern Box* None, *NotImplemented, *True, *False; extern Box* None, *NotImplemented, *True, *False;
...@@ -435,7 +436,7 @@ public: ...@@ -435,7 +436,7 @@ public:
}; };
static_assert(sizeof(BoxedDict) == sizeof(PyDictObject), ""); static_assert(sizeof(BoxedDict) == sizeof(PyDictObject), "");
class BoxedFunction : public Box { class BoxedFunctionBase : public Box {
public: public:
HCAttrs attrs; HCAttrs attrs;
CLFunction* f; CLFunction* f;
...@@ -448,13 +449,31 @@ public: ...@@ -448,13 +449,31 @@ public:
// Accessed via member descriptor // Accessed via member descriptor
Box* modname; // __module__ Box* modname; // __module__
BoxedFunction(CLFunction* f); BoxedFunctionBase(CLFunction* f);
BoxedFunctionBase(CLFunction* f, std::initializer_list<Box*> defaults, BoxedClosure* closure = NULL,
bool isGenerator = false);
};
class BoxedFunction : public BoxedFunctionBase {
public:
BoxedFunction(CLFunction* f) : BoxedFunctionBase(f) {}
BoxedFunction(CLFunction* f, std::initializer_list<Box*> defaults, BoxedClosure* closure = NULL, BoxedFunction(CLFunction* f, std::initializer_list<Box*> defaults, BoxedClosure* closure = NULL,
bool isGenerator = false); bool isGenerator = false)
: BoxedFunctionBase(f, defaults, closure, isGenerator) {}
DEFAULT_CLASS(function_cls); DEFAULT_CLASS(function_cls);
}; };
class BoxedBuiltinFunctionOrMethod : public BoxedFunctionBase {
public:
BoxedBuiltinFunctionOrMethod(CLFunction* f) : BoxedFunctionBase(f) {}
BoxedBuiltinFunctionOrMethod(CLFunction* f, std::initializer_list<Box*> defaults, BoxedClosure* closure = NULL,
bool isGenerator = false)
: BoxedFunctionBase(f, defaults, closure, isGenerator) {}
DEFAULT_CLASS(builtin_function_or_method_cls);
};
class BoxedModule : public Box { class BoxedModule : public Box {
public: public:
HCAttrs attrs; HCAttrs attrs;
...@@ -564,7 +583,7 @@ public: ...@@ -564,7 +583,7 @@ public:
class BoxedGenerator : public Box { class BoxedGenerator : public Box {
public: public:
HCAttrs attrs; HCAttrs attrs;
BoxedFunction* function; BoxedFunctionBase* function;
Box* arg1, *arg2, *arg3; Box* arg1, *arg2, *arg3;
GCdArray* args; GCdArray* args;
...@@ -576,7 +595,7 @@ public: ...@@ -576,7 +595,7 @@ public:
ucontext_t context, returnContext; ucontext_t context, returnContext;
void* stack_begin; void* stack_begin;
BoxedGenerator(BoxedFunction* function, Box* arg1, Box* arg2, Box* arg3, Box** args); BoxedGenerator(BoxedFunctionBase* function, Box* arg1, Box* arg2, Box* arg3, Box** args);
DEFAULT_CLASS(generator_cls); DEFAULT_CLASS(generator_cls);
}; };
......
...@@ -78,3 +78,9 @@ class Iterable(object): ...@@ -78,3 +78,9 @@ class Iterable(object):
i = Iterable() i = Iterable()
it = iter(i) it = iter(i)
print it is i print it is i
# check that builtins don't bind
class C(object):
s = sorted
c = C()
print c.s([3,2,1])
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment