Commit 9a33763c authored by Kevin Modzelewski's avatar Kevin Modzelewski

Some initial refactoring work for arg passing

Replace a simple "num_args" argument with a packed struct that takes
num_args and adds num_keywords, has_varargs, and has_kwargs.  Tried
to add asserts in all the places that don't allow
keywords/varargs/starargs

Started refactoring things; got to the point of attempting
argument->parameter shuffling, but it's tricky if we allow every
compilation to have a different signature (used by builtins).
Really they all have the same signatures but different
specializations; to get to that point, need to add defaults.
parent a8c83341
......@@ -273,7 +273,7 @@ pyston_all: pyston_dbg pyston pyston_oprof pyston_prof $(OPTIONAL_SRCS:.cpp=.o)
ALL_HEADERS := $(wildcard */*.h) $(wildcard */*/*.h)
tags: $(SRCS) $(OPTIONAL_SRCS) $(ALL_HEADERS)
$(ECHO) Computing tags...
$(ECHO) Calculating tags...
$(VERB) ctags $^
$(UNITTEST_SRCS:.cpp=.o): CXXFLAGS := $(CXXFLAGS) -isystem $(GTEST_DIR)/include
......
......@@ -210,7 +210,7 @@ private:
std::vector<CompilerType*> arg_types;
arg_types.push_back(right);
CompilerType* rtn = attr_type->callType(arg_types);
CompilerType* rtn = attr_type->callType(ArgPassSpec(2), arg_types, NULL);
if (left == right && (left == INT || left == FLOAT)) {
ASSERT((rtn == left || rtn == UNKNOWN) && "not strictly required but probably something worth looking into",
......@@ -237,7 +237,7 @@ private:
std::vector<CompilerType*> arg_types;
arg_types.push_back(right);
CompilerType* rtn = attr_type->callType(arg_types);
CompilerType* rtn = attr_type->callType(ArgPassSpec(2), arg_types, NULL);
if (left == right && (left == INT || left == FLOAT)) {
ASSERT((rtn == left || rtn == UNKNOWN) && "not strictly required but probably something worth looking into",
......@@ -287,7 +287,7 @@ private:
return UNKNOWN;
}
CompilerType* rtn_type = func->callType(arg_types);
CompilerType* rtn_type = func->callType(ArgPassSpec(arg_types.size()), arg_types, NULL);
// Should be unboxing things before getting here:
ASSERT(rtn_type == unboxedType(rtn_type->getConcreteType()), "%s", rtn_type->debugName().c_str());
......@@ -322,7 +322,7 @@ private:
std::vector<CompilerType*> arg_types;
arg_types.push_back(right);
return attr_type->callType(arg_types);
return attr_type->callType(ArgPassSpec(2), arg_types, NULL);
}
virtual void* visit_dict(AST_Dict* node) {
......@@ -404,7 +404,7 @@ private:
CompilerType* getitem_type = val->getattrType(&name, true);
std::vector<CompilerType*> args;
args.push_back(slice);
return getitem_type->callType(args);
return getitem_type->callType(ArgPassSpec(1), args, NULL);
}
virtual void* visit_tuple(AST_Tuple* node) {
......@@ -422,7 +422,7 @@ private:
const std::string& name = getOpName(node->op_type);
CompilerType* attr_type = operand->getattrType(&name, true);
std::vector<CompilerType*> arg_types;
return attr_type->callType(arg_types);
return attr_type->callType(ArgPassSpec(0), arg_types, NULL);
}
......
......@@ -72,6 +72,7 @@ struct GlobalState {
llvm::Type* llvm_clfunction_type_ptr;
llvm::Type* llvm_module_type_ptr, *llvm_bool_type_ptr;
llvm::Type* i1, *i8, *i8_ptr, *i32, *i64, *void_, *double_;
llvm::Type* vector_ptr;
GlobalFuncs funcs;
......
This diff is collapsed.
......@@ -40,7 +40,8 @@ public:
virtual ConcreteCompilerType* getBoxType() = 0;
virtual bool canConvertTo(ConcreteCompilerType* other_type) = 0;
virtual CompilerType* getattrType(const std::string* attr, bool cls_only) = 0;
virtual CompilerType* callType(std::vector<CompilerType*>& arg_types) = 0;
virtual CompilerType* callType(ArgPassSpec argspec, const std::vector<CompilerType*>& arg_types,
const std::vector<const std::string*>* keyword_names) = 0;
virtual BoxedClass* guaranteedClass() = 0;
};
......@@ -93,12 +94,15 @@ public:
abort();
}
virtual CompilerVariable* callattr(IREmitter& emitter, const OpInfo& info, VAR* value, const std::string* attr,
bool clsonly, const std::vector<CompilerVariable*>& args) {
bool clsonly, struct ArgPassSpec argspec,
const std::vector<CompilerVariable*>& args,
const std::vector<const std::string*>* keyword_names) {
printf("callattr not defined for %s\n", debugName().c_str());
abort();
}
virtual CompilerVariable* call(IREmitter& emitter, const OpInfo& info, VAR* value,
const std::vector<CompilerVariable*>& args) {
virtual CompilerVariable* call(IREmitter& emitter, const OpInfo& info, VAR* value, struct ArgPassSpec argspec,
const std::vector<CompilerVariable*>& args,
const std::vector<const std::string*>* keyword_names) {
printf("call not defined for %s\n", debugName().c_str());
abort();
}
......@@ -122,7 +126,8 @@ public:
printf("getattrType not defined for %s\n", debugName().c_str());
abort();
}
CompilerType* callType(std::vector<CompilerType*>& arg_types) override {
CompilerType* callType(struct ArgPassSpec argspec, const std::vector<CompilerType*>& arg_types,
const std::vector<const std::string*>* keyword_names) override {
printf("callType not defined for %s\n", debugName().c_str());
abort();
}
......@@ -213,9 +218,11 @@ public:
= 0;
virtual void setattr(IREmitter& emitter, const OpInfo& info, const std::string* attr, CompilerVariable* v) = 0;
virtual CompilerVariable* callattr(IREmitter& emitter, const OpInfo& info, const std::string* attr, bool clsonly,
const std::vector<CompilerVariable*>& args) = 0;
virtual CompilerVariable* call(IREmitter& emitter, const OpInfo& info, const std::vector<CompilerVariable*>& args)
= 0;
struct ArgPassSpec argspec, const std::vector<CompilerVariable*>& args,
const std::vector<const std::string*>* keyword_names) = 0;
virtual CompilerVariable* call(IREmitter& emitter, const OpInfo& info, struct ArgPassSpec argspec,
const std::vector<CompilerVariable*>& args,
const std::vector<const std::string*>* keyword_names) = 0;
virtual void print(IREmitter& emitter, const OpInfo& info) = 0;
virtual ConcreteCompilerVariable* len(IREmitter& emitter, const OpInfo& info) = 0;
virtual CompilerVariable* getitem(IREmitter& emitter, const OpInfo& info, CompilerVariable*) = 0;
......@@ -273,12 +280,14 @@ public:
type->setattr(emitter, info, this, attr, v);
}
virtual CompilerVariable* callattr(IREmitter& emitter, const OpInfo& info, const std::string* attr, bool clsonly,
const std::vector<CompilerVariable*>& args) {
return type->callattr(emitter, info, this, attr, clsonly, args);
}
CompilerVariable* call(IREmitter& emitter, const OpInfo& info,
const std::vector<CompilerVariable*>& args) override {
return type->call(emitter, info, this, args);
struct ArgPassSpec argspec, const std::vector<CompilerVariable*>& args,
const std::vector<const std::string*>* keyword_names) {
return type->callattr(emitter, info, this, attr, clsonly, argspec, args, keyword_names);
}
CompilerVariable* call(IREmitter& emitter, const OpInfo& info, struct ArgPassSpec argspec,
const std::vector<CompilerVariable*>& args,
const std::vector<const std::string*>* keyword_names) override {
return type->call(emitter, info, this, argspec, args, keyword_names);
}
void print(IREmitter& emitter, const OpInfo& info) override { type->print(emitter, info, this); }
ConcreteCompilerVariable* len(IREmitter& emitter, const OpInfo& info) override {
......
......@@ -881,10 +881,10 @@ static std::string getUniqueFunctionName(std::string nameprefix, EffortLevel::Ef
return os.str();
}
CompiledFunction* compileFunction(SourceInfo* source, const OSREntryDescriptor* entry_descriptor,
CompiledFunction* doCompile(SourceInfo* source, const OSREntryDescriptor* entry_descriptor,
EffortLevel::EffortLevel effort, FunctionSignature* sig,
const std::vector<AST_expr*>& arg_names, std::string nameprefix) {
Timer _t("in compileFunction");
Timer _t("in doCompile");
if (VERBOSITY("irgen") >= 1)
source->cfg->print();
......
......@@ -76,7 +76,7 @@ public:
const std::vector<llvm::Value*>& args, ExcInfo exc_info) = 0;
};
CompiledFunction* compileFunction(SourceInfo* source, const OSREntryDescriptor* entry_descriptor,
CompiledFunction* doCompile(SourceInfo* source, const OSREntryDescriptor* entry_descriptor,
EffortLevel::EffortLevel effort, FunctionSignature* sig,
const std::vector<AST_expr*>& arg_names, std::string nameprefix);
......
This diff is collapsed.
......@@ -190,6 +190,17 @@ IREmitter* createIREmitter(IRGenState* irstate, llvm::BasicBlock*& curblock) {
return new IREmitterImpl(irstate, curblock);
}
static std::unordered_map<AST_expr*, std::vector<const std::string*>*> made_keyword_storage;
static std::vector<const std::string*>* getKeywordNameStorage(AST_Call* node) {
auto it = made_keyword_storage.find(node);
if (it != made_keyword_storage.end())
return it->second;
auto rtn = new std::vector<const std::string*>();
made_keyword_storage.insert(it, std::make_pair(node, rtn));
return rtn;
}
class IRGeneratorImpl : public IRGenerator {
private:
IRGenState* irstate;
......@@ -623,10 +634,6 @@ private:
CompilerVariable* evalCall(AST_Call* node, ExcInfo exc_info) {
assert(state != PARTIAL);
assert(!node->starargs);
assert(!node->kwargs);
assert(!node->keywords.size());
bool is_callattr;
bool callattr_clsonly = false;
std::string* attr = NULL;
......@@ -649,19 +656,42 @@ private:
}
std::vector<CompilerVariable*> args;
std::vector<const std::string*>* keyword_names;
if (node->keywords.size()) {
keyword_names = getKeywordNameStorage(node);
} else {
keyword_names = NULL;
}
for (int i = 0; i < node->args.size(); i++) {
CompilerVariable* a = evalExpr(node->args[i], exc_info);
args.push_back(a);
}
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)
args.push_back(evalExpr(node->starargs, exc_info));
if (node->kwargs)
args.push_back(evalExpr(node->kwargs, exc_info));
struct ArgPassSpec argspec(node->args.size(), node->keywords.size(), node->starargs != NULL,
node->kwargs != NULL);
// if (VERBOSITY("irgen") >= 1)
//_addAnnotation("before_call");
CompilerVariable* rtn;
if (is_callattr) {
rtn = func->callattr(emitter, getOpInfoForNode(node, exc_info), attr, callattr_clsonly, args);
rtn = func->callattr(emitter, getOpInfoForNode(node, exc_info), attr, callattr_clsonly, argspec, args,
keyword_names);
} else {
rtn = func->call(emitter, getOpInfoForNode(node, exc_info), args);
rtn = func->call(emitter, getOpInfoForNode(node, exc_info), argspec, args, keyword_names);
}
func->decvref(emitter);
......@@ -669,9 +699,6 @@ private:
args[i]->decvref(emitter);
}
// if (VERBOSITY("irgen") >= 1)
//_addAnnotation("end_of_call");
return rtn;
}
......@@ -693,7 +720,7 @@ private:
args.push_back(key);
args.push_back(value);
// TODO could use the internal _listAppend function to avoid incref/decref'ing None
CompilerVariable* rtn = setitem->call(emitter, getEmptyOpInfo(exc_info), args);
CompilerVariable* rtn = setitem->call(emitter, getEmptyOpInfo(exc_info), ArgPassSpec(2), args, NULL);
rtn->decvref(emitter);
key->decvref(emitter);
......
......@@ -642,12 +642,18 @@ Box* interpretFunction(llvm::Function* f, int nargs, Box* arg1, Box* arg2, Box*
int64_t)>(f)(args[0].n, args[1].n, args[2].n, args[3].n,
args[4].n, args[5].n, args[6].n);
break;
case 0b1000000000:
case 0b1000000000: // 512
r = reinterpret_cast<int64_t (*)(int64_t, int64_t, int64_t, int64_t, int64_t, int64_t,
int64_t, int64_t)>(f)(args[0].n, args[1].n, args[2].n,
args[3].n, args[4].n, args[5].n,
args[6].n, args[7].n);
break;
case 0b10000000000: // 1024
r = reinterpret_cast<int64_t (*)(int64_t, int64_t, int64_t, int64_t, int64_t, int64_t,
int64_t, int64_t, int64_t)>(
f)(args[0].n, args[1].n, args[2].n, args[3].n, args[4].n, args[5].n, args[6].n,
args[7].n, args[8].n);
break;
default:
inst->dump();
RELEASE_ASSERT(0, "%d", mask);
......
......@@ -132,6 +132,9 @@ void initGlobalFuncs(GlobalState& g) {
g.llvm_str_type_ptr = lookupFunction("boxStringPtr")->arg_begin()->getType();
auto vector_type = g.stdlib_module->getTypeByName("class.std::vector");
assert(vector_type);
g.vector_ptr = vector_type->getPointerTo();
#define GET(N) g.funcs.N = getFunc((void*)N, STRINGIFY(N))
......@@ -185,23 +188,23 @@ void initGlobalFuncs(GlobalState& g) {
GET(listAppendInternal);
g.funcs.runtimeCall = getFunc((void*)runtimeCall, "runtimeCall");
g.funcs.runtimeCall0 = addFunc((void*)runtimeCall, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.i64);
g.funcs.runtimeCall0 = addFunc((void*)runtimeCall, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.i32);
g.funcs.runtimeCall1
= addFunc((void*)runtimeCall, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.i64, g.llvm_value_type_ptr);
g.funcs.runtimeCall2 = addFunc((void*)runtimeCall, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.i64,
= addFunc((void*)runtimeCall, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.i32, g.llvm_value_type_ptr);
g.funcs.runtimeCall2 = addFunc((void*)runtimeCall, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.i32,
g.llvm_value_type_ptr, g.llvm_value_type_ptr);
g.funcs.runtimeCall3 = addFunc((void*)runtimeCall, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.i64,
g.funcs.runtimeCall3 = addFunc((void*)runtimeCall, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.i32,
g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.llvm_value_type_ptr);
g.funcs.callattr = getFunc((void*)callattr, "callattr");
g.funcs.callattr0
= addFunc((void*)callattr, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.llvm_str_type_ptr, g.i1, g.i64);
= addFunc((void*)callattr, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.llvm_str_type_ptr, g.i1, g.i32);
g.funcs.callattr1 = addFunc((void*)callattr, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.llvm_str_type_ptr,
g.i1, g.i64, g.llvm_value_type_ptr);
g.i1, g.i32, g.llvm_value_type_ptr);
g.funcs.callattr2 = addFunc((void*)callattr, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.llvm_str_type_ptr,
g.i1, g.i64, g.llvm_value_type_ptr, g.llvm_value_type_ptr);
g.i1, g.i32, g.llvm_value_type_ptr, g.llvm_value_type_ptr);
g.funcs.callattr3 = addFunc((void*)callattr, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.llvm_str_type_ptr,
g.i1, g.i64, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.llvm_value_type_ptr);
g.i1, g.i32, g.llvm_value_type_ptr, g.llvm_value_type_ptr, g.llvm_value_type_ptr);
g.funcs.reoptCompiledFunc = addFunc((void*)reoptCompiledFunc, g.i8_ptr, g.i8_ptr);
g.funcs.compilePartialFunc = addFunc((void*)compilePartialFunc, g.i8_ptr, g.i8_ptr);
......
......@@ -32,6 +32,31 @@ class Value;
namespace pyston {
struct ArgPassSpec {
bool has_starargs : 1;
bool has_kwargs : 1;
unsigned int num_keywords : 14;
unsigned int num_args : 16;
static const int MAX_ARGS = (1 << 16) - 1;
static const int MAX_KEYWORDS = (1 << 14) - 1;
explicit ArgPassSpec(int num_args) : has_starargs(false), has_kwargs(false), num_keywords(0), num_args(num_args) {
assert(num_args <= MAX_ARGS);
assert(num_keywords <= MAX_KEYWORDS);
}
explicit ArgPassSpec(int num_args, int num_keywords, bool has_starargs, bool has_kwargs)
: has_starargs(has_starargs), has_kwargs(has_kwargs), num_keywords(num_keywords), num_args(num_args) {
assert(num_args <= MAX_ARGS);
assert(num_keywords <= MAX_KEYWORDS);
}
int totalPassed() { return num_args + num_keywords + (has_starargs ? 1 : 0) + (has_kwargs ? 1 : 0); }
uintptr_t asInt() const { return *reinterpret_cast<const uintptr_t*>(this); }
};
static_assert(sizeof(ArgPassSpec) <= sizeof(void*), "ArgPassSpec doesn't fit in register!");
class GCVisitor {
public:
virtual ~GCVisitor() {}
......@@ -129,20 +154,30 @@ public:
struct FunctionSignature {
ConcreteCompilerType* rtn_type;
const std::vector<AST_expr*>* arg_names;
std::vector<ConcreteCompilerType*> arg_types;
bool is_vararg;
FunctionSignature(ConcreteCompilerType* rtn_type, bool is_vararg) : rtn_type(rtn_type), is_vararg(is_vararg) {}
FunctionSignature(ConcreteCompilerType* rtn_type, ConcreteCompilerType* arg1, ConcreteCompilerType* arg2,
bool is_vararg)
: rtn_type(rtn_type), is_vararg(is_vararg) {
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);
}
FunctionSignature(ConcreteCompilerType* rtn_type, std::vector<ConcreteCompilerType*>& arg_types, bool is_vararg)
: rtn_type(rtn_type), arg_types(arg_types), is_vararg(is_vararg) {}
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) {}
};
struct CompiledFunction {
......@@ -190,13 +225,23 @@ public:
SourceInfo(BoxedModule* m, ScopingAnalysis* scoping)
: parent_module(m), scoping(scoping), ast(NULL), cfg(NULL), liveness(NULL), phis(NULL) {}
};
typedef std::vector<CompiledFunction*> FunctionList;
class CallRewriteArgs;
struct CLFunction {
SourceInfo* source;
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;
// Functions can provide an "internal" version, which will get called instead
// of the normal dispatch through the functionlist.
// This can be used to implement functions which know how to rewrite themselves,
// such as typeCall.
typedef Box* (*InternalCallable)(BoxedFunction*, CallRewriteArgs*, ArgPassSpec, Box*, Box*, Box*, Box**,
const std::vector<const std::string*>*);
InternalCallable internal_callable = NULL;
CLFunction(SourceInfo* source) : source(source) {}
void addVersion(CompiledFunction* compiled) {
......@@ -215,14 +260,20 @@ struct CLFunction {
};
extern "C" CLFunction* createRTFunction();
extern "C" CLFunction* boxRTFunction(void* f, ConcreteCompilerType* rtn_type, int nargs, bool is_vararg);
void addRTFunction(CLFunction* cf, void* f, ConcreteCompilerType* rtn_type, int nargs, bool is_vararg);
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);
void addRTFunction(CLFunction* cf, void* f, ConcreteCompilerType* rtn_type,
const std::vector<ConcreteCompilerType*>& arg_types, bool is_vararg);
const std::vector<ConcreteCompilerType*>& arg_types, bool takes_varargs = false,
bool takes_kwargs = false);
CLFunction* unboxRTFunction(Box*);
// extern "C" CLFunction* boxRTFunctionVariadic(const char* name, int nargs_min, int nargs_max, void* f);
extern "C" CompiledFunction* resolveCLFunc(CLFunction* f, int64_t nargs, Box* arg1, Box* arg2, Box* arg3, Box** args);
extern "C" Box* callCompiledFunc(CompiledFunction* cf, int64_t nargs, Box* arg1, Box* arg2, Box* arg3, Box** args);
// 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,
const OSREntryDescriptor* entry);
EffortLevel::EffortLevel initialEffort();
typedef bool i1;
typedef int64_t i64;
......
......@@ -40,7 +40,8 @@ extern "C" Box* dir1(Box* obj) {
BoxedList* result = nullptr;
// If __dir__ is present just call it and return what it returns
static std::string attr_dir = "__dir__";
Box* dir_result = callattrInternal(obj, &attr_dir, CLASS_ONLY, nullptr, 0, nullptr, nullptr, nullptr, nullptr);
Box* dir_result = callattrInternal(obj, &attr_dir, CLASS_ONLY, nullptr, ArgPassSpec(0), nullptr, nullptr, nullptr,
nullptr, nullptr);
if (dir_result && dir_result->cls == list_cls) {
return dir_result;
}
......@@ -366,7 +367,7 @@ Box* hasattr(Box* obj, Box* _str) {
Box* map2(Box* f, Box* container) {
Box* rtn = new BoxedList();
for (Box* e : container->pyElements()) {
listAppendInternal(rtn, runtimeCall(f, 1, e, NULL, NULL, NULL));
listAppendInternal(rtn, runtimeCall(f, ArgPassSpec(1), e, NULL, NULL, NULL, NULL));
}
return rtn;
}
......
This diff is collapsed.
......@@ -39,8 +39,9 @@ extern "C" void my_assert(bool b);
extern "C" Box* getattr(Box* obj, const char* attr);
extern "C" void setattr(Box* obj, const char* attr, Box* attr_val);
extern "C" bool nonzero(Box* obj);
extern "C" Box* runtimeCall(Box*, int64_t, Box*, Box*, Box*, Box**);
extern "C" Box* callattr(Box*, std::string*, bool, int64_t, Box*, Box*, Box*, Box**);
extern "C" Box* runtimeCall(Box*, ArgPassSpec, Box*, Box*, Box*, Box**, const std::vector<const std::string*>*);
extern "C" Box* callattr(Box*, std::string*, bool, ArgPassSpec, Box*, Box*, Box*, Box**,
const std::vector<const std::string*>*);
extern "C" BoxedString* str(Box* obj);
extern "C" Box* repr(Box* obj);
extern "C" BoxedString* reprOrNull(Box* obj); // similar to repr, but returns NULL on exception
......@@ -73,6 +74,9 @@ extern "C" bool isSubclass(BoxedClass* child, BoxedClass* parent);
class BinopRewriteArgs;
extern "C" Box* binopInternal(Box* lhs, Box* rhs, int op_type, bool inplace, BinopRewriteArgs* rewrite_args);
Box* typeCallInternal(BoxedFunction* f, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2,
Box* arg3, Box** args, const std::vector<const std::string*>* keyword_names);
class CallRewriteArgs;
enum LookupScope {
CLASS_ONLY = 1,
......@@ -80,7 +84,8 @@ enum LookupScope {
CLASS_OR_INST = 3,
};
extern "C" Box* callattrInternal(Box* obj, const std::string* attr, LookupScope, CallRewriteArgs* rewrite_args,
int64_t nargs, Box* arg1, Box* arg2, Box* arg3, Box** args);
ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3, Box** args,
const std::vector<const std::string*>* keyword_names);
struct CompareRewriteArgs;
Box* compareInternal(Box* lhs, Box* rhs, int op_type, CompareRewriteArgs* rewrite_args);
......
......@@ -43,9 +43,9 @@ BoxIterator& BoxIterator::operator++() {
static std::string hasnext_str("__hasnext__");
static std::string next_str("next");
Box* hasnext = callattrInternal(iter, &hasnext_str, CLASS_ONLY, NULL, 0, NULL, NULL, NULL, NULL);
Box* hasnext = callattrInternal(iter, &hasnext_str, CLASS_ONLY, NULL, ArgPassSpec(0), NULL, NULL, NULL, NULL, NULL);
if (nonzero(hasnext)) {
value = callattrInternal(iter, &next_str, CLASS_ONLY, NULL, 0, NULL, NULL, NULL, NULL);
value = callattrInternal(iter, &next_str, CLASS_ONLY, NULL, ArgPassSpec(0), NULL, NULL, NULL, NULL, NULL);
} else {
iter = nullptr;
value = nullptr;
......@@ -56,7 +56,7 @@ BoxIterator& BoxIterator::operator++() {
llvm::iterator_range<BoxIterator> Box::pyElements() {
static std::string iter_str("__iter__");
Box* iter = callattr(const_cast<Box*>(this), &iter_str, true, 0, NULL, NULL, NULL, NULL);
Box* iter = callattr(const_cast<Box*>(this), &iter_str, true, ArgPassSpec(0), NULL, NULL, NULL, NULL, NULL);
if (iter) {
return llvm::iterator_range<BoxIterator>(++BoxIterator(iter), BoxIterator(nullptr));
}
......@@ -466,8 +466,11 @@ void setupRuntime() {
object_cls->giveAttr("__new__", new BoxedFunction(object_new));
object_cls->freeze();
auto typeCallObj = boxRTFunction((void*)typeCall, NULL, 1, true);
typeCallObj->internal_callable = &typeCallInternal;
type_cls->giveAttr("__call__", new BoxedFunction(typeCallObj));
type_cls->giveAttr("__name__", boxStrConstant("type"));
type_cls->giveAttr("__call__", new BoxedFunction(boxRTFunction((void*)typeCall, NULL, 1, true)));
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("__str__", type_cls->getattr("__repr__"));
......
# expected: fail
# - keywords
def f(a, b, c):
print a, b, c
f(1, 2, 3)
f(1, b=2, c=3)
f(1, b=2, c=3)
f(1, c=2, b=3)
f(1, b="2", c=3)
f(1, b=2, c="3")
f(1, c="2", b=3)
f(1, c=2, b="3")
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