diff --git a/docs/features/differences.md b/docs/features/differences.md index 66f310d8..98b3b7c3 100644 --- a/docs/features/differences.md +++ b/docs/features/differences.md @@ -23,13 +23,12 @@ The easiest way to test a feature is to [try it on your browser](https://pocketp 1. `__getattr__` and `__setattr__`. 2. Descriptor protocol `__get__` and `__set__`. However, `@property` is implemented. 3. `__slots__` in class definition. -4. One element tuple. `(1,)` is not supported. -5. Unpacking in `list` and `dict` literals, e.g. `[1, 2, *a]`. -6. Access the exception object in try..except. -7. `else` clause in try..except. -8. Inplace methods like `__iadd__` and `__imul__`. -9. `__del__` in class definition. -10. Multiple inheritance. +4. Unpacking in `list` and `dict` literals, e.g. `[1, 2, *a]`. +5. Access the exception object in try..except. +6. `else` clause in try..except. +7. Inplace methods like `__iadd__` and `__imul__`. +8. `__del__` in class definition. +9. Multiple inheritance. ## Different behaviors @@ -41,5 +40,4 @@ The easiest way to test a feature is to [try it on your browser](https://pocketp 6. `__ne__` is not required. Define `__eq__` is enough. 7. Raw string cannot have boundary quotes in it, even escaped. See [#55](https://github.com/blueloveTH/pocketpy/issues/55). 8. In a starred unpacked assignment, e.g. `a, b, *c = x`, the starred variable can only be presented in the last position. `a, *b, c = x` is not supported. -9. `a < b < c` does not work as you expected. Use `a < b and b < c` instead. **(available in main branch now)** -10. A `Tab` is equivalent to 4 spaces. You can mix `Tab` and spaces in indentation, but it is not recommended. \ No newline at end of file +9. A `Tab` is equivalent to 4 spaces. You can mix `Tab` and spaces in indentation, but it is not recommended. \ No newline at end of file diff --git a/python/builtins.py b/python/builtins.py index 6e615ee4..3cfc4aef 100644 --- a/python/builtins.py +++ b/python/builtins.py @@ -160,10 +160,15 @@ str.strip = __f ##### list ##### list.__repr__ = lambda self: '[' + ', '.join([repr(i) for i in self]) + ']' -tuple.__repr__ = lambda self: '(' + ', '.join([repr(i) for i in self]) + ')' list.__json__ = lambda self: '[' + ', '.join([i.__json__() for i in self]) + ']' tuple.__json__ = lambda self: '[' + ', '.join([i.__json__() for i in self]) + ']' +def __f(self): + if len(self) == 1: + return '(' + repr(self[0]) + ',)' + return '(' + ', '.join([repr(i) for i in self]) + ')' +tuple.__repr__ = __f + def __qsort(a: list, L: int, R: int, key): if L >= R: return; mid = a[(R+L)//2]; diff --git a/src/compiler.h b/src/compiler.h index b55d6c9f..a649a08f 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -221,7 +221,8 @@ class Compiler { std::vector items; items.push_back(ctx()->s_expr.popx()); do { - EXPR(); // NOTE: "1," will fail, "1,2" will be ok + if(!is_expression()) break; + EXPR(); items.push_back(ctx()->s_expr.popx()); } while(match(TK(","))); ctx()->s_expr.push(make_expr( @@ -563,16 +564,21 @@ __SUBSCR_END: consume_end_stmt(); } + bool is_expression(){ + PrattCallback prefix = rules[curr().type].prefix; + return prefix != nullptr; + } + void parse_expression(int precedence, bool push_stack=true) { + PrattCallback prefix = rules[curr().type].prefix; + if (prefix == nullptr) SyntaxError(Str("expected an expression, but got ") + TK_STR(curr().type)); advance(); - PrattCallback prefix = rules[prev().type].prefix; - if (prefix == nullptr) SyntaxError(Str("expected an expression, but got ") + TK_STR(prev().type)); (this->*prefix)(); while (rules[curr().type].precedence >= precedence) { TokenIndex op = curr().type; advance(); PrattCallback infix = rules[op].infix; - if(infix == nullptr) throw std::runtime_error("(infix == nullptr) is true"); + PK_ASSERT(infix != nullptr); (this->*infix)(); } if(!push_stack) ctx()->emit_expr(); diff --git a/tests/06_tuple.py b/tests/06_tuple.py index a631d454..6fae7069 100644 --- a/tests/06_tuple.py +++ b/tests/06_tuple.py @@ -14,4 +14,11 @@ assert b == (1, 2, 3, 4, 5) a = tuple([]) b = *a, 1, 2, 3, *a, *a -assert b == (1, 2, 3) \ No newline at end of file +assert b == (1, 2, 3) + + +assert (1,) == tuple([1]) +assert (1,2,) == tuple([1,2]) + +a = 1, +assert a == (1,) \ No newline at end of file