🐐 Unpacking arrays
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user