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

added to BoxedList so it will work for functions inside the exec

parent 9c78c3d4
...@@ -275,9 +275,11 @@ private: ...@@ -275,9 +275,11 @@ private:
std::vector<std::pair<InternedString, DerefInfo>> allDerefVarsAndInfo; std::vector<std::pair<InternedString, DerefInfo>> allDerefVarsAndInfo;
bool allDerefVarsAndInfoCached; bool allDerefVarsAndInfoCached;
bool globals_from_module;
public: public:
ScopeInfoBase(ScopeInfo* parent, ScopingAnalysis::ScopeNameUsage* usage, AST* ast, bool usesNameLookup) ScopeInfoBase(ScopeInfo* parent, ScopingAnalysis::ScopeNameUsage* usage, AST* ast, bool usesNameLookup, bool globals_from_module)
: parent(parent), usage(usage), ast(ast), usesNameLookup_(usesNameLookup), allDerefVarsAndInfoCached(false) { : parent(parent), usage(usage), ast(ast), usesNameLookup_(usesNameLookup), allDerefVarsAndInfoCached(false), globals_from_module(globals_from_module) {
assert(usage); assert(usage);
assert(ast); assert(ast);
...@@ -325,7 +327,7 @@ public: ...@@ -325,7 +327,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; } bool areGlobalsFromModule() override { return globals_from_module; }
DerefInfo getDerefInfo(InternedString name) override { DerefInfo getDerefInfo(InternedString name) override {
assert(getScopeTypeOfName(name) == VarScopeType::DEREF); assert(getScopeTypeOfName(name) == VarScopeType::DEREF);
...@@ -816,7 +818,7 @@ void ScopingAnalysis::processNameUsages(ScopingAnalysis::NameUsageMap* usages) { ...@@ -816,7 +818,7 @@ void ScopingAnalysis::processNameUsages(ScopingAnalysis::NameUsageMap* usages) {
switch (node->type) { switch (node->type) {
case AST_TYPE::ClassDef: { case AST_TYPE::ClassDef: {
ScopeInfoBase* scopeInfo ScopeInfoBase* scopeInfo
= new ScopeInfoBase(parent_info, usage, usage->node, true /* usesNameLookup */); = new ScopeInfoBase(parent_info, usage, usage->node, true /* usesNameLookup */, globals_from_module);
this->scopes[node] = scopeInfo; this->scopes[node] = scopeInfo;
break; break;
} }
...@@ -826,9 +828,9 @@ void ScopingAnalysis::processNameUsages(ScopingAnalysis::NameUsageMap* usages) { ...@@ -826,9 +828,9 @@ void ScopingAnalysis::processNameUsages(ScopingAnalysis::NameUsageMap* usages) {
case AST_TYPE::DictComp: case AST_TYPE::DictComp:
case AST_TYPE::SetComp: { case AST_TYPE::SetComp: {
ScopeInfoBase* scopeInfo = new ScopeInfoBase(parent_info, usage, usage->node, ScopeInfoBase* scopeInfo = new ScopeInfoBase(parent_info, usage, usage->node,
usage->hasNameForcingSyntax() /* usesNameLookup */); usage->hasNameForcingSyntax() /* usesNameLookup */,
this->scopes[node] = scopeInfo; globals_from_module);
break; this->scopes[node] = scopeInfo; break;
} }
default: default:
RELEASE_ASSERT(0, "%d", usage->node->type); RELEASE_ASSERT(0, "%d", usage->node->type);
...@@ -882,16 +884,16 @@ ScopeInfo* ScopingAnalysis::getScopeInfoForNode(AST* node) { ...@@ -882,16 +884,16 @@ ScopeInfo* ScopingAnalysis::getScopeInfoForNode(AST* node) {
return analyzeSubtree(node); return analyzeSubtree(node);
} }
ScopingAnalysis::ScopingAnalysis(AST_Module* m) : parent_module(m), interned_strings(*m->interned_strings.get()) { ScopingAnalysis::ScopingAnalysis(AST_Module* m) : parent_module(m), interned_strings(*m->interned_strings.get()), globals_from_module(true) {
scopes[m] = new ModuleScopeInfo(); scopes[m] = new ModuleScopeInfo();
} }
ScopingAnalysis::ScopingAnalysis(AST_Expression* e, bool globals_from_module) : interned_strings(*e->interned_strings.get()) { ScopingAnalysis::ScopingAnalysis(AST_Expression* e, bool globals_from_module) : interned_strings(*e->interned_strings.get()), globals_from_module(globals_from_module) {
// 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(globals_from_module); scopes[e] = new EvalExprScopeInfo(globals_from_module);
} }
ScopingAnalysis::ScopingAnalysis(AST_Suite* s, bool globals_from_module) : interned_strings(*s->interned_strings.get()) { ScopingAnalysis::ScopingAnalysis(AST_Suite* s, bool globals_from_module) : interned_strings(*s->interned_strings.get()), globals_from_module(globals_from_module) {
scopes[s] = new EvalExprScopeInfo(s, globals_from_module); scopes[s] = new EvalExprScopeInfo(s, globals_from_module);
} }
} }
...@@ -159,6 +159,8 @@ private: ...@@ -159,6 +159,8 @@ private:
ScopeInfo* analyzeSubtree(AST* node); ScopeInfo* analyzeSubtree(AST* node);
void processNameUsages(NameUsageMap* usages); void processNameUsages(NameUsageMap* usages);
bool globals_from_module;
public: public:
// The scope-analysis is done before any CFG-ization is done, // The scope-analysis is done before any CFG-ization is done,
// but many of the queries will be done post-CFG-ization. // but many of the queries will be done post-CFG-ization.
......
...@@ -742,7 +742,7 @@ Box* ASTInterpreter::createFunction(AST* node, AST_arguments* args, const std::v ...@@ -742,7 +742,7 @@ Box* ASTInterpreter::createFunction(AST* node, AST_arguments* args, const std::v
} }
assert(closure); assert(closure);
} }
return boxCLFunction(cl, closure, is_generator, u.il); return boxCLFunction(cl, closure, is_generator, globals->cls == dict_cls ? static_cast<BoxedDict*>(globals) : NULL, u.il);
} }
Value ASTInterpreter::visit_makeFunction(AST_MakeFunction* mkfn) { Value ASTInterpreter::visit_makeFunction(AST_MakeFunction* mkfn) {
...@@ -778,7 +778,7 @@ Value ASTInterpreter::visit_makeClass(AST_MakeClass* mkclass) { ...@@ -778,7 +778,7 @@ Value ASTInterpreter::visit_makeClass(AST_MakeClass* mkclass) {
BoxedClosure* closure = scope_info->takesClosure() ? created_closure : 0; BoxedClosure* closure = scope_info->takesClosure() ? created_closure : 0;
CLFunction* cl = wrapFunction(node, nullptr, node->body, source_info); CLFunction* cl = wrapFunction(node, nullptr, node->body, source_info);
Box* attrDict = runtimeCall(boxCLFunction(cl, closure, false, {}), ArgPassSpec(0), 0, 0, 0, 0, 0); Box* attrDict = runtimeCall(boxCLFunction(cl, closure, false, globals->cls == dict_cls ? static_cast<BoxedDict*>(globals) : NULL, {}), ArgPassSpec(0), 0, 0, 0, 0, 0);
Box* classobj = createUserClass(&node->name.str(), basesTuple, attrDict); Box* classobj = createUserClass(&node->name.str(), basesTuple, attrDict);
...@@ -1164,7 +1164,7 @@ Value ASTInterpreter::visit_attribute(AST_Attribute* node) { ...@@ -1164,7 +1164,7 @@ Value ASTInterpreter::visit_attribute(AST_Attribute* node) {
const void* interpreter_instr_addr = (void*)&ASTInterpreter::execute; const void* interpreter_instr_addr = (void*)&ASTInterpreter::execute;
Box* astInterpretFunction(CompiledFunction* cf, int nargs, Box* closure, Box* generator, Box* arg1, Box* arg2, Box* astInterpretFunction(CompiledFunction* cf, int nargs, Box* closure, Box* generator, BoxedDict* globals, Box* arg1, Box* arg2,
Box* arg3, Box** args) { Box* arg3, Box** args) {
if (unlikely(cf->times_called > REOPT_THRESHOLD_INTERPRETER && ENABLE_REOPT && !FORCE_INTERPRETER)) { if (unlikely(cf->times_called > REOPT_THRESHOLD_INTERPRETER && ENABLE_REOPT && !FORCE_INTERPRETER)) {
CompiledFunction* optimized = reoptCompiledFuncInternal(cf); CompiledFunction* optimized = reoptCompiledFuncInternal(cf);
...@@ -1187,8 +1187,12 @@ Box* astInterpretFunction(CompiledFunction* cf, int nargs, Box* closure, Box* ge ...@@ -1187,8 +1187,12 @@ Box* astInterpretFunction(CompiledFunction* cf, int nargs, Box* closure, Box* ge
interpreter.setBoxedLocals(new BoxedDict()); interpreter.setBoxedLocals(new BoxedDict());
} }
assert(scope_info->areGlobalsFromModule()); assert((!globals) == scope_info->areGlobalsFromModule());
interpreter.setGlobals(source_info->parent_module); if (globals) {
interpreter.setGlobals(globals);
} else {
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);
......
...@@ -33,7 +33,7 @@ struct LineInfo; ...@@ -33,7 +33,7 @@ struct LineInfo;
extern const void* interpreter_instr_addr; 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, BoxedDict* globals, Box* arg1, Box* arg2, Box* arg3,
Box** args); Box** args);
Box* astInterpretFunctionEval(CompiledFunction* cf, BoxedDict* globals, 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,
......
...@@ -321,7 +321,7 @@ void compileAndRunModule(AST_Module* m, BoxedModule* bm) { ...@@ -321,7 +321,7 @@ void compileAndRunModule(AST_Module* m, BoxedModule* bm) {
} }
if (cf->is_interpreted) if (cf->is_interpreted)
astInterpretFunction(cf, 0, NULL, NULL, NULL, NULL, NULL, NULL); astInterpretFunction(cf, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
else else
((void (*)())cf->code)(); ((void (*)())cf->code)();
} }
......
...@@ -95,7 +95,7 @@ void generatorEntry(BoxedGenerator* g) { ...@@ -95,7 +95,7 @@ void generatorEntry(BoxedGenerator* g) {
BoxedFunctionBase* func = g->function; BoxedFunctionBase* func = g->function;
Box** args = g->args ? &g->args->elts[0] : nullptr; Box** args = g->args ? &g->args->elts[0] : nullptr;
callCLFunc(func->f, nullptr, func->f->numReceivedArgs(), func->closure, g, g->arg1, g->arg2, g->arg3, args); callCLFunc(func->f, nullptr, func->f->numReceivedArgs(), func->closure, g, func->globals, g->arg1, g->arg2, g->arg3, args);
} catch (ExcInfo e) { } catch (ExcInfo e) {
// unhandled exception: propagate the exception to the caller // unhandled exception: propagate the exception to the caller
g->exception = e; g->exception = e;
......
...@@ -2667,7 +2667,7 @@ Box* callFunc(BoxedFunctionBase* func, CallRewriteArgs* rewrite_args, ArgPassSpe ...@@ -2667,7 +2667,7 @@ Box* callFunc(BoxedFunctionBase* func, CallRewriteArgs* rewrite_args, ArgPassSpe
if (!func->isGenerator) { if (!func->isGenerator) {
if (argspec.num_keywords == 0 && !argspec.has_starargs && !argspec.has_kwargs && argspec.num_args == f->num_args if (argspec.num_keywords == 0 && !argspec.has_starargs && !argspec.has_kwargs && argspec.num_args == f->num_args
&& !f->takes_varargs && !f->takes_kwargs) { && !f->takes_varargs && !f->takes_kwargs) {
return callCLFunc(f, rewrite_args, argspec.num_args, closure, NULL, arg1, arg2, arg3, args); return callCLFunc(f, rewrite_args, argspec.num_args, closure, NULL, func->globals, arg1, arg2, arg3, args);
} }
} }
slowpath_callfunc_slowpath.log(); slowpath_callfunc_slowpath.log();
...@@ -2924,19 +2924,19 @@ Box* callFunc(BoxedFunctionBase* func, CallRewriteArgs* rewrite_args, ArgPassSpe ...@@ -2924,19 +2924,19 @@ Box* callFunc(BoxedFunctionBase* func, CallRewriteArgs* rewrite_args, ArgPassSpe
if (func->isGenerator) { if (func->isGenerator) {
res = createGenerator(func, oarg1, oarg2, oarg3, oargs); res = createGenerator(func, oarg1, oarg2, oarg3, oargs);
} else { } else {
res = callCLFunc(f, rewrite_args, num_output_args, closure, NULL, oarg1, oarg2, oarg3, oargs); res = callCLFunc(f, rewrite_args, num_output_args, closure, NULL, func->globals, oarg1, oarg2, oarg3, oargs);
} }
return res; return res;
} }
Box* callCLFunc(CLFunction* f, CallRewriteArgs* rewrite_args, int num_output_args, BoxedClosure* closure, Box* callCLFunc(CLFunction* f, CallRewriteArgs* rewrite_args, int num_output_args, BoxedClosure* closure,
BoxedGenerator* generator, Box* oarg1, Box* oarg2, Box* oarg3, Box** oargs) { BoxedGenerator* generator, BoxedDict* globals, Box* oarg1, Box* oarg2, Box* oarg3, Box** oargs) {
CompiledFunction* chosen_cf = pickVersion(f, num_output_args, oarg1, oarg2, oarg3, oargs); CompiledFunction* chosen_cf = pickVersion(f, num_output_args, oarg1, oarg2, oarg3, oargs);
assert(chosen_cf->is_interpreted == (chosen_cf->code == NULL)); assert(chosen_cf->is_interpreted == (chosen_cf->code == NULL));
if (chosen_cf->is_interpreted) { if (chosen_cf->is_interpreted) {
return astInterpretFunction(chosen_cf, num_output_args, closure, generator, oarg1, oarg2, oarg3, oargs); return astInterpretFunction(chosen_cf, num_output_args, closure, generator, globals, oarg1, oarg2, oarg3, oargs);
} }
if (rewrite_args) { if (rewrite_args) {
......
...@@ -138,7 +138,7 @@ bool isUserDefined(BoxedClass* cls); ...@@ -138,7 +138,7 @@ bool isUserDefined(BoxedClass* cls);
Box* processDescriptor(Box* obj, Box* inst, Box* owner); Box* processDescriptor(Box* obj, Box* inst, Box* owner);
Box* callCLFunc(CLFunction* f, CallRewriteArgs* rewrite_args, int num_output_args, BoxedClosure* closure, Box* callCLFunc(CLFunction* f, CallRewriteArgs* rewrite_args, int num_output_args, BoxedClosure* closure,
BoxedGenerator* generator, Box* oarg1, Box* oarg2, Box* oarg3, Box** oargs); BoxedGenerator* generator, BoxedDict* globals, Box* oarg1, Box* oarg2, Box* oarg3, Box** oargs);
static const char* objectNewParameterTypeErrorMsg() { static const char* objectNewParameterTypeErrorMsg() {
if (PYTHON_VERSION_HEX >= version_hex(2, 7, 4)) { if (PYTHON_VERSION_HEX >= version_hex(2, 7, 4)) {
......
...@@ -310,9 +310,11 @@ BoxedFunction::BoxedFunction(CLFunction* f) : BoxedFunction(f, {}) { ...@@ -310,9 +310,11 @@ BoxedFunction::BoxedFunction(CLFunction* f) : BoxedFunction(f, {}) {
} }
BoxedFunction::BoxedFunction(CLFunction* f, std::initializer_list<Box*> defaults, BoxedClosure* closure, BoxedFunction::BoxedFunction(CLFunction* f, std::initializer_list<Box*> defaults, BoxedClosure* closure,
bool isGenerator) bool isGenerator, BoxedDict* globals)
: BoxedFunctionBase(f, defaults, closure, isGenerator) { : BoxedFunctionBase(f, defaults, closure, isGenerator) {
this->globals = globals;
// TODO eventually we want this to assert(f->source), I think, but there are still // TODO eventually we want this to assert(f->source), I think, but there are still
// some builtin functions that are BoxedFunctions but really ought to be a type that // some builtin functions that are BoxedFunctions but really ought to be a type that
// we don't have yet. // we don't have yet.
...@@ -355,6 +357,9 @@ extern "C" void functionGCHandler(GCVisitor* v, Box* b) { ...@@ -355,6 +357,9 @@ extern "C" void functionGCHandler(GCVisitor* v, Box* b) {
if (f->closure) if (f->closure)
v->visit(f->closure); v->visit(f->closure);
if (f->globals)
v->visit(f->globals);
// It's ok for f->defaults to be NULL here even if f->ndefaults isn't, // It's ok for f->defaults to be NULL here even if f->ndefaults isn't,
// since we could be collecting from inside a BoxedFunctionBase constructor // since we could be collecting from inside a BoxedFunctionBase constructor
if (f->ndefaults) { if (f->ndefaults) {
...@@ -412,12 +417,14 @@ extern "C" void moduleGCHandler(GCVisitor* v, Box* b) { ...@@ -412,12 +417,14 @@ extern "C" void moduleGCHandler(GCVisitor* v, Box* b) {
// This mustn't throw; our IR generator generates calls to it without "invoke" even when there are exception handlers / // This mustn't throw; our IR generator generates calls to it without "invoke" even when there are exception handlers /
// finally-blocks in scope. // finally-blocks in scope.
// TODO: should we use C++11 `noexcept' here? // TODO: should we use C++11 `noexcept' here?
extern "C" Box* boxCLFunction(CLFunction* f, BoxedClosure* closure, bool isGenerator, extern "C" Box* boxCLFunction(CLFunction* f, BoxedClosure* closure, bool isGenerator, BoxedDict* globals,
std::initializer_list<Box*> defaults) { std::initializer_list<Box*> defaults) {
if (closure) if (closure)
assert(closure->cls == closure_cls); assert(closure->cls == closure_cls);
if (globals)
assert(globals->cls == dict_cls);
return new BoxedFunction(f, defaults, closure, isGenerator); return new BoxedFunction(f, defaults, closure, isGenerator, globals);
} }
extern "C" CLFunction* unboxCLFunction(Box* b) { extern "C" CLFunction* unboxCLFunction(Box* b) {
......
...@@ -123,7 +123,7 @@ char* getWriteableStringContents(BoxedString* s); ...@@ -123,7 +123,7 @@ char* getWriteableStringContents(BoxedString* s);
extern "C" void listAppendInternal(Box* self, Box* v); extern "C" void listAppendInternal(Box* self, Box* v);
extern "C" void listAppendArrayInternal(Box* self, Box** v, int nelts); extern "C" void listAppendArrayInternal(Box* self, Box** v, int nelts);
extern "C" Box* boxCLFunction(CLFunction* f, BoxedClosure* closure, bool isGenerator, extern "C" Box* boxCLFunction(CLFunction* f, BoxedClosure* closure, bool isGenerator, BoxedDict* globals,
std::initializer_list<Box*> defaults); std::initializer_list<Box*> defaults);
extern "C" CLFunction* unboxCLFunction(Box* b); extern "C" CLFunction* unboxCLFunction(Box* b);
extern "C" Box* createUserClass(const std::string* name, Box* base, Box* attr_dict); extern "C" Box* createUserClass(const std::string* name, Box* base, Box* attr_dict);
...@@ -478,7 +478,13 @@ public: ...@@ -478,7 +478,13 @@ public:
Box** in_weakreflist; Box** in_weakreflist;
CLFunction* f; CLFunction* f;
// TODO these should really go in BoxedFunction but it's annoying because they don't get
// initializd until after BoxedFunctionBase's constructor is run which means they could have
// garbage values when the GC is run (BoxedFunctionBase's constructor might call the GC).
// So ick... needs to be fixed.
BoxedClosure* closure; BoxedClosure* closure;
BoxedDict* globals;
bool isGenerator; bool isGenerator;
int ndefaults; int ndefaults;
...@@ -502,7 +508,7 @@ public: ...@@ -502,7 +508,7 @@ public:
BoxedFunction(CLFunction* f); BoxedFunction(CLFunction* f);
BoxedFunction(CLFunction* f, std::initializer_list<Box*> defaults, BoxedClosure* closure = NULL, BoxedFunction(CLFunction* f, std::initializer_list<Box*> defaults, BoxedClosure* closure = NULL,
bool isGenerator = false); bool isGenerator = false, BoxedDict* globals = NULL);
DEFAULT_CLASS(function_cls); DEFAULT_CLASS(function_cls);
}; };
......
...@@ -37,3 +37,16 @@ def f(): ...@@ -37,3 +37,16 @@ def f():
c = 20 c = 20
f() f()
""" in g, {} """ in g, {}
print 'Test global access in comprehensions'
g = {'a' : 4, 'b': 5, 'c': 6}
exec """
global a
global b
global c
print [a for i in xrange(1)]
print {b for i in xrange(1)}
print {i : b for i in xrange(1)}
print
""" 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