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, ) # --- Builtins --- builtin_tests = [ ("AVDI_NVMERVS()", Program([], [ExpressionStatement(BuiltIn("AVDI_NVMERVS", []))]), ValInt(3), "", ["III"]), ("AVDI_NVMERVS()", Program([], [ExpressionStatement(BuiltIn("AVDI_NVMERVS", []))]), ValInt(10), "", ["X"]), ("CVM FORS\nDESIGNA a VT [I, II, III]\nDIC(a[FORTVITVS_NVMERVS(I, LONGITVDO(a))])", Program([ModuleCall("FORS")], [Designa(ID("a"), DataArray([Numeral("I"), Numeral("II"), Numeral("III")])), ExpressionStatement(BuiltIn("DIC", [ArrayIndex(ID("a"), BuiltIn("FORTVITVS_NVMERVS", [Numeral("I"), BuiltIn("LONGITVDO", [ID("a")])]))]))]), ValStr("I"), "I\n"), ("AVDI()", Program([], [ExpressionStatement(BuiltIn("AVDI", []))]), ValStr("hello"), "", ["hello"]), ("LONGITVDO([I, II, III])", Program([], [ExpressionStatement(BuiltIn("LONGITVDO", [DataArray([Numeral("I"), Numeral("II"), Numeral("III")])]))]), ValInt(3)), ("LONGITVDO([])", Program([], [ExpressionStatement(BuiltIn("LONGITVDO", [DataArray([])]))]), ValInt(0)), ('LONGITVDO("salve")', Program([], [ExpressionStatement(BuiltIn("LONGITVDO", [String("salve")]))]), ValInt(5)), ('LONGITVDO("")', Program([], [ExpressionStatement(BuiltIn("LONGITVDO", [String("")]))]), ValInt(0)), ("CVM FORS\nDIC(FORTVITA_ELECTIO([I, II, III]))", Program([ModuleCall("FORS")], [ExpressionStatement(BuiltIn("DIC", [BuiltIn("FORTVITA_ELECTIO", [DataArray([Numeral("I"), Numeral("II"), Numeral("III")])])]))]), ValStr("I"), "I\n"), ("CVM FORS\nSEMEN(XLII)\nDIC(FORTVITVS_NVMERVS(I, C))", Program([ModuleCall("FORS")], [ExpressionStatement(BuiltIn("SEMEN", [Numeral("XLII")])), ExpressionStatement(BuiltIn("DIC", [BuiltIn("FORTVITVS_NVMERVS", [Numeral("I"), Numeral("C")])]))]), ValStr("XXXIII"), "XXXIII\n"), # DECIMATIO: seed 42, 10 elements → removes 1 (element III) ("CVM FORS\nSEMEN(XLII)\nDIC(DECIMATIO([I, II, III, IV, V, VI, VII, VIII, IX, X]))", Program([ModuleCall("FORS")], [ExpressionStatement(BuiltIn("SEMEN", [Numeral("XLII")])), ExpressionStatement(BuiltIn("DIC", [BuiltIn("DECIMATIO", [DataArray([Numeral("I"), Numeral("II"), Numeral("III"), Numeral("IV"), Numeral("V"), Numeral("VI"), Numeral("VII"), Numeral("VIII"), Numeral("IX"), Numeral("X")])])]))]), ValStr("[I II IV V VI VII VIII IX X]"), "[I II IV V VI VII VIII IX X]\n"), # DECIMATIO: seed 1, 3 elements → 3//10=0, nothing removed ("CVM FORS\nSEMEN(I)\nDIC(DECIMATIO([I, II, III]))", Program([ModuleCall("FORS")], [ExpressionStatement(BuiltIn("SEMEN", [Numeral("I")])), ExpressionStatement(BuiltIn("DIC", [BuiltIn("DECIMATIO", [DataArray([Numeral("I"), Numeral("II"), Numeral("III")])])]))]), ValStr("[I II III]"), "[I II III]\n"), # DECIMATIO: empty array → empty array ("CVM FORS\nDIC(DECIMATIO([]))", Program([ModuleCall("FORS")], [ExpressionStatement(BuiltIn("DIC", [BuiltIn("DECIMATIO", [DataArray([])])]))]), ValStr("[]"), "[]\n"), # DECIMATIO: seed 42, 20 elements → removes 2 (elements XIII and XII) ("CVM FORS\nSEMEN(XLII)\nDIC(DECIMATIO([I, II, III, IV, V, VI, VII, VIII, IX, X, XI, XII, XIII, XIV, XV, XVI, XVII, XVIII, XIX, XX]))", Program([ModuleCall("FORS")], [ExpressionStatement(BuiltIn("SEMEN", [Numeral("XLII")])), ExpressionStatement(BuiltIn("DIC", [BuiltIn("DECIMATIO", [DataArray([Numeral("I"), Numeral("II"), Numeral("III"), Numeral("IV"), Numeral("V"), Numeral("VI"), Numeral("VII"), Numeral("VIII"), Numeral("IX"), Numeral("X"), Numeral("XI"), Numeral("XII"), Numeral("XIII"), Numeral("XIV"), Numeral("XV"), Numeral("XVI"), Numeral("XVII"), Numeral("XVIII"), Numeral("XIX"), Numeral("XX")])])]))]), ValStr("[I II III IV V VI VII VIII IX X XI XIV XV XVI XVII XVIII XIX XX]"), "[I II III IV V VI VII VIII IX X XI XIV XV XVI XVII XVIII XIX XX]\n"), # SENATVS: majority true → VERITAS ("SENATVS(VERITAS, VERITAS, FALSITAS)", Program([], [ExpressionStatement(BuiltIn("SENATVS", [Bool(True), Bool(True), Bool(False)]))]), ValBool(True)), # SENATVS: majority false → FALSITAS ("SENATVS(FALSITAS, FALSITAS, VERITAS)", Program([], [ExpressionStatement(BuiltIn("SENATVS", [Bool(False), Bool(False), Bool(True)]))]), ValBool(False)), # SENATVS: tie → FALSITAS ("SENATVS(VERITAS, FALSITAS)", Program([], [ExpressionStatement(BuiltIn("SENATVS", [Bool(True), Bool(False)]))]), ValBool(False)), # SENATVS: 4-arg tie → FALSITAS ("SENATVS(VERITAS, VERITAS, FALSITAS, FALSITAS)", Program([], [ExpressionStatement(BuiltIn("SENATVS", [Bool(True), Bool(True), Bool(False), Bool(False)]))]), ValBool(False)), # SENATVS: single true → VERITAS ("SENATVS(VERITAS)", Program([], [ExpressionStatement(BuiltIn("SENATVS", [Bool(True)]))]), ValBool(True)), # SENATVS: single false → FALSITAS ("SENATVS(FALSITAS)", Program([], [ExpressionStatement(BuiltIn("SENATVS", [Bool(False)]))]), ValBool(False)), # SENATVS: empty → FALSITAS (vacuous) ("SENATVS()", Program([], [ExpressionStatement(BuiltIn("SENATVS", []))]), ValBool(False)), # SENATVS: all true �� VERITAS ("SENATVS(VERITAS, VERITAS, VERITAS, VERITAS, VERITAS)", Program([], [ExpressionStatement(BuiltIn("SENATVS", [Bool(True), Bool(True), Bool(True), Bool(True), Bool(True)]))]), ValBool(True)), # SENATVS: array input, majority true → VERITAS ("SENATVS([VERITAS, VERITAS, FALSITAS])", Program([], [ExpressionStatement(BuiltIn("SENATVS", [DataArray([Bool(True), Bool(True), Bool(False)])]))]), ValBool(True)), # SENATVS: array input, majority false → FALSITAS ("SENATVS([FALSITAS, FALSITAS, VERITAS])", Program([], [ExpressionStatement(BuiltIn("SENATVS", [DataArray([Bool(False), Bool(False), Bool(True)])]))]), ValBool(False)), # SENATVS: array input, empty → FALSITAS ("SENATVS([])", Program([], [ExpressionStatement(BuiltIn("SENATVS", [DataArray([])]))]), ValBool(False)), # ORDINA: sort integers ("ORDINA([III, I, II])", Program([], [ExpressionStatement(BuiltIn("ORDINA", [DataArray([Numeral("III"), Numeral("I"), Numeral("II")])]))]), ValList([ValInt(1), ValInt(2), ValInt(3)])), # ORDINA: sort strings ('ORDINA(["c", "a", "b"])', Program([], [ExpressionStatement(BuiltIn("ORDINA", [DataArray([String("c"), String("a"), String("b")])]))]), ValList([ValStr("a"), ValStr("b"), ValStr("c")])), # ORDINA: empty list ("ORDINA([])", Program([], [ExpressionStatement(BuiltIn("ORDINA", [DataArray([])]))]), ValList([])), # ORDINA: single element ("ORDINA([V])", Program([], [ExpressionStatement(BuiltIn("ORDINA", [DataArray([Numeral("V")])]))]), ValList([ValInt(5)])), # ORDINA: already sorted ("ORDINA([I, II, III])", Program([], [ExpressionStatement(BuiltIn("ORDINA", [DataArray([Numeral("I"), Numeral("II"), Numeral("III")])]))]), ValList([ValInt(1), ValInt(2), ValInt(3)])), # ORDINA: duplicates ("ORDINA([II, I, II])", Program([], [ExpressionStatement(BuiltIn("ORDINA", [DataArray([Numeral("II"), Numeral("I"), Numeral("II")])]))]), ValList([ValInt(1), ValInt(2), ValInt(2)])), # ORDINA: negative numbers ("CVM SVBNVLLA\nORDINA([-II, III, -I])", Program([ModuleCall("SVBNVLLA")], [ExpressionStatement(BuiltIn("ORDINA", [DataArray([UnaryMinus(Numeral("II")), Numeral("III"), UnaryMinus(Numeral("I"))])]))]), ValList([ValInt(-2), ValInt(-1), ValInt(3)])), # ORDINA: fractions only ("CVM FRACTIO\nORDINA([IIIS, S, IIS])", Program([ModuleCall("FRACTIO")], [ExpressionStatement(BuiltIn("ORDINA", [DataArray([Fractio("IIIS"), Fractio("S"), Fractio("IIS")])]))]), ValList([ValFrac(Fraction(1, 2)), ValFrac(Fraction(5, 2)), ValFrac(Fraction(7, 2))])), # ORDINA: mixed integers and fractions ("CVM FRACTIO\nORDINA([III, S, II])", Program([ModuleCall("FRACTIO")], [ExpressionStatement(BuiltIn("ORDINA", [DataArray([Numeral("III"), Fractio("S"), Numeral("II")])]))]), ValList([ValFrac(Fraction(1, 2)), ValInt(2), ValInt(3)])), # ORDINA: array passed via variable ("DESIGNA x VT [III, I, II]\nORDINA(x)", Program([], [Designa(ID("x"), DataArray([Numeral("III"), Numeral("I"), Numeral("II")])), ExpressionStatement(BuiltIn("ORDINA", [ID("x")]))]), ValList([ValInt(1), ValInt(2), ValInt(3)])), # ORDINA: descending sort with named comparator ("DEFINI gt (a, b) VT { REDI (a PLVS b) }\nORDINA([II, V, I, III], gt)", Program([], [Defini(ID("gt"), [ID("a"), ID("b")], [Redi([BinOp(ID("a"), ID("b"), "KEYWORD_PLVS")])]), ExpressionStatement(BuiltIn("ORDINA", [DataArray([Numeral("II"), Numeral("V"), Numeral("I"), Numeral("III")]), ID("gt")]))]), ValList([ValInt(5), ValInt(3), ValInt(2), ValInt(1)])), # ORDINA: ascending sort with inline FVNCTIO comparator ("ORDINA([V, I, III], FVNCTIO (a, b) VT { REDI (a MINVS b) })", Program([], [ExpressionStatement(BuiltIn("ORDINA", [DataArray([Numeral("V"), Numeral("I"), Numeral("III")]), Fvnctio([ID("a"), ID("b")], [Redi([BinOp(ID("a"), ID("b"), "KEYWORD_MINVS")])])]))]), ValList([ValInt(1), ValInt(3), ValInt(5)])), # ORDINA: empty list with comparator ("ORDINA([], FVNCTIO (a, b) VT { REDI (VERITAS) })", Program([], [ExpressionStatement(BuiltIn("ORDINA", [DataArray([]), Fvnctio([ID("a"), ID("b")], [Redi([Bool(True)])])]))]), ValList([])), # ORDINA: single element with comparator ("ORDINA([VII], FVNCTIO (a, b) VT { REDI (VERITAS) })", Program([], [ExpressionStatement(BuiltIn("ORDINA", [DataArray([Numeral("VII")]), Fvnctio([ID("a"), ID("b")], [Redi([Bool(True)])])]))]), ValList([ValInt(7)])), # ORDINA: comparator sorting two-element subarrays by first element ("ORDINA([[II, I], [I, II]], FVNCTIO (a, b) VT { REDI (a[I] PLVS b[I]) })", Program([], [ExpressionStatement(BuiltIn("ORDINA", [DataArray([DataArray([Numeral("II"), Numeral("I")]), DataArray([Numeral("I"), Numeral("II")])]), Fvnctio([ID("a"), ID("b")], [Redi([BinOp(ArrayIndex(ID("a"), Numeral("I")), ArrayIndex(ID("b"), Numeral("I")), "KEYWORD_PLVS")])])]))]), ValList([ValList([ValInt(2), ValInt(1)]), ValList([ValInt(1), ValInt(2)])])), # MVTA: empty array → empty array ("MVTA([], FVNCTIO (x) VT { REDI (x + x) })", Program([], [ExpressionStatement(BuiltIn("MVTA", [DataArray([]), Fvnctio([ID("x")], [Redi([BinOp(ID("x"), ID("x"), "SYMBOL_PLUS")])])]))]), ValList([])), # MVTA: single element doubled ("MVTA([V], FVNCTIO (x) VT { REDI (x + x) })", Program([], [ExpressionStatement(BuiltIn("MVTA", [DataArray([Numeral("V")]), Fvnctio([ID("x")], [Redi([BinOp(ID("x"), ID("x"), "SYMBOL_PLUS")])])]))]), ValList([ValInt(10)])), # MVTA: multiple elements with named function ("DEFINI dbl (x) VT { REDI (x + x) }\nMVTA([I, II, III], dbl)", Program([], [Defini(ID("dbl"), [ID("x")], [Redi([BinOp(ID("x"), ID("x"), "SYMBOL_PLUS")])]), ExpressionStatement(BuiltIn("MVTA", [DataArray([Numeral("I"), Numeral("II"), Numeral("III")]), ID("dbl")]))]), ValList([ValInt(2), ValInt(4), ValInt(6)])), # MVTA: inline FVNCTIO squaring ("MVTA([I, II, III], FVNCTIO (x) VT { REDI (x * x) })", Program([], [ExpressionStatement(BuiltIn("MVTA", [DataArray([Numeral("I"), Numeral("II"), Numeral("III")]), Fvnctio([ID("x")], [Redi([BinOp(ID("x"), ID("x"), "SYMBOL_TIMES")])])]))]), ValList([ValInt(1), ValInt(4), ValInt(9)])), # MVTA: print form to confirm output rendering ("DIC(MVTA([I, II, III], FVNCTIO (x) VT { REDI (x + x) }))", Program([], [ExpressionStatement(BuiltIn("DIC", [BuiltIn("MVTA", [DataArray([Numeral("I"), Numeral("II"), Numeral("III")]), Fvnctio([ID("x")], [Redi([BinOp(ID("x"), ID("x"), "SYMBOL_PLUS")])])])]))]), ValStr("[II IV VI]"), "[II IV VI]\n"), # MVTA: array passed via variable ("DESIGNA xs VT [I, II, III]\nDIC(MVTA(xs, FVNCTIO (x) VT { REDI (x + I) }))", Program([], [Designa(ID("xs"), DataArray([Numeral("I"), Numeral("II"), Numeral("III")])), ExpressionStatement(BuiltIn("DIC", [BuiltIn("MVTA", [ID("xs"), Fvnctio([ID("x")], [Redi([BinOp(ID("x"), Numeral("I"), "SYMBOL_PLUS")])])])]))]), ValStr("[II III IV]"), "[II III IV]\n"), # MVTA: callback may return a different type than input ('DIC(MVTA([I, II, III], FVNCTIO (x) VT { REDI (LITTERA(x)) }))', Program([], [ExpressionStatement(BuiltIn("DIC", [BuiltIn("MVTA", [DataArray([Numeral("I"), Numeral("II"), Numeral("III")]), Fvnctio([ID("x")], [Redi([BuiltIn("LITTERA", [ID("x")])])])])]))]), ValStr("[I II III]"), "[I II III]\n"), # CRIBRA: empty array → empty array ("CRIBRA([], FVNCTIO (x) VT { REDI (VERITAS) })", Program([], [ExpressionStatement(BuiltIn("CRIBRA", [DataArray([]), Fvnctio([ID("x")], [Redi([Bool(True)])])]))]), ValList([])), # CRIBRA: predicate always true keeps everything ("CRIBRA([I, II, III], FVNCTIO (x) VT { REDI (VERITAS) })", Program([], [ExpressionStatement(BuiltIn("CRIBRA", [DataArray([Numeral("I"), Numeral("II"), Numeral("III")]), Fvnctio([ID("x")], [Redi([Bool(True)])])]))]), ValList([ValInt(1), ValInt(2), ValInt(3)])), # CRIBRA: predicate always false drops everything ("CRIBRA([I, II, III], FVNCTIO (x) VT { REDI (FALSITAS) })", Program([], [ExpressionStatement(BuiltIn("CRIBRA", [DataArray([Numeral("I"), Numeral("II"), Numeral("III")]), Fvnctio([ID("x")], [Redi([Bool(False)])])]))]), ValList([])), # CRIBRA: keep elements ≤ III ("CRIBRA([I, II, III, IV, V], FVNCTIO (x) VT { REDI (x HAVD_PLVS III) })", Program([], [ExpressionStatement(BuiltIn("CRIBRA", [DataArray([Numeral("I"), Numeral("II"), Numeral("III"), Numeral("IV"), Numeral("V")]), Fvnctio([ID("x")], [Redi([BinOp(ID("x"), Numeral("III"), "KEYWORD_HAVD_PLVS")])])]))]), ValList([ValInt(1), ValInt(2), ValInt(3)])), # CRIBRA: with named predicate ("DEFINI big (x) VT { REDI (x PLVS III) }\nCRIBRA([I, II, III, IV, V], big)", Program([], [Defini(ID("big"), [ID("x")], [Redi([BinOp(ID("x"), Numeral("III"), "KEYWORD_PLVS")])]), ExpressionStatement(BuiltIn("CRIBRA", [DataArray([Numeral("I"), Numeral("II"), Numeral("III"), Numeral("IV"), Numeral("V")]), ID("big")]))]), ValList([ValInt(4), ValInt(5)])), # CRIBRA: print form ("DIC(CRIBRA([I, II, III, IV, V], FVNCTIO (x) VT { REDI (x PLVS II) }))", Program([], [ExpressionStatement(BuiltIn("DIC", [BuiltIn("CRIBRA", [DataArray([Numeral("I"), Numeral("II"), Numeral("III"), Numeral("IV"), Numeral("V")]), Fvnctio([ID("x")], [Redi([BinOp(ID("x"), Numeral("II"), "KEYWORD_PLVS")])])])]))]), ValStr("[III IV V]"), "[III IV V]\n"), # CONFLA: empty array returns initial unchanged ("CONFLA([], V, FVNCTIO (a, b) VT { REDI (a + b) })", Program([], [ExpressionStatement(BuiltIn("CONFLA", [DataArray([]), Numeral("V"), Fvnctio([ID("a"), ID("b")], [Redi([BinOp(ID("a"), ID("b"), "SYMBOL_PLUS")])])]))]), ValInt(5)), # CONFLA: sum from initial I (so result = 1 + 1 + 2 + 3 = 7) ("CONFLA([I, II, III], I, FVNCTIO (a, b) VT { REDI (a + b) })", Program([], [ExpressionStatement(BuiltIn("CONFLA", [DataArray([Numeral("I"), Numeral("II"), Numeral("III")]), Numeral("I"), Fvnctio([ID("a"), ID("b")], [Redi([BinOp(ID("a"), ID("b"), "SYMBOL_PLUS")])])]))]), ValInt(7)), # CONFLA: product starting from I ("CONFLA([II, III, IV], I, FVNCTIO (a, b) VT { REDI (a * b) })", Program([], [ExpressionStatement(BuiltIn("CONFLA", [DataArray([Numeral("II"), Numeral("III"), Numeral("IV")]), Numeral("I"), Fvnctio([ID("a"), ID("b")], [Redi([BinOp(ID("a"), ID("b"), "SYMBOL_TIMES")])])]))]), ValInt(24)), # CONFLA: with named function ("DEFINI addi (a, b) VT { REDI (a + b) }\nCONFLA([I, II, III, IV], V, addi)", Program([], [Defini(ID("addi"), [ID("a"), ID("b")], [Redi([BinOp(ID("a"), ID("b"), "SYMBOL_PLUS")])]), ExpressionStatement(BuiltIn("CONFLA", [DataArray([Numeral("I"), Numeral("II"), Numeral("III"), Numeral("IV")]), Numeral("V"), ID("addi")]))]), ValInt(15)), # CONFLA: string concatenation ('CONFLA(["b", "c"], "a", FVNCTIO (a, b) VT { REDI (a & b) })', Program([], [ExpressionStatement(BuiltIn("CONFLA", [DataArray([String("b"), String("c")]), String("a"), Fvnctio([ID("a"), ID("b")], [Redi([BinOp(ID("a"), ID("b"), "SYMBOL_AMPERSAND")])])]))]), ValStr("abc")), # CONFLA: print sum ("DIC(CONFLA([I, II, III, IV], I, FVNCTIO (a, b) VT { REDI (a + b) }))", Program([], [ExpressionStatement(BuiltIn("DIC", [BuiltIn("CONFLA", [DataArray([Numeral("I"), Numeral("II"), Numeral("III"), Numeral("IV")]), Numeral("I"), Fvnctio([ID("a"), ID("b")], [Redi([BinOp(ID("a"), ID("b"), "SYMBOL_PLUS")])])])]))]), ValStr("XI"), "XI\n"), # ADDE: append to non-empty ("ADDE([I, II], III)", Program([], [ExpressionStatement(BuiltIn("ADDE", [DataArray([Numeral("I"), Numeral("II")]), Numeral("III")]))]), ValList([ValInt(1), ValInt(2), ValInt(3)])), # ADDE: append to empty ("ADDE([], V)", Program([], [ExpressionStatement(BuiltIn("ADDE", [DataArray([]), Numeral("V")]))]), ValList([ValInt(5)])), # ADDE: heterogeneous types are allowed ('ADDE([I, II], "x")', Program([], [ExpressionStatement(BuiltIn("ADDE", [DataArray([Numeral("I"), Numeral("II")]), String("x")]))]), ValList([ValInt(1), ValInt(2), ValStr("x")])), # ADDE: print form to confirm output rendering ("DIC(ADDE([I, II], III))", Program([], [ExpressionStatement(BuiltIn("DIC", [BuiltIn("ADDE", [DataArray([Numeral("I"), Numeral("II")]), Numeral("III")])]))]), ValStr("[I II III]"), "[I II III]\n"), # TOLLE: remove middle element ("TOLLE([I, II, III], II)", Program([], [ExpressionStatement(BuiltIn("TOLLE", [DataArray([Numeral("I"), Numeral("II"), Numeral("III")]), Numeral("II")]))]), ValList([ValInt(1), ValInt(3)])), # TOLLE: remove first element ("TOLLE([I, II, III], I)", Program([], [ExpressionStatement(BuiltIn("TOLLE", [DataArray([Numeral("I"), Numeral("II"), Numeral("III")]), Numeral("I")]))]), ValList([ValInt(2), ValInt(3)])), # TOLLE: remove last element ("TOLLE([I, II, III], III)", Program([], [ExpressionStatement(BuiltIn("TOLLE", [DataArray([Numeral("I"), Numeral("II"), Numeral("III")]), Numeral("III")]))]), ValList([ValInt(1), ValInt(2)])), # TOLLE: single-element array → empty ("TOLLE([V], I)", Program([], [ExpressionStatement(BuiltIn("TOLLE", [DataArray([Numeral("V")]), Numeral("I")]))]), ValList([])), # INSERE: insert into middle ("INSERE([I, III], II, II)", Program([], [ExpressionStatement(BuiltIn("INSERE", [DataArray([Numeral("I"), Numeral("III")]), Numeral("II"), Numeral("II")]))]), ValList([ValInt(1), ValInt(2), ValInt(3)])), # INSERE: insert at front ("INSERE([II, III], I, I)", Program([], [ExpressionStatement(BuiltIn("INSERE", [DataArray([Numeral("II"), Numeral("III")]), Numeral("I"), Numeral("I")]))]), ValList([ValInt(1), ValInt(2), ValInt(3)])), # INSERE: insert at len+1 (== append) ("INSERE([I, II], III, III)", Program([], [ExpressionStatement(BuiltIn("INSERE", [DataArray([Numeral("I"), Numeral("II")]), Numeral("III"), Numeral("III")]))]), ValList([ValInt(1), ValInt(2), ValInt(3)])), # INSERE: into empty array at idx 1 ("INSERE([], I, V)", Program([], [ExpressionStatement(BuiltIn("INSERE", [DataArray([]), Numeral("I"), Numeral("V")]))]), ValList([ValInt(5)])), # TYPVS: integer ("TYPVS(V)", Program([], [ExpressionStatement(BuiltIn("TYPVS", [Numeral("V")]))]), ValStr("NVMERVS")), # TYPVS: string ('TYPVS("hello")', Program([], [ExpressionStatement(BuiltIn("TYPVS", [String("hello")]))]), ValStr("LITTERA")), # TYPVS: boolean ("TYPVS(VERITAS)", Program([], [ExpressionStatement(BuiltIn("TYPVS", [Bool(True)]))]), ValStr("VERAX")), # TYPVS: list ("TYPVS([I, II])", Program([], [ExpressionStatement(BuiltIn("TYPVS", [DataArray([Numeral("I"), Numeral("II")])]))]), ValStr("CATALOGVS")), # TYPVS: empty list ("TYPVS([])", Program([], [ExpressionStatement(BuiltIn("TYPVS", [DataArray([])]))]), ValStr("CATALOGVS")), # TYPVS: fraction ("CVM FRACTIO\nTYPVS(S)", Program([ModuleCall("FRACTIO")], [ExpressionStatement(BuiltIn("TYPVS", [Fractio("S")]))]), ValStr("FRACTIO")), # TYPVS: dict ("TYPVS(TABVLA {})", Program([], [ExpressionStatement(BuiltIn("TYPVS", [DataDict([])]))]), ValStr("TABVLA")), # TYPVS: function ("TYPVS(FVNCTIO () VT { REDI(I) })", Program([], [ExpressionStatement(BuiltIn("TYPVS", [Fvnctio([], [Redi([Numeral("I")])])]))]), ValStr("FVNCTIO")), # TYPVS: null ("TYPVS(NVLLVS)", Program([], [ExpressionStatement(BuiltIn("TYPVS", [Nullus()]))]), ValStr("NVLLVS")), # LITTERA: integer → Roman numeral ("LITTERA(V)", Program([], [ExpressionStatement(BuiltIn("LITTERA", [Numeral("V")]))]), ValStr("V")), # LITTERA: larger integer ("LITTERA(MCMLXXXIV)", Program([], [ExpressionStatement(BuiltIn("LITTERA", [Numeral("MCMLXXXIV")]))]), ValStr("MCMLXXXIV")), # LITTERA: zero → NVLLVS ("LITTERA(I - I)", Program([], [ExpressionStatement(BuiltIn("LITTERA", [BinOp(Numeral("I"), Numeral("I"), "SYMBOL_MINUS")]))]), ValStr("NVLLVS")), # LITTERA: string passthrough ('LITTERA("salve")', Program([], [ExpressionStatement(BuiltIn("LITTERA", [String("salve")]))]), ValStr("salve")), # LITTERA: empty string ('LITTERA("")', Program([], [ExpressionStatement(BuiltIn("LITTERA", [String("")]))]), ValStr("")), # LITTERA: VERITAS ("LITTERA(VERITAS)", Program([], [ExpressionStatement(BuiltIn("LITTERA", [Bool(True)]))]), ValStr("VERITAS")), # LITTERA: FALSITAS ("LITTERA(FALSITAS)", Program([], [ExpressionStatement(BuiltIn("LITTERA", [Bool(False)]))]), ValStr("FALSITAS")), # LITTERA: NVLLVS ("LITTERA(NVLLVS)", Program([], [ExpressionStatement(BuiltIn("LITTERA", [Nullus()]))]), ValStr("NVLLVS")), # LITTERA: array of integers ("LITTERA([I, II, III])", Program([], [ExpressionStatement(BuiltIn("LITTERA", [DataArray([Numeral("I"), Numeral("II"), Numeral("III")])]))]), ValStr("[I II III]")), # LITTERA: empty array ("LITTERA([])", Program([], [ExpressionStatement(BuiltIn("LITTERA", [DataArray([])]))]), ValStr("[]")), # LITTERA: dict with string keys (make_string emits bare keys, not quoted — matches DIC's output) ('LITTERA(TABVLA {"a" VT I})', Program([], [ExpressionStatement(BuiltIn("LITTERA", [DataDict([(String("a"), Numeral("I"))])]))]), ValStr('{a VT I}')), # LITTERA: fraction (requires FRACTIO module) ("CVM FRACTIO\nLITTERA(S)", Program([ModuleCall("FRACTIO")], [ExpressionStatement(BuiltIn("LITTERA", [Fractio("S")]))]), ValStr("S")), # LITTERA: negative integer ("CVM SVBNVLLA\nLITTERA(-III)", Program([ModuleCall("SVBNVLLA")], [ExpressionStatement(BuiltIn("LITTERA", [UnaryMinus(Numeral("III"))]))]), ValStr("-III")), # LITTERA: round-trips through NVMERVS ('NVMERVS(LITTERA(VII))', Program([], [ExpressionStatement(BuiltIn("NVMERVS", [BuiltIn("LITTERA", [Numeral("VII")])]))]), ValInt(7)), # LITTERA: concatenated with a string via & ('LITTERA(V) & " est quinque"', Program([], [ExpressionStatement(BinOp(BuiltIn("LITTERA", [Numeral("V")]), String(" est quinque"), "SYMBOL_AMPERSAND"))]), ValStr("V est quinque")), # LITTERA: via variable ("DESIGNA x VT IX\nLITTERA(x)", Program([], [Designa(ID("x"), Numeral("IX")), ExpressionStatement(BuiltIn("LITTERA", [ID("x")]))]), ValStr("IX")), # QVAERE: basic literal match ('QVAERE("ab", "abcabc")', Program([], [ExpressionStatement(BuiltIn("QVAERE", [String("ab"), String("abcabc")]))]), ValList([ValStr("ab"), ValStr("ab")])), # QVAERE: no match → empty list ('QVAERE("xyz", "abc")', Program([], [ExpressionStatement(BuiltIn("QVAERE", [String("xyz"), String("abc")]))]), ValList([])), # QVAERE: regex character class ('QVAERE("[a-z]+", "abc123def")', Program([], [ExpressionStatement(BuiltIn("QVAERE", [String("[a-z]+"), String("abc123def")]))]), ValList([ValStr("abc"), ValStr("def")])), # QVAERE: empty text → empty list ('QVAERE("a", "")', Program([], [ExpressionStatement(BuiltIn("QVAERE", [String("a"), String("")]))]), ValList([])), # QVAERE: capture groups still return full match ('QVAERE("(a)(b)", "ab")', Program([], [ExpressionStatement(BuiltIn("QVAERE", [String("(a)(b)"), String("ab")]))]), ValList([ValStr("ab")])), # QVAERE: empty pattern matches between every character ('QVAERE("", "ab")', Program([], [ExpressionStatement(BuiltIn("QVAERE", [String(""), String("ab")]))]), ValList([ValStr(""), ValStr(""), ValStr("")])), # QVAERE: dot matches any character ('QVAERE(".", "ab")', Program([], [ExpressionStatement(BuiltIn("QVAERE", [String("."), String("ab")]))]), ValList([ValStr("a"), ValStr("b")])), # SVBSTITVE: basic literal replacement ('SVBSTITVE("a", "b", "aaa")', Program([], [ExpressionStatement(BuiltIn("SVBSTITVE", [String("a"), String("b"), String("aaa")]))]), ValStr("bbb")), # SVBSTITVE: regex character class ('SVBSTITVE("[0-9]+", "N", "abc123def456")', Program([], [ExpressionStatement(BuiltIn("SVBSTITVE", [String("[0-9]+"), String("N"), String("abc123def456")]))]), ValStr("abcNdefN")), # SVBSTITVE: no match → string unchanged ('SVBSTITVE("x", "y", "abc")', Program([], [ExpressionStatement(BuiltIn("SVBSTITVE", [String("x"), String("y"), String("abc")]))]), ValStr("abc")), # SVBSTITVE: empty replacement (deletion) ('SVBSTITVE("a", "", "banana")', Program([], [ExpressionStatement(BuiltIn("SVBSTITVE", [String("a"), String(""), String("banana")]))]), ValStr("bnn")), # SVBSTITVE: empty text → empty string ('SVBSTITVE("a", "b", "")', Program([], [ExpressionStatement(BuiltIn("SVBSTITVE", [String("a"), String("b"), String("")]))]), ValStr("")), # SVBSTITVE: dot matches any character ('SVBSTITVE(".", "x", "ab")', Program([], [ExpressionStatement(BuiltIn("SVBSTITVE", [String("."), String("x"), String("ab")]))]), ValStr("xx")), # SVBSTITVE: backreference swaps two groups (Roman numerals) ('SVBSTITVE("(a)(b)", "\\II\\I", "ab")', Program([], [ExpressionStatement(BuiltIn("SVBSTITVE", [String("(a)(b)"), String("\\II\\I"), String("ab")]))]), ValStr("ba")), # SVBSTITVE: backreference with unmatched group (ignored) ('SVBSTITVE("(a)(b)?", "\\I\\II", "a")', Program([], [ExpressionStatement(BuiltIn("SVBSTITVE", [String("(a)(b)?"), String("\\I\\II"), String("a")]))]), ValStr("a")), # SVBSTITVE: Roman numeral quantifier in pattern ("SVBSTITVE('a{III}', 'x', 'aaa')", Program([], [ExpressionStatement(BuiltIn("SVBSTITVE", [String("a{III}"), String("x"), String("aaa")]))]), ValStr("x")), # QVAERE: Roman numeral quantifier — exact repetition ("QVAERE('a{III}', 'aaaa')", Program([], [ExpressionStatement(BuiltIn("QVAERE", [String("a{III}"), String("aaaa")]))]), ValList([ValStr("aaa")])), # QVAERE: Roman numeral quantifier — range ("QVAERE('a{II,III}', 'aaaaaa')", Program([], [ExpressionStatement(BuiltIn("QVAERE", [String("a{II,III}"), String("aaaaaa")]))]), ValList([ValStr("aaa"), ValStr("aaa")])), # QVAERE: Roman numeral quantifier — at-least ("QVAERE('a{II,}', 'a aa aaa')", Program([], [ExpressionStatement(BuiltIn("QVAERE", [String("a{II,}"), String("a aa aaa")]))]), ValList([ValStr("aa"), ValStr("aaa")])), # QVAERE: pattern backreference — repeated character ("QVAERE('(.)\\I', 'aabcdd')", Program([], [ExpressionStatement(BuiltIn("QVAERE", [String("(.)\\I"), String("aabcdd")]))]), ValList([ValStr("aa"), ValStr("dd")])), # QVAERE: pattern backreference — repeated group ("QVAERE('(..)\\I', 'ababcc')", Program([], [ExpressionStatement(BuiltIn("QVAERE", [String("(..)\\I"), String("ababcc")]))]), ValList([ValStr("abab")])), # NVMERVS: basic conversion ('NVMERVS("XIV")', Program([], [ExpressionStatement(BuiltIn("NVMERVS", [String("XIV")]))]), ValInt(14)), # NVMERVS: simple single numeral ('NVMERVS("I")', Program([], [ExpressionStatement(BuiltIn("NVMERVS", [String("I")]))]), ValInt(1)), # NVMERVS: large numeral ('NVMERVS("MMMCMXCIX")', Program([], [ExpressionStatement(BuiltIn("NVMERVS", [String("MMMCMXCIX")]))]), ValInt(3999)), # NVMERVS: subtractive form ('NVMERVS("IX")', Program([], [ExpressionStatement(BuiltIn("NVMERVS", [String("IX")]))]), ValInt(9)), # SCINDE: basic split ('SCINDE("a,b,c", ",")', Program([], [ExpressionStatement(BuiltIn("SCINDE", [String("a,b,c"), String(",")]))]), ValList([ValStr("a"), ValStr("b"), ValStr("c")])), # SCINDE: no match (delimiter not found) ('SCINDE("abc", ",")', Program([], [ExpressionStatement(BuiltIn("SCINDE", [String("abc"), String(",")]))]), ValList([ValStr("abc")])), # SCINDE: empty string ('SCINDE("", ",")', Program([], [ExpressionStatement(BuiltIn("SCINDE", [String(""), String(",")]))]), ValList([ValStr("")])), # SCINDE: multi-char delimiter ('SCINDE("a::b::c", "::")', Program([], [ExpressionStatement(BuiltIn("SCINDE", [String("a::b::c"), String("::")]))]), ValList([ValStr("a"), ValStr("b"), ValStr("c")])), # SCINDE: delimiter at edges ('SCINDE(",a,", ",")', Program([], [ExpressionStatement(BuiltIn("SCINDE", [String(",a,"), String(",")]))]), ValList([ValStr(""), ValStr("a"), ValStr("")])), # SCINDE: empty delimiter (split into chars) ('SCINDE("abc", "")', Program([], [ExpressionStatement(BuiltIn("SCINDE", [String("abc"), String("")]))]), ValList([ValStr("a"), ValStr("b"), ValStr("c")])), # MAIVSCVLA: basic lowercase→uppercase ('MAIVSCVLA("hello")', Program([], [ExpressionStatement(BuiltIn("MAIVSCVLA", [String("hello")]))]), ValStr("HELLO")), # MAIVSCVLA: mixed case ('MAIVSCVLA("HeLLo")', Program([], [ExpressionStatement(BuiltIn("MAIVSCVLA", [String("HeLLo")]))]), ValStr("HELLO")), # MAIVSCVLA: already uppercase (idempotence) ('MAIVSCVLA("HELLO")', Program([], [ExpressionStatement(BuiltIn("MAIVSCVLA", [String("HELLO")]))]), ValStr("HELLO")), # MAIVSCVLA: empty string ('MAIVSCVLA("")', Program([], [ExpressionStatement(BuiltIn("MAIVSCVLA", [String("")]))]), ValStr("")), # MAIVSCVLA: Roman-numeral-shaped ASCII (case-only, not numeral-aware) ('MAIVSCVLA("xii")', Program([], [ExpressionStatement(BuiltIn("MAIVSCVLA", [String("xii")]))]), ValStr("XII")), # MAIVSCVLA: non-alphabetic chars unchanged ('MAIVSCVLA("a,b!1")', Program([], [ExpressionStatement(BuiltIn("MAIVSCVLA", [String("a,b!1")]))]), ValStr("A,B!1")), # MAIVSCVLA: via variable ('DESIGNA s VT "foo"\nDIC(MAIVSCVLA(s))', Program([], [Designa(ID("s"), String("foo")), ExpressionStatement(BuiltIn("DIC", [BuiltIn("MAIVSCVLA", [ID("s")])]))]), ValStr("FOO"), "FOO\n"), # MAIVSCVLA: concatenated with & ('MAIVSCVLA("hi") & "!"', Program([], [ExpressionStatement(BinOp(BuiltIn("MAIVSCVLA", [String("hi")]), String("!"), "SYMBOL_AMPERSAND"))]), ValStr("HI!")), # MINVSCVLA: basic uppercase→lowercase ('MINVSCVLA("HELLO")', Program([], [ExpressionStatement(BuiltIn("MINVSCVLA", [String("HELLO")]))]), ValStr("hello")), # MINVSCVLA: mixed case ('MINVSCVLA("HeLLo")', Program([], [ExpressionStatement(BuiltIn("MINVSCVLA", [String("HeLLo")]))]), ValStr("hello")), # MINVSCVLA: already lowercase (idempotence) ('MINVSCVLA("hello")', Program([], [ExpressionStatement(BuiltIn("MINVSCVLA", [String("hello")]))]), ValStr("hello")), # MINVSCVLA: empty string ('MINVSCVLA("")', Program([], [ExpressionStatement(BuiltIn("MINVSCVLA", [String("")]))]), ValStr("")), # MINVSCVLA: Roman-numeral-shaped ASCII (case-only, not numeral-aware) ('MINVSCVLA("XII")', Program([], [ExpressionStatement(BuiltIn("MINVSCVLA", [String("XII")]))]), ValStr("xii")), # MINVSCVLA: non-alphabetic chars unchanged ('MINVSCVLA("A,B!1")', Program([], [ExpressionStatement(BuiltIn("MINVSCVLA", [String("A,B!1")]))]), ValStr("a,b!1")), # MINVSCVLA round-trips MAIVSCVLA on lowercase input ('MINVSCVLA(MAIVSCVLA("hi"))', Program([], [ExpressionStatement(BuiltIn("MINVSCVLA", [BuiltIn("MAIVSCVLA", [String("hi")])]))]), ValStr("hi")), # NECTE: zip two integer arrays ("NECTE([I, II, III], [IV, V, VI])", Program([], [ExpressionStatement(BuiltIn("NECTE", [DataArray([Numeral("I"), Numeral("II"), Numeral("III")]), DataArray([Numeral("IV"), Numeral("V"), Numeral("VI")])]))]), ValList([ValList([ValInt(1), ValInt(4)]), ValList([ValInt(2), ValInt(5)]), ValList([ValInt(3), ValInt(6)])])), # NECTE: empty + empty ("NECTE([], [])", Program([], [ExpressionStatement(BuiltIn("NECTE", [DataArray([]), DataArray([])]))]), ValList([])), # NECTE: single element ("NECTE([I], [II])", Program([], [ExpressionStatement(BuiltIn("NECTE", [DataArray([Numeral("I")]), DataArray([Numeral("II")])]))]), ValList([ValList([ValInt(1), ValInt(2)])])), # NECTE: mixed types (numerals paired with strings) ('NECTE([I, II], ["a", "b"])', Program([], [ExpressionStatement(BuiltIn("NECTE", [DataArray([Numeral("I"), Numeral("II")]), DataArray([String("a"), String("b")])]))]), ValList([ValList([ValInt(1), ValStr("a")]), ValList([ValInt(2), ValStr("b")])])), # NECTE: print form ('DIC(NECTE([I, II], [III, IV]))', Program([], [ExpressionStatement(BuiltIn("DIC", [BuiltIn("NECTE", [DataArray([Numeral("I"), Numeral("II")]), DataArray([Numeral("III"), Numeral("IV")])])]))]), ValStr("[[I III] [II IV]]"), "[[I III] [II IV]]\n"), # NECTE: via variables ("DESIGNA a VT [I, II]\nDESIGNA b VT [III, IV]\nNECTE(a, b)", Program([], [Designa(ID("a"), DataArray([Numeral("I"), Numeral("II")])), Designa(ID("b"), DataArray([Numeral("III"), Numeral("IV")])), ExpressionStatement(BuiltIn("NECTE", [ID("a"), ID("b")]))]), ValList([ValList([ValInt(1), ValInt(3)]), ValList([ValInt(2), ValInt(4)])])), # IVNGE: string keys ('IVNGE(["a", "b"], [I, II])', Program([], [ExpressionStatement(BuiltIn("IVNGE", [DataArray([String("a"), String("b")]), DataArray([Numeral("I"), Numeral("II")])]))]), ValDict({"a": ValInt(1), "b": ValInt(2)})), # IVNGE: integer keys ('IVNGE([I, II], ["one", "two"])', Program([], [ExpressionStatement(BuiltIn("IVNGE", [DataArray([Numeral("I"), Numeral("II")]), DataArray([String("one"), String("two")])]))]), ValDict({1: ValStr("one"), 2: ValStr("two")})), # IVNGE: empty + empty ("IVNGE([], [])", Program([], [ExpressionStatement(BuiltIn("IVNGE", [DataArray([]), DataArray([])]))]), ValDict({})), # IVNGE: duplicate keys → last wins ('IVNGE(["a", "a"], [I, II])', Program([], [ExpressionStatement(BuiltIn("IVNGE", [DataArray([String("a"), String("a")]), DataArray([Numeral("I"), Numeral("II")])]))]), ValDict({"a": ValInt(2)})), # IVNGE: print form ('DIC(IVNGE(["a", "b"], [I, II]))', Program([], [ExpressionStatement(BuiltIn("DIC", [BuiltIn("IVNGE", [DataArray([String("a"), String("b")]), DataArray([Numeral("I"), Numeral("II")])])]))]), ValStr("{a VT I, b VT II}"), "{a VT I, b VT II}\n"), # IVNGE composes with CLAVES (round-trip keys) ('CLAVES(IVNGE(["a", "b"], [I, II]))', Program([], [ExpressionStatement(BuiltIn("CLAVES", [BuiltIn("IVNGE", [DataArray([String("a"), String("b")]), DataArray([Numeral("I"), Numeral("II")])])]))]), ValList([ValStr("a"), ValStr("b")])), ] class TestBuiltins(unittest.TestCase): @parameterized.expand(builtin_tests) def test_builtins(self, source, nodes, value, output="", input_lines=[]): run_test(self, source, nodes, value, output, input_lines)