namespace pyston { int GLOBAL_VERBOSITY = 0; int PYTHON_VERSION_MAJOR = DEFAULT_PYTHON_MAJOR_VERSION; int PYTHON_VERSION_MINOR = DEFAULT_PYTHON_MINOR_VERSION; int PYTHON_VERSION_MICRO = DEFAULT_PYTHON_MICRO_VERSION; int PYTHON_VERSION_HEX = version_hex(PYTHON_VERSION_MAJOR, PYTHON_VERSION_MINOR, PYTHON_VERSION_MICRO); int MAX_OPT_ITERATIONS = 1; bool FORCE_OPTIMIZE = false; bool SHOW_DISASM = false; bool BENCH = false; bool PROFILE = false; bool DUMPJIT = false; bool TRAP = false; bool USE_STRIPPED_STDLIB = true; // always true bool ENABLE_INTERPRETER = true; bool ENABLE_PYPA_PARSER = false; static bool _GLOBAL_ENABLE = 1; bool ENABLE_ICS = 1 && _GLOBAL_ENABLE; bool ENABLE_ICGENERICS = 1 && ENABLE_ICS; bool ENABLE_ICGETITEMS = 1 && ENABLE_ICS; bool ENABLE_ICSETITEMS = 1 && ENABLE_ICS; bool ENABLE_ICDELITEMS = 1 && ENABLE_ICS; bool ENABLE_ICCALLSITES = 1 && ENABLE_ICS; bool ENABLE_ICSETATTRS = 1 && ENABLE_ICS; bool ENABLE_ICGETATTRS = 1 && ENABLE_ICS; bool ENALBE_ICDELATTRS = 1 && ENABLE_ICS; bool ENABLE_ICGETGLOBALS = 1 && ENABLE_ICS; bool ENABLE_ICBINEXPS = 1 && ENABLE_ICS; bool ENABLE_ICNONZEROS = 1 && ENABLE_ICS; bool ENABLE_SPECULATION = 1 && _GLOBAL_ENABLE; bool ENABLE_OSR = 1 && _GLOBAL_ENABLE; bool ENABLE_LLVMOPTS = 1 && _GLOBAL_ENABLE; bool ENABLE_INLINING = 1 && _GLOBAL_ENABLE; bool ENABLE_REOPT = 1 && _GLOBAL_ENABLE; bool ENABLE_PYSTON_PASSES = 1 && _GLOBAL_ENABLE; bool ENABLE_TYPE_FEEDBACK = 1 && _GLOBAL_ENABLE; bool ENABLE_RUNTIME_ICS = 1 && _GLOBAL_ENABLE; bool ENABLE_FRAME_INTROSPECTION = 1; bool BOOLS_AS_I64 = ENABLE_FRAME_INTROSPECTION; }
namespace pyston { struct FutureOption { int optional_version_hex; int mandatory_version_hex; int ff_mask; }; const std::map<std::string, FutureOption> future_options = { { "absolute_import", { version_hex(2, 5, 0), version_hex(3, 0, 0), FF_ABSOLUTE_IMPORT } }, { "division", { version_hex(2, 2, 0), version_hex(3, 0, 0), FF_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), FF_UNICODE_LITERALS } }, { "print_function", { version_hex(2, 6, 0), version_hex(3, 0, 0), FF_PRINT_FUNCTION } }, { "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 } } }; void raiseFutureImportErrorNotFound(const char* file, AST* node, const char* name) { raiseSyntaxErrorHelper(file, "", node, "future feature %s is not defined", name); } void raiseFutureImportErrorNotBeginning(const char* file, AST* node) { raiseSyntaxErrorHelper(file, "", node, "from __future__ imports must occur at the beginning of the file"); } class BadFutureImportVisitor : public NoopASTVisitor { public: virtual bool visit_importfrom(AST_ImportFrom* node) { if (node->module.str() == "__future__") { raiseFutureImportErrorNotBeginning(file, node); } return true; } // TODO optimization: have it skip things like expressions that you know // there is no need to descend into BadFutureImportVisitor(const char* file) : file(file) {} const char* file; }; inline bool is_stmt_string(AST_stmt* stmt) { 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 ff = 0; // Set the defaults for the future flags depending on what version we are for (const std::pair<std::string, FutureOption>& p : future_options) { if (PYTHON_VERSION_HEX >= p.second.mandatory_version_hex) { ff |= p.second.ff_mask; } } // Find all the __future__ imports, raising an error for those that do not // occur at the beginning of the file. bool future_import_allowed = true; BadFutureImportVisitor import_visitor(file); for (int i = 0; i < m->body.size(); i++) { AST_stmt* stmt = m->body[i]; if (stmt->type == AST_TYPE::ImportFrom && static_cast<AST_ImportFrom*>(stmt)->module.str() == "__future__") { if (future_import_allowed) { // We have a `from __future__` import statement, and we are // still at the top of the file, so just set the appropriate // future flag for each imported option. for (AST_alias* alias : static_cast<AST_ImportFrom*>(stmt)->names) { const std::string& option_name = alias->name.str(); auto iter = future_options.find(option_name); if (iter == future_options.end()) { // If it's not one of the available options, throw an error. // Note: the __future__ module also exposes "all_feature_names", // but you still can't import that using a from-import, so we // don't need to worry about that here. raiseFutureImportErrorNotFound(file, alias, option_name.c_str()); } else { const FutureOption& fo = iter->second; if (PYTHON_VERSION_HEX >= fo.optional_version_hex) { ff |= fo.ff_mask; } else { raiseFutureImportErrorNotFound(file, alias, option_name.c_str()); } } } } else { raiseFutureImportErrorNotBeginning(file, stmt); } } else { // A docstring is allowed at the beginning of a module; otherwise, // we cannot permit any __future__ import after this point. if (i > 0 || !is_stmt_string(stmt)) { // Recurse on the node and throw an error if it has any // `from __future__` import statement. stmt->accept(&import_visitor); future_import_allowed = false; } } } return ff; } }
namespace pyston { int GLOBAL_VERBOSITY = 0; int PYSTON_VERSION_MAJOR = 0; int PYSTON_VERSION_MINOR = 3; int PYTHON_VERSION_MAJOR = DEFAULT_PYTHON_MAJOR_VERSION; int PYTHON_VERSION_MINOR = DEFAULT_PYTHON_MINOR_VERSION; int PYTHON_VERSION_MICRO = DEFAULT_PYTHON_MICRO_VERSION; int PYTHON_VERSION_HEX = version_hex(PYTHON_VERSION_MAJOR, PYTHON_VERSION_MINOR, PYTHON_VERSION_MICRO); int MAX_OPT_ITERATIONS = 1; bool FORCE_INTERPRETER = false; bool FORCE_OPTIMIZE = false; bool SHOW_DISASM = false; bool PROFILE = false; bool DUMPJIT = false; bool TRAP = false; bool USE_STRIPPED_STDLIB = true; // always true bool ENABLE_INTERPRETER = true; bool ENABLE_PYPA_PARSER = true; bool USE_REGALLOC_BASIC = true; int OSR_THRESHOLD_INTERPRETER = 200; int REOPT_THRESHOLD_INTERPRETER = 100; int OSR_THRESHOLD_BASELINE = 10000; int REOPT_THRESHOLD_BASELINE = 250; int OSR_THRESHOLD_T2 = 10000; int REOPT_THRESHOLD_T2 = 10000; int SPECULATION_THRESHOLD = 100; static bool _GLOBAL_ENABLE = 1; bool ENABLE_ICS = 1 && _GLOBAL_ENABLE; bool ENABLE_ICGENERICS = 1 && ENABLE_ICS; bool ENABLE_ICGETITEMS = 1 && ENABLE_ICS; bool ENABLE_ICSETITEMS = 1 && ENABLE_ICS; bool ENABLE_ICDELITEMS = 1 && ENABLE_ICS; bool ENABLE_ICCALLSITES = 1 && ENABLE_ICS; bool ENABLE_ICSETATTRS = 1 && ENABLE_ICS; bool ENABLE_ICGETATTRS = 1 && ENABLE_ICS; bool ENALBE_ICDELATTRS = 1 && ENABLE_ICS; bool ENABLE_ICGETGLOBALS = 1 && ENABLE_ICS; bool ENABLE_ICBINEXPS = 1 && ENABLE_ICS; bool ENABLE_ICNONZEROS = 1 && ENABLE_ICS; bool ENABLE_SPECULATION = 1 && _GLOBAL_ENABLE; bool ENABLE_OSR = 1 && _GLOBAL_ENABLE; bool ENABLE_LLVMOPTS = 1 && _GLOBAL_ENABLE; bool ENABLE_INLINING = 1 && _GLOBAL_ENABLE; bool ENABLE_REOPT = 1 && _GLOBAL_ENABLE; bool ENABLE_PYSTON_PASSES = 1 && _GLOBAL_ENABLE; bool ENABLE_TYPE_FEEDBACK = 1 && _GLOBAL_ENABLE; bool ENABLE_RUNTIME_ICS = 1 && _GLOBAL_ENABLE; bool ENABLE_FRAME_INTROSPECTION = 1; bool BOOLS_AS_I64 = ENABLE_FRAME_INTROSPECTION; extern "C" { int Py_FrozenFlag = 1; int Py_IgnoreEnvironmentFlag = 0; int Py_NoSiteFlag = 0; int Py_OptimizeFlag = 0; int Py_VerboseFlag = 0; } }
namespace pyston { struct FutureOption { int optional_version_hex; int mandatory_version_hex; int ff_mask; }; const std::map<std::string, FutureOption> future_options = { { "absolute_import", { version_hex(2, 5, 0), version_hex(3, 0, 0), FF_ABSOLUTE_IMPORT } }, { "division", { version_hex(2, 2, 0), version_hex(3, 0, 0), FF_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), FF_UNICODE_LITERALS } }, { "print_functions", { version_hex(2, 6, 0), version_hex(3, 0, 0), FF_PRINT_FUNCTIONS } }, { "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 } } }; // Helper function: void raiseSyntaxError(const char* file, AST* node_at, const char* msg, ...) { va_list ap; va_start(ap, msg); char buf[1024]; vsnprintf(buf, sizeof(buf), msg, ap); // TODO I'm not sure that it's safe to raise an exception here, since I think // there will be things that end up not getting cleaned up. // Then again, there are a huge number of things that don't get cleaned up even // if an exception doesn't get thrown... // TODO output is still a little wrong, should be, for example // // File "../test/tests/future_non_existent.py", line 1 // from __future__ import rvalue_references # should cause syntax error // // but instead it is // // Traceback (most recent call last): // File "../test/tests/future_non_existent.py", line -1, in : // from __future__ import rvalue_references # should cause syntax error ::pyston::raiseSyntaxError(buf, node_at->lineno, node_at->col_offset, file, ""); } void raiseFutureImportErrorNotFound(const char* file, AST* node, const char* name) { raiseSyntaxError(file, node, "future feature %s is not defined", name); } void raiseFutureImportErrorNotBeginning(const char* file, AST* node) { raiseSyntaxError(file, node, "from __future__ imports must occur at the beginning of the file"); } class BadFutureImportVisitor : public NoopASTVisitor { public: virtual bool visit_importfrom(AST_ImportFrom* node) { if (node->module == "__future__") { raiseFutureImportErrorNotBeginning(file, node); } return true; } // TODO optimization: have it skip things like expressions that you know // there is no need to descend into BadFutureImportVisitor(const char* file) : file(file) {} const char* file; }; inline bool is_stmt_string(AST_stmt* stmt) { 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 ff = 0; // Set the defaults for the future flags depending on what version we are for (const std::pair<std::string, FutureOption>& p : future_options) { if (PYTHON_VERSION_HEX >= p.second.mandatory_version_hex) { ff |= p.second.ff_mask; } } // Find all the __future__ imports, raising an error for those that do not // occur at the beginning of the file. bool future_import_allowed = true; BadFutureImportVisitor import_visitor(file); for (int i = 0; i < m->body.size(); i++) { AST_stmt* stmt = m->body[i]; if (stmt->type == AST_TYPE::ImportFrom && static_cast<AST_ImportFrom*>(stmt)->module == "__future__") { if (future_import_allowed) { // We have a `from __future__` import statement, and we are // still at the top of the file, so just set the appropriate // future flag for each imported option. for (AST_alias* alias : static_cast<AST_ImportFrom*>(stmt)->names) { const std::string& option_name = alias->name; auto iter = future_options.find(option_name); if (iter == future_options.end()) { // If it's not one of the available options, throw an error. // Note: the __future__ module also exposes "all_feature_names", // but you still can't import that using a from-import, so we // don't need to worry about that here. raiseFutureImportErrorNotFound(file, alias, option_name.c_str()); } else { const FutureOption& fo = iter->second; if (PYTHON_VERSION_HEX >= fo.optional_version_hex) { ff |= fo.ff_mask; } else { raiseFutureImportErrorNotFound(file, alias, option_name.c_str()); } } } } else { raiseFutureImportErrorNotBeginning(file, stmt); } } else { // A docstring is allowed at the beginning of a module; otherwise, // we cannot permit any __future__ import after this point. if (i > 0 || !is_stmt_string(stmt)) { // Recurse on the node and throw an error if it has any // `from __future__` import statement. stmt->accept(&import_visitor); future_import_allowed = false; } } } return ff; } }