224 lines
14 KiB
Python
224 lines
14 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,
|
|
)
|
|
|
|
# --- Comparison operators ---
|
|
|
|
comparison_tests = [
|
|
# EST on strings
|
|
('\"hello\" EST \"hello\"', Program([], [ExpressionStatement(BinOp(String("hello"), String("hello"), "KEYWORD_EST"))]), ValBool(True)),
|
|
('\"hello\" EST \"world\"', Program([], [ExpressionStatement(BinOp(String("hello"), String("world"), "KEYWORD_EST"))]), ValBool(False)),
|
|
# chain comparisons as conditions
|
|
("SI III PLVS II TVNC { DESIGNA r VT I }\nr",
|
|
Program([], [SiStatement(BinOp(Numeral("III"), Numeral("II"), "KEYWORD_PLVS"), [Designa(ID("r"), Numeral("I"))], None), ExpressionStatement(ID("r"))]),
|
|
ValInt(1)),
|
|
("SI II PLVS III TVNC { DESIGNA r VT I } ALIVD { DESIGNA r VT II }\nr",
|
|
Program([], [SiStatement(BinOp(Numeral("II"), Numeral("III"), "KEYWORD_PLVS"), [Designa(ID("r"), Numeral("I"))], [Designa(ID("r"), Numeral("II"))]), ExpressionStatement(ID("r"))]),
|
|
ValInt(2)),
|
|
# result of comparison is ValBool
|
|
("I EST I", Program([], [ExpressionStatement(BinOp(Numeral("I"), Numeral("I"), "KEYWORD_EST"))]), ValBool(True)),
|
|
("I EST II", Program([], [ExpressionStatement(BinOp(Numeral("I"), Numeral("II"), "KEYWORD_EST"))]), ValBool(False)),
|
|
("I MINVS II", Program([], [ExpressionStatement(BinOp(Numeral("I"), Numeral("II"), "KEYWORD_MINVS"))]), ValBool(True)),
|
|
("II MINVS I", Program([], [ExpressionStatement(BinOp(Numeral("II"), Numeral("I"), "KEYWORD_MINVS"))]), ValBool(False)),
|
|
("II PLVS I", Program([], [ExpressionStatement(BinOp(Numeral("II"), Numeral("I"), "KEYWORD_PLVS"))]), ValBool(True)),
|
|
("I PLVS II", Program([], [ExpressionStatement(BinOp(Numeral("I"), Numeral("II"), "KEYWORD_PLVS"))]), ValBool(False)),
|
|
# NVLLVS coerces to 0 in comparisons
|
|
("V PLVS NVLLVS", Program([], [ExpressionStatement(BinOp(Numeral("V"), Nullus(), "KEYWORD_PLVS"))]), ValBool(True)),
|
|
("NVLLVS MINVS V", Program([], [ExpressionStatement(BinOp(Nullus(), Numeral("V"), "KEYWORD_MINVS"))]), ValBool(True)),
|
|
# DISPAR (not-equal): mirrors EST semantics, negated
|
|
("I DISPAR II", Program([], [ExpressionStatement(BinOp(Numeral("I"), Numeral("II"), "KEYWORD_DISPAR"))]), ValBool(True)),
|
|
("I DISPAR I", Program([], [ExpressionStatement(BinOp(Numeral("I"), Numeral("I"), "KEYWORD_DISPAR"))]), ValBool(False)),
|
|
('"hello" DISPAR "hello"', Program([], [ExpressionStatement(BinOp(String("hello"), String("hello"), "KEYWORD_DISPAR"))]), ValBool(False)),
|
|
('"hello" DISPAR "world"', Program([], [ExpressionStatement(BinOp(String("hello"), String("world"), "KEYWORD_DISPAR"))]), ValBool(True)),
|
|
("VERITAS DISPAR FALSITAS", Program([], [ExpressionStatement(BinOp(Bool(True), Bool(False), "KEYWORD_DISPAR"))]), ValBool(True)),
|
|
("NVLLVS DISPAR NVLLVS", Program([], [ExpressionStatement(BinOp(Nullus(), Nullus(), "KEYWORD_DISPAR"))]), ValBool(False)),
|
|
# cross-type: an int and a string are never equal
|
|
('I DISPAR "I"', Program([], [ExpressionStatement(BinOp(Numeral("I"), String("I"), "KEYWORD_DISPAR"))]), ValBool(True)),
|
|
# integer 0 equals NVLLVS
|
|
("(I - I) EST NVLLVS", Program([], [ExpressionStatement(BinOp(BinOp(Numeral("I"), Numeral("I"), "SYMBOL_MINUS"), Nullus(), "KEYWORD_EST"))]), ValBool(True)),
|
|
("NVLLVS EST (I - I)", Program([], [ExpressionStatement(BinOp(Nullus(), BinOp(Numeral("I"), Numeral("I"), "SYMBOL_MINUS"), "KEYWORD_EST"))]), ValBool(True)),
|
|
("(I - I) DISPAR NVLLVS", Program([], [ExpressionStatement(BinOp(BinOp(Numeral("I"), Numeral("I"), "SYMBOL_MINUS"), Nullus(), "KEYWORD_DISPAR"))]), ValBool(False)),
|
|
("NVLLVS DISPAR (I - I)", Program([], [ExpressionStatement(BinOp(Nullus(), BinOp(Numeral("I"), Numeral("I"), "SYMBOL_MINUS"), "KEYWORD_DISPAR"))]), ValBool(False)),
|
|
# non-zero integer does not equal NVLLVS
|
|
("I EST NVLLVS", Program([], [ExpressionStatement(BinOp(Numeral("I"), Nullus(), "KEYWORD_EST"))]), ValBool(False)),
|
|
("NVLLVS DISPAR I", Program([], [ExpressionStatement(BinOp(Nullus(), Numeral("I"), "KEYWORD_DISPAR"))]), ValBool(True)),
|
|
# EST / DISPAR on arrays
|
|
("[I, II] EST [I, II]", Program([], [ExpressionStatement(BinOp(DataArray([Numeral("I"), Numeral("II")]), DataArray([Numeral("I"), Numeral("II")]), "KEYWORD_EST"))]), ValBool(True)),
|
|
("[I, II] EST [I, III]", Program([], [ExpressionStatement(BinOp(DataArray([Numeral("I"), Numeral("II")]), DataArray([Numeral("I"), Numeral("III")]), "KEYWORD_EST"))]), ValBool(False)),
|
|
("[I, II] EST [I, II, III]", Program([], [ExpressionStatement(BinOp(DataArray([Numeral("I"), Numeral("II")]), DataArray([Numeral("I"), Numeral("II"), Numeral("III")]), "KEYWORD_EST"))]), ValBool(False)),
|
|
("[] EST []", Program([], [ExpressionStatement(BinOp(DataArray([]), DataArray([]), "KEYWORD_EST"))]), ValBool(True)),
|
|
("[I, II] DISPAR [I, III]", Program([], [ExpressionStatement(BinOp(DataArray([Numeral("I"), Numeral("II")]), DataArray([Numeral("I"), Numeral("III")]), "KEYWORD_DISPAR"))]), ValBool(True)),
|
|
("[I, II] DISPAR [I, II]", Program([], [ExpressionStatement(BinOp(DataArray([Numeral("I"), Numeral("II")]), DataArray([Numeral("I"), Numeral("II")]), "KEYWORD_DISPAR"))]), ValBool(False)),
|
|
# HAVD_PLVS (<=) and HAVD_MINVS (>=)
|
|
("I HAVD_PLVS II", Program([], [ExpressionStatement(BinOp(Numeral("I"), Numeral("II"), "KEYWORD_HAVD_PLVS"))]), ValBool(True)),
|
|
("II HAVD_PLVS I", Program([], [ExpressionStatement(BinOp(Numeral("II"), Numeral("I"), "KEYWORD_HAVD_PLVS"))]), ValBool(False)),
|
|
# equality boundary — the only case that distinguishes <= from <
|
|
("II HAVD_PLVS II", Program([], [ExpressionStatement(BinOp(Numeral("II"), Numeral("II"), "KEYWORD_HAVD_PLVS"))]), ValBool(True)),
|
|
("II HAVD_MINVS I", Program([], [ExpressionStatement(BinOp(Numeral("II"), Numeral("I"), "KEYWORD_HAVD_MINVS"))]), ValBool(True)),
|
|
("I HAVD_MINVS II", Program([], [ExpressionStatement(BinOp(Numeral("I"), Numeral("II"), "KEYWORD_HAVD_MINVS"))]), ValBool(False)),
|
|
# equality boundary — the only case that distinguishes >= from >
|
|
("II HAVD_MINVS II",Program([], [ExpressionStatement(BinOp(Numeral("II"), Numeral("II"), "KEYWORD_HAVD_MINVS"))]), ValBool(True)),
|
|
# NVLLVS coerces to 0
|
|
("V HAVD_MINVS NVLLVS", Program([], [ExpressionStatement(BinOp(Numeral("V"), Nullus(), "KEYWORD_HAVD_MINVS"))]), ValBool(True)),
|
|
("NVLLVS HAVD_PLVS V", Program([], [ExpressionStatement(BinOp(Nullus(), Numeral("V"), "KEYWORD_HAVD_PLVS"))]), ValBool(True)),
|
|
("NVLLVS HAVD_PLVS NVLLVS", Program([], [ExpressionStatement(BinOp(Nullus(), Nullus(), "KEYWORD_HAVD_PLVS"))]), ValBool(True)),
|
|
# precedence: * binds tighter, so II*III HAVD_PLVS VI parses as (II*III) HAVD_PLVS VI = 6 <= 6 = True
|
|
("II * III HAVD_PLVS VI",
|
|
Program([], [ExpressionStatement(BinOp(BinOp(Numeral("II"), Numeral("III"), "SYMBOL_TIMES"), Numeral("VI"), "KEYWORD_HAVD_PLVS"))]),
|
|
ValBool(True)),
|
|
# control flow: SI ... HAVD_MINVS
|
|
("SI II HAVD_MINVS II TVNC { DESIGNA r VT I } ALIVD { DESIGNA r VT II }\nr",
|
|
Program([], [SiStatement(BinOp(Numeral("II"), Numeral("II"), "KEYWORD_HAVD_MINVS"), [Designa(ID("r"), Numeral("I"))], [Designa(ID("r"), Numeral("II"))]), ExpressionStatement(ID("r"))]),
|
|
ValInt(1)),
|
|
]
|
|
|
|
class TestComparisons(unittest.TestCase):
|
|
@parameterized.expand(comparison_tests)
|
|
def test_comparisons(self, source, nodes, value):
|
|
run_test(self, source, nodes, value)
|
|
|
|
# --- ET and AVT (boolean and/or) ---
|
|
|
|
et_avt_tests = [
|
|
("VERITAS ET VERITAS", Program([], [ExpressionStatement(BinOp(Bool(True), Bool(True), "KEYWORD_ET"))]), ValBool(True)),
|
|
("VERITAS ET FALSITAS", Program([], [ExpressionStatement(BinOp(Bool(True), Bool(False), "KEYWORD_ET"))]), ValBool(False)),
|
|
("FALSITAS ET VERITAS", Program([], [ExpressionStatement(BinOp(Bool(False), Bool(True), "KEYWORD_ET"))]), ValBool(False)),
|
|
("FALSITAS ET FALSITAS", Program([], [ExpressionStatement(BinOp(Bool(False), Bool(False), "KEYWORD_ET"))]), ValBool(False)),
|
|
("VERITAS AVT VERITAS", Program([], [ExpressionStatement(BinOp(Bool(True), Bool(True), "KEYWORD_AVT"))]), ValBool(True)),
|
|
("VERITAS AVT FALSITAS", Program([], [ExpressionStatement(BinOp(Bool(True), Bool(False), "KEYWORD_AVT"))]), ValBool(True)),
|
|
("FALSITAS AVT VERITAS", Program([], [ExpressionStatement(BinOp(Bool(False), Bool(True), "KEYWORD_AVT"))]), ValBool(True)),
|
|
("FALSITAS AVT FALSITAS", Program([], [ExpressionStatement(BinOp(Bool(False), Bool(False), "KEYWORD_AVT"))]), ValBool(False)),
|
|
# short-circuit behavior: combined with comparisons
|
|
("(I EST I) ET (II EST II)",
|
|
Program([], [ExpressionStatement(BinOp(BinOp(Numeral("I"), Numeral("I"), "KEYWORD_EST"), BinOp(Numeral("II"), Numeral("II"), "KEYWORD_EST"), "KEYWORD_ET"))]),
|
|
ValBool(True)),
|
|
("(I EST II) AVT (II EST II)",
|
|
Program([], [ExpressionStatement(BinOp(BinOp(Numeral("I"), Numeral("II"), "KEYWORD_EST"), BinOp(Numeral("II"), Numeral("II"), "KEYWORD_EST"), "KEYWORD_AVT"))]),
|
|
ValBool(True)),
|
|
# used as SI condition
|
|
("SI VERITAS ET VERITAS TVNC { DESIGNA r VT I } ALIVD { DESIGNA r VT II }\nr",
|
|
Program([], [SiStatement(BinOp(Bool(True), Bool(True), "KEYWORD_ET"), [Designa(ID("r"), Numeral("I"))], [Designa(ID("r"), Numeral("II"))]), ExpressionStatement(ID("r"))]),
|
|
ValInt(1)),
|
|
("SI FALSITAS AVT FALSITAS TVNC { DESIGNA r VT I } ALIVD { DESIGNA r VT II }\nr",
|
|
Program([], [SiStatement(BinOp(Bool(False), Bool(False), "KEYWORD_AVT"), [Designa(ID("r"), Numeral("I"))], [Designa(ID("r"), Numeral("II"))]), ExpressionStatement(ID("r"))]),
|
|
ValInt(2)),
|
|
# short-circuit: right side not evaluated when result is determined
|
|
("VERITAS AVT NVLLVS",
|
|
Program([], [ExpressionStatement(BinOp(Bool(True), Nullus(), "KEYWORD_AVT"))]),
|
|
ValBool(True)),
|
|
("FALSITAS ET NVLLVS",
|
|
Program([], [ExpressionStatement(BinOp(Bool(False), Nullus(), "KEYWORD_ET"))]),
|
|
ValBool(False)),
|
|
# short-circuit with side-effect-prone expressions
|
|
("DESIGNA x VT NVLLVS\nSI x EST NVLLVS AVT [I, II][x] EST I TVNC { DESIGNA r VT I } ALIVD { DESIGNA r VT II }\nr",
|
|
Program([], [
|
|
Designa(ID("x"), Nullus()),
|
|
SiStatement(
|
|
BinOp(BinOp(ID("x"), Nullus(), "KEYWORD_EST"), BinOp(ArrayIndex(DataArray([Numeral("I"), Numeral("II")]), ID("x")), Numeral("I"), "KEYWORD_EST"), "KEYWORD_AVT"),
|
|
[Designa(ID("r"), Numeral("I"))],
|
|
[Designa(ID("r"), Numeral("II"))]),
|
|
ExpressionStatement(ID("r"))]),
|
|
ValInt(1)),
|
|
("DESIGNA x VT NVLLVS\nSI x DISPAR NVLLVS ET [I, II][x] EST I TVNC { DESIGNA r VT I } ALIVD { DESIGNA r VT II }\nr",
|
|
Program([], [
|
|
Designa(ID("x"), Nullus()),
|
|
SiStatement(
|
|
BinOp(BinOp(ID("x"), Nullus(), "KEYWORD_DISPAR"), BinOp(ArrayIndex(DataArray([Numeral("I"), Numeral("II")]), ID("x")), Numeral("I"), "KEYWORD_EST"), "KEYWORD_ET"),
|
|
[Designa(ID("r"), Numeral("I"))],
|
|
[Designa(ID("r"), Numeral("II"))]),
|
|
ExpressionStatement(ID("r"))]),
|
|
ValInt(2)),
|
|
]
|
|
|
|
class TestEtAvt(unittest.TestCase):
|
|
@parameterized.expand(et_avt_tests)
|
|
def test_et_avt(self, source, nodes, value):
|
|
run_test(self, source, nodes, value)
|
|
|
|
# --- NON (boolean not) ---
|
|
|
|
non_tests = [
|
|
("NON VERITAS",
|
|
Program([], [ExpressionStatement(UnaryNot(Bool(True)))]),
|
|
ValBool(False)),
|
|
("NON FALSITAS",
|
|
Program([], [ExpressionStatement(UnaryNot(Bool(False)))]),
|
|
ValBool(True)),
|
|
("NON NON VERITAS",
|
|
Program([], [ExpressionStatement(UnaryNot(UnaryNot(Bool(True))))]),
|
|
ValBool(True)),
|
|
("DESIGNA b VT I EST II\nNON b",
|
|
Program([], [Designa(ID("b"), BinOp(Numeral("I"), Numeral("II"), "KEYWORD_EST")), ExpressionStatement(UnaryNot(ID("b")))]),
|
|
ValBool(True)),
|
|
("DESIGNA z VT I EST I\nNON z",
|
|
Program([], [Designa(ID("z"), BinOp(Numeral("I"), Numeral("I"), "KEYWORD_EST")), ExpressionStatement(UnaryNot(ID("z")))]),
|
|
ValBool(False)),
|
|
("NON VERITAS AVT FALSITAS",
|
|
Program([], [ExpressionStatement(BinOp(UnaryNot(Bool(True)), Bool(False), "KEYWORD_AVT"))]),
|
|
ValBool(False)),
|
|
("NON VERITAS EST FALSITAS",
|
|
Program([], [ExpressionStatement(BinOp(UnaryNot(Bool(True)), Bool(False), "KEYWORD_EST"))]),
|
|
ValBool(True)),
|
|
]
|
|
|
|
class TestNon(unittest.TestCase):
|
|
@parameterized.expand(non_tests)
|
|
def test_non(self, source, nodes, value):
|
|
run_test(self, source, nodes, value)
|
|
|
|
# --- Values: equality and truthiness ---
|
|
|
|
class TestValues(unittest.TestCase):
|
|
def test_valint_equality(self):
|
|
self.assertEqual(ValInt(3), ValInt(3))
|
|
self.assertNotEqual(ValInt(3), ValInt(4))
|
|
|
|
def test_valstr_equality(self):
|
|
self.assertEqual(ValStr("hi"), ValStr("hi"))
|
|
self.assertNotEqual(ValStr("hi"), ValStr("bye"))
|
|
|
|
def test_valbool_equality(self):
|
|
self.assertEqual(ValBool(True), ValBool(True))
|
|
self.assertNotEqual(ValBool(True), ValBool(False))
|
|
|
|
def test_valnul_equality(self):
|
|
self.assertEqual(ValNul(), ValNul())
|
|
|
|
def test_vallist_equality(self):
|
|
self.assertEqual(ValList([ValInt(1)]), ValList([ValInt(1)]))
|
|
self.assertNotEqual(ValList([ValInt(1)]), ValList([ValInt(2)]))
|
|
self.assertNotEqual(ValList([ValInt(1)]), ValList([]))
|
|
|
|
def test_valint_truthiness(self):
|
|
self.assertTrue(bool(ValInt(1)))
|
|
self.assertTrue(bool(ValInt(-1)))
|
|
self.assertFalse(bool(ValInt(0)))
|
|
|
|
def test_valstr_truthiness(self):
|
|
self.assertTrue(bool(ValStr("x")))
|
|
self.assertFalse(bool(ValStr("")))
|
|
|
|
def test_valbool_truthiness(self):
|
|
self.assertTrue(bool(ValBool(True)))
|
|
self.assertFalse(bool(ValBool(False)))
|
|
|
|
def test_vallist_truthiness(self):
|
|
self.assertTrue(bool(ValList([ValInt(1)])))
|
|
self.assertFalse(bool(ValList([])))
|
|
|
|
def test_cross_type_inequality(self):
|
|
self.assertNotEqual(ValInt(1), ValBool(True))
|
|
self.assertNotEqual(ValInt(0), ValNul())
|
|
self.assertNotEqual(ValStr(""), ValNul())
|