419 lines
19 KiB
Python
419 lines
19 KiB
Python
from tests._helpers import (
|
|
unittest, parameterized, Fraction, time,
|
|
run_test, run_compiler_error_test,
|
|
ArrayIndex, ArraySlice, Bool, BinOp, BuiltIn, DataArray, DataDict, DataRangeArray,
|
|
Defini, Continva, Designa, DesignaDestructure, DesignaIndex, DumStatement,
|
|
Erumpe, ExpressionStatement, Fvnctio, ID, InterpolatedString, Invoca,
|
|
ModuleCall, Nullus, Numeral, PerStatement, Program, Redi, SiStatement,
|
|
String, TemptaStatement, UnaryMinus, UnaryNot, Fractio, frac_to_fraction,
|
|
fraction_to_frac, num_to_int, int_to_num, make_string,
|
|
ValInt, ValStr, ValBool, ValList, ValDict, ValNul, ValFunc, ValFrac,
|
|
CentvrionError, _RUNTIME_C, _cent_rng,
|
|
Lexer, Parser, compile_program,
|
|
os, subprocess, tempfile, StringIO, patch,
|
|
)
|
|
|
|
# --- Control flow ---
|
|
|
|
control_tests = [
|
|
# SI without ALIVD — true branch
|
|
("SI VERITAS TVNC { DESIGNA r VT I }\nr",
|
|
Program([], [SiStatement(Bool(True), [Designa(ID("r"), Numeral("I"))], None), ExpressionStatement(ID("r"))]),
|
|
ValInt(1)),
|
|
# SI without ALIVD — false branch
|
|
("SI FALSITAS TVNC { DESIGNA r VT I }",
|
|
Program([], [SiStatement(Bool(False), [Designa(ID("r"), Numeral("I"))], None)]),
|
|
ValNul()),
|
|
# SI with ALIVD — true branch
|
|
("SI VERITAS TVNC { DESIGNA r VT I } ALIVD { DESIGNA r VT II }\nr",
|
|
Program([], [SiStatement(Bool(True), [Designa(ID("r"), Numeral("I"))], [Designa(ID("r"), Numeral("II"))]), ExpressionStatement(ID("r"))]),
|
|
ValInt(1)),
|
|
# SI with ALIVD — false branch
|
|
("SI FALSITAS TVNC { DESIGNA r VT I } ALIVD { DESIGNA r VT II }\nr",
|
|
Program([], [SiStatement(Bool(False), [Designa(ID("r"), Numeral("I"))], [Designa(ID("r"), Numeral("II"))]), ExpressionStatement(ID("r"))]),
|
|
ValInt(2)),
|
|
# SI with comparison — equal
|
|
("SI I EST I TVNC { DESIGNA r VT I } ALIVD { DESIGNA r VT II }\nr",
|
|
Program([], [SiStatement(BinOp(Numeral("I"), Numeral("I"), "KEYWORD_EST"), [Designa(ID("r"), Numeral("I"))], [Designa(ID("r"), Numeral("II"))]), ExpressionStatement(ID("r"))]),
|
|
ValInt(1)),
|
|
# SI with comparison — unequal
|
|
("SI I EST II TVNC { DESIGNA r VT I } ALIVD { DESIGNA r VT II }\nr",
|
|
Program([], [SiStatement(BinOp(Numeral("I"), Numeral("II"), "KEYWORD_EST"), [Designa(ID("r"), Numeral("I"))], [Designa(ID("r"), Numeral("II"))]), ExpressionStatement(ID("r"))]),
|
|
ValInt(2)),
|
|
# SI MINVS
|
|
("SI I MINVS II TVNC { DESIGNA r VT I } ALIVD { DESIGNA r VT II }\nr",
|
|
Program([], [SiStatement(BinOp(Numeral("I"), Numeral("II"), "KEYWORD_MINVS"), [Designa(ID("r"), Numeral("I"))], [Designa(ID("r"), Numeral("II"))]), ExpressionStatement(ID("r"))]),
|
|
ValInt(1)),
|
|
# SI PLVS
|
|
("SI II PLVS I TVNC { DESIGNA r VT I } ALIVD { DESIGNA r VT II }\nr",
|
|
Program([], [SiStatement(BinOp(Numeral("II"), Numeral("I"), "KEYWORD_PLVS"), [Designa(ID("r"), Numeral("I"))], [Designa(ID("r"), Numeral("II"))]), ExpressionStatement(ID("r"))]),
|
|
ValInt(1)),
|
|
# ALIVD SI chain
|
|
(
|
|
"SI I EST II TVNC { DESIGNA r VT I } ALIVD SI I EST I TVNC { DESIGNA r VT II } ALIVD { DESIGNA r VT III }\nr",
|
|
Program([], [
|
|
SiStatement(
|
|
BinOp(Numeral("I"), Numeral("II"), "KEYWORD_EST"),
|
|
[Designa(ID("r"), Numeral("I"))],
|
|
[SiStatement(
|
|
BinOp(Numeral("I"), Numeral("I"), "KEYWORD_EST"),
|
|
[Designa(ID("r"), Numeral("II"))],
|
|
[Designa(ID("r"), Numeral("III"))],
|
|
)],
|
|
),
|
|
ExpressionStatement(ID("r")),
|
|
]),
|
|
ValInt(2),
|
|
),
|
|
# DVM (while not): loops until condition is true
|
|
(
|
|
"DESIGNA x VT I\nDVM x EST III FAC {\nDESIGNA x VT x + I\n}\nx",
|
|
Program([], [
|
|
Designa(ID("x"), Numeral("I")),
|
|
DumStatement(BinOp(ID("x"), Numeral("III"), "KEYWORD_EST"), [Designa(ID("x"), BinOp(ID("x"), Numeral("I"), "SYMBOL_PLUS"))]),
|
|
ExpressionStatement(ID("x")),
|
|
]),
|
|
ValInt(3),
|
|
),
|
|
# DVM with ERVMPE — loop body prints (testing DIC + ERVMPE together)
|
|
("DESIGNA x VT I\nDVM FALSITAS FAC {\nDIC(x)\nERVMPE\n}",
|
|
Program([], [
|
|
Designa(ID("x"), Numeral("I")),
|
|
DumStatement(Bool(False), [ExpressionStatement(BuiltIn("DIC", [ID("x")])), Erumpe()]),
|
|
]),
|
|
ValStr("I"), "I\n"),
|
|
# AETERNVM is sugar for DVM FALSITAS — must produce the same AST.
|
|
("DESIGNA x VT I\nAETERNVM FAC {\nDIC(x)\nERVMPE\n}",
|
|
Program([], [
|
|
Designa(ID("x"), Numeral("I")),
|
|
DumStatement(Bool(False), [ExpressionStatement(BuiltIn("DIC", [ID("x")])), Erumpe()]),
|
|
]),
|
|
ValStr("I"), "I\n"),
|
|
# AETERNVM with counter + ERVMPE on condition
|
|
("DESIGNA x VT I\nAETERNVM FAC {\nSI x EST III TVNC { ERVMPE }\nDESIGNA x VT x + I\n}\nx",
|
|
Program([], [
|
|
Designa(ID("x"), Numeral("I")),
|
|
DumStatement(Bool(False), [
|
|
SiStatement(BinOp(ID("x"), Numeral("III"), "KEYWORD_EST"), [Erumpe()], None),
|
|
Designa(ID("x"), BinOp(ID("x"), Numeral("I"), "SYMBOL_PLUS")),
|
|
]),
|
|
ExpressionStatement(ID("x")),
|
|
]),
|
|
ValInt(3)),
|
|
# AETERNVM with CONTINVA — skip printing III; ERVMPE after V.
|
|
# Return value is ValNul because the iteration that triggers ERVMPE runs
|
|
# Designa first (resetting last_val); we test on output, which is the point.
|
|
("DESIGNA x VT NVLLVS\nAETERNVM FAC {\nDESIGNA x VT x + I\nSI x PLVS V TVNC { ERVMPE }\nSI x EST III TVNC { CONTINVA }\nDIC(x)\n}",
|
|
Program([], [
|
|
Designa(ID("x"), Nullus()),
|
|
DumStatement(Bool(False), [
|
|
Designa(ID("x"), BinOp(ID("x"), Numeral("I"), "SYMBOL_PLUS")),
|
|
SiStatement(BinOp(ID("x"), Numeral("V"), "KEYWORD_PLVS"), [Erumpe()], None),
|
|
SiStatement(BinOp(ID("x"), Numeral("III"), "KEYWORD_EST"), [Continva()], None),
|
|
ExpressionStatement(BuiltIn("DIC", [ID("x")])),
|
|
]),
|
|
]),
|
|
ValNul(), "I\nII\nIV\nV\n"),
|
|
# REDI inside AETERNVM (inside DEFINI) — exits both loop and function
|
|
(
|
|
"DEFINI f () VT {\nDESIGNA x VT I\nAETERNVM FAC {\nREDI (x)\n}\n}\nINVOCA f ()",
|
|
Program([], [
|
|
Defini(ID("f"), [], [
|
|
Designa(ID("x"), Numeral("I")),
|
|
DumStatement(Bool(False), [Redi([ID("x")])]),
|
|
]),
|
|
ExpressionStatement(Invoca(ID("f"), [])),
|
|
]),
|
|
ValInt(1),
|
|
),
|
|
# PER foreach
|
|
("PER i IN [I, II, III] FAC { DIC(i) }",
|
|
Program([], [PerStatement(DataArray([Numeral("I"), Numeral("II"), Numeral("III")]), ID("i"), [ExpressionStatement(BuiltIn("DIC", [ID("i")]))])]),
|
|
ValStr("III"), "I\nII\nIII\n"),
|
|
# DONICVM range loop
|
|
("DONICVM i VT I VSQVE V FAC { DIC(i) }",
|
|
Program([], [PerStatement(DataRangeArray(Numeral("I"), Numeral("V")), ID("i"), [ExpressionStatement(BuiltIn("DIC", [ID("i")]))])]),
|
|
ValStr("V"), "I\nII\nIII\nIV\nV\n"),
|
|
# PER destructuring
|
|
("PER a, b IN [[I, II], [III, IV]] FAC { DIC(a + b) }",
|
|
Program([], [PerStatement(
|
|
DataArray([DataArray([Numeral("I"), Numeral("II")]), DataArray([Numeral("III"), Numeral("IV")])]),
|
|
[ID("a"), ID("b")],
|
|
[ExpressionStatement(BuiltIn("DIC", [BinOp(ID("a"), ID("b"), "SYMBOL_PLUS")]))])]),
|
|
ValStr("VII"), "III\nVII\n"),
|
|
# PER destructuring: three variables
|
|
("PER a, b, c IN [[I, II, III]] FAC { DIC(a + b + c) }",
|
|
Program([], [PerStatement(
|
|
DataArray([DataArray([Numeral("I"), Numeral("II"), Numeral("III")])]),
|
|
[ID("a"), ID("b"), ID("c")],
|
|
[ExpressionStatement(BuiltIn("DIC", [BinOp(BinOp(ID("a"), ID("b"), "SYMBOL_PLUS"), ID("c"), "SYMBOL_PLUS")]))])]),
|
|
ValStr("VI"), "VI\n"),
|
|
]
|
|
|
|
class TestControl(unittest.TestCase):
|
|
@parameterized.expand(control_tests)
|
|
def test_control(self, source, nodes, value, output=""):
|
|
run_test(self, source, nodes, value, output)
|
|
|
|
# --- Loop edge cases ---
|
|
|
|
loop_edge_tests = [
|
|
# [III VSQVE III] = [3] — single iteration
|
|
("DONICVM i VT III VSQVE III FAC { DIC(i) }",
|
|
Program([], [PerStatement(DataRangeArray(Numeral("III"), Numeral("III")), ID("i"), [ExpressionStatement(BuiltIn("DIC", [ID("i")]))])]),
|
|
ValStr("III"), "III\n"),
|
|
# empty array — body never runs
|
|
("PER i IN [] FAC { DIC(i) }",
|
|
Program([], [PerStatement(DataArray([]), ID("i"), [ExpressionStatement(BuiltIn("DIC", [ID("i")]))])]),
|
|
ValNul(), ""),
|
|
# PER breaks on element 2 — last assigned i is 2
|
|
("PER i IN [I, II, III] FAC { SI i EST II TVNC { ERVMPE } }\ni",
|
|
Program([], [
|
|
PerStatement(
|
|
DataArray([Numeral("I"), Numeral("II"), Numeral("III")]),
|
|
ID("i"),
|
|
[SiStatement(BinOp(ID("i"), Numeral("II"), "KEYWORD_EST"), [Erumpe()], None)],
|
|
),
|
|
ExpressionStatement(ID("i")),
|
|
]),
|
|
ValInt(2), ""),
|
|
# nested DVM: inner always breaks; outer runs until btr==3
|
|
("DESIGNA btr VT I\nDVM btr EST III FAC {\nDVM FALSITAS FAC {\nERVMPE\n}\nDESIGNA btr VT btr + I\n}\nbtr",
|
|
Program([], [
|
|
Designa(ID("btr"), Numeral("I")),
|
|
DumStatement(
|
|
BinOp(ID("btr"), Numeral("III"), "KEYWORD_EST"),
|
|
[DumStatement(Bool(False), [Erumpe()]), Designa(ID("btr"), BinOp(ID("btr"), Numeral("I"), "SYMBOL_PLUS"))],
|
|
),
|
|
ExpressionStatement(ID("btr")),
|
|
]),
|
|
ValInt(3), ""),
|
|
# nested PER: inner always breaks on first element; outer completes both iterations
|
|
# cnt starts at 1, increments twice → 3
|
|
("DESIGNA cnt VT I\nPER i IN [I, II] FAC {\nPER k IN [I, II] FAC {\nERVMPE\n}\nDESIGNA cnt VT cnt + I\n}\ncnt",
|
|
Program([], [
|
|
Designa(ID("cnt"), Numeral("I")),
|
|
PerStatement(
|
|
DataArray([Numeral("I"), Numeral("II")]),
|
|
ID("i"),
|
|
[PerStatement(DataArray([Numeral("I"), Numeral("II")]), ID("k"), [Erumpe()]),
|
|
Designa(ID("cnt"), BinOp(ID("cnt"), Numeral("I"), "SYMBOL_PLUS"))],
|
|
),
|
|
ExpressionStatement(ID("cnt")),
|
|
]),
|
|
ValInt(3), ""),
|
|
# PER with CONTINVA: skip odd numbers, sum evens
|
|
# [I,II,III,IV] → skip I and III; cnt increments on II and IV → cnt = III
|
|
("DESIGNA cnt VT I\nPER i IN [I, II, III, IV] FAC {\nSI i EST I AVT i EST III TVNC { CONTINVA }\nDESIGNA cnt VT cnt + I\n}\ncnt",
|
|
Program([], [
|
|
Designa(ID("cnt"), Numeral("I")),
|
|
PerStatement(
|
|
DataArray([Numeral("I"), Numeral("II"), Numeral("III"), Numeral("IV")]),
|
|
ID("i"),
|
|
[SiStatement(BinOp(BinOp(ID("i"), Numeral("I"), "KEYWORD_EST"), BinOp(ID("i"), Numeral("III"), "KEYWORD_EST"), "KEYWORD_AVT"), [Continva()], None),
|
|
Designa(ID("cnt"), BinOp(ID("cnt"), Numeral("I"), "SYMBOL_PLUS"))],
|
|
),
|
|
ExpressionStatement(ID("cnt")),
|
|
]),
|
|
ValInt(3), ""),
|
|
# DVM with CONTINVA: skip body when x is II, increment regardless
|
|
# x goes 1→2→3; on x=2 we continue (no DIC); DIC fires for x=1 and x=3
|
|
("DESIGNA x VT I\nDVM x EST IV FAC {\nSI x EST II TVNC { DESIGNA x VT x + I\nCONTINVA }\nDIC(x)\nDESIGNA x VT x + I\n}\nx",
|
|
Program([], [
|
|
Designa(ID("x"), Numeral("I")),
|
|
DumStatement(
|
|
BinOp(ID("x"), Numeral("IV"), "KEYWORD_EST"),
|
|
[SiStatement(BinOp(ID("x"), Numeral("II"), "KEYWORD_EST"),
|
|
[Designa(ID("x"), BinOp(ID("x"), Numeral("I"), "SYMBOL_PLUS")), Continva()], None),
|
|
ExpressionStatement(BuiltIn("DIC", [ID("x")])),
|
|
Designa(ID("x"), BinOp(ID("x"), Numeral("I"), "SYMBOL_PLUS"))],
|
|
),
|
|
ExpressionStatement(ID("x")),
|
|
]),
|
|
ValInt(4), "I\nIII\n"),
|
|
# nested PER: CONTINVA in inner only skips rest of inner body; outer still increments
|
|
("DESIGNA cnt VT I\nPER i IN [I, II] FAC {\nPER k IN [I, II] FAC {\nCONTINVA\nDESIGNA cnt VT cnt + I\n}\nDESIGNA cnt VT cnt + I\n}\ncnt",
|
|
Program([], [
|
|
Designa(ID("cnt"), Numeral("I")),
|
|
PerStatement(
|
|
DataArray([Numeral("I"), Numeral("II")]),
|
|
ID("i"),
|
|
[PerStatement(DataArray([Numeral("I"), Numeral("II")]), ID("k"),
|
|
[Continva(), Designa(ID("cnt"), BinOp(ID("cnt"), Numeral("I"), "SYMBOL_PLUS"))]),
|
|
Designa(ID("cnt"), BinOp(ID("cnt"), Numeral("I"), "SYMBOL_PLUS"))],
|
|
),
|
|
ExpressionStatement(ID("cnt")),
|
|
]),
|
|
ValInt(3), ""),
|
|
# DONICVM with CONTINVA: skip value III, count remaining (I VSQVE IV = [1,2,3,4], skip 3 → 3 increments)
|
|
("DESIGNA cnt VT I\nDONICVM i VT I VSQVE IV FAC {\nSI i EST III TVNC { CONTINVA }\nDESIGNA cnt VT cnt + I\n}\ncnt",
|
|
Program([], [
|
|
Designa(ID("cnt"), Numeral("I")),
|
|
PerStatement(
|
|
DataRangeArray(Numeral("I"), Numeral("IV")),
|
|
ID("i"),
|
|
[SiStatement(BinOp(ID("i"), Numeral("III"), "KEYWORD_EST"), [Continva()], None),
|
|
Designa(ID("cnt"), BinOp(ID("cnt"), Numeral("I"), "SYMBOL_PLUS"))],
|
|
),
|
|
ExpressionStatement(ID("cnt")),
|
|
]),
|
|
ValInt(4)),
|
|
# DVM condition true from start — body never runs
|
|
("DESIGNA x VT I\nDVM VERITAS FAC {\nDESIGNA x VT x + I\n}\nx",
|
|
Program([], [
|
|
Designa(ID("x"), Numeral("I")),
|
|
DumStatement(Bool(True), [Designa(ID("x"), BinOp(ID("x"), Numeral("I"), "SYMBOL_PLUS"))]),
|
|
ExpressionStatement(ID("x")),
|
|
]),
|
|
ValInt(1), ""),
|
|
# two iterations: [I VSQVE II] = [1, 2]
|
|
("DONICVM i VT I VSQVE II FAC { DIC(i) }",
|
|
Program([], [PerStatement(DataRangeArray(Numeral("I"), Numeral("II")), ID("i"), [ExpressionStatement(BuiltIn("DIC", [ID("i")]))])]),
|
|
ValStr("II"), "I\nII\n"),
|
|
# single iteration: [I VSQVE I] = [1]
|
|
("DONICVM i VT I VSQVE I FAC { DIC(i) }",
|
|
Program([], [PerStatement(DataRangeArray(Numeral("I"), Numeral("I")), ID("i"), [ExpressionStatement(BuiltIn("DIC", [ID("i")]))])]),
|
|
ValStr("I"), "I\n"),
|
|
# empty range: [V VSQVE I] = []
|
|
("DESIGNA x VT NVLLVS\nDONICVM i VT V VSQVE I FAC { DESIGNA x VT x + i }\nx",
|
|
Program([], [Designa(ID("x"), Nullus()),
|
|
PerStatement(DataRangeArray(Numeral("V"), Numeral("I")), ID("i"),
|
|
[Designa(ID("x"), BinOp(ID("x"), ID("i"), "SYMBOL_PLUS"))]),
|
|
ExpressionStatement(ID("x"))]),
|
|
ValNul(), ""),
|
|
# PER destructuring with ERVMPE
|
|
("DESIGNA r VT I\nPER a, b IN [[I, II], [III, IV], [V, VI]] FAC {\nSI a EST III TVNC { ERVMPE }\nDESIGNA r VT r + a + b\n}\nr",
|
|
Program([], [
|
|
Designa(ID("r"), Numeral("I")),
|
|
PerStatement(
|
|
DataArray([DataArray([Numeral("I"), Numeral("II")]), DataArray([Numeral("III"), Numeral("IV")]), DataArray([Numeral("V"), Numeral("VI")])]),
|
|
[ID("a"), ID("b")],
|
|
[SiStatement(BinOp(ID("a"), Numeral("III"), "KEYWORD_EST"), [Erumpe()], None),
|
|
Designa(ID("r"), BinOp(BinOp(ID("r"), ID("a"), "SYMBOL_PLUS"), ID("b"), "SYMBOL_PLUS"))],
|
|
),
|
|
ExpressionStatement(ID("r")),
|
|
]),
|
|
ValInt(4)), # 1 + 1 + 2 = 4, breaks before [III, IV]
|
|
# PER destructuring with REDI
|
|
("DEFINI f () VT {\nPER a, b IN [[I, II], [III, IV]] FAC {\nSI a EST III TVNC { REDI (b) }\n}\n}\nINVOCA f ()",
|
|
Program([], [
|
|
Defini(ID("f"), [],
|
|
[PerStatement(
|
|
DataArray([DataArray([Numeral("I"), Numeral("II")]), DataArray([Numeral("III"), Numeral("IV")])]),
|
|
[ID("a"), ID("b")],
|
|
[SiStatement(BinOp(ID("a"), Numeral("III"), "KEYWORD_EST"), [Redi([ID("b")])], None)],
|
|
)]),
|
|
ExpressionStatement(Invoca(ID("f"), [])),
|
|
]),
|
|
ValInt(4)), # returns b=IV when a=III
|
|
# DONICVM GRADV II, endpoint hit exactly: [I, III, V]
|
|
("DONICVM i VT I VSQVE V GRADV II FAC { DIC(i) }",
|
|
Program([], [PerStatement(
|
|
DataRangeArray(Numeral("I"), Numeral("V"), Numeral("II")),
|
|
ID("i"),
|
|
[ExpressionStatement(BuiltIn("DIC", [ID("i")]))])]),
|
|
ValStr("V"), "I\nIII\nV\n"),
|
|
# DONICVM GRADV II, endpoint overshot: VI excluded, stops at V
|
|
("DONICVM i VT I VSQVE VI GRADV II FAC { DIC(i) }",
|
|
Program([], [PerStatement(
|
|
DataRangeArray(Numeral("I"), Numeral("VI"), Numeral("II")),
|
|
ID("i"),
|
|
[ExpressionStatement(BuiltIn("DIC", [ID("i")]))])]),
|
|
ValStr("V"), "I\nIII\nV\n"),
|
|
# DONICVM GRADV I is equivalent to default step
|
|
("DONICVM i VT I VSQVE III GRADV I FAC { DIC(i) }",
|
|
Program([], [PerStatement(
|
|
DataRangeArray(Numeral("I"), Numeral("III"), Numeral("I")),
|
|
ID("i"),
|
|
[ExpressionStatement(BuiltIn("DIC", [ID("i")]))])]),
|
|
ValStr("III"), "I\nII\nIII\n"),
|
|
# DONICVM descending by I
|
|
("CVM SVBNVLLA\nDONICVM i VT V VSQVE I GRADV - I FAC { DIC(i) }",
|
|
Program([ModuleCall("SVBNVLLA")], [PerStatement(
|
|
DataRangeArray(Numeral("V"), Numeral("I"), UnaryMinus(Numeral("I"))),
|
|
ID("i"),
|
|
[ExpressionStatement(BuiltIn("DIC", [ID("i")]))])]),
|
|
ValStr("I"), "V\nIV\nIII\nII\nI\n"),
|
|
# DONICVM descending by II, endpoint overshot
|
|
("CVM SVBNVLLA\nDONICVM i VT X VSQVE I GRADV - II FAC { DIC(i) }",
|
|
Program([ModuleCall("SVBNVLLA")], [PerStatement(
|
|
DataRangeArray(Numeral("X"), Numeral("I"), UnaryMinus(Numeral("II"))),
|
|
ID("i"),
|
|
[ExpressionStatement(BuiltIn("DIC", [ID("i")]))])]),
|
|
ValStr("II"), "X\nVIII\nVI\nIV\nII\n"),
|
|
# DONICVM with step bound to a variable
|
|
("DESIGNA s VT II\nDONICVM i VT I VSQVE V GRADV s FAC { DIC(i) }",
|
|
Program([], [
|
|
Designa(ID("s"), Numeral("II")),
|
|
PerStatement(
|
|
DataRangeArray(Numeral("I"), Numeral("V"), ID("s")),
|
|
ID("i"),
|
|
[ExpressionStatement(BuiltIn("DIC", [ID("i")]))])]),
|
|
ValStr("V"), "I\nIII\nV\n"),
|
|
# DONICVM from == to with nonzero step: single iteration
|
|
("DONICVM i VT III VSQVE III GRADV II FAC { DIC(i) }",
|
|
Program([], [PerStatement(
|
|
DataRangeArray(Numeral("III"), Numeral("III"), Numeral("II")),
|
|
ID("i"),
|
|
[ExpressionStatement(BuiltIn("DIC", [ID("i")]))])]),
|
|
ValStr("III"), "III\n"),
|
|
# DONICVM direction mismatch — negative step with ascending bounds: body never runs
|
|
("CVM SVBNVLLA\nDESIGNA x VT NVLLVS\nDONICVM i VT I VSQVE X GRADV - I FAC { DESIGNA x VT x + i }\nx",
|
|
Program([ModuleCall("SVBNVLLA")], [
|
|
Designa(ID("x"), Nullus()),
|
|
PerStatement(
|
|
DataRangeArray(Numeral("I"), Numeral("X"), UnaryMinus(Numeral("I"))),
|
|
ID("i"),
|
|
[Designa(ID("x"), BinOp(ID("x"), ID("i"), "SYMBOL_PLUS"))]),
|
|
ExpressionStatement(ID("x"))]),
|
|
ValNul(), ""),
|
|
# Range-array literal with GRADV used via PER
|
|
("PER i IN [I VSQVE V GRADV II] FAC { DIC(i) }",
|
|
Program([], [PerStatement(
|
|
DataRangeArray(Numeral("I"), Numeral("V"), Numeral("II")),
|
|
ID("i"),
|
|
[ExpressionStatement(BuiltIn("DIC", [ID("i")]))])]),
|
|
ValStr("V"), "I\nIII\nV\n"),
|
|
# DONICVM GRADV II with CONTINVA: skip value V, print the others
|
|
("DONICVM i VT I VSQVE IX GRADV II FAC {\nSI i EST V TVNC { CONTINVA }\nDIC(i)\n}",
|
|
Program([], [PerStatement(
|
|
DataRangeArray(Numeral("I"), Numeral("IX"), Numeral("II")),
|
|
ID("i"),
|
|
[SiStatement(BinOp(ID("i"), Numeral("V"), "KEYWORD_EST"), [Continva()], None),
|
|
ExpressionStatement(BuiltIn("DIC", [ID("i")]))])]),
|
|
ValStr("IX"), "I\nIII\nVII\nIX\n"),
|
|
# DONICVM GRADV II with ERVMPE: stop at V (last successful DIC was III)
|
|
("DONICVM i VT I VSQVE IX GRADV II FAC {\nSI i EST V TVNC { ERVMPE }\nDIC(i)\n}",
|
|
Program([], [PerStatement(
|
|
DataRangeArray(Numeral("I"), Numeral("IX"), Numeral("II")),
|
|
ID("i"),
|
|
[SiStatement(BinOp(ID("i"), Numeral("V"), "KEYWORD_EST"), [Erumpe()], None),
|
|
ExpressionStatement(BuiltIn("DIC", [ID("i")]))])]),
|
|
ValStr("III"), "I\nIII\n"),
|
|
]
|
|
|
|
class TestLoopEdge(unittest.TestCase):
|
|
@parameterized.expand(loop_edge_tests)
|
|
def test_loop_edge(self, source, nodes, value, output=""):
|
|
run_test(self, source, nodes, value, output)
|
|
|
|
# --- SI/DVM: boolean condition enforcement ---
|
|
|
|
dvm_bool_condition_tests = [
|
|
# DVM exits when condition becomes true (boolean comparison)
|
|
(
|
|
"DESIGNA x VT I\nDVM x PLVS III FAC {\nDESIGNA x VT x + I\n}\nx",
|
|
Program([], [
|
|
Designa(ID("x"), Numeral("I")),
|
|
DumStatement(BinOp(ID("x"), Numeral("III"), "KEYWORD_PLVS"), [Designa(ID("x"), BinOp(ID("x"), Numeral("I"), "SYMBOL_PLUS"))]),
|
|
ExpressionStatement(ID("x")),
|
|
]),
|
|
ValInt(4),
|
|
),
|
|
]
|
|
|
|
class TestDvmBoolCondition(unittest.TestCase):
|
|
@parameterized.expand(dvm_bool_condition_tests)
|
|
def test_dvm_bool_condition(self, source, nodes, value):
|
|
run_test(self, source, nodes, value)
|