Commit bc36f5df authored by Kevin Modzelewski's avatar Kevin Modzelewski

Merge pull request #594 from tjhance/future_flags_in_exec

Some `__future__` import stuff
parents 28963ea6 8d93be97
...@@ -111,6 +111,8 @@ ...@@ -111,6 +111,8 @@
#include "pyfpe.h" #include "pyfpe.h"
#include "code.h"
#define Py_single_input 256 #define Py_single_input 256
#define Py_file_input 257 #define Py_file_input 257
#define Py_eval_input 258 #define Py_eval_input 258
......
# expected: fail
# need `exec' support
"""Tests for binary operators on subtypes of built-in types.""" """Tests for binary operators on subtypes of built-in types."""
import unittest import unittest
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include "Python.h" #include "Python.h"
#include "capi/types.h" #include "capi/types.h"
#include "core/ast.h"
#include "core/threading.h" #include "core/threading.h"
#include "core/types.h" #include "core/types.h"
#include "runtime/classobj.h" #include "runtime/classobj.h"
......
...@@ -373,9 +373,6 @@ Value ASTInterpreter::execute(ASTInterpreter& interpreter, CFGBlock* start_block ...@@ -373,9 +373,6 @@ Value ASTInterpreter::execute(ASTInterpreter& interpreter, CFGBlock* start_block
} }
Value ASTInterpreter::doBinOp(Box* left, Box* right, int op, BinExpType exp_type) { Value ASTInterpreter::doBinOp(Box* left, Box* right, int op, BinExpType exp_type) {
if (op == AST_TYPE::Div && (source_info->parent_module->future_flags & FF_DIVISION)) {
op = AST_TYPE::TrueDiv;
}
switch (exp_type) { switch (exp_type) {
case BinExpType::AugBinOp: case BinExpType::AugBinOp:
return augbinop(left, right, op); return augbinop(left, right, op);
...@@ -1017,7 +1014,7 @@ Value ASTInterpreter::visit_exec(AST_Exec* node) { ...@@ -1017,7 +1014,7 @@ Value ASTInterpreter::visit_exec(AST_Exec* node) {
Box* globals = node->globals == NULL ? NULL : visit_expr(node->globals).o; Box* globals = node->globals == NULL ? NULL : visit_expr(node->globals).o;
Box* locals = node->locals == NULL ? NULL : visit_expr(node->locals).o; Box* locals = node->locals == NULL ? NULL : visit_expr(node->locals).o;
exec(code, globals, locals); exec(code, globals, locals, this->source_info->future_flags);
return Value(); return Value();
} }
......
...@@ -34,8 +34,15 @@ namespace pyston { ...@@ -34,8 +34,15 @@ namespace pyston {
DS_DEFINE_RWLOCK(codegen_rwlock); DS_DEFINE_RWLOCK(codegen_rwlock);
SourceInfo::SourceInfo(BoxedModule* m, ScopingAnalysis* scoping, AST* ast, std::vector<AST_stmt*> body, std::string fn) SourceInfo::SourceInfo(BoxedModule* m, ScopingAnalysis* scoping, FutureFlags future_flags, AST* ast,
: parent_module(m), scoping(scoping), ast(ast), cfg(NULL), fn(std::move(fn)), body(std::move(body)) { std::vector<AST_stmt*> body, std::string fn)
: parent_module(m),
scoping(scoping),
future_flags(future_flags),
ast(ast),
cfg(NULL),
fn(std::move(fn)),
body(std::move(body)) {
assert(this->fn.size()); assert(this->fn.size());
switch (ast->type) { switch (ast->type) {
......
...@@ -12,7 +12,13 @@ ...@@ -12,7 +12,13 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#include "future.h" #include "codegen/irgen/future.h"
#include <map>
#include "Python.h"
#include "core/ast.h"
namespace pyston { namespace pyston {
...@@ -23,13 +29,15 @@ struct FutureOption { ...@@ -23,13 +29,15 @@ struct FutureOption {
}; };
const std::map<std::string, FutureOption> future_options const std::map<std::string, FutureOption> future_options
= { { "absolute_import", { version_hex(2, 5, 0), version_hex(3, 0, 0), FF_ABSOLUTE_IMPORT } }, = { { "absolute_import", { version_hex(2, 5, 0), version_hex(3, 0, 0), CO_FUTURE_ABSOLUTE_IMPORT } },
{ "division", { version_hex(2, 2, 0), version_hex(3, 0, 0), FF_DIVISION } }, { "division", { version_hex(2, 2, 0), version_hex(3, 0, 0), CO_FUTURE_DIVISION } },
{ "generators", { version_hex(2, 2, 0), version_hex(3, 0, 0), FF_GENERATOR } }, { "unicode_literals", { version_hex(2, 6, 0), version_hex(3, 0, 0), CO_FUTURE_UNICODE_LITERALS } },
{ "unicode_literals", { version_hex(2, 6, 0), version_hex(3, 0, 0), FF_UNICODE_LITERALS } }, { "print_function", { version_hex(2, 6, 0), version_hex(3, 0, 0), CO_FUTURE_PRINT_FUNCTION } },
{ "print_function", { version_hex(2, 6, 0), version_hex(3, 0, 0), FF_PRINT_FUNCTION } }, { "with_statement", { version_hex(2, 5, 0), version_hex(3, 6, 0), CO_FUTURE_WITH_STATEMENT } },
{ "nested_scopes", { version_hex(2, 1, 0), version_hex(2, 2, 0), FF_NESTED_SCOPES } },
{ "with_statement", { version_hex(2, 5, 0), version_hex(3, 6, 0), FF_WITH_STATEMENT } } }; // These are mandatory in all versions we care about (>= 2.3)
{ "generators", { version_hex(2, 2, 0), version_hex(3, 0, 0), CO_GENERATOR } },
{ "nested_scopes", { version_hex(2, 1, 0), version_hex(2, 2, 0), CO_NESTED } } };
void raiseFutureImportErrorNotFound(const char* file, AST* node, const char* name) { void raiseFutureImportErrorNotFound(const char* file, AST* node, const char* name) {
raiseSyntaxErrorHelper(file, "", node, "future feature %s is not defined", name); raiseSyntaxErrorHelper(file, "", node, "future feature %s is not defined", name);
...@@ -59,7 +67,7 @@ inline bool is_stmt_string(AST_stmt* stmt) { ...@@ -59,7 +67,7 @@ inline bool is_stmt_string(AST_stmt* stmt) {
return stmt->type == AST_TYPE::Expr && static_cast<AST_Expr*>(stmt)->value->type == AST_TYPE::Str; return stmt->type == AST_TYPE::Expr && static_cast<AST_Expr*>(stmt)->value->type == AST_TYPE::Str;
} }
FutureFlags getFutureFlags(AST_Module* m, const char* file) { FutureFlags getFutureFlags(std::vector<AST_stmt*> const& body, const char* file) {
FutureFlags ff = 0; FutureFlags ff = 0;
// Set the defaults for the future flags depending on what version we are // Set the defaults for the future flags depending on what version we are
...@@ -73,8 +81,8 @@ FutureFlags getFutureFlags(AST_Module* m, const char* file) { ...@@ -73,8 +81,8 @@ FutureFlags getFutureFlags(AST_Module* m, const char* file) {
// occur at the beginning of the file. // occur at the beginning of the file.
bool future_import_allowed = true; bool future_import_allowed = true;
BadFutureImportVisitor import_visitor(file); BadFutureImportVisitor import_visitor(file);
for (int i = 0; i < m->body.size(); i++) { for (int i = 0; i < body.size(); i++) {
AST_stmt* stmt = m->body[i]; AST_stmt* stmt = body[i];
if (stmt->type == AST_TYPE::ImportFrom && static_cast<AST_ImportFrom*>(stmt)->module.str() == "__future__") { if (stmt->type == AST_TYPE::ImportFrom && static_cast<AST_ImportFrom*>(stmt)->module.str() == "__future__") {
if (future_import_allowed) { if (future_import_allowed) {
......
...@@ -15,29 +15,17 @@ ...@@ -15,29 +15,17 @@
#ifndef PYSTON_CODEGEN_IRGEN_FUTURE_H #ifndef PYSTON_CODEGEN_IRGEN_FUTURE_H
#define PYSTON_CODEGEN_IRGEN_FUTURE_H #define PYSTON_CODEGEN_IRGEN_FUTURE_H
#include <map> #include <vector>
#include "core/ast.h"
#include "core/options.h"
#include "core/types.h" #include "core/types.h"
namespace pyston { namespace pyston {
#define FF_ABSOLUTE_IMPORT 0x01
#define FF_DIVISION 0x02
#define FF_GENERATOR 0x04
#define FF_UNICODE_LITERALS 0x08
#define FF_PRINT_FUNCTION 0x10
#define FF_NESTED_SCOPES 0x20
#define FF_WITH_STATEMENT 0x40
typedef int FutureFlags;
// Loop through import statements to find __future__ imports throwing errors for // Loop through import statements to find __future__ imports throwing errors for
// bad __future__ imports. Returns the futures that are turned on. This is used // bad __future__ imports. Returns the futures that are turned on. This is used
// for irgeneration; the parser still has to handle some futures on its own, // for irgeneration; the parser still has to handle some futures on its own,
// when they are relevant for the parser. // when they are relevant for the parser.
FutureFlags getFutureFlags(AST_Module* m, const char* file); FutureFlags getFutureFlags(std::vector<AST_stmt*> const& body, const char* file);
} }
#endif #endif
...@@ -309,11 +309,11 @@ void compileAndRunModule(AST_Module* m, BoxedModule* bm) { ...@@ -309,11 +309,11 @@ void compileAndRunModule(AST_Module* m, BoxedModule* bm) {
const char* fn = PyModule_GetFilename(bm); const char* fn = PyModule_GetFilename(bm);
RELEASE_ASSERT(fn, ""); RELEASE_ASSERT(fn, "");
bm->future_flags = getFutureFlags(m, fn);
FutureFlags future_flags = getFutureFlags(m->body, fn);
ScopingAnalysis* scoping = new ScopingAnalysis(m, true); ScopingAnalysis* scoping = new ScopingAnalysis(m, true);
std::unique_ptr<SourceInfo> si(new SourceInfo(bm, scoping, m, m->body, fn)); std::unique_ptr<SourceInfo> si(new SourceInfo(bm, scoping, future_flags, m, m->body, fn));
bm->setattr("__doc__", si->getDocString(), NULL); bm->setattr("__doc__", si->getDocString(), NULL);
if (!bm->hasattr("__builtins__")) if (!bm->hasattr("__builtins__"))
bm->giveAttr("__builtins__", PyModule_GetDict(builtins_module)); bm->giveAttr("__builtins__", PyModule_GetDict(builtins_module));
...@@ -360,14 +360,26 @@ Box* evalOrExec(CLFunction* cl, Box* globals, Box* boxedLocals) { ...@@ -360,14 +360,26 @@ Box* evalOrExec(CLFunction* cl, Box* globals, Box* boxedLocals) {
return astInterpretFunctionEval(cf, globals, boxedLocals); return astInterpretFunctionEval(cf, globals, boxedLocals);
} }
CLFunction* compileForEvalOrExec(AST* source, std::vector<AST_stmt*> body, std::string fn) { CLFunction* compileForEvalOrExec(AST* source, std::vector<AST_stmt*> body, std::string fn, PyCompilerFlags* flags) {
LOCK_REGION(codegen_rwlock.asWrite()); LOCK_REGION(codegen_rwlock.asWrite());
Timer _t("for evalOrExec()"); Timer _t("for evalOrExec()");
ScopingAnalysis* scoping = new ScopingAnalysis(source, false); ScopingAnalysis* scoping = new ScopingAnalysis(source, false);
std::unique_ptr<SourceInfo> si(new SourceInfo(getCurrentModule(), scoping, source, std::move(body), std::move(fn))); // `my_future_flags` are the future flags enabled in the exec's code.
// `caller_future_flags` are the future flags of the source that the exec statement is in.
// We need to enable features that are enabled in either.
FutureFlags caller_future_flags = flags ? flags->cf_flags : 0;
FutureFlags my_future_flags = getFutureFlags(body, fn.c_str());
FutureFlags future_flags = caller_future_flags | my_future_flags;
if (flags) {
flags->cf_flags = future_flags;
}
std::unique_ptr<SourceInfo> si(
new SourceInfo(getCurrentModule(), scoping, future_flags, source, std::move(body), std::move(fn)));
CLFunction* cl_f = new CLFunction(0, 0, false, false, std::move(si)); CLFunction* cl_f = new CLFunction(0, 0, false, false, std::move(si));
return cl_f; return cl_f;
...@@ -405,8 +417,8 @@ static AST_Suite* parseExec(llvm::StringRef source, bool interactive = false) { ...@@ -405,8 +417,8 @@ static AST_Suite* parseExec(llvm::StringRef source, bool interactive = false) {
return parsedSuite; return parsedSuite;
} }
static CLFunction* compileExec(AST_Suite* parsedSuite, llvm::StringRef fn) { static CLFunction* compileExec(AST_Suite* parsedSuite, llvm::StringRef fn, PyCompilerFlags* flags) {
return compileForEvalOrExec(parsedSuite, parsedSuite->body, fn); return compileForEvalOrExec(parsedSuite, parsedSuite->body, fn, flags);
} }
static AST_Expression* parseEval(llvm::StringRef source) { static AST_Expression* parseEval(llvm::StringRef source) {
...@@ -432,20 +444,21 @@ static AST_Expression* parseEval(llvm::StringRef source) { ...@@ -432,20 +444,21 @@ static AST_Expression* parseEval(llvm::StringRef source) {
return parsedExpr; return parsedExpr;
} }
static CLFunction* compileEval(AST_Expression* parsedExpr, llvm::StringRef fn) { static CLFunction* compileEval(AST_Expression* parsedExpr, llvm::StringRef fn, PyCompilerFlags* flags) {
// We need body (list of statements) to compile. // We need body (list of statements) to compile.
// Obtain this by simply making a single statement which contains the expression. // Obtain this by simply making a single statement which contains the expression.
AST_Return* stmt = new AST_Return(); AST_Return* stmt = new AST_Return();
stmt->value = parsedExpr->body; stmt->value = parsedExpr->body;
std::vector<AST_stmt*> body = { stmt }; std::vector<AST_stmt*> body = { stmt };
return compileForEvalOrExec(parsedExpr, std::move(body), fn); return compileForEvalOrExec(parsedExpr, std::move(body), fn, flags);
} }
Box* compile(Box* source, Box* fn, Box* type, Box** _args) { Box* compile(Box* source, Box* fn, Box* type, Box** _args) {
Box* flags = _args[0]; Box* flags = _args[0];
Box* dont_inherit = _args[1];
RELEASE_ASSERT(dont_inherit == boxInt(0), ""); RELEASE_ASSERT(PyInt_Check(_args[1]), "");
bool dont_inherit = (bool)static_cast<BoxedInt*>(_args[1])->n;
RELEASE_ASSERT(flags->cls == int_cls, ""); RELEASE_ASSERT(flags->cls == int_cls, "");
int64_t iflags = static_cast<BoxedInt*>(flags)->n; int64_t iflags = static_cast<BoxedInt*>(flags)->n;
...@@ -475,12 +488,27 @@ Box* compile(Box* source, Box* fn, Box* type, Box** _args) { ...@@ -475,12 +488,27 @@ Box* compile(Box* source, Box* fn, Box* type, Box** _args) {
llvm::StringRef filename_str = static_cast<BoxedString*>(fn)->s(); llvm::StringRef filename_str = static_cast<BoxedString*>(fn)->s();
llvm::StringRef type_str = static_cast<BoxedString*>(type)->s(); llvm::StringRef type_str = static_cast<BoxedString*>(type)->s();
if (iflags & ~(/*PyCF_MASK | PyCF_MASK_OBSOLETE | PyCF_DONT_IMPLY_DEDENT | */ PyCF_ONLY_AST)) { if (iflags & ~(PyCF_MASK | PyCF_MASK_OBSOLETE | /* PyCF_DONT_IMPLY_DEDENT | */ PyCF_ONLY_AST)) {
raiseExcHelper(ValueError, "compile(): unrecognised flags"); raiseExcHelper(ValueError, "compile(): unrecognised flags");
} }
bool only_ast = (bool)(iflags & PyCF_ONLY_AST); bool only_ast = (bool)(iflags & PyCF_ONLY_AST);
iflags &= ~PyCF_ONLY_AST; iflags &= ~PyCF_ONLY_AST;
FutureFlags arg_future_flags = iflags & PyCF_MASK;
FutureFlags future_flags;
if (dont_inherit) {
future_flags = arg_future_flags;
} else {
CompiledFunction* caller_cf = getTopCompiledFunction();
assert(caller_cf != NULL);
assert(caller_cf->clfunc->source != NULL);
FutureFlags caller_future_flags = caller_cf->clfunc->source->future_flags;
future_flags = arg_future_flags | caller_future_flags;
}
iflags &= !(PyCF_MASK | PyCF_MASK_OBSOLETE);
RELEASE_ASSERT(iflags == 0, ""); RELEASE_ASSERT(iflags == 0, "");
AST* parsed; AST* parsed;
...@@ -505,16 +533,19 @@ Box* compile(Box* source, Box* fn, Box* type, Box** _args) { ...@@ -505,16 +533,19 @@ Box* compile(Box* source, Box* fn, Box* type, Box** _args) {
if (only_ast) if (only_ast)
return boxAst(parsed); return boxAst(parsed);
PyCompilerFlags pcf;
pcf.cf_flags = future_flags;
CLFunction* cl; CLFunction* cl;
if (type_str == "exec" || type_str == "single") { if (type_str == "exec" || type_str == "single") {
// TODO: CPython parses execs as Modules // TODO: CPython parses execs as Modules
if (parsed->type != AST_TYPE::Suite) if (parsed->type != AST_TYPE::Suite)
raiseExcHelper(TypeError, "expected Suite node, got %s", boxAst(parsed)->cls->tp_name); raiseExcHelper(TypeError, "expected Suite node, got %s", boxAst(parsed)->cls->tp_name);
cl = compileExec(static_cast<AST_Suite*>(parsed), filename_str); cl = compileExec(static_cast<AST_Suite*>(parsed), filename_str, &pcf);
} else if (type_str == "eval") { } else if (type_str == "eval") {
if (parsed->type != AST_TYPE::Expression) if (parsed->type != AST_TYPE::Expression)
raiseExcHelper(TypeError, "expected Expression node, got %s", boxAst(parsed)->cls->tp_name); raiseExcHelper(TypeError, "expected Expression node, got %s", boxAst(parsed)->cls->tp_name);
cl = compileEval(static_cast<AST_Expression*>(parsed), filename_str); cl = compileEval(static_cast<AST_Expression*>(parsed), filename_str, &pcf);
} else { } else {
raiseExcHelper(ValueError, "compile() arg 3 must be 'exec', 'eval' or 'single'"); raiseExcHelper(ValueError, "compile() arg 3 must be 'exec', 'eval' or 'single'");
} }
...@@ -522,7 +553,7 @@ Box* compile(Box* source, Box* fn, Box* type, Box** _args) { ...@@ -522,7 +553,7 @@ Box* compile(Box* source, Box* fn, Box* type, Box** _args) {
return codeForCLFunction(cl); return codeForCLFunction(cl);
} }
Box* eval(Box* boxedCode, Box* globals, Box* locals) { static Box* evalMain(Box* boxedCode, Box* globals, Box* locals, PyCompilerFlags* flags) {
if (globals == None) if (globals == None)
globals = NULL; globals = NULL;
...@@ -559,16 +590,28 @@ Box* eval(Box* boxedCode, Box* globals, Box* locals) { ...@@ -559,16 +590,28 @@ Box* eval(Box* boxedCode, Box* globals, Box* locals) {
CLFunction* cl; CLFunction* cl;
if (boxedCode->cls == str_cls) { if (boxedCode->cls == str_cls) {
AST_Expression* parsed = parseEval(static_cast<BoxedString*>(boxedCode)->s()); AST_Expression* parsed = parseEval(static_cast<BoxedString*>(boxedCode)->s());
cl = compileEval(parsed, "<string>"); cl = compileEval(parsed, "<string>", flags);
} else if (boxedCode->cls == code_cls) { } else if (boxedCode->cls == code_cls) {
cl = clfunctionFromCode(boxedCode); cl = clfunctionFromCode(boxedCode);
} else { } else {
abort(); abort();
} }
return evalOrExec(cl, globals, locals); return evalOrExec(cl, globals, locals);
} }
Box* exec(Box* boxedCode, Box* globals, Box* locals) { Box* eval(Box* boxedCode, Box* globals, Box* locals) {
CompiledFunction* caller_cf = getTopCompiledFunction();
assert(caller_cf != NULL);
assert(caller_cf->clfunc->source != NULL);
FutureFlags caller_future_flags = caller_cf->clfunc->source->future_flags;
PyCompilerFlags pcf;
pcf.cf_flags = caller_future_flags;
return evalMain(boxedCode, globals, locals, &pcf);
}
Box* execMain(Box* boxedCode, Box* globals, Box* locals, PyCompilerFlags* flags) {
if (isSubclass(boxedCode->cls, tuple_cls)) { if (isSubclass(boxedCode->cls, tuple_cls)) {
RELEASE_ASSERT(!globals, ""); RELEASE_ASSERT(!globals, "");
RELEASE_ASSERT(!locals, ""); RELEASE_ASSERT(!locals, "");
...@@ -626,7 +669,7 @@ Box* exec(Box* boxedCode, Box* globals, Box* locals) { ...@@ -626,7 +669,7 @@ Box* exec(Box* boxedCode, Box* globals, Box* locals) {
CLFunction* cl; CLFunction* cl;
if (boxedCode->cls == str_cls) { if (boxedCode->cls == str_cls) {
AST_Suite* parsed = parseExec(static_cast<BoxedString*>(boxedCode)->s()); AST_Suite* parsed = parseExec(static_cast<BoxedString*>(boxedCode)->s());
cl = compileExec(parsed, "<string>"); cl = compileExec(parsed, "<string>", flags);
} else if (boxedCode->cls == code_cls) { } else if (boxedCode->cls == code_cls) {
cl = clfunctionFromCode(boxedCode); cl = clfunctionFromCode(boxedCode);
} else { } else {
...@@ -637,14 +680,21 @@ Box* exec(Box* boxedCode, Box* globals, Box* locals) { ...@@ -637,14 +680,21 @@ Box* exec(Box* boxedCode, Box* globals, Box* locals) {
return evalOrExec(cl, globals, locals); return evalOrExec(cl, globals, locals);
} }
Box* exec(Box* boxedCode, Box* globals, Box* locals, FutureFlags caller_future_flags) {
PyCompilerFlags pcf;
pcf.cf_flags = caller_future_flags;
return execMain(boxedCode, globals, locals, &pcf);
}
extern "C" PyObject* PyRun_StringFlags(const char* str, int start, PyObject* globals, PyObject* locals, extern "C" PyObject* PyRun_StringFlags(const char* str, int start, PyObject* globals, PyObject* locals,
PyCompilerFlags* flags) noexcept { PyCompilerFlags* flags) noexcept {
try { try {
// TODO pass future_flags (the information is in PyCompilerFlags but we need to
// unify the format...)
if (start == Py_file_input) if (start == Py_file_input)
return exec(boxString(str), globals, locals); return execMain(boxString(str), globals, locals, flags);
else if (start == Py_eval_input) else if (start == Py_eval_input)
return eval(boxString(str), globals, locals); return evalMain(boxString(str), globals, locals, flags);
} catch (ExcInfo e) { } catch (ExcInfo e) {
setCAPIException(e); setCAPIException(e);
return NULL; return NULL;
......
...@@ -17,6 +17,8 @@ ...@@ -17,6 +17,8 @@
#include <string> #include <string>
#include "core/types.h"
namespace pyston { namespace pyston {
struct CompiledFunction; struct CompiledFunction;
...@@ -37,7 +39,7 @@ void compileAndRunModule(AST_Module* m, BoxedModule* bm); ...@@ -37,7 +39,7 @@ void compileAndRunModule(AST_Module* m, BoxedModule* bm);
// will we always want to generate unique function names? (ie will this function always be reasonable?) // will we always want to generate unique function names? (ie will this function always be reasonable?)
CompiledFunction* cfForMachineFunctionName(const std::string&); CompiledFunction* cfForMachineFunctionName(const std::string&);
extern "C" Box* exec(Box* boxedCode, Box* globals, Box* locals); extern "C" Box* exec(Box* boxedCode, Box* globals, Box* locals, FutureFlags caller_future_flags);
extern "C" Box* eval(Box* boxedCode, Box* globals, Box* locals); extern "C" Box* eval(Box* boxedCode, Box* globals, Box* locals);
extern "C" Box* compile(Box* source, Box* filename, Box* mode, Box** _args /* flags, dont_inherit */); extern "C" Box* compile(Box* source, Box* filename, Box* mode, Box** _args /* flags, dont_inherit */);
} }
......
...@@ -747,10 +747,6 @@ private: ...@@ -747,10 +747,6 @@ private:
assert(left); assert(left);
assert(right); assert(right);
if (type == AST_TYPE::Div && (irstate->getSourceInfo()->parent_module->future_flags & FF_DIVISION)) {
type = AST_TYPE::TrueDiv;
}
return left->binexp(emitter, getOpInfoForNode(node, unw_info), right, type, exp_type); return left->binexp(emitter, getOpInfoForNode(node, unw_info), right, type, exp_type);
} }
...@@ -1842,7 +1838,9 @@ private: ...@@ -1842,7 +1838,9 @@ private:
vlocals = getNullPtr(g.llvm_value_type_ptr); vlocals = getNullPtr(g.llvm_value_type_ptr);
} }
emitter.createCall3(unw_info, g.funcs.exec, vbody, vglobals, vlocals); static_assert(sizeof(FutureFlags) == 4, "");
emitter.createCall(unw_info, g.funcs.exec,
{ vbody, vglobals, vlocals, getConstantInt(irstate->getSourceInfo()->future_flags, g.i32) });
} }
void doPrint(AST_Print* node, UnwindInfo unw_info) { void doPrint(AST_Print* node, UnwindInfo unw_info) {
...@@ -2655,7 +2653,8 @@ CLFunction* wrapFunction(AST* node, AST_arguments* args, const std::vector<AST_s ...@@ -2655,7 +2653,8 @@ CLFunction* wrapFunction(AST* node, AST_arguments* args, const std::vector<AST_s
CLFunction*& cl = made[node]; CLFunction*& cl = made[node];
if (cl == NULL) { if (cl == NULL) {
std::unique_ptr<SourceInfo> si(new SourceInfo(source->parent_module, source->scoping, node, body, source->fn)); std::unique_ptr<SourceInfo> si(
new SourceInfo(source->parent_module, source->scoping, source->future_flags, node, body, source->fn));
if (args) if (args)
cl = new CLFunction(args->args.size(), args->defaults.size(), args->vararg.str().size(), cl = new CLFunction(args->args.size(), args->defaults.size(), args->vararg.str().size(),
args->kwarg.str().size(), std::move(si)); args->kwarg.str().size(), std::move(si));
......
...@@ -98,6 +98,8 @@ struct FrameStackState { ...@@ -98,6 +98,8 @@ struct FrameStackState {
// Returns all the stack locals, including hidden ones. // Returns all the stack locals, including hidden ones.
FrameStackState getFrameStackState(); FrameStackState getFrameStackState();
CompiledFunction* getTopCompiledFunction();
} }
#endif #endif
...@@ -19,6 +19,8 @@ ...@@ -19,6 +19,8 @@
#include <cstdio> #include <cstdio>
#include <cstdlib> #include <cstdlib>
#include "Python.h"
#include "analysis/scoping_analysis.h" #include "analysis/scoping_analysis.h"
#include "core/ast.h" #include "core/ast.h"
#include "core/options.h" #include "core/options.h"
...@@ -637,7 +639,7 @@ private: ...@@ -637,7 +639,7 @@ private:
AST_BinOp* rtn = new AST_BinOp(); AST_BinOp* rtn = new AST_BinOp();
rtn->lineno = node->lineno; rtn->lineno = node->lineno;
rtn->col_offset = node->col_offset; rtn->col_offset = node->col_offset;
rtn->op_type = node->op_type; rtn->op_type = remapBinOpType(node->op_type);
rtn->left = remapExpr(node->left); rtn->left = remapExpr(node->left);
rtn->right = remapExpr(node->right); rtn->right = remapExpr(node->right);
return rtn; return rtn;
...@@ -1481,7 +1483,7 @@ public: ...@@ -1481,7 +1483,7 @@ public:
// level == -1 means check both sys path and relative for imports. // level == -1 means check both sys path and relative for imports.
// so if `from __future__ import absolute_import` was used in the file, set level to 0 // so if `from __future__ import absolute_import` was used in the file, set level to 0
int level; int level;
if (!(future_flags & FF_ABSOLUTE_IMPORT)) if (!(future_flags & CO_FUTURE_ABSOLUTE_IMPORT))
level = -1; level = -1;
else else
level = 0; level = 0;
...@@ -1532,7 +1534,7 @@ public: ...@@ -1532,7 +1534,7 @@ public:
// level == -1 means check both sys path and relative for imports. // level == -1 means check both sys path and relative for imports.
// so if `from __future__ import absolute_import` was used in the file, set level to 0 // so if `from __future__ import absolute_import` was used in the file, set level to 0
int level; int level;
if (node->level == 0 && !(future_flags & FF_ABSOLUTE_IMPORT)) if (node->level == 0 && !(future_flags & CO_FUTURE_ABSOLUTE_IMPORT))
level = -1; level = -1;
else else
level = node->level; level = node->level;
...@@ -1716,7 +1718,7 @@ public: ...@@ -1716,7 +1718,7 @@ public:
} }
AST_AugBinOp* binop = new AST_AugBinOp(); AST_AugBinOp* binop = new AST_AugBinOp();
binop->op_type = node->op_type; binop->op_type = remapBinOpType(node->op_type);
binop->left = remapped_lhs; binop->left = remapped_lhs;
binop->right = remapExpr(node->value); binop->right = remapExpr(node->value);
binop->col_offset = node->col_offset; binop->col_offset = node->col_offset;
...@@ -1728,6 +1730,14 @@ public: ...@@ -1728,6 +1730,14 @@ public:
return true; return true;
} }
AST_TYPE::AST_TYPE remapBinOpType(AST_TYPE::AST_TYPE op_type) {
if (op_type == AST_TYPE::Div && (future_flags & (CO_FUTURE_DIVISION))) {
return AST_TYPE::TrueDiv;
} else {
return op_type;
}
}
bool visit_delete(AST_Delete* node) override { bool visit_delete(AST_Delete* node) override {
for (auto t : node->targets) { for (auto t : node->targets) {
AST_Delete* astdel = new AST_Delete(); AST_Delete* astdel = new AST_Delete();
...@@ -2466,7 +2476,7 @@ CFG* computeCFG(SourceInfo* source, std::vector<AST_stmt*> body) { ...@@ -2466,7 +2476,7 @@ CFG* computeCFG(SourceInfo* source, std::vector<AST_stmt*> body) {
ScopingAnalysis* scoping_analysis = source->scoping; ScopingAnalysis* scoping_analysis = source->scoping;
CFGVisitor visitor(source, source->ast->type, source->parent_module->future_flags, scoping_analysis, rtn); CFGVisitor visitor(source, source->ast->type, source->future_flags, scoping_analysis, rtn);
bool skip_first = false; bool skip_first = false;
......
...@@ -242,6 +242,8 @@ private: ...@@ -242,6 +242,8 @@ private:
ParamNames() : takes_param_names(false) {} ParamNames() : takes_param_names(false) {}
}; };
typedef int FutureFlags;
class BoxedModule; class BoxedModule;
class ScopeInfo; class ScopeInfo;
class InternedStringPool; class InternedStringPool;
...@@ -249,6 +251,7 @@ class SourceInfo { ...@@ -249,6 +251,7 @@ class SourceInfo {
public: public:
BoxedModule* parent_module; BoxedModule* parent_module;
ScopingAnalysis* scoping; ScopingAnalysis* scoping;
FutureFlags future_flags;
AST* ast; AST* ast;
CFG* cfg; CFG* cfg;
bool is_generator; bool is_generator;
...@@ -267,7 +270,8 @@ public: ...@@ -267,7 +270,8 @@ public:
Box* getDocString(); Box* getDocString();
SourceInfo(BoxedModule* m, ScopingAnalysis* scoping, AST* ast, std::vector<AST_stmt*> body, std::string fn); SourceInfo(BoxedModule* m, ScopingAnalysis* scoping, FutureFlags future_flags, AST* ast,
std::vector<AST_stmt*> body, std::string fn);
}; };
typedef std::vector<CompiledFunction*> FunctionList; typedef std::vector<CompiledFunction*> FunctionList;
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "llvm/Support/Path.h" #include "llvm/Support/Path.h"
#include "codegen/unwinding.h" #include "codegen/unwinding.h"
#include "core/ast.h"
#include "core/types.h" #include "core/types.h"
#include "gc/collector.h" #include "gc/collector.h"
#include "runtime/file.h" #include "runtime/file.h"
......
...@@ -1282,9 +1282,11 @@ void setupBuiltins() { ...@@ -1282,9 +1282,11 @@ void setupBuiltins() {
builtins_module->giveAttr("execfile", builtins_module->giveAttr("execfile",
new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)execfile, UNKNOWN, 1), "execfile")); new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)execfile, UNKNOWN, 1), "execfile"));
builtins_module->giveAttr( CLFunction* compile_func = createRTFunction(
"compile", new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)compile, UNKNOWN, 5, 2, false, false), 5, 2, false, false, ParamNames({ "source", "filename", "mode", "flags", "dont_inherit" }, "", ""));
"compile", { boxInt(0), boxInt(0) })); addRTFunction(compile_func, (void*)compile, UNKNOWN, { UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN });
builtins_module->giveAttr("compile",
new BoxedBuiltinFunctionOrMethod(compile_func, "compile", { boxInt(0), boxInt(0) }));
builtins_module->giveAttr( builtins_module->giveAttr(
"map", new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)map, LIST, 1, 0, true, false), "map")); "map", new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)map, LIST, 1, 0, true, false), "map"));
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include "code.h" #include "code.h"
#include "core/ast.h"
#include "gc/collector.h" #include "gc/collector.h"
#include "runtime/objmodel.h" #include "runtime/objmodel.h"
#include "runtime/set.h" #include "runtime/set.h"
......
...@@ -22,10 +22,11 @@ ...@@ -22,10 +22,11 @@
#include "codegen/ast_interpreter.h" // interpreter_instr_addr #include "codegen/ast_interpreter.h" // interpreter_instr_addr
#include "codegen/unwinding.h" // getCFForAddress #include "codegen/unwinding.h" // getCFForAddress
#include "core/stats.h" // StatCounter #include "core/ast.h"
#include "core/types.h" // for ExcInfo #include "core/stats.h" // StatCounter
#include "core/util.h" // Timer #include "core/types.h" // for ExcInfo
#include "runtime/generator.h" // generatorEntry #include "core/util.h" // Timer
#include "runtime/generator.h" // generatorEntry
#define UNW_LOCAL_ONLY #define UNW_LOCAL_ONLY
#include <libunwind.h> #include <libunwind.h>
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "runtime/dict.h" #include "runtime/dict.h"
#include "capi/types.h" #include "capi/types.h"
#include "core/ast.h"
#include "core/common.h" #include "core/common.h"
#include "core/stats.h" #include "core/stats.h"
#include "core/types.h" #include "core/types.h"
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "pythread.h" #include "pythread.h"
#include "codegen/unwinding.h" #include "codegen/unwinding.h"
#include "core/ast.h"
#include "runtime/types.h" #include "runtime/types.h"
namespace pyston { namespace pyston {
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include "codegen/irgen/hooks.h" #include "codegen/irgen/hooks.h"
#include "codegen/parser.h" #include "codegen/parser.h"
#include "codegen/unwinding.h" #include "codegen/unwinding.h"
#include "core/ast.h"
#include "runtime/capi.h" #include "runtime/capi.h"
#include "runtime/objmodel.h" #include "runtime/objmodel.h"
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <sstream> #include <sstream>
#include "capi/typeobject.h" #include "capi/typeobject.h"
#include "core/ast.h"
#include "core/common.h" #include "core/common.h"
#include "core/options.h" #include "core/options.h"
#include "core/stats.h" #include "core/stats.h"
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <dlfcn.h> #include <dlfcn.h>
#include "codegen/unwinding.h" #include "codegen/unwinding.h"
#include "core/ast.h"
#include "core/options.h" #include "core/options.h"
#include "gc/collector.h" #include "gc/collector.h"
#include "runtime/objmodel.h" #include "runtime/objmodel.h"
......
...@@ -22,10 +22,12 @@ ...@@ -22,10 +22,12 @@
#include "llvm/Support/raw_ostream.h" #include "llvm/Support/raw_ostream.h"
#include "analysis/scoping_analysis.h"
#include "capi/typeobject.h" #include "capi/typeobject.h"
#include "capi/types.h" #include "capi/types.h"
#include "codegen/ast_interpreter.h" #include "codegen/ast_interpreter.h"
#include "codegen/unwinding.h" #include "codegen/unwinding.h"
#include "core/ast.h"
#include "core/options.h" #include "core/options.h"
#include "core/stats.h" #include "core/stats.h"
#include "core/types.h" #include "core/types.h"
......
...@@ -5,4 +5,10 @@ print 1 / 2 ...@@ -5,4 +5,10 @@ print 1 / 2
exec "print 1 / 2" exec "print 1 / 2"
exec compile("print 1 / 2", "<string>", "exec") exec compile("print 1 / 2", "<string>", "exec")
# But you can explicitly request that they not be inherited: # But you can explicitly request that they not be inherited:
# exec compile("print 1 / 2", "<string>", "exec", flags=0, dont_inherit=True) exec compile("print 1 / 2", "<string>", "exec", flags=0, dont_inherit=True)
exec compile("print 1 / 2", "<string>", "exec", flags=division.compiler_flag, dont_inherit=True)
# test the above but with eval
print eval(compile("1 / 2", "<string>", "eval"))
print eval(compile("1 / 2", "<string>", "eval", flags=0, dont_inherit=True))
print eval(compile("1 / 2", "<string>", "eval", flags=division.compiler_flag, dont_inherit=True))
# co is compiled without the __future__ division import.
# So even though the import is present in the exec statements,
# the code will be evaluated without it. Each should print 0.
co = compile("1 / 2", "<string>", "eval")
exec """
from __future__ import division
print eval(co)
"""
co = compile("print 1 / 2", "<string>", "exec")
exec """
from __future__ import division
exec co
"""
print 1 / 2
exec """
print 1 / 2
"""
exec """
from __future__ import division
print 1 / 2
"""
exec """
from __future__ import division
exec "print 1 / 2"
"""
print 1 / 2
print eval("1 / 2")
exec """
print eval("1 / 2")
"""
exec """
from __future__ import division
print eval("1 / 2")
"""
from __future__ import division
print 1 / 2
exec """print 1 / 2"""
exec """
from __future__ import division
print 1 / 2
"""
print eval("1 / 2")
exec """
print eval("1 / 2")
"""
exec """
from __future__ import division
print eval("1 / 2")
"""
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "analysis/function_analysis.h" #include "analysis/function_analysis.h"
#include "analysis/scoping_analysis.h" #include "analysis/scoping_analysis.h"
#include "codegen/irgen/future.h"
#include "codegen/osrentry.h" #include "codegen/osrentry.h"
#include "codegen/parser.h" #include "codegen/parser.h"
#include "core/ast.h" #include "core/ast.h"
...@@ -36,7 +37,9 @@ TEST_F(AnalysisTest, augassign) { ...@@ -36,7 +37,9 @@ TEST_F(AnalysisTest, augassign) {
ASSERT_FALSE(scope_info->getScopeTypeOfName(module->interned_strings->get("a")) == ScopeInfo::VarScopeType::GLOBAL); ASSERT_FALSE(scope_info->getScopeTypeOfName(module->interned_strings->get("a")) == ScopeInfo::VarScopeType::GLOBAL);
ASSERT_FALSE(scope_info->getScopeTypeOfName(module->interned_strings->get("b")) == ScopeInfo::VarScopeType::GLOBAL); ASSERT_FALSE(scope_info->getScopeTypeOfName(module->interned_strings->get("b")) == ScopeInfo::VarScopeType::GLOBAL);
SourceInfo* si = new SourceInfo(createModule("augassign", fn.c_str()), scoping, func, func->body, fn); FutureFlags future_flags = getFutureFlags(module->body, fn.c_str());
SourceInfo* si = new SourceInfo(createModule("augassign", fn.c_str()), scoping, future_flags, func, func->body, fn);
CFG* cfg = computeCFG(si, func->body); CFG* cfg = computeCFG(si, func->body);
std::unique_ptr<LivenessAnalysis> liveness = computeLivenessInfo(cfg); std::unique_ptr<LivenessAnalysis> liveness = computeLivenessInfo(cfg);
...@@ -62,9 +65,11 @@ void doOsrTest(bool is_osr, bool i_maybe_undefined) { ...@@ -62,9 +65,11 @@ void doOsrTest(bool is_osr, bool i_maybe_undefined) {
assert(module->body[0]->type == AST_TYPE::FunctionDef); assert(module->body[0]->type == AST_TYPE::FunctionDef);
AST_FunctionDef* func = static_cast<AST_FunctionDef*>(module->body[0]); AST_FunctionDef* func = static_cast<AST_FunctionDef*>(module->body[0]);
FutureFlags future_flags = getFutureFlags(module->body, fn.c_str());
ScopeInfo* scope_info = scoping->getScopeInfoForNode(func); ScopeInfo* scope_info = scoping->getScopeInfoForNode(func);
SourceInfo* si = new SourceInfo(createModule("osr" + std::to_string((is_osr << 1) + i_maybe_undefined), fn.c_str()), SourceInfo* si = new SourceInfo(createModule("osr" + std::to_string((is_osr << 1) + i_maybe_undefined), fn.c_str()),
scoping, func, func->body, fn); scoping, future_flags, func, func->body, fn);
CFG* cfg = computeCFG(si, func->body); CFG* cfg = computeCFG(si, func->body);
std::unique_ptr<LivenessAnalysis> liveness = computeLivenessInfo(cfg); std::unique_ptr<LivenessAnalysis> liveness = computeLivenessInfo(cfg);
......
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