294 lines
13 KiB
Python
294 lines
13 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,
|
|
)
|
|
|
|
|
|
# --- Array concatenation ---
|
|
|
|
array_concat_tests = [
|
|
("[I, II] @ [III, IV]",
|
|
Program([], [ExpressionStatement(BinOp(DataArray([Numeral("I"), Numeral("II")]), DataArray([Numeral("III"), Numeral("IV")]), "SYMBOL_AT"))]),
|
|
ValList([ValInt(1), ValInt(2), ValInt(3), ValInt(4)])),
|
|
("[] @ [I]",
|
|
Program([], [ExpressionStatement(BinOp(DataArray([]), DataArray([Numeral("I")]), "SYMBOL_AT"))]),
|
|
ValList([ValInt(1)])),
|
|
("[I] @ []",
|
|
Program([], [ExpressionStatement(BinOp(DataArray([Numeral("I")]), DataArray([]), "SYMBOL_AT"))]),
|
|
ValList([ValInt(1)])),
|
|
("[] @ []",
|
|
Program([], [ExpressionStatement(BinOp(DataArray([]), DataArray([]), "SYMBOL_AT"))]),
|
|
ValList([])),
|
|
('["a"] @ [I]',
|
|
Program([], [ExpressionStatement(BinOp(DataArray([String("a")]), DataArray([Numeral("I")]), "SYMBOL_AT"))]),
|
|
ValList([ValStr("a"), ValInt(1)])),
|
|
# left-associative chaining
|
|
("[I] @ [II] @ [III]",
|
|
Program([], [ExpressionStatement(BinOp(BinOp(DataArray([Numeral("I")]), DataArray([Numeral("II")]), "SYMBOL_AT"), DataArray([Numeral("III")]), "SYMBOL_AT"))]),
|
|
ValList([ValInt(1), ValInt(2), ValInt(3)])),
|
|
# concat with variable
|
|
("DESIGNA a VT [I, II]\nDESIGNA b VT [III]\na @ b",
|
|
Program([], [Designa(ID("a"), DataArray([Numeral("I"), Numeral("II")])), Designa(ID("b"), DataArray([Numeral("III")])), ExpressionStatement(BinOp(ID("a"), ID("b"), "SYMBOL_AT"))]),
|
|
ValList([ValInt(1), ValInt(2), ValInt(3)])),
|
|
]
|
|
|
|
class TestArrayConcat(unittest.TestCase):
|
|
@parameterized.expand(array_concat_tests)
|
|
def test_array_concat(self, source, nodes, value):
|
|
run_test(self, source, nodes, value)
|
|
|
|
# --- Array indexing ---
|
|
# Indexing is 1-based; I is the first element
|
|
|
|
array_index_tests = [
|
|
# basic indexing
|
|
("[I, II, III][I]", Program([], [ExpressionStatement(ArrayIndex(DataArray([Numeral("I"), Numeral("II"), Numeral("III")]), Numeral("I")))]), ValInt(1)), # first element
|
|
("[I, II, III][II]", Program([], [ExpressionStatement(ArrayIndex(DataArray([Numeral("I"), Numeral("II"), Numeral("III")]), Numeral("II")))]), ValInt(2)), # second element
|
|
("[I, II, III][III]", Program([], [ExpressionStatement(ArrayIndex(DataArray([Numeral("I"), Numeral("II"), Numeral("III")]), Numeral("III")))]), ValInt(3)), # third element
|
|
# index into a variable
|
|
("DESIGNA a VT [X, XX, XXX]\na[II]",
|
|
Program([], [Designa(ID("a"), DataArray([Numeral("X"), Numeral("XX"), Numeral("XXX")])), ExpressionStatement(ArrayIndex(ID("a"), Numeral("II")))]),
|
|
ValInt(20)), # second element
|
|
# index into range array
|
|
("[I VSQVE V][II]", Program([], [ExpressionStatement(ArrayIndex(DataRangeArray(Numeral("I"), Numeral("V")), Numeral("II")))]), ValInt(2)), # second element of [1,2,3,4,5]
|
|
# expression as index
|
|
("[I, II, III][I + I]",
|
|
Program([], [ExpressionStatement(ArrayIndex(
|
|
DataArray([Numeral("I"), Numeral("II"), Numeral("III")]),
|
|
BinOp(Numeral("I"), Numeral("I"), "SYMBOL_PLUS")))]),
|
|
ValInt(2)),
|
|
# division result as index (no FRACTIO): IV / II = 2
|
|
("[X, XX, XXX][IV / II]",
|
|
Program([], [ExpressionStatement(ArrayIndex(
|
|
DataArray([Numeral("X"), Numeral("XX"), Numeral("XXX")]),
|
|
BinOp(Numeral("IV"), Numeral("II"), "SYMBOL_DIVIDE")))]),
|
|
ValInt(20)),
|
|
# whole-number fraction (from division) as index, with FRACTIO imported
|
|
("CVM FRACTIO\n[X, XX, XXX][IV / II]",
|
|
Program([ModuleCall("FRACTIO")], [ExpressionStatement(ArrayIndex(
|
|
DataArray([Numeral("X"), Numeral("XX"), Numeral("XXX")]),
|
|
BinOp(Numeral("IV"), Numeral("II"), "SYMBOL_DIVIDE")))]),
|
|
ValInt(20)),
|
|
]
|
|
|
|
class TestArrayIndex(unittest.TestCase):
|
|
@parameterized.expand(array_index_tests)
|
|
def test_array_index(self, source, nodes, value):
|
|
run_test(self, source, nodes, value)
|
|
|
|
# --- Array index assignment ---
|
|
|
|
array_index_assign_tests = [
|
|
# assign to middle element
|
|
("DESIGNA a VT [I, II, III]\nDESIGNA a[II] VT X\na[II]",
|
|
Program([], [
|
|
Designa(ID("a"), DataArray([Numeral("I"), Numeral("II"), Numeral("III")])),
|
|
DesignaIndex(ID("a"), [Numeral("II")], Numeral("X")),
|
|
ExpressionStatement(ArrayIndex(ID("a"), Numeral("II"))),
|
|
]),
|
|
ValInt(10)),
|
|
# assign to first element
|
|
("DESIGNA a VT [I, II, III]\nDESIGNA a[I] VT V\na[I]",
|
|
Program([], [
|
|
Designa(ID("a"), DataArray([Numeral("I"), Numeral("II"), Numeral("III")])),
|
|
DesignaIndex(ID("a"), [Numeral("I")], Numeral("V")),
|
|
ExpressionStatement(ArrayIndex(ID("a"), Numeral("I"))),
|
|
]),
|
|
ValInt(5)),
|
|
# assign to last element
|
|
("DESIGNA a VT [I, II, III]\nDESIGNA a[III] VT L\na[III]",
|
|
Program([], [
|
|
Designa(ID("a"), DataArray([Numeral("I"), Numeral("II"), Numeral("III")])),
|
|
DesignaIndex(ID("a"), [Numeral("III")], Numeral("L")),
|
|
ExpressionStatement(ArrayIndex(ID("a"), Numeral("III"))),
|
|
]),
|
|
ValInt(50)),
|
|
# other elements unaffected
|
|
("DESIGNA a VT [I, II, III]\nDESIGNA a[II] VT X\na[I]",
|
|
Program([], [
|
|
Designa(ID("a"), DataArray([Numeral("I"), Numeral("II"), Numeral("III")])),
|
|
DesignaIndex(ID("a"), [Numeral("II")], Numeral("X")),
|
|
ExpressionStatement(ArrayIndex(ID("a"), Numeral("I"))),
|
|
]),
|
|
ValInt(1)),
|
|
# expression as index
|
|
("DESIGNA a VT [I, II, III]\nDESIGNA i VT II\nDESIGNA a[i] VT X\na[II]",
|
|
Program([], [
|
|
Designa(ID("a"), DataArray([Numeral("I"), Numeral("II"), Numeral("III")])),
|
|
Designa(ID("i"), Numeral("II")),
|
|
DesignaIndex(ID("a"), [ID("i")], Numeral("X")),
|
|
ExpressionStatement(ArrayIndex(ID("a"), Numeral("II"))),
|
|
]),
|
|
ValInt(10)),
|
|
]
|
|
|
|
class TestArrayIndexAssign(unittest.TestCase):
|
|
@parameterized.expand(array_index_assign_tests)
|
|
def test_array_index_assign(self, source, nodes, value):
|
|
run_test(self, source, nodes, value)
|
|
|
|
# --- Multi-dimensional array index assignment ---
|
|
|
|
multidim_assign_tests = [
|
|
# 2D array assignment
|
|
("DESIGNA a VT [[I, II], [III, IV]]\nDESIGNA a[I][II] VT X\na[I][II]",
|
|
Program([], [
|
|
Designa(ID("a"), DataArray([DataArray([Numeral("I"), Numeral("II")]), DataArray([Numeral("III"), Numeral("IV")])])),
|
|
DesignaIndex(ID("a"), [Numeral("I"), Numeral("II")], Numeral("X")),
|
|
ExpressionStatement(ArrayIndex(ArrayIndex(ID("a"), Numeral("I")), Numeral("II"))),
|
|
]),
|
|
ValInt(10)),
|
|
# other elements unaffected
|
|
("DESIGNA a VT [[I, II], [III, IV]]\nDESIGNA a[I][II] VT X\na[II][I]",
|
|
Program([], [
|
|
Designa(ID("a"), DataArray([DataArray([Numeral("I"), Numeral("II")]), DataArray([Numeral("III"), Numeral("IV")])])),
|
|
DesignaIndex(ID("a"), [Numeral("I"), Numeral("II")], Numeral("X")),
|
|
ExpressionStatement(ArrayIndex(ArrayIndex(ID("a"), Numeral("II")), Numeral("I"))),
|
|
]),
|
|
ValInt(3)),
|
|
# dict inside array
|
|
('DESIGNA a VT [TABVLA {"x" VT I}]\nDESIGNA a[I]["x"] VT X\na[I]["x"]',
|
|
Program([], [
|
|
Designa(ID("a"), DataArray([DataDict([(String("x"), Numeral("I"))])])),
|
|
DesignaIndex(ID("a"), [Numeral("I"), String("x")], Numeral("X")),
|
|
ExpressionStatement(ArrayIndex(ArrayIndex(ID("a"), Numeral("I")), String("x"))),
|
|
]),
|
|
ValInt(10)),
|
|
# array inside dict
|
|
('DESIGNA d VT TABVLA {"a" VT [I, II]}\nDESIGNA d["a"][I] VT X\nd["a"][I]',
|
|
Program([], [
|
|
Designa(ID("d"), DataDict([(String("a"), DataArray([Numeral("I"), Numeral("II")]))])),
|
|
DesignaIndex(ID("d"), [String("a"), Numeral("I")], Numeral("X")),
|
|
ExpressionStatement(ArrayIndex(ArrayIndex(ID("d"), String("a")), Numeral("I"))),
|
|
]),
|
|
ValInt(10)),
|
|
# 3 levels deep
|
|
("DESIGNA a VT [[[I]]]\nDESIGNA a[I][I][I] VT X\na[I][I][I]",
|
|
Program([], [
|
|
Designa(ID("a"), DataArray([DataArray([DataArray([Numeral("I")])])])),
|
|
DesignaIndex(ID("a"), [Numeral("I"), Numeral("I"), Numeral("I")], Numeral("X")),
|
|
ExpressionStatement(ArrayIndex(ArrayIndex(ArrayIndex(ID("a"), Numeral("I")), Numeral("I")), Numeral("I"))),
|
|
]),
|
|
ValInt(10)),
|
|
]
|
|
|
|
class TestMultidimAssign(unittest.TestCase):
|
|
@parameterized.expand(multidim_assign_tests)
|
|
def test_multidim_assign(self, source, nodes, value):
|
|
run_test(self, source, nodes, value)
|
|
|
|
# --- Array slicing ---
|
|
|
|
array_slice_tests = [
|
|
# basic slice from middle
|
|
("[X, XX, XXX, XL, L][II VSQVE IV]",
|
|
Program([], [ExpressionStatement(ArraySlice(
|
|
DataArray([Numeral("X"), Numeral("XX"), Numeral("XXX"), Numeral("XL"), Numeral("L")]),
|
|
Numeral("II"), Numeral("IV")))]),
|
|
ValList([ValInt(20), ValInt(30), ValInt(40)])),
|
|
# slice of length 1
|
|
("[I, II, III][II VSQVE II]",
|
|
Program([], [ExpressionStatement(ArraySlice(
|
|
DataArray([Numeral("I"), Numeral("II"), Numeral("III")]),
|
|
Numeral("II"), Numeral("II")))]),
|
|
ValList([ValInt(2)])),
|
|
# full array slice
|
|
("[I, II, III][I VSQVE III]",
|
|
Program([], [ExpressionStatement(ArraySlice(
|
|
DataArray([Numeral("I"), Numeral("II"), Numeral("III")]),
|
|
Numeral("I"), Numeral("III")))]),
|
|
ValList([ValInt(1), ValInt(2), ValInt(3)])),
|
|
# slice on variable
|
|
("DESIGNA a VT [I, II, III, IV, V]\na[II VSQVE IV]",
|
|
Program([], [
|
|
Designa(ID("a"), DataArray([Numeral("I"), Numeral("II"), Numeral("III"), Numeral("IV"), Numeral("V")])),
|
|
ExpressionStatement(ArraySlice(ID("a"), Numeral("II"), Numeral("IV"))),
|
|
]),
|
|
ValList([ValInt(2), ValInt(3), ValInt(4)])),
|
|
# slice then index (chained)
|
|
("[I, II, III, IV][I VSQVE III][II]",
|
|
Program([], [ExpressionStatement(ArrayIndex(
|
|
ArraySlice(
|
|
DataArray([Numeral("I"), Numeral("II"), Numeral("III"), Numeral("IV")]),
|
|
Numeral("I"), Numeral("III")),
|
|
Numeral("II")))]),
|
|
ValInt(2)),
|
|
# slice on range array
|
|
("[I VSQVE X][III VSQVE VII]",
|
|
Program([], [ExpressionStatement(ArraySlice(
|
|
DataRangeArray(Numeral("I"), Numeral("X")),
|
|
Numeral("III"), Numeral("VII")))]),
|
|
ValList([ValInt(3), ValInt(4), ValInt(5), ValInt(6), ValInt(7)])),
|
|
# expression as slice bounds
|
|
("[I, II, III, IV, V][I + I VSQVE II + II]",
|
|
Program([], [ExpressionStatement(ArraySlice(
|
|
DataArray([Numeral("I"), Numeral("II"), Numeral("III"), Numeral("IV"), Numeral("V")]),
|
|
BinOp(Numeral("I"), Numeral("I"), "SYMBOL_PLUS"),
|
|
BinOp(Numeral("II"), Numeral("II"), "SYMBOL_PLUS")))]),
|
|
ValList([ValInt(2), ValInt(3), ValInt(4)])),
|
|
]
|
|
|
|
class TestArraySlice(unittest.TestCase):
|
|
@parameterized.expand(array_slice_tests)
|
|
def test_array_slice(self, source, nodes, value):
|
|
run_test(self, source, nodes, value)
|
|
|
|
# --- Multiline arrays ---
|
|
|
|
multiline_array_tests = [
|
|
# newlines after commas
|
|
("[I,\nII,\nIII]",
|
|
Program([], [ExpressionStatement(DataArray([Numeral("I"), Numeral("II"), Numeral("III")]))]),
|
|
ValList([ValInt(1), ValInt(2), ValInt(3)])),
|
|
# single newline after comma
|
|
("[I, II,\nIII]",
|
|
Program([], [ExpressionStatement(DataArray([Numeral("I"), Numeral("II"), Numeral("III")]))]),
|
|
ValList([ValInt(1), ValInt(2), ValInt(3)])),
|
|
# empty array still works
|
|
("[]",
|
|
Program([], [ExpressionStatement(DataArray([]))]),
|
|
ValList([])),
|
|
# nested arrays with newlines
|
|
("[I,\n[II, III],\nIV]",
|
|
Program([], [ExpressionStatement(DataArray([
|
|
Numeral("I"),
|
|
DataArray([Numeral("II"), Numeral("III")]),
|
|
Numeral("IV")]))]),
|
|
ValList([ValInt(1), ValList([ValInt(2), ValInt(3)]), ValInt(4)])),
|
|
# empty array with newline
|
|
("[\n]",
|
|
Program([], [ExpressionStatement(DataArray([]))]),
|
|
ValList([])),
|
|
# newline immediately after [
|
|
("[\nI, II, III]",
|
|
Program([], [ExpressionStatement(DataArray([Numeral("I"), Numeral("II"), Numeral("III")]))]),
|
|
ValList([ValInt(1), ValInt(2), ValInt(3)])),
|
|
# newline immediately before ]
|
|
("[I, II, III\n]",
|
|
Program([], [ExpressionStatement(DataArray([Numeral("I"), Numeral("II"), Numeral("III")]))]),
|
|
ValList([ValInt(1), ValInt(2), ValInt(3)])),
|
|
# newlines on both sides
|
|
("[\nI, II, III\n]",
|
|
Program([], [ExpressionStatement(DataArray([Numeral("I"), Numeral("II"), Numeral("III")]))]),
|
|
ValList([ValInt(1), ValInt(2), ValInt(3)])),
|
|
# newlines around every delimiter
|
|
("[\nI,\nII,\nIII\n]",
|
|
Program([], [ExpressionStatement(DataArray([Numeral("I"), Numeral("II"), Numeral("III")]))]),
|
|
ValList([ValInt(1), ValInt(2), ValInt(3)])),
|
|
]
|
|
|
|
class TestMultilineArray(unittest.TestCase):
|
|
@parameterized.expand(multiline_array_tests)
|
|
def test_multiline_array(self, source, nodes, value):
|
|
run_test(self, source, nodes, value)
|