🐐 Unpacking arrays

This commit is contained in:
2026-04-21 14:54:36 +02:00
parent c28ffbbf45
commit 63c35605a2
7 changed files with 127 additions and 4 deletions

View File

@@ -431,6 +431,35 @@ class DesignaIndex(Node):
return vtable, ValNul()
class DesignaDestructure(Node):
def __init__(self, variables: list, value: Node) -> None:
self.ids = variables
self.value = value
def __eq__(self, other):
return type(self) == type(other) and self.ids == other.ids and self.value == other.value
def __repr__(self) -> str:
ids_string = ", ".join(repr(i) for i in self.ids)
value_string = repr(self.value).replace('\n', '\n ')
return f"DesignaDestructure(\n [{ids_string}],\n {value_string}\n)"
def print(self):
ids_str = ", ".join(i.print() for i in self.ids)
return f"DESIGNA {ids_str} VT {self.value.print()}"
def _eval(self, vtable):
vtable, val = self.value.eval(vtable)
if not isinstance(val, ValList):
raise CentvrionError("Cannot destructure non-array value")
if len(val.value()) != len(self.ids):
raise CentvrionError(
f"Destructuring mismatch: {len(self.ids)} targets, {len(val.value())} values")
for id_node, item in zip(self.ids, val.value()):
vtable[id_node.name] = item
return vtable, ValNul()
class Defini(Node):
def __init__(self, name: ID, parameters: list[ID], statements: list[Node]) -> None:
self.name = name

View File

@@ -1,6 +1,6 @@
from centvrion.ast_nodes import (
Designa, DesignaIndex, SiStatement, DumStatement, PerStatement,
Defini, Redi, Erumpe, Continva, ExpressionStatement, ID,
Designa, DesignaIndex, DesignaDestructure, SiStatement, DumStatement,
PerStatement, Defini, Redi, Erumpe, Continva, ExpressionStatement, ID,
)
from centvrion.compiler.emit_expr import emit_expr
@@ -29,6 +29,18 @@ def emit_stmt(node, ctx):
]
)
if isinstance(node, DesignaDestructure):
n = len(node.ids)
val_lines, val_var = emit_expr(node.value, ctx)
lines = val_lines[:]
lines.append(f'if ({val_var}.type != CENT_LIST) cent_type_error("Cannot destructure non-array value");')
lines.append(f'if ({val_var}.lval.len != {n}) cent_runtime_error("Destructuring mismatch");')
for i, id_node in enumerate(node.ids):
tmp = ctx.fresh_tmp()
lines.append(f"CentValue {tmp} = cent_list_index({val_var}, cent_int({i + 1}));")
lines.append(f'cent_scope_set(&_scope, "{id_node.name}", {tmp});')
return lines
if isinstance(node, SiStatement):
cond_lines, cond_var = emit_expr(node.test, ctx)
then_lines = _emit_body(node.statements, ctx)

View File

@@ -74,6 +74,10 @@ class Parser():
def statement_designa_index(tokens):
return ast_nodes.DesignaIndex(tokens[1], tokens[3], tokens[6])
@self.pg.production('statement : KEYWORD_DESIGNA id SYMBOL_COMMA id_list_rest KEYWORD_VT expression')
def statement_designa_destructure(tokens):
return ast_nodes.DesignaDestructure([tokens[1]] + tokens[3], tokens[5])
@self.pg.production('statement : id KEYWORD_AVGE expression')
def statement_avge(tokens):
return ast_nodes.Designa(tokens[0], ast_nodes.BinOp(tokens[0], tokens[2], "SYMBOL_PLUS"))
@@ -258,6 +262,14 @@ class Parser():
else:
return [calls[0]] + calls[2]
@self.pg.production('id_list_rest : id')
@self.pg.production('id_list_rest : id SYMBOL_COMMA id_list_rest')
def id_list_rest(calls):
if len(calls) == 1:
return [calls[0]]
else:
return [calls[0]] + calls[2]
@self.pg.production("id : ID")
def id_expression(tokens):
return ast_nodes.ID(tokens[0].value)