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:
for (int i = 0; i < clf->versions.size(); i++) {
CompiledFunction* cf = clf->versions[i];
FunctionSignature* fsig = cf->sig;
FunctionSpecialization* fspec = cf->spec;
Sig* type_sig = new Sig();
type_sig->rtn_type = fsig->rtn_type;
type_sig->rtn_type = fspec->rtn_type;
if (stripfirst) {
assert(fsig->arg_types.size() >= 1);
type_sig->arg_types.insert(type_sig->arg_types.end(), fsig->arg_types.begin() + 1,
fsig->arg_types.end());
assert(fspec->arg_types.size() >= 1);
type_sig->arg_types.insert(type_sig->arg_types.end(), fspec->arg_types.begin() + 1,
fspec->arg_types.end());
} 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);
}
......@@ -950,34 +950,12 @@ public:
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) {
ConcreteCompilerVariable* converted = var->makeConverted(emitter, UNKNOWN);
converted->print(emitter, info);
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,
ArgPassSpec argspec, const std::vector<CompilerVariable*>& args,
const std::vector<const std::string*>* keyword_names) {
......@@ -987,23 +965,30 @@ public:
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::vector<CompilerVariable*>& args,
const std::vector<const std::string*>* keyword_names) {
if (cls->is_constant && !cls->instancesHaveAttrs() && cls->hasGenericGetattr()) {
const std::vector<const std::string*>* keyword_names,
bool raise_on_missing = true) {
if (!cls->is_constant || cls->instancesHaveAttrs() || !cls->hasGenericGetattr())
return NULL;
Box* rtattr = cls->getattr(*attr);
if (rtattr == NULL) {
if (raise_on_missing) {
llvm::CallSite call = emitter.createCall2(info.exc_info, g.funcs.raiseAttributeErrorStr,
getStringConstantPtr(*getNameOfClass(cls) + "\0"),
getStringConstantPtr(*attr + '\0'));
call.setDoesNotReturn();
return undefVariable();
} else {
return NULL;
}
}
if (rtattr->cls == function_cls) {
// Functions themselves can't remunge their passed arguments;
// that should either happen here, or we skip things that aren't a simple match
if (rtattr->cls != function_cls)
return NULL;
RELEASE_ASSERT(!argspec.has_starargs, "");
RELEASE_ASSERT(!argspec.has_kwargs, "");
RELEASE_ASSERT(argspec.num_keywords == 0, "");
......@@ -1011,25 +996,27 @@ public:
CLFunction* cl = unboxRTFunction(rtattr);
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;
int nsig_args = 0;
bool found = false;
// TODO have to find the right version.. similar to resolveclfunc?
for (int i = 0; i < cl->versions.size(); i++) {
cf = cl->versions[i];
nsig_args = cf->sig->arg_types.size();
if (nsig_args != args.size() + 1) {
continue;
}
assert(cf->spec->arg_types.size() == cl->numReceivedArgs());
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]->isFitBy(args[j-1]->guaranteedClass())) {
if (!args[j - 1]->canConvertTo(cf->sig->arg_types[j])) {
printf("Can't use version %d since arg %d (%s) doesn't fit into sig arg of %s\n", i, j,
args[j - 1]->getType()->debugName().c_str(),
cf->sig->arg_types[j]->debugName().c_str());
if (!args[j - 1]->canConvertTo(cf->spec->arg_types[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(),
// cf->spec->arg_types[j]->debugName().c_str());
fits = false;
break;
}
......@@ -1042,14 +1029,14 @@ public:
}
assert(found);
assert(nsig_args == args.size() + 1);
assert(!cf->is_interpreted);
assert(cf->code);
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
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);
if (i == 3) {
......@@ -1057,7 +1044,7 @@ public:
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());
......@@ -1067,17 +1054,39 @@ public:
std::vector<llvm::Value*> other_args;
ConcreteCompilerVariable* rtn = _call(emitter, info, linked_function, cf->code, other_args, argspec,
new_args, keyword_names, cf->sig->rtn_type);
assert(rtn->getType() == cf->sig->rtn_type);
ConcreteCompilerVariable* rtn = _call(emitter, info, linked_function, cf->code, other_args, argspec, new_args,
keyword_names, cf->spec->rtn_type);
assert(rtn->getType() == cf->spec->rtn_type);
assert(cf->sig->rtn_type != BOXED_INT);
ASSERT(cf->sig->rtn_type != BOXED_BOOL, "%p", cf->code);
assert(cf->sig->rtn_type != BOXED_FLOAT);
// We should provide unboxed versions of these rather than boxing then unboxing:
// TODO is it more efficient to unbox here, or should we leave it boxed?
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;
}
}
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);
CompilerVariable* rtn = converted->callattr(emitter, info, attr, clsonly, argspec, args, keyword_names);
......@@ -1085,6 +1094,43 @@ public:
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) {
NormalObjectType*& rtn = made[cls];
if (rtn == NULL) {
......@@ -1466,7 +1512,7 @@ public:
} _UNDEF;
CompilerType* UNDEF = &_UNDEF;
CompilerVariable* undefVariable() {
ConcreteCompilerVariable* undefVariable() {
return new ConcreteCompilerVariable(&_UNDEF, llvm::UndefValue::get(_UNDEF.llvmType()), true);
}
......
......@@ -115,6 +115,9 @@ public:
abort();
}
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());
abort();
}
......@@ -314,7 +317,7 @@ ConcreteCompilerVariable* makeFloat(double);
ConcreteCompilerVariable* makeBool(bool);
CompilerVariable* makeStr(std::string*);
CompilerVariable* makeFunction(IREmitter& emitter, CLFunction*);
CompilerVariable* undefVariable();
ConcreteCompilerVariable* undefVariable();
CompilerVariable* makeTuple(const std::vector<CompilerVariable*>& elts);
ConcreteCompilerType* typeFromClass(BoxedClass*);
......
......@@ -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()]);
}
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) {
assert(block->predecessors.size() > 1);
assert(osr_entry_block);
......@@ -882,7 +882,7 @@ static std::string getUniqueFunctionName(std::string nameprefix, EffortLevel::Ef
}
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) {
Timer _t("in doCompile");
......@@ -899,7 +899,7 @@ CompiledFunction* doCompile(SourceInfo* source, const OSREntryDescriptor* entry_
// Initializing the llvm-level structures:
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;
if (entry_descriptor == NULL) {
......@@ -908,7 +908,7 @@ CompiledFunction* doCompile(SourceInfo* source, const OSREntryDescriptor* entry_
llvm_arg_types.push_back(g.llvm_value_type_ptr->getPointerTo());
break;
}
llvm_arg_types.push_back(sig->arg_types[i]->llvmType());
llvm_arg_types.push_back(spec->arg_types[i]->llvmType());
}
} else {
int arg_num = -1;
......@@ -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);
// g.func_registry.registerFunction(f, g.cur_module);
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);
TypeAnalysis::SpeculationLevel speculation_level = TypeAnalysis::NONE;
if (ENABLE_SPECULATION && effort >= EffortLevel::MODERATE)
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));
GuardList guards;
......@@ -973,7 +973,7 @@ CompiledFunction* doCompile(SourceInfo* source, const OSREntryDescriptor* entry_
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));
emitBBs(&irstate, "deopt", deopt_guards, guards, deopt_types, arg_names, NULL, deopt_full_blocks,
deopt_partial_blocks);
......
......@@ -77,7 +77,7 @@ public:
};
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);
class TypeRecorder;
......
......@@ -68,7 +68,6 @@ AST_arguments* SourceInfo::getArgsAST() {
const std::vector<AST_expr*>& SourceInfo::getArgNames() {
static std::vector<AST_expr*> empty;
assert(this);
AST_arguments* args = getArgsAST();
if (args == NULL)
......@@ -76,6 +75,12 @@ const std::vector<AST_expr*>& SourceInfo::getArgNames() {
return args->args;
}
const std::vector<AST_expr*>* CLFunction::getArgNames() {
if (!source)
return NULL;
return &source->getArgNames();
}
const std::vector<AST_stmt*>& SourceInfo::getBody() {
assert(ast);
switch (ast->type) {
......@@ -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;
// 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) {
Timer _t("for compileFunction()");
assert(sig);
assert(spec);
ASSERT(f->versions.size() < 20, "%ld", f->versions.size());
SourceInfo* source = f->source;
......@@ -160,15 +165,15 @@ CompiledFunction* compileFunction(CLFunction* f, FunctionSignature* sig, EffortL
llvm::raw_string_ostream ss(s);
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)
ss << ", ";
ss << sig->arg_types[i]->debugName();
// sig->arg_types[i]->llvmType()->print(ss);
ss << spec->arg_types[i]->debugName();
// spec->arg_types[i]->llvmType()->print(ss);
}
ss << ") -> ";
ss << sig->rtn_type->debugName();
// sig->rtn_type->llvmType()->print(ss);
ss << spec->rtn_type->debugName();
// spec->rtn_type->llvmType()->print(ss);
ss << " at effort level " << effort;
if (entry != NULL) {
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
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);
f->addVersion(cf);
......@@ -244,12 +249,11 @@ void compileAndRunModule(AST_Module* m, BoxedModule* bm) {
si->liveness = computeLivenessInfo(si->cfg);
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();
CompiledFunction* cf
= compileFunction(cl_f, new FunctionSignature(VOID, &si->getArgNames(), 0, false, false), effort, NULL);
CompiledFunction* cf = compileFunction(cl_f, new FunctionSpecialization(VOID), effort, NULL);
assert(cf->clfunc->versions.size());
_t.end();
......@@ -268,7 +272,7 @@ static CompiledFunction* _doReopt(CompiledFunction* cf, EffortLevel::EffortLevel
assert(cf);
assert(cf->entry_descriptor == NULL && "We can't reopt an osr-entry compile!");
assert(cf->sig);
assert(cf->spec);
CLFunction* clfunc = cf->clfunc;
assert(clfunc);
......@@ -281,7 +285,7 @@ static CompiledFunction* _doReopt(CompiledFunction* cf, EffortLevel::EffortLevel
versions.erase(versions.begin() + i);
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
cf->dependent_callsites.invalidateAll();
......@@ -289,6 +293,11 @@ static CompiledFunction* _doReopt(CompiledFunction* cf, EffortLevel::EffortLevel
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?");
abort();
}
......@@ -311,7 +320,7 @@ void* compilePartialFunc(OSRExit* exit) {
// EffortLevel::EffortLevel new_effort = (EffortLevel::EffortLevel)(exit->parent_cf->effort + 1);
// new_effort = EffortLevel::MAXIMAL;
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);
}
......@@ -331,55 +340,56 @@ extern "C" char* reoptCompiledFunc(CompiledFunction* cf) {
return (char*)new_cf->code;
}
CLFunction* createRTFunction() {
return new CLFunction(NULL);
CLFunction* createRTFunction(int num_args, int num_defaults, bool takes_varargs, bool takes_kwargs) {
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) {
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;
}
void addRTFunction(CLFunction* cl_f, void* f, ConcreteCompilerType* rtn_type, int nargs, bool takes_varargs,
bool takes_kwargs) {
std::vector<ConcreteCompilerType*> arg_types(nargs, NULL);
return addRTFunction(cl_f, f, rtn_type, arg_types, takes_varargs, takes_kwargs);
void addRTFunction(CLFunction* cl_f, void* f, ConcreteCompilerType* rtn_type) {
std::vector<ConcreteCompilerType*> arg_types(cl_f->numReceivedArgs(), UNKNOWN);
return addRTFunction(cl_f, f, rtn_type, arg_types);
}
static ConcreteCompilerType* processType(ConcreteCompilerType* type) {
if (type == NULL)
return UNKNOWN;
assert(type);
return type;
}
void addRTFunction(CLFunction* cl_f, void* f, ConcreteCompilerType* rtn_type,
const std::vector<ConcreteCompilerType*>& arg_types, bool takes_varargs, bool takes_kwargs) {
FunctionSignature* sig = new FunctionSignature(processType(rtn_type), NULL, 0, takes_varargs, takes_kwargs);
const std::vector<ConcreteCompilerType*>& arg_types) {
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++) {
sig->arg_types.push_back(processType(arg_types[i]));
}
FunctionSpecialization* spec = new FunctionSpecialization(processType(rtn_type), arg_types);
std::vector<llvm::Type*> llvm_arg_types;
int npassed_args = arg_types.size();
if (takes_varargs)
npassed_args++;
if (takes_kwargs)
npassed_args++;
assert(npassed_args == cl_f->numReceivedArgs());
for (int i = 0; i < npassed_args; i++) {
if (i == 3) {
llvm_arg_types.push_back(g.llvm_value_type_ptr->getPointerTo());
llvm_arg_types.push_back(g.i8_ptr->getPointerTo());
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);
cl_f->addVersion(
new CompiledFunction(NULL, sig, false, f, embedConstantPtr(f, ft->getPointerTo()), EffortLevel::MAXIMAL, NULL));
cl_f->addVersion(new CompiledFunction(NULL, spec, false, f, embedConstantPtr(f, ft->getPointerTo()),
EffortLevel::MAXIMAL, NULL));
}
}
......@@ -659,6 +659,15 @@ private:
std::vector<const std::string*>* keyword_names;
if (node->keywords.size()) {
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 {
keyword_names = NULL;
}
......@@ -671,7 +680,6 @@ private:
for (int i = 0; i < node->keywords.size(); i++) {
CompilerVariable* a = evalExpr(node->keywords[i]->value, exc_info);
args.push_back(a);
keyword_names->push_back(&node->keywords[i]->arg);
}
if (node->starargs)
......@@ -1246,6 +1254,9 @@ private:
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);
if (do_patchpoint) {
PatchpointSetupInfo* pp = patchpoints::createSetitemPatchpoint(emitter.currentFunction(),
......@@ -1431,7 +1442,8 @@ private:
if (cl == NULL) {
SourceInfo* si = new SourceInfo(irstate->getSourceInfo()->parent_module, irstate->getSourceInfo()->scoping);
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;
}
......
......@@ -72,8 +72,8 @@ public:
llvm::Value* getScratchSpace(int min_bytes);
ConcreteCompilerType* getReturnType() {
assert(cf->sig);
return cf->sig->rtn_type;
assert(cf->spec);
return cf->spec->rtn_type;
}
SourceInfo* getSourceInfo() { return source_info; }
......
......@@ -152,32 +152,17 @@ public:
// Codegen types:
struct FunctionSignature {
struct FunctionSpecialization {
ConcreteCompilerType* rtn_type;
const std::vector<AST_expr*>* arg_names;
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,
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);
}
FunctionSpecialization(ConcreteCompilerType* rtn_type) : rtn_type(rtn_type) {}
FunctionSignature(ConcreteCompilerType* rtn_type, const std::vector<AST_expr*>* arg_names,
std::vector<ConcreteCompilerType*>& arg_types, int ndefaults, bool takes_varargs,
bool takes_kwargs)
: rtn_type(rtn_type), arg_names(arg_names), arg_types(arg_types), ndefaults(ndefaults),
takes_varargs(takes_varargs), takes_kwargs(takes_kwargs) {}
FunctionSpecialization(ConcreteCompilerType* rtn_type, ConcreteCompilerType* arg1, ConcreteCompilerType* arg2)
: rtn_type(rtn_type), arg_types({ arg1, arg2 }) {}
FunctionSpecialization(ConcreteCompilerType* rtn_type, const std::vector<ConcreteCompilerType*>& arg_types)
: rtn_type(rtn_type), arg_types(arg_types) {}
};
struct CompiledFunction {
......@@ -185,7 +170,7 @@ private:
public:
CLFunction* clfunc;
llvm::Function* func; // the llvm IR object
FunctionSignature* sig;
FunctionSpecialization* spec;
const OSREntryDescriptor* entry_descriptor;
bool is_interpreted;
......@@ -200,10 +185,10 @@ public:
int64_t times_called;
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,
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) {}
};
......@@ -229,6 +214,10 @@ public:
typedef std::vector<CompiledFunction*> FunctionList;
class CallRewriteArgs;
struct CLFunction {
int num_args;
int num_defaults;
bool takes_varargs, takes_kwargs;
SourceInfo* source;
FunctionList
versions; // any compiled versions along with their type parameters; in order from most preferred to least
......@@ -242,12 +231,21 @@ struct CLFunction {
const std::vector<const std::string*>*);
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) {
assert(compiled);
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->is_interpreted == (compiled->code == NULL));
assert(compiled->is_interpreted == (compiled->llvm_code == NULL));
......@@ -259,19 +257,18 @@ struct CLFunction {
}
};
extern "C" CLFunction* createRTFunction();
extern "C" CLFunction* boxRTFunction(void* f, ConcreteCompilerType* rtn_type, int nargs, bool takes_varargs = false,
bool takes_kwargs = false);
void addRTFunction(CLFunction* cf, void* f, ConcreteCompilerType* rtn_type, int nargs, bool takes_varargs = false,
bool takes_kwargs = false);
CLFunction* createRTFunction(int num_args, int num_defaults, bool takes_varargs, bool takes_kwargs);
CLFunction* boxRTFunction(void* f, ConcreteCompilerType* rtn_type, int nargs, int num_defaults, bool takes_varargs,
bool takes_kwargs);
CLFunction* boxRTFunction(void* f, ConcreteCompilerType* rtn_type, int nargs);
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,
bool takes_kwargs = false);
const std::vector<ConcreteCompilerType*>& arg_types);
CLFunction* unboxRTFunction(Box*);
// 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.
CompiledFunction* compileFunction(CLFunction* f, FunctionSignature* sig, EffortLevel::EffortLevel effort,
CompiledFunction* compileFunction(CLFunction* f, FunctionSpecialization* spec, EffortLevel::EffortLevel effort,
const OSREntryDescriptor* entry);
EffortLevel::EffortLevel initialEffort();
......@@ -280,6 +277,7 @@ typedef int64_t i64;
extern "C" void* rt_alloc(size_t);
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);
......
......@@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include "codegen/compvars.h"
#include "core/common.h"
#include "core/types.h"
#include "gc/collector.h"
......@@ -45,12 +46,7 @@ extern "C" Box* boolRepr(BoxedBool* v) {
return boxStrConstant("False");
}
extern "C" Box* boolNew1(Box* cls) {
assert(cls == bool_cls);
return False;
}
extern "C" Box* boolNew2(Box* cls, Box* val) {
extern "C" Box* boolNew(Box* cls, Box* val) {
assert(cls == bool_cls);
bool b = nonzero(val);
......@@ -60,16 +56,15 @@ extern "C" Box* boolNew2(Box* cls, Box* val) {
void setupBool() {
bool_cls->giveAttr("__name__", boxStrConstant("bool"));
bool_cls->giveAttr("__invert__", new BoxedFunction(boxRTFunction((void*)boolInvert, NULL, 1, false)));
bool_cls->giveAttr("__pos__", new BoxedFunction(boxRTFunction((void*)boolPos, NULL, 1, false)));
bool_cls->giveAttr("__neg__", new BoxedFunction(boxRTFunction((void*)boolNeg, NULL, 1, false)));
bool_cls->giveAttr("__nonzero__", new BoxedFunction(boxRTFunction((void*)boolNonzero, NULL, 1, false)));
bool_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)boolRepr, NULL, 1, false)));
bool_cls->giveAttr("__invert__", new BoxedFunction(boxRTFunction((void*)boolInvert, BOXED_INT, 1)));
bool_cls->giveAttr("__pos__", new BoxedFunction(boxRTFunction((void*)boolPos, BOXED_INT, 1)));
bool_cls->giveAttr("__neg__", new BoxedFunction(boxRTFunction((void*)boolNeg, BOXED_INT, 1)));
bool_cls->giveAttr("__nonzero__", new BoxedFunction(boxRTFunction((void*)boolNonzero, BOXED_BOOL, 1)));
bool_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)boolRepr, STR, 1)));
bool_cls->giveAttr("__str__", bool_cls->getattr("__repr__"));
CLFunction* __new__ = boxRTFunction((void*)boolNew1, NULL, 1, false);
addRTFunction(__new__, (void*)boolNew2, NULL, 2, false);
bool_cls->giveAttr("__new__", new BoxedFunction(__new__));
bool_cls->giveAttr("__new__",
new BoxedFunction(boxRTFunction((void*)boolNew, UNKNOWN, 2, 1, false, false), { None }));
bool_cls->freeze();
......
......@@ -34,7 +34,13 @@ extern "C" Box* trap() {
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
// duplicates afterwards
BoxedList* result = nullptr;
......@@ -70,12 +76,6 @@ extern "C" Box* dir1(Box* obj) {
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) {
if (x->cls == int_cls) {
i64 n = static_cast<BoxedInt*>(x)->n;
......@@ -106,8 +106,19 @@ extern "C" Box* any(Box* container) {
return boxBool(false);
}
extern "C" Box* min1(Box* container) {
Box* minElement = nullptr;
extern "C" Box* min(Box* arg0, BoxedTuple* args) {
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()) {
if (!minElement) {
minElement = e;
......@@ -125,17 +136,19 @@ extern "C" Box* min1(Box* container) {
return minElement;
}
extern "C" Box* min2(Box* o0, Box* o1) {
Box* comp_result = compareInternal(o0, o1, AST_TYPE::Gt, NULL);
bool b = nonzero(comp_result);
if (b) {
return o1;
extern "C" Box* max(Box* arg0, BoxedTuple* args) {
assert(args->cls == tuple_cls);
Box* maxElement;
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()) {
if (!maxElement) {
maxElement = e;
......@@ -153,16 +166,7 @@ extern "C" Box* max1(Box* container) {
return maxElement;
}
extern "C" Box* max2(Box* o0, Box* o1) {
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) {
extern "C" Box* sum(Box* container, Box* initial) {
if (initial->cls == str_cls)
raiseExcHelper(TypeError, "sum() can't sum strings [use ''.join(seq) instead]");
......@@ -173,11 +177,9 @@ extern "C" Box* sum2(Box* container, Box* initial) {
return cur;
}
extern "C" Box* sum1(Box* container) {
return sum2(container, boxInt(0));
}
Box* open(Box* arg1, Box* arg2) {
assert(arg2);
extern "C" Box* open2(Box* arg1, Box* arg2) {
if (arg1->cls != str_cls) {
fprintf(stderr, "TypeError: coercing to Unicode: need string of buffer, %s found\n",
getTypeName(arg1)->c_str());
......@@ -198,12 +200,6 @@ extern "C" Box* open2(Box* arg1, Box* arg2) {
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) {
if (arg->cls != int_cls) {
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) {
return boxInt(s[0]);
}
Box* range1(Box* end) {
RELEASE_ASSERT(end->cls == int_cls, "%s", getTypeName(end)->c_str());
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) {
Box* range(Box* start, Box* stop, Box* step) {
i64 istart, istop, istep;
if (stop == NULL) {
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();
i64 istart = static_cast<BoxedInt*>(start)->n;
i64 iend = static_cast<BoxedInt*>(end)->n;
if ((iend - istart) > 0)
rtn->ensure(iend - istart);
for (i64 i = istart; i < iend; i++) {
listAppendInternal(rtn, boxInt(i));
}
return rtn;
}
istart = 0;
istop = static_cast<BoxedInt*>(start)->n;
istep = 1;
} else if (step == NULL) {
RELEASE_ASSERT(start->cls == int_cls, "%s", getTypeName(start)->c_str());
RELEASE_ASSERT(stop->cls == int_cls, "%s", getTypeName(stop)->c_str());
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(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());
BoxedList* rtn = new BoxedList();
i64 istart = static_cast<BoxedInt*>(start)->n;
i64 iend = static_cast<BoxedInt*>(end)->n;
i64 istep = static_cast<BoxedInt*>(step)->n;
istart = static_cast<BoxedInt*>(start)->n;
istop = static_cast<BoxedInt*>(stop)->n;
istep = static_cast<BoxedInt*>(step)->n;
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) {
for (i64 i = istart; i < iend; i += istep) {
for (i64 i = istart; i < istop; i += istep) {
Box* bi = boxInt(i);
listAppendInternal(rtn, bi);
}
} else {
for (i64 i = istart; i > iend; i += istep) {
for (i64 i = istart; i > istop; i += istep) {
Box* bi = boxInt(i);
listAppendInternal(rtn, bi);
}
......@@ -303,7 +288,7 @@ Box* sortedList(Box* obj) {
BoxedList* rtn = new BoxedList();
int size = lobj->size;
rtn->elts = new (size) BoxedList::ElementArray();
rtn->elts = new (size) GCdArray();
rtn->size = size;
rtn->capacity = size;
for (int i = 0; i < size; i++) {
......@@ -322,22 +307,7 @@ Box* isinstance_func(Box* obj, Box* cls) {
return boxBool(isinstance(obj, cls, 0));
}
Box* getattr2(Box* obj, Box* _str) {
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) {
Box* getattrFunc(Box* obj, Box* _str, Box* default_value) {
if (_str->cls != str_cls) {
raiseExcHelper(TypeError, "getattr(): attribute name must be string");
}
......@@ -346,7 +316,11 @@ Box* getattr3(Box* obj, Box* _str, Box* default_value) {
Box* rtn = getattr_internal(obj, str->s, true, true, NULL, NULL);
if (!rtn) {
if (default_value)
return default_value;
else
raiseExcHelper(AttributeError, "'%s' object has no attribute '%s'", getTypeName(obj)->c_str(),
str->s.c_str());
}
return rtn;
......@@ -440,9 +414,9 @@ static BoxedClass* makeBuiltinException(BoxedClass* base, const char* name) {
cls->giveAttr("__name__", boxStrConstant(name));
// TODO these should be on the base Exception class:
cls->giveAttr("__new__", new BoxedFunction(boxRTFunction((void*)exceptionNew1, NULL, 1, false)));
cls->giveAttr("__str__", new BoxedFunction(boxRTFunction((void*)exceptionStr, NULL, 1, false)));
cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)exceptionRepr, NULL, 1, false)));
cls->giveAttr("__new__", new BoxedFunction(boxRTFunction((void*)exceptionNew1, UNKNOWN, 1)));
cls->giveAttr("__str__", new BoxedFunction(boxRTFunction((void*)exceptionStr, STR, 1)));
cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)exceptionRepr, STR, 1)));
cls->freeze();
builtins_module->giveAttr(name, cls);
......@@ -456,8 +430,7 @@ void setupBuiltins() {
notimplemented_cls = new BoxedClass(object_cls, 0, sizeof(Box), false);
notimplemented_cls->giveAttr("__name__", boxStrConstant("NotImplementedType"));
notimplemented_cls->giveAttr("__repr__",
new BoxedFunction(boxRTFunction((void*)notimplementedRepr, NULL, 1, false)));
notimplemented_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)notimplementedRepr, STR, 1)));
notimplemented_cls->freeze();
NotImplemented = new Box(&notimplemented_flavor, notimplemented_cls);
gc::registerStaticRootObj(NotImplemented);
......@@ -465,8 +438,8 @@ void setupBuiltins() {
builtins_module->giveAttr("NotImplemented", NotImplemented);
builtins_module->giveAttr("NotImplementedType", notimplemented_cls);
builtins_module->giveAttr("all", new BoxedFunction(boxRTFunction((void*)all, BOXED_BOOL, 1, false)));
builtins_module->giveAttr("any", new BoxedFunction(boxRTFunction((void*)any, 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)));
Exception = makeBuiltinException(object_cls, "Exception");
AssertionError = makeBuiltinException(Exception, "AssertionError");
......@@ -484,74 +457,62 @@ void setupBuiltins() {
ImportError = makeBuiltinException(Exception, "ImportError");
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);
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);
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);
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);
CLFunction* min_func = boxRTFunction((void*)min1, NULL, 1, false);
addRTFunction(min_func, (void*)min2, NULL, 2, false);
min_obj = new BoxedFunction(min_func);
min_obj = new BoxedFunction(boxRTFunction((void*)min, UNKNOWN, 1, 0, true, false));
builtins_module->giveAttr("min", min_obj);
CLFunction* max_func = boxRTFunction((void*)max1, NULL, 1, false);
addRTFunction(max_func, (void*)max2, NULL, 2, false);
max_obj = new BoxedFunction(max_func);
max_obj = new BoxedFunction(boxRTFunction((void*)max, UNKNOWN, 1, 0, true, false));
builtins_module->giveAttr("max", max_obj);
CLFunction* sum_func = boxRTFunction((void*)sum1, NULL, 1, false);
addRTFunction(sum_func, (void*)sum2, NULL, 2, false);
builtins_module->giveAttr("sum", new BoxedFunction(sum_func));
builtins_module->giveAttr("sum",
new BoxedFunction(boxRTFunction((void*)sum, UNKNOWN, 2, 1, false, false), { boxInt(0) }));
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);
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);
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);
CLFunction* getattr_func = boxRTFunction((void*)getattr2, NULL, 2, false);
addRTFunction(getattr_func, (void*)getattr3, NULL, 3, false);
builtins_module->giveAttr("getattr", new BoxedFunction(getattr_func));
builtins_module->giveAttr(
"getattr", new BoxedFunction(boxRTFunction((void*)getattrFunc, UNKNOWN, 3, 1, false, false), { NULL }));
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);
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);
CLFunction* sorted_func = createRTFunction();
addRTFunction(sorted_func, (void*)sortedList, LIST, { LIST }, false);
addRTFunction(sorted_func, (void*)sorted, LIST, { UNKNOWN }, false);
CLFunction* sorted_func = createRTFunction(1, 0, false, false);
addRTFunction(sorted_func, (void*)sortedList, LIST, { LIST });
addRTFunction(sorted_func, (void*)sorted, LIST, { UNKNOWN });
builtins_module->giveAttr("sorted", new BoxedFunction(sorted_func));
builtins_module->giveAttr("True", True);
builtins_module->giveAttr("False", False);
CLFunction* range_clf = boxRTFunction((void*)range1, NULL, 1, false);
addRTFunction(range_clf, (void*)range2, NULL, 2, false);
addRTFunction(range_clf, (void*)range3, NULL, 3, false);
range_obj = new BoxedFunction(range_clf);
range_obj = new BoxedFunction(boxRTFunction((void*)range, LIST, 3, 2, false, false), { NULL, NULL });
builtins_module->giveAttr("range", range_obj);
setupXrange();
builtins_module->giveAttr("xrange", xrange_cls);
CLFunction* open = boxRTFunction((void*)open1, NULL, 1, false);
addRTFunction(open, (void*)open2, NULL, 2, false);
open_obj = new BoxedFunction(open);
open_obj = new BoxedFunction(boxRTFunction((void*)open, typeFromClass(file_cls), 2, 1, false, false),
{ boxStrConstant("r") });
builtins_module->giveAttr("open", open_obj);
builtins_module->giveAttr("map", new BoxedFunction(boxRTFunction((void*)map2, LIST, 2, false)));
builtins_module->giveAttr("zip", new BoxedFunction(boxRTFunction((void*)zip2, LIST, 2, false)));
CLFunction* dir_clf = boxRTFunction((void*)dir0, LIST, 0, false);
addRTFunction(dir_clf, (void*)dir1, LIST, 1, false);
builtins_module->giveAttr("dir", new BoxedFunction(dir_clf));
builtins_module->giveAttr("map", new BoxedFunction(boxRTFunction((void*)map2, LIST, 2)));
builtins_module->giveAttr("zip", new BoxedFunction(boxRTFunction((void*)zip2, LIST, 2)));
builtins_module->giveAttr("dir", new BoxedFunction(boxRTFunction((void*)dir, LIST, 1, 1, false, false), { NULL }));
builtins_module->giveAttr("object", object_cls);
builtins_module->giveAttr("str", str_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
assert(BOXED_INT);
v_i.push_back(BOXED_INT);
v_f.push_back(BOXED_FLOAT);
v_u.push_back(NULL);
v_u.push_back(UNKNOWN);
CLFunction* cl = createRTFunction();
addRTFunction(cl, int_func, BOXED_FLOAT, v_i, false);
addRTFunction(cl, float_func, BOXED_FLOAT, v_f, false);
addRTFunction(cl, boxed_func, NULL, v_u, false);
CLFunction* cl = createRTFunction(1, 0, false, false);
addRTFunction(cl, int_func, BOXED_FLOAT, v_i);
addRTFunction(cl, float_func, BOXED_FLOAT, v_f);
addRTFunction(cl, boxed_func, UNKNOWN, v_u);
math_module->giveAttr(name, new BoxedFunction(cl));
}
......@@ -103,6 +103,6 @@ void setupMath() {
math_module->giveAttr("pi", boxFloat(M_PI));
_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 @@
#include <ctime>
#include <sys/time.h>
#include "codegen/compvars.h"
#include "core/types.h"
#include "runtime/gc_runtime.h"
#include "runtime/types.h"
......@@ -33,6 +34,6 @@ Box* timeTime() {
void setupTime() {
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 @@
#include "Python.h"
#include "codegen/compvars.h"
#include "core/types.h"
#include "runtime/types.h"
......@@ -41,9 +42,9 @@ public:
return boxStrConstant(self->name);
}
static Box* __call__(BoxedCApiFunction* self, BoxedList* varargs) {
static Box* __call__(BoxedCApiFunction* self, BoxedTuple* varargs) {
assert(self->cls == capifunc_cls);
assert(varargs->cls == list_cls);
assert(varargs->cls == tuple_cls);
Box* rtn = (Box*)self->func(test_module, varargs);
assert(rtn);
......@@ -78,14 +79,14 @@ extern "C" bool PyArg_ParseTuple(void* tuple, const char* fmt, ...) {
assert(strcmp("O", fmt) == 0);
BoxedList* varargs = (BoxedList*)tuple;
assert(varargs->size == 1);
BoxedTuple* varargs = (BoxedTuple*)tuple;
assert(varargs->elts.size() == 1);
va_list ap;
va_start(ap, fmt);
Box** arg0 = va_arg(ap, Box**);
*arg0 = varargs->elts->elts[0];
*arg0 = varargs->elts[0];
va_end(ap);
......@@ -124,11 +125,11 @@ void setupCAPI() {
capifunc_cls->giveAttr("__name__", boxStrConstant("capifunc"));
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("__call__",
new BoxedFunction(boxRTFunction((void*)BoxedCApiFunction::__call__, NULL, 1, true)));
capifunc_cls->giveAttr(
"__call__", new BoxedFunction(boxRTFunction((void*)BoxedCApiFunction::__call__, UNKNOWN, 1, 0, true, false)));
capifunc_cls->freeze();
}
......
......@@ -104,11 +104,14 @@ Box* dictSetitem(BoxedDict* self, Box* k, Box* v) {
return None;
}
Box* dictPop2(BoxedDict* self, Box* k) {
Box* dictPop(BoxedDict* self, Box* k, Box* d) {
assert(self->cls == dict_cls);
auto it = self->d.find(k);
if (it == self->d.end()) {
if (d)
return d;
BoxedString* s = reprOrNull(k);
if (s)
......@@ -122,19 +125,7 @@ Box* dictPop2(BoxedDict* self, Box* k) {
return rtn;
}
Box* dictPop3(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) {
Box* dictGet(BoxedDict* self, Box* k, Box* d) {
assert(self->cls == dict_cls);
auto it = self->d.find(k);
......@@ -144,11 +135,7 @@ Box* dictGet3(BoxedDict* self, Box* k, Box* d) {
return it->second;
}
Box* dictGet2(BoxedDict* self, Box* k) {
return dictGet3(self, k, None);
}
Box* dictSetdefault3(BoxedDict* self, Box* k, Box* v) {
Box* dictSetdefault(BoxedDict* self, Box* k, Box* v) {
assert(self->cls == dict_cls);
auto it = self->d.find(k);
......@@ -159,10 +146,6 @@ Box* dictSetdefault3(BoxedDict* self, Box* k, Box* v) {
return v;
}
Box* dictSetdefault2(BoxedDict* self, Box* k) {
return dictSetdefault3(self, k, None);
}
BoxedClass* dict_iterator_cls = NULL;
extern "C" void dictIteratorGCHandler(GCVisitor* v, void* p) {
boxGCHandler(v, p);
......@@ -176,53 +159,48 @@ void setupDict() {
dict_iterator_cls = new BoxedClass(object_cls, 0, sizeof(BoxedDict), false);
dict_cls->giveAttr("__name__", boxStrConstant("dict"));
// dict_cls->giveAttr("__len__", new BoxedFunction(boxRTFunction((void*)dictLen, NULL, 1, false)));
// dict_cls->giveAttr("__getitem__", new BoxedFunction(boxRTFunction((void*)dictGetitem, NULL, 2, false)));
// dict_cls->giveAttr("__new__", new BoxedFunction(boxRTFunction((void*)dictNew, NULL, 1, false)));
// dict_cls->giveAttr("__init__", new BoxedFunction(boxRTFunction((void*)dictInit, NULL, 1, false)));
dict_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)dictRepr, 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)));
// dict_cls->giveAttr("__new__", new BoxedFunction(boxRTFunction((void*)dictNew, NULL, 1)));
// dict_cls->giveAttr("__init__", new BoxedFunction(boxRTFunction((void*)dictInit, NULL, 1)));
dict_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)dictRepr, STR, 1)));
dict_cls->giveAttr("__str__", dict_cls->getattr("__repr__"));
dict_cls->giveAttr(
"__iter__", new BoxedFunction(boxRTFunction((void*)dictIterKeys, typeFromClass(dict_iterator_cls), 1, false)));
dict_cls->giveAttr("__iter__",
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("iteritems", new BoxedFunction(boxRTFunction((void*)dictIterItems,
typeFromClass(dict_iterator_cls), 1, false)));
dict_cls->giveAttr("items", new BoxedFunction(boxRTFunction((void*)dictItems, LIST, 1)));
dict_cls->giveAttr("iteritems",
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("itervalues", new BoxedFunction(boxRTFunction((void*)dictIterValues,
typeFromClass(dict_iterator_cls), 1, false)));
dict_cls->giveAttr("values", new BoxedFunction(boxRTFunction((void*)dictValues, LIST, 1)));
dict_cls->giveAttr("itervalues",
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__"));
CLFunction* pop = boxRTFunction((void*)dictPop2, UNKNOWN, 2, false);
addRTFunction(pop, (void*)dictPop3, UNKNOWN, 3, false);
dict_cls->giveAttr("pop", new BoxedFunction(pop));
dict_cls->giveAttr("pop", new BoxedFunction(boxRTFunction((void*)dictPop, UNKNOWN, 3, 1, false, false), { NULL }));
CLFunction* get = boxRTFunction((void*)dictGet2, UNKNOWN, 2, false);
addRTFunction(get, (void*)dictGet3, UNKNOWN, 3, false);
dict_cls->giveAttr("get", new BoxedFunction(get));
dict_cls->giveAttr("get", new BoxedFunction(boxRTFunction((void*)dictGet, UNKNOWN, 3, 1, false, false), { None }));
CLFunction* setdefault = boxRTFunction((void*)dictSetdefault2, UNKNOWN, 2, false);
addRTFunction(setdefault, (void*)dictSetdefault3, UNKNOWN, 3, false);
dict_cls->giveAttr("setdefault", new BoxedFunction(setdefault));
dict_cls->giveAttr("setdefault",
new BoxedFunction(boxRTFunction((void*)dictSetdefault, UNKNOWN, 3, 1, false, false), { None }));
dict_cls->giveAttr("__getitem__", new BoxedFunction(boxRTFunction((void*)dictGetitem, NULL, 2, false)));
dict_cls->giveAttr("__setitem__", new BoxedFunction(boxRTFunction((void*)dictSetitem, NULL, 3, false)));
dict_cls->giveAttr("__getitem__", new BoxedFunction(boxRTFunction((void*)dictGetitem, UNKNOWN, 2)));
dict_cls->giveAttr("__setitem__", new BoxedFunction(boxRTFunction((void*)dictSetitem, NONE, 3)));
dict_cls->freeze();
gc::registerStaticRootObj(dict_iterator_cls);
dict_iterator_cls->giveAttr("__name__", boxStrConstant("dictiterator"));
CLFunction* hasnext = boxRTFunction((void*)dictIterHasnextUnboxed, BOOL, 1, false);
addRTFunction(hasnext, (void*)dictIterHasnext, BOXED_BOOL, 1, false);
CLFunction* hasnext = boxRTFunction((void*)dictIterHasnextUnboxed, BOOL, 1);
addRTFunction(hasnext, (void*)dictIterHasnext, BOXED_BOOL);
dict_iterator_cls->giveAttr("__hasnext__", new BoxedFunction(hasnext));
dict_iterator_cls->giveAttr(
"__iter__", new BoxedFunction(boxRTFunction((void*)dictIterIter, typeFromClass(dict_iterator_cls), 1, false)));
dict_iterator_cls->giveAttr("next", new BoxedFunction(boxRTFunction((void*)dictIterNext, UNKNOWN, 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)));
dict_iterator_cls->freeze();
}
......
......@@ -31,7 +31,14 @@ Box* fileRepr(BoxedFile* self) {
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) {
fprintf(stderr, "IOError: file not open for reading\n");
raiseExcHelper(IOError, "");
......@@ -59,11 +66,6 @@ static Box* _fileRead(BoxedFile* self, i64 size) {
return boxString(os.str());
}
Box* fileRead1(BoxedFile* self) {
assert(self->cls == file_cls);
return _fileRead(self, -1);
}
Box* fileReadline1(BoxedFile* self) {
assert(self->cls == file_cls);
......@@ -82,15 +84,6 @@ Box* fileReadline1(BoxedFile* self) {
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) {
assert(self->cls == file_cls);
......@@ -158,38 +151,31 @@ Box* fileExit(BoxedFile* self, Box* exc_type, Box* exc_val, Box** args) {
return fileClose(self);
}
Box* fileNew2(BoxedClass* cls, Box* s) {
assert(cls == file_cls);
return open1(s);
}
Box* fileNew3(BoxedClass* cls, Box* s, Box* m) {
Box* fileNew(BoxedClass* cls, Box* s, Box* m) {
assert(cls == file_cls);
return open2(s, m);
return open(s, m);
}
void setupFile() {
file_cls->giveAttr("__name__", boxStrConstant("file"));
CLFunction* read = boxRTFunction((void*)fileRead1, NULL, 1, false);
addRTFunction(read, (void*)fileRead2, NULL, 2, false);
file_cls->giveAttr("read", new BoxedFunction(read));
file_cls->giveAttr("read",
new BoxedFunction(boxRTFunction((void*)fileRead, STR, 2, 1, false, false), { boxInt(-1) }));
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("write", new BoxedFunction(boxRTFunction((void*)fileWrite, NULL, 2, false)));
file_cls->giveAttr("close", new BoxedFunction(boxRTFunction((void*)fileClose, NULL, 1, false)));
file_cls->giveAttr("write", new BoxedFunction(boxRTFunction((void*)fileWrite, NONE, 2)));
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("__enter__", new BoxedFunction(boxRTFunction((void*)fileEnter, NULL, 1, false)));
file_cls->giveAttr("__exit__", new BoxedFunction(boxRTFunction((void*)fileExit, NULL, 4, false)));
file_cls->giveAttr("__enter__", new BoxedFunction(boxRTFunction((void*)fileEnter, typeFromClass(file_cls), 1)));
file_cls->giveAttr("__exit__", new BoxedFunction(boxRTFunction((void*)fileExit, UNKNOWN, 4)));
CLFunction* __new__ = boxRTFunction((void*)fileNew2, NULL, 2, false);
addRTFunction(__new__, (void*)fileNew3, NULL, 3, false);
file_cls->giveAttr("__new__", new BoxedFunction(__new__));
file_cls->giveAttr("__new__", new BoxedFunction(boxRTFunction((void*)fileNew, UNKNOWN, 3, 1, false, false),
{ boxStrConstant("r") }));
file_cls->freeze();
}
......
......@@ -502,13 +502,7 @@ std::string floatFmt(double x, int precision, char code) {
return std::string(buf, n);
}
Box* floatNew1(BoxedClass* cls) {
assert(cls == float_cls);
// TODO intern this?
return boxFloat(0.0);
}
Box* floatNew2(BoxedClass* cls, Box* a) {
Box* floatNew(BoxedClass* cls, Box* a) {
assert(cls == float_cls);
if (a->cls == float_cls) {
......@@ -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_INT);
v_fu.push_back(BOXED_FLOAT);
v_fu.push_back(NULL);
v_fu.push_back(UNKNOWN);
CLFunction* cl = createRTFunction();
addRTFunction(cl, float_func, rtn_type, v_ff, false);
addRTFunction(cl, int_func, rtn_type, v_fi, false);
addRTFunction(cl, boxed_func, NULL, v_fu, false);
CLFunction* cl = createRTFunction(2, 0, false, false);
addRTFunction(cl, float_func, rtn_type, v_ff);
addRTFunction(cl, int_func, rtn_type, v_fi);
addRTFunction(cl, boxed_func, UNKNOWN, v_fu);
float_cls->giveAttr(name, new BoxedFunction(cl));
}
......@@ -569,7 +563,7 @@ void setupFloat() {
_addFunc("__div__", BOXED_FLOAT, (void*)floatDivFloat, (void*)floatDivInt, (void*)floatDiv);
_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("__ge__", BOXED_BOOL, (void*)floatGeFloat, (void*)floatGeInt, (void*)floatGe);
......@@ -587,17 +581,18 @@ void setupFloat() {
_addFunc("__sub__", BOXED_FLOAT, (void*)floatSubFloat, (void*)floatSubInt, (void*)floatSub);
_addFunc("__rsub__", BOXED_FLOAT, (void*)floatRSubFloat, (void*)floatRSubInt, (void*)floatRSub);
CLFunction* __new__ = boxRTFunction((void*)floatNew1, NULL, 1, false);
addRTFunction(__new__, (void*)floatNew2, NULL, 2, false);
float_cls->giveAttr("__new__", new BoxedFunction(__new__));
float_cls->giveAttr(
"__new__", new BoxedFunction(boxRTFunction((void*)floatNew, UNKNOWN, 2, 1, false, false), { boxFloat(0.0) }));
float_cls->giveAttr("__neg__", new BoxedFunction(boxRTFunction((void*)floatNeg, NULL, 1, false)));
CLFunction* nonzero = boxRTFunction((void*)floatNonzeroUnboxed, BOOL, 1, false);
addRTFunction(nonzero, (void*)floatNonzero, UNKNOWN, 1, false);
float_cls->giveAttr("__neg__", new BoxedFunction(boxRTFunction((void*)floatNeg, BOXED_FLOAT, 1)));
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(boxRTFunction((void*)floatNonzero, NULL, 1, false)));
float_cls->giveAttr("__str__", new BoxedFunction(boxRTFunction((void*)floatStr, NULL, 1, false)));
float_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)floatRepr, NULL, 1, false)));
// float_cls->giveAttr("__nonzero__", new BoxedFunction(boxRTFunction((void*)floatNonzero, NULL, 1)));
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();
}
......
......@@ -69,8 +69,7 @@ void BoxedList::shrink() {
if (capacity > size * 3) {
int new_capacity = std::max(static_cast<int64_t>(INITIAL_CAPACITY), capacity / 2);
if (size > 0) {
elts = (BoxedList::ElementArray*)rt_realloc(elts,
new_capacity * sizeof(Box*) + sizeof(BoxedList::ElementArray));
elts = GCdArray::realloc(elts, new_capacity);
capacity = new_capacity;
} else if (size == 0) {
rt_free(elts);
......@@ -85,12 +84,11 @@ void BoxedList::ensure(int space) {
if (capacity == 0) {
const int INITIAL_CAPACITY = 8;
int initial = std::max(INITIAL_CAPACITY, space);
elts = new (initial) BoxedList::ElementArray();
elts = new (initial) GCdArray();
capacity = initial;
} else {
int new_capacity = std::max(capacity * 2, size + space);
elts = (BoxedList::ElementArray*)rt_realloc(elts,
new_capacity * sizeof(Box*) + sizeof(BoxedList::ElementArray));
elts = GCdArray::realloc(elts, new_capacity);
capacity = new_capacity;
}
}
......
......@@ -79,28 +79,24 @@ public:
};
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);
RELEASE_ASSERT(stop->cls == int_cls, "%s", getTypeName(stop)->c_str());
i64 istop = static_cast<BoxedInt*>(stop)->n;
return new BoxedXrange(0, istop, 1);
}
Box* step = args[0];
Box* xrange2(Box* cls, Box* start, Box* stop) {
assert(cls == xrange_cls);
if (stop == NULL) {
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(stop->cls == int_cls, "%s", getTypeName(stop)->c_str());
i64 istart = static_cast<BoxedInt*>(start)->n;
i64 istop = static_cast<BoxedInt*>(stop)->n;
return new BoxedXrange(istart, istop, 1);
}
Box* xrange3(Box* cls, Box* start, Box* stop, Box** args) {
Box* step = args[0];
assert(cls == xrange_cls);
} else {
RELEASE_ASSERT(start->cls == int_cls, "%s", getTypeName(start)->c_str());
RELEASE_ASSERT(stop->cls == int_cls, "%s", getTypeName(stop)->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) {
i64 istep = static_cast<BoxedInt*>(step)->n;
RELEASE_ASSERT(istep != 0, "step can't be 0");
return new BoxedXrange(istart, istop, istep);
}
}
Box* xrangeIter(Box* self) {
......@@ -125,19 +122,18 @@ void setupXrange() {
xrange_iterator_cls = new BoxedClass(object_cls, 0, sizeof(BoxedXrangeIterator), false);
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(
"__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);
addRTFunction(hasnext, (void*)BoxedXrangeIterator::xrangeIteratorHasnext, BOXED_BOOL, 1, false);
CLFunction* hasnext = boxRTFunction((void*)BoxedXrangeIterator::xrangeIteratorHasnextUnboxed, BOOL, 1);
addRTFunction(hasnext, (void*)BoxedXrangeIterator::xrangeIteratorHasnext, BOXED_BOOL);
xrange_iterator_cls->giveAttr("__hasnext__", new BoxedFunction(hasnext));
CLFunction* next = boxRTFunction((void*)BoxedXrangeIterator::xrangeIteratorNextUnboxed, INT, 1, false);
addRTFunction(next, (void*)BoxedXrangeIterator::xrangeIteratorNext, BOXED_INT, 1, false);
CLFunction* next = boxRTFunction((void*)BoxedXrangeIterator::xrangeIteratorNextUnboxed, INT, 1);
addRTFunction(next, (void*)BoxedXrangeIterator::xrangeIteratorNext, BOXED_INT);
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
......
......@@ -447,14 +447,7 @@ extern "C" Box* intHash(BoxedInt* self) {
return self;
}
extern "C" Box* intNew1(Box* _cls) {
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) {
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());
......@@ -489,12 +482,7 @@ extern "C" Box* intNew2(Box* _cls, Box* val) {
return rtn;
}
extern "C" Box* intInit1(Box* self) {
// int.__init__ will actually let you call it with anything
return None;
}
extern "C" Box* intInit2(BoxedInt* self, Box* val) {
extern "C" Box* intInit(BoxedInt* self, Box* val, Box* args) {
// int.__init__ will actually let you call it with anything
return None;
}
......@@ -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);
CLFunction* cl = createRTFunction();
addRTFunction(cl, int_func, BOXED_INT, v_ii, false);
addRTFunction(cl, float_func, BOXED_FLOAT, v_if, false);
addRTFunction(cl, boxed_func, NULL, v_iu, false);
CLFunction* cl = createRTFunction(2, 0, false, false);
addRTFunction(cl, int_func, BOXED_INT, v_ii);
addRTFunction(cl, float_func, BOXED_FLOAT, v_if);
addRTFunction(cl, boxed_func, UNKNOWN, v_iu);
int_cls->giveAttr(name, new BoxedFunction(cl));
}
......@@ -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_iu.push_back(BOXED_INT);
v_iu.push_back(NULL);
v_iu.push_back(UNKNOWN);
CLFunction* cl = createRTFunction();
addRTFunction(cl, int_func, rtn_type, v_ii, false);
addRTFunction(cl, boxed_func, NULL, v_iu, false);
CLFunction* cl = createRTFunction(2, 0, false, false);
addRTFunction(cl, int_func, rtn_type, v_ii);
addRTFunction(cl, boxed_func, UNKNOWN, v_iu);
int_cls->giveAttr(name, new BoxedFunction(cl));
}
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"));
_addFuncIntFloatUnknown("__add__", (void*)intAddInt, (void*)intAddFloat, (void*)intAdd);
......@@ -552,29 +545,22 @@ void setupInt() {
_addFuncIntUnknown("__lshift__", BOXED_INT, (void*)intLShiftInt, (void*)intLShift);
_addFuncIntUnknown("__rshift__", BOXED_INT, (void*)intRShiftInt, (void*)intRShift);
int_cls->giveAttr("__invert__", new BoxedFunction(boxRTFunction((void*)intInvert, BOXED_INT, 1, false)));
int_cls->giveAttr("__pos__", new BoxedFunction(boxRTFunction((void*)intPos, BOXED_INT, 1, false)));
int_cls->giveAttr("__neg__", new BoxedFunction(boxRTFunction((void*)intNeg, BOXED_INT, 1, false)));
int_cls->giveAttr("__nonzero__", new BoxedFunction(boxRTFunction((void*)intNonzero, BOXED_BOOL, 1, false)));
int_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)intRepr, STR, 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)));
int_cls->giveAttr("__neg__", new BoxedFunction(boxRTFunction((void*)intNeg, BOXED_INT, 1)));
int_cls->giveAttr("__nonzero__", new BoxedFunction(boxRTFunction((void*)intNonzero, BOXED_BOOL, 1)));
int_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)intRepr, STR, 1)));
int_cls->giveAttr("__str__", int_cls->getattr("__repr__"));
int_cls->giveAttr("__hash__", new BoxedFunction(boxRTFunction((void*)intHash, BOXED_INT, 1, false)));
int_cls->giveAttr("__divmod__", new BoxedFunction(boxRTFunction((void*)intDivmod, BOXED_TUPLE, 2, 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)));
CLFunction* __new__ = boxRTFunction((void*)intNew1, NULL, 1, false);
addRTFunction(__new__, (void*)intNew2, NULL, 2, false);
int_cls->giveAttr("__new__", new BoxedFunction(__new__));
int_cls->giveAttr("__new__",
new BoxedFunction(boxRTFunction((void*)intNew, BOXED_INT, 2, 1, false, false), { boxInt(0) }));
CLFunction* __init__ = boxRTFunction((void*)intInit1, NULL, 1, false);
addRTFunction(__init__, (void*)intInit2, NULL, 2, false);
int_cls->giveAttr("__init__", new BoxedFunction(__init__));
int_cls->giveAttr("__init__",
new BoxedFunction(boxRTFunction((void*)intInit, NONE, 2, 1, true, false), { boxInt(0) }));
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() {
......
......@@ -50,7 +50,8 @@ extern "C" Box* listNonzero(BoxedList* self) {
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) {
raiseExcHelper(IndexError, "pop from empty list");
}
......@@ -58,9 +59,8 @@ extern "C" Box* listPop1(BoxedList* self) {
self->size--;
Box* rtn = self->elts->elts[self->size];
return rtn;
}
}
extern "C" Box* listPop2(BoxedList* self, Box* idx) {
if (idx->cls != int_cls) {
raiseExcHelper(TypeError, "an integer is required");
}
......@@ -417,13 +417,11 @@ extern "C" void listIteratorGCHandler(GCVisitor* v, void* p) {
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);
return new BoxedList();
}
extern "C" Box* listNew2(Box* cls, Box* container) {
assert(cls == list_cls);
if (container == None)
return new BoxedList();
BoxedList* rtn = new BoxedList();
for (Box* e : container->pyElements()) {
......@@ -485,72 +483,67 @@ void setupList() {
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();
addRTFunction(getitem, (void*)listGetitemInt, NULL, std::vector<ConcreteCompilerType*>{ LIST, BOXED_INT }, false);
addRTFunction(getitem, (void*)listGetitemSlice, NULL, std::vector<ConcreteCompilerType*>{ LIST, SLICE }, false);
addRTFunction(getitem, (void*)listGetitem, NULL, std::vector<ConcreteCompilerType*>{ LIST, NULL }, false);
CLFunction* getitem = createRTFunction(2, 0, 0, 0);
addRTFunction(getitem, (void*)listGetitemInt, UNKNOWN, std::vector<ConcreteCompilerType*>{ LIST, BOXED_INT });
addRTFunction(getitem, (void*)listGetitemSlice, LIST, std::vector<ConcreteCompilerType*>{ LIST, SLICE });
addRTFunction(getitem, (void*)listGetitem, UNKNOWN, std::vector<ConcreteCompilerType*>{ LIST, UNKNOWN });
list_cls->giveAttr("__getitem__", new BoxedFunction(getitem));
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("__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);
addRTFunction(pop, (void*)listPop2, NULL, 2, false);
list_cls->giveAttr("pop", new BoxedFunction(pop));
list_cls->giveAttr("pop", new BoxedFunction(boxRTFunction((void*)listPop, UNKNOWN, 2, 1, false, false), { None }));
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();
addRTFunction(setitem, (void*)listSetitemInt, NULL, std::vector<ConcreteCompilerType*>{ LIST, BOXED_INT, NULL },
false);
addRTFunction(setitem, (void*)listSetitemSlice, NULL, std::vector<ConcreteCompilerType*>{ LIST, SLICE, NULL },
false);
addRTFunction(setitem, (void*)listSetitem, NULL, std::vector<ConcreteCompilerType*>{ LIST, NULL, NULL }, false);
CLFunction* setitem = createRTFunction(3, 0, false, false);
addRTFunction(setitem, (void*)listSetitemInt, NONE, std::vector<ConcreteCompilerType*>{ LIST, BOXED_INT, UNKNOWN });
addRTFunction(setitem, (void*)listSetitemSlice, NONE, std::vector<ConcreteCompilerType*>{ LIST, SLICE, UNKNOWN });
addRTFunction(setitem, (void*)listSetitem, NONE, std::vector<ConcreteCompilerType*>{ LIST, UNKNOWN, UNKNOWN });
list_cls->giveAttr("__setitem__", new BoxedFunction(setitem));
CLFunction* delitem = createRTFunction();
addRTFunction(delitem, (void*)listDelitemInt, NULL, std::vector<ConcreteCompilerType*>{ LIST, BOXED_INT }, false);
addRTFunction(delitem, (void*)listDelitemSlice, NULL, std::vector<ConcreteCompilerType*>{ LIST, SLICE }, false);
addRTFunction(delitem, (void*)listDelitem, NULL, std::vector<ConcreteCompilerType*>{ LIST, NULL }, false);
CLFunction* delitem = createRTFunction(2, 0, false, false);
addRTFunction(delitem, (void*)listDelitemInt, NONE, std::vector<ConcreteCompilerType*>{ LIST, BOXED_INT });
addRTFunction(delitem, (void*)listDelitemSlice, NONE, std::vector<ConcreteCompilerType*>{ LIST, SLICE });
addRTFunction(delitem, (void*)listDelitem, NONE, std::vector<ConcreteCompilerType*>{ LIST, UNKNOWN });
list_cls->giveAttr("__delitem__", new BoxedFunction(delitem));
list_cls->giveAttr("insert", new BoxedFunction(boxRTFunction((void*)listInsert, NULL, 3, false)));
list_cls->giveAttr("__mul__", new BoxedFunction(boxRTFunction((void*)listMul, NULL, 2, false)));
list_cls->giveAttr("insert", new BoxedFunction(boxRTFunction((void*)listInsert, NONE, 3)));
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("__add__", new BoxedFunction(boxRTFunction((void*)listAdd, NULL, 2, false)));
list_cls->giveAttr("__iadd__", new BoxedFunction(boxRTFunction((void*)listIAdd, UNKNOWN, 2)));
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("__contains__", new BoxedFunction(boxRTFunction((void*)listContains, BOXED_BOOL, 2, false)));
list_cls->giveAttr("sort", new BoxedFunction(boxRTFunction((void*)listSort1, NONE, 1)));
list_cls->giveAttr("__contains__", new BoxedFunction(boxRTFunction((void*)listContains, BOXED_BOOL, 2)));
CLFunction* new_ = boxRTFunction((void*)listNew1, NULL, 1, false);
addRTFunction(new_, (void*)listNew2, NULL, 2, false);
list_cls->giveAttr("__new__", new BoxedFunction(new_));
list_cls->giveAttr("__new__",
new BoxedFunction(boxRTFunction((void*)listNew, UNKNOWN, 2, 1, false, false), { None }));
list_cls->giveAttr("count", new BoxedFunction(boxRTFunction((void*)listCount, BOXED_INT, 2, false)));
list_cls->giveAttr("index", new BoxedFunction(boxRTFunction((void*)listIndex, NULL, 2, false)));
list_cls->giveAttr("remove", new BoxedFunction(boxRTFunction((void*)listRemove, NONE, 2, false)));
list_cls->giveAttr("reverse", new BoxedFunction(boxRTFunction((void*)listReverse, NONE, 1, false)));
list_cls->giveAttr("count", new BoxedFunction(boxRTFunction((void*)listCount, BOXED_INT, 2)));
list_cls->giveAttr("index", new BoxedFunction(boxRTFunction((void*)listIndex, BOXED_INT, 2)));
list_cls->giveAttr("remove", new BoxedFunction(boxRTFunction((void*)listRemove, NONE, 2)));
list_cls->giveAttr("reverse", new BoxedFunction(boxRTFunction((void*)listReverse, NONE, 1)));
list_cls->freeze();
gc::registerStaticRootObj(list_iterator_cls);
list_iterator_cls->giveAttr("__name__", boxStrConstant("listiterator"));
CLFunction* hasnext = boxRTFunction((void*)listiterHasnextUnboxed, BOOL, 1, false);
addRTFunction(hasnext, (void*)listiterHasnext, BOXED_BOOL, 1, false);
CLFunction* hasnext = boxRTFunction((void*)listiterHasnextUnboxed, BOOL, 1);
addRTFunction(hasnext, (void*)listiterHasnext, BOXED_BOOL);
list_iterator_cls->giveAttr("__hasnext__", new BoxedFunction(hasnext));
list_iterator_cls->giveAttr(
"__iter__", new BoxedFunction(boxRTFunction((void*)listIterIter, typeFromClass(list_iterator_cls), 1, false)));
list_iterator_cls->giveAttr("next", new BoxedFunction(boxRTFunction((void*)listiterNext, UNKNOWN, 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)));
list_iterator_cls->freeze();
}
......
......@@ -1575,298 +1575,338 @@ extern "C" Box* callattr(Box* obj, std::string* attr, bool clsonly, ArgPassSpec
return rtn;
}
CompiledFunction* resolveCLFunc(CLFunction* f, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3, Box** args,
const std::vector<const std::string*>* keyword_names) {
RELEASE_ASSERT(!argspec.has_starargs, "");
RELEASE_ASSERT(!argspec.has_kwargs, "");
RELEASE_ASSERT(argspec.num_keywords == 0, "");
int64_t nargs = argspec.totalPassed();
static inline Box*& getArg(int idx, Box*& arg1, Box*& arg2, Box*& arg3, Box** args) {
if (idx == 0)
return arg1;
if (idx == 1)
return arg2;
if (idx == 2)
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();
CLFunction* f = func->f;
FunctionList& versions = f->versions;
for (int i = 0; i < versions.size(); i++) {
CompiledFunction* cf = versions[i];
FunctionSignature* sig = cf->sig;
assert(!sig->takes_kwargs && "not handled yet");
if (sig->rtn_type->llvmType() != UNKNOWN->llvmType())
continue;
if ((!sig->takes_varargs && sig->arg_types.size() != nargs)
|| (sig->takes_varargs && nargs < sig->arg_types.size()))
continue;
int num_output_args = f->numReceivedArgs();
if (argspec.has_starargs || argspec.has_kwargs || f->takes_kwargs)
rewrite_args = NULL;
int nsig_args = sig->arg_types.size();
// These could be handled:
if (argspec.num_keywords)
rewrite_args = NULL;
if (nsig_args >= 1) {
if (sig->arg_types[0]->isFitBy(arg1->cls)) {
// pass
// TODO Should we guard on the CLFunction or the BoxedFunction?
// A single CLFunction could end up forming multiple BoxedFunctions, and we
// could emit assembly that handles any of them. But doing this involves some
// extra indirection, and it's not clear if that's worth it, since it seems like
// the common case will be functions only ever getting a single set of default arguments.
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 {
continue;
rewrite_args->obj.addGuard((intptr_t)func);
}
}
if (nsig_args >= 2) {
if (sig->arg_types[1]->isFitBy(arg2->cls)) {
// pass
} else {
continue;
if (guard_clfunc) {
// Have to save the defaults array since the object itself will probably get overwritten:
rewrite_args->obj = rewrite_args->obj.move(-2);
r_defaults_array = rewrite_args->obj.getAttr(offsetof(BoxedFunction, defaults), -2);
}
}
if (nsig_args >= 3) {
if (sig->arg_types[2]->isFitBy(arg3->cls)) {
// pass
if (rewrite_args) {
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 {
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 };
printf(" %s", getTypeName(firstargs[i])->c_str());
}
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();
}
// The "output" args that we will pass to the called function:
Box* oarg1 = NULL, *oarg2 = NULL, *oarg3 = NULL;
Box** oargs = NULL;
assert(f->source->getArgsAST()->vararg.size() == 0);
assert(f->source->getArgsAST()->kwarg.size() == 0);
assert(f->source->getArgsAST()->defaults.size() == 0);
bool takes_varargs = false;
bool takes_kwargs = false;
int ndefaults = 0;
if (num_output_args > 3)
oargs = (Box**)alloca((num_output_args - 3) * sizeof(Box*));
std::vector<ConcreteCompilerType*> arg_types;
if (nargs >= 1) {
arg_types.push_back(typeFromClass(arg1->cls));
}
if (nargs >= 2) {
arg_types.push_back(typeFromClass(arg2->cls));
////
// First, match up positional parameters to positional/varargs:
int positional_to_positional = std::min((int)argspec.num_args, f->num_args);
for (int i = 0; i < positional_to_positional; i++) {
getArg(i, oarg1, oarg2, oarg3, oargs) = getArg(i, arg1, arg2, arg3, args);
// 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,
const std::vector<const std::string*>* keyword_names) {
RELEASE_ASSERT(!argspec.has_starargs, "");
RELEASE_ASSERT(!argspec.has_kwargs, "");
if (f->takes_varargs) {
int varargs_idx = f->num_args;
if (rewrite_args) {
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
// that disables the warning for the whole file:
Box* oarg1 = NULL, *oarg2 = NULL, *oarg3 = NULL;
Box** oargs = NULL;
BoxedDict* okwargs = NULL;
if (f->takes_kwargs) {
assert(!rewrite_args && "would need to be handled here");
okwargs = new BoxedDict();
getArg(f->num_args + (f->takes_varargs ? 1 : 0), oarg1, oarg2, oarg3, oargs) = okwargs;
}
int num_out_args = npassed_args;
if (cf->sig->takes_varargs)
num_out_args++;
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];
const std::vector<AST_expr*>* arg_names = f->getArgNames();
if (arg_names == nullptr && argspec.num_keywords) {
raiseExcHelper(TypeError, "<function>() doesn't take keyword arguments");
}
// Then, fill any remaining formal parameters from keywords:
if (argspec.num_args < nsig_args) {
const std::vector<AST_expr*>* arg_names = cf->sig->arg_names;
assert(arg_names);
assert(arg_names->size() == nsig_args);
if (argspec.num_keywords)
assert(argspec.num_keywords == keyword_names->size());
for (int j = argspec.num_args; j < nsig_args; j++) {
assert((*arg_names)[j]->type == AST_TYPE::Name); // we should already have picked a good signature
const std::string& name = ast_cast<AST_Name>((*arg_names)[j])->id;
for (int i = 0; i < argspec.num_keywords; i++) {
assert(!rewrite_args && "would need to be handled here");
int arg_idx = i + argspec.num_args;
Box* kw_val = getArg(arg_idx, arg1, arg2, arg3, args);
assert(arg_names);
bool found = false;
for (int i = 0; i < keyword_names->size(); i++) {
if (keywords_used[i])
for (int j = 0; j < arg_names->size(); j++) {
AST_expr* e = (*arg_names)[j];
if (e->type != AST_TYPE::Name)
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;
}
}
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();
if (nsig_args == 0)
oarg1 = made_vararg;
else if (nsig_args == 1)
oarg2 = made_vararg;
else if (nsig_args == 2)
oarg3 = made_vararg;
else
oargs[nsig_args - 3] = made_vararg;
assert(argspec.num_args == npassed_args);
for (int i = nsig_args; i < npassed_args; i++) {
if (i == 0)
listAppendInternal(made_vararg, iarg1);
else if (i == 1)
listAppendInternal(made_vararg, iarg2);
else if (i == 2)
listAppendInternal(made_vararg, iarg3);
else
listAppendInternal(made_vararg, iargs[i - 3]);
// Fill with defaults:
for (int i = 0; i < f->num_args - f->num_defaults; i++) {
if (params_filled[i])
continue;
// TODO not right error message
raiseExcHelper(TypeError, "<function>() did not get a value for positional argument %d", i);
}
for (int i = f->num_args - f->num_defaults; i < f->num_args; i++) {
if (params_filled[i])
continue;
int default_idx = i + f->num_defaults - f->num_args;
Box* default_obj = func->defaults->elts[default_idx];
if (rewrite_args) {
int offset = offsetof(std::remove_pointer<decltype(BoxedFunction::defaults)>::type, elts)
+ sizeof(Box*) * default_idx;
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 {
assert(!cf->sig->takes_kwargs);
assert(nsig_args == npassed_args);
// If we guarded on the BoxedFunction, which has a constant set of defaults,
// 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) {
return cf->call(oarg1, oarg2, oarg3, oargs);
} else {
return interpretFunction(cf->func, num_out_args, oarg1, oarg2, oarg3, oargs);
getArg(i, oarg1, oarg2, oarg3, oargs) = default_obj;
}
}
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
|| argspec.has_kwargs) {
if (rewrite_args && VERBOSITY())
printf("Not patchpointing this non-simple function call\n");
rewrite_args = NULL;
// Pick a specific version to use:
CompiledFunction* chosen_cf = NULL;
for (CompiledFunction* cf : f->versions) {
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) {
// TODO should it be the func object or its CLFunction?
if (!rewrite_args->func_guarded)
rewrite_args->obj.addGuard((intptr_t)func);
if (!works)
continue;
rewrite_args->rewriter->addDependenceOn(cf->dependent_callsites);
chosen_cf = cf;
break;
}
if (npassed_args >= 1)
rewrite_args->arg1.move(0);
if (npassed_args >= 2)
rewrite_args->arg2.move(1);
if (npassed_args >= 3)
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);
if (chosen_cf == NULL) {
if (f->source == NULL) {
// TODO I don't think this should be happening any more?
printf("Error: couldn't find suitable function version and no source to recompile!\n");
abort();
}
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;
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** args, const std::vector<const std::string*>* keyword_names) {
int npassed_args = argspec.totalPassed();
......@@ -1982,8 +2022,10 @@ extern "C" Box* runtimeCall(Box* obj, ArgPassSpec argspec, Box* arg1, Box* arg2,
slowpath_runtimecall.log();
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++;
}
std::unique_ptr<Rewriter> rewriter(Rewriter::createRewriter(
__builtin_extract_return_addr(__builtin_return_address(0)), num_orig_args, 2, "runtimeCall"));
Box* rtn;
......
......@@ -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" BoxedInt* hash(Box* obj);
// extern "C" Box* abs_(Box* obj);
extern "C" Box* open1(Box* arg);
extern "C" Box* open2(Box* arg1, Box* arg2);
Box* open(Box* arg1, Box* arg2);
// extern "C" Box* chr(Box* arg);
extern "C" Box* compare(Box*, Box*, int);
extern "C" BoxedInt* len(Box* obj);
......
......@@ -89,13 +89,11 @@ Box* setAdd2(Box* _self, Box* b) {
return None;
}
Box* setNew1(Box* cls) {
Box* setNew(Box* cls, Box* container) {
assert(cls == set_cls);
return new BoxedSet();
}
Box* setNew2(Box* cls, Box* container) {
assert(cls == set_cls);
if (container == None)
return new BoxedSet();
Box* rtn = new BoxedSet();
for (Box* e : container->pyElements()) {
......@@ -212,16 +210,15 @@ void setupSet() {
set_iterator_cls = new BoxedClass(object_cls, 0, sizeof(BoxedSet), false);
set_iterator_cls->giveAttr("__name__", boxStrConstant("setiterator"));
set_iterator_cls->giveAttr("__hasnext__",
new BoxedFunction(boxRTFunction((void*)setiteratorHasnext, BOXED_BOOL, 1, false)));
set_iterator_cls->giveAttr("next", new BoxedFunction(boxRTFunction((void*)setiteratorNext, UNKNOWN, 1, false)));
new BoxedFunction(boxRTFunction((void*)setiteratorHasnext, BOXED_BOOL, 1)));
set_iterator_cls->giveAttr("next", new BoxedFunction(boxRTFunction((void*)setiteratorNext, UNKNOWN, 1)));
set_iterator_cls->freeze();
gc::registerStaticRootObj(set_iterator_cls);
CLFunction* new_ = boxRTFunction((void*)setNew1, SET, 1, false);
addRTFunction(new_, (void*)setNew2, SET, 2, false);
set_cls->giveAttr("__new__", new BoxedFunction(new_));
set_cls->giveAttr("__new__",
new BoxedFunction(boxRTFunction((void*)setNew, UNKNOWN, 2, 1, false, false), { None }));
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("__str__", repr);
......@@ -231,28 +228,27 @@ void setupSet() {
v_su.push_back(SET);
v_su.push_back(UNKNOWN);
CLFunction* or_ = createRTFunction();
addRTFunction(or_, (void*)setOrSet, SET, v_ss, false);
CLFunction* or_ = createRTFunction(2, 0, false, false);
addRTFunction(or_, (void*)setOrSet, SET, v_ss);
set_cls->giveAttr("__or__", new BoxedFunction(or_));
CLFunction* sub_ = createRTFunction();
addRTFunction(sub_, (void*)setSubSet, SET, v_ss, false);
CLFunction* sub_ = createRTFunction(2, 0, false, false);
addRTFunction(sub_, (void*)setSubSet, SET, v_ss);
set_cls->giveAttr("__sub__", new BoxedFunction(sub_));
CLFunction* xor_ = createRTFunction();
addRTFunction(xor_, (void*)setXorSet, SET, v_ss, false);
CLFunction* xor_ = createRTFunction(2, 0, false, false);
addRTFunction(xor_, (void*)setXorSet, SET, v_ss);
set_cls->giveAttr("__xor__", new BoxedFunction(xor_));
CLFunction* and_ = createRTFunction();
addRTFunction(and_, (void*)setAndSet, SET, v_ss, false);
CLFunction* and_ = createRTFunction(2, 0, false, false);
addRTFunction(and_, (void*)setAndSet, SET, v_ss);
set_cls->giveAttr("__and__", new BoxedFunction(and_));
set_cls->giveAttr("__iter__",
new BoxedFunction(boxRTFunction((void*)setIter, typeFromClass(set_iterator_cls), 1, false)));
set_cls->giveAttr("__iter__", new BoxedFunction(boxRTFunction((void*)setIter, typeFromClass(set_iterator_cls), 1)));
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();
}
......
......@@ -293,12 +293,7 @@ extern "C" Box* strNonzero(BoxedString* self) {
return boxBool(self->s.size() != 0);
}
extern "C" Box* strNew1(BoxedClass* cls) {
assert(cls == str_cls);
return boxStrConstant("");
}
extern "C" Box* strNew2(BoxedClass* cls, Box* obj) {
extern "C" Box* strNew(BoxedClass* cls, Box* obj) {
assert(cls == str_cls);
return str(obj);
......@@ -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);
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();
std::ostringstream os("");
......@@ -374,76 +382,42 @@ Box* strSplit1(BoxedString* self) {
listAppendInternal(rtn, boxString(os.str()));
}
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 {
raiseExcHelper(TypeError, "expected a character buffer object");
}
}
Box* strStrip1(BoxedString* self) {
assert(self->cls == str_cls);
return new BoxedString(llvm::StringRef(self->s).trim(" \t\n\r\f\v"));
}
Box* strStrip2(BoxedString* self, Box* chars) {
Box* strStrip(BoxedString* self, Box* chars) {
assert(self->cls == str_cls);
if (chars->cls == str_cls) {
return new BoxedString(llvm::StringRef(self->s).trim(static_cast<BoxedString*>(chars)->s));
} else if (chars->cls == none_cls) {
return strStrip1(self);
return new BoxedString(llvm::StringRef(self->s).trim(" \t\n\r\f\v"));
} else {
raiseExcHelper(TypeError, "strip arg must be None, str or unicode");
}
}
Box* strLStrip1(BoxedString* self) {
assert(self->cls == str_cls);
return new BoxedString(llvm::StringRef(self->s).ltrim(" \t\n\r\f\v"));
}
Box* strLStrip2(BoxedString* self, Box* chars) {
Box* strLStrip(BoxedString* self, Box* chars) {
assert(self->cls == str_cls);
if (chars->cls == str_cls) {
return new BoxedString(llvm::StringRef(self->s).ltrim(static_cast<BoxedString*>(chars)->s));
} else if (chars->cls == none_cls) {
return strLStrip1(self);
return new BoxedString(llvm::StringRef(self->s).ltrim(" \t\n\r\f\v"));
} else {
raiseExcHelper(TypeError, "lstrip arg must be None, str or unicode");
}
}
Box* strRStrip1(BoxedString* self) {
assert(self->cls == str_cls);
return new BoxedString(llvm::StringRef(self->s).rtrim(" \t\n\r\f\v"));
}
Box* strRStrip2(BoxedString* self, Box* chars) {
Box* strRStrip(BoxedString* self, Box* chars) {
assert(self->cls == str_cls);
if (chars->cls == str_cls) {
return new BoxedString(llvm::StringRef(self->s).rtrim(static_cast<BoxedString*>(chars)->s));
} else if (chars->cls == none_cls) {
return strRStrip1(self);
return new BoxedString(llvm::StringRef(self->s).rtrim(" \t\n\r\f\v"));
} else {
raiseExcHelper(TypeError, "rstrip arg must be None, str or unicode");
}
......@@ -569,58 +543,47 @@ void setupStr() {
gc::registerStaticRootObj(str_iterator_cls);
str_iterator_cls->giveAttr("__name__", boxStrConstant("striterator"));
str_iterator_cls->giveAttr("__hasnext__",
new BoxedFunction(boxRTFunction((void*)BoxedStringIterator::hasnext, NULL, 1, false)));
str_iterator_cls->giveAttr("next",
new BoxedFunction(boxRTFunction((void*)BoxedStringIterator::next, STR, 1, false)));
new BoxedFunction(boxRTFunction((void*)BoxedStringIterator::hasnext, BOXED_BOOL, 1)));
str_iterator_cls->giveAttr("next", new BoxedFunction(boxRTFunction((void*)BoxedStringIterator::next, STR, 1)));
str_iterator_cls->freeze();
str_cls->giveAttr("__name__", boxStrConstant("str"));
str_cls->giveAttr("__len__", new BoxedFunction(boxRTFunction((void*)strLen, NULL, 1, false)));
str_cls->giveAttr("__str__", new BoxedFunction(boxRTFunction((void*)strStr, NULL, 1, false)));
str_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)strRepr, NULL, 1, false)));
str_cls->giveAttr("__hash__", new BoxedFunction(boxRTFunction((void*)strHash, NULL, 1, false)));
str_cls->giveAttr("__nonzero__", new BoxedFunction(boxRTFunction((void*)strNonzero, NULL, 1, false)));
str_cls->giveAttr("__len__", new BoxedFunction(boxRTFunction((void*)strLen, BOXED_INT, 1)));
str_cls->giveAttr("__str__", new BoxedFunction(boxRTFunction((void*)strStr, STR, 1)));
str_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)strRepr, STR, 1)));
str_cls->giveAttr("__hash__", new BoxedFunction(boxRTFunction((void*)strHash, BOXED_INT, 1)));
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);
addRTFunction(strStrip, (void*)strStrip2, STR, 2, false);
str_cls->giveAttr("strip", new BoxedFunction(strStrip));
str_cls->giveAttr("strip", new BoxedFunction(boxRTFunction((void*)strStrip, STR, 2, 1, false, false), { None }));
CLFunction* strLStrip = boxRTFunction((void*)strLStrip1, STR, 1, false);
addRTFunction(strLStrip, (void*)strLStrip2, STR, 2, false);
str_cls->giveAttr("lstrip", new BoxedFunction(strLStrip));
str_cls->giveAttr("lstrip", new BoxedFunction(boxRTFunction((void*)strLStrip, STR, 2, 1, false, false), { None }));
CLFunction* strRStrip = boxRTFunction((void*)strRStrip1, STR, 1, false);
addRTFunction(strRStrip, (void*)strRStrip2, STR, 2, false);
str_cls->giveAttr("rstrip", new BoxedFunction(strRStrip));
str_cls->giveAttr("rstrip", new BoxedFunction(boxRTFunction((void*)strRStrip, STR, 2, 1, false, false), { None }));
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("__mod__", new BoxedFunction(boxRTFunction((void*)strMod, NULL, 2, false)));
str_cls->giveAttr("__mul__", new BoxedFunction(boxRTFunction((void*)strMul, NULL, 2, false)));
str_cls->giveAttr("__eq__", new BoxedFunction(boxRTFunction((void*)strEq, NULL, 2, false)));
str_cls->giveAttr("__getitem__", new BoxedFunction(boxRTFunction((void*)strGetitem, NULL, 2, false)));
str_cls->giveAttr("__add__", new BoxedFunction(boxRTFunction((void*)strAdd, UNKNOWN, 2)));
str_cls->giveAttr("__mod__", new BoxedFunction(boxRTFunction((void*)strMod, STR, 2)));
str_cls->giveAttr("__mul__", new BoxedFunction(boxRTFunction((void*)strMul, UNKNOWN, 2)));
str_cls->giveAttr("__eq__", new BoxedFunction(boxRTFunction((void*)strEq, UNKNOWN, 2)));
str_cls->giveAttr("__getitem__", new BoxedFunction(boxRTFunction((void*)strGetitem, STR, 2)));
str_cls->giveAttr("__iter__",
new BoxedFunction(boxRTFunction((void*)strIter, typeFromClass(str_iterator_cls), 1, false)));
str_cls->giveAttr("__iter__", new BoxedFunction(boxRTFunction((void*)strIter, typeFromClass(str_iterator_cls), 1)));
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);
addRTFunction(strSplit, (void*)strSplit2, LIST, 2, false);
str_cls->giveAttr("split", new BoxedFunction(strSplit));
str_cls->giveAttr("split", new BoxedFunction(boxRTFunction((void*)strSplit, LIST, 2, 1, false, false), { None }));
str_cls->giveAttr("rsplit", str_cls->getattr("split"));
CLFunction* count = boxRTFunction((void*)strCount2Unboxed, INT, 2, false);
addRTFunction(count, (void*)strCount2, BOXED_INT, 2, false);
CLFunction* count = boxRTFunction((void*)strCount2Unboxed, INT, 2);
addRTFunction(count, (void*)strCount2, BOXED_INT);
str_cls->giveAttr("count", new BoxedFunction(count));
CLFunction* __new__ = boxRTFunction((void*)strNew1, NULL, 1, false);
addRTFunction(__new__, (void*)strNew2, NULL, 2, false);
str_cls->giveAttr("__new__", new BoxedFunction(__new__));
str_cls->giveAttr("__new__", new BoxedFunction(boxRTFunction((void*)strNew, UNKNOWN, 2, 1, false, false),
{ boxStrConstant("") }));
str_cls->freeze();
}
......
......@@ -205,23 +205,23 @@ void setupTuple() {
tuple_cls->giveAttr("__name__", boxStrConstant("tuple"));
tuple_cls->giveAttr("__getitem__", new BoxedFunction(boxRTFunction((void*)tupleGetitem, NULL, 2, false)));
tuple_cls->giveAttr("__contains__", new BoxedFunction(boxRTFunction((void*)tupleContains, NULL, 2, false)));
tuple_cls->giveAttr("__getitem__", new BoxedFunction(boxRTFunction((void*)tupleGetitem, UNKNOWN, 2)));
tuple_cls->giveAttr("__contains__", new BoxedFunction(boxRTFunction((void*)tupleContains, BOXED_BOOL, 2)));
tuple_cls->giveAttr(
"__iter__", new BoxedFunction(boxRTFunction((void*)tupleIter, typeFromClass(tuple_iterator_cls), 1, false)));
tuple_cls->giveAttr("__iter__",
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("__le__", new BoxedFunction(boxRTFunction((void*)tupleLe, NULL, 2, false)));
tuple_cls->giveAttr("__gt__", new BoxedFunction(boxRTFunction((void*)tupleGt, NULL, 2, false)));
tuple_cls->giveAttr("__ge__", new BoxedFunction(boxRTFunction((void*)tupleGe, NULL, 2, false)));
tuple_cls->giveAttr("__eq__", new BoxedFunction(boxRTFunction((void*)tupleEq, NULL, 2, false)));
tuple_cls->giveAttr("__ne__", new BoxedFunction(boxRTFunction((void*)tupleNe, NULL, 2, false)));
tuple_cls->giveAttr("__lt__", new BoxedFunction(boxRTFunction((void*)tupleLt, UNKNOWN, 2)));
tuple_cls->giveAttr("__le__", new BoxedFunction(boxRTFunction((void*)tupleLe, UNKNOWN, 2)));
tuple_cls->giveAttr("__gt__", new BoxedFunction(boxRTFunction((void*)tupleGt, UNKNOWN, 2)));
tuple_cls->giveAttr("__ge__", new BoxedFunction(boxRTFunction((void*)tupleGe, UNKNOWN, 2)));
tuple_cls->giveAttr("__eq__", new BoxedFunction(boxRTFunction((void*)tupleEq, UNKNOWN, 2)));
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("__len__", new BoxedFunction(boxRTFunction((void*)tupleLen, NULL, 1, false)));
tuple_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)tupleRepr, NULL, 1, false)));
tuple_cls->giveAttr("__hash__", new BoxedFunction(boxRTFunction((void*)tupleHash, BOXED_INT, 1)));
tuple_cls->giveAttr("__len__", new BoxedFunction(boxRTFunction((void*)tupleLen, BOXED_INT, 1)));
tuple_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)tupleRepr, STR, 1)));
tuple_cls->giveAttr("__str__", tuple_cls->getattr("__repr__"));
tuple_cls->freeze();
......@@ -229,12 +229,12 @@ void setupTuple() {
gc::registerStaticRootObj(tuple_iterator_cls);
tuple_iterator_cls->giveAttr("__name__", boxStrConstant("tupleiterator"));
CLFunction* hasnext = boxRTFunction((void*)tupleiterHasnextUnboxed, BOOL, 1, false);
addRTFunction(hasnext, (void*)tupleiterHasnext, BOXED_BOOL, 1, false);
CLFunction* hasnext = boxRTFunction((void*)tupleiterHasnextUnboxed, BOOL, 1);
addRTFunction(hasnext, (void*)tupleiterHasnext, BOXED_BOOL);
tuple_iterator_cls->giveAttr("__hasnext__", new BoxedFunction(hasnext));
tuple_iterator_cls->giveAttr("__iter__", new BoxedFunction(boxRTFunction(
(void*)tupleIterIter, typeFromClass(tuple_iterator_cls), 1, false)));
tuple_iterator_cls->giveAttr("next", new BoxedFunction(boxRTFunction((void*)tupleiterNext, UNKNOWN, 1, false)));
tuple_iterator_cls->giveAttr(
"__iter__", new BoxedFunction(boxRTFunction((void*)tupleIterIter, typeFromClass(tuple_iterator_cls), 1)));
tuple_iterator_cls->giveAttr("next", new BoxedFunction(boxRTFunction((void*)tupleiterNext, UNKNOWN, 1)));
tuple_iterator_cls->freeze();
}
......
......@@ -64,7 +64,8 @@ llvm::iterator_range<BoxIterator> Box::pyElements() {
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) {
assert(f->source->ast);
// this->giveAttr("__name__", boxString(&f->source->ast->name));
......@@ -73,6 +74,45 @@ extern "C" BoxedFunction::BoxedFunction(CLFunction* f) : Box(&function_flavor, f
Box* modname = f->source->parent_module->getattr("__name__", NULL, NULL);
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) {
......@@ -216,7 +256,7 @@ const ObjectFlavor bool_flavor(&boxGCHandler, NULL);
const ObjectFlavor int_flavor(&boxGCHandler, NULL);
const ObjectFlavor float_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 list_flavor(&listGCHandler, NULL);
const ObjectFlavor slice_flavor(&sliceGCHandler, NULL);
......@@ -229,6 +269,8 @@ const ObjectFlavor member_flavor(&boxGCHandler, NULL);
const AllocationKind untracked_kind(NULL, NULL);
const AllocationKind hc_kind(&hcGCHandler, NULL);
const AllocationKind conservative_kind(&conservativeGCHandler, NULL);
BoxedTuple* EmptyTuple;
}
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) {
return rtn;
}
extern "C" Box* sliceNew2(Box* cls, Box* stop) {
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);
extern "C" Box* sliceNew(Box* cls, Box* start, Box* stop, Box** args) {
RELEASE_ASSERT(cls == slice_cls, "");
Box* step = args[0];
if (stop == NULL)
return createSlice(None, start, None);
return createSlice(start, stop, step);
}
......@@ -389,24 +424,21 @@ CLFunction* unboxRTFunction(Box* b) {
return static_cast<BoxedFunction*>(b)->f;
}
Box* objectNew1(BoxedClass* 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;
}
Box* objectNew(BoxedClass* cls, BoxedList* args) {
Box* objectNew(BoxedClass* cls, BoxedTuple* args) {
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)
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;
......@@ -430,6 +462,11 @@ void setupRuntime() {
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);
// TODO it'd be nice to be able to do these in the respective setupType methods,
......@@ -443,7 +480,6 @@ void setupRuntime() {
list_cls = new BoxedClass(object_cls, 0, sizeof(BoxedList), false);
slice_cls = new BoxedClass(object_cls, 0, sizeof(BoxedSlice), 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);
set_cls = new BoxedClass(object_cls, 0, sizeof(BoxedSet), false);
member_cls = new BoxedClass(object_cls, 0, sizeof(BoxedMemberDescriptor), false);
......@@ -461,29 +497,27 @@ void setupRuntime() {
BOXED_TUPLE = typeFromClass(tuple_cls);
object_cls->giveAttr("__name__", boxStrConstant("object"));
auto object_new = boxRTFunction((void*)objectNew1, NULL, 1, false);
addRTFunction(object_new, (void*)objectNew, NULL, 1, true);
object_cls->giveAttr("__new__", new BoxedFunction(object_new));
object_cls->giveAttr("__new__", new BoxedFunction(boxRTFunction((void*)objectNew, UNKNOWN, 1, 0, true, false)));
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;
type_cls->giveAttr("__call__", new BoxedFunction(typeCallObj));
type_cls->giveAttr("__name__", boxStrConstant("type"));
type_cls->giveAttr("__new__", new BoxedFunction(boxRTFunction((void*)typeNew, NULL, 2, true)));
type_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)typeRepr, NULL, 1, true)));
type_cls->giveAttr("__new__", new BoxedFunction(boxRTFunction((void*)typeNew, UNKNOWN, 2)));
type_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)typeRepr, STR, 1)));
type_cls->giveAttr("__str__", type_cls->getattr("__repr__"));
type_cls->freeze();
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("__hash__", new BoxedFunction(boxRTFunction((void*)noneHash, NULL, 1, false)));
none_cls->giveAttr("__hash__", new BoxedFunction(boxRTFunction((void*)noneHash, UNKNOWN, 1)));
none_cls->freeze();
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->freeze();
......@@ -501,21 +535,18 @@ void setupRuntime() {
setupFile();
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->freeze();
instancemethod_cls->giveAttr("__name__", boxStrConstant("instancemethod"));
instancemethod_cls->giveAttr("__repr__",
new BoxedFunction(boxRTFunction((void*)instancemethodRepr, NULL, 1, true)));
instancemethod_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)instancemethodRepr, STR, 1)));
instancemethod_cls->freeze();
slice_cls->giveAttr("__name__", boxStrConstant("slice"));
CLFunction* slice_new = boxRTFunction((void*)sliceNew2, NULL, 2, false);
addRTFunction(slice_new, (void*)sliceNew3, NULL, 3, false);
addRTFunction(slice_new, (void*)sliceNew4, NULL, 4, false);
slice_cls->giveAttr("__new__", new BoxedFunction(slice_new));
slice_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)sliceRepr, NULL, 1, true)));
slice_cls->giveAttr("__new__",
new BoxedFunction(boxRTFunction((void*)sliceNew, UNKNOWN, 4, 2, false, false), { NULL, None }));
slice_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)sliceRepr, STR, 1)));
slice_cls->giveAttr("__str__", slice_cls->getattr("__repr__"));
slice_cls->giveAttr("start", new BoxedMemberDescriptor(BoxedMemberDescriptor::OBJECT, SLICE_START_OFFSET));
slice_cls->giveAttr("stop", new BoxedMemberDescriptor(BoxedMemberDescriptor::OBJECT, SLICE_STOP_OFFSET));
......
......@@ -196,21 +196,26 @@ public:
: Box(&instancemethod_flavor, instancemethod_cls), obj(obj), func(func) {}
};
class BoxedList : public Box {
class GCdArray : public GCObject {
public:
class ElementArray : public GCObject {
public:
Box* elts[0];
ElementArray() : GCObject(&untracked_kind) {}
GCdArray() : GCObject(&untracked_kind) {}
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;
ElementArray* elts;
GCdArray* elts;
BoxedList() __attribute__((visibility("default"))) : Box(&list_flavor, list_cls), size(0), capacity(0) {}
......@@ -229,6 +234,7 @@ public:
BoxedTuple(std::vector<Box*, StlCompatAllocator<Box*> >&& elts) __attribute__((visibility("default")))
: Box(&tuple_flavor, tuple_cls), elts(std::move(elts)) {}
};
extern "C" BoxedTuple* EmptyTuple;
class BoxedFile : public Box {
public:
......@@ -263,7 +269,11 @@ public:
HCAttrs attrs;
CLFunction* f;
int ndefaults;
GCdArray* defaults;
BoxedFunction(CLFunction* f);
BoxedFunction(CLFunction* f, std::initializer_list<Box*> defaults);
};
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):
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
# statcheck: stats['slowpath_getitem'] <= 20
# statcheck: stats.get('slowpath_getitem', 0) <= 20
# statcheck: stats['slowpath_setitem'] <= 20
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