Commit 9c78c3d4 authored by Travis Hance's avatar Travis Hance

basic functionality working

parent 39afd252
...@@ -104,6 +104,7 @@ public: ...@@ -104,6 +104,7 @@ public:
bool usesNameLookup() override { return false; } bool usesNameLookup() override { return false; }
bool areLocalsFromModule() override { return true; } bool areLocalsFromModule() override { return true; }
bool areGlobalsFromModule() override { return true; }
DerefInfo getDerefInfo(InternedString) override { RELEASE_ASSERT(0, "This should never get called"); } DerefInfo getDerefInfo(InternedString) override { RELEASE_ASSERT(0, "This should never get called"); }
size_t getClosureOffset(InternedString) override { RELEASE_ASSERT(0, "This should never get called"); } size_t getClosureOffset(InternedString) override { RELEASE_ASSERT(0, "This should never get called"); }
...@@ -142,10 +143,12 @@ private: ...@@ -142,10 +143,12 @@ private:
} }
}; };
bool globals_from_module;
public: public:
EvalExprScopeInfo() {} EvalExprScopeInfo(bool globals_from_module) : globals_from_module(globals_from_module) {}
EvalExprScopeInfo(AST* node) { EvalExprScopeInfo(AST* node, bool globals_from_module) : globals_from_module(globals_from_module) {
// Find all the global statements in the node's scope (not delving into FuncitonDefs // Find all the global statements in the node's scope (not delving into FuncitonDefs
// or ClassDefs) and put the names in `forced_globals`. // or ClassDefs) and put the names in `forced_globals`.
GlobalStmtVisitor visitor(forced_globals); GlobalStmtVisitor visitor(forced_globals);
...@@ -170,6 +173,7 @@ public: ...@@ -170,6 +173,7 @@ public:
bool usesNameLookup() override { return true; } bool usesNameLookup() override { return true; }
bool areLocalsFromModule() override { return false; } bool areLocalsFromModule() override { return false; }
bool areGlobalsFromModule() override { return globals_from_module; }
DerefInfo getDerefInfo(InternedString) override { RELEASE_ASSERT(0, "This should never get called"); } DerefInfo getDerefInfo(InternedString) override { RELEASE_ASSERT(0, "This should never get called"); }
size_t getClosureOffset(InternedString) override { RELEASE_ASSERT(0, "This should never get called"); } size_t getClosureOffset(InternedString) override { RELEASE_ASSERT(0, "This should never get called"); }
...@@ -321,6 +325,7 @@ public: ...@@ -321,6 +325,7 @@ public:
bool usesNameLookup() override { return usesNameLookup_; } bool usesNameLookup() override { return usesNameLookup_; }
bool areLocalsFromModule() override { return false; } bool areLocalsFromModule() override { return false; }
bool areGlobalsFromModule() override { return true; }
DerefInfo getDerefInfo(InternedString name) override { DerefInfo getDerefInfo(InternedString name) override {
assert(getScopeTypeOfName(name) == VarScopeType::DEREF); assert(getScopeTypeOfName(name) == VarScopeType::DEREF);
...@@ -881,12 +886,12 @@ ScopingAnalysis::ScopingAnalysis(AST_Module* m) : parent_module(m), interned_str ...@@ -881,12 +886,12 @@ ScopingAnalysis::ScopingAnalysis(AST_Module* m) : parent_module(m), interned_str
scopes[m] = new ModuleScopeInfo(); scopes[m] = new ModuleScopeInfo();
} }
ScopingAnalysis::ScopingAnalysis(AST_Expression* e) : interned_strings(*e->interned_strings.get()) { ScopingAnalysis::ScopingAnalysis(AST_Expression* e, bool globals_from_module) : interned_strings(*e->interned_strings.get()) {
// It's an expression, so it can't have a `global` statement // It's an expression, so it can't have a `global` statement
scopes[e] = new EvalExprScopeInfo(); scopes[e] = new EvalExprScopeInfo(globals_from_module);
} }
ScopingAnalysis::ScopingAnalysis(AST_Suite* s) : interned_strings(*s->interned_strings.get()) { ScopingAnalysis::ScopingAnalysis(AST_Suite* s, bool globals_from_module) : interned_strings(*s->interned_strings.get()) {
scopes[s] = new EvalExprScopeInfo(s); scopes[s] = new EvalExprScopeInfo(s, globals_from_module);
} }
} }
...@@ -92,6 +92,7 @@ public: ...@@ -92,6 +92,7 @@ public:
virtual bool usesNameLookup() = 0; virtual bool usesNameLookup() = 0;
virtual bool areLocalsFromModule() = 0; virtual bool areLocalsFromModule() = 0;
virtual bool areGlobalsFromModule() = 0;
// For a variable with DEREF lookup, return the DerefInfo used to lookup // For a variable with DEREF lookup, return the DerefInfo used to lookup
// the variable in a passed closure. // the variable in a passed closure.
...@@ -169,8 +170,8 @@ public: ...@@ -169,8 +170,8 @@ public:
void registerScopeReplacement(AST* original_node, AST* new_node); void registerScopeReplacement(AST* original_node, AST* new_node);
ScopingAnalysis(AST_Module* m); ScopingAnalysis(AST_Module* m);
ScopingAnalysis(AST_Expression* e); ScopingAnalysis(AST_Expression* e, bool globals_from_module);
ScopingAnalysis(AST_Suite* s); ScopingAnalysis(AST_Suite* s, bool globals_from_module);
ScopeInfo* getScopeInfoForNode(AST* node); ScopeInfo* getScopeInfoForNode(AST* node);
InternedStringPool& getInternedStrings(); InternedStringPool& getInternedStrings();
......
...@@ -141,6 +141,9 @@ private: ...@@ -141,6 +141,9 @@ private:
unsigned edgecount; unsigned edgecount;
FrameInfo frame_info; FrameInfo frame_info;
// This is either a module or a dict
Box* globals;
public: public:
AST_stmt* getCurrentStatement() { AST_stmt* getCurrentStatement() {
assert(current_inst); assert(current_inst);
...@@ -159,6 +162,7 @@ public: ...@@ -159,6 +162,7 @@ public:
void setCreatedClosure(Box* closure); void setCreatedClosure(Box* closure);
void setBoxedLocals(Box*); void setBoxedLocals(Box*);
void setFrameInfo(const FrameInfo* frame_info); void setFrameInfo(const FrameInfo* frame_info);
void setGlobals(Box* globals);
void gcVisit(GCVisitor* visitor); void gcVisit(GCVisitor* visitor);
}; };
...@@ -195,6 +199,13 @@ void ASTInterpreter::setFrameInfo(const FrameInfo* frame_info) { ...@@ -195,6 +199,13 @@ void ASTInterpreter::setFrameInfo(const FrameInfo* frame_info) {
this->frame_info = *frame_info; this->frame_info = *frame_info;
} }
void ASTInterpreter::setGlobals(Box* globals) {
this->globals = globals;
if (globals->cls == dict_cls) {
frame_info.globals = static_cast<BoxedDict*>(globals);
}
}
void ASTInterpreter::gcVisit(GCVisitor* visitor) { void ASTInterpreter::gcVisit(GCVisitor* visitor) {
visitor->visitRange((void* const*)&sym_table.vector()[0], (void* const*)&sym_table.vector()[sym_table.size()]); visitor->visitRange((void* const*)&sym_table.vector()[0], (void* const*)&sym_table.vector()[sym_table.size()]);
if (passed_closure) if (passed_closure)
...@@ -205,6 +216,8 @@ void ASTInterpreter::gcVisit(GCVisitor* visitor) { ...@@ -205,6 +216,8 @@ void ASTInterpreter::gcVisit(GCVisitor* visitor) {
visitor->visit(generator); visitor->visit(generator);
if (frame_info.boxedLocals) if (frame_info.boxedLocals)
visitor->visit(frame_info.boxedLocals); visitor->visit(frame_info.boxedLocals);
if (frame_info.globals)
visitor->visit(frame_info.globals);
} }
ASTInterpreter::ASTInterpreter(CompiledFunction* compiled_function) ASTInterpreter::ASTInterpreter(CompiledFunction* compiled_function)
...@@ -217,6 +230,7 @@ ASTInterpreter::ASTInterpreter(CompiledFunction* compiled_function) ...@@ -217,6 +230,7 @@ ASTInterpreter::ASTInterpreter(CompiledFunction* compiled_function)
source_info->cfg = computeCFG(f->source, f->source->body); source_info->cfg = computeCFG(f->source, f->source->body);
scope_info = source_info->getScopeInfo(); scope_info = source_info->getScopeInfo();
assert(scope_info); assert(scope_info);
} }
...@@ -345,7 +359,12 @@ Value ASTInterpreter::doBinOp(Box* left, Box* right, int op, BinExpType exp_type ...@@ -345,7 +359,12 @@ Value ASTInterpreter::doBinOp(Box* left, Box* right, int op, BinExpType exp_type
void ASTInterpreter::doStore(InternedString name, Value value) { void ASTInterpreter::doStore(InternedString name, Value value) {
ScopeInfo::VarScopeType vst = scope_info->getScopeTypeOfName(name); ScopeInfo::VarScopeType vst = scope_info->getScopeTypeOfName(name);
if (vst == ScopeInfo::VarScopeType::GLOBAL) { if (vst == ScopeInfo::VarScopeType::GLOBAL) {
setattr(source_info->parent_module, name.c_str(), value.o); if (globals->cls == module_cls) {
setattr(static_cast<BoxedModule*>(globals), name.c_str(), value.o);
} else {
assert(globals->cls == dict_cls);
static_cast<BoxedDict*>(globals)->d[boxString(name.str())] = value.o;
}
} else if (vst == ScopeInfo::VarScopeType::NAME) { } else if (vst == ScopeInfo::VarScopeType::NAME) {
assert(frame_info.boxedLocals != NULL); assert(frame_info.boxedLocals != NULL);
// TODO should probably pre-box the names when it's a scope that usesNameLookup // TODO should probably pre-box the names when it's a scope that usesNameLookup
...@@ -819,7 +838,7 @@ Value ASTInterpreter::visit_delete(AST_Delete* node) { ...@@ -819,7 +838,7 @@ Value ASTInterpreter::visit_delete(AST_Delete* node) {
ScopeInfo::VarScopeType vst = scope_info->getScopeTypeOfName(target->id); ScopeInfo::VarScopeType vst = scope_info->getScopeTypeOfName(target->id);
if (vst == ScopeInfo::VarScopeType::GLOBAL) { if (vst == ScopeInfo::VarScopeType::GLOBAL) {
// Can't use delattr since the errors are different: // Can't use delattr since the errors are different:
delGlobal(source_info->parent_module, &target->id.str()); delGlobal(globals, &target->id.str());
continue; continue;
} else if (vst == ScopeInfo::VarScopeType::NAME) { } else if (vst == ScopeInfo::VarScopeType::NAME) {
assert(frame_info.boxedLocals != NULL); assert(frame_info.boxedLocals != NULL);
...@@ -1084,7 +1103,7 @@ Value ASTInterpreter::visit_name(AST_Name* node) { ...@@ -1084,7 +1103,7 @@ Value ASTInterpreter::visit_name(AST_Name* node) {
switch (node->lookup_type) { switch (node->lookup_type) {
case ScopeInfo::VarScopeType::GLOBAL: case ScopeInfo::VarScopeType::GLOBAL:
return getGlobal(source_info->parent_module, &node->id.str()); return getGlobal(globals, &node->id.str());
case ScopeInfo::VarScopeType::DEREF: { case ScopeInfo::VarScopeType::DEREF: {
DerefInfo deref_info = scope_info->getDerefInfo(node->id); DerefInfo deref_info = scope_info->getDerefInfo(node->id);
assert(passed_closure); assert(passed_closure);
...@@ -1109,7 +1128,7 @@ Value ASTInterpreter::visit_name(AST_Name* node) { ...@@ -1109,7 +1128,7 @@ Value ASTInterpreter::visit_name(AST_Name* node) {
return Value(); return Value();
} }
case ScopeInfo::VarScopeType::NAME: { case ScopeInfo::VarScopeType::NAME: {
return boxedLocalsGet(frame_info.boxedLocals, node->id.c_str(), source_info->parent_module); return boxedLocalsGet(frame_info.boxedLocals, node->id.c_str(), globals);
} }
default: default:
abort(); abort();
...@@ -1161,22 +1180,39 @@ Box* astInterpretFunction(CompiledFunction* cf, int nargs, Box* closure, Box* ge ...@@ -1161,22 +1180,39 @@ Box* astInterpretFunction(CompiledFunction* cf, int nargs, Box* closure, Box* ge
++cf->times_called; ++cf->times_called;
ASTInterpreter interpreter(cf); ASTInterpreter interpreter(cf);
if (unlikely(cf->clfunc->source->getScopeInfo()->usesNameLookup())) {
ScopeInfo* scope_info = cf->clfunc->source->getScopeInfo();
SourceInfo* source_info = cf->clfunc->source;
if (unlikely(scope_info->usesNameLookup())) {
interpreter.setBoxedLocals(new BoxedDict()); interpreter.setBoxedLocals(new BoxedDict());
} }
assert(scope_info->areGlobalsFromModule());
interpreter.setGlobals(source_info->parent_module);
interpreter.initArguments(nargs, (BoxedClosure*)closure, (BoxedGenerator*)generator, arg1, arg2, arg3, args); interpreter.initArguments(nargs, (BoxedClosure*)closure, (BoxedGenerator*)generator, arg1, arg2, arg3, args);
Value v = ASTInterpreter::execute(interpreter); Value v = ASTInterpreter::execute(interpreter);
return v.o ? v.o : None; return v.o ? v.o : None;
} }
Box* astInterpretFunctionEval(CompiledFunction* cf, Box* boxedLocals) { Box* astInterpretFunctionEval(CompiledFunction* cf, BoxedDict* globals, Box* boxedLocals) {
++cf->times_called; ++cf->times_called;
ASTInterpreter interpreter(cf); ASTInterpreter interpreter(cf);
interpreter.initArguments(0, NULL, NULL, NULL, NULL, NULL, NULL); interpreter.initArguments(0, NULL, NULL, NULL, NULL, NULL, NULL);
interpreter.setBoxedLocals(boxedLocals); interpreter.setBoxedLocals(boxedLocals);
ScopeInfo* scope_info = cf->clfunc->source->getScopeInfo();
SourceInfo* source_info = cf->clfunc->source;
if (scope_info->areGlobalsFromModule()) {
assert(!globals);
interpreter.setGlobals(source_info->parent_module);
} else {
assert(globals);
interpreter.setGlobals(globals);
}
Value v = ASTInterpreter::execute(interpreter); Value v = ASTInterpreter::execute(interpreter);
return v.o ? v.o : None; return v.o ? v.o : None;
...@@ -1192,6 +1228,15 @@ Box* astInterpretFrom(CompiledFunction* cf, AST_expr* after_expr, AST_stmt* encl ...@@ -1192,6 +1228,15 @@ Box* astInterpretFrom(CompiledFunction* cf, AST_expr* after_expr, AST_stmt* encl
ASTInterpreter interpreter(cf); ASTInterpreter interpreter(cf);
ScopeInfo* scope_info = cf->clfunc->source->getScopeInfo();
SourceInfo* source_info = cf->clfunc->source;
if (scope_info->areGlobalsFromModule()) {
interpreter.setGlobals(source_info->parent_module);
} else {
assert(frame_state.frame_info->globals);
interpreter.setGlobals(frame_state.frame_info->globals);
}
for (const auto& p : frame_state.locals->d) { for (const auto& p : frame_state.locals->d) {
assert(p.first->cls == str_cls); assert(p.first->cls == str_cls);
std::string name = static_cast<BoxedString*>(p.first)->s; std::string name = static_cast<BoxedString*>(p.first)->s;
......
...@@ -35,7 +35,7 @@ extern const void* interpreter_instr_addr; ...@@ -35,7 +35,7 @@ extern const void* interpreter_instr_addr;
Box* astInterpretFunction(CompiledFunction* f, int nargs, Box* closure, Box* generator, Box* arg1, Box* arg2, Box* arg3, Box* astInterpretFunction(CompiledFunction* f, int nargs, Box* closure, Box* generator, Box* arg1, Box* arg2, Box* arg3,
Box** args); Box** args);
Box* astInterpretFunctionEval(CompiledFunction* cf, Box* boxedLocals); Box* astInterpretFunctionEval(CompiledFunction* cf, BoxedDict* globals, Box* boxedLocals);
Box* astInterpretFrom(CompiledFunction* cf, AST_expr* after_expr, AST_stmt* enclosing_stmt, Box* expr_val, Box* astInterpretFrom(CompiledFunction* cf, AST_expr* after_expr, AST_stmt* enclosing_stmt, Box* expr_val,
FrameStackState frame_state); FrameStackState frame_state);
......
...@@ -327,7 +327,7 @@ void compileAndRunModule(AST_Module* m, BoxedModule* bm) { ...@@ -327,7 +327,7 @@ void compileAndRunModule(AST_Module* m, BoxedModule* bm) {
} }
template <typename AST_Type> template <typename AST_Type>
Box* evalOrExec(AST_Type* source, std::vector<AST_stmt*>& body, BoxedModule* bm, Box* boxedLocals) { Box* evalOrExec(AST_Type* source, std::vector<AST_stmt*>& body, BoxedModule* bm, BoxedDict* globals, Box* boxedLocals) {
CompiledFunction* cf; CompiledFunction* cf;
{ // scope for limiting the locked region: { // scope for limiting the locked region:
...@@ -335,7 +335,7 @@ Box* evalOrExec(AST_Type* source, std::vector<AST_stmt*>& body, BoxedModule* bm, ...@@ -335,7 +335,7 @@ Box* evalOrExec(AST_Type* source, std::vector<AST_stmt*>& body, BoxedModule* bm,
Timer _t("for evalOrExec()"); Timer _t("for evalOrExec()");
ScopingAnalysis* scoping = new ScopingAnalysis(source); ScopingAnalysis* scoping = new ScopingAnalysis(source, globals == NULL);
SourceInfo* si = new SourceInfo(bm, scoping, source, body); SourceInfo* si = new SourceInfo(bm, scoping, source, body);
CLFunction* cl_f = new CLFunction(0, 0, false, false, si); CLFunction* cl_f = new CLFunction(0, 0, false, false, si);
...@@ -352,7 +352,7 @@ Box* evalOrExec(AST_Type* source, std::vector<AST_stmt*>& body, BoxedModule* bm, ...@@ -352,7 +352,7 @@ Box* evalOrExec(AST_Type* source, std::vector<AST_stmt*>& body, BoxedModule* bm,
assert(cf->clfunc->versions.size()); assert(cf->clfunc->versions.size());
} }
return astInterpretFunctionEval(cf, boxedLocals); return astInterpretFunctionEval(cf, globals, boxedLocals);
} }
// Main entrypoints for eval and exec. // Main entrypoints for eval and exec.
...@@ -376,7 +376,7 @@ Box* eval(Box* boxedCode) { ...@@ -376,7 +376,7 @@ Box* eval(Box* boxedCode) {
stmt->value = parsedExpr->body; stmt->value = parsedExpr->body;
std::vector<AST_stmt*> body = { stmt }; std::vector<AST_stmt*> body = { stmt };
return evalOrExec<AST_Expression>(parsedExpr, body, module, boxedLocals); return evalOrExec<AST_Expression>(parsedExpr, body, module, NULL, boxedLocals);
} }
Box* exec(Box* boxedCode, Box* globals, Box* locals) { Box* exec(Box* boxedCode, Box* globals, Box* locals) {
...@@ -392,6 +392,8 @@ Box* exec(Box* boxedCode, Box* globals, Box* locals) { ...@@ -392,6 +392,8 @@ Box* exec(Box* boxedCode, Box* globals, Box* locals) {
BoxedModule* module = getCurrentModule(); BoxedModule* module = getCurrentModule();
assert(!globals || globals->cls == dict_cls);
// TODO same issues as in `eval` // TODO same issues as in `eval`
RELEASE_ASSERT(boxedCode->cls == str_cls, ""); RELEASE_ASSERT(boxedCode->cls == str_cls, "");
const char* code = static_cast<BoxedString*>(boxedCode)->s.c_str(); const char* code = static_cast<BoxedString*>(boxedCode)->s.c_str();
...@@ -399,7 +401,7 @@ Box* exec(Box* boxedCode, Box* globals, Box* locals) { ...@@ -399,7 +401,7 @@ Box* exec(Box* boxedCode, Box* globals, Box* locals) {
AST_Suite* parsedSuite = new AST_Suite(std::move(parsedModule->interned_strings)); AST_Suite* parsedSuite = new AST_Suite(std::move(parsedModule->interned_strings));
parsedSuite->body = parsedModule->body; parsedSuite->body = parsedModule->body;
return evalOrExec<AST_Suite>(parsedSuite, parsedSuite->body, module, locals); return evalOrExec<AST_Suite>(parsedSuite, parsedSuite->body, module, static_cast<BoxedDict*>(globals), locals);
} }
// If a function version keeps failing its speculations, kill it (remove it // If a function version keeps failing its speculations, kill it (remove it
......
...@@ -567,8 +567,9 @@ struct FrameInfo { ...@@ -567,8 +567,9 @@ struct FrameInfo {
ExcInfo exc; ExcInfo exc;
Box* boxedLocals; Box* boxedLocals;
BoxedDict* globals;
FrameInfo(ExcInfo exc) : exc(exc), boxedLocals(NULL) {} FrameInfo(ExcInfo exc) : exc(exc), boxedLocals(NULL), globals(NULL) {}
}; };
struct CallattrFlags { struct CallattrFlags {
......
...@@ -4245,14 +4245,24 @@ Box* typeCall(Box* obj, BoxedTuple* vararg, BoxedDict* kwargs) { ...@@ -4245,14 +4245,24 @@ Box* typeCall(Box* obj, BoxedTuple* vararg, BoxedDict* kwargs) {
return typeCallInternal(NULL, NULL, ArgPassSpec(n + 1, 0, false, true), arg1, arg2, arg3, args, NULL); return typeCallInternal(NULL, NULL, ArgPassSpec(n + 1, 0, false, true), arg1, arg2, arg3, args, NULL);
} }
extern "C" void delGlobal(BoxedModule* m, const std::string* name) { extern "C" void delGlobal(Box* globals, const std::string* name) {
if (!m->getattr(*name)) { if (globals->cls == module_cls) {
raiseExcHelper(NameError, "name '%s' is not defined", name->c_str()); BoxedModule* m = static_cast<BoxedModule*>(globals);
if (!m->getattr(*name)) {
raiseExcHelper(NameError, "name '%s' is not defined", name->c_str());
}
m->delattr(*name, NULL);
} else {
assert(globals->cls == dict_cls);
BoxedDict* d = static_cast<BoxedDict*>(globals);
auto it = d->d.find(boxString(*name));
assertNameDefined(it != d->d.end(), name->c_str(), NameError, false /* local_var_msg */);
d->d.erase(it);
} }
m->delattr(*name, NULL);
} }
extern "C" Box* getGlobal(BoxedModule* m, const std::string* name) { extern "C" Box* getGlobal(Box* globals, const std::string* name) {
static StatCounter slowpath_getglobal("slowpath_getglobal"); static StatCounter slowpath_getglobal("slowpath_getglobal");
slowpath_getglobal.log(); slowpath_getglobal.log();
static StatCounter nopatch_getglobal("nopatch_getglobal"); static StatCounter nopatch_getglobal("nopatch_getglobal");
...@@ -4270,25 +4280,44 @@ extern "C" Box* getGlobal(BoxedModule* m, const std::string* name) { ...@@ -4270,25 +4280,44 @@ extern "C" Box* getGlobal(BoxedModule* m, const std::string* name) {
Rewriter::createRewriter(__builtin_extract_return_addr(__builtin_return_address(0)), 3, "getGlobal")); Rewriter::createRewriter(__builtin_extract_return_addr(__builtin_return_address(0)), 3, "getGlobal"));
Box* r; Box* r;
if (rewriter.get()) { if (globals->cls == module_cls) {
// rewriter->trap(); BoxedModule* m = static_cast<BoxedModule*>(globals);
if (rewriter.get()) {
RewriterVar* r_mod = rewriter->getArg(0);
GetattrRewriteArgs rewrite_args(rewriter.get(), rewriter->getArg(0), rewriter->getReturnDestination()); // Guard on it being a module rather than a dict
r = m->getattr(*name, &rewrite_args); // TODO is this guard necessary? I'm being conservative now, but I think we can just
if (!rewrite_args.out_success) { // insist that the type passed in is fixed for any given instance of a getGlobal call.
rewriter.reset(NULL); r_mod->addAttrGuard(BOX_CLS_OFFSET, (intptr_t)module_cls);
}
if (r) { GetattrRewriteArgs rewrite_args(rewriter.get(), r_mod, rewriter->getReturnDestination());
if (rewriter.get()) { r = m->getattr(*name, &rewrite_args);
rewriter->commitReturning(rewrite_args.out_rtn); if (!rewrite_args.out_success) {
rewriter.reset(NULL);
}
if (r) {
if (rewriter.get()) {
rewriter->commitReturning(rewrite_args.out_rtn);
}
return r;
}
} else {
r = m->getattr(*name, NULL);
nopatch_getglobal.log();
if (r) {
return r;
} }
return r;
} }
} else { } else {
r = m->getattr(*name, NULL); assert(globals->cls == dict_cls);
nopatch_getglobal.log(); BoxedDict* d = static_cast<BoxedDict*>(globals);
if (r) {
return r; rewriter.reset(NULL);
REWRITE_ABORTED("Rewriting not implemented for getGlobals with a dict globals yet");
auto it = d->d.find(boxString(*name));
if (it != d->d.end()) {
return it->second;
} }
} }
...@@ -4408,8 +4437,7 @@ extern "C" void boxedLocalsSet(Box* boxedLocals, const char* attr, Box* val) { ...@@ -4408,8 +4437,7 @@ extern "C" void boxedLocalsSet(Box* boxedLocals, const char* attr, Box* val) {
setitem(boxedLocals, boxString(attr), val); setitem(boxedLocals, boxString(attr), val);
} }
extern "C" Box* boxedLocalsGet(Box* boxedLocals, const char* attr, BoxedModule* parent_module) { extern "C" Box* boxedLocalsGet(Box* boxedLocals, const char* attr, Box* globals) {
assert(parent_module->cls == module_cls);
assert(boxedLocals != NULL); assert(boxedLocals != NULL);
if (boxedLocals->cls == dict_cls) { if (boxedLocals->cls == dict_cls) {
...@@ -4434,7 +4462,7 @@ extern "C" Box* boxedLocalsGet(Box* boxedLocals, const char* attr, BoxedModule* ...@@ -4434,7 +4462,7 @@ extern "C" Box* boxedLocalsGet(Box* boxedLocals, const char* attr, BoxedModule*
// TODO exception name? // TODO exception name?
std::string attr_string(attr); std::string attr_string(attr);
return getGlobal(parent_module, &attr_string); return getGlobal(globals, &attr_string);
} }
extern "C" void boxedLocalsDel(Box* boxedLocals, const char* attr) { extern "C" void boxedLocalsDel(Box* boxedLocals, const char* attr) {
......
...@@ -72,8 +72,6 @@ extern "C" BoxedInt* len(Box* obj); ...@@ -72,8 +72,6 @@ extern "C" BoxedInt* len(Box* obj);
extern "C" i64 unboxedLen(Box* obj); extern "C" i64 unboxedLen(Box* obj);
extern "C" Box* binop(Box* lhs, Box* rhs, int op_type); extern "C" Box* binop(Box* lhs, Box* rhs, int op_type);
extern "C" Box* augbinop(Box* lhs, Box* rhs, int op_type); extern "C" Box* augbinop(Box* lhs, Box* rhs, int op_type);
extern "C" Box* getGlobal(BoxedModule* m, const std::string* name);
extern "C" void delGlobal(BoxedModule* m, const std::string* name);
extern "C" Box* getitem(Box* value, Box* slice); extern "C" Box* getitem(Box* value, Box* slice);
extern "C" void setitem(Box* target, Box* slice, Box* value); extern "C" void setitem(Box* target, Box* slice, Box* value);
extern "C" void delitem(Box* target, Box* slice); extern "C" void delitem(Box* target, Box* slice);
...@@ -168,8 +166,13 @@ inline std::tuple<Box*, Box*, Box*, Box**> getTupleFromArgsArray(Box** args, int ...@@ -168,8 +166,13 @@ inline std::tuple<Box*, Box*, Box*, Box**> getTupleFromArgsArray(Box** args, int
return std::make_tuple(arg1, arg2, arg3, argtuple); return std::make_tuple(arg1, arg2, arg3, argtuple);
} }
// The `globals` argument can be either a BoxedModule or a BoxedDict
extern "C" Box* getGlobal(Box* globals, const std::string* name);
extern "C" void delGlobal(Box* globals, const std::string* name);
extern "C" void boxedLocalsSet(Box* boxedLocals, const char* attr, Box* val); extern "C" void boxedLocalsSet(Box* boxedLocals, const char* attr, Box* val);
extern "C" Box* boxedLocalsGet(Box* boxedLocals, const char* attr, BoxedModule* parent_module); extern "C" Box* boxedLocalsGet(Box* boxedLocals, const char* attr, Box* globals);
extern "C" void boxedLocalsDel(Box* boxedLocals, const char* attr); extern "C" void boxedLocalsDel(Box* boxedLocals, const char* attr);
} }
#endif #endif
print 'Test getting'
g = {'a': 1}
l = {'b': 2}
exec """global a
print a
print b""" in g, l
print 'Test setting'
g = {}
l = {}
exec """global a
a = 1
b = 2""" in g, l
print g
print l
print 'Test deleting'
g = {'a': 1}
l = {'b': 2}
exec """global a
del a
del b""" in g, l
print g
print l
print 'Test global access in a function'
g = {'a': 4, 'b': 5}
exec """
def f():
global a, b, c
print 'a =', a
del b
c = 20
f()
""" in g, {}
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