diff --git a/include/pocketpy/expr.h b/include/pocketpy/expr.h index c61c1046..0f9e3abf 100644 --- a/include/pocketpy/expr.h +++ b/include/pocketpy/expr.h @@ -22,6 +22,7 @@ struct Expr{ virtual bool is_compare() const { return false; } virtual int star_level() const { return 0; } virtual bool is_tuple() const { return false; } + virtual bool is_name() const { return false; } bool is_starred() const { return star_level() > 0; } std::string str() const { PK_ASSERT(false); } @@ -73,6 +74,7 @@ struct NameExpr: Expr{ void emit(CodeEmitContext* ctx) override; bool emit_del(CodeEmitContext* ctx) override; bool emit_store(CodeEmitContext* ctx) override; + bool is_name() const override { return true; } }; struct InvertExpr: Expr{ diff --git a/src/compiler.cpp b/src/compiler.cpp index e5713d71..f96ac93b 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -862,17 +862,29 @@ __EAT_DOTS_END: default: { advance(-1); // do revert since we have pre-called advance() at the beginning EXPR_TUPLE(); - // eat variable's type hint - if(match(TK(":"))) consume_type_hints(); + + bool is_typed_name = false; // e.g. x: int + // eat variable's type hint if it is a single name + if(ctx()->s_expr.top()->is_name()){ + if(match(TK(":"))){ + consume_type_hints(); + is_typed_name = true; + } + } if(!try_compile_assignment()){ if(!ctx()->s_expr.empty() && ctx()->s_expr.top()->is_starred()){ SyntaxError(); } - ctx()->emit_expr(); - if((mode()==CELL_MODE || mode()==REPL_MODE) && name_scope()==NAME_GLOBAL){ - ctx()->emit(OP_PRINT_EXPR, BC_NOARG, BC_KEEPLINE); + if(!is_typed_name){ + ctx()->emit_expr(); + if((mode()==CELL_MODE || mode()==REPL_MODE) && name_scope()==NAME_GLOBAL){ + ctx()->emit(OP_PRINT_EXPR, BC_NOARG, BC_KEEPLINE); + }else{ + ctx()->emit(OP_POP_TOP, BC_NOARG, BC_KEEPLINE); + } }else{ - ctx()->emit(OP_POP_TOP, BC_NOARG, BC_KEEPLINE); + PK_ASSERT(ctx()->s_expr.size() == 1) + ctx()->s_expr.pop(); } } consume_end_stmt(); diff --git a/tests/40_class.py b/tests/40_class.py index 80947df0..e87081ab 100644 --- a/tests/40_class.py +++ b/tests/40_class.py @@ -98,4 +98,4 @@ class A(c.void_p): pass a = A() -assert repr(a).startswith(' bool: resp = {'code': 0, 'message': 'OK', 'data': []} successed: bool = converter(resp['message'], mapper=is_success, default=False) + + +class A: + x: List[Callable[[int], Any]] + y: Dict[str, int] + +a = A() +assert not hasattr(a, 'x') +assert not hasattr(a, 'y') + +class B: + x: List[Callable[[int], Any]] = [] + y: Dict[str, int] = {} + +b = B() +assert hasattr(b, 'x') +assert hasattr(b, 'y') + +abc123: int +assert 'abc123' not in globals() \ No newline at end of file