Преглед на файлове

support pure type hints

blueloveTH преди 2 години
родител
ревизия
bf6aaa66fb
променени са 4 файла, в които са добавени 41 реда и са изтрити 7 реда
  1. 2 0
      include/pocketpy/expr.h
  2. 18 6
      src/compiler.cpp
  3. 1 1
      tests/40_class.py
  4. 20 0
      tests/80_typing.py

+ 2 - 0
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{

+ 18 - 6
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();

+ 1 - 1
tests/40_class.py

@@ -98,4 +98,4 @@ class A(c.void_p):
     pass
     
 a = A()
-assert repr(a).startswith('<void* at')
+assert repr(a).startswith('<void* at')

+ 20 - 0
tests/80_typing.py

@@ -72,3 +72,23 @@ def is_success(value) -> 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()