Commit 6acfb996 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Implement defaults, keywords, varargs and kwargs

Not all exposed to python code yet

This commit is pretty large because it contains two separate but interrelated changes:
- Rewrite the function argument handling code (callCompiledFunction and resolveCLFunc)
  into a single callFunc that does its own rewriting, and support the new features.
-- this required a change of data representations, so instead of having each function
   consist of variants with unrelated signatures, we can only have a single signature,
   but multiple type specializations of that signature
- To do that, had to rewrite all of the stdlib functions that used signature-variation
  (ex range1 + range2 + range3) to be a single function that took default arguments, and
  then took action appropriately.
parent 31f7002a
...@@ -583,17 +583,17 @@ public: ...@@ -583,17 +583,17 @@ public:
for (int i = 0; i < clf->versions.size(); i++) { for (int i = 0; i < clf->versions.size(); i++) {
CompiledFunction* cf = clf->versions[i]; CompiledFunction* cf = clf->versions[i];
FunctionSignature* fsig = cf->sig; FunctionSpecialization* fspec = cf->spec;
Sig* type_sig = new Sig(); Sig* type_sig = new Sig();
type_sig->rtn_type = fsig->rtn_type; type_sig->rtn_type = fspec->rtn_type;
if (stripfirst) { if (stripfirst) {
assert(fsig->arg_types.size() >= 1); assert(fspec->arg_types.size() >= 1);
type_sig->arg_types.insert(type_sig->arg_types.end(), fsig->arg_types.begin() + 1, type_sig->arg_types.insert(type_sig->arg_types.end(), fspec->arg_types.begin() + 1,
fsig->arg_types.end()); fspec->arg_types.end());
} else { } else {
type_sig->arg_types.insert(type_sig->arg_types.end(), fsig->arg_types.begin(), fsig->arg_types.end()); type_sig->arg_types.insert(type_sig->arg_types.end(), fspec->arg_types.begin(), fspec->arg_types.end());
} }
sigs.push_back(type_sig); sigs.push_back(type_sig);
} }
...@@ -950,34 +950,12 @@ public: ...@@ -950,34 +950,12 @@ public:
return UNKNOWN->setattr(emitter, info, var, attr, v); return UNKNOWN->setattr(emitter, info, var, attr, v);
} }
virtual ConcreteCompilerVariable* nonzero(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var) {
if (cls == bool_cls) {
llvm::Value* unboxed = emitter.getBuilder()->CreateCall(g.funcs.unboxBool, var->getValue());
assert(unboxed->getType() == g.i1);
return new ConcreteCompilerVariable(BOOL, unboxed, true);
}
ConcreteCompilerVariable* converted = var->makeConverted(emitter, UNKNOWN);
ConcreteCompilerVariable* rtn = converted->nonzero(emitter, info);
converted->decvref(emitter);
return rtn;
}
virtual void print(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var) { virtual void print(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var) {
ConcreteCompilerVariable* converted = var->makeConverted(emitter, UNKNOWN); ConcreteCompilerVariable* converted = var->makeConverted(emitter, UNKNOWN);
converted->print(emitter, info); converted->print(emitter, info);
converted->decvref(emitter); converted->decvref(emitter);
} }
virtual CompilerVariable* getitem(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var,
CompilerVariable* slice) {
return UNKNOWN->getitem(emitter, info, var, slice);
}
virtual ConcreteCompilerVariable* len(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var) {
return UNKNOWN->len(emitter, info, var);
}
virtual CompilerVariable* call(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var, virtual CompilerVariable* call(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var,
ArgPassSpec argspec, const std::vector<CompilerVariable*>& args, ArgPassSpec argspec, const std::vector<CompilerVariable*>& args,
const std::vector<const std::string*>* keyword_names) { const std::vector<const std::string*>* keyword_names) {
...@@ -987,23 +965,30 @@ public: ...@@ -987,23 +965,30 @@ public:
return rtn; return rtn;
} }
virtual CompilerVariable* callattr(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var, ConcreteCompilerVariable* tryCallattrConstant(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var,
const std::string* attr, bool clsonly, ArgPassSpec argspec, const std::string* attr, bool clsonly, ArgPassSpec argspec,
const std::vector<CompilerVariable*>& args, const std::vector<CompilerVariable*>& args,
const std::vector<const std::string*>* keyword_names) { const std::vector<const std::string*>* keyword_names,
if (cls->is_constant && !cls->instancesHaveAttrs() && cls->hasGenericGetattr()) { bool raise_on_missing = true) {
if (!cls->is_constant || cls->instancesHaveAttrs() || !cls->hasGenericGetattr())
return NULL;
Box* rtattr = cls->getattr(*attr); Box* rtattr = cls->getattr(*attr);
if (rtattr == NULL) { if (rtattr == NULL) {
if (raise_on_missing) {
llvm::CallSite call = emitter.createCall2(info.exc_info, g.funcs.raiseAttributeErrorStr, llvm::CallSite call = emitter.createCall2(info.exc_info, g.funcs.raiseAttributeErrorStr,
getStringConstantPtr(*getNameOfClass(cls) + "\0"), getStringConstantPtr(*getNameOfClass(cls) + "\0"),
getStringConstantPtr(*attr + '\0')); getStringConstantPtr(*attr + '\0'));
call.setDoesNotReturn(); call.setDoesNotReturn();
return undefVariable(); return undefVariable();
} else {
return NULL;
}
} }
if (rtattr->cls == function_cls) { if (rtattr->cls != function_cls)
// Functions themselves can't remunge their passed arguments; return NULL;
// that should either happen here, or we skip things that aren't a simple match
RELEASE_ASSERT(!argspec.has_starargs, ""); RELEASE_ASSERT(!argspec.has_starargs, "");
RELEASE_ASSERT(!argspec.has_kwargs, ""); RELEASE_ASSERT(!argspec.has_kwargs, "");
RELEASE_ASSERT(argspec.num_keywords == 0, ""); RELEASE_ASSERT(argspec.num_keywords == 0, "");
...@@ -1011,25 +996,27 @@ public: ...@@ -1011,25 +996,27 @@ public:
CLFunction* cl = unboxRTFunction(rtattr); CLFunction* cl = unboxRTFunction(rtattr);
assert(cl); assert(cl);
if (cl->num_defaults || cl->takes_varargs || cl->takes_kwargs)
return NULL;
RELEASE_ASSERT(cl->num_args == cl->numReceivedArgs(), "");
RELEASE_ASSERT(cl->num_args == args.size() + 1, "");
CompiledFunction* cf = NULL; CompiledFunction* cf = NULL;
int nsig_args = 0;
bool found = false; bool found = false;
// TODO have to find the right version.. similar to resolveclfunc? // TODO have to find the right version.. similar to resolveclfunc?
for (int i = 0; i < cl->versions.size(); i++) { for (int i = 0; i < cl->versions.size(); i++) {
cf = cl->versions[i]; cf = cl->versions[i];
nsig_args = cf->sig->arg_types.size(); assert(cf->spec->arg_types.size() == cl->numReceivedArgs());
if (nsig_args != args.size() + 1) {
continue;
}
bool fits = true; bool fits = true;
for (int j = 1; j < nsig_args; j++) { for (int j = 1; j < cl->num_args; j++) {
// if (cf->sig->arg_types[j] != UNKNOWN) { // if (cf->sig->arg_types[j] != UNKNOWN) {
// if (cf->sig->arg_types[j]->isFitBy(args[j-1]->guaranteedClass())) { // if (cf->sig->arg_types[j]->isFitBy(args[j-1]->guaranteedClass())) {
if (!args[j - 1]->canConvertTo(cf->sig->arg_types[j])) { if (!args[j - 1]->canConvertTo(cf->spec->arg_types[j])) {
printf("Can't use version %d since arg %d (%s) doesn't fit into sig arg of %s\n", i, j, // printf("Can't use version %d since arg %d (%s) doesn't fit into spec arg of %s\n", i, j,
args[j - 1]->getType()->debugName().c_str(), // args[j - 1]->getType()->debugName().c_str(),
cf->sig->arg_types[j]->debugName().c_str()); // cf->spec->arg_types[j]->debugName().c_str());
fits = false; fits = false;
break; break;
} }
...@@ -1042,14 +1029,14 @@ public: ...@@ -1042,14 +1029,14 @@ public:
} }
assert(found); assert(found);
assert(nsig_args == args.size() + 1);
assert(!cf->is_interpreted); assert(!cf->is_interpreted);
assert(cf->code); assert(cf->code);
std::vector<llvm::Type*> arg_types; std::vector<llvm::Type*> arg_types;
for (int i = 0; i < nsig_args; i++) { RELEASE_ASSERT(cl->num_args == cl->numReceivedArgs(), "");
for (int i = 0; i < cl->num_args; i++) {
// TODO support passing unboxed values as arguments // TODO support passing unboxed values as arguments
assert(cf->sig->arg_types[i]->llvmType() == g.llvm_value_type_ptr); assert(cf->spec->arg_types[i]->llvmType() == g.llvm_value_type_ptr);
arg_types.push_back(g.llvm_value_type_ptr); arg_types.push_back(g.llvm_value_type_ptr);
if (i == 3) { if (i == 3) {
...@@ -1057,7 +1044,7 @@ public: ...@@ -1057,7 +1044,7 @@ public:
break; break;
} }
} }
llvm::FunctionType* ft = llvm::FunctionType::get(cf->sig->rtn_type->llvmType(), arg_types, false); llvm::FunctionType* ft = llvm::FunctionType::get(cf->spec->rtn_type->llvmType(), arg_types, false);
llvm::Value* linked_function = embedConstantPtr(cf->code, ft->getPointerTo()); llvm::Value* linked_function = embedConstantPtr(cf->code, ft->getPointerTo());
...@@ -1067,17 +1054,39 @@ public: ...@@ -1067,17 +1054,39 @@ public:
std::vector<llvm::Value*> other_args; std::vector<llvm::Value*> other_args;
ConcreteCompilerVariable* rtn = _call(emitter, info, linked_function, cf->code, other_args, argspec, ConcreteCompilerVariable* rtn = _call(emitter, info, linked_function, cf->code, other_args, argspec, new_args,
new_args, keyword_names, cf->sig->rtn_type); keyword_names, cf->spec->rtn_type);
assert(rtn->getType() == cf->sig->rtn_type); assert(rtn->getType() == cf->spec->rtn_type);
assert(cf->sig->rtn_type != BOXED_INT); // We should provide unboxed versions of these rather than boxing then unboxing:
ASSERT(cf->sig->rtn_type != BOXED_BOOL, "%p", cf->code); // TODO is it more efficient to unbox here, or should we leave it boxed?
assert(cf->sig->rtn_type != BOXED_FLOAT); if (cf->spec->rtn_type == BOXED_BOOL) {
llvm::Value* unboxed = emitter.getBuilder()->CreateCall(g.funcs.unboxBool, rtn->getValue());
return new ConcreteCompilerVariable(BOOL, unboxed, true);
}
if (cf->spec->rtn_type == BOXED_INT) {
llvm::Value* unboxed = emitter.getBuilder()->CreateCall(g.funcs.unboxInt, rtn->getValue());
return new ConcreteCompilerVariable(INT, unboxed, true);
}
if (cf->spec->rtn_type == BOXED_FLOAT) {
llvm::Value* unboxed = emitter.getBuilder()->CreateCall(g.funcs.unboxFloat, rtn->getValue());
return new ConcreteCompilerVariable(FLOAT, unboxed, true);
}
assert(cf->spec->rtn_type != BOXED_INT);
ASSERT(cf->spec->rtn_type != BOXED_BOOL, "%p", cf->code);
assert(cf->spec->rtn_type != BOXED_FLOAT);
return rtn; return rtn;
} }
}
virtual CompilerVariable* callattr(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var,
const std::string* attr, bool clsonly, ArgPassSpec argspec,
const std::vector<CompilerVariable*>& args,
const std::vector<const std::string*>* keyword_names) {
ConcreteCompilerVariable* called_constant
= tryCallattrConstant(emitter, info, var, attr, clsonly, argspec, args, keyword_names);
if (called_constant)
return called_constant;
ConcreteCompilerVariable* converted = var->makeConverted(emitter, UNKNOWN); ConcreteCompilerVariable* converted = var->makeConverted(emitter, UNKNOWN);
CompilerVariable* rtn = converted->callattr(emitter, info, attr, clsonly, argspec, args, keyword_names); CompilerVariable* rtn = converted->callattr(emitter, info, attr, clsonly, argspec, args, keyword_names);
...@@ -1085,6 +1094,43 @@ public: ...@@ -1085,6 +1094,43 @@ public:
return rtn; return rtn;
} }
virtual CompilerVariable* getitem(IREmitter& emitter, const OpInfo& info, VAR* var, CompilerVariable* slice) {
static const std::string attr("__getitem__");
ConcreteCompilerVariable* called_constant
= tryCallattrConstant(emitter, info, var, &attr, true, ArgPassSpec(1, 0, 0, 0), { slice }, NULL, false);
if (called_constant)
return called_constant;
return UNKNOWN->getitem(emitter, info, var, slice);
}
virtual ConcreteCompilerVariable* len(IREmitter& emitter, const OpInfo& info, VAR* var) {
static const std::string attr("__len__");
ConcreteCompilerVariable* called_constant
= tryCallattrConstant(emitter, info, var, &attr, true, ArgPassSpec(0, 0, 0, 0), {}, NULL);
if (called_constant)
return called_constant;
return UNKNOWN->len(emitter, info, var);
}
virtual ConcreteCompilerVariable* nonzero(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var) {
static const std::string attr("__nonzero__");
ConcreteCompilerVariable* called_constant
= tryCallattrConstant(emitter, info, var, &attr, true, ArgPassSpec(0, 0, 0, 0), {}, NULL);
if (called_constant)
return called_constant;
if (cls == bool_cls) {
assert(0 && "should have been caught by above case");
llvm::Value* unboxed = emitter.getBuilder()->CreateCall(g.funcs.unboxBool, var->getValue());
assert(unboxed->getType() == g.i1);
return new ConcreteCompilerVariable(BOOL, unboxed, true);
}
return UNKNOWN->nonzero(emitter, info, var);
}
static NormalObjectType* fromClass(BoxedClass* cls) { static NormalObjectType* fromClass(BoxedClass* cls) {
NormalObjectType*& rtn = made[cls]; NormalObjectType*& rtn = made[cls];
if (rtn == NULL) { if (rtn == NULL) {
...@@ -1466,7 +1512,7 @@ public: ...@@ -1466,7 +1512,7 @@ public:
} _UNDEF; } _UNDEF;
CompilerType* UNDEF = &_UNDEF; CompilerType* UNDEF = &_UNDEF;
CompilerVariable* undefVariable() { ConcreteCompilerVariable* undefVariable() {
return new ConcreteCompilerVariable(&_UNDEF, llvm::UndefValue::get(_UNDEF.llvmType()), true); return new ConcreteCompilerVariable(&_UNDEF, llvm::UndefValue::get(_UNDEF.llvmType()), true);
} }
......
...@@ -115,6 +115,9 @@ public: ...@@ -115,6 +115,9 @@ public:
abort(); abort();
} }
virtual CompilerVariable* getitem(IREmitter& emitter, const OpInfo& info, VAR* value, CompilerVariable* v) { virtual CompilerVariable* getitem(IREmitter& emitter, const OpInfo& info, VAR* value, CompilerVariable* v) {
// Can almost do this, except for error messages + types:
// static const std::string attr("__getitem__");
// return callattr(emitter, info, value, &attr, true, ArgPassSpec(1, 0, 0, 0), {v}, NULL);
printf("getitem not defined for %s\n", debugName().c_str()); printf("getitem not defined for %s\n", debugName().c_str());
abort(); abort();
} }
...@@ -314,7 +317,7 @@ ConcreteCompilerVariable* makeFloat(double); ...@@ -314,7 +317,7 @@ ConcreteCompilerVariable* makeFloat(double);
ConcreteCompilerVariable* makeBool(bool); ConcreteCompilerVariable* makeBool(bool);
CompilerVariable* makeStr(std::string*); CompilerVariable* makeStr(std::string*);
CompilerVariable* makeFunction(IREmitter& emitter, CLFunction*); CompilerVariable* makeFunction(IREmitter& emitter, CLFunction*);
CompilerVariable* undefVariable(); ConcreteCompilerVariable* undefVariable();
CompilerVariable* makeTuple(const std::vector<CompilerVariable*>& elts); CompilerVariable* makeTuple(const std::vector<CompilerVariable*>& elts);
ConcreteCompilerType* typeFromClass(BoxedClass*); ConcreteCompilerType* typeFromClass(BoxedClass*);
......
...@@ -563,7 +563,7 @@ static void emitBBs(IRGenState* irstate, const char* bb_type, GuardList& out_gua ...@@ -563,7 +563,7 @@ static void emitBBs(IRGenState* irstate, const char* bb_type, GuardList& out_gua
emitter->getBuilder()->SetInsertPoint(llvm_entry_blocks[source->cfg->getStartingBlock()]); emitter->getBuilder()->SetInsertPoint(llvm_entry_blocks[source->cfg->getStartingBlock()]);
} }
generator->unpackArguments(arg_names, cf->sig->arg_types); generator->unpackArguments(arg_names, cf->spec->arg_types);
} else if (entry_descriptor && block == entry_descriptor->backedge->target) { } else if (entry_descriptor && block == entry_descriptor->backedge->target) {
assert(block->predecessors.size() > 1); assert(block->predecessors.size() > 1);
assert(osr_entry_block); assert(osr_entry_block);
...@@ -882,7 +882,7 @@ static std::string getUniqueFunctionName(std::string nameprefix, EffortLevel::Ef ...@@ -882,7 +882,7 @@ static std::string getUniqueFunctionName(std::string nameprefix, EffortLevel::Ef
} }
CompiledFunction* doCompile(SourceInfo* source, const OSREntryDescriptor* entry_descriptor, CompiledFunction* doCompile(SourceInfo* source, const OSREntryDescriptor* entry_descriptor,
EffortLevel::EffortLevel effort, FunctionSignature* sig, EffortLevel::EffortLevel effort, FunctionSpecialization* spec,
const std::vector<AST_expr*>& arg_names, std::string nameprefix) { const std::vector<AST_expr*>& arg_names, std::string nameprefix) {
Timer _t("in doCompile"); Timer _t("in doCompile");
...@@ -899,7 +899,7 @@ CompiledFunction* doCompile(SourceInfo* source, const OSREntryDescriptor* entry_ ...@@ -899,7 +899,7 @@ CompiledFunction* doCompile(SourceInfo* source, const OSREntryDescriptor* entry_
// Initializing the llvm-level structures: // Initializing the llvm-level structures:
int nargs = arg_names.size(); int nargs = arg_names.size();
ASSERT(nargs == sig->arg_types.size(), "%d %ld", nargs, sig->arg_types.size()); ASSERT(nargs == spec->arg_types.size(), "%d %ld", nargs, spec->arg_types.size());
std::vector<llvm::Type*> llvm_arg_types; std::vector<llvm::Type*> llvm_arg_types;
if (entry_descriptor == NULL) { if (entry_descriptor == NULL) {
...@@ -908,7 +908,7 @@ CompiledFunction* doCompile(SourceInfo* source, const OSREntryDescriptor* entry_ ...@@ -908,7 +908,7 @@ CompiledFunction* doCompile(SourceInfo* source, const OSREntryDescriptor* entry_
llvm_arg_types.push_back(g.llvm_value_type_ptr->getPointerTo()); llvm_arg_types.push_back(g.llvm_value_type_ptr->getPointerTo());
break; break;
} }
llvm_arg_types.push_back(sig->arg_types[i]->llvmType()); llvm_arg_types.push_back(spec->arg_types[i]->llvmType());
} }
} else { } else {
int arg_num = -1; int arg_num = -1;
...@@ -924,20 +924,20 @@ CompiledFunction* doCompile(SourceInfo* source, const OSREntryDescriptor* entry_ ...@@ -924,20 +924,20 @@ CompiledFunction* doCompile(SourceInfo* source, const OSREntryDescriptor* entry_
} }
} }
llvm::FunctionType* ft = llvm::FunctionType::get(sig->rtn_type->llvmType(), llvm_arg_types, false /*vararg*/); llvm::FunctionType* ft = llvm::FunctionType::get(spec->rtn_type->llvmType(), llvm_arg_types, false /*vararg*/);
llvm::Function* f = llvm::Function::Create(ft, llvm::Function::ExternalLinkage, name, g.cur_module); llvm::Function* f = llvm::Function::Create(ft, llvm::Function::ExternalLinkage, name, g.cur_module);
// g.func_registry.registerFunction(f, g.cur_module); // g.func_registry.registerFunction(f, g.cur_module);
CompiledFunction* cf CompiledFunction* cf
= new CompiledFunction(f, sig, (effort == EffortLevel::INTERPRETED), NULL, NULL, effort, entry_descriptor); = new CompiledFunction(f, spec, (effort == EffortLevel::INTERPRETED), NULL, NULL, effort, entry_descriptor);
llvm::MDNode* dbg_funcinfo = setupDebugInfo(source, f, nameprefix); llvm::MDNode* dbg_funcinfo = setupDebugInfo(source, f, nameprefix);
TypeAnalysis::SpeculationLevel speculation_level = TypeAnalysis::NONE; TypeAnalysis::SpeculationLevel speculation_level = TypeAnalysis::NONE;
if (ENABLE_SPECULATION && effort >= EffortLevel::MODERATE) if (ENABLE_SPECULATION && effort >= EffortLevel::MODERATE)
speculation_level = TypeAnalysis::SOME; speculation_level = TypeAnalysis::SOME;
TypeAnalysis* types = doTypeAnalysis(source->cfg, arg_names, sig->arg_types, speculation_level, TypeAnalysis* types = doTypeAnalysis(source->cfg, arg_names, spec->arg_types, speculation_level,
source->scoping->getScopeInfoForNode(source->ast)); source->scoping->getScopeInfoForNode(source->ast));
GuardList guards; GuardList guards;
...@@ -973,7 +973,7 @@ CompiledFunction* doCompile(SourceInfo* source, const OSREntryDescriptor* entry_ ...@@ -973,7 +973,7 @@ CompiledFunction* doCompile(SourceInfo* source, const OSREntryDescriptor* entry_
assert(deopt_full_blocks.size() || deopt_partial_blocks.size()); assert(deopt_full_blocks.size() || deopt_partial_blocks.size());
TypeAnalysis* deopt_types = doTypeAnalysis(source->cfg, arg_names, sig->arg_types, TypeAnalysis::NONE, TypeAnalysis* deopt_types = doTypeAnalysis(source->cfg, arg_names, spec->arg_types, TypeAnalysis::NONE,
source->scoping->getScopeInfoForNode(source->ast)); source->scoping->getScopeInfoForNode(source->ast));
emitBBs(&irstate, "deopt", deopt_guards, guards, deopt_types, arg_names, NULL, deopt_full_blocks, emitBBs(&irstate, "deopt", deopt_guards, guards, deopt_types, arg_names, NULL, deopt_full_blocks,
deopt_partial_blocks); deopt_partial_blocks);
......
...@@ -77,7 +77,7 @@ public: ...@@ -77,7 +77,7 @@ public:
}; };
CompiledFunction* doCompile(SourceInfo* source, const OSREntryDescriptor* entry_descriptor, CompiledFunction* doCompile(SourceInfo* source, const OSREntryDescriptor* entry_descriptor,
EffortLevel::EffortLevel effort, FunctionSignature* sig, EffortLevel::EffortLevel effort, FunctionSpecialization* spec,
const std::vector<AST_expr*>& arg_names, std::string nameprefix); const std::vector<AST_expr*>& arg_names, std::string nameprefix);
class TypeRecorder; class TypeRecorder;
......
...@@ -68,7 +68,6 @@ AST_arguments* SourceInfo::getArgsAST() { ...@@ -68,7 +68,6 @@ AST_arguments* SourceInfo::getArgsAST() {
const std::vector<AST_expr*>& SourceInfo::getArgNames() { const std::vector<AST_expr*>& SourceInfo::getArgNames() {
static std::vector<AST_expr*> empty; static std::vector<AST_expr*> empty;
assert(this);
AST_arguments* args = getArgsAST(); AST_arguments* args = getArgsAST();
if (args == NULL) if (args == NULL)
...@@ -76,6 +75,12 @@ const std::vector<AST_expr*>& SourceInfo::getArgNames() { ...@@ -76,6 +75,12 @@ const std::vector<AST_expr*>& SourceInfo::getArgNames() {
return args->args; return args->args;
} }
const std::vector<AST_expr*>* CLFunction::getArgNames() {
if (!source)
return NULL;
return &source->getArgNames();
}
const std::vector<AST_stmt*>& SourceInfo::getBody() { const std::vector<AST_stmt*>& SourceInfo::getBody() {
assert(ast); assert(ast);
switch (ast->type) { switch (ast->type) {
...@@ -135,10 +140,10 @@ static void compileIR(CompiledFunction* cf, EffortLevel::EffortLevel effort) { ...@@ -135,10 +140,10 @@ static void compileIR(CompiledFunction* cf, EffortLevel::EffortLevel effort) {
// Compiles a new version of the function with the given signature and adds it to the list; // Compiles a new version of the function with the given signature and adds it to the list;
// should only be called after checking to see if the other versions would work. // should only be called after checking to see if the other versions would work.
CompiledFunction* compileFunction(CLFunction* f, FunctionSignature* sig, EffortLevel::EffortLevel effort, CompiledFunction* compileFunction(CLFunction* f, FunctionSpecialization* spec, EffortLevel::EffortLevel effort,
const OSREntryDescriptor* entry) { const OSREntryDescriptor* entry) {
Timer _t("for compileFunction()"); Timer _t("for compileFunction()");
assert(sig); assert(spec);
ASSERT(f->versions.size() < 20, "%ld", f->versions.size()); ASSERT(f->versions.size() < 20, "%ld", f->versions.size());
SourceInfo* source = f->source; SourceInfo* source = f->source;
...@@ -160,15 +165,15 @@ CompiledFunction* compileFunction(CLFunction* f, FunctionSignature* sig, EffortL ...@@ -160,15 +165,15 @@ CompiledFunction* compileFunction(CLFunction* f, FunctionSignature* sig, EffortL
llvm::raw_string_ostream ss(s); llvm::raw_string_ostream ss(s);
ss << "\033[34;1mJIT'ing " << name << " with signature ("; ss << "\033[34;1mJIT'ing " << name << " with signature (";
for (int i = 0; i < sig->arg_types.size(); i++) { for (int i = 0; i < spec->arg_types.size(); i++) {
if (i > 0) if (i > 0)
ss << ", "; ss << ", ";
ss << sig->arg_types[i]->debugName(); ss << spec->arg_types[i]->debugName();
// sig->arg_types[i]->llvmType()->print(ss); // spec->arg_types[i]->llvmType()->print(ss);
} }
ss << ") -> "; ss << ") -> ";
ss << sig->rtn_type->debugName(); ss << spec->rtn_type->debugName();
// sig->rtn_type->llvmType()->print(ss); // spec->rtn_type->llvmType()->print(ss);
ss << " at effort level " << effort; ss << " at effort level " << effort;
if (entry != NULL) { if (entry != NULL) {
ss << "\nDoing OSR-entry partial compile, starting with backedge to block " << entry->backedge->target->idx ss << "\nDoing OSR-entry partial compile, starting with backedge to block " << entry->backedge->target->idx
...@@ -187,7 +192,7 @@ CompiledFunction* compileFunction(CLFunction* f, FunctionSignature* sig, EffortL ...@@ -187,7 +192,7 @@ CompiledFunction* compileFunction(CLFunction* f, FunctionSignature* sig, EffortL
source->scoping->getScopeInfoForNode(source->ast)); source->scoping->getScopeInfoForNode(source->ast));
} }
CompiledFunction* cf = doCompile(source, entry, effort, sig, arg_names, name); CompiledFunction* cf = doCompile(source, entry, effort, spec, arg_names, name);
compileIR(cf, effort); compileIR(cf, effort);
f->addVersion(cf); f->addVersion(cf);
...@@ -244,12 +249,11 @@ void compileAndRunModule(AST_Module* m, BoxedModule* bm) { ...@@ -244,12 +249,11 @@ void compileAndRunModule(AST_Module* m, BoxedModule* bm) {
si->liveness = computeLivenessInfo(si->cfg); si->liveness = computeLivenessInfo(si->cfg);
si->phis = computeRequiredPhis(NULL, si->cfg, si->liveness, si->scoping->getScopeInfoForNode(si->ast)); si->phis = computeRequiredPhis(NULL, si->cfg, si->liveness, si->scoping->getScopeInfoForNode(si->ast));
CLFunction* cl_f = new CLFunction(si); CLFunction* cl_f = new CLFunction(0, 0, false, false, si);
EffortLevel::EffortLevel effort = initialEffort(); EffortLevel::EffortLevel effort = initialEffort();
CompiledFunction* cf CompiledFunction* cf = compileFunction(cl_f, new FunctionSpecialization(VOID), effort, NULL);
= compileFunction(cl_f, new FunctionSignature(VOID, &si->getArgNames(), 0, false, false), effort, NULL);
assert(cf->clfunc->versions.size()); assert(cf->clfunc->versions.size());
_t.end(); _t.end();
...@@ -268,7 +272,7 @@ static CompiledFunction* _doReopt(CompiledFunction* cf, EffortLevel::EffortLevel ...@@ -268,7 +272,7 @@ static CompiledFunction* _doReopt(CompiledFunction* cf, EffortLevel::EffortLevel
assert(cf); assert(cf);
assert(cf->entry_descriptor == NULL && "We can't reopt an osr-entry compile!"); assert(cf->entry_descriptor == NULL && "We can't reopt an osr-entry compile!");
assert(cf->sig); assert(cf->spec);
CLFunction* clfunc = cf->clfunc; CLFunction* clfunc = cf->clfunc;
assert(clfunc); assert(clfunc);
...@@ -281,7 +285,7 @@ static CompiledFunction* _doReopt(CompiledFunction* cf, EffortLevel::EffortLevel ...@@ -281,7 +285,7 @@ static CompiledFunction* _doReopt(CompiledFunction* cf, EffortLevel::EffortLevel
versions.erase(versions.begin() + i); versions.erase(versions.begin() + i);
CompiledFunction* new_cf CompiledFunction* new_cf
= compileFunction(clfunc, cf->sig, new_effort, = compileFunction(clfunc, cf->spec, new_effort,
NULL); // this pushes the new CompiledVersion to the back of the version list NULL); // this pushes the new CompiledVersion to the back of the version list
cf->dependent_callsites.invalidateAll(); cf->dependent_callsites.invalidateAll();
...@@ -289,6 +293,11 @@ static CompiledFunction* _doReopt(CompiledFunction* cf, EffortLevel::EffortLevel ...@@ -289,6 +293,11 @@ static CompiledFunction* _doReopt(CompiledFunction* cf, EffortLevel::EffortLevel
return new_cf; return new_cf;
} }
} }
printf("Couldn't find a version; %ld exist:\n", versions.size());
for (auto cf : versions) {
printf("%p\n", cf);
}
assert(0 && "Couldn't find a version to reopt! Probably reopt'd already?"); assert(0 && "Couldn't find a version to reopt! Probably reopt'd already?");
abort(); abort();
} }
...@@ -311,7 +320,7 @@ void* compilePartialFunc(OSRExit* exit) { ...@@ -311,7 +320,7 @@ void* compilePartialFunc(OSRExit* exit) {
// EffortLevel::EffortLevel new_effort = (EffortLevel::EffortLevel)(exit->parent_cf->effort + 1); // EffortLevel::EffortLevel new_effort = (EffortLevel::EffortLevel)(exit->parent_cf->effort + 1);
// new_effort = EffortLevel::MAXIMAL; // new_effort = EffortLevel::MAXIMAL;
CompiledFunction* compiled CompiledFunction* compiled
= compileFunction(exit->parent_cf->clfunc, exit->parent_cf->sig, new_effort, exit->entry); = compileFunction(exit->parent_cf->clfunc, exit->parent_cf->spec, new_effort, exit->entry);
assert(compiled = new_cf); assert(compiled = new_cf);
} }
...@@ -331,55 +340,56 @@ extern "C" char* reoptCompiledFunc(CompiledFunction* cf) { ...@@ -331,55 +340,56 @@ extern "C" char* reoptCompiledFunc(CompiledFunction* cf) {
return (char*)new_cf->code; return (char*)new_cf->code;
} }
CLFunction* createRTFunction() { CLFunction* createRTFunction(int num_args, int num_defaults, bool takes_varargs, bool takes_kwargs) {
return new CLFunction(NULL); return new CLFunction(num_args, num_defaults, takes_varargs, takes_kwargs, NULL);
} }
extern "C" CLFunction* boxRTFunction(void* f, ConcreteCompilerType* rtn_type, int nargs, bool takes_varargs, CLFunction* boxRTFunction(void* f, ConcreteCompilerType* rtn_type, int num_args) {
return boxRTFunction(f, rtn_type, num_args, 0, false, false);
}
CLFunction* boxRTFunction(void* f, ConcreteCompilerType* rtn_type, int num_args, int num_defaults, bool takes_varargs,
bool takes_kwargs) { bool takes_kwargs) {
CLFunction* cl_f = createRTFunction(); CLFunction* cl_f = createRTFunction(num_args, num_defaults, takes_varargs, takes_kwargs);
addRTFunction(cl_f, f, rtn_type, nargs, takes_varargs, takes_kwargs); addRTFunction(cl_f, f, rtn_type);
return cl_f; return cl_f;
} }
void addRTFunction(CLFunction* cl_f, void* f, ConcreteCompilerType* rtn_type, int nargs, bool takes_varargs, void addRTFunction(CLFunction* cl_f, void* f, ConcreteCompilerType* rtn_type) {
bool takes_kwargs) { std::vector<ConcreteCompilerType*> arg_types(cl_f->numReceivedArgs(), UNKNOWN);
std::vector<ConcreteCompilerType*> arg_types(nargs, NULL); return addRTFunction(cl_f, f, rtn_type, arg_types);
return addRTFunction(cl_f, f, rtn_type, arg_types, takes_varargs, takes_kwargs);
} }
static ConcreteCompilerType* processType(ConcreteCompilerType* type) { static ConcreteCompilerType* processType(ConcreteCompilerType* type) {
if (type == NULL) assert(type);
return UNKNOWN;
return type; return type;
} }
void addRTFunction(CLFunction* cl_f, void* f, ConcreteCompilerType* rtn_type, void addRTFunction(CLFunction* cl_f, void* f, ConcreteCompilerType* rtn_type,
const std::vector<ConcreteCompilerType*>& arg_types, bool takes_varargs, bool takes_kwargs) { const std::vector<ConcreteCompilerType*>& arg_types) {
FunctionSignature* sig = new FunctionSignature(processType(rtn_type), NULL, 0, takes_varargs, takes_kwargs); assert(arg_types.size() == cl_f->numReceivedArgs());
#ifndef NDEBUG
for (ConcreteCompilerType* t : arg_types)
assert(t);
#endif
for (int i = 0; i < arg_types.size(); i++) { FunctionSpecialization* spec = new FunctionSpecialization(processType(rtn_type), arg_types);
sig->arg_types.push_back(processType(arg_types[i]));
}
std::vector<llvm::Type*> llvm_arg_types; std::vector<llvm::Type*> llvm_arg_types;
int npassed_args = arg_types.size(); int npassed_args = arg_types.size();
if (takes_varargs) assert(npassed_args == cl_f->numReceivedArgs());
npassed_args++;
if (takes_kwargs)
npassed_args++;
for (int i = 0; i < npassed_args; i++) { for (int i = 0; i < npassed_args; i++) {
if (i == 3) { if (i == 3) {
llvm_arg_types.push_back(g.llvm_value_type_ptr->getPointerTo()); llvm_arg_types.push_back(g.i8_ptr->getPointerTo());
break; break;
} }
llvm_arg_types.push_back(g.llvm_value_type_ptr); llvm_arg_types.push_back(arg_types[i]->llvmType());
} }
llvm::FunctionType* ft = llvm::FunctionType::get(g.llvm_value_type_ptr, llvm_arg_types, false); llvm::FunctionType* ft = llvm::FunctionType::get(g.llvm_value_type_ptr, llvm_arg_types, false);
cl_f->addVersion( cl_f->addVersion(new CompiledFunction(NULL, spec, false, f, embedConstantPtr(f, ft->getPointerTo()),
new CompiledFunction(NULL, sig, false, f, embedConstantPtr(f, ft->getPointerTo()), EffortLevel::MAXIMAL, NULL)); EffortLevel::MAXIMAL, NULL));
} }
} }
...@@ -659,6 +659,15 @@ private: ...@@ -659,6 +659,15 @@ private:
std::vector<const std::string*>* keyword_names; std::vector<const std::string*>* keyword_names;
if (node->keywords.size()) { if (node->keywords.size()) {
keyword_names = getKeywordNameStorage(node); keyword_names = getKeywordNameStorage(node);
// Only add the keywords to the array the first time, since
// the later times we will hit the cache which will have the
// keyword names already populated:
if (!keyword_names->size()) {
for (auto kw : node->keywords) {
keyword_names->push_back(&kw->arg);
}
}
} else { } else {
keyword_names = NULL; keyword_names = NULL;
} }
...@@ -671,7 +680,6 @@ private: ...@@ -671,7 +680,6 @@ private:
for (int i = 0; i < node->keywords.size(); i++) { for (int i = 0; i < node->keywords.size(); i++) {
CompilerVariable* a = evalExpr(node->keywords[i]->value, exc_info); CompilerVariable* a = evalExpr(node->keywords[i]->value, exc_info);
args.push_back(a); args.push_back(a);
keyword_names->push_back(&node->keywords[i]->arg);
} }
if (node->starargs) if (node->starargs)
...@@ -1246,6 +1254,9 @@ private: ...@@ -1246,6 +1254,9 @@ private:
ConcreteCompilerVariable* converted_val = val->makeConverted(emitter, val->getBoxType()); ConcreteCompilerVariable* converted_val = val->makeConverted(emitter, val->getBoxType());
// TODO add a CompilerVariable::setattr, which can (similar to getitem)
// statically-resolve the function if possible, and only fall back to
// patchpoints if it couldn't.
bool do_patchpoint = ENABLE_ICSETITEMS && (irstate->getEffortLevel() != EffortLevel::INTERPRETED); bool do_patchpoint = ENABLE_ICSETITEMS && (irstate->getEffortLevel() != EffortLevel::INTERPRETED);
if (do_patchpoint) { if (do_patchpoint) {
PatchpointSetupInfo* pp = patchpoints::createSetitemPatchpoint(emitter.currentFunction(), PatchpointSetupInfo* pp = patchpoints::createSetitemPatchpoint(emitter.currentFunction(),
...@@ -1431,7 +1442,8 @@ private: ...@@ -1431,7 +1442,8 @@ private:
if (cl == NULL) { if (cl == NULL) {
SourceInfo* si = new SourceInfo(irstate->getSourceInfo()->parent_module, irstate->getSourceInfo()->scoping); SourceInfo* si = new SourceInfo(irstate->getSourceInfo()->parent_module, irstate->getSourceInfo()->scoping);
si->ast = node; si->ast = node;
cl = new CLFunction(si); cl = new CLFunction(node->args->args.size(), node->args->defaults.size(), node->args->vararg.size(),
node->args->kwarg.size(), si);
} }
return cl; return cl;
} }
......
...@@ -72,8 +72,8 @@ public: ...@@ -72,8 +72,8 @@ public:
llvm::Value* getScratchSpace(int min_bytes); llvm::Value* getScratchSpace(int min_bytes);
ConcreteCompilerType* getReturnType() { ConcreteCompilerType* getReturnType() {
assert(cf->sig); assert(cf->spec);
return cf->sig->rtn_type; return cf->spec->rtn_type;
} }
SourceInfo* getSourceInfo() { return source_info; } SourceInfo* getSourceInfo() { return source_info; }
......
...@@ -152,32 +152,17 @@ public: ...@@ -152,32 +152,17 @@ public:
// Codegen types: // Codegen types:
struct FunctionSignature { struct FunctionSpecialization {
ConcreteCompilerType* rtn_type; ConcreteCompilerType* rtn_type;
const std::vector<AST_expr*>* arg_names;
std::vector<ConcreteCompilerType*> arg_types; std::vector<ConcreteCompilerType*> arg_types;
int ndefaults;
bool takes_varargs, takes_kwargs;
FunctionSignature(ConcreteCompilerType* rtn_type, const std::vector<AST_expr*>* arg_names, int ndefaults, FunctionSpecialization(ConcreteCompilerType* rtn_type) : rtn_type(rtn_type) {}
bool takes_varargs, bool takes_kwargs)
: rtn_type(rtn_type), arg_names(arg_names), ndefaults(ndefaults), takes_varargs(takes_varargs),
takes_kwargs(takes_kwargs) {}
FunctionSignature(ConcreteCompilerType* rtn_type, const std::vector<AST_expr*>* arg_names,
ConcreteCompilerType* arg1, ConcreteCompilerType* arg2, int ndefaults, bool takes_varargs,
bool takes_kwargs)
: rtn_type(rtn_type), arg_names(arg_names), ndefaults(ndefaults), takes_varargs(takes_varargs),
takes_kwargs(takes_kwargs) {
arg_types.push_back(arg1);
arg_types.push_back(arg2);
}
FunctionSignature(ConcreteCompilerType* rtn_type, const std::vector<AST_expr*>* arg_names, FunctionSpecialization(ConcreteCompilerType* rtn_type, ConcreteCompilerType* arg1, ConcreteCompilerType* arg2)
std::vector<ConcreteCompilerType*>& arg_types, int ndefaults, bool takes_varargs, : rtn_type(rtn_type), arg_types({ arg1, arg2 }) {}
bool takes_kwargs)
: rtn_type(rtn_type), arg_names(arg_names), arg_types(arg_types), ndefaults(ndefaults), FunctionSpecialization(ConcreteCompilerType* rtn_type, const std::vector<ConcreteCompilerType*>& arg_types)
takes_varargs(takes_varargs), takes_kwargs(takes_kwargs) {} : rtn_type(rtn_type), arg_types(arg_types) {}
}; };
struct CompiledFunction { struct CompiledFunction {
...@@ -185,7 +170,7 @@ private: ...@@ -185,7 +170,7 @@ private:
public: public:
CLFunction* clfunc; CLFunction* clfunc;
llvm::Function* func; // the llvm IR object llvm::Function* func; // the llvm IR object
FunctionSignature* sig; FunctionSpecialization* spec;
const OSREntryDescriptor* entry_descriptor; const OSREntryDescriptor* entry_descriptor;
bool is_interpreted; bool is_interpreted;
...@@ -200,10 +185,10 @@ public: ...@@ -200,10 +185,10 @@ public:
int64_t times_called; int64_t times_called;
ICInvalidator dependent_callsites; ICInvalidator dependent_callsites;
CompiledFunction(llvm::Function* func, FunctionSignature* sig, bool is_interpreted, void* code, CompiledFunction(llvm::Function* func, FunctionSpecialization* spec, bool is_interpreted, void* code,
llvm::Value* llvm_code, EffortLevel::EffortLevel effort, llvm::Value* llvm_code, EffortLevel::EffortLevel effort,
const OSREntryDescriptor* entry_descriptor) const OSREntryDescriptor* entry_descriptor)
: clfunc(NULL), func(func), sig(sig), entry_descriptor(entry_descriptor), is_interpreted(is_interpreted), : clfunc(NULL), func(func), spec(spec), entry_descriptor(entry_descriptor), is_interpreted(is_interpreted),
code(code), llvm_code(llvm_code), effort(effort), times_called(0) {} code(code), llvm_code(llvm_code), effort(effort), times_called(0) {}
}; };
...@@ -229,6 +214,10 @@ public: ...@@ -229,6 +214,10 @@ public:
typedef std::vector<CompiledFunction*> FunctionList; typedef std::vector<CompiledFunction*> FunctionList;
class CallRewriteArgs; class CallRewriteArgs;
struct CLFunction { struct CLFunction {
int num_args;
int num_defaults;
bool takes_varargs, takes_kwargs;
SourceInfo* source; SourceInfo* source;
FunctionList FunctionList
versions; // any compiled versions along with their type parameters; in order from most preferred to least versions; // any compiled versions along with their type parameters; in order from most preferred to least
...@@ -242,12 +231,21 @@ struct CLFunction { ...@@ -242,12 +231,21 @@ struct CLFunction {
const std::vector<const std::string*>*); const std::vector<const std::string*>*);
InternalCallable internal_callable = NULL; InternalCallable internal_callable = NULL;
CLFunction(SourceInfo* source) : source(source) {} CLFunction(int num_args, int num_defaults, bool takes_varargs, bool takes_kwargs, SourceInfo* source)
: num_args(num_args), num_defaults(num_defaults), takes_varargs(takes_varargs), takes_kwargs(takes_kwargs),
source(source) {
assert(num_args >= num_defaults);
}
int numReceivedArgs() { return num_args + (takes_varargs ? 1 : 0) + (takes_kwargs ? 1 : 0); }
const std::vector<AST_expr*>* getArgNames();
void addVersion(CompiledFunction* compiled) { void addVersion(CompiledFunction* compiled) {
assert(compiled); assert(compiled);
assert((source == NULL) == (compiled->func == NULL)); assert((source == NULL) == (compiled->func == NULL));
assert(compiled->sig); assert(compiled->spec);
assert(compiled->spec->arg_types.size() == num_args + (takes_varargs ? 1 : 0) + (takes_kwargs ? 1 : 0));
assert(compiled->clfunc == NULL); assert(compiled->clfunc == NULL);
assert(compiled->is_interpreted == (compiled->code == NULL)); assert(compiled->is_interpreted == (compiled->code == NULL));
assert(compiled->is_interpreted == (compiled->llvm_code == NULL)); assert(compiled->is_interpreted == (compiled->llvm_code == NULL));
...@@ -259,19 +257,18 @@ struct CLFunction { ...@@ -259,19 +257,18 @@ struct CLFunction {
} }
}; };
extern "C" CLFunction* createRTFunction(); CLFunction* createRTFunction(int num_args, int num_defaults, bool takes_varargs, bool takes_kwargs);
extern "C" CLFunction* boxRTFunction(void* f, ConcreteCompilerType* rtn_type, int nargs, bool takes_varargs = false, CLFunction* boxRTFunction(void* f, ConcreteCompilerType* rtn_type, int nargs, int num_defaults, bool takes_varargs,
bool takes_kwargs = false); bool takes_kwargs);
void addRTFunction(CLFunction* cf, void* f, ConcreteCompilerType* rtn_type, int nargs, bool takes_varargs = false, CLFunction* boxRTFunction(void* f, ConcreteCompilerType* rtn_type, int nargs);
bool takes_kwargs = false); void addRTFunction(CLFunction* cf, void* f, ConcreteCompilerType* rtn_type);
void addRTFunction(CLFunction* cf, void* f, ConcreteCompilerType* rtn_type, void addRTFunction(CLFunction* cf, void* f, ConcreteCompilerType* rtn_type,
const std::vector<ConcreteCompilerType*>& arg_types, bool takes_varargs = false, const std::vector<ConcreteCompilerType*>& arg_types);
bool takes_kwargs = false);
CLFunction* unboxRTFunction(Box*); CLFunction* unboxRTFunction(Box*);
// Compiles a new version of the function with the given signature and adds it to the list; // Compiles a new version of the function with the given signature and adds it to the list;
// should only be called after checking to see if the other versions would work. // should only be called after checking to see if the other versions would work.
CompiledFunction* compileFunction(CLFunction* f, FunctionSignature* sig, EffortLevel::EffortLevel effort, CompiledFunction* compileFunction(CLFunction* f, FunctionSpecialization* spec, EffortLevel::EffortLevel effort,
const OSREntryDescriptor* entry); const OSREntryDescriptor* entry);
EffortLevel::EffortLevel initialEffort(); EffortLevel::EffortLevel initialEffort();
...@@ -280,6 +277,7 @@ typedef int64_t i64; ...@@ -280,6 +277,7 @@ typedef int64_t i64;
extern "C" void* rt_alloc(size_t); extern "C" void* rt_alloc(size_t);
extern "C" void rt_free(void*); extern "C" void rt_free(void*);
extern "C" void* rt_realloc(void* ptr, size_t new_size);
extern "C" const std::string* getNameOfClass(BoxedClass* cls); extern "C" const std::string* getNameOfClass(BoxedClass* cls);
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#include "codegen/compvars.h"
#include "core/common.h" #include "core/common.h"
#include "core/types.h" #include "core/types.h"
#include "gc/collector.h" #include "gc/collector.h"
...@@ -45,12 +46,7 @@ extern "C" Box* boolRepr(BoxedBool* v) { ...@@ -45,12 +46,7 @@ extern "C" Box* boolRepr(BoxedBool* v) {
return boxStrConstant("False"); return boxStrConstant("False");
} }
extern "C" Box* boolNew1(Box* cls) { extern "C" Box* boolNew(Box* cls, Box* val) {
assert(cls == bool_cls);
return False;
}
extern "C" Box* boolNew2(Box* cls, Box* val) {
assert(cls == bool_cls); assert(cls == bool_cls);
bool b = nonzero(val); bool b = nonzero(val);
...@@ -60,16 +56,15 @@ extern "C" Box* boolNew2(Box* cls, Box* val) { ...@@ -60,16 +56,15 @@ extern "C" Box* boolNew2(Box* cls, Box* val) {
void setupBool() { void setupBool() {
bool_cls->giveAttr("__name__", boxStrConstant("bool")); bool_cls->giveAttr("__name__", boxStrConstant("bool"));
bool_cls->giveAttr("__invert__", new BoxedFunction(boxRTFunction((void*)boolInvert, NULL, 1, false))); bool_cls->giveAttr("__invert__", new BoxedFunction(boxRTFunction((void*)boolInvert, BOXED_INT, 1)));
bool_cls->giveAttr("__pos__", new BoxedFunction(boxRTFunction((void*)boolPos, NULL, 1, false))); bool_cls->giveAttr("__pos__", new BoxedFunction(boxRTFunction((void*)boolPos, BOXED_INT, 1)));
bool_cls->giveAttr("__neg__", new BoxedFunction(boxRTFunction((void*)boolNeg, NULL, 1, false))); bool_cls->giveAttr("__neg__", new BoxedFunction(boxRTFunction((void*)boolNeg, BOXED_INT, 1)));
bool_cls->giveAttr("__nonzero__", new BoxedFunction(boxRTFunction((void*)boolNonzero, NULL, 1, false))); bool_cls->giveAttr("__nonzero__", new BoxedFunction(boxRTFunction((void*)boolNonzero, BOXED_BOOL, 1)));
bool_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)boolRepr, NULL, 1, false))); bool_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)boolRepr, STR, 1)));
bool_cls->giveAttr("__str__", bool_cls->getattr("__repr__")); bool_cls->giveAttr("__str__", bool_cls->getattr("__repr__"));
CLFunction* __new__ = boxRTFunction((void*)boolNew1, NULL, 1, false); bool_cls->giveAttr("__new__",
addRTFunction(__new__, (void*)boolNew2, NULL, 2, false); new BoxedFunction(boxRTFunction((void*)boolNew, UNKNOWN, 2, 1, false, false), { None }));
bool_cls->giveAttr("__new__", new BoxedFunction(__new__));
bool_cls->freeze(); bool_cls->freeze();
......
...@@ -34,7 +34,13 @@ extern "C" Box* trap() { ...@@ -34,7 +34,13 @@ extern "C" Box* trap() {
return None; return None;
} }
extern "C" Box* dir1(Box* obj) { extern "C" Box* dir(Box* obj) {
if (obj == NULL) {
// TODO: This should actually return the elements in the current local
// scope not the content of the builtins_module
obj = builtins_module;
}
// TODO: Recursive class traversal for lookup of types and eliminating // TODO: Recursive class traversal for lookup of types and eliminating
// duplicates afterwards // duplicates afterwards
BoxedList* result = nullptr; BoxedList* result = nullptr;
...@@ -70,12 +76,6 @@ extern "C" Box* dir1(Box* obj) { ...@@ -70,12 +76,6 @@ extern "C" Box* dir1(Box* obj) {
return result; return result;
} }
extern "C" Box* dir0() {
// TODO: This should actually return the elements in the current local
// scope not the content of the builtins_module
return dir1(builtins_module);
}
extern "C" Box* abs_(Box* x) { extern "C" Box* abs_(Box* x) {
if (x->cls == int_cls) { if (x->cls == int_cls) {
i64 n = static_cast<BoxedInt*>(x)->n; i64 n = static_cast<BoxedInt*>(x)->n;
...@@ -106,8 +106,19 @@ extern "C" Box* any(Box* container) { ...@@ -106,8 +106,19 @@ extern "C" Box* any(Box* container) {
return boxBool(false); return boxBool(false);
} }
extern "C" Box* min1(Box* container) { extern "C" Box* min(Box* arg0, BoxedTuple* args) {
Box* minElement = nullptr; assert(args->cls == tuple_cls);
Box* minElement;
Box* container;
if (args->elts.size() == 0) {
minElement = nullptr;
container = arg0;
} else {
minElement = arg0;
container = args;
}
for (Box* e : container->pyElements()) { for (Box* e : container->pyElements()) {
if (!minElement) { if (!minElement) {
minElement = e; minElement = e;
...@@ -125,17 +136,19 @@ extern "C" Box* min1(Box* container) { ...@@ -125,17 +136,19 @@ extern "C" Box* min1(Box* container) {
return minElement; return minElement;
} }
extern "C" Box* min2(Box* o0, Box* o1) { extern "C" Box* max(Box* arg0, BoxedTuple* args) {
Box* comp_result = compareInternal(o0, o1, AST_TYPE::Gt, NULL); assert(args->cls == tuple_cls);
bool b = nonzero(comp_result);
if (b) { Box* maxElement;
return o1; Box* container;
if (args->elts.size() == 0) {
maxElement = nullptr;
container = arg0;
} else {
maxElement = arg0;
container = args;
} }
return o0;
}
extern "C" Box* max1(Box* container) {
Box* maxElement = nullptr;
for (Box* e : container->pyElements()) { for (Box* e : container->pyElements()) {
if (!maxElement) { if (!maxElement) {
maxElement = e; maxElement = e;
...@@ -153,16 +166,7 @@ extern "C" Box* max1(Box* container) { ...@@ -153,16 +166,7 @@ extern "C" Box* max1(Box* container) {
return maxElement; return maxElement;
} }
extern "C" Box* max2(Box* o0, Box* o1) { extern "C" Box* sum(Box* container, Box* initial) {
Box* comp_result = compareInternal(o0, o1, AST_TYPE::Lt, NULL);
bool b = nonzero(comp_result);
if (b) {
return o1;
}
return o0;
}
extern "C" Box* sum2(Box* container, Box* initial) {
if (initial->cls == str_cls) if (initial->cls == str_cls)
raiseExcHelper(TypeError, "sum() can't sum strings [use ''.join(seq) instead]"); raiseExcHelper(TypeError, "sum() can't sum strings [use ''.join(seq) instead]");
...@@ -173,11 +177,9 @@ extern "C" Box* sum2(Box* container, Box* initial) { ...@@ -173,11 +177,9 @@ extern "C" Box* sum2(Box* container, Box* initial) {
return cur; return cur;
} }
extern "C" Box* sum1(Box* container) { Box* open(Box* arg1, Box* arg2) {
return sum2(container, boxInt(0)); assert(arg2);
}
extern "C" Box* open2(Box* arg1, Box* arg2) {
if (arg1->cls != str_cls) { if (arg1->cls != str_cls) {
fprintf(stderr, "TypeError: coercing to Unicode: need string of buffer, %s found\n", fprintf(stderr, "TypeError: coercing to Unicode: need string of buffer, %s found\n",
getTypeName(arg1)->c_str()); getTypeName(arg1)->c_str());
...@@ -198,12 +200,6 @@ extern "C" Box* open2(Box* arg1, Box* arg2) { ...@@ -198,12 +200,6 @@ extern "C" Box* open2(Box* arg1, Box* arg2) {
return new BoxedFile(f); return new BoxedFile(f);
} }
extern "C" Box* open1(Box* arg) {
Box* mode = boxStrConstant("r");
Box* rtn = open2(arg, mode);
return rtn;
}
extern "C" Box* chr(Box* arg) { extern "C" Box* chr(Box* arg) {
if (arg->cls != int_cls) { if (arg->cls != int_cls) {
fprintf(stderr, "TypeError: coercing to Unicode: need string of buffer, %s found\n", getTypeName(arg)->c_str()); fprintf(stderr, "TypeError: coercing to Unicode: need string of buffer, %s found\n", getTypeName(arg)->c_str());
...@@ -227,52 +223,41 @@ extern "C" Box* ord(Box* arg) { ...@@ -227,52 +223,41 @@ extern "C" Box* ord(Box* arg) {
return boxInt(s[0]); return boxInt(s[0]);
} }
Box* range1(Box* end) { Box* range(Box* start, Box* stop, Box* step) {
RELEASE_ASSERT(end->cls == int_cls, "%s", getTypeName(end)->c_str()); i64 istart, istop, istep;
if (stop == NULL) {
BoxedList* rtn = new BoxedList();
i64 iend = static_cast<BoxedInt*>(end)->n;
rtn->ensure(iend);
for (i64 i = 0; i < iend; i++) {
Box* bi = boxInt(i);
listAppendInternal(rtn, bi);
}
return rtn;
}
Box* range2(Box* start, Box* end) {
RELEASE_ASSERT(start->cls == int_cls, "%s", getTypeName(start)->c_str()); RELEASE_ASSERT(start->cls == int_cls, "%s", getTypeName(start)->c_str());
RELEASE_ASSERT(end->cls == int_cls, "%s", getTypeName(end)->c_str());
BoxedList* rtn = new BoxedList(); istart = 0;
i64 istart = static_cast<BoxedInt*>(start)->n; istop = static_cast<BoxedInt*>(start)->n;
i64 iend = static_cast<BoxedInt*>(end)->n; istep = 1;
if ((iend - istart) > 0) } else if (step == NULL) {
rtn->ensure(iend - istart); RELEASE_ASSERT(start->cls == int_cls, "%s", getTypeName(start)->c_str());
for (i64 i = istart; i < iend; i++) { RELEASE_ASSERT(stop->cls == int_cls, "%s", getTypeName(stop)->c_str());
listAppendInternal(rtn, boxInt(i));
}
return rtn;
}
Box* range3(Box* start, Box* end, Box* step) { istart = static_cast<BoxedInt*>(start)->n;
istop = static_cast<BoxedInt*>(stop)->n;
istep = 1;
} else {
RELEASE_ASSERT(start->cls == int_cls, "%s", getTypeName(start)->c_str()); RELEASE_ASSERT(start->cls == int_cls, "%s", getTypeName(start)->c_str());
RELEASE_ASSERT(end->cls == int_cls, "%s", getTypeName(end)->c_str()); RELEASE_ASSERT(stop->cls == int_cls, "%s", getTypeName(stop)->c_str());
RELEASE_ASSERT(step->cls == int_cls, "%s", getTypeName(step)->c_str()); RELEASE_ASSERT(step->cls == int_cls, "%s", getTypeName(step)->c_str());
BoxedList* rtn = new BoxedList(); istart = static_cast<BoxedInt*>(start)->n;
i64 istart = static_cast<BoxedInt*>(start)->n; istop = static_cast<BoxedInt*>(stop)->n;
i64 iend = static_cast<BoxedInt*>(end)->n; istep = static_cast<BoxedInt*>(step)->n;
i64 istep = static_cast<BoxedInt*>(step)->n;
RELEASE_ASSERT(istep != 0, "step can't be 0"); RELEASE_ASSERT(istep != 0, "step can't be 0");
}
BoxedList* rtn = new BoxedList();
rtn->ensure(std::max(0l, 1 + (istop - istart) / istep));
if (istep > 0) { if (istep > 0) {
for (i64 i = istart; i < iend; i += istep) { for (i64 i = istart; i < istop; i += istep) {
Box* bi = boxInt(i); Box* bi = boxInt(i);
listAppendInternal(rtn, bi); listAppendInternal(rtn, bi);
} }
} else { } else {
for (i64 i = istart; i > iend; i += istep) { for (i64 i = istart; i > istop; i += istep) {
Box* bi = boxInt(i); Box* bi = boxInt(i);
listAppendInternal(rtn, bi); listAppendInternal(rtn, bi);
} }
...@@ -303,7 +288,7 @@ Box* sortedList(Box* obj) { ...@@ -303,7 +288,7 @@ Box* sortedList(Box* obj) {
BoxedList* rtn = new BoxedList(); BoxedList* rtn = new BoxedList();
int size = lobj->size; int size = lobj->size;
rtn->elts = new (size) BoxedList::ElementArray(); rtn->elts = new (size) GCdArray();
rtn->size = size; rtn->size = size;
rtn->capacity = size; rtn->capacity = size;
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
...@@ -322,22 +307,7 @@ Box* isinstance_func(Box* obj, Box* cls) { ...@@ -322,22 +307,7 @@ Box* isinstance_func(Box* obj, Box* cls) {
return boxBool(isinstance(obj, cls, 0)); return boxBool(isinstance(obj, cls, 0));
} }
Box* getattr2(Box* obj, Box* _str) { Box* getattrFunc(Box* obj, Box* _str, Box* default_value) {
if (_str->cls != str_cls) {
raiseExcHelper(TypeError, "getattr(): attribute name must be string");
}
BoxedString* str = static_cast<BoxedString*>(_str);
Box* rtn = getattr_internal(obj, str->s, true, true, NULL, NULL);
if (!rtn) {
raiseExcHelper(AttributeError, "'%s' object has no attribute '%s'", getTypeName(obj)->c_str(), str->s.c_str());
}
return rtn;
}
Box* getattr3(Box* obj, Box* _str, Box* default_value) {
if (_str->cls != str_cls) { if (_str->cls != str_cls) {
raiseExcHelper(TypeError, "getattr(): attribute name must be string"); raiseExcHelper(TypeError, "getattr(): attribute name must be string");
} }
...@@ -346,7 +316,11 @@ Box* getattr3(Box* obj, Box* _str, Box* default_value) { ...@@ -346,7 +316,11 @@ Box* getattr3(Box* obj, Box* _str, Box* default_value) {
Box* rtn = getattr_internal(obj, str->s, true, true, NULL, NULL); Box* rtn = getattr_internal(obj, str->s, true, true, NULL, NULL);
if (!rtn) { if (!rtn) {
if (default_value)
return default_value; return default_value;
else
raiseExcHelper(AttributeError, "'%s' object has no attribute '%s'", getTypeName(obj)->c_str(),
str->s.c_str());
} }
return rtn; return rtn;
...@@ -440,9 +414,9 @@ static BoxedClass* makeBuiltinException(BoxedClass* base, const char* name) { ...@@ -440,9 +414,9 @@ static BoxedClass* makeBuiltinException(BoxedClass* base, const char* name) {
cls->giveAttr("__name__", boxStrConstant(name)); cls->giveAttr("__name__", boxStrConstant(name));
// TODO these should be on the base Exception class: // TODO these should be on the base Exception class:
cls->giveAttr("__new__", new BoxedFunction(boxRTFunction((void*)exceptionNew1, NULL, 1, false))); cls->giveAttr("__new__", new BoxedFunction(boxRTFunction((void*)exceptionNew1, UNKNOWN, 1)));
cls->giveAttr("__str__", new BoxedFunction(boxRTFunction((void*)exceptionStr, NULL, 1, false))); cls->giveAttr("__str__", new BoxedFunction(boxRTFunction((void*)exceptionStr, STR, 1)));
cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)exceptionRepr, NULL, 1, false))); cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)exceptionRepr, STR, 1)));
cls->freeze(); cls->freeze();
builtins_module->giveAttr(name, cls); builtins_module->giveAttr(name, cls);
...@@ -456,8 +430,7 @@ void setupBuiltins() { ...@@ -456,8 +430,7 @@ void setupBuiltins() {
notimplemented_cls = new BoxedClass(object_cls, 0, sizeof(Box), false); notimplemented_cls = new BoxedClass(object_cls, 0, sizeof(Box), false);
notimplemented_cls->giveAttr("__name__", boxStrConstant("NotImplementedType")); notimplemented_cls->giveAttr("__name__", boxStrConstant("NotImplementedType"));
notimplemented_cls->giveAttr("__repr__", notimplemented_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)notimplementedRepr, STR, 1)));
new BoxedFunction(boxRTFunction((void*)notimplementedRepr, NULL, 1, false)));
notimplemented_cls->freeze(); notimplemented_cls->freeze();
NotImplemented = new Box(&notimplemented_flavor, notimplemented_cls); NotImplemented = new Box(&notimplemented_flavor, notimplemented_cls);
gc::registerStaticRootObj(NotImplemented); gc::registerStaticRootObj(NotImplemented);
...@@ -465,8 +438,8 @@ void setupBuiltins() { ...@@ -465,8 +438,8 @@ void setupBuiltins() {
builtins_module->giveAttr("NotImplemented", NotImplemented); builtins_module->giveAttr("NotImplemented", NotImplemented);
builtins_module->giveAttr("NotImplementedType", notimplemented_cls); builtins_module->giveAttr("NotImplementedType", notimplemented_cls);
builtins_module->giveAttr("all", new BoxedFunction(boxRTFunction((void*)all, BOXED_BOOL, 1, false))); builtins_module->giveAttr("all", new BoxedFunction(boxRTFunction((void*)all, BOXED_BOOL, 1)));
builtins_module->giveAttr("any", new BoxedFunction(boxRTFunction((void*)any, BOXED_BOOL, 1, false))); builtins_module->giveAttr("any", new BoxedFunction(boxRTFunction((void*)any, BOXED_BOOL, 1)));
Exception = makeBuiltinException(object_cls, "Exception"); Exception = makeBuiltinException(object_cls, "Exception");
AssertionError = makeBuiltinException(Exception, "AssertionError"); AssertionError = makeBuiltinException(Exception, "AssertionError");
...@@ -484,74 +457,62 @@ void setupBuiltins() { ...@@ -484,74 +457,62 @@ void setupBuiltins() {
ImportError = makeBuiltinException(Exception, "ImportError"); ImportError = makeBuiltinException(Exception, "ImportError");
StopIteration = makeBuiltinException(Exception, "StopIteration"); StopIteration = makeBuiltinException(Exception, "StopIteration");
repr_obj = new BoxedFunction(boxRTFunction((void*)repr, NULL, 1, false)); repr_obj = new BoxedFunction(boxRTFunction((void*)repr, UNKNOWN, 1));
builtins_module->giveAttr("repr", repr_obj); builtins_module->giveAttr("repr", repr_obj);
len_obj = new BoxedFunction(boxRTFunction((void*)len, NULL, 1, false)); len_obj = new BoxedFunction(boxRTFunction((void*)len, UNKNOWN, 1));
builtins_module->giveAttr("len", len_obj); builtins_module->giveAttr("len", len_obj);
hash_obj = new BoxedFunction(boxRTFunction((void*)hash, NULL, 1, false)); hash_obj = new BoxedFunction(boxRTFunction((void*)hash, UNKNOWN, 1));
builtins_module->giveAttr("hash", hash_obj); builtins_module->giveAttr("hash", hash_obj);
abs_obj = new BoxedFunction(boxRTFunction((void*)abs_, NULL, 1, false)); abs_obj = new BoxedFunction(boxRTFunction((void*)abs_, UNKNOWN, 1));
builtins_module->giveAttr("abs", abs_obj); builtins_module->giveAttr("abs", abs_obj);
CLFunction* min_func = boxRTFunction((void*)min1, NULL, 1, false); min_obj = new BoxedFunction(boxRTFunction((void*)min, UNKNOWN, 1, 0, true, false));
addRTFunction(min_func, (void*)min2, NULL, 2, false);
min_obj = new BoxedFunction(min_func);
builtins_module->giveAttr("min", min_obj); builtins_module->giveAttr("min", min_obj);
CLFunction* max_func = boxRTFunction((void*)max1, NULL, 1, false); max_obj = new BoxedFunction(boxRTFunction((void*)max, UNKNOWN, 1, 0, true, false));
addRTFunction(max_func, (void*)max2, NULL, 2, false);
max_obj = new BoxedFunction(max_func);
builtins_module->giveAttr("max", max_obj); builtins_module->giveAttr("max", max_obj);
CLFunction* sum_func = boxRTFunction((void*)sum1, NULL, 1, false); builtins_module->giveAttr("sum",
addRTFunction(sum_func, (void*)sum2, NULL, 2, false); new BoxedFunction(boxRTFunction((void*)sum, UNKNOWN, 2, 1, false, false), { boxInt(0) }));
builtins_module->giveAttr("sum", new BoxedFunction(sum_func));
chr_obj = new BoxedFunction(boxRTFunction((void*)chr, NULL, 1, false)); chr_obj = new BoxedFunction(boxRTFunction((void*)chr, STR, 1));
builtins_module->giveAttr("chr", chr_obj); builtins_module->giveAttr("chr", chr_obj);
ord_obj = new BoxedFunction(boxRTFunction((void*)ord, NULL, 1, false)); ord_obj = new BoxedFunction(boxRTFunction((void*)ord, BOXED_INT, 1));
builtins_module->giveAttr("ord", ord_obj); builtins_module->giveAttr("ord", ord_obj);
trap_obj = new BoxedFunction(boxRTFunction((void*)trap, NULL, 0, false)); trap_obj = new BoxedFunction(boxRTFunction((void*)trap, UNKNOWN, 0));
builtins_module->giveAttr("trap", trap_obj); builtins_module->giveAttr("trap", trap_obj);
CLFunction* getattr_func = boxRTFunction((void*)getattr2, NULL, 2, false); builtins_module->giveAttr(
addRTFunction(getattr_func, (void*)getattr3, NULL, 3, false); "getattr", new BoxedFunction(boxRTFunction((void*)getattrFunc, UNKNOWN, 3, 1, false, false), { NULL }));
builtins_module->giveAttr("getattr", new BoxedFunction(getattr_func));
Box* hasattr_obj = new BoxedFunction(boxRTFunction((void*)hasattr, NULL, 2, false)); Box* hasattr_obj = new BoxedFunction(boxRTFunction((void*)hasattr, BOXED_BOOL, 2));
builtins_module->giveAttr("hasattr", hasattr_obj); builtins_module->giveAttr("hasattr", hasattr_obj);
Box* isinstance_obj = new BoxedFunction(boxRTFunction((void*)isinstance_func, NULL, 2, false)); Box* isinstance_obj = new BoxedFunction(boxRTFunction((void*)isinstance_func, BOXED_BOOL, 2));
builtins_module->giveAttr("isinstance", isinstance_obj); builtins_module->giveAttr("isinstance", isinstance_obj);
CLFunction* sorted_func = createRTFunction(); CLFunction* sorted_func = createRTFunction(1, 0, false, false);
addRTFunction(sorted_func, (void*)sortedList, LIST, { LIST }, false); addRTFunction(sorted_func, (void*)sortedList, LIST, { LIST });
addRTFunction(sorted_func, (void*)sorted, LIST, { UNKNOWN }, false); addRTFunction(sorted_func, (void*)sorted, LIST, { UNKNOWN });
builtins_module->giveAttr("sorted", new BoxedFunction(sorted_func)); builtins_module->giveAttr("sorted", new BoxedFunction(sorted_func));
builtins_module->giveAttr("True", True); builtins_module->giveAttr("True", True);
builtins_module->giveAttr("False", False); builtins_module->giveAttr("False", False);
CLFunction* range_clf = boxRTFunction((void*)range1, NULL, 1, false); range_obj = new BoxedFunction(boxRTFunction((void*)range, LIST, 3, 2, false, false), { NULL, NULL });
addRTFunction(range_clf, (void*)range2, NULL, 2, false);
addRTFunction(range_clf, (void*)range3, NULL, 3, false);
range_obj = new BoxedFunction(range_clf);
builtins_module->giveAttr("range", range_obj); builtins_module->giveAttr("range", range_obj);
setupXrange(); setupXrange();
builtins_module->giveAttr("xrange", xrange_cls); builtins_module->giveAttr("xrange", xrange_cls);
CLFunction* open = boxRTFunction((void*)open1, NULL, 1, false); open_obj = new BoxedFunction(boxRTFunction((void*)open, typeFromClass(file_cls), 2, 1, false, false),
addRTFunction(open, (void*)open2, NULL, 2, false); { boxStrConstant("r") });
open_obj = new BoxedFunction(open);
builtins_module->giveAttr("open", open_obj); builtins_module->giveAttr("open", open_obj);
builtins_module->giveAttr("map", new BoxedFunction(boxRTFunction((void*)map2, LIST, 2, false))); builtins_module->giveAttr("map", new BoxedFunction(boxRTFunction((void*)map2, LIST, 2)));
builtins_module->giveAttr("zip", new BoxedFunction(boxRTFunction((void*)zip2, LIST, 2, false))); builtins_module->giveAttr("zip", new BoxedFunction(boxRTFunction((void*)zip2, LIST, 2)));
CLFunction* dir_clf = boxRTFunction((void*)dir0, LIST, 0, false); builtins_module->giveAttr("dir", new BoxedFunction(boxRTFunction((void*)dir, LIST, 1, 1, false, false), { NULL }));
addRTFunction(dir_clf, (void*)dir1, LIST, 1, false);
builtins_module->giveAttr("dir", new BoxedFunction(dir_clf));
builtins_module->giveAttr("object", object_cls); builtins_module->giveAttr("object", object_cls);
builtins_module->giveAttr("str", str_cls); builtins_module->giveAttr("str", str_cls);
builtins_module->giveAttr("int", int_cls); builtins_module->giveAttr("int", int_cls);
......
...@@ -89,12 +89,12 @@ static void _addFunc(const char* name, void* int_func, void* float_func, void* b ...@@ -89,12 +89,12 @@ static void _addFunc(const char* name, void* int_func, void* float_func, void* b
assert(BOXED_INT); assert(BOXED_INT);
v_i.push_back(BOXED_INT); v_i.push_back(BOXED_INT);
v_f.push_back(BOXED_FLOAT); v_f.push_back(BOXED_FLOAT);
v_u.push_back(NULL); v_u.push_back(UNKNOWN);
CLFunction* cl = createRTFunction(); CLFunction* cl = createRTFunction(1, 0, false, false);
addRTFunction(cl, int_func, BOXED_FLOAT, v_i, false); addRTFunction(cl, int_func, BOXED_FLOAT, v_i);
addRTFunction(cl, float_func, BOXED_FLOAT, v_f, false); addRTFunction(cl, float_func, BOXED_FLOAT, v_f);
addRTFunction(cl, boxed_func, NULL, v_u, false); addRTFunction(cl, boxed_func, UNKNOWN, v_u);
math_module->giveAttr(name, new BoxedFunction(cl)); math_module->giveAttr(name, new BoxedFunction(cl));
} }
...@@ -103,6 +103,6 @@ void setupMath() { ...@@ -103,6 +103,6 @@ void setupMath() {
math_module->giveAttr("pi", boxFloat(M_PI)); math_module->giveAttr("pi", boxFloat(M_PI));
_addFunc("sqrt", (void*)mathSqrtInt, (void*)mathSqrtFloat, (void*)mathSqrt); _addFunc("sqrt", (void*)mathSqrtInt, (void*)mathSqrtFloat, (void*)mathSqrt);
_addFunc("tan", (void*)mathTanInt, (void*)mathTanFloat, (void*)mathSqrt); _addFunc("tan", (void*)mathTanInt, (void*)mathTanFloat, (void*)mathTan);
} }
} }
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <ctime> #include <ctime>
#include <sys/time.h> #include <sys/time.h>
#include "codegen/compvars.h"
#include "core/types.h" #include "core/types.h"
#include "runtime/gc_runtime.h" #include "runtime/gc_runtime.h"
#include "runtime/types.h" #include "runtime/types.h"
...@@ -33,6 +34,6 @@ Box* timeTime() { ...@@ -33,6 +34,6 @@ Box* timeTime() {
void setupTime() { void setupTime() {
time_module = createModule("time", "__builtin__"); time_module = createModule("time", "__builtin__");
time_module->giveAttr("time", new BoxedFunction(boxRTFunction((void*)timeTime, NULL, 0, false))); time_module->giveAttr("time", new BoxedFunction(boxRTFunction((void*)timeTime, BOXED_FLOAT, 0)));
} }
} }
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include "Python.h" #include "Python.h"
#include "codegen/compvars.h"
#include "core/types.h" #include "core/types.h"
#include "runtime/types.h" #include "runtime/types.h"
...@@ -41,9 +42,9 @@ public: ...@@ -41,9 +42,9 @@ public:
return boxStrConstant(self->name); return boxStrConstant(self->name);
} }
static Box* __call__(BoxedCApiFunction* self, BoxedList* varargs) { static Box* __call__(BoxedCApiFunction* self, BoxedTuple* varargs) {
assert(self->cls == capifunc_cls); assert(self->cls == capifunc_cls);
assert(varargs->cls == list_cls); assert(varargs->cls == tuple_cls);
Box* rtn = (Box*)self->func(test_module, varargs); Box* rtn = (Box*)self->func(test_module, varargs);
assert(rtn); assert(rtn);
...@@ -78,14 +79,14 @@ extern "C" bool PyArg_ParseTuple(void* tuple, const char* fmt, ...) { ...@@ -78,14 +79,14 @@ extern "C" bool PyArg_ParseTuple(void* tuple, const char* fmt, ...) {
assert(strcmp("O", fmt) == 0); assert(strcmp("O", fmt) == 0);
BoxedList* varargs = (BoxedList*)tuple; BoxedTuple* varargs = (BoxedTuple*)tuple;
assert(varargs->size == 1); assert(varargs->elts.size() == 1);
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
Box** arg0 = va_arg(ap, Box**); Box** arg0 = va_arg(ap, Box**);
*arg0 = varargs->elts->elts[0]; *arg0 = varargs->elts[0];
va_end(ap); va_end(ap);
...@@ -124,11 +125,11 @@ void setupCAPI() { ...@@ -124,11 +125,11 @@ void setupCAPI() {
capifunc_cls->giveAttr("__name__", boxStrConstant("capifunc")); capifunc_cls->giveAttr("__name__", boxStrConstant("capifunc"));
capifunc_cls->giveAttr("__repr__", capifunc_cls->giveAttr("__repr__",
new BoxedFunction(boxRTFunction((void*)BoxedCApiFunction::__repr__, NULL, 1, false))); new BoxedFunction(boxRTFunction((void*)BoxedCApiFunction::__repr__, UNKNOWN, 1)));
capifunc_cls->giveAttr("__str__", capifunc_cls->getattr("__repr__")); capifunc_cls->giveAttr("__str__", capifunc_cls->getattr("__repr__"));
capifunc_cls->giveAttr("__call__", capifunc_cls->giveAttr(
new BoxedFunction(boxRTFunction((void*)BoxedCApiFunction::__call__, NULL, 1, true))); "__call__", new BoxedFunction(boxRTFunction((void*)BoxedCApiFunction::__call__, UNKNOWN, 1, 0, true, false)));
capifunc_cls->freeze(); capifunc_cls->freeze();
} }
......
...@@ -104,11 +104,14 @@ Box* dictSetitem(BoxedDict* self, Box* k, Box* v) { ...@@ -104,11 +104,14 @@ Box* dictSetitem(BoxedDict* self, Box* k, Box* v) {
return None; return None;
} }
Box* dictPop2(BoxedDict* self, Box* k) { Box* dictPop(BoxedDict* self, Box* k, Box* d) {
assert(self->cls == dict_cls); assert(self->cls == dict_cls);
auto it = self->d.find(k); auto it = self->d.find(k);
if (it == self->d.end()) { if (it == self->d.end()) {
if (d)
return d;
BoxedString* s = reprOrNull(k); BoxedString* s = reprOrNull(k);
if (s) if (s)
...@@ -122,19 +125,7 @@ Box* dictPop2(BoxedDict* self, Box* k) { ...@@ -122,19 +125,7 @@ Box* dictPop2(BoxedDict* self, Box* k) {
return rtn; return rtn;
} }
Box* dictPop3(BoxedDict* self, Box* k, Box* d) { Box* dictGet(BoxedDict* self, Box* k, Box* d) {
assert(self->cls == dict_cls);
auto it = self->d.find(k);
if (it == self->d.end())
return d;
Box* rtn = it->second;
self->d.erase(it);
return rtn;
}
Box* dictGet3(BoxedDict* self, Box* k, Box* d) {
assert(self->cls == dict_cls); assert(self->cls == dict_cls);
auto it = self->d.find(k); auto it = self->d.find(k);
...@@ -144,11 +135,7 @@ Box* dictGet3(BoxedDict* self, Box* k, Box* d) { ...@@ -144,11 +135,7 @@ Box* dictGet3(BoxedDict* self, Box* k, Box* d) {
return it->second; return it->second;
} }
Box* dictGet2(BoxedDict* self, Box* k) { Box* dictSetdefault(BoxedDict* self, Box* k, Box* v) {
return dictGet3(self, k, None);
}
Box* dictSetdefault3(BoxedDict* self, Box* k, Box* v) {
assert(self->cls == dict_cls); assert(self->cls == dict_cls);
auto it = self->d.find(k); auto it = self->d.find(k);
...@@ -159,10 +146,6 @@ Box* dictSetdefault3(BoxedDict* self, Box* k, Box* v) { ...@@ -159,10 +146,6 @@ Box* dictSetdefault3(BoxedDict* self, Box* k, Box* v) {
return v; return v;
} }
Box* dictSetdefault2(BoxedDict* self, Box* k) {
return dictSetdefault3(self, k, None);
}
BoxedClass* dict_iterator_cls = NULL; BoxedClass* dict_iterator_cls = NULL;
extern "C" void dictIteratorGCHandler(GCVisitor* v, void* p) { extern "C" void dictIteratorGCHandler(GCVisitor* v, void* p) {
boxGCHandler(v, p); boxGCHandler(v, p);
...@@ -176,53 +159,48 @@ void setupDict() { ...@@ -176,53 +159,48 @@ void setupDict() {
dict_iterator_cls = new BoxedClass(object_cls, 0, sizeof(BoxedDict), false); dict_iterator_cls = new BoxedClass(object_cls, 0, sizeof(BoxedDict), false);
dict_cls->giveAttr("__name__", boxStrConstant("dict")); dict_cls->giveAttr("__name__", boxStrConstant("dict"));
// dict_cls->giveAttr("__len__", new BoxedFunction(boxRTFunction((void*)dictLen, NULL, 1, false))); // dict_cls->giveAttr("__len__", new BoxedFunction(boxRTFunction((void*)dictLen, NULL, 1)));
// dict_cls->giveAttr("__getitem__", new BoxedFunction(boxRTFunction((void*)dictGetitem, NULL, 2, false))); // dict_cls->giveAttr("__getitem__", new BoxedFunction(boxRTFunction((void*)dictGetitem, NULL, 2)));
// dict_cls->giveAttr("__new__", new BoxedFunction(boxRTFunction((void*)dictNew, NULL, 1, false))); // dict_cls->giveAttr("__new__", new BoxedFunction(boxRTFunction((void*)dictNew, NULL, 1)));
// dict_cls->giveAttr("__init__", new BoxedFunction(boxRTFunction((void*)dictInit, NULL, 1, false))); // dict_cls->giveAttr("__init__", new BoxedFunction(boxRTFunction((void*)dictInit, NULL, 1)));
dict_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)dictRepr, NULL, 1, false))); dict_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)dictRepr, STR, 1)));
dict_cls->giveAttr("__str__", dict_cls->getattr("__repr__")); dict_cls->giveAttr("__str__", dict_cls->getattr("__repr__"));
dict_cls->giveAttr( dict_cls->giveAttr("__iter__",
"__iter__", new BoxedFunction(boxRTFunction((void*)dictIterKeys, typeFromClass(dict_iterator_cls), 1, false))); new BoxedFunction(boxRTFunction((void*)dictIterKeys, typeFromClass(dict_iterator_cls), 1)));
dict_cls->giveAttr("items", new BoxedFunction(boxRTFunction((void*)dictItems, NULL, 1, false))); dict_cls->giveAttr("items", new BoxedFunction(boxRTFunction((void*)dictItems, LIST, 1)));
dict_cls->giveAttr("iteritems", new BoxedFunction(boxRTFunction((void*)dictIterItems, dict_cls->giveAttr("iteritems",
typeFromClass(dict_iterator_cls), 1, false))); new BoxedFunction(boxRTFunction((void*)dictIterItems, typeFromClass(dict_iterator_cls), 1)));
dict_cls->giveAttr("values", new BoxedFunction(boxRTFunction((void*)dictValues, NULL, 1, false))); dict_cls->giveAttr("values", new BoxedFunction(boxRTFunction((void*)dictValues, LIST, 1)));
dict_cls->giveAttr("itervalues", new BoxedFunction(boxRTFunction((void*)dictIterValues, dict_cls->giveAttr("itervalues",
typeFromClass(dict_iterator_cls), 1, false))); new BoxedFunction(boxRTFunction((void*)dictIterValues, typeFromClass(dict_iterator_cls), 1)));
dict_cls->giveAttr("keys", new BoxedFunction(boxRTFunction((void*)dictKeys, NULL, 1, false))); dict_cls->giveAttr("keys", new BoxedFunction(boxRTFunction((void*)dictKeys, LIST, 1)));
dict_cls->giveAttr("iterkeys", dict_cls->getattr("__iter__")); dict_cls->giveAttr("iterkeys", dict_cls->getattr("__iter__"));
CLFunction* pop = boxRTFunction((void*)dictPop2, UNKNOWN, 2, false); dict_cls->giveAttr("pop", new BoxedFunction(boxRTFunction((void*)dictPop, UNKNOWN, 3, 1, false, false), { NULL }));
addRTFunction(pop, (void*)dictPop3, UNKNOWN, 3, false);
dict_cls->giveAttr("pop", new BoxedFunction(pop));
CLFunction* get = boxRTFunction((void*)dictGet2, UNKNOWN, 2, false); dict_cls->giveAttr("get", new BoxedFunction(boxRTFunction((void*)dictGet, UNKNOWN, 3, 1, false, false), { None }));
addRTFunction(get, (void*)dictGet3, UNKNOWN, 3, false);
dict_cls->giveAttr("get", new BoxedFunction(get));
CLFunction* setdefault = boxRTFunction((void*)dictSetdefault2, UNKNOWN, 2, false); dict_cls->giveAttr("setdefault",
addRTFunction(setdefault, (void*)dictSetdefault3, UNKNOWN, 3, false); new BoxedFunction(boxRTFunction((void*)dictSetdefault, UNKNOWN, 3, 1, false, false), { None }));
dict_cls->giveAttr("setdefault", new BoxedFunction(setdefault));
dict_cls->giveAttr("__getitem__", new BoxedFunction(boxRTFunction((void*)dictGetitem, NULL, 2, false))); dict_cls->giveAttr("__getitem__", new BoxedFunction(boxRTFunction((void*)dictGetitem, UNKNOWN, 2)));
dict_cls->giveAttr("__setitem__", new BoxedFunction(boxRTFunction((void*)dictSetitem, NULL, 3, false))); dict_cls->giveAttr("__setitem__", new BoxedFunction(boxRTFunction((void*)dictSetitem, NONE, 3)));
dict_cls->freeze(); dict_cls->freeze();
gc::registerStaticRootObj(dict_iterator_cls); gc::registerStaticRootObj(dict_iterator_cls);
dict_iterator_cls->giveAttr("__name__", boxStrConstant("dictiterator")); dict_iterator_cls->giveAttr("__name__", boxStrConstant("dictiterator"));
CLFunction* hasnext = boxRTFunction((void*)dictIterHasnextUnboxed, BOOL, 1, false); CLFunction* hasnext = boxRTFunction((void*)dictIterHasnextUnboxed, BOOL, 1);
addRTFunction(hasnext, (void*)dictIterHasnext, BOXED_BOOL, 1, false); addRTFunction(hasnext, (void*)dictIterHasnext, BOXED_BOOL);
dict_iterator_cls->giveAttr("__hasnext__", new BoxedFunction(hasnext)); dict_iterator_cls->giveAttr("__hasnext__", new BoxedFunction(hasnext));
dict_iterator_cls->giveAttr( dict_iterator_cls->giveAttr(
"__iter__", new BoxedFunction(boxRTFunction((void*)dictIterIter, typeFromClass(dict_iterator_cls), 1, false))); "__iter__", new BoxedFunction(boxRTFunction((void*)dictIterIter, typeFromClass(dict_iterator_cls), 1)));
dict_iterator_cls->giveAttr("next", new BoxedFunction(boxRTFunction((void*)dictIterNext, UNKNOWN, 1, false))); dict_iterator_cls->giveAttr("next", new BoxedFunction(boxRTFunction((void*)dictIterNext, UNKNOWN, 1)));
dict_iterator_cls->freeze(); dict_iterator_cls->freeze();
} }
......
...@@ -31,7 +31,14 @@ Box* fileRepr(BoxedFile* self) { ...@@ -31,7 +31,14 @@ Box* fileRepr(BoxedFile* self) {
RELEASE_ASSERT(0, ""); RELEASE_ASSERT(0, "");
} }
static Box* _fileRead(BoxedFile* self, i64 size) { Box* fileRead(BoxedFile* self, Box* _size) {
assert(self->cls == file_cls);
if (_size->cls != int_cls) {
fprintf(stderr, "TypeError: an integer is required\n");
raiseExcHelper(TypeError, "");
}
int64_t size = static_cast<BoxedInt*>(_size)->n;
if (self->closed) { if (self->closed) {
fprintf(stderr, "IOError: file not open for reading\n"); fprintf(stderr, "IOError: file not open for reading\n");
raiseExcHelper(IOError, ""); raiseExcHelper(IOError, "");
...@@ -59,11 +66,6 @@ static Box* _fileRead(BoxedFile* self, i64 size) { ...@@ -59,11 +66,6 @@ static Box* _fileRead(BoxedFile* self, i64 size) {
return boxString(os.str()); return boxString(os.str());
} }
Box* fileRead1(BoxedFile* self) {
assert(self->cls == file_cls);
return _fileRead(self, -1);
}
Box* fileReadline1(BoxedFile* self) { Box* fileReadline1(BoxedFile* self) {
assert(self->cls == file_cls); assert(self->cls == file_cls);
...@@ -82,15 +84,6 @@ Box* fileReadline1(BoxedFile* self) { ...@@ -82,15 +84,6 @@ Box* fileReadline1(BoxedFile* self) {
return boxString(os.str()); return boxString(os.str());
} }
Box* fileRead2(BoxedFile* self, Box* size) {
assert(self->cls == file_cls);
if (size->cls != int_cls) {
fprintf(stderr, "TypeError: an integer is required\n");
raiseExcHelper(TypeError, "");
}
return _fileRead(self, static_cast<BoxedInt*>(size)->n);
}
Box* fileWrite(BoxedFile* self, Box* val) { Box* fileWrite(BoxedFile* self, Box* val) {
assert(self->cls == file_cls); assert(self->cls == file_cls);
...@@ -158,38 +151,31 @@ Box* fileExit(BoxedFile* self, Box* exc_type, Box* exc_val, Box** args) { ...@@ -158,38 +151,31 @@ Box* fileExit(BoxedFile* self, Box* exc_type, Box* exc_val, Box** args) {
return fileClose(self); return fileClose(self);
} }
Box* fileNew2(BoxedClass* cls, Box* s) { Box* fileNew(BoxedClass* cls, Box* s, Box* m) {
assert(cls == file_cls);
return open1(s);
}
Box* fileNew3(BoxedClass* cls, Box* s, Box* m) {
assert(cls == file_cls); assert(cls == file_cls);
return open2(s, m); return open(s, m);
} }
void setupFile() { void setupFile() {
file_cls->giveAttr("__name__", boxStrConstant("file")); file_cls->giveAttr("__name__", boxStrConstant("file"));
CLFunction* read = boxRTFunction((void*)fileRead1, NULL, 1, false); file_cls->giveAttr("read",
addRTFunction(read, (void*)fileRead2, NULL, 2, false); new BoxedFunction(boxRTFunction((void*)fileRead, STR, 2, 1, false, false), { boxInt(-1) }));
file_cls->giveAttr("read", new BoxedFunction(read));
CLFunction* readline = boxRTFunction((void*)fileReadline1, STR, 1, false); CLFunction* readline = boxRTFunction((void*)fileReadline1, STR, 1);
file_cls->giveAttr("readline", new BoxedFunction(readline)); file_cls->giveAttr("readline", new BoxedFunction(readline));
file_cls->giveAttr("write", new BoxedFunction(boxRTFunction((void*)fileWrite, NULL, 2, false))); file_cls->giveAttr("write", new BoxedFunction(boxRTFunction((void*)fileWrite, NONE, 2)));
file_cls->giveAttr("close", new BoxedFunction(boxRTFunction((void*)fileClose, NULL, 1, false))); file_cls->giveAttr("close", new BoxedFunction(boxRTFunction((void*)fileClose, NONE, 1)));
file_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)fileRepr, NULL, 1, false))); file_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)fileRepr, STR, 1)));
file_cls->giveAttr("__str__", file_cls->getattr("__repr__")); file_cls->giveAttr("__str__", file_cls->getattr("__repr__"));
file_cls->giveAttr("__enter__", new BoxedFunction(boxRTFunction((void*)fileEnter, NULL, 1, false))); file_cls->giveAttr("__enter__", new BoxedFunction(boxRTFunction((void*)fileEnter, typeFromClass(file_cls), 1)));
file_cls->giveAttr("__exit__", new BoxedFunction(boxRTFunction((void*)fileExit, NULL, 4, false))); file_cls->giveAttr("__exit__", new BoxedFunction(boxRTFunction((void*)fileExit, UNKNOWN, 4)));
CLFunction* __new__ = boxRTFunction((void*)fileNew2, NULL, 2, false); file_cls->giveAttr("__new__", new BoxedFunction(boxRTFunction((void*)fileNew, UNKNOWN, 3, 1, false, false),
addRTFunction(__new__, (void*)fileNew3, NULL, 3, false); { boxStrConstant("r") }));
file_cls->giveAttr("__new__", new BoxedFunction(__new__));
file_cls->freeze(); file_cls->freeze();
} }
......
...@@ -502,13 +502,7 @@ std::string floatFmt(double x, int precision, char code) { ...@@ -502,13 +502,7 @@ std::string floatFmt(double x, int precision, char code) {
return std::string(buf, n); return std::string(buf, n);
} }
Box* floatNew1(BoxedClass* cls) { Box* floatNew(BoxedClass* cls, Box* a) {
assert(cls == float_cls);
// TODO intern this?
return boxFloat(0.0);
}
Box* floatNew2(BoxedClass* cls, Box* a) {
assert(cls == float_cls); assert(cls == float_cls);
if (a->cls == float_cls) { if (a->cls == float_cls) {
...@@ -552,12 +546,12 @@ static void _addFunc(const char* name, ConcreteCompilerType* rtn_type, void* flo ...@@ -552,12 +546,12 @@ static void _addFunc(const char* name, ConcreteCompilerType* rtn_type, void* flo
v_fi.push_back(BOXED_FLOAT); v_fi.push_back(BOXED_FLOAT);
v_fi.push_back(BOXED_INT); v_fi.push_back(BOXED_INT);
v_fu.push_back(BOXED_FLOAT); v_fu.push_back(BOXED_FLOAT);
v_fu.push_back(NULL); v_fu.push_back(UNKNOWN);
CLFunction* cl = createRTFunction(); CLFunction* cl = createRTFunction(2, 0, false, false);
addRTFunction(cl, float_func, rtn_type, v_ff, false); addRTFunction(cl, float_func, rtn_type, v_ff);
addRTFunction(cl, int_func, rtn_type, v_fi, false); addRTFunction(cl, int_func, rtn_type, v_fi);
addRTFunction(cl, boxed_func, NULL, v_fu, false); addRTFunction(cl, boxed_func, UNKNOWN, v_fu);
float_cls->giveAttr(name, new BoxedFunction(cl)); float_cls->giveAttr(name, new BoxedFunction(cl));
} }
...@@ -569,7 +563,7 @@ void setupFloat() { ...@@ -569,7 +563,7 @@ void setupFloat() {
_addFunc("__div__", BOXED_FLOAT, (void*)floatDivFloat, (void*)floatDivInt, (void*)floatDiv); _addFunc("__div__", BOXED_FLOAT, (void*)floatDivFloat, (void*)floatDivInt, (void*)floatDiv);
_addFunc("__rdiv__", BOXED_FLOAT, (void*)floatRDivFloat, (void*)floatRDivInt, (void*)floatRDiv); _addFunc("__rdiv__", BOXED_FLOAT, (void*)floatRDivFloat, (void*)floatRDivInt, (void*)floatRDiv);
float_cls->giveAttr("__floordiv__", new BoxedFunction(boxRTFunction((void*)floatFloorDiv, NULL, 2, false))); float_cls->giveAttr("__floordiv__", new BoxedFunction(boxRTFunction((void*)floatFloorDiv, UNKNOWN, 2)));
_addFunc("__eq__", BOXED_BOOL, (void*)floatEqFloat, (void*)floatEqInt, (void*)floatEq); _addFunc("__eq__", BOXED_BOOL, (void*)floatEqFloat, (void*)floatEqInt, (void*)floatEq);
_addFunc("__ge__", BOXED_BOOL, (void*)floatGeFloat, (void*)floatGeInt, (void*)floatGe); _addFunc("__ge__", BOXED_BOOL, (void*)floatGeFloat, (void*)floatGeInt, (void*)floatGe);
...@@ -587,17 +581,18 @@ void setupFloat() { ...@@ -587,17 +581,18 @@ void setupFloat() {
_addFunc("__sub__", BOXED_FLOAT, (void*)floatSubFloat, (void*)floatSubInt, (void*)floatSub); _addFunc("__sub__", BOXED_FLOAT, (void*)floatSubFloat, (void*)floatSubInt, (void*)floatSub);
_addFunc("__rsub__", BOXED_FLOAT, (void*)floatRSubFloat, (void*)floatRSubInt, (void*)floatRSub); _addFunc("__rsub__", BOXED_FLOAT, (void*)floatRSubFloat, (void*)floatRSubInt, (void*)floatRSub);
CLFunction* __new__ = boxRTFunction((void*)floatNew1, NULL, 1, false); float_cls->giveAttr(
addRTFunction(__new__, (void*)floatNew2, NULL, 2, false); "__new__", new BoxedFunction(boxRTFunction((void*)floatNew, UNKNOWN, 2, 1, false, false), { boxFloat(0.0) }));
float_cls->giveAttr("__new__", new BoxedFunction(__new__));
float_cls->giveAttr("__neg__", new BoxedFunction(boxRTFunction((void*)floatNeg, NULL, 1, false))); float_cls->giveAttr("__neg__", new BoxedFunction(boxRTFunction((void*)floatNeg, BOXED_FLOAT, 1)));
CLFunction* nonzero = boxRTFunction((void*)floatNonzeroUnboxed, BOOL, 1, false);
addRTFunction(nonzero, (void*)floatNonzero, UNKNOWN, 1, false); CLFunction* nonzero = boxRTFunction((void*)floatNonzeroUnboxed, BOOL, 1);
addRTFunction(nonzero, (void*)floatNonzero, UNKNOWN);
float_cls->giveAttr("__nonzero__", new BoxedFunction(nonzero)); float_cls->giveAttr("__nonzero__", new BoxedFunction(nonzero));
// float_cls->giveAttr("__nonzero__", new BoxedFunction(boxRTFunction((void*)floatNonzero, NULL, 1, false)));
float_cls->giveAttr("__str__", new BoxedFunction(boxRTFunction((void*)floatStr, NULL, 1, false))); // float_cls->giveAttr("__nonzero__", new BoxedFunction(boxRTFunction((void*)floatNonzero, NULL, 1)));
float_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)floatRepr, NULL, 1, false))); float_cls->giveAttr("__str__", new BoxedFunction(boxRTFunction((void*)floatStr, STR, 1)));
float_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)floatRepr, STR, 1)));
float_cls->freeze(); float_cls->freeze();
} }
......
...@@ -69,8 +69,7 @@ void BoxedList::shrink() { ...@@ -69,8 +69,7 @@ void BoxedList::shrink() {
if (capacity > size * 3) { if (capacity > size * 3) {
int new_capacity = std::max(static_cast<int64_t>(INITIAL_CAPACITY), capacity / 2); int new_capacity = std::max(static_cast<int64_t>(INITIAL_CAPACITY), capacity / 2);
if (size > 0) { if (size > 0) {
elts = (BoxedList::ElementArray*)rt_realloc(elts, elts = GCdArray::realloc(elts, new_capacity);
new_capacity * sizeof(Box*) + sizeof(BoxedList::ElementArray));
capacity = new_capacity; capacity = new_capacity;
} else if (size == 0) { } else if (size == 0) {
rt_free(elts); rt_free(elts);
...@@ -85,12 +84,11 @@ void BoxedList::ensure(int space) { ...@@ -85,12 +84,11 @@ void BoxedList::ensure(int space) {
if (capacity == 0) { if (capacity == 0) {
const int INITIAL_CAPACITY = 8; const int INITIAL_CAPACITY = 8;
int initial = std::max(INITIAL_CAPACITY, space); int initial = std::max(INITIAL_CAPACITY, space);
elts = new (initial) BoxedList::ElementArray(); elts = new (initial) GCdArray();
capacity = initial; capacity = initial;
} else { } else {
int new_capacity = std::max(capacity * 2, size + space); int new_capacity = std::max(capacity * 2, size + space);
elts = (BoxedList::ElementArray*)rt_realloc(elts, elts = GCdArray::realloc(elts, new_capacity);
new_capacity * sizeof(Box*) + sizeof(BoxedList::ElementArray));
capacity = new_capacity; capacity = new_capacity;
} }
} }
......
...@@ -79,28 +79,24 @@ public: ...@@ -79,28 +79,24 @@ public:
}; };
extern "C" const ObjectFlavor xrange_iterator_flavor(&BoxedXrangeIterator::xrangeIteratorGCHandler, NULL); extern "C" const ObjectFlavor xrange_iterator_flavor(&BoxedXrangeIterator::xrangeIteratorGCHandler, NULL);
Box* xrange1(Box* cls, Box* stop) { Box* xrange(Box* cls, Box* start, Box* stop, Box** args) {
assert(cls == xrange_cls); assert(cls == xrange_cls);
RELEASE_ASSERT(stop->cls == int_cls, "%s", getTypeName(stop)->c_str());
i64 istop = static_cast<BoxedInt*>(stop)->n; Box* step = args[0];
return new BoxedXrange(0, istop, 1);
}
Box* xrange2(Box* cls, Box* start, Box* stop) { if (stop == NULL) {
assert(cls == xrange_cls); RELEASE_ASSERT(start->cls == int_cls, "%s", getTypeName(start)->c_str());
i64 istop = static_cast<BoxedInt*>(start)->n;
return new BoxedXrange(0, istop, 1);
} else if (step == NULL) {
RELEASE_ASSERT(start->cls == int_cls, "%s", getTypeName(start)->c_str()); RELEASE_ASSERT(start->cls == int_cls, "%s", getTypeName(start)->c_str());
RELEASE_ASSERT(stop->cls == int_cls, "%s", getTypeName(stop)->c_str()); RELEASE_ASSERT(stop->cls == int_cls, "%s", getTypeName(stop)->c_str());
i64 istart = static_cast<BoxedInt*>(start)->n; i64 istart = static_cast<BoxedInt*>(start)->n;
i64 istop = static_cast<BoxedInt*>(stop)->n; i64 istop = static_cast<BoxedInt*>(stop)->n;
return new BoxedXrange(istart, istop, 1); return new BoxedXrange(istart, istop, 1);
} } else {
Box* xrange3(Box* cls, Box* start, Box* stop, Box** args) {
Box* step = args[0];
assert(cls == xrange_cls);
RELEASE_ASSERT(start->cls == int_cls, "%s", getTypeName(start)->c_str()); RELEASE_ASSERT(start->cls == int_cls, "%s", getTypeName(start)->c_str());
RELEASE_ASSERT(stop->cls == int_cls, "%s", getTypeName(stop)->c_str()); RELEASE_ASSERT(stop->cls == int_cls, "%s", getTypeName(stop)->c_str());
RELEASE_ASSERT(step->cls == int_cls, "%s", getTypeName(step)->c_str()); RELEASE_ASSERT(step->cls == int_cls, "%s", getTypeName(step)->c_str());
...@@ -110,6 +106,7 @@ Box* xrange3(Box* cls, Box* start, Box* stop, Box** args) { ...@@ -110,6 +106,7 @@ Box* xrange3(Box* cls, Box* start, Box* stop, Box** args) {
i64 istep = static_cast<BoxedInt*>(step)->n; i64 istep = static_cast<BoxedInt*>(step)->n;
RELEASE_ASSERT(istep != 0, "step can't be 0"); RELEASE_ASSERT(istep != 0, "step can't be 0");
return new BoxedXrange(istart, istop, istep); return new BoxedXrange(istart, istop, istep);
}
} }
Box* xrangeIter(Box* self) { Box* xrangeIter(Box* self) {
...@@ -125,19 +122,18 @@ void setupXrange() { ...@@ -125,19 +122,18 @@ void setupXrange() {
xrange_iterator_cls = new BoxedClass(object_cls, 0, sizeof(BoxedXrangeIterator), false); xrange_iterator_cls = new BoxedClass(object_cls, 0, sizeof(BoxedXrangeIterator), false);
xrange_iterator_cls->giveAttr("__name__", boxStrConstant("rangeiterator")); xrange_iterator_cls->giveAttr("__name__", boxStrConstant("rangeiterator"));
CLFunction* xrange_clf = boxRTFunction((void*)xrange1, NULL, 2, false);
addRTFunction(xrange_clf, (void*)xrange2, NULL, 3, false);
addRTFunction(xrange_clf, (void*)xrange3, NULL, 4, false);
xrange_cls->giveAttr("__new__", new BoxedFunction(xrange_clf));
xrange_cls->giveAttr( xrange_cls->giveAttr(
"__iter__", new BoxedFunction(boxRTFunction((void*)xrangeIter, typeFromClass(xrange_iterator_cls), 1, false))); "__new__",
new BoxedFunction(boxRTFunction((void*)xrange, typeFromClass(xrange_cls), 4, 2, false, false), { NULL, NULL }));
xrange_cls->giveAttr("__iter__",
new BoxedFunction(boxRTFunction((void*)xrangeIter, typeFromClass(xrange_iterator_cls), 1)));
CLFunction* hasnext = boxRTFunction((void*)BoxedXrangeIterator::xrangeIteratorHasnextUnboxed, BOOL, 1, false); CLFunction* hasnext = boxRTFunction((void*)BoxedXrangeIterator::xrangeIteratorHasnextUnboxed, BOOL, 1);
addRTFunction(hasnext, (void*)BoxedXrangeIterator::xrangeIteratorHasnext, BOXED_BOOL, 1, false); addRTFunction(hasnext, (void*)BoxedXrangeIterator::xrangeIteratorHasnext, BOXED_BOOL);
xrange_iterator_cls->giveAttr("__hasnext__", new BoxedFunction(hasnext)); xrange_iterator_cls->giveAttr("__hasnext__", new BoxedFunction(hasnext));
CLFunction* next = boxRTFunction((void*)BoxedXrangeIterator::xrangeIteratorNextUnboxed, INT, 1, false); CLFunction* next = boxRTFunction((void*)BoxedXrangeIterator::xrangeIteratorNextUnboxed, INT, 1);
addRTFunction(next, (void*)BoxedXrangeIterator::xrangeIteratorNext, BOXED_INT, 1, false); addRTFunction(next, (void*)BoxedXrangeIterator::xrangeIteratorNext, BOXED_INT);
xrange_iterator_cls->giveAttr("next", new BoxedFunction(next)); xrange_iterator_cls->giveAttr("next", new BoxedFunction(next));
// TODO this is pretty hacky, but stuff the iterator cls into xrange to make sure it gets decref'd at the end // TODO this is pretty hacky, but stuff the iterator cls into xrange to make sure it gets decref'd at the end
......
...@@ -447,14 +447,7 @@ extern "C" Box* intHash(BoxedInt* self) { ...@@ -447,14 +447,7 @@ extern "C" Box* intHash(BoxedInt* self) {
return self; return self;
} }
extern "C" Box* intNew1(Box* _cls) { extern "C" Box* intNew(Box* _cls, Box* val) {
if (!isSubclass(_cls->cls, type_cls))
raiseExcHelper(TypeError, "int.__new__(X): X is not a type object (%s)", getTypeName(_cls)->c_str());
return boxInt(0);
}
extern "C" Box* intNew2(Box* _cls, Box* val) {
if (!isSubclass(_cls->cls, type_cls)) if (!isSubclass(_cls->cls, type_cls))
raiseExcHelper(TypeError, "int.__new__(X): X is not a type object (%s)", getTypeName(_cls)->c_str()); raiseExcHelper(TypeError, "int.__new__(X): X is not a type object (%s)", getTypeName(_cls)->c_str());
...@@ -489,12 +482,7 @@ extern "C" Box* intNew2(Box* _cls, Box* val) { ...@@ -489,12 +482,7 @@ extern "C" Box* intNew2(Box* _cls, Box* val) {
return rtn; return rtn;
} }
extern "C" Box* intInit1(Box* self) { extern "C" Box* intInit(BoxedInt* self, Box* val, Box* args) {
// int.__init__ will actually let you call it with anything
return None;
}
extern "C" Box* intInit2(BoxedInt* self, Box* val) {
// int.__init__ will actually let you call it with anything // int.__init__ will actually let you call it with anything
return None; return None;
} }
...@@ -510,10 +498,10 @@ static void _addFuncIntFloatUnknown(const char* name, void* int_func, void* floa ...@@ -510,10 +498,10 @@ static void _addFuncIntFloatUnknown(const char* name, void* int_func, void* floa
v_iu.push_back(UNKNOWN); v_iu.push_back(UNKNOWN);
v_iu.push_back(UNKNOWN); v_iu.push_back(UNKNOWN);
CLFunction* cl = createRTFunction(); CLFunction* cl = createRTFunction(2, 0, false, false);
addRTFunction(cl, int_func, BOXED_INT, v_ii, false); addRTFunction(cl, int_func, BOXED_INT, v_ii);
addRTFunction(cl, float_func, BOXED_FLOAT, v_if, false); addRTFunction(cl, float_func, BOXED_FLOAT, v_if);
addRTFunction(cl, boxed_func, NULL, v_iu, false); addRTFunction(cl, boxed_func, UNKNOWN, v_iu);
int_cls->giveAttr(name, new BoxedFunction(cl)); int_cls->giveAttr(name, new BoxedFunction(cl));
} }
...@@ -523,15 +511,20 @@ static void _addFuncIntUnknown(const char* name, ConcreteCompilerType* rtn_type, ...@@ -523,15 +511,20 @@ static void _addFuncIntUnknown(const char* name, ConcreteCompilerType* rtn_type,
v_ii.push_back(BOXED_INT); v_ii.push_back(BOXED_INT);
v_ii.push_back(BOXED_INT); v_ii.push_back(BOXED_INT);
v_iu.push_back(BOXED_INT); v_iu.push_back(BOXED_INT);
v_iu.push_back(NULL); v_iu.push_back(UNKNOWN);
CLFunction* cl = createRTFunction(); CLFunction* cl = createRTFunction(2, 0, false, false);
addRTFunction(cl, int_func, rtn_type, v_ii, false); addRTFunction(cl, int_func, rtn_type, v_ii);
addRTFunction(cl, boxed_func, NULL, v_iu, false); addRTFunction(cl, boxed_func, UNKNOWN, v_iu);
int_cls->giveAttr(name, new BoxedFunction(cl)); int_cls->giveAttr(name, new BoxedFunction(cl));
} }
void setupInt() { void setupInt() {
for (int i = 0; i < NUM_INTERNED_INTS; i++) {
interned_ints[i] = new BoxedInt(int_cls, i);
gc::registerStaticRootObj(interned_ints[i]);
}
int_cls->giveAttr("__name__", boxStrConstant("int")); int_cls->giveAttr("__name__", boxStrConstant("int"));
_addFuncIntFloatUnknown("__add__", (void*)intAddInt, (void*)intAddFloat, (void*)intAdd); _addFuncIntFloatUnknown("__add__", (void*)intAddInt, (void*)intAddFloat, (void*)intAdd);
...@@ -552,29 +545,22 @@ void setupInt() { ...@@ -552,29 +545,22 @@ void setupInt() {
_addFuncIntUnknown("__lshift__", BOXED_INT, (void*)intLShiftInt, (void*)intLShift); _addFuncIntUnknown("__lshift__", BOXED_INT, (void*)intLShiftInt, (void*)intLShift);
_addFuncIntUnknown("__rshift__", BOXED_INT, (void*)intRShiftInt, (void*)intRShift); _addFuncIntUnknown("__rshift__", BOXED_INT, (void*)intRShiftInt, (void*)intRShift);
int_cls->giveAttr("__invert__", new BoxedFunction(boxRTFunction((void*)intInvert, BOXED_INT, 1, false))); int_cls->giveAttr("__invert__", new BoxedFunction(boxRTFunction((void*)intInvert, BOXED_INT, 1)));
int_cls->giveAttr("__pos__", new BoxedFunction(boxRTFunction((void*)intPos, BOXED_INT, 1, false))); int_cls->giveAttr("__pos__", new BoxedFunction(boxRTFunction((void*)intPos, BOXED_INT, 1)));
int_cls->giveAttr("__neg__", new BoxedFunction(boxRTFunction((void*)intNeg, BOXED_INT, 1, false))); int_cls->giveAttr("__neg__", new BoxedFunction(boxRTFunction((void*)intNeg, BOXED_INT, 1)));
int_cls->giveAttr("__nonzero__", new BoxedFunction(boxRTFunction((void*)intNonzero, BOXED_BOOL, 1, false))); int_cls->giveAttr("__nonzero__", new BoxedFunction(boxRTFunction((void*)intNonzero, BOXED_BOOL, 1)));
int_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)intRepr, STR, 1, false))); int_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)intRepr, STR, 1)));
int_cls->giveAttr("__str__", int_cls->getattr("__repr__")); int_cls->giveAttr("__str__", int_cls->getattr("__repr__"));
int_cls->giveAttr("__hash__", new BoxedFunction(boxRTFunction((void*)intHash, BOXED_INT, 1, false))); int_cls->giveAttr("__hash__", new BoxedFunction(boxRTFunction((void*)intHash, BOXED_INT, 1)));
int_cls->giveAttr("__divmod__", new BoxedFunction(boxRTFunction((void*)intDivmod, BOXED_TUPLE, 2, false))); int_cls->giveAttr("__divmod__", new BoxedFunction(boxRTFunction((void*)intDivmod, BOXED_TUPLE, 2)));
CLFunction* __new__ = boxRTFunction((void*)intNew1, NULL, 1, false); int_cls->giveAttr("__new__",
addRTFunction(__new__, (void*)intNew2, NULL, 2, false); new BoxedFunction(boxRTFunction((void*)intNew, BOXED_INT, 2, 1, false, false), { boxInt(0) }));
int_cls->giveAttr("__new__", new BoxedFunction(__new__));
CLFunction* __init__ = boxRTFunction((void*)intInit1, NULL, 1, false); int_cls->giveAttr("__init__",
addRTFunction(__init__, (void*)intInit2, NULL, 2, false); new BoxedFunction(boxRTFunction((void*)intInit, NONE, 2, 1, true, false), { boxInt(0) }));
int_cls->giveAttr("__init__", new BoxedFunction(__init__));
int_cls->freeze(); int_cls->freeze();
for (int i = 0; i < NUM_INTERNED_INTS; i++) {
interned_ints[i] = new BoxedInt(int_cls, i);
gc::registerStaticRootObj(interned_ints[i]);
}
} }
void teardownInt() { void teardownInt() {
......
...@@ -50,7 +50,8 @@ extern "C" Box* listNonzero(BoxedList* self) { ...@@ -50,7 +50,8 @@ extern "C" Box* listNonzero(BoxedList* self) {
return boxBool(self->size != 0); return boxBool(self->size != 0);
} }
extern "C" Box* listPop1(BoxedList* self) { extern "C" Box* listPop(BoxedList* self, Box* idx) {
if (idx == None) {
if (self->size == 0) { if (self->size == 0) {
raiseExcHelper(IndexError, "pop from empty list"); raiseExcHelper(IndexError, "pop from empty list");
} }
...@@ -58,9 +59,8 @@ extern "C" Box* listPop1(BoxedList* self) { ...@@ -58,9 +59,8 @@ extern "C" Box* listPop1(BoxedList* self) {
self->size--; self->size--;
Box* rtn = self->elts->elts[self->size]; Box* rtn = self->elts->elts[self->size];
return rtn; return rtn;
} }
extern "C" Box* listPop2(BoxedList* self, Box* idx) {
if (idx->cls != int_cls) { if (idx->cls != int_cls) {
raiseExcHelper(TypeError, "an integer is required"); raiseExcHelper(TypeError, "an integer is required");
} }
...@@ -417,13 +417,11 @@ extern "C" void listIteratorGCHandler(GCVisitor* v, void* p) { ...@@ -417,13 +417,11 @@ extern "C" void listIteratorGCHandler(GCVisitor* v, void* p) {
extern "C" const ObjectFlavor list_iterator_flavor(&listIteratorGCHandler, NULL); extern "C" const ObjectFlavor list_iterator_flavor(&listIteratorGCHandler, NULL);
extern "C" Box* listNew1(Box* cls) { extern "C" Box* listNew(Box* cls, Box* container) {
assert(cls == list_cls); assert(cls == list_cls);
return new BoxedList();
}
extern "C" Box* listNew2(Box* cls, Box* container) { if (container == None)
assert(cls == list_cls); return new BoxedList();
BoxedList* rtn = new BoxedList(); BoxedList* rtn = new BoxedList();
for (Box* e : container->pyElements()) { for (Box* e : container->pyElements()) {
...@@ -485,72 +483,67 @@ void setupList() { ...@@ -485,72 +483,67 @@ void setupList() {
list_cls->giveAttr("__name__", boxStrConstant("list")); list_cls->giveAttr("__name__", boxStrConstant("list"));
list_cls->giveAttr("__len__", new BoxedFunction(boxRTFunction((void*)listLen, BOXED_INT, 1, false))); list_cls->giveAttr("__len__", new BoxedFunction(boxRTFunction((void*)listLen, BOXED_INT, 1)));
CLFunction* getitem = createRTFunction(); CLFunction* getitem = createRTFunction(2, 0, 0, 0);
addRTFunction(getitem, (void*)listGetitemInt, NULL, std::vector<ConcreteCompilerType*>{ LIST, BOXED_INT }, false); addRTFunction(getitem, (void*)listGetitemInt, UNKNOWN, std::vector<ConcreteCompilerType*>{ LIST, BOXED_INT });
addRTFunction(getitem, (void*)listGetitemSlice, NULL, std::vector<ConcreteCompilerType*>{ LIST, SLICE }, false); addRTFunction(getitem, (void*)listGetitemSlice, LIST, std::vector<ConcreteCompilerType*>{ LIST, SLICE });
addRTFunction(getitem, (void*)listGetitem, NULL, std::vector<ConcreteCompilerType*>{ LIST, NULL }, false); addRTFunction(getitem, (void*)listGetitem, UNKNOWN, std::vector<ConcreteCompilerType*>{ LIST, UNKNOWN });
list_cls->giveAttr("__getitem__", new BoxedFunction(getitem)); list_cls->giveAttr("__getitem__", new BoxedFunction(getitem));
list_cls->giveAttr("__iter__", list_cls->giveAttr("__iter__",
new BoxedFunction(boxRTFunction((void*)listIter, typeFromClass(list_iterator_cls), 1, false))); new BoxedFunction(boxRTFunction((void*)listIter, typeFromClass(list_iterator_cls), 1)));
list_cls->giveAttr("__eq__", new BoxedFunction(boxRTFunction((void*)listEq, NULL, 2, false))); list_cls->giveAttr("__eq__", new BoxedFunction(boxRTFunction((void*)listEq, UNKNOWN, 2)));
list_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)listRepr, STR, 1, false))); list_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)listRepr, STR, 1)));
list_cls->giveAttr("__str__", list_cls->getattr("__repr__")); list_cls->giveAttr("__str__", list_cls->getattr("__repr__"));
list_cls->giveAttr("__nonzero__", new BoxedFunction(boxRTFunction((void*)listNonzero, BOXED_BOOL, 1, false))); list_cls->giveAttr("__nonzero__", new BoxedFunction(boxRTFunction((void*)listNonzero, BOXED_BOOL, 1)));
CLFunction* pop = boxRTFunction((void*)listPop1, NULL, 1, false); list_cls->giveAttr("pop", new BoxedFunction(boxRTFunction((void*)listPop, UNKNOWN, 2, 1, false, false), { None }));
addRTFunction(pop, (void*)listPop2, NULL, 2, false);
list_cls->giveAttr("pop", new BoxedFunction(pop));
list_cls->giveAttr("append", new BoxedFunction(boxRTFunction((void*)listAppend, NULL, 2, false))); list_cls->giveAttr("append", new BoxedFunction(boxRTFunction((void*)listAppend, NONE, 2)));
CLFunction* setitem = createRTFunction(); CLFunction* setitem = createRTFunction(3, 0, false, false);
addRTFunction(setitem, (void*)listSetitemInt, NULL, std::vector<ConcreteCompilerType*>{ LIST, BOXED_INT, NULL }, addRTFunction(setitem, (void*)listSetitemInt, NONE, std::vector<ConcreteCompilerType*>{ LIST, BOXED_INT, UNKNOWN });
false); addRTFunction(setitem, (void*)listSetitemSlice, NONE, std::vector<ConcreteCompilerType*>{ LIST, SLICE, UNKNOWN });
addRTFunction(setitem, (void*)listSetitemSlice, NULL, std::vector<ConcreteCompilerType*>{ LIST, SLICE, NULL }, addRTFunction(setitem, (void*)listSetitem, NONE, std::vector<ConcreteCompilerType*>{ LIST, UNKNOWN, UNKNOWN });
false);
addRTFunction(setitem, (void*)listSetitem, NULL, std::vector<ConcreteCompilerType*>{ LIST, NULL, NULL }, false);
list_cls->giveAttr("__setitem__", new BoxedFunction(setitem)); list_cls->giveAttr("__setitem__", new BoxedFunction(setitem));
CLFunction* delitem = createRTFunction(); CLFunction* delitem = createRTFunction(2, 0, false, false);
addRTFunction(delitem, (void*)listDelitemInt, NULL, std::vector<ConcreteCompilerType*>{ LIST, BOXED_INT }, false); addRTFunction(delitem, (void*)listDelitemInt, NONE, std::vector<ConcreteCompilerType*>{ LIST, BOXED_INT });
addRTFunction(delitem, (void*)listDelitemSlice, NULL, std::vector<ConcreteCompilerType*>{ LIST, SLICE }, false); addRTFunction(delitem, (void*)listDelitemSlice, NONE, std::vector<ConcreteCompilerType*>{ LIST, SLICE });
addRTFunction(delitem, (void*)listDelitem, NULL, std::vector<ConcreteCompilerType*>{ LIST, NULL }, false); addRTFunction(delitem, (void*)listDelitem, NONE, std::vector<ConcreteCompilerType*>{ LIST, UNKNOWN });
list_cls->giveAttr("__delitem__", new BoxedFunction(delitem)); list_cls->giveAttr("__delitem__", new BoxedFunction(delitem));
list_cls->giveAttr("insert", new BoxedFunction(boxRTFunction((void*)listInsert, NULL, 3, false))); list_cls->giveAttr("insert", new BoxedFunction(boxRTFunction((void*)listInsert, NONE, 3)));
list_cls->giveAttr("__mul__", new BoxedFunction(boxRTFunction((void*)listMul, NULL, 2, false))); list_cls->giveAttr("__mul__", new BoxedFunction(boxRTFunction((void*)listMul, NONE, 2)));
list_cls->giveAttr("__iadd__", new BoxedFunction(boxRTFunction((void*)listIAdd, NULL, 2, false))); list_cls->giveAttr("__iadd__", new BoxedFunction(boxRTFunction((void*)listIAdd, UNKNOWN, 2)));
list_cls->giveAttr("__add__", new BoxedFunction(boxRTFunction((void*)listAdd, NULL, 2, false))); list_cls->giveAttr("__add__", new BoxedFunction(boxRTFunction((void*)listAdd, UNKNOWN, 2)));
list_cls->giveAttr("sort", new BoxedFunction(boxRTFunction((void*)listSort1, NULL, 1, false))); list_cls->giveAttr("sort", new BoxedFunction(boxRTFunction((void*)listSort1, NONE, 1)));
list_cls->giveAttr("__contains__", new BoxedFunction(boxRTFunction((void*)listContains, BOXED_BOOL, 2, false))); list_cls->giveAttr("__contains__", new BoxedFunction(boxRTFunction((void*)listContains, BOXED_BOOL, 2)));
CLFunction* new_ = boxRTFunction((void*)listNew1, NULL, 1, false); list_cls->giveAttr("__new__",
addRTFunction(new_, (void*)listNew2, NULL, 2, false); new BoxedFunction(boxRTFunction((void*)listNew, UNKNOWN, 2, 1, false, false), { None }));
list_cls->giveAttr("__new__", new BoxedFunction(new_));
list_cls->giveAttr("count", new BoxedFunction(boxRTFunction((void*)listCount, BOXED_INT, 2, false))); list_cls->giveAttr("count", new BoxedFunction(boxRTFunction((void*)listCount, BOXED_INT, 2)));
list_cls->giveAttr("index", new BoxedFunction(boxRTFunction((void*)listIndex, NULL, 2, false))); list_cls->giveAttr("index", new BoxedFunction(boxRTFunction((void*)listIndex, BOXED_INT, 2)));
list_cls->giveAttr("remove", new BoxedFunction(boxRTFunction((void*)listRemove, NONE, 2, false))); list_cls->giveAttr("remove", new BoxedFunction(boxRTFunction((void*)listRemove, NONE, 2)));
list_cls->giveAttr("reverse", new BoxedFunction(boxRTFunction((void*)listReverse, NONE, 1, false))); list_cls->giveAttr("reverse", new BoxedFunction(boxRTFunction((void*)listReverse, NONE, 1)));
list_cls->freeze(); list_cls->freeze();
gc::registerStaticRootObj(list_iterator_cls); gc::registerStaticRootObj(list_iterator_cls);
list_iterator_cls->giveAttr("__name__", boxStrConstant("listiterator")); list_iterator_cls->giveAttr("__name__", boxStrConstant("listiterator"));
CLFunction* hasnext = boxRTFunction((void*)listiterHasnextUnboxed, BOOL, 1, false); CLFunction* hasnext = boxRTFunction((void*)listiterHasnextUnboxed, BOOL, 1);
addRTFunction(hasnext, (void*)listiterHasnext, BOXED_BOOL, 1, false); addRTFunction(hasnext, (void*)listiterHasnext, BOXED_BOOL);
list_iterator_cls->giveAttr("__hasnext__", new BoxedFunction(hasnext)); list_iterator_cls->giveAttr("__hasnext__", new BoxedFunction(hasnext));
list_iterator_cls->giveAttr( list_iterator_cls->giveAttr(
"__iter__", new BoxedFunction(boxRTFunction((void*)listIterIter, typeFromClass(list_iterator_cls), 1, false))); "__iter__", new BoxedFunction(boxRTFunction((void*)listIterIter, typeFromClass(list_iterator_cls), 1)));
list_iterator_cls->giveAttr("next", new BoxedFunction(boxRTFunction((void*)listiterNext, UNKNOWN, 1, false))); list_iterator_cls->giveAttr("next", new BoxedFunction(boxRTFunction((void*)listiterNext, UNKNOWN, 1)));
list_iterator_cls->freeze(); list_iterator_cls->freeze();
} }
......
...@@ -1575,298 +1575,338 @@ extern "C" Box* callattr(Box* obj, std::string* attr, bool clsonly, ArgPassSpec ...@@ -1575,298 +1575,338 @@ extern "C" Box* callattr(Box* obj, std::string* attr, bool clsonly, ArgPassSpec
return rtn; return rtn;
} }
CompiledFunction* resolveCLFunc(CLFunction* f, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3, Box** args, static inline Box*& getArg(int idx, Box*& arg1, Box*& arg2, Box*& arg3, Box** args) {
const std::vector<const std::string*>* keyword_names) { if (idx == 0)
RELEASE_ASSERT(!argspec.has_starargs, ""); return arg1;
RELEASE_ASSERT(!argspec.has_kwargs, ""); if (idx == 1)
RELEASE_ASSERT(argspec.num_keywords == 0, ""); return arg2;
if (idx == 2)
int64_t nargs = argspec.totalPassed(); return arg3;
return args[idx - 3];
}
static StatCounter slowpath_resolveclfunc("slowpath_resolveclfunc"); 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) {
/*
* Procedure:
* - First match up positional arguments; any extra go to varargs. error if too many.
* - Then apply keywords; any extra go to kwargs. error if too many.
* - Use defaults to fill in any missing
* - error about missing parameters
*/
static StatCounter slowpath_resolveclfunc("slowpath_callfunc");
slowpath_resolveclfunc.log(); slowpath_resolveclfunc.log();
CLFunction* f = func->f;
FunctionList& versions = f->versions; FunctionList& versions = f->versions;
for (int i = 0; i < versions.size(); i++) { int num_output_args = f->numReceivedArgs();
CompiledFunction* cf = versions[i];
FunctionSignature* sig = cf->sig;
assert(!sig->takes_kwargs && "not handled yet"); if (argspec.has_starargs || argspec.has_kwargs || f->takes_kwargs)
if (sig->rtn_type->llvmType() != UNKNOWN->llvmType()) rewrite_args = NULL;
continue;
if ((!sig->takes_varargs && sig->arg_types.size() != nargs)
|| (sig->takes_varargs && nargs < sig->arg_types.size()))
continue;
int nsig_args = sig->arg_types.size(); // These could be handled:
if (argspec.num_keywords)
rewrite_args = NULL;
if (nsig_args >= 1) { // TODO Should we guard on the CLFunction or the BoxedFunction?
if (sig->arg_types[0]->isFitBy(arg1->cls)) { // A single CLFunction could end up forming multiple BoxedFunctions, and we
// pass // 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.
bool guard_clfunc = false;
assert(!guard_clfunc && "I think there are users that expect the boxedfunction to be guarded");
RewriterVar r_defaults_array;
if (rewrite_args) {
if (!rewrite_args->func_guarded) {
if (guard_clfunc) {
rewrite_args->obj.addAttrGuard(offsetof(BoxedFunction, f), (intptr_t)f);
} else { } else {
continue; rewrite_args->obj.addGuard((intptr_t)func);
} }
} }
if (nsig_args >= 2) { if (guard_clfunc) {
if (sig->arg_types[1]->isFitBy(arg2->cls)) { // Have to save the defaults array since the object itself will probably get overwritten:
// pass rewrite_args->obj = rewrite_args->obj.move(-2);
} else { r_defaults_array = rewrite_args->obj.getAttr(offsetof(BoxedFunction, defaults), -2);
continue;
} }
} }
if (nsig_args >= 3) {
if (sig->arg_types[2]->isFitBy(arg3->cls)) { if (rewrite_args) {
// pass int num_passed = argspec.totalPassed();
if (num_passed >= 1)
rewrite_args->arg1 = rewrite_args->arg1.move(0);
if (num_passed >= 2)
rewrite_args->arg2 = rewrite_args->arg2.move(1);
if (num_passed >= 3)
rewrite_args->arg3 = rewrite_args->arg3.move(2);
if (num_passed >= 4)
rewrite_args->args = rewrite_args->args.move(3);
// We might have trouble if we have more output args than input args,
// such as if we need more space to pass defaults.
if (num_output_args > 3 && num_output_args > argspec.totalPassed()) {
int arg_bytes_required = (num_output_args - 3) * sizeof(Box*);
// Try to fit it in the scratch space
// TODO it should be a separate arg scratch space, esp once we switch this to rewriter2
if (arg_bytes_required > rewrite_args->rewriter->getScratchBytes()) {
// if it doesn't fit, just bail.
// TODO could try to rt_alloc some space maybe?
rewrite_args = NULL;
} else { } else {
continue; // Otherwise, use the scratch space for the arguments:
RewriterVar rbp = rewrite_args->rewriter->getRbp();
// This could just be a single LEA:
RewriterVar new_args = rbp.move(-1);
int rbp_offset = rewrite_args->rewriter->getScratchRbpOffset();
new_args = new_args.add(rbp_offset);
for (int i = 3; i < argspec.totalPassed(); i++) {
int offset = (i - 3) * sizeof(Box*);
RewriterVar old_arg = rewrite_args->args.getAttr(offset, -2);
new_args.setAttr(offset, old_arg);
} }
rewrite_args->args = new_args.move(3);
} }
bool bad = false;
for (int j = 3; j < nsig_args; j++) {
if (sig->arg_types[j]->isFitBy(args[j - 3]->cls)) {
// pass
} else {
bad = true;
break;
} }
} }
if (bad)
continue;
assert(cf);
assert(!cf->entry_descriptor);
assert(cf->is_interpreted == (cf->code == NULL));
return cf; std::vector<Box*> varargs;
if (argspec.has_starargs) {
Box* given_varargs = getArg(argspec.num_args + argspec.num_keywords, arg1, arg2, arg3, args);
for (Box* e : given_varargs->pyElements()) {
varargs.push_back(e);
} }
if (f->source == NULL) {
printf("Error: couldn't find suitable function version and no source to recompile!\n");
printf("%ld args:", nargs);
for (int i = 0; i < nargs; i++) {
if (i == 3) {
printf(" [and more]");
break;
} }
Box* firstargs[] = { arg1, arg2, arg3 }; // The "output" args that we will pass to the called function:
printf(" %s", getTypeName(firstargs[i])->c_str()); Box* oarg1 = NULL, *oarg2 = NULL, *oarg3 = NULL;
} Box** oargs = NULL;
printf("\n");
for (int j = 0; j < f->versions.size(); j++) {
std::string func_name = g.func_addr_registry.getFuncNameAtAddress(f->versions[j]->code, true);
printf("Version %d, %s:", j, func_name.c_str());
FunctionSignature* sig = f->versions[j]->sig;
for (int i = 0; i < sig->arg_types.size(); i++) {
printf(" %s", sig->arg_types[i]->debugName().c_str());
}
if (sig->takes_varargs)
printf(" *vararg");
if (sig->takes_kwargs)
printf(" *kwarg");
printf("\n");
// printf(" @%p %s\n", f->versions[j]->code, func_name.c_str());
}
abort();
}
assert(f->source->getArgsAST()->vararg.size() == 0); if (num_output_args > 3)
assert(f->source->getArgsAST()->kwarg.size() == 0); oargs = (Box**)alloca((num_output_args - 3) * sizeof(Box*));
assert(f->source->getArgsAST()->defaults.size() == 0);
bool takes_varargs = false;
bool takes_kwargs = false;
int ndefaults = 0;
std::vector<ConcreteCompilerType*> arg_types; ////
if (nargs >= 1) { // First, match up positional parameters to positional/varargs:
arg_types.push_back(typeFromClass(arg1->cls)); int positional_to_positional = std::min((int)argspec.num_args, f->num_args);
} for (int i = 0; i < positional_to_positional; i++) {
if (nargs >= 2) { getArg(i, oarg1, oarg2, oarg3, oargs) = getArg(i, arg1, arg2, arg3, args);
arg_types.push_back(typeFromClass(arg2->cls));
// we already moved the positional args into position
} }
if (nargs >= 3) {
arg_types.push_back(typeFromClass(arg3->cls)); int varargs_to_positional = std::min((int)varargs.size(), f->num_args - positional_to_positional);
for (int i = 0; i < varargs_to_positional; i++) {
assert(!rewrite_args && "would need to be handled here");
getArg(i + positional_to_positional, oarg1, oarg2, oarg3, oargs) = varargs[i];
} }
for (int j = 3; j < nargs; j++) {
arg_types.push_back(typeFromClass(args[j - 3]->cls)); std::vector<bool> params_filled(argspec.num_args, false);
for (int i = 0; i < positional_to_positional + varargs_to_positional; i++) {
params_filled[i] = true;
} }
FunctionSignature* sig
= new FunctionSignature(UNKNOWN, &f->source->getArgNames(), arg_types, ndefaults, takes_varargs, takes_kwargs);
EffortLevel::EffortLevel new_effort = initialEffort();
CompiledFunction* cf = compileFunction(f, sig, new_effort,
NULL); // this pushes the new CompiledVersion to the back of the version list
assert(cf->is_interpreted == (cf->code == NULL));
return cf; std::vector<Box*, StlCompatAllocator<Box*> > unused_positional;
} for (int i = positional_to_positional; i < argspec.num_args; i++) {
rewrite_args = NULL;
unused_positional.push_back(getArg(i, arg1, arg2, arg3, args));
}
for (int i = varargs_to_positional; i < varargs.size(); i++) {
rewrite_args = NULL;
unused_positional.push_back(varargs[i]);
}
Box* callCompiledFunc(CompiledFunction* cf, ArgPassSpec argspec, Box* iarg1, Box* iarg2, Box* iarg3, Box** iargs, if (f->takes_varargs) {
const std::vector<const std::string*>* keyword_names) { int varargs_idx = f->num_args;
RELEASE_ASSERT(!argspec.has_starargs, ""); if (rewrite_args) {
RELEASE_ASSERT(!argspec.has_kwargs, ""); assert(!unused_positional.size());
rewrite_args->rewriter->loadConst(varargs_idx, (intptr_t)EmptyTuple);
}
int64_t npassed_args = argspec.totalPassed(); Box* ovarargs = new BoxedTuple(std::move(unused_positional));
getArg(varargs_idx, oarg1, oarg2, oarg3, oargs) = ovarargs;
} else if (unused_positional.size()) {
raiseExcHelper(TypeError, "<function>() takes at most %d argument%s (%d given)", f->num_args,
(f->num_args == 1 ? "" : "s"), argspec.num_args + argspec.num_keywords + varargs.size());
}
assert(cf); ////
// Second, apply any keywords:
// TODO these shouldn't have to be initialized, but I don't want to issue a #pragma BoxedDict* okwargs = NULL;
// that disables the warning for the whole file: if (f->takes_kwargs) {
Box* oarg1 = NULL, *oarg2 = NULL, *oarg3 = NULL; assert(!rewrite_args && "would need to be handled here");
Box** oargs = NULL; okwargs = new BoxedDict();
getArg(f->num_args + (f->takes_varargs ? 1 : 0), oarg1, oarg2, oarg3, oargs) = okwargs;
}
int num_out_args = npassed_args; const std::vector<AST_expr*>* arg_names = f->getArgNames();
if (cf->sig->takes_varargs) if (arg_names == nullptr && argspec.num_keywords) {
num_out_args++; raiseExcHelper(TypeError, "<function>() doesn't take keyword arguments");
assert(!cf->sig->takes_kwargs);
if (cf->sig->takes_kwargs)
num_out_args++;
assert(!cf->sig->ndefaults);
num_out_args += cf->sig->ndefaults;
if (num_out_args > 3)
oargs = (Box**)alloca((num_out_args - 3) * sizeof(Box*));
int nsig_args = cf->sig->arg_types.size();
std::vector<bool> keywords_used(false, argspec.num_keywords);
// First, fill formal parameters from positional arguments:
for (int i = 0; i < std::min((int)argspec.num_args, nsig_args); i++) {
if (i == 0)
oarg1 = iarg1;
else if (i == 1)
oarg2 = iarg2;
else if (i == 2)
oarg3 = iarg3;
else
oargs[i - 3] = iargs[i - 3];
} }
// Then, fill any remaining formal parameters from keywords: if (argspec.num_keywords)
if (argspec.num_args < nsig_args) { assert(argspec.num_keywords == keyword_names->size());
const std::vector<AST_expr*>* arg_names = cf->sig->arg_names;
assert(arg_names);
assert(arg_names->size() == nsig_args);
for (int j = argspec.num_args; j < nsig_args; j++) { for (int i = 0; i < argspec.num_keywords; i++) {
assert((*arg_names)[j]->type == AST_TYPE::Name); // we should already have picked a good signature assert(!rewrite_args && "would need to be handled here");
const std::string& name = ast_cast<AST_Name>((*arg_names)[j])->id; int arg_idx = i + argspec.num_args;
Box* kw_val = getArg(arg_idx, arg1, arg2, arg3, args);
assert(arg_names);
bool found = false; bool found = false;
for (int i = 0; i < keyword_names->size(); i++) { for (int j = 0; j < arg_names->size(); j++) {
if (keywords_used[i]) AST_expr* e = (*arg_names)[j];
if (e->type != AST_TYPE::Name)
continue; continue;
if (*(*keyword_names)[i] == name) {
found = true;
keywords_used[i] = true;
int from_arg = argspec.num_args + i;
Box* arg;
if (from_arg == 0)
arg = iarg1;
else if (from_arg == 1)
arg = iarg2;
else if (from_arg == 2)
arg = iarg3;
else
arg = iargs[from_arg - 3];
if (j == 0)
oarg1 = arg;
else if (j == 1)
oarg2 = arg;
else if (j == 2)
oarg3 = arg;
else
oargs[j - 3] = arg;
AST_Name* n = ast_cast<AST_Name>(e);
if (n->id == *(*keyword_names)[i]) {
if (params_filled[j]) {
raiseExcHelper(TypeError, "<function>() got multiple values for keyword argument '%s'",
n->id.c_str());
}
getArg(j, oarg1, oarg2, oarg3, oargs) = kw_val;
params_filled[j] = true;
found = true;
break; break;
} }
} }
assert(found); // should have been disallowed
if (!found) {
if (okwargs) {
okwargs->d[boxString(*(*keyword_names)[i])] = kw_val;
} else {
raiseExcHelper(TypeError, "<function>() got an unexpected keyword argument '%s'",
(*keyword_names)[i]->c_str());
} }
} }
}
RELEASE_ASSERT(!argspec.has_kwargs, "need to copy the above");
assert(!cf->sig->takes_kwargs);
for (bool b : keywords_used)
assert(b);
if (cf->sig->takes_varargs) {
BoxedList* made_vararg = (BoxedList*)createList(); // Fill with defaults:
if (nsig_args == 0)
oarg1 = made_vararg; for (int i = 0; i < f->num_args - f->num_defaults; i++) {
else if (nsig_args == 1) if (params_filled[i])
oarg2 = made_vararg; continue;
else if (nsig_args == 2) // TODO not right error message
oarg3 = made_vararg; raiseExcHelper(TypeError, "<function>() did not get a value for positional argument %d", i);
else }
oargs[nsig_args - 3] = made_vararg;
for (int i = f->num_args - f->num_defaults; i < f->num_args; i++) {
assert(argspec.num_args == npassed_args); if (params_filled[i])
for (int i = nsig_args; i < npassed_args; i++) { continue;
if (i == 0)
listAppendInternal(made_vararg, iarg1); int default_idx = i + f->num_defaults - f->num_args;
else if (i == 1) Box* default_obj = func->defaults->elts[default_idx];
listAppendInternal(made_vararg, iarg2);
else if (i == 2) if (rewrite_args) {
listAppendInternal(made_vararg, iarg3); int offset = offsetof(std::remove_pointer<decltype(BoxedFunction::defaults)>::type, elts)
else + sizeof(Box*) * default_idx;
listAppendInternal(made_vararg, iargs[i - 3]); if (guard_clfunc) {
// If we just guarded on the CLFunction, then we have to emit assembly
// to fetch the values from the defaults array:
if (i < 3) {
r_defaults_array.getAttr(offset, i);
} else {
RewriterVar r_default = r_defaults_array.getAttr(offset, -3);
rewrite_args->args.setAttr((i - 3) * sizeof(Box*), r_default, false);
} }
} else { } else {
assert(!cf->sig->takes_kwargs); // If we guarded on the BoxedFunction, which has a constant set of defaults,
assert(nsig_args == npassed_args); // we can embed the default arguments directly into the instructions.
if (i < 3) {
rewrite_args->rewriter->loadConst(i, (intptr_t)default_obj);
} else {
RewriterVar r_default = rewrite_args->rewriter->loadConst(-1, (intptr_t)default_obj);
rewrite_args->args.setAttr((i - 3) * sizeof(Box*), r_default, false);
}
}
} }
if (!cf->is_interpreted) { getArg(i, oarg1, oarg2, oarg3, oargs) = default_obj;
return cf->call(oarg1, oarg2, oarg3, oargs);
} else {
return interpretFunction(cf->func, num_out_args, oarg1, oarg2, oarg3, oargs);
} }
}
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) {
int npassed_args = argspec.totalPassed();
CompiledFunction* cf = resolveCLFunc(func->f, argspec, arg1, arg2, arg3, args, keyword_names);
if (cf->sig->takes_varargs || cf->sig->takes_kwargs || argspec.num_keywords || argspec.has_starargs // Pick a specific version to use:
|| argspec.has_kwargs) {
if (rewrite_args && VERBOSITY()) CompiledFunction* chosen_cf = NULL;
printf("Not patchpointing this non-simple function call\n"); for (CompiledFunction* cf : f->versions) {
rewrite_args = NULL; assert(cf->spec->arg_types.size() == num_output_args);
if (cf->spec->rtn_type->llvmType() != UNKNOWN->llvmType())
continue;
bool works = true;
for (int i = 0; i < num_output_args; i++) {
Box* arg = getArg(i, oarg1, oarg2, oarg3, oargs);
ConcreteCompilerType* t = cf->spec->arg_types[i];
if ((arg && !t->isFitBy(arg->cls)) || (!arg && t != UNKNOWN)) {
works = false;
break;
}
} }
if (cf->is_interpreted)
rewrite_args = NULL;
if (rewrite_args) { if (!works)
// TODO should it be the func object or its CLFunction? continue;
if (!rewrite_args->func_guarded)
rewrite_args->obj.addGuard((intptr_t)func);
rewrite_args->rewriter->addDependenceOn(cf->dependent_callsites); chosen_cf = cf;
break;
}
if (npassed_args >= 1) if (chosen_cf == NULL) {
rewrite_args->arg1.move(0); if (f->source == NULL) {
if (npassed_args >= 2) // TODO I don't think this should be happening any more?
rewrite_args->arg2.move(1); printf("Error: couldn't find suitable function version and no source to recompile!\n");
if (npassed_args >= 3) abort();
rewrite_args->arg3.move(2);
if (npassed_args >= 4)
rewrite_args->args.move(3);
RewriterVar r_rtn = rewrite_args->rewriter->call(cf->code);
rewrite_args->out_rtn = r_rtn.move(-1);
} }
Box* rtn = callCompiledFunc(cf, argspec, arg1, arg2, arg3, args, keyword_names);
if (rewrite_args) std::vector<ConcreteCompilerType*> arg_types;
for (int i = 0; i < num_output_args; i++) {
Box* arg = getArg(i, oarg1, oarg2, oarg3, oargs);
assert(arg); // only builtin functions can pass NULL args
arg_types.push_back(typeFromClass(arg->cls));
}
FunctionSpecialization* spec = new FunctionSpecialization(UNKNOWN, arg_types);
EffortLevel::EffortLevel new_effort = initialEffort();
// this also pushes the new CompiledVersion to the back of the version list:
chosen_cf = compileFunction(f, spec, new_effort, NULL);
}
assert(chosen_cf->is_interpreted == (chosen_cf->code == NULL));
if (chosen_cf->is_interpreted) {
return interpretFunction(chosen_cf->func, num_output_args, oarg1, oarg2, oarg3, oargs);
} else {
if (rewrite_args) {
rewrite_args->rewriter->addDependenceOn(chosen_cf->dependent_callsites);
RewriterVar var = rewrite_args->rewriter->call((void*)chosen_cf->call);
rewrite_args->out_rtn = var;
rewrite_args->out_success = true; rewrite_args->out_success = true;
return rtn; }
return chosen_cf->call(oarg1, oarg2, oarg3, oargs);
}
} }
Box* runtimeCallInternal(Box* obj, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3, Box* runtimeCallInternal(Box* obj, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3,
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();
...@@ -1982,8 +2022,10 @@ extern "C" Box* runtimeCall(Box* obj, ArgPassSpec argspec, Box* arg1, Box* arg2, ...@@ -1982,8 +2022,10 @@ extern "C" Box* runtimeCall(Box* obj, ArgPassSpec argspec, Box* arg1, Box* arg2,
slowpath_runtimecall.log(); slowpath_runtimecall.log();
int num_orig_args = 2 + std::min(4, npassed_args); int num_orig_args = 2 + std::min(4, npassed_args);
if (argspec.num_keywords > 0) if (argspec.num_keywords > 0) {
assert(argspec.num_keywords == keyword_names->size());
num_orig_args++; num_orig_args++;
}
std::unique_ptr<Rewriter> rewriter(Rewriter::createRewriter( std::unique_ptr<Rewriter> rewriter(Rewriter::createRewriter(
__builtin_extract_return_addr(__builtin_return_address(0)), num_orig_args, 2, "runtimeCall")); __builtin_extract_return_addr(__builtin_return_address(0)), num_orig_args, 2, "runtimeCall"));
Box* rtn; Box* rtn;
......
...@@ -49,8 +49,7 @@ extern "C" BoxedString* strOrNull(Box* obj); // similar to str, but returns NUL ...@@ -49,8 +49,7 @@ extern "C" BoxedString* strOrNull(Box* obj); // similar to str, but returns NUL
extern "C" bool isinstance(Box* obj, Box* cls, int64_t flags); extern "C" bool isinstance(Box* obj, Box* cls, int64_t flags);
extern "C" BoxedInt* hash(Box* obj); extern "C" BoxedInt* hash(Box* obj);
// extern "C" Box* abs_(Box* obj); // extern "C" Box* abs_(Box* obj);
extern "C" Box* open1(Box* arg); Box* open(Box* arg1, Box* arg2);
extern "C" Box* open2(Box* arg1, Box* arg2);
// extern "C" Box* chr(Box* arg); // extern "C" Box* chr(Box* arg);
extern "C" Box* compare(Box*, Box*, int); extern "C" Box* compare(Box*, Box*, int);
extern "C" BoxedInt* len(Box* obj); extern "C" BoxedInt* len(Box* obj);
......
...@@ -89,13 +89,11 @@ Box* setAdd2(Box* _self, Box* b) { ...@@ -89,13 +89,11 @@ Box* setAdd2(Box* _self, Box* b) {
return None; return None;
} }
Box* setNew1(Box* cls) { Box* setNew(Box* cls, Box* container) {
assert(cls == set_cls); assert(cls == set_cls);
return new BoxedSet();
}
Box* setNew2(Box* cls, Box* container) { if (container == None)
assert(cls == set_cls); return new BoxedSet();
Box* rtn = new BoxedSet(); Box* rtn = new BoxedSet();
for (Box* e : container->pyElements()) { for (Box* e : container->pyElements()) {
...@@ -212,16 +210,15 @@ void setupSet() { ...@@ -212,16 +210,15 @@ void setupSet() {
set_iterator_cls = new BoxedClass(object_cls, 0, sizeof(BoxedSet), false); set_iterator_cls = new BoxedClass(object_cls, 0, sizeof(BoxedSet), false);
set_iterator_cls->giveAttr("__name__", boxStrConstant("setiterator")); set_iterator_cls->giveAttr("__name__", boxStrConstant("setiterator"));
set_iterator_cls->giveAttr("__hasnext__", set_iterator_cls->giveAttr("__hasnext__",
new BoxedFunction(boxRTFunction((void*)setiteratorHasnext, BOXED_BOOL, 1, false))); new BoxedFunction(boxRTFunction((void*)setiteratorHasnext, BOXED_BOOL, 1)));
set_iterator_cls->giveAttr("next", new BoxedFunction(boxRTFunction((void*)setiteratorNext, UNKNOWN, 1, false))); set_iterator_cls->giveAttr("next", new BoxedFunction(boxRTFunction((void*)setiteratorNext, UNKNOWN, 1)));
set_iterator_cls->freeze(); set_iterator_cls->freeze();
gc::registerStaticRootObj(set_iterator_cls); gc::registerStaticRootObj(set_iterator_cls);
CLFunction* new_ = boxRTFunction((void*)setNew1, SET, 1, false); set_cls->giveAttr("__new__",
addRTFunction(new_, (void*)setNew2, SET, 2, false); new BoxedFunction(boxRTFunction((void*)setNew, UNKNOWN, 2, 1, false, false), { None }));
set_cls->giveAttr("__new__", new BoxedFunction(new_));
Box* repr = new BoxedFunction(boxRTFunction((void*)setRepr, STR, 1, false)); Box* repr = new BoxedFunction(boxRTFunction((void*)setRepr, STR, 1));
set_cls->giveAttr("__repr__", repr); set_cls->giveAttr("__repr__", repr);
set_cls->giveAttr("__str__", repr); set_cls->giveAttr("__str__", repr);
...@@ -231,28 +228,27 @@ void setupSet() { ...@@ -231,28 +228,27 @@ void setupSet() {
v_su.push_back(SET); v_su.push_back(SET);
v_su.push_back(UNKNOWN); v_su.push_back(UNKNOWN);
CLFunction* or_ = createRTFunction(); CLFunction* or_ = createRTFunction(2, 0, false, false);
addRTFunction(or_, (void*)setOrSet, SET, v_ss, false); addRTFunction(or_, (void*)setOrSet, SET, v_ss);
set_cls->giveAttr("__or__", new BoxedFunction(or_)); set_cls->giveAttr("__or__", new BoxedFunction(or_));
CLFunction* sub_ = createRTFunction(); CLFunction* sub_ = createRTFunction(2, 0, false, false);
addRTFunction(sub_, (void*)setSubSet, SET, v_ss, false); addRTFunction(sub_, (void*)setSubSet, SET, v_ss);
set_cls->giveAttr("__sub__", new BoxedFunction(sub_)); set_cls->giveAttr("__sub__", new BoxedFunction(sub_));
CLFunction* xor_ = createRTFunction(); CLFunction* xor_ = createRTFunction(2, 0, false, false);
addRTFunction(xor_, (void*)setXorSet, SET, v_ss, false); addRTFunction(xor_, (void*)setXorSet, SET, v_ss);
set_cls->giveAttr("__xor__", new BoxedFunction(xor_)); set_cls->giveAttr("__xor__", new BoxedFunction(xor_));
CLFunction* and_ = createRTFunction(); CLFunction* and_ = createRTFunction(2, 0, false, false);
addRTFunction(and_, (void*)setAndSet, SET, v_ss, false); addRTFunction(and_, (void*)setAndSet, SET, v_ss);
set_cls->giveAttr("__and__", new BoxedFunction(and_)); set_cls->giveAttr("__and__", new BoxedFunction(and_));
set_cls->giveAttr("__iter__", set_cls->giveAttr("__iter__", new BoxedFunction(boxRTFunction((void*)setIter, typeFromClass(set_iterator_cls), 1)));
new BoxedFunction(boxRTFunction((void*)setIter, typeFromClass(set_iterator_cls), 1, false)));
set_cls->giveAttr("__len__", new BoxedFunction(boxRTFunction((void*)setLen, BOXED_INT, 1, false))); set_cls->giveAttr("__len__", new BoxedFunction(boxRTFunction((void*)setLen, BOXED_INT, 1)));
set_cls->giveAttr("add", new BoxedFunction(boxRTFunction((void*)setAdd, NONE, 2, false))); set_cls->giveAttr("add", new BoxedFunction(boxRTFunction((void*)setAdd, NONE, 2)));
set_cls->freeze(); set_cls->freeze();
} }
......
...@@ -293,12 +293,7 @@ extern "C" Box* strNonzero(BoxedString* self) { ...@@ -293,12 +293,7 @@ extern "C" Box* strNonzero(BoxedString* self) {
return boxBool(self->s.size() != 0); return boxBool(self->s.size() != 0);
} }
extern "C" Box* strNew1(BoxedClass* cls) { extern "C" Box* strNew(BoxedClass* cls, Box* obj) {
assert(cls == str_cls);
return boxStrConstant("");
}
extern "C" Box* strNew2(BoxedClass* cls, Box* obj) {
assert(cls == str_cls); assert(cls == str_cls);
return str(obj); return str(obj);
...@@ -354,9 +349,22 @@ Box* strJoin(BoxedString* self, Box* rhs) { ...@@ -354,9 +349,22 @@ Box* strJoin(BoxedString* self, Box* rhs) {
} }
} }
Box* strSplit1(BoxedString* self) { Box* strSplit(BoxedString* self, BoxedString* sep) {
assert(self->cls == str_cls); assert(self->cls == str_cls);
if (sep->cls == str_cls) {
if (!sep->s.empty()) {
llvm::SmallVector<llvm::StringRef, 16> parts;
llvm::StringRef(self->s).split(parts, sep->s);
BoxedList* rtn = new BoxedList();
for (const auto& s : parts)
listAppendInternal(rtn, boxString(s.str()));
return rtn;
} else {
raiseExcHelper(ValueError, "empty separator");
}
} else if (sep->cls == none_cls) {
BoxedList* rtn = new BoxedList(); BoxedList* rtn = new BoxedList();
std::ostringstream os(""); std::ostringstream os("");
...@@ -374,76 +382,42 @@ Box* strSplit1(BoxedString* self) { ...@@ -374,76 +382,42 @@ Box* strSplit1(BoxedString* self) {
listAppendInternal(rtn, boxString(os.str())); listAppendInternal(rtn, boxString(os.str()));
} }
return rtn; return rtn;
}
Box* strSplit2(BoxedString* self, BoxedString* sep) {
assert(self->cls == str_cls);
if (sep->cls == str_cls) {
if (!sep->s.empty()) {
llvm::SmallVector<llvm::StringRef, 16> parts;
llvm::StringRef(self->s).split(parts, sep->s);
BoxedList* rtn = new BoxedList();
for (const auto& s : parts)
listAppendInternal(rtn, boxString(s.str()));
return rtn;
} else {
raiseExcHelper(ValueError, "empty separator");
}
} else if (sep->cls == none_cls) {
return strSplit1(self);
} else { } else {
raiseExcHelper(TypeError, "expected a character buffer object"); raiseExcHelper(TypeError, "expected a character buffer object");
} }
} }
Box* strStrip1(BoxedString* self) { Box* strStrip(BoxedString* self, Box* chars) {
assert(self->cls == str_cls);
return new BoxedString(llvm::StringRef(self->s).trim(" \t\n\r\f\v"));
}
Box* strStrip2(BoxedString* self, Box* chars) {
assert(self->cls == str_cls); assert(self->cls == str_cls);
if (chars->cls == str_cls) { if (chars->cls == str_cls) {
return new BoxedString(llvm::StringRef(self->s).trim(static_cast<BoxedString*>(chars)->s)); return new BoxedString(llvm::StringRef(self->s).trim(static_cast<BoxedString*>(chars)->s));
} else if (chars->cls == none_cls) { } else if (chars->cls == none_cls) {
return strStrip1(self); return new BoxedString(llvm::StringRef(self->s).trim(" \t\n\r\f\v"));
} else { } else {
raiseExcHelper(TypeError, "strip arg must be None, str or unicode"); raiseExcHelper(TypeError, "strip arg must be None, str or unicode");
} }
} }
Box* strLStrip1(BoxedString* self) { Box* strLStrip(BoxedString* self, Box* chars) {
assert(self->cls == str_cls);
return new BoxedString(llvm::StringRef(self->s).ltrim(" \t\n\r\f\v"));
}
Box* strLStrip2(BoxedString* self, Box* chars) {
assert(self->cls == str_cls); assert(self->cls == str_cls);
if (chars->cls == str_cls) { if (chars->cls == str_cls) {
return new BoxedString(llvm::StringRef(self->s).ltrim(static_cast<BoxedString*>(chars)->s)); return new BoxedString(llvm::StringRef(self->s).ltrim(static_cast<BoxedString*>(chars)->s));
} else if (chars->cls == none_cls) { } else if (chars->cls == none_cls) {
return strLStrip1(self); return new BoxedString(llvm::StringRef(self->s).ltrim(" \t\n\r\f\v"));
} else { } else {
raiseExcHelper(TypeError, "lstrip arg must be None, str or unicode"); raiseExcHelper(TypeError, "lstrip arg must be None, str or unicode");
} }
} }
Box* strRStrip1(BoxedString* self) { Box* strRStrip(BoxedString* self, Box* chars) {
assert(self->cls == str_cls);
return new BoxedString(llvm::StringRef(self->s).rtrim(" \t\n\r\f\v"));
}
Box* strRStrip2(BoxedString* self, Box* chars) {
assert(self->cls == str_cls); assert(self->cls == str_cls);
if (chars->cls == str_cls) { if (chars->cls == str_cls) {
return new BoxedString(llvm::StringRef(self->s).rtrim(static_cast<BoxedString*>(chars)->s)); return new BoxedString(llvm::StringRef(self->s).rtrim(static_cast<BoxedString*>(chars)->s));
} else if (chars->cls == none_cls) { } else if (chars->cls == none_cls) {
return strRStrip1(self); return new BoxedString(llvm::StringRef(self->s).rtrim(" \t\n\r\f\v"));
} else { } else {
raiseExcHelper(TypeError, "rstrip arg must be None, str or unicode"); raiseExcHelper(TypeError, "rstrip arg must be None, str or unicode");
} }
...@@ -569,58 +543,47 @@ void setupStr() { ...@@ -569,58 +543,47 @@ void setupStr() {
gc::registerStaticRootObj(str_iterator_cls); gc::registerStaticRootObj(str_iterator_cls);
str_iterator_cls->giveAttr("__name__", boxStrConstant("striterator")); str_iterator_cls->giveAttr("__name__", boxStrConstant("striterator"));
str_iterator_cls->giveAttr("__hasnext__", str_iterator_cls->giveAttr("__hasnext__",
new BoxedFunction(boxRTFunction((void*)BoxedStringIterator::hasnext, NULL, 1, false))); new BoxedFunction(boxRTFunction((void*)BoxedStringIterator::hasnext, BOXED_BOOL, 1)));
str_iterator_cls->giveAttr("next", str_iterator_cls->giveAttr("next", new BoxedFunction(boxRTFunction((void*)BoxedStringIterator::next, STR, 1)));
new BoxedFunction(boxRTFunction((void*)BoxedStringIterator::next, STR, 1, false)));
str_iterator_cls->freeze(); str_iterator_cls->freeze();
str_cls->giveAttr("__name__", boxStrConstant("str")); str_cls->giveAttr("__name__", boxStrConstant("str"));
str_cls->giveAttr("__len__", new BoxedFunction(boxRTFunction((void*)strLen, NULL, 1, false))); str_cls->giveAttr("__len__", new BoxedFunction(boxRTFunction((void*)strLen, BOXED_INT, 1)));
str_cls->giveAttr("__str__", new BoxedFunction(boxRTFunction((void*)strStr, NULL, 1, false))); str_cls->giveAttr("__str__", new BoxedFunction(boxRTFunction((void*)strStr, STR, 1)));
str_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)strRepr, NULL, 1, false))); str_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)strRepr, STR, 1)));
str_cls->giveAttr("__hash__", new BoxedFunction(boxRTFunction((void*)strHash, NULL, 1, false))); str_cls->giveAttr("__hash__", new BoxedFunction(boxRTFunction((void*)strHash, BOXED_INT, 1)));
str_cls->giveAttr("__nonzero__", new BoxedFunction(boxRTFunction((void*)strNonzero, NULL, 1, false))); str_cls->giveAttr("__nonzero__", new BoxedFunction(boxRTFunction((void*)strNonzero, BOXED_BOOL, 1)));
str_cls->giveAttr("lower", new BoxedFunction(boxRTFunction((void*)strLower, STR, 1, false))); str_cls->giveAttr("lower", new BoxedFunction(boxRTFunction((void*)strLower, STR, 1)));
CLFunction* strStrip = boxRTFunction((void*)strStrip1, STR, 1, false); str_cls->giveAttr("strip", new BoxedFunction(boxRTFunction((void*)strStrip, STR, 2, 1, false, false), { None }));
addRTFunction(strStrip, (void*)strStrip2, STR, 2, false);
str_cls->giveAttr("strip", new BoxedFunction(strStrip));
CLFunction* strLStrip = boxRTFunction((void*)strLStrip1, STR, 1, false); str_cls->giveAttr("lstrip", new BoxedFunction(boxRTFunction((void*)strLStrip, STR, 2, 1, false, false), { None }));
addRTFunction(strLStrip, (void*)strLStrip2, STR, 2, false);
str_cls->giveAttr("lstrip", new BoxedFunction(strLStrip));
CLFunction* strRStrip = boxRTFunction((void*)strRStrip1, STR, 1, false); str_cls->giveAttr("rstrip", new BoxedFunction(boxRTFunction((void*)strRStrip, STR, 2, 1, false, false), { None }));
addRTFunction(strRStrip, (void*)strRStrip2, STR, 2, false);
str_cls->giveAttr("rstrip", new BoxedFunction(strRStrip));
str_cls->giveAttr("__contains__", new BoxedFunction(boxRTFunction((void*)strContains, BOXED_BOOL, 2, false))); str_cls->giveAttr("__contains__", new BoxedFunction(boxRTFunction((void*)strContains, BOXED_BOOL, 2)));
str_cls->giveAttr("__add__", new BoxedFunction(boxRTFunction((void*)strAdd, NULL, 2, false))); str_cls->giveAttr("__add__", new BoxedFunction(boxRTFunction((void*)strAdd, UNKNOWN, 2)));
str_cls->giveAttr("__mod__", new BoxedFunction(boxRTFunction((void*)strMod, NULL, 2, false))); str_cls->giveAttr("__mod__", new BoxedFunction(boxRTFunction((void*)strMod, STR, 2)));
str_cls->giveAttr("__mul__", new BoxedFunction(boxRTFunction((void*)strMul, NULL, 2, false))); str_cls->giveAttr("__mul__", new BoxedFunction(boxRTFunction((void*)strMul, UNKNOWN, 2)));
str_cls->giveAttr("__eq__", new BoxedFunction(boxRTFunction((void*)strEq, NULL, 2, false))); str_cls->giveAttr("__eq__", new BoxedFunction(boxRTFunction((void*)strEq, UNKNOWN, 2)));
str_cls->giveAttr("__getitem__", new BoxedFunction(boxRTFunction((void*)strGetitem, NULL, 2, false))); str_cls->giveAttr("__getitem__", new BoxedFunction(boxRTFunction((void*)strGetitem, STR, 2)));
str_cls->giveAttr("__iter__", str_cls->giveAttr("__iter__", new BoxedFunction(boxRTFunction((void*)strIter, typeFromClass(str_iterator_cls), 1)));
new BoxedFunction(boxRTFunction((void*)strIter, typeFromClass(str_iterator_cls), 1, false)));
str_cls->giveAttr("join", new BoxedFunction(boxRTFunction((void*)strJoin, NULL, 2, false))); str_cls->giveAttr("join", new BoxedFunction(boxRTFunction((void*)strJoin, STR, 2)));
CLFunction* strSplit = boxRTFunction((void*)strSplit1, LIST, 1, false); str_cls->giveAttr("split", new BoxedFunction(boxRTFunction((void*)strSplit, LIST, 2, 1, false, false), { None }));
addRTFunction(strSplit, (void*)strSplit2, LIST, 2, false);
str_cls->giveAttr("split", new BoxedFunction(strSplit));
str_cls->giveAttr("rsplit", str_cls->getattr("split")); str_cls->giveAttr("rsplit", str_cls->getattr("split"));
CLFunction* count = boxRTFunction((void*)strCount2Unboxed, INT, 2, false); CLFunction* count = boxRTFunction((void*)strCount2Unboxed, INT, 2);
addRTFunction(count, (void*)strCount2, BOXED_INT, 2, false); addRTFunction(count, (void*)strCount2, BOXED_INT);
str_cls->giveAttr("count", new BoxedFunction(count)); str_cls->giveAttr("count", new BoxedFunction(count));
CLFunction* __new__ = boxRTFunction((void*)strNew1, NULL, 1, false); str_cls->giveAttr("__new__", new BoxedFunction(boxRTFunction((void*)strNew, UNKNOWN, 2, 1, false, false),
addRTFunction(__new__, (void*)strNew2, NULL, 2, false); { boxStrConstant("") }));
str_cls->giveAttr("__new__", new BoxedFunction(__new__));
str_cls->freeze(); str_cls->freeze();
} }
......
...@@ -205,23 +205,23 @@ void setupTuple() { ...@@ -205,23 +205,23 @@ void setupTuple() {
tuple_cls->giveAttr("__name__", boxStrConstant("tuple")); tuple_cls->giveAttr("__name__", boxStrConstant("tuple"));
tuple_cls->giveAttr("__getitem__", new BoxedFunction(boxRTFunction((void*)tupleGetitem, NULL, 2, false))); tuple_cls->giveAttr("__getitem__", new BoxedFunction(boxRTFunction((void*)tupleGetitem, UNKNOWN, 2)));
tuple_cls->giveAttr("__contains__", new BoxedFunction(boxRTFunction((void*)tupleContains, NULL, 2, false))); tuple_cls->giveAttr("__contains__", new BoxedFunction(boxRTFunction((void*)tupleContains, BOXED_BOOL, 2)));
tuple_cls->giveAttr( tuple_cls->giveAttr("__iter__",
"__iter__", new BoxedFunction(boxRTFunction((void*)tupleIter, typeFromClass(tuple_iterator_cls), 1, false))); new BoxedFunction(boxRTFunction((void*)tupleIter, typeFromClass(tuple_iterator_cls), 1)));
tuple_cls->giveAttr("__lt__", new BoxedFunction(boxRTFunction((void*)tupleLt, NULL, 2, false))); tuple_cls->giveAttr("__lt__", new BoxedFunction(boxRTFunction((void*)tupleLt, UNKNOWN, 2)));
tuple_cls->giveAttr("__le__", new BoxedFunction(boxRTFunction((void*)tupleLe, NULL, 2, false))); tuple_cls->giveAttr("__le__", new BoxedFunction(boxRTFunction((void*)tupleLe, UNKNOWN, 2)));
tuple_cls->giveAttr("__gt__", new BoxedFunction(boxRTFunction((void*)tupleGt, NULL, 2, false))); tuple_cls->giveAttr("__gt__", new BoxedFunction(boxRTFunction((void*)tupleGt, UNKNOWN, 2)));
tuple_cls->giveAttr("__ge__", new BoxedFunction(boxRTFunction((void*)tupleGe, NULL, 2, false))); tuple_cls->giveAttr("__ge__", new BoxedFunction(boxRTFunction((void*)tupleGe, UNKNOWN, 2)));
tuple_cls->giveAttr("__eq__", new BoxedFunction(boxRTFunction((void*)tupleEq, NULL, 2, false))); tuple_cls->giveAttr("__eq__", new BoxedFunction(boxRTFunction((void*)tupleEq, UNKNOWN, 2)));
tuple_cls->giveAttr("__ne__", new BoxedFunction(boxRTFunction((void*)tupleNe, NULL, 2, false))); tuple_cls->giveAttr("__ne__", new BoxedFunction(boxRTFunction((void*)tupleNe, UNKNOWN, 2)));
tuple_cls->giveAttr("__hash__", new BoxedFunction(boxRTFunction((void*)tupleHash, BOXED_INT, 1, false))); tuple_cls->giveAttr("__hash__", new BoxedFunction(boxRTFunction((void*)tupleHash, BOXED_INT, 1)));
tuple_cls->giveAttr("__len__", new BoxedFunction(boxRTFunction((void*)tupleLen, NULL, 1, false))); tuple_cls->giveAttr("__len__", new BoxedFunction(boxRTFunction((void*)tupleLen, BOXED_INT, 1)));
tuple_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)tupleRepr, NULL, 1, false))); tuple_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)tupleRepr, STR, 1)));
tuple_cls->giveAttr("__str__", tuple_cls->getattr("__repr__")); tuple_cls->giveAttr("__str__", tuple_cls->getattr("__repr__"));
tuple_cls->freeze(); tuple_cls->freeze();
...@@ -229,12 +229,12 @@ void setupTuple() { ...@@ -229,12 +229,12 @@ void setupTuple() {
gc::registerStaticRootObj(tuple_iterator_cls); gc::registerStaticRootObj(tuple_iterator_cls);
tuple_iterator_cls->giveAttr("__name__", boxStrConstant("tupleiterator")); tuple_iterator_cls->giveAttr("__name__", boxStrConstant("tupleiterator"));
CLFunction* hasnext = boxRTFunction((void*)tupleiterHasnextUnboxed, BOOL, 1, false); CLFunction* hasnext = boxRTFunction((void*)tupleiterHasnextUnboxed, BOOL, 1);
addRTFunction(hasnext, (void*)tupleiterHasnext, BOXED_BOOL, 1, false); addRTFunction(hasnext, (void*)tupleiterHasnext, BOXED_BOOL);
tuple_iterator_cls->giveAttr("__hasnext__", new BoxedFunction(hasnext)); tuple_iterator_cls->giveAttr("__hasnext__", new BoxedFunction(hasnext));
tuple_iterator_cls->giveAttr("__iter__", new BoxedFunction(boxRTFunction( tuple_iterator_cls->giveAttr(
(void*)tupleIterIter, typeFromClass(tuple_iterator_cls), 1, false))); "__iter__", new BoxedFunction(boxRTFunction((void*)tupleIterIter, typeFromClass(tuple_iterator_cls), 1)));
tuple_iterator_cls->giveAttr("next", new BoxedFunction(boxRTFunction((void*)tupleiterNext, UNKNOWN, 1, false))); tuple_iterator_cls->giveAttr("next", new BoxedFunction(boxRTFunction((void*)tupleiterNext, UNKNOWN, 1)));
tuple_iterator_cls->freeze(); tuple_iterator_cls->freeze();
} }
......
...@@ -64,7 +64,8 @@ llvm::iterator_range<BoxIterator> Box::pyElements() { ...@@ -64,7 +64,8 @@ llvm::iterator_range<BoxIterator> Box::pyElements() {
raiseExcHelper(TypeError, "'%s' object is not iterable", getTypeName(this)->c_str()); raiseExcHelper(TypeError, "'%s' object is not iterable", getTypeName(this)->c_str());
} }
extern "C" BoxedFunction::BoxedFunction(CLFunction* f) : Box(&function_flavor, function_cls), f(f) { extern "C" BoxedFunction::BoxedFunction(CLFunction* f)
: Box(&function_flavor, function_cls), f(f), ndefaults(0), defaults(NULL) {
if (f->source) { if (f->source) {
assert(f->source->ast); assert(f->source->ast);
// this->giveAttr("__name__", boxString(&f->source->ast->name)); // this->giveAttr("__name__", boxString(&f->source->ast->name));
...@@ -73,6 +74,45 @@ extern "C" BoxedFunction::BoxedFunction(CLFunction* f) : Box(&function_flavor, f ...@@ -73,6 +74,45 @@ extern "C" BoxedFunction::BoxedFunction(CLFunction* f) : Box(&function_flavor, f
Box* modname = f->source->parent_module->getattr("__name__", NULL, NULL); Box* modname = f->source->parent_module->getattr("__name__", NULL, NULL);
this->giveAttr("__module__", modname); this->giveAttr("__module__", modname);
} }
assert(f->num_defaults == ndefaults);
}
extern "C" BoxedFunction::BoxedFunction(CLFunction* f, std::initializer_list<Box*> defaults)
: Box(&function_flavor, function_cls), f(f), ndefaults(0), defaults(NULL) {
// make sure to initialize defaults first, since the GC behavior is triggered by ndefaults,
// and a GC can happen within this constructor:
this->defaults = new (defaults.size()) GCdArray();
memcpy(this->defaults->elts, defaults.begin(), defaults.size() * sizeof(Box*));
this->ndefaults = defaults.size();
if (f->source) {
assert(f->source->ast);
// this->giveAttr("__name__", boxString(&f->source->ast->name));
this->giveAttr("__name__", boxString(f->source->getName()));
Box* modname = f->source->parent_module->getattr("__name__", NULL, NULL);
this->giveAttr("__module__", modname);
}
assert(f->num_defaults == ndefaults);
}
// This probably belongs in dict.cpp?
extern "C" void functionGCHandler(GCVisitor* v, void* p) {
boxGCHandler(v, p);
BoxedFunction* f = (BoxedFunction*)p;
// 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
if (f->ndefaults) {
assert(f->defaults);
v->visit(f->defaults);
// do a conservative scan since there can be NULLs in there:
v->visitPotentialRange(reinterpret_cast<void* const*>(&f->defaults[0]),
reinterpret_cast<void* const*>(&f->defaults[f->ndefaults]));
}
} }
BoxedModule::BoxedModule(const std::string& name, const std::string& fn) : Box(&module_flavor, module_cls), fn(fn) { BoxedModule::BoxedModule(const std::string& name, const std::string& fn) : Box(&module_flavor, module_cls), fn(fn) {
...@@ -216,7 +256,7 @@ const ObjectFlavor bool_flavor(&boxGCHandler, NULL); ...@@ -216,7 +256,7 @@ const ObjectFlavor bool_flavor(&boxGCHandler, NULL);
const ObjectFlavor int_flavor(&boxGCHandler, NULL); const ObjectFlavor int_flavor(&boxGCHandler, NULL);
const ObjectFlavor float_flavor(&boxGCHandler, NULL); const ObjectFlavor float_flavor(&boxGCHandler, NULL);
const ObjectFlavor str_flavor(&boxGCHandler, NULL); const ObjectFlavor str_flavor(&boxGCHandler, NULL);
const ObjectFlavor function_flavor(&boxGCHandler, NULL); const ObjectFlavor function_flavor(&functionGCHandler, NULL);
const ObjectFlavor instancemethod_flavor(&instancemethodGCHandler, NULL); const ObjectFlavor instancemethod_flavor(&instancemethodGCHandler, NULL);
const ObjectFlavor list_flavor(&listGCHandler, NULL); const ObjectFlavor list_flavor(&listGCHandler, NULL);
const ObjectFlavor slice_flavor(&sliceGCHandler, NULL); const ObjectFlavor slice_flavor(&sliceGCHandler, NULL);
...@@ -229,6 +269,8 @@ const ObjectFlavor member_flavor(&boxGCHandler, NULL); ...@@ -229,6 +269,8 @@ const ObjectFlavor member_flavor(&boxGCHandler, NULL);
const AllocationKind untracked_kind(NULL, NULL); const AllocationKind untracked_kind(NULL, NULL);
const AllocationKind hc_kind(&hcGCHandler, NULL); const AllocationKind hc_kind(&hcGCHandler, NULL);
const AllocationKind conservative_kind(&conservativeGCHandler, NULL); const AllocationKind conservative_kind(&conservativeGCHandler, NULL);
BoxedTuple* EmptyTuple;
} }
extern "C" Box* createUserClass(std::string* name, Box* _base, BoxedModule* parent_module) { extern "C" Box* createUserClass(std::string* name, Box* _base, BoxedModule* parent_module) {
...@@ -314,19 +356,12 @@ extern "C" Box* createSlice(Box* start, Box* stop, Box* step) { ...@@ -314,19 +356,12 @@ extern "C" Box* createSlice(Box* start, Box* stop, Box* step) {
return rtn; return rtn;
} }
extern "C" Box* sliceNew2(Box* cls, Box* stop) { extern "C" Box* sliceNew(Box* cls, Box* start, Box* stop, Box** args) {
assert(cls == slice_cls); RELEASE_ASSERT(cls == slice_cls, "");
return createSlice(None, stop, None);
}
extern "C" Box* sliceNew3(Box* cls, Box* start, Box* stop) {
assert(cls == slice_cls);
return createSlice(start, stop, None);
}
extern "C" Box* sliceNew4(Box* cls, Box* start, Box* stop, Box** args) {
assert(cls == slice_cls);
Box* step = args[0]; Box* step = args[0];
if (stop == NULL)
return createSlice(None, start, None);
return createSlice(start, stop, step); return createSlice(start, stop, step);
} }
...@@ -389,24 +424,21 @@ CLFunction* unboxRTFunction(Box* b) { ...@@ -389,24 +424,21 @@ CLFunction* unboxRTFunction(Box* b) {
return static_cast<BoxedFunction*>(b)->f; return static_cast<BoxedFunction*>(b)->f;
} }
Box* objectNew1(BoxedClass* cls) { Box* objectNew(BoxedClass* cls, BoxedTuple* args) {
assert(cls->instance_size >= sizeof(Box));
void* mem = rt_alloc(cls->instance_size);
Box* rtn = ::new (mem) Box(&object_flavor, cls);
initUserAttrs(rtn, cls);
return rtn;
}
Box* objectNew(BoxedClass* cls, BoxedList* args) {
assert(isSubclass(cls->cls, type_cls)); assert(isSubclass(cls->cls, type_cls));
assert(args->cls == tuple_cls);
if (args->size != 0) { if (args->elts.size() != 0) {
if (typeLookup(cls, "__init__", NULL, NULL) == NULL) if (typeLookup(cls, "__init__", NULL, NULL) == NULL)
raiseExcHelper(TypeError, "object.__new__() takes no parameters"); raiseExcHelper(TypeError, "object.__new__() takes no parameters");
} }
return objectNew1(cls); assert(cls->instance_size >= sizeof(Box));
void* mem = rt_alloc(cls->instance_size);
Box* rtn = ::new (mem) Box(&object_flavor, cls);
initUserAttrs(rtn, cls);
return rtn;
} }
bool TRACK_ALLOCATIONS = false; bool TRACK_ALLOCATIONS = false;
...@@ -430,6 +462,11 @@ void setupRuntime() { ...@@ -430,6 +462,11 @@ void setupRuntime() {
object_cls->giveAttr("__base__", None); object_cls->giveAttr("__base__", None);
tuple_cls = new BoxedClass(object_cls, 0, sizeof(BoxedTuple), false);
EmptyTuple = new BoxedTuple({});
gc::registerStaticRootObj(EmptyTuple);
module_cls = new BoxedClass(object_cls, offsetof(BoxedModule, attrs), sizeof(BoxedModule), false); module_cls = new BoxedClass(object_cls, offsetof(BoxedModule, attrs), sizeof(BoxedModule), false);
// TODO it'd be nice to be able to do these in the respective setupType methods, // TODO it'd be nice to be able to do these in the respective setupType methods,
...@@ -443,7 +480,6 @@ void setupRuntime() { ...@@ -443,7 +480,6 @@ void setupRuntime() {
list_cls = new BoxedClass(object_cls, 0, sizeof(BoxedList), false); list_cls = new BoxedClass(object_cls, 0, sizeof(BoxedList), false);
slice_cls = new BoxedClass(object_cls, 0, sizeof(BoxedSlice), false); slice_cls = new BoxedClass(object_cls, 0, sizeof(BoxedSlice), false);
dict_cls = new BoxedClass(object_cls, 0, sizeof(BoxedDict), false); dict_cls = new BoxedClass(object_cls, 0, sizeof(BoxedDict), false);
tuple_cls = new BoxedClass(object_cls, 0, sizeof(BoxedTuple), false);
file_cls = new BoxedClass(object_cls, 0, sizeof(BoxedFile), false); file_cls = new BoxedClass(object_cls, 0, sizeof(BoxedFile), false);
set_cls = new BoxedClass(object_cls, 0, sizeof(BoxedSet), false); set_cls = new BoxedClass(object_cls, 0, sizeof(BoxedSet), false);
member_cls = new BoxedClass(object_cls, 0, sizeof(BoxedMemberDescriptor), false); member_cls = new BoxedClass(object_cls, 0, sizeof(BoxedMemberDescriptor), false);
...@@ -461,29 +497,27 @@ void setupRuntime() { ...@@ -461,29 +497,27 @@ void setupRuntime() {
BOXED_TUPLE = typeFromClass(tuple_cls); BOXED_TUPLE = typeFromClass(tuple_cls);
object_cls->giveAttr("__name__", boxStrConstant("object")); object_cls->giveAttr("__name__", boxStrConstant("object"));
auto object_new = boxRTFunction((void*)objectNew1, NULL, 1, false); object_cls->giveAttr("__new__", new BoxedFunction(boxRTFunction((void*)objectNew, UNKNOWN, 1, 0, true, false)));
addRTFunction(object_new, (void*)objectNew, NULL, 1, true);
object_cls->giveAttr("__new__", new BoxedFunction(object_new));
object_cls->freeze(); object_cls->freeze();
auto typeCallObj = boxRTFunction((void*)typeCall, NULL, 1, true); auto typeCallObj = boxRTFunction((void*)typeCall, UNKNOWN, 1, 0, true, false);
typeCallObj->internal_callable = &typeCallInternal; typeCallObj->internal_callable = &typeCallInternal;
type_cls->giveAttr("__call__", new BoxedFunction(typeCallObj)); type_cls->giveAttr("__call__", new BoxedFunction(typeCallObj));
type_cls->giveAttr("__name__", boxStrConstant("type")); type_cls->giveAttr("__name__", boxStrConstant("type"));
type_cls->giveAttr("__new__", new BoxedFunction(boxRTFunction((void*)typeNew, NULL, 2, true))); type_cls->giveAttr("__new__", new BoxedFunction(boxRTFunction((void*)typeNew, UNKNOWN, 2)));
type_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)typeRepr, NULL, 1, true))); type_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)typeRepr, STR, 1)));
type_cls->giveAttr("__str__", type_cls->getattr("__repr__")); type_cls->giveAttr("__str__", type_cls->getattr("__repr__"));
type_cls->freeze(); type_cls->freeze();
none_cls->giveAttr("__name__", boxStrConstant("NoneType")); none_cls->giveAttr("__name__", boxStrConstant("NoneType"));
none_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)noneRepr, NULL, 1, false))); none_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)noneRepr, STR, 1)));
none_cls->giveAttr("__str__", none_cls->getattr("__repr__")); none_cls->giveAttr("__str__", none_cls->getattr("__repr__"));
none_cls->giveAttr("__hash__", new BoxedFunction(boxRTFunction((void*)noneHash, NULL, 1, false))); none_cls->giveAttr("__hash__", new BoxedFunction(boxRTFunction((void*)noneHash, UNKNOWN, 1)));
none_cls->freeze(); none_cls->freeze();
module_cls->giveAttr("__name__", boxStrConstant("module")); module_cls->giveAttr("__name__", boxStrConstant("module"));
module_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)moduleRepr, NULL, 1, false))); module_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)moduleRepr, STR, 1)));
module_cls->giveAttr("__str__", module_cls->getattr("__repr__")); module_cls->giveAttr("__str__", module_cls->getattr("__repr__"));
module_cls->freeze(); module_cls->freeze();
...@@ -501,21 +535,18 @@ void setupRuntime() { ...@@ -501,21 +535,18 @@ void setupRuntime() {
setupFile(); setupFile();
function_cls->giveAttr("__name__", boxStrConstant("function")); function_cls->giveAttr("__name__", boxStrConstant("function"));
function_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)functionRepr, NULL, 1, false))); function_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)functionRepr, STR, 1)));
function_cls->giveAttr("__str__", function_cls->getattr("__repr__")); function_cls->giveAttr("__str__", function_cls->getattr("__repr__"));
function_cls->freeze(); function_cls->freeze();
instancemethod_cls->giveAttr("__name__", boxStrConstant("instancemethod")); instancemethod_cls->giveAttr("__name__", boxStrConstant("instancemethod"));
instancemethod_cls->giveAttr("__repr__", instancemethod_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)instancemethodRepr, STR, 1)));
new BoxedFunction(boxRTFunction((void*)instancemethodRepr, NULL, 1, true)));
instancemethod_cls->freeze(); instancemethod_cls->freeze();
slice_cls->giveAttr("__name__", boxStrConstant("slice")); slice_cls->giveAttr("__name__", boxStrConstant("slice"));
CLFunction* slice_new = boxRTFunction((void*)sliceNew2, NULL, 2, false); slice_cls->giveAttr("__new__",
addRTFunction(slice_new, (void*)sliceNew3, NULL, 3, false); new BoxedFunction(boxRTFunction((void*)sliceNew, UNKNOWN, 4, 2, false, false), { NULL, None }));
addRTFunction(slice_new, (void*)sliceNew4, NULL, 4, false); slice_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)sliceRepr, STR, 1)));
slice_cls->giveAttr("__new__", new BoxedFunction(slice_new));
slice_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)sliceRepr, NULL, 1, true)));
slice_cls->giveAttr("__str__", slice_cls->getattr("__repr__")); slice_cls->giveAttr("__str__", slice_cls->getattr("__repr__"));
slice_cls->giveAttr("start", new BoxedMemberDescriptor(BoxedMemberDescriptor::OBJECT, SLICE_START_OFFSET)); slice_cls->giveAttr("start", new BoxedMemberDescriptor(BoxedMemberDescriptor::OBJECT, SLICE_START_OFFSET));
slice_cls->giveAttr("stop", new BoxedMemberDescriptor(BoxedMemberDescriptor::OBJECT, SLICE_STOP_OFFSET)); slice_cls->giveAttr("stop", new BoxedMemberDescriptor(BoxedMemberDescriptor::OBJECT, SLICE_STOP_OFFSET));
......
...@@ -196,21 +196,26 @@ public: ...@@ -196,21 +196,26 @@ public:
: Box(&instancemethod_flavor, instancemethod_cls), obj(obj), func(func) {} : Box(&instancemethod_flavor, instancemethod_cls), obj(obj), func(func) {}
}; };
class BoxedList : public Box { class GCdArray : public GCObject {
public: public:
class ElementArray : public GCObject {
public:
Box* elts[0]; Box* elts[0];
ElementArray() : GCObject(&untracked_kind) {} GCdArray() : GCObject(&untracked_kind) {}
void* operator new(size_t size, int capacity) { void* operator new(size_t size, int capacity) {
return rt_alloc(capacity * sizeof(Box*) + sizeof(BoxedList::ElementArray)); assert(size == sizeof(GCdArray));
return rt_alloc(capacity * sizeof(Box*) + size);
}
static GCdArray* realloc(GCdArray* array, int capacity) {
return (GCdArray*)rt_realloc(array, capacity * sizeof(Box*) + sizeof(GCdArray));
} }
}; };
class BoxedList : public Box {
public:
int64_t size, capacity; int64_t size, capacity;
ElementArray* elts; GCdArray* elts;
BoxedList() __attribute__((visibility("default"))) : Box(&list_flavor, list_cls), size(0), capacity(0) {} BoxedList() __attribute__((visibility("default"))) : Box(&list_flavor, list_cls), size(0), capacity(0) {}
...@@ -229,6 +234,7 @@ public: ...@@ -229,6 +234,7 @@ public:
BoxedTuple(std::vector<Box*, StlCompatAllocator<Box*> >&& elts) __attribute__((visibility("default"))) BoxedTuple(std::vector<Box*, StlCompatAllocator<Box*> >&& elts) __attribute__((visibility("default")))
: Box(&tuple_flavor, tuple_cls), elts(std::move(elts)) {} : Box(&tuple_flavor, tuple_cls), elts(std::move(elts)) {}
}; };
extern "C" BoxedTuple* EmptyTuple;
class BoxedFile : public Box { class BoxedFile : public Box {
public: public:
...@@ -263,7 +269,11 @@ public: ...@@ -263,7 +269,11 @@ public:
HCAttrs attrs; HCAttrs attrs;
CLFunction* f; CLFunction* f;
int ndefaults;
GCdArray* defaults;
BoxedFunction(CLFunction* f); BoxedFunction(CLFunction* f);
BoxedFunction(CLFunction* f, std::initializer_list<Box*> defaults);
}; };
class BoxedModule : public Box { class BoxedModule : public Box {
......
d = {}
print d.get(1)
print d.setdefault(2)
print d
d[2] = 5
print d.pop(2)
print d.pop(2, None)
print d.pop(2, None)
print range(5)
print range(5, 10)
print list(xrange(5))
print list(xrange(5, 10))
# expected: fail
# - with statements
# Test for various defaults arguments in builtin functions:
class ExpectationFailedException(Exception):
pass
class ExpectedException(object):
def __init__(self, excs):
if isinstance(excs, BaseException):
excs = (excs,)
self.excs = excs
def __enter__(self):
pass
def __exit__(self, type, val, tback):
if not val:
raise ExpectationFailedException("Didn't raise any exception")
if not isinstance(val, self.excs):
raise ExpectationFailedException("Raised %s instead of %s" % (val, self.excs))
print "Caught", type.__name__
return True
expected_exception = ExpectedException
d = {}
print d.get(1)
print d.setdefault(2)
print d.pop(2)
print d.pop(2, None)
print d.pop(2, None)
with expected_exception(KeyError):
print d.pop(2)
print min([1])
print min([1], None)
class Int(int):
def __add__(self, rhs):
print "Int.__add__", rhs
return int.__add__(self, rhs)
def __radd__(self, rhs):
print "Int.__radd__", rhs
return int.__radd__(self, rhs)
print sum([Int(2)])
with expected_exception(AttributeError):
print getattr(object(), "")
print getattr(object(), "", None)
print range(5)
with expected_exception(TypeError):
print range(5, None)
print range(5, 10)
print list(xrange(5))
with expected_exception(TypeError):
print list(xrange(5, None))
print list(xrange(5, 10))
# expected: fail
# - keywords
def f(a, b, c): def f(a, b, c):
print a, b, c print a, b, c
......
# expected: statfail
# - rewriter bails on keywords for now
# statcheck: stats['slowpath_runtimecall'] <= 20
# statcheck: stats.get("slowpath_callclfunc", 0) <= 20
# statcheck: stats['rewriter_nopatch'] <= 20
def f(a, b):
print a, b
for i in xrange(10000):
f(a=1, b=2)
f(b=1, a=2)
# expected: fail
# - not supported yet
class C(object):
def __len__(self):
print "__len__"
return 2
def __iter__(self):
print "__iter__"
return self
def next(self):
print "Next"
raise StopIteration()
def __getitem__(self, k):
print "getitem", k
return k
def keys(self):
print "keys"
return ["a", "c", "b"]
def f(a, b, c):
print a, b, c
f(**C())
# run_args: -n # run_args: -n
# statcheck: stats['slowpath_getitem'] <= 20 # statcheck: stats.get('slowpath_getitem', 0) <= 20
# statcheck: stats['slowpath_setitem'] <= 20 # statcheck: stats['slowpath_setitem'] <= 20
def sort(l): def sort(l):
......
# expected: fail
# - not supported yet
class C(object):
def __len__(self):
print "__len__"
return 2
def __iter__(self):
print "__iter__"
return self
def next(self):
print "Next"
raise StopIteration()
def f(a, b, c):
print a, b, c
f(*C())
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