diff --git a/src/common.h b/src/common.h index acbb9c50..331dd29c 100644 --- a/src/common.h +++ b/src/common.h @@ -20,7 +20,7 @@ #include #include -#define PK_VERSION "1.0.4" +#define PK_VERSION "1.0.5" #include "config.h" diff --git a/src/compiler.h b/src/compiler.h index 165ffcf7..06a81c51 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -679,7 +679,7 @@ __SUBSCR_END: case TK("<<="): case TK(">>="): case TK("&="): case TK("|="): case TK("^="): { Expr* lhs_p = ctx()->s_expr.top().get(); if(lhs_p->is_starred()) SyntaxError(); - if(ctx()->is_compiling_class) SyntaxError(); + if(ctx()->is_compiling_class) SyntaxError("can't use inplace operator in class definition"); advance(); auto e = make_expr(); e->op = prev().type - 1; // -1 to remove = @@ -695,8 +695,15 @@ __SUBSCR_END: int n = 0; while(match(TK("="))){ EXPR_TUPLE(); + Expr* _tp = ctx()->s_expr.top().get(); + if(ctx()->is_compiling_class && _tp->is_tuple()){ + SyntaxError("can't use unpack tuple in class definition"); + } n += 1; } + if(ctx()->is_compiling_class && n>1){ + SyntaxError("can't assign to multiple targets in class definition"); + } // stack size is n+1 Expr_ val = ctx()->s_expr.popx(); val->emit(ctx()); diff --git a/src/expr.h b/src/expr.h index 6782437c..d779ecf8 100644 --- a/src/expr.h +++ b/src/expr.h @@ -61,12 +61,16 @@ struct CodeEmitContext{ } void exit_block(){ - if(co->blocks[curr_block_i].type == FOR_LOOP) for_loop_depth--; + auto curr_type = co->blocks[curr_block_i].type; + if(curr_type == FOR_LOOP) for_loop_depth--; co->blocks[curr_block_i].end = co->codes.size(); curr_block_i = co->blocks[curr_block_i].parent; if(curr_block_i < 0) FATAL_ERROR(); - // add a no op here to make block check work - emit(OP_NO_OP, BC_NOARG, BC_KEEPLINE); + + if(curr_type == FOR_LOOP){ + // add a no op here to make block check work + emit(OP_NO_OP, BC_NOARG, BC_KEEPLINE); + } } // clear the expression stack and generate bytecode diff --git a/src/vm.h b/src/vm.h index edd40462..2eb7a6cb 100644 --- a/src/vm.h +++ b/src/vm.h @@ -995,7 +995,7 @@ inline std::string _opcode_argstr(VM* vm, Bytecode byte, const CodeObject* co){ case OP_LOAD_NAME: case OP_LOAD_GLOBAL: case OP_LOAD_NONLOCAL: case OP_STORE_GLOBAL: case OP_LOAD_ATTR: case OP_LOAD_METHOD: case OP_STORE_ATTR: case OP_DELETE_ATTR: case OP_IMPORT_NAME: case OP_BEGIN_CLASS: case OP_RAISE: - case OP_DELETE_GLOBAL: case OP_INC_GLOBAL: case OP_DEC_GLOBAL: + case OP_DELETE_GLOBAL: case OP_INC_GLOBAL: case OP_DEC_GLOBAL: case OP_STORE_CLASS_ATTR: argStr += fmt(" (", StrName(byte.arg).sv(), ")"); break; case OP_LOAD_FAST: case OP_STORE_FAST: case OP_DELETE_FAST: case OP_INC_FAST: case OP_DEC_FAST: diff --git a/tests/99_bugs.py b/tests/99_bugs.py index 46f83156..f058b418 100644 --- a/tests/99_bugs.py +++ b/tests/99_bugs.py @@ -53,4 +53,7 @@ def f(): for i in range(4): _ = 0 while i: --i -f() \ No newline at end of file +f() + +# class A: a=b=1 +# class A: a, b = 1, 2 \ No newline at end of file