Commit 5de99b04 authored by Travis Hance's avatar Travis Hance

give all CLFunctions a ParamNames (renamed from ArgNames) including builtin ones

parent 3089737c
......@@ -235,10 +235,10 @@ private:
typedef DefinednessAnalysis::DefinitionLevel DefinitionLevel;
CFG* cfg;
const SourceInfo::ArgNames& arg_names;
const ParamNames& arg_names;
public:
DefinednessBBAnalyzer(CFG* cfg, const SourceInfo::ArgNames& arg_names) : cfg(cfg), arg_names(arg_names) {}
DefinednessBBAnalyzer(CFG* cfg, const ParamNames& arg_names) : cfg(cfg), arg_names(arg_names) {}
virtual DefinitionLevel merge(DefinitionLevel from, DefinitionLevel into) const {
assert(from != DefinednessAnalysis::Undefined);
......@@ -343,13 +343,13 @@ public:
void DefinednessBBAnalyzer::processBB(Map& starting, CFGBlock* block) const {
DefinednessVisitor visitor(starting);
if (block == cfg->getStartingBlock() && arg_names.args) {
for (auto e : (*arg_names.args))
if (block == cfg->getStartingBlock()) {
for (auto e : arg_names.args)
visitor._doSet(e);
if (arg_names.vararg->size())
visitor._doSet(*arg_names.vararg);
if (arg_names.kwarg->size())
visitor._doSet(*arg_names.kwarg);
if (arg_names.vararg.size())
visitor._doSet(arg_names.vararg);
if (arg_names.kwarg.size())
visitor._doSet(arg_names.kwarg);
}
for (int i = 0; i < block->body.size(); i++) {
......@@ -364,7 +364,7 @@ void DefinednessBBAnalyzer::processBB(Map& starting, CFGBlock* block) const {
}
}
DefinednessAnalysis::DefinednessAnalysis(const SourceInfo::ArgNames& arg_names, CFG* cfg, ScopeInfo* scope_info)
DefinednessAnalysis::DefinednessAnalysis(const ParamNames& arg_names, CFG* cfg, ScopeInfo* scope_info)
: scope_info(scope_info) {
Timer _t("DefinednessAnalysis()", 10);
......@@ -397,8 +397,7 @@ const DefinednessAnalysis::RequiredSet& DefinednessAnalysis::getDefinedNamesAtEn
return defined_at_end[block];
}
PhiAnalysis::PhiAnalysis(const SourceInfo::ArgNames& arg_names, CFG* cfg, LivenessAnalysis* liveness,
ScopeInfo* scope_info)
PhiAnalysis::PhiAnalysis(const ParamNames& arg_names, CFG* cfg, LivenessAnalysis* liveness, ScopeInfo* scope_info)
: definedness(arg_names, cfg, scope_info), liveness(liveness) {
Timer _t("PhiAnalysis()", 10);
......@@ -476,8 +475,7 @@ LivenessAnalysis* computeLivenessInfo(CFG* cfg) {
return new LivenessAnalysis(cfg);
}
PhiAnalysis* computeRequiredPhis(const SourceInfo::ArgNames& args, CFG* cfg, LivenessAnalysis* liveness,
ScopeInfo* scope_info) {
PhiAnalysis* computeRequiredPhis(const ParamNames& args, CFG* cfg, LivenessAnalysis* liveness, ScopeInfo* scope_info) {
return new PhiAnalysis(args, cfg, liveness, scope_info);
}
}
......@@ -75,7 +75,7 @@ private:
ScopeInfo* scope_info;
public:
DefinednessAnalysis(const SourceInfo::ArgNames& args, CFG* cfg, ScopeInfo* scope_info);
DefinednessAnalysis(const ParamNames& param_names, CFG* cfg, ScopeInfo* scope_info);
DefinitionLevel isDefinedAtEnd(const std::string& name, CFGBlock* block);
const RequiredSet& getDefinedNamesAtEnd(CFGBlock* block);
......@@ -91,7 +91,7 @@ private:
std::unordered_map<CFGBlock*, const RequiredSet> required_phis;
public:
PhiAnalysis(const SourceInfo::ArgNames&, CFG* cfg, LivenessAnalysis* liveness, ScopeInfo* scope_info);
PhiAnalysis(const ParamNames&, CFG* cfg, LivenessAnalysis* liveness, ScopeInfo* scope_info);
bool isRequired(const std::string& name, CFGBlock* block);
bool isRequiredAfter(const std::string& name, CFGBlock* block);
......@@ -102,7 +102,7 @@ public:
};
LivenessAnalysis* computeLivenessInfo(CFG*);
PhiAnalysis* computeRequiredPhis(const SourceInfo::ArgNames&, CFG*, LivenessAnalysis*, ScopeInfo* scope_Info);
PhiAnalysis* computeRequiredPhis(const ParamNames&, CFG*, LivenessAnalysis*, ScopeInfo* scope_Info);
}
#endif
......@@ -670,7 +670,7 @@ public:
return changed;
}
static PropagatingTypeAnalysis* doAnalysis(CFG* cfg, const SourceInfo::ArgNames& arg_names,
static PropagatingTypeAnalysis* doAnalysis(CFG* cfg, const ParamNames& arg_names,
const std::vector<ConcreteCompilerType*>& arg_types,
SpeculationLevel speculation, ScopeInfo* scope_info) {
Timer _t("PropagatingTypeAnalysis::doAnalysis()");
......@@ -681,30 +681,25 @@ public:
assert(arg_names.totalParameters() == arg_types.size());
if (arg_names.args) {
TypeMap& initial_types = starting_types[cfg->getStartingBlock()];
int i = 0;
TypeMap& initial_types = starting_types[cfg->getStartingBlock()];
int i = 0;
for (; i < arg_names.args->size(); i++) {
AST_expr* arg = (*arg_names.args)[i];
RELEASE_ASSERT(arg->type == AST_TYPE::Name, "");
AST_Name* arg_name = ast_cast<AST_Name>(arg);
initial_types[arg_name->id] = unboxedType(arg_types[i]);
}
if (arg_names.vararg->size()) {
initial_types[*arg_names.vararg] = unboxedType(arg_types[i]);
i++;
}
for (; i < arg_names.args.size(); i++) {
initial_types[arg_names.args[i]] = unboxedType(arg_types[i]);
}
if (arg_names.kwarg->size()) {
initial_types[*arg_names.kwarg] = unboxedType(arg_types[i]);
i++;
}
if (arg_names.vararg.size()) {
initial_types[arg_names.vararg] = unboxedType(arg_types[i]);
i++;
}
assert(i == arg_types.size());
if (arg_names.kwarg.size()) {
initial_types[arg_names.kwarg] = unboxedType(arg_types[i]);
i++;
}
assert(i == arg_types.size());
std::unordered_set<CFGBlock*> in_queue;
std::priority_queue<CFGBlock*, std::vector<CFGBlock*>, CFGBlockMinIndex> queue;
queue.push(cfg->getStartingBlock());
......@@ -785,9 +780,9 @@ public:
// public entry point:
TypeAnalysis* doTypeAnalysis(CFG* cfg, const SourceInfo::ArgNames& arg_names,
const std::vector<ConcreteCompilerType*>& arg_types, EffortLevel::EffortLevel effort,
TypeAnalysis::SpeculationLevel speculation, ScopeInfo* scope_info) {
TypeAnalysis* doTypeAnalysis(CFG* cfg, const ParamNames& arg_names, const std::vector<ConcreteCompilerType*>& arg_types,
EffortLevel::EffortLevel effort, TypeAnalysis::SpeculationLevel speculation,
ScopeInfo* scope_info) {
// if (effort == EffortLevel::INTERPRETED) {
// return new NullTypeAnalysis();
//}
......
......@@ -42,7 +42,7 @@ public:
};
// TypeAnalysis* analyze(CFG *cfg, std::unordered_map<std::string, ConcreteCompilerType*> arg_types);
TypeAnalysis* doTypeAnalysis(CFG* cfg, const SourceInfo::ArgNames& arg_names,
TypeAnalysis* doTypeAnalysis(CFG* cfg, const ParamNames& param_names,
const std::vector<ConcreteCompilerType*>& arg_types, EffortLevel::EffortLevel effort,
TypeAnalysis::SpeculationLevel speculation, ScopeInfo* scope_info);
}
......
......@@ -254,21 +254,19 @@ void ASTInterpreter::initArguments(int nargs, BoxedClosure* _closure, BoxedGener
for (int i = 3; i < nargs; ++i)
argsArray.push_back(args[i - 3]);
const ParamNames& param_names = compiled_func->clfunc->param_names;
int i = 0;
if (source_info->arg_names.args) {
for (AST_expr* e : *source_info->arg_names.args) {
RELEASE_ASSERT(e->type == AST_TYPE::Name, "not implemented");
AST_Name* name = (AST_Name*)e;
doStore(name->id, argsArray[i++]);
}
for (const std::string& name : param_names.args) {
doStore(name, argsArray[i++]);
}
if (source_info->arg_names.vararg && !source_info->arg_names.vararg->empty()) {
doStore(*source_info->arg_names.vararg, argsArray[i++]);
if (!param_names.vararg.empty()) {
doStore(param_names.vararg, argsArray[i++]);
}
if (source_info->arg_names.kwarg && !source_info->arg_names.kwarg->empty()) {
doStore(*source_info->arg_names.kwarg, argsArray[i++]);
if (!param_names.kwarg.empty()) {
doStore(param_names.kwarg, argsArray[i++]);
}
}
......@@ -315,8 +313,8 @@ void ASTInterpreter::eraseDeadSymbols() {
source_info->liveness = computeLivenessInfo(source_info->cfg);
if (source_info->phis == NULL)
source_info->phis
= computeRequiredPhis(source_info->arg_names, source_info->cfg, source_info->liveness, scope_info);
source_info->phis = computeRequiredPhis(compiled_func->clfunc->param_names, source_info->cfg,
source_info->liveness, scope_info);
std::vector<std::string> dead_symbols;
for (auto&& it : sym_table) {
......
......@@ -34,7 +34,7 @@ namespace pyston {
DS_DEFINE_RWLOCK(codegen_rwlock);
SourceInfo::SourceInfo(BoxedModule* m, ScopingAnalysis* scoping, AST* ast, const std::vector<AST_stmt*>& body)
: parent_module(m), scoping(scoping), ast(ast), cfg(NULL), liveness(NULL), phis(NULL), arg_names(ast), body(body) {
: parent_module(m), scoping(scoping), ast(ast), cfg(NULL), liveness(NULL), phis(NULL), body(body) {
switch (ast->type) {
case AST_TYPE::ClassDef:
case AST_TYPE::Lambda:
......
......@@ -663,7 +663,7 @@ static void emitBBs(IRGenState* irstate, const char* bb_type, GuardList& out_gua
emitter->getBuilder()->SetInsertPoint(llvm_entry_blocks[source->cfg->getStartingBlock()]);
}
generator->doFunctionEntry(source->arg_names, cf->spec->arg_types);
generator->doFunctionEntry(*irstate->getParamNames(), cf->spec->arg_types);
// Function-entry safepoint:
// TODO might be more efficient to do post-call safepoints?
......@@ -1085,7 +1085,7 @@ static std::string getUniqueFunctionName(std::string nameprefix, EffortLevel::Ef
return os.str();
}
CompiledFunction* doCompile(SourceInfo* source, const OSREntryDescriptor* entry_descriptor,
CompiledFunction* doCompile(SourceInfo* source, ParamNames* param_names, const OSREntryDescriptor* entry_descriptor,
EffortLevel::EffortLevel effort, FunctionSpecialization* spec, std::string nameprefix) {
Timer _t("in doCompile");
Timer _t2;
......@@ -1107,7 +1107,7 @@ CompiledFunction* doCompile(SourceInfo* source, const OSREntryDescriptor* entry_
////
// Initializing the llvm-level structures:
int nargs = source->arg_names.totalParameters();
int nargs = param_names->totalParameters();
ASSERT(nargs == spec->arg_types.size(), "%d %ld", nargs, spec->arg_types.size());
......@@ -1155,8 +1155,8 @@ CompiledFunction* doCompile(SourceInfo* source, const OSREntryDescriptor* entry_
TypeAnalysis::SpeculationLevel speculation_level = TypeAnalysis::NONE;
if (ENABLE_SPECULATION && effort >= EffortLevel::MODERATE)
speculation_level = TypeAnalysis::SOME;
TypeAnalysis* types = doTypeAnalysis(source->cfg, source->arg_names, spec->arg_types, effort, speculation_level,
source->getScopeInfo());
TypeAnalysis* types
= doTypeAnalysis(source->cfg, *param_names, spec->arg_types, effort, speculation_level, source->getScopeInfo());
_t2.split();
......@@ -1172,7 +1172,7 @@ CompiledFunction* doCompile(SourceInfo* source, const OSREntryDescriptor* entry_
computeBlockSetClosure(full_blocks, partial_blocks);
}
IRGenState irstate(cf, source, getGCBuilder(), dbg_funcinfo);
IRGenState irstate(cf, source, param_names, getGCBuilder(), dbg_funcinfo);
emitBBs(&irstate, "opt", guards, GuardList(), types, entry_descriptor, full_blocks, partial_blocks);
......@@ -1194,7 +1194,7 @@ CompiledFunction* doCompile(SourceInfo* source, const OSREntryDescriptor* entry_
assert(deopt_full_blocks.size() || deopt_partial_blocks.size());
irgen_us += _t2.split();
TypeAnalysis* deopt_types = doTypeAnalysis(source->cfg, source->arg_names, spec->arg_types, effort,
TypeAnalysis* deopt_types = doTypeAnalysis(source->cfg, *param_names, spec->arg_types, effort,
TypeAnalysis::NONE, source->getScopeInfo());
_t2.split();
......
......@@ -94,7 +94,7 @@ extern const std::string PASSED_GENERATOR_NAME;
std::string getIsDefinedName(const std::string& name);
bool isIsDefinedName(const std::string& name);
CompiledFunction* doCompile(SourceInfo* source, const OSREntryDescriptor* entry_descriptor,
CompiledFunction* doCompile(SourceInfo* source, ParamNames* param_names, const OSREntryDescriptor* entry_descriptor,
EffortLevel::EffortLevel effort, FunctionSpecialization* spec, std::string nameprefix);
// A common pattern is to branch based off whether a variable is defined but only if it is
......
......@@ -42,25 +42,36 @@
namespace pyston {
// TODO terrible place for these!
SourceInfo::ArgNames::ArgNames(AST* ast) {
ParamNames::ParamNames(AST* ast) : takes_param_names(true) {
if (ast->type == AST_TYPE::Module || ast->type == AST_TYPE::ClassDef) {
args = NULL;
kwarg = vararg = NULL;
} else if (ast->type == AST_TYPE::FunctionDef) {
AST_FunctionDef* f = ast_cast<AST_FunctionDef>(ast);
args = &f->args->args;
vararg = &f->args->vararg;
kwarg = &f->args->kwarg;
} else if (ast->type == AST_TYPE::Lambda) {
AST_Lambda* l = ast_cast<AST_Lambda>(ast);
args = &l->args->args;
vararg = &l->args->vararg;
kwarg = &l->args->kwarg;
kwarg = "";
vararg = "";
} else if (ast->type == AST_TYPE::FunctionDef || ast->type == AST_TYPE::Lambda) {
AST_arguments* arguments = ast->type == AST_TYPE::FunctionDef ? ast_cast<AST_FunctionDef>(ast)->args
: ast_cast<AST_Lambda>(ast)->args;
for (int i = 0; i < arguments->args.size(); i++) {
AST_expr* arg = arguments->args[i];
if (arg->type == AST_TYPE::Name) {
args.push_back(ast_cast<AST_Name>(arg)->id);
} else {
args.push_back("." + std::to_string(i + 1));
}
}
vararg = arguments->vararg;
kwarg = arguments->kwarg;
} else {
RELEASE_ASSERT(0, "%d", ast->type);
}
}
ParamNames::ParamNames(const std::vector<std::string>& args, const std::string& vararg, const std::string& kwarg)
: takes_param_names(true) {
this->args = args;
this->vararg = vararg;
this->kwarg = kwarg;
}
std::string SourceInfo::mangleName(const std::string& id) {
assert(ast);
if (ast->type == AST_TYPE::Module)
......@@ -192,8 +203,7 @@ CompiledFunction* compileFunction(CLFunction* f, FunctionSpecialization* spec, E
source->liveness = computeLivenessInfo(source->cfg);
if (source->phis == NULL)
source->phis
= computeRequiredPhis(source->arg_names, source->cfg, source->liveness, source->getScopeInfo());
source->phis = computeRequiredPhis(f->param_names, source->cfg, source->liveness, source->getScopeInfo());
}
......@@ -202,7 +212,7 @@ CompiledFunction* compileFunction(CLFunction* f, FunctionSpecialization* spec, E
if (effort == EffortLevel::INTERPRETED) {
cf = new CompiledFunction(0, spec, true, NULL, NULL, effort, 0);
} else {
cf = doCompile(source, entry, effort, spec, name);
cf = doCompile(source, &f->param_names, entry, effort, spec, name);
compileIR(cf, effort);
}
......@@ -370,17 +380,26 @@ extern "C" char* reoptCompiledFunc(CompiledFunction* cf) {
return (char*)reoptCompiledFuncInternal(cf)->code;
}
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);
CLFunction* createRTFunction(int num_args, int num_defaults, bool takes_varargs, bool takes_kwargs,
const ParamNames& param_names) {
return new CLFunction(num_args, num_defaults, takes_varargs, takes_kwargs, param_names);
}
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, const ParamNames& param_names) {
assert(!param_names.takes_param_names || num_args == param_names.args.size());
assert(param_names.vararg == "");
assert(param_names.kwarg == "");
return boxRTFunction(f, rtn_type, num_args, 0, false, false, param_names);
}
CLFunction* boxRTFunction(void* f, ConcreteCompilerType* rtn_type, int num_args, int num_defaults, bool takes_varargs,
bool takes_kwargs) {
CLFunction* cl_f = createRTFunction(num_args, num_defaults, takes_varargs, takes_kwargs);
bool takes_kwargs, const ParamNames& param_names) {
assert(!param_names.takes_param_names || num_args == param_names.args.size());
assert(takes_varargs || param_names.vararg == "");
assert(takes_kwargs || param_names.kwarg == "");
CLFunction* cl_f = createRTFunction(num_args, num_defaults, takes_varargs, takes_kwargs, param_names);
addRTFunction(cl_f, f, rtn_type);
return cl_f;
......
......@@ -2413,9 +2413,8 @@ public:
return CLOSURE;
}
void doFunctionEntry(const SourceInfo::ArgNames& arg_names,
const std::vector<ConcreteCompilerType*>& arg_types) override {
assert(arg_names.totalParameters() == arg_types.size());
void doFunctionEntry(const ParamNames& param_names, const std::vector<ConcreteCompilerType*>& arg_types) override {
assert(param_names.totalParameters() == arg_types.size());
auto scope_info = irstate->getScopeInfo();
......@@ -2467,26 +2466,24 @@ public:
}
assert(AI == irstate->getLLVMFunction()->arg_end());
assert(python_parameters.size() == arg_names.totalParameters());
assert(python_parameters.size() == param_names.totalParameters());
if (arg_names.args) {
int i = 0;
for (; i < arg_names.args->size(); i++) {
loadArgument((*arg_names.args)[i], arg_types[i], python_parameters[i], UnwindInfo::cantUnwind());
}
if (arg_names.vararg->size()) {
loadArgument(*arg_names.vararg, arg_types[i], python_parameters[i], UnwindInfo::cantUnwind());
i++;
}
int i = 0;
for (; i < param_names.args.size(); i++) {
loadArgument(param_names.args[i], arg_types[i], python_parameters[i], UnwindInfo::cantUnwind());
}
if (arg_names.kwarg->size()) {
loadArgument(*arg_names.kwarg, arg_types[i], python_parameters[i], UnwindInfo::cantUnwind());
i++;
}
if (param_names.vararg.size()) {
loadArgument(param_names.vararg, arg_types[i], python_parameters[i], UnwindInfo::cantUnwind());
i++;
}
assert(i == arg_types.size());
if (param_names.kwarg.size()) {
loadArgument(param_names.kwarg, arg_types[i], python_parameters[i], UnwindInfo::cantUnwind());
i++;
}
assert(i == arg_types.size());
}
void run(const CFGBlock* block) override {
......
......@@ -54,6 +54,7 @@ class IRGenState {
private:
CompiledFunction* cf;
SourceInfo* source_info;
ParamNames* param_names;
GCBuilder* gc;
llvm::MDNode* func_dbg_info;
......@@ -62,9 +63,10 @@ private:
int scratch_size;
public:
IRGenState(CompiledFunction* cf, SourceInfo* source_info, GCBuilder* gc, llvm::MDNode* func_dbg_info)
: cf(cf), source_info(source_info), gc(gc), func_dbg_info(func_dbg_info), scratch_space(NULL), frame_info(NULL),
scratch_size(0) {
IRGenState(CompiledFunction* cf, SourceInfo* source_info, ParamNames* param_names, GCBuilder* gc,
llvm::MDNode* func_dbg_info)
: cf(cf), source_info(source_info), param_names(param_names), gc(gc), func_dbg_info(func_dbg_info),
scratch_space(NULL), frame_info(NULL), scratch_size(0) {
assert(cf->func);
assert(!cf->clfunc); // in this case don't need to pass in sourceinfo
}
......@@ -91,6 +93,8 @@ public:
ScopeInfo* getScopeInfoForNode(AST* node);
llvm::MDNode* getFuncDbgInfo() { return func_dbg_info; }
ParamNames* getParamNames() { return param_names; }
};
class GuardList {
......@@ -193,8 +197,8 @@ public:
virtual ~IRGenerator() {}
virtual void doFunctionEntry(const SourceInfo::ArgNames& arg_names,
const std::vector<ConcreteCompilerType*>& arg_types) = 0;
virtual void doFunctionEntry(const ParamNames& param_names, const std::vector<ConcreteCompilerType*>& arg_types)
= 0;
virtual void giveLocalSymbol(const std::string& name, CompilerVariable* var) = 0;
virtual void copySymbolsFrom(SymbolTable* st) = 0;
......
......@@ -212,6 +212,21 @@ public:
~CompiledFunction();
};
struct ParamNames {
bool takes_param_names;
std::vector<std::string> args;
std::string vararg, kwarg;
explicit ParamNames(AST* ast);
ParamNames(const std::vector<std::string>& args, const std::string& vararg, const std::string& kwarg);
static ParamNames empty() { return ParamNames(); }
int totalParameters() const { return args.size() + (vararg.size() == 0 ? 0 : 1) + (kwarg.size() == 0 ? 0 : 1); }
private:
ParamNames() : takes_param_names(false) {}
};
class BoxedModule;
class ScopeInfo;
class SourceInfo {
......@@ -226,20 +241,6 @@ public:
ScopeInfo* getScopeInfo();
struct ArgNames {
const std::vector<AST_expr*>* args;
const std::string* vararg, *kwarg;
explicit ArgNames(AST* ast);
int totalParameters() const {
if (!args)
return 0;
return args->size() + (vararg->size() == 0 ? 0 : 1) + (kwarg->size() == 0 ? 0 : 1);
}
};
ArgNames arg_names;
// TODO we're currently copying the body of the AST into here, since lambdas don't really have a statement-based
// body and we have to create one. Ideally, we'd be able to avoid the space duplication for non-lambdas.
const std::vector<AST_stmt*> body;
......@@ -259,6 +260,8 @@ public:
bool takes_varargs, takes_kwargs;
SourceInfo* source;
ParamNames param_names;
FunctionList
versions; // any compiled versions along with their type parameters; in order from most preferred to least
std::unordered_map<const OSREntryDescriptor*, CompiledFunction*> osr_versions;
......@@ -273,14 +276,17 @@ public:
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) {
source(source), param_names(source->ast) {
assert(num_args >= num_defaults);
}
CLFunction(int num_args, int num_defaults, bool takes_varargs, bool takes_kwargs, const ParamNames& param_names)
: num_args(num_args), num_defaults(num_defaults), takes_varargs(takes_varargs), takes_kwargs(takes_kwargs),
source(NULL), param_names(param_names) {
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(compiled->spec);
......@@ -296,10 +302,12 @@ public:
}
};
CLFunction* createRTFunction(int num_args, int num_defaults, bool takes_varargs, bool takes_kwargs);
CLFunction* createRTFunction(int num_args, int num_defaults, bool takes_varargs, bool takes_kwargs,
const ParamNames& param_names = ParamNames::empty());
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);
bool takes_kwargs, const ParamNames& param_names = ParamNames::empty());
CLFunction* boxRTFunction(void* f, ConcreteCompilerType* rtn_type, int nargs,
const ParamNames& param_names = ParamNames::empty());
void addRTFunction(CLFunction* cf, void* f, ConcreteCompilerType* rtn_type);
void addRTFunction(CLFunction* cf, void* f, ConcreteCompilerType* rtn_type,
const std::vector<ConcreteCompilerType*>& arg_types);
......
......@@ -425,7 +425,9 @@ Box* notimplementedRepr(Box* self) {
return boxStrConstant("NotImplemented");
}
Box* sorted(Box* obj) {
Box* sorted(Box* obj, Box* key, Box* cmp, Box** args) {
Box* reverse = args[0];
BoxedList* rtn = new BoxedList();
for (Box* e : obj->pyElements()) {
listAppendInternal(rtn, e);
......@@ -1115,10 +1117,10 @@ void setupBuiltins() {
builtins_module->giveAttr("enumerate", enumerate_cls);
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));
CLFunction* sorted_func = createRTFunction(4, 3, false, false, ParamNames({ "", "cmp", "key", "reverse" }, "", ""));
addRTFunction(sorted_func, (void*)sortedList, LIST, { LIST, UNKNOWN, UNKNOWN, UNKNOWN });
addRTFunction(sorted_func, (void*)sorted, LIST, { UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN });
builtins_module->giveAttr("sorted", new BoxedFunction(sorted_func, { None, None, False }));
builtins_module->giveAttr("True", True);
builtins_module->giveAttr("False", False);
......@@ -1129,8 +1131,9 @@ void setupBuiltins() {
setupXrange();
builtins_module->giveAttr("xrange", xrange_cls);
open_obj = new BoxedFunction(boxRTFunction((void*)open, typeFromClass(file_cls), 2, 1, false, false),
{ boxStrConstant("r") });
open_obj = new BoxedFunction(
boxRTFunction((void*)open, typeFromClass(file_cls), 2, 1, false, false, ParamNames({ "name", "mode" }, "", "")),
{ boxStrConstant("r") });
builtins_module->giveAttr("open", open_obj);
builtins_module->giveAttr("globals", new BoxedFunction(boxRTFunction((void*)globals, UNKNOWN, 0, 0, false, false)));
......
......@@ -1718,8 +1718,7 @@ extern "C" bool nonzero(Box* obj) {
if (func == NULL) {
ASSERT(isUserDefined(obj->cls) || obj->cls == classobj_cls || obj->cls == type_cls
|| isSubclass(obj->cls, Exception),
"%s.__nonzero__",
getTypeName(obj)->c_str()); // TODO
"%s.__nonzero__", getTypeName(obj)->c_str()); // TODO
return true;
}
......@@ -2276,19 +2275,14 @@ static std::string getFunctionName(CLFunction* f) {
return "<unknown function>";
}
static void placeKeyword(const std::vector<AST_expr*>& arg_names, std::vector<bool>& params_filled,
const std::string& kw_name, Box* kw_val, Box*& oarg1, Box*& oarg2, Box*& oarg3, Box** oargs,
BoxedDict* okwargs, CLFunction* cl) {
static void placeKeyword(const ParamNames& param_names, std::vector<bool>& params_filled, const std::string& kw_name,
Box* kw_val, Box*& oarg1, Box*& oarg2, Box*& oarg3, Box** oargs, BoxedDict* okwargs,
CLFunction* cl) {
assert(kw_val);
bool found = false;
for (int j = 0; j < arg_names.size(); j++) {
AST_expr* e = arg_names[j];
if (e->type != AST_TYPE::Name)
continue;
AST_Name* n = ast_cast<AST_Name>(e);
if (n->id == kw_name) {
for (int j = 0; j < param_names.args.size(); j++) {
if (param_names.args[j] == kw_name && kw_name.size() > 0) {
if (params_filled[j]) {
raiseExcHelper(TypeError, "%.200s() got multiple values for keyword argument '%s'",
getFunctionName(cl).c_str(), kw_name.c_str());
......@@ -2476,8 +2470,8 @@ Box* callFunc(BoxedFunction* func, CallRewriteArgs* rewrite_args, ArgPassSpec ar
getArg(f->num_args + (f->takes_varargs ? 1 : 0), oarg1, oarg2, oarg3, oargs) = okwargs;
}
const std::vector<AST_expr*>* arg_names = f->source ? f->source->arg_names.args : NULL;
if (arg_names == nullptr && argspec.num_keywords && !f->takes_kwargs) {
const ParamNames& param_names = f->param_names;
if (!param_names.takes_param_names && argspec.num_keywords && !f->takes_kwargs) {
raiseExcHelper(TypeError, "%s() doesn't take keyword arguments", getFunctionName(f).c_str());
}
......@@ -2490,15 +2484,13 @@ Box* callFunc(BoxedFunction* func, CallRewriteArgs* rewrite_args, ArgPassSpec ar
int arg_idx = i + argspec.num_args;
Box* kw_val = getArg(arg_idx, arg1, arg2, arg3, args);
if (!arg_names) {
if (!param_names.takes_param_names) {
assert(okwargs);
okwargs->d[boxStringPtr((*keyword_names)[i])] = kw_val;
continue;
}
assert(arg_names);
placeKeyword(*arg_names, params_filled, *(*keyword_names)[i], kw_val, oarg1, oarg2, oarg3, oargs, okwargs, f);
placeKeyword(param_names, params_filled, *(*keyword_names)[i], kw_val, oarg1, oarg2, oarg3, oargs, okwargs, f);
}
if (argspec.has_kwargs) {
......@@ -2515,8 +2507,8 @@ Box* callFunc(BoxedFunction* func, CallRewriteArgs* rewrite_args, ArgPassSpec ar
BoxedString* s = static_cast<BoxedString*>(p.first);
if (arg_names) {
placeKeyword(*arg_names, params_filled, s->s, p.second, oarg1, oarg2, oarg3, oargs, okwargs, f);
if (param_names.takes_param_names) {
placeKeyword(param_names, params_filled, s->s, p.second, oarg1, oarg2, oarg3, oargs, okwargs, f);
} else {
assert(okwargs);
......
f = open(**{"name": "/dev/null", "mode": "r"})
print repr(f.read())
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