🐐 Step in for loop
This commit is contained in:
+33
-6
@@ -369,19 +369,28 @@ class DataArray(Node):
|
||||
|
||||
|
||||
class DataRangeArray(Node):
|
||||
def __init__(self, from_value, to_value) -> None:
|
||||
def __init__(self, from_value, to_value, step=None) -> None:
|
||||
self.from_value = from_value
|
||||
self.to_value = to_value
|
||||
self.step = step
|
||||
|
||||
def __eq__(self, other):
|
||||
return type(self) == type(other) and self.from_value == other.from_value and self.to_value == other.to_value
|
||||
return (type(self) == type(other)
|
||||
and self.from_value == other.from_value
|
||||
and self.to_value == other.to_value
|
||||
and self.step == other.step)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
content_string = rep_join([self.from_value, self.to_value])
|
||||
return f"RangeArray([{content_string}])"
|
||||
parts = [self.from_value, self.to_value]
|
||||
if self.step is not None:
|
||||
parts.append(self.step)
|
||||
return f"RangeArray([{rep_join(parts)}])"
|
||||
|
||||
def print(self):
|
||||
return f"[{self.from_value.print()} VSQVE {self.to_value.print()}]"
|
||||
base = f"[{self.from_value.print()} VSQVE {self.to_value.print()}"
|
||||
if self.step is not None:
|
||||
base += f" GRADV {self.step.print()}"
|
||||
return base + "]"
|
||||
|
||||
def _eval(self, vtable):
|
||||
vtable, from_val = self.from_value.eval(vtable)
|
||||
@@ -390,7 +399,25 @@ class DataRangeArray(Node):
|
||||
raise CentvrionError("Range bounds must be numbers")
|
||||
from_int = from_val.value() or 0
|
||||
to_int = to_val.value() or 0
|
||||
return vtable, ValList([ValInt(i) for i in range(from_int, to_int + 1)])
|
||||
if self.step is None:
|
||||
return vtable, ValList([ValInt(i) for i in range(from_int, to_int + 1)])
|
||||
vtable, step_val = self.step.eval(vtable)
|
||||
if not isinstance(step_val, ValInt):
|
||||
raise CentvrionError("Range step must be a number")
|
||||
step_int = step_val.value()
|
||||
if step_int == 0:
|
||||
raise CentvrionError("Range step cannot be zero")
|
||||
items = []
|
||||
i = from_int
|
||||
if step_int > 0:
|
||||
while i <= to_int:
|
||||
items.append(ValInt(i))
|
||||
i += step_int
|
||||
else:
|
||||
while i >= to_int:
|
||||
items.append(ValInt(i))
|
||||
i += step_int
|
||||
return vtable, ValList(items)
|
||||
|
||||
|
||||
class DataDict(Node):
|
||||
|
||||
@@ -166,10 +166,21 @@ def emit_expr(node, ctx):
|
||||
hi_lines, hi_var = emit_expr(node.to_value, ctx)
|
||||
tmp = ctx.fresh_tmp()
|
||||
i_var = ctx.fresh_tmp()
|
||||
cap = f"({hi_var}.ival >= {lo_var}.ival ? (int)({hi_var}.ival - {lo_var}.ival + 1) : 0)"
|
||||
lines = lo_lines + hi_lines + [
|
||||
f"CentValue {tmp} = cent_list_new({cap});",
|
||||
f"for (long {i_var} = {lo_var}.ival; {i_var} <= {hi_var}.ival; {i_var}++) {{",
|
||||
if node.step is None:
|
||||
cap = f"({hi_var}.ival >= {lo_var}.ival ? (int)({hi_var}.ival - {lo_var}.ival + 1) : 0)"
|
||||
lines = lo_lines + hi_lines + [
|
||||
f"CentValue {tmp} = cent_list_new({cap});",
|
||||
f"for (long {i_var} = {lo_var}.ival; {i_var} <= {hi_var}.ival; {i_var}++) {{",
|
||||
f" cent_list_push(&{tmp}, cent_int({i_var}));",
|
||||
"}",
|
||||
]
|
||||
return lines, tmp
|
||||
step_lines, step_var = emit_expr(node.step, ctx)
|
||||
lines = lo_lines + hi_lines + step_lines + [
|
||||
f'if ({step_var}.type != CENT_INT) cent_type_error("Range step must be a number");',
|
||||
f'if ({step_var}.ival == 0) cent_runtime_error("Range step cannot be zero");',
|
||||
f"CentValue {tmp} = cent_list_new(0);",
|
||||
f"for (long {i_var} = {lo_var}.ival; ({step_var}.ival > 0 ? {i_var} <= {hi_var}.ival : {i_var} >= {hi_var}.ival); {i_var} += {step_var}.ival) {{",
|
||||
f" cent_list_push(&{tmp}, cent_int({i_var}));",
|
||||
"}",
|
||||
]
|
||||
|
||||
@@ -21,6 +21,7 @@ keyword_tokens = [("KEYWORD_"+i, i) for i in [
|
||||
"FAC",
|
||||
"FALSITAS",
|
||||
"FVNCTIO",
|
||||
"GRADV",
|
||||
"HAVD_MINVS",
|
||||
"HAVD_PLVS",
|
||||
"INVOCA",
|
||||
|
||||
@@ -276,6 +276,11 @@ class Parser():
|
||||
range_array = ast_nodes.DataRangeArray(tokens[3], tokens[5])
|
||||
return ast_nodes.PerStatement(range_array, tokens[1], tokens[8])
|
||||
|
||||
@self.pg.production('donicum_statement : KEYWORD_DONICVM id KEYWORD_VT expression KEYWORD_VSQVE expression KEYWORD_GRADV expression KEYWORD_FAC SYMBOL_LCURL statements SYMBOL_RCURL')
|
||||
def donicum_step(tokens):
|
||||
range_array = ast_nodes.DataRangeArray(tokens[3], tokens[5], tokens[7])
|
||||
return ast_nodes.PerStatement(range_array, tokens[1], tokens[10])
|
||||
|
||||
# expressions
|
||||
@self.pg.production('expressions : SYMBOL_LPARENS expression_list')
|
||||
def expressions(tokens):
|
||||
@@ -394,6 +399,10 @@ class Parser():
|
||||
def range_array(tokens):
|
||||
return ast_nodes.DataRangeArray(tokens[1], tokens[3])
|
||||
|
||||
@self.pg.production('expression : SYMBOL_LBRACKET expression KEYWORD_VSQVE expression KEYWORD_GRADV expression SYMBOL_RBRACKET')
|
||||
def range_array_step(tokens):
|
||||
return ast_nodes.DataRangeArray(tokens[1], tokens[3], tokens[5])
|
||||
|
||||
@self.pg.production('expression : expression SYMBOL_LBRACKET expression SYMBOL_RBRACKET', precedence='INDEX')
|
||||
def array_index(tokens):
|
||||
return ast_nodes.ArrayIndex(tokens[0], tokens[2])
|
||||
|
||||
Reference in New Issue
Block a user