From b894cc076db54c237531cbeb6b1a0f0360ce81db Mon Sep 17 00:00:00 2001 From: Sayon Dey Date: Sun, 18 Jan 2026 19:23:16 +0530 Subject: [PATCH] Added Tuple Configurations --- include/pocketpy/xmacros/opcodes.h | 1 + src/compiler/compiler.c | 20 ++++++++++++++++---- tests/060_tuple.py | 10 ++++++++++ 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/include/pocketpy/xmacros/opcodes.h b/include/pocketpy/xmacros/opcodes.h index 3a91ed38..09489364 100644 --- a/include/pocketpy/xmacros/opcodes.h +++ b/include/pocketpy/xmacros/opcodes.h @@ -51,6 +51,7 @@ OPCODE(BUILD_DICT) OPCODE(BUILD_SET) OPCODE(BUILD_SLICE) OPCODE(BUILD_STRING) +OPCODE(BUILD_GENERATOR) /**************************/ OPCODE(BINARY_ADD) OPCODE(BINARY_SUB) diff --git a/src/compiler/compiler.c b/src/compiler/compiler.c index e035ff77..37421850 100644 --- a/src/compiler/compiler.c +++ b/src/compiler/compiler.c @@ -580,6 +580,7 @@ typedef struct CompExpr { Opcode op0; Opcode op1; + bool convert_to_tuple; } CompExpr; void CompExpr__dtor(Expr* self_) { @@ -612,6 +613,11 @@ void CompExpr__emit_(Expr* self_, Ctx* ctx) { } Ctx__emit_jump(ctx, block_start, BC_KEEPLINE); Ctx__exit_block(ctx); + if(self->convert_to_tuple) { + int index = Ctx__add_name(ctx, py_name("tuple")); + Ctx__emit_(ctx, OP_LOAD_GLOBAL, index, BC_KEEPLINE); + Ctx__emit_(ctx, OP_CALL, 1, BC_KEEPLINE); + } } CompExpr* CompExpr__new(int line, Opcode op0, Opcode op1) { @@ -621,6 +627,7 @@ CompExpr* CompExpr__new(int line, Opcode op0, Opcode op1) { self->line = line; self->op0 = op0; self->op1 = op1; + self->convert_to_tuple = false; self->expr = NULL; self->vars = NULL; self->iter = NULL; @@ -1769,6 +1776,10 @@ static Error* exprGroup(Compiler* self) { check(EXPR_TUPLE(self)); // () is just for change precedence consume(TK_RPAREN); if(Ctx__s_top(ctx())->vt->is_tuple) return NULL; + if(match(TK_FOR)) { + check(consume_comp(self, OP_BUILD_LIST, OP_LIST_APPEND, true)); + return NULL; + } GroupedExpr* g = GroupedExpr__new(line, Ctx__s_popx(ctx())); Ctx__s_push(ctx(), (Expr*)g); return NULL; @@ -1801,7 +1812,7 @@ static Error* exprLiteral0(Compiler* self) { return NULL; } -static Error* consume_comp(Compiler* self, Opcode op0, Opcode op1) { +static Error* consume_comp(Compiler* self, Opcode op0, Opcode op1, bool convert_to_tuple) { // [expr] Error* err; int line = prev()->line; @@ -1814,6 +1825,7 @@ static Error* consume_comp(Compiler* self, Opcode op0, Opcode op1) { has_cond = true; } CompExpr* ce = CompExpr__new(line, op0, op1); + ce->convert_to_tuple = convert_to_tuple; if(has_cond) ce->cond = Ctx__s_popx(ctx()); ce->iter = Ctx__s_popx(ctx()); ce->vars = Ctx__s_popx(ctx()); @@ -1831,7 +1843,7 @@ static Error* exprList(Compiler* self) { check(EXPR(self)); count += 1; if(count == 1 && match(TK_FOR)) { - check(consume_comp(self, OP_BUILD_LIST, OP_LIST_APPEND)); + check(consume_comp(self, OP_BUILD_LIST, OP_LIST_APPEND, false)); consume(TK_RBRACKET); return NULL; } @@ -1865,9 +1877,9 @@ static Error* exprMap(Compiler* self) { count += 1; // key-value pair count if(count == 1 && match(TK_FOR)) { if(parsing_dict) { - check(consume_comp(self, OP_BUILD_DICT, OP_DICT_ADD)); + check(consume_comp(self, OP_BUILD_DICT, OP_DICT_ADD, false)); } else { - check(consume_comp(self, OP_BUILD_SET, OP_SET_ADD)); + check(consume_comp(self, OP_BUILD_SET, OP_SET_ADD, false)); } consume(TK_RBRACE); return NULL; diff --git a/tests/060_tuple.py b/tests/060_tuple.py index c7fd1b4b..06c63e7d 100644 --- a/tests/060_tuple.py +++ b/tests/060_tuple.py @@ -48,6 +48,16 @@ assert (1,2) < (1,3) assert (1,2) < (2,1) assert (1,2) < (2,2) assert (1,2) < (1,2,3) + +# test tuple comprehension +a = (x for x in range(5)) +assert a == (0, 1, 2, 3, 4) + +a = (x*2 for x in range(3)) +assert a == (0, 2, 4) + +a = (x for x in range(10) if x % 2 == 0) +assert a == (0, 2, 4, 6, 8) assert (1,2) < (1,2,1) assert (1,2) < (1,2,2)