diff --git a/src/ceval.h b/src/ceval.h index 971674c3..78016a70 100644 --- a/src/ceval.h +++ b/src/ceval.h @@ -301,6 +301,14 @@ PyVar VM::run_frame(Frame* frame){ frame->push(*ext_mod); } } continue; + case OP_STORE_ALL_NAMES: { + PyVar obj = frame->pop_value(this); + for(auto& [name, value]: obj->attr().items()){ + Str s = name.str(); + if(s.empty() || s[0] == '_') continue; + frame->f_globals().set(name, value); + } + }; continue; case OP_YIELD_VALUE: return _py_op_yield; // TODO: using "goto" inside with block may cause __exit__ not called case OP_WITH_ENTER: call(frame->pop_value(this), __enter__); continue; diff --git a/src/cffi.h b/src/cffi.h index 1f1e1e5a..fb9a7d3e 100644 --- a/src/cffi.h +++ b/src/cffi.h @@ -3,7 +3,7 @@ #include "vm.h" struct CType{ - PY_CLASS(c, type) + PY_CLASS(c, _type) const char* name; // must be a literal int size; @@ -15,7 +15,7 @@ struct CType{ vm->bind_method<0>(type, "__repr__", [](VM* vm, pkpy::Args& args) { CType& self = vm->py_cast(args[0]); StrStream ss; - ss << ""; + ss << ""; return vm->PyStr(ss.str()); }); } @@ -44,7 +44,7 @@ constexpr CType ctype_t(const char name[]){ } struct Pointer{ - PY_CLASS(c, ptr) + PY_CLASS(c, _ptr) void* ptr; CType _ctype; @@ -165,7 +165,7 @@ void add_module_c(VM* vm){ Pointer& p = vm->py_cast(args[0]); return vm->new_object(strdup(p.cast()), ctype_t("char")); }else{ - vm->TypeError("strdup() argument must be 'str' or 'c.ptr'"); + vm->TypeError("strdup() argument must be 'str' or 'c._ptr'"); return vm->None; } }); diff --git a/src/compiler.h b/src/compiler.h index 67b89828..16a91d25 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -745,6 +745,12 @@ __LISTCOMP: void compile_from_import() { Token tkmodule = _compile_import(); consume(TK("import")); + if (match(TK("*"))) { + if(name_scope() != NAME_GLOBAL) SyntaxError("import * can only be used in global scope"); + emit(OP_STORE_ALL_NAMES); + consume_end_stmt(); + return; + } do { emit(OP_DUP_TOP_VALUE); consume(TK("@id")); @@ -971,7 +977,7 @@ __LISTCOMP: consume_end_stmt(); // If last op is not an assignment, pop the result. uint8_t last_op = co()->codes.back().op; - if( last_op!=OP_STORE_NAME && last_op!=OP_STORE_REF && last_op!=OP_INPLACE_BINARY_OP && last_op!=OP_INPLACE_BITWISE_OP){ + if( last_op!=OP_STORE_NAME && last_op!=OP_STORE_REF && last_op!=OP_INPLACE_BINARY_OP && last_op!=OP_INPLACE_BITWISE_OP && last_op!=OP_STORE_ALL_NAMES){ if(last_op == OP_BUILD_TUPLE_REF) co()->codes.back().op = OP_BUILD_TUPLE; if(mode()==REPL_MODE && name_scope() == NAME_GLOBAL) emit(OP_PRINT_EXPR, -1, true); emit(OP_POP_TOP, -1, true); diff --git a/src/opcodes.h b/src/opcodes.h index 711dfbb6..2c80e3d7 100644 --- a/src/opcodes.h +++ b/src/opcodes.h @@ -85,5 +85,6 @@ OPCODE(INPLACE_BITWISE_OP) OPCODE(SETUP_CLOSURE) OPCODE(SETUP_DECORATOR) +OPCODE(STORE_ALL_NAMES) #endif \ No newline at end of file