Commit 128cb7c7 authored by Travis Hance's avatar Travis Hance

builtin functions

parent ee548408
......@@ -83,7 +83,7 @@ public:
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);
};
......
......@@ -121,7 +121,7 @@ typedef ValuedCompilerVariable<llvm::Value*> ConcreteCompilerVariable;
class Box;
class BoxedClass;
class BoxedModule;
class BoxedFunction;
class BoxedFunctionBase;
class ICGetattr;
struct ICSlotInfo;
......@@ -277,7 +277,7 @@ public:
// of the normal dispatch through the functionlist.
// This can be used to implement functions which know how to rewrite themselves,
// 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*>*);
InternalCallable internal_callable = NULL;
......
This diff is collapsed.
......@@ -40,9 +40,9 @@ static Box* enable() {
void setupGC() {
BoxedModule* gc_module = createModule("gc", "__builtin__");
gc_module->giveAttr("__hex__", new BoxedFunction(boxRTFunction((void*)gcCollect, NONE, 0)));
gc_module->giveAttr("isenabled", new BoxedFunction(boxRTFunction((void*)isEnabled, BOXED_BOOL, 0)));
gc_module->giveAttr("disable", new BoxedFunction(boxRTFunction((void*)disable, NONE, 0)));
gc_module->giveAttr("enable", new BoxedFunction(boxRTFunction((void*)enable, NONE, 0)));
gc_module->giveAttr("__hex__", new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)gcCollect, NONE, 0)));
gc_module->giveAttr("isenabled", new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)isEnabled, BOXED_BOOL, 0)));
gc_module->giveAttr("disable", new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)disable, NONE, 0)));
gc_module->giveAttr("enable", new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)enable, NONE, 0)));
}
}
......@@ -224,9 +224,11 @@ void setupSys() {
sys_module->giveAttr("stdin", new BoxedFile(stdin, "<stdin>", "r"));
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_clear", new BoxedFunction(boxRTFunction((void*)sysExcClear, NONE, 0)));
sys_module->giveAttr("exit", new BoxedFunction(boxRTFunction((void*)sysExit, NONE, 1, 1, false, false), { None }));
sys_module->giveAttr("exc_info",
new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)sysExcInfo, BOXED_TUPLE, 0)));
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("py3kwarning", False);
......
......@@ -139,10 +139,14 @@ Box* stackSize() {
void setupThread() {
thread_module = createModule("thread", "__builtin__");
thread_module->giveAttr("start_new_thread", new BoxedFunction(boxRTFunction((void*)startNewThread, BOXED_INT, 2)));
thread_module->giveAttr("allocate_lock", new BoxedFunction(boxRTFunction((void*)allocateLock, UNKNOWN, 0)));
thread_module->giveAttr("get_ident", new BoxedFunction(boxRTFunction((void*)getIdent, BOXED_INT, 0)));
thread_module->giveAttr("stack_size", new BoxedFunction(boxRTFunction((void*)stackSize, BOXED_INT, 0)));
thread_module->giveAttr("start_new_thread",
new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)startNewThread, BOXED_INT, 2)));
thread_module->giveAttr("allocate_lock",
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->giveAttr("__module__", boxStrConstant("thread"));
......
......@@ -1442,8 +1442,8 @@ BoxedModule* importTestExtension(const std::string& name) {
return m;
}
Box* BoxedCApiFunction::callInternal(BoxedFunction* func, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1,
Box* arg2, Box* arg3, Box** args,
Box* BoxedCApiFunction::callInternal(BoxedFunctionBase* func, CallRewriteArgs* rewrite_args, ArgPassSpec argspec,
Box* arg1, Box* arg2, Box* arg3, Box** args,
const std::vector<const std::string*>* keyword_names) {
if (argspec != ArgPassSpec(2))
return callFunc(func, rewrite_args, argspec, arg1, arg2, arg3, args, keyword_names);
......
......@@ -49,7 +49,7 @@ static void generatorEntry(BoxedGenerator* g) {
try {
// call body of the generator
BoxedFunction* func = g->function;
BoxedFunctionBase* func = g->function;
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);
......@@ -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->cls == function_cls);
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),
returnValue(nullptr), exception(nullptr, nullptr, nullptr) {
......
......@@ -25,7 +25,7 @@ extern BoxedClass* generator_cls;
void setupGenerator();
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
......@@ -101,12 +101,13 @@ static Box* (*runtimeCallInternal2)(Box*, CallRewriteArgs*, ArgPassSpec, Box*, B
static Box* (*runtimeCallInternal3)(Box*, CallRewriteArgs*, ArgPassSpec, Box*, Box*, Box*)
= (Box * (*)(Box*, CallRewriteArgs*, ArgPassSpec, Box*, Box*, Box*))runtimeCallInternal;
static Box* (*typeCallInternal1)(BoxedFunction*, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box*)
= (Box * (*)(BoxedFunction*, CallRewriteArgs*, ArgPassSpec, Box*))typeCallInternal;
static Box* (*typeCallInternal2)(BoxedFunction*, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box*, Box*)
= (Box * (*)(BoxedFunction*, CallRewriteArgs*, ArgPassSpec, Box*, Box*))typeCallInternal;
static Box* (*typeCallInternal3)(BoxedFunction*, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box*, Box*, Box*)
= (Box * (*)(BoxedFunction*, CallRewriteArgs*, ArgPassSpec, Box*, Box*, Box*))typeCallInternal;
static Box* (*typeCallInternal1)(BoxedFunctionBase*, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box*)
= (Box * (*)(BoxedFunctionBase*, CallRewriteArgs*, ArgPassSpec, Box*))typeCallInternal;
static Box* (*typeCallInternal2)(BoxedFunctionBase*, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box*, Box*)
= (Box * (*)(BoxedFunctionBase*, CallRewriteArgs*, ArgPassSpec, Box*, Box*))typeCallInternal;
static Box* (*typeCallInternal3)(BoxedFunctionBase*, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box*, Box*,
Box*)
= (Box * (*)(BoxedFunctionBase*, CallRewriteArgs*, ArgPassSpec, Box*, Box*, Box*))typeCallInternal;
bool checkClass(LookupScope scope) {
return (scope & CLASS_ONLY) != 0;
......@@ -2096,7 +2097,8 @@ extern "C" Box* callattrInternal(Box* obj, const std::string* attr, LookupScope
Box* rtn;
// 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.
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_ABORTED("");
}
......@@ -2306,8 +2308,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** args, const std::vector<const std::string*>* keyword_names) {
Box* callFunc(BoxedFunctionBase* func, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2,
Box* arg3, Box** args, const std::vector<const std::string*>* keyword_names) {
/*
* Procedure:
......@@ -2339,8 +2341,8 @@ Box* callFunc(BoxedFunction* func, CallRewriteArgs* rewrite_args, ArgPassSpec ar
REWRITE_ABORTED("");
}
// TODO Should we guard on the CLFunction or the BoxedFunction?
// A single CLFunction could end up forming multiple BoxedFunctions, and we
// TODO Should we guard on the CLFunction or the BoxedFunctionBase?
// A single CLFunction could end up forming multiple BoxedFunctionBases, and we
// 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
// the common case will be functions only ever getting a single set of default arguments.
......@@ -2352,7 +2354,7 @@ Box* callFunc(BoxedFunction* func, CallRewriteArgs* rewrite_args, ArgPassSpec ar
if (!rewrite_args->func_guarded) {
if (guard_clfunc) {
rewrite_args->obj->addAttrGuard(offsetof(BoxedFunction, f), (intptr_t)f);
rewrite_args->obj->addAttrGuard(offsetof(BoxedFunctionBase, f), (intptr_t)f);
} else {
rewrite_args->obj->addGuard((intptr_t)func);
}
......@@ -2530,7 +2532,7 @@ Box* callFunc(BoxedFunction* func, CallRewriteArgs* rewrite_args, ArgPassSpec ar
RewriterVar* r_defaults_array = NULL;
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++) {
......@@ -2541,7 +2543,7 @@ Box* callFunc(BoxedFunction* func, CallRewriteArgs* rewrite_args, ArgPassSpec ar
Box* default_obj = func->defaults->elts[default_idx];
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;
if (guard_clfunc) {
// If we just guarded on the CLFunction, then we have to emit assembly
......@@ -2559,7 +2561,7 @@ Box* callFunc(BoxedFunction* func, CallRewriteArgs* rewrite_args, ArgPassSpec ar
rewrite_args->args->setAttr((i - 3) * sizeof(Box*), r_default);
}
} 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.
if (i < 3) {
RewriterVar* r_default = rewrite_args->rewriter->loadConst((intptr_t)default_obj, Location::any());
......@@ -2636,7 +2638,7 @@ Box* runtimeCallInternal(Box* obj, CallRewriteArgs* rewrite_args, ArgPassSpec ar
Box** args, const std::vector<const std::string*>* keyword_names) {
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;
if (rewrite_args) {
// TODO is this ok?
......@@ -2670,11 +2672,12 @@ Box* runtimeCallInternal(Box* obj, CallRewriteArgs* rewrite_args, ArgPassSpec ar
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) {
BoxedFunction* f = static_cast<BoxedFunction*>(obj);
if (obj->cls == function_cls || obj->cls == builtin_function_or_method_cls) {
BoxedFunctionBase* f = static_cast<BoxedFunctionBase*>(obj);
// 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:
......@@ -3462,7 +3465,7 @@ Box* typeNew(Box* _cls, Box* arg1, Box* arg2, Box** _args) {
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) {
int npassed_args = argspec.totalPassed();
......
......@@ -100,11 +100,11 @@ struct BinopRewriteArgs;
extern "C" Box* binopInternal(Box* lhs, Box* rhs, int op_type, bool inplace, BinopRewriteArgs* rewrite_args);
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* callFunc(BoxedFunction* func, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3,
Box** args, const std::vector<const std::string*>* keyword_names);
Box* callFunc(BoxedFunctionBase* func, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2,
Box* arg3, Box** args, const std::vector<const std::string*>* keyword_names);
enum LookupScope {
CLASS_ONLY = 1,
......
......@@ -265,7 +265,7 @@ void BoxIterator::gcHandler(GCVisitor* v) {
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) {
if (f->source) {
this->modname = f->source->parent_module->getattr("__name__", NULL);
......@@ -278,8 +278,8 @@ extern "C" BoxedFunction::BoxedFunction(CLFunction* f)
assert(f->num_defaults == ndefaults);
}
extern "C" BoxedFunction::BoxedFunction(CLFunction* f, std::initializer_list<Box*> defaults, BoxedClosure* closure,
bool isGenerator)
extern "C" BoxedFunctionBase::BoxedFunctionBase(CLFunction* f, std::initializer_list<Box*> defaults,
BoxedClosure* closure, bool isGenerator)
: f(f), closure(closure), isGenerator(isGenerator), ndefaults(0), defaults(NULL) {
if (defaults.size()) {
// make sure to initialize defaults first, since the GC behavior is triggered by ndefaults,
......@@ -304,13 +304,13 @@ extern "C" BoxedFunction::BoxedFunction(CLFunction* f, std::initializer_list<Box
extern "C" void functionGCHandler(GCVisitor* v, Box* b) {
boxGCHandler(v, b);
BoxedFunction* f = (BoxedFunction*)b;
BoxedFunctionBase* f = (BoxedFunctionBase*)b;
if (f->closure)
v->visit(f->closure);
// 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) {
assert(f->defaults);
v->visit(f->defaults);
......@@ -495,8 +495,7 @@ extern "C" {
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,
*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;
}
......@@ -575,7 +574,7 @@ extern "C" Box* noneNonzero(Box* v) {
return False;
}
extern "C" BoxedString* functionRepr(BoxedFunction* v) {
extern "C" BoxedString* builtinFunctionOrMethodRepr(BoxedBuiltinFunctionOrMethod* v) {
// TODO there has to be a better way
if (v == repr_obj)
return boxStrConstant("<built-in function repr>");
......@@ -599,6 +598,10 @@ extern "C" BoxedString* functionRepr(BoxedFunction* v) {
return boxStrConstant("<built-in function chr>");
if (v == ord_obj)
return boxStrConstant("<built-in function ord>");
RELEASE_ASSERT(false, "builtinFunctionOrMethodRepr not properly implemented");
}
extern "C" BoxedString* functionRepr(BoxedFunction* v) {
return new BoxedString("function");
}
......@@ -1075,6 +1078,9 @@ void setupRuntime() {
float_cls = new BoxedHeapClass(object_cls, NULL, 0, sizeof(BoxedFloat), false, "float");
function_cls = new BoxedHeapClass(object_cls, &functionGCHandler, offsetof(BoxedFunction, attrs),
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");
list_cls = new BoxedHeapClass(object_cls, &listGCHandler, 0, sizeof(BoxedList), false, "list");
......@@ -1166,6 +1172,13 @@ void setupRuntime() {
function_cls->giveAttr("__nonzero__", new BoxedFunction(boxRTFunction((void*)functionNonzero, BOXED_BOOL, 1)));
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("__eq__", new BoxedFunction(boxRTFunction((void*)instancemethodEq, UNKNOWN, 2)));
instancemethod_cls->giveAttr(
......
......@@ -79,7 +79,8 @@ extern "C" {
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,
*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 Box* None, *NotImplemented, *True, *False;
......@@ -448,7 +449,7 @@ public:
};
static_assert(sizeof(BoxedDict) == sizeof(PyDictObject), "");
class BoxedFunction : public Box {
class BoxedFunctionBase : public Box {
public:
HCAttrs attrs;
CLFunction* f;
......@@ -461,13 +462,31 @@ public:
// Accessed via member descriptor
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,
bool isGenerator = false);
bool isGenerator = false)
: BoxedFunctionBase(f, defaults, closure, isGenerator) {}
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 {
public:
HCAttrs attrs;
......@@ -577,7 +596,7 @@ public:
class BoxedGenerator : public Box {
public:
HCAttrs attrs;
BoxedFunction* function;
BoxedFunctionBase* function;
Box* arg1, *arg2, *arg3;
GCdArray* args;
......@@ -589,7 +608,7 @@ public:
ucontext_t context, returnContext;
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);
};
......
......@@ -78,3 +78,9 @@ class Iterable(object):
i = Iterable()
it = iter(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