174 lines
6.2 KiB
Python
174 lines
6.2 KiB
Python
from tests._helpers import (
|
|
unittest, parameterized, Fraction,
|
|
run_test,
|
|
Bool, BuiltIn, DataArray, DataDict, Designa, ExpressionStatement, ID,
|
|
ModuleCall, Nullus, Numeral, Program, String,
|
|
ValInt, ValStr, ValBool, ValList, ValDict, ValNul, ValFrac,
|
|
)
|
|
|
|
|
|
def _scribe(arg, modules=("IASON",)):
|
|
return Program(
|
|
[ModuleCall(m) for m in modules],
|
|
[ExpressionStatement(BuiltIn("IASON_SCRIBE", [arg]))],
|
|
)
|
|
|
|
def _lege(arg, modules=("IASON",)):
|
|
return Program(
|
|
[ModuleCall(m) for m in modules],
|
|
[ExpressionStatement(BuiltIn("IASON_LEGE", [String(arg)]))],
|
|
)
|
|
|
|
def _src_lege(arg, extra_modules=()):
|
|
modules = ("IASON",) + tuple(extra_modules)
|
|
prefix = "\n".join(f"CVM {m}" for m in modules) + "\n"
|
|
return prefix + f"IASON_LEGE('{arg}')"
|
|
|
|
def _src_scribe(arg_text, extra_modules=()):
|
|
modules = ("IASON",) + tuple(extra_modules)
|
|
prefix = "\n".join(f"CVM {m}" for m in modules) + "\n"
|
|
return prefix + f"IASON_SCRIBE({arg_text})"
|
|
|
|
|
|
iason_tests = [
|
|
# ---- Parse: scalars ----
|
|
(_src_lege("null"), _lege("null"), ValNul()),
|
|
(_src_lege("true"), _lege("true"), ValBool(True)),
|
|
(_src_lege("false"), _lege("false"), ValBool(False)),
|
|
(_src_lege("42"), _lege("42"), ValInt(42)),
|
|
(_src_lege('"hello"'), _lege('"hello"'), ValStr("hello")),
|
|
|
|
# ---- Parse: empty containers ----
|
|
(_src_lege("[]"), _lege("[]"), ValList([])),
|
|
(_src_lege("{}"), _lege("{}"), ValDict({})),
|
|
|
|
# ---- Parse: array of mixed types ----
|
|
(_src_lege('[1, true, null, "x"]'),
|
|
_lege('[1, true, null, "x"]'),
|
|
ValList([ValInt(1), ValBool(True), ValNul(), ValStr("x")])),
|
|
|
|
# ---- Parse: nested ----
|
|
(_src_lege('{"a": [1, 2], "b": {"c": 3}}'),
|
|
_lege('{"a": [1, 2], "b": {"c": 3}}'),
|
|
ValDict({
|
|
"a": ValList([ValInt(1), ValInt(2)]),
|
|
"b": ValDict({"c": ValInt(3)}),
|
|
})),
|
|
|
|
# ---- Parse: numbers ----
|
|
(_src_lege("-7"), _lege("-7"), ValInt(-7)),
|
|
(_src_lege("0"), _lege("0"), ValInt(0)),
|
|
|
|
# ---- Parse: string escapes ----
|
|
# NB: single-quoted CENTVRION strings unescape \n / \" / \\ before the
|
|
# JSON parser sees them, so direct parse tests for those escapes would
|
|
# have ambiguous semantics. Serialize tests below cover the inverse, and
|
|
# this \u test exercises the JSON parser's escape path.
|
|
(_src_lege('"\\u00e9"'),
|
|
_lege('"\\u00e9"'),
|
|
ValStr("é")),
|
|
|
|
# ---- Parse: float without FRACTIO floors ----
|
|
(_src_lege("3.7"), _lege("3.7"), ValInt(3)),
|
|
(_src_lege("-2.5"), _lege("-2.5"), ValInt(-3)),
|
|
(_src_lege("1e2"), _lege("1e2"), ValInt(100)),
|
|
|
|
# ---- Parse: float with FRACTIO is exact ----
|
|
(_src_lege("0.5", extra_modules=("FRACTIO",)),
|
|
_lege("0.5", modules=("IASON", "FRACTIO")),
|
|
ValFrac(Fraction(1, 2))),
|
|
(_src_lege("0.1", extra_modules=("FRACTIO",)),
|
|
_lege("0.1", modules=("IASON", "FRACTIO")),
|
|
ValFrac(Fraction(1, 10))),
|
|
(_src_lege("-0.25", extra_modules=("FRACTIO",)),
|
|
_lege("-0.25", modules=("IASON", "FRACTIO")),
|
|
ValFrac(Fraction(-1, 4))),
|
|
(_src_lege("5", extra_modules=("FRACTIO",)),
|
|
_lege("5", modules=("IASON", "FRACTIO")),
|
|
ValInt(5)),
|
|
(_src_lege("3.0", extra_modules=("FRACTIO",)),
|
|
_lege("3.0", modules=("IASON", "FRACTIO")),
|
|
ValInt(3)),
|
|
|
|
# ---- Serialize: scalars ----
|
|
(_src_scribe("NVLLVS"), _scribe(Nullus()), ValStr("null")),
|
|
(_src_scribe("VERITAS"), _scribe(Bool(True)), ValStr("true")),
|
|
(_src_scribe("FALSITAS"), _scribe(Bool(False)), ValStr("false")),
|
|
(_src_scribe("XLII"), _scribe(Numeral("XLII")), ValStr("42")),
|
|
(_src_scribe('"hello"'), _scribe(String("hello")), ValStr('"hello"')),
|
|
(_src_scribe("[]"), _scribe(DataArray([])), ValStr("[]")),
|
|
(_src_scribe("TABVLA {}"), _scribe(DataDict([])), ValStr("{}")),
|
|
|
|
# ---- Serialize: nested ----
|
|
(_src_scribe("[I, II, III]"),
|
|
_scribe(DataArray([Numeral("I"), Numeral("II"), Numeral("III")])),
|
|
ValStr("[1, 2, 3]")),
|
|
(_src_scribe('TABVLA {"a" VT I, "b" VT VERITAS}'),
|
|
_scribe(DataDict([(String("a"), Numeral("I")), (String("b"), Bool(True))])),
|
|
ValStr('{"a": 1, "b": true}')),
|
|
|
|
# ---- Serialize: special chars ----
|
|
(_src_scribe('"a\\nb"'),
|
|
_scribe(String("a\nb")),
|
|
ValStr('"a\\nb"')),
|
|
(_src_scribe('"a\\"b"'),
|
|
_scribe(String('a"b')),
|
|
ValStr('"a\\"b"')),
|
|
(_src_scribe('"a\\\\b"'),
|
|
_scribe(String("a\\b")),
|
|
ValStr('"a\\\\b"')),
|
|
|
|
# ---- Round-trip ----
|
|
("CVM IASON\nDIC(IASON_LEGE('[1, 2, 3]'))",
|
|
Program([ModuleCall("IASON")], [ExpressionStatement(BuiltIn("DIC",
|
|
[BuiltIn("IASON_LEGE", [String("[1, 2, 3]")])]))]),
|
|
ValStr("[I II III]"), "[I II III]\n"),
|
|
|
|
("CVM IASON\nDIC(IASON_SCRIBE(IASON_LEGE('{\"a\": [1, true, null]}')))",
|
|
Program([ModuleCall("IASON")], [ExpressionStatement(BuiltIn("DIC",
|
|
[BuiltIn("IASON_SCRIBE",
|
|
[BuiltIn("IASON_LEGE", [String('{"a": [1, true, null]}')])])]))]),
|
|
ValStr('{"a": [1, true, null]}'),
|
|
'{"a": [1, true, null]}\n'),
|
|
|
|
("CVM IASON\nCVM FRACTIO\nDIC(IASON_SCRIBE(IASON_LEGE('0.5')))",
|
|
Program([ModuleCall("IASON"), ModuleCall("FRACTIO")],
|
|
[ExpressionStatement(BuiltIn("DIC",
|
|
[BuiltIn("IASON_SCRIBE",
|
|
[BuiltIn("IASON_LEGE", [String("0.5")])])]))]),
|
|
ValStr("0.5"), "0.5\n"),
|
|
|
|
("CVM IASON\nCVM FRACTIO\nDIC(IASON_SCRIBE(IASON_LEGE('0.1')))",
|
|
Program([ModuleCall("IASON"), ModuleCall("FRACTIO")],
|
|
[ExpressionStatement(BuiltIn("DIC",
|
|
[BuiltIn("IASON_SCRIBE",
|
|
[BuiltIn("IASON_LEGE", [String("0.1")])])]))]),
|
|
ValStr("0.1"), "0.1\n"),
|
|
|
|
# ---- Serialize: insertion order preserved ----
|
|
(_src_scribe('TABVLA {"b" VT II, "a" VT I, "c" VT III}'),
|
|
_scribe(DataDict([
|
|
(String("b"), Numeral("II")),
|
|
(String("a"), Numeral("I")),
|
|
(String("c"), Numeral("III")),
|
|
])),
|
|
ValStr('{"b": 2, "a": 1, "c": 3}')),
|
|
|
|
# ---- Whitespace-tolerant parse ----
|
|
(_src_lege(" [ 1 , 2 ] "),
|
|
_lege(" [ 1 , 2 ] "),
|
|
ValList([ValInt(1), ValInt(2)])),
|
|
|
|
# ---- Unicode passes through serialize (ensure_ascii=False) ----
|
|
('CVM IASON\nDIC(IASON_SCRIBE("café"))',
|
|
Program([ModuleCall("IASON")], [ExpressionStatement(BuiltIn("DIC",
|
|
[BuiltIn("IASON_SCRIBE", [String("café")])]))]),
|
|
ValStr('"café"'), '"café"\n'),
|
|
]
|
|
|
|
|
|
class TestIason(unittest.TestCase):
|
|
@parameterized.expand(iason_tests)
|
|
def test_iason(self, source, nodes, value, output="", input_lines=[]):
|
|
run_test(self, source, nodes, value, output, input_lines)
|