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())