diff --git a/README.md b/README.md index 8d2a6e0..d603c17 100644 --- a/README.md +++ b/README.md @@ -370,6 +370,36 @@ With a comparator, the type-uniformity rule is dropped — the comparator decide > [V III II I] ``` +### MVTA +`MVTA(array, fn)` + +Returns a new array obtained by applying `fn` to every element of `array`. The original array is unchanged. `fn` must be a function of exactly one parameter; its return value is unrestricted, so `MVTA` may produce an array of a different element type than its input. + +![MVTA doubling each element](snippets/mvta.png) +``` +> [II IV VI VIII] +``` + +### CRIBRA +`CRIBRA(array, predicate)` + +Returns a new array containing the elements of `array` for which `predicate` returns `VERITAS`, in their original order. The original array is unchanged. `predicate` must be a function of exactly one parameter and must return `VERAX`. + +![CRIBRA keeping elements ≤ III](snippets/cribra.png) +``` +> [I II III] +``` + +### CONFLA +`CONFLA(array, initial, fn)` + +Left fold: starts with `initial` as the accumulator, then for each element `e` of `array` updates the accumulator to `fn(acc, e)`, and returns the final accumulator. The original array is unchanged. `fn` must be a function of exactly two parameters. If `array` is empty, `initial` is returned unchanged. + +![CONFLA summing elements](snippets/confla.png) +``` +> XVI +``` + ### ADDE `ADDE(array, value)` diff --git a/centvrion/ast_nodes.py b/centvrion/ast_nodes.py index 96e65f8..f1e2b25 100644 --- a/centvrion/ast_nodes.py +++ b/centvrion/ast_nodes.py @@ -1580,6 +1580,51 @@ class BuiltIn(Node): if not (all_numeric or all_string): raise CentvrionError("ORDINA requires all elements to be numbers or all strings") return vtable, ValList(sorted(items, key=lambda v: v.value())) + case "MVTA": + if len(params) != 2: + raise CentvrionError("MVTA takes II arguments") + if not isinstance(params[0], ValList): + raise CentvrionError("MVTA requires an array") + fn = params[1] + if not isinstance(fn, ValFunc): + raise CentvrionError("MVTA requires a function") + if len(fn.params) != 1: + raise CentvrionError("MVTA function must take I argument") + out = [_call_func(fn, [item], vtable, "MVTA function") + for item in params[0].value()] + return vtable, ValList(out) + case "CRIBRA": + if len(params) != 2: + raise CentvrionError("CRIBRA takes II arguments") + if not isinstance(params[0], ValList): + raise CentvrionError("CRIBRA requires an array") + fn = params[1] + if not isinstance(fn, ValFunc): + raise CentvrionError("CRIBRA requires a function") + if len(fn.params) != 1: + raise CentvrionError("CRIBRA predicate must take I argument") + out = [] + for item in params[0].value(): + r = _call_func(fn, [item], vtable, "CRIBRA predicate") + if not isinstance(r, ValBool): + raise CentvrionError("CRIBRA predicate must return VERAX") + if r.value(): + out.append(item) + return vtable, ValList(out) + case "CONFLA": + if len(params) != 3: + raise CentvrionError("CONFLA takes III arguments") + if not isinstance(params[0], ValList): + raise CentvrionError("CONFLA requires an array") + fn = params[2] + if not isinstance(fn, ValFunc): + raise CentvrionError("CONFLA requires a function") + if len(fn.params) != 2: + raise CentvrionError("CONFLA function must take II arguments") + acc = params[1] + for item in params[0].value(): + acc = _call_func(fn, [acc, item], vtable, "CONFLA function") + return vtable, acc case "TYPVS": type_map = { ValInt: "NVMERVS", ValStr: "LITTERA", ValBool: "VERAX", diff --git a/centvrion/compiler/emit_expr.py b/centvrion/compiler/emit_expr.py index bed2b2f..aa53fcd 100644 --- a/centvrion/compiler/emit_expr.py +++ b/centvrion/compiler/emit_expr.py @@ -320,6 +320,27 @@ def _emit_builtin(node, ctx): else: raise CentvrionError("ORDINA takes 1 or 2 arguments") + case "MVTA": + if len(param_vars) != 2: + raise CentvrionError("MVTA takes II arguments") + lines.append( + f"CentValue {tmp} = cent_mvta({param_vars[0]}, {param_vars[1]}, _scope);" + ) + + case "CRIBRA": + if len(param_vars) != 2: + raise CentvrionError("CRIBRA takes II arguments") + lines.append( + f"CentValue {tmp} = cent_cribra({param_vars[0]}, {param_vars[1]}, _scope);" + ) + + case "CONFLA": + if len(param_vars) != 3: + raise CentvrionError("CONFLA takes III arguments") + lines.append( + f"CentValue {tmp} = cent_confla({param_vars[0]}, {param_vars[1]}, {param_vars[2]}, _scope);" + ) + case "ADDE": lines.append(f"CentValue {tmp} = cent_adde({param_vars[0]}, {param_vars[1]});") diff --git a/centvrion/compiler/runtime/cent_runtime.c b/centvrion/compiler/runtime/cent_runtime.c index 44b003d..867d9a2 100644 --- a/centvrion/compiler/runtime/cent_runtime.c +++ b/centvrion/compiler/runtime/cent_runtime.c @@ -897,6 +897,62 @@ CentValue cent_ordina_cmp(CentValue lst, CentValue cmp, CentScope scope) { return result; } +CentValue cent_mvta(CentValue lst, CentValue fn, CentScope scope) { + if (lst.type != CENT_LIST) + cent_type_error("'MVTA' requires an array"); + if (fn.type != CENT_FUNC) + cent_type_error("'MVTA' requires a function"); + if (fn.fnval.param_count != 1) + cent_runtime_error("'MVTA' function must take I argument"); + int len = lst.lval.len; + CentValue result = cent_list_new(len); + for (int i = 0; i < len; i++) { + CentScope s = cent_scope_copy(&scope); + cent_scope_set(&s, fn.fnval.param_names[0], lst.lval.items[i]); + cent_list_push(&result, fn.fnval.fn(s)); + } + return result; +} + +CentValue cent_cribra(CentValue lst, CentValue fn, CentScope scope) { + if (lst.type != CENT_LIST) + cent_type_error("'CRIBRA' requires an array"); + if (fn.type != CENT_FUNC) + cent_type_error("'CRIBRA' requires a function"); + if (fn.fnval.param_count != 1) + cent_runtime_error("'CRIBRA' predicate must take I argument"); + int len = lst.lval.len; + CentValue result = cent_list_new(len); + for (int i = 0; i < len; i++) { + CentScope s = cent_scope_copy(&scope); + cent_scope_set(&s, fn.fnval.param_names[0], lst.lval.items[i]); + CentValue r = fn.fnval.fn(s); + if (r.type != CENT_BOOL) + cent_type_error("'CRIBRA' predicate must return VERAX"); + if (r.bval) + cent_list_push(&result, lst.lval.items[i]); + } + return result; +} + +CentValue cent_confla(CentValue lst, CentValue init, CentValue fn, CentScope scope) { + if (lst.type != CENT_LIST) + cent_type_error("'CONFLA' requires an array"); + if (fn.type != CENT_FUNC) + cent_type_error("'CONFLA' requires a function"); + if (fn.fnval.param_count != 2) + cent_runtime_error("'CONFLA' function must take II arguments"); + CentValue acc = init; + int len = lst.lval.len; + for (int i = 0; i < len; i++) { + CentScope s = cent_scope_copy(&scope); + cent_scope_set(&s, fn.fnval.param_names[0], acc); + cent_scope_set(&s, fn.fnval.param_names[1], lst.lval.items[i]); + acc = fn.fnval.fn(s); + } + return acc; +} + static long _index_arg(CentValue idx, const char *name) { if (idx.type == CENT_INT) return idx.ival; diff --git a/centvrion/compiler/runtime/cent_runtime.h b/centvrion/compiler/runtime/cent_runtime.h index fcc6d15..a1328e9 100644 --- a/centvrion/compiler/runtime/cent_runtime.h +++ b/centvrion/compiler/runtime/cent_runtime.h @@ -240,6 +240,9 @@ CentValue cent_typvs(CentValue v); /* TYPVS */ void cent_dormi(CentValue n); /* DORMI */ CentValue cent_ordina(CentValue lst); /* ORDINA */ CentValue cent_ordina_cmp(CentValue lst, CentValue cmp, CentScope scope); /* ORDINA w/ comparator */ +CentValue cent_mvta(CentValue lst, CentValue fn, CentScope scope); /* MVTA */ +CentValue cent_cribra(CentValue lst, CentValue fn, CentScope scope); /* CRIBRA */ +CentValue cent_confla(CentValue lst, CentValue init, CentValue fn, CentScope scope); /* CONFLA */ CentValue cent_adde(CentValue lst, CentValue v); /* ADDE */ CentValue cent_tolle(CentValue lst, CentValue idx); /* TOLLE */ CentValue cent_insere(CentValue lst, CentValue idx, CentValue v); /* INSERE */ diff --git a/centvrion/lexer.py b/centvrion/lexer.py index 66c5dee..0e68727 100644 --- a/centvrion/lexer.py +++ b/centvrion/lexer.py @@ -50,6 +50,8 @@ builtin_tokens = [("BUILTIN", i) for i in [ "AVDI_NVMERVS", "AVDI", "CLAVES", + "CONFLA", + "CRIBRA", "DECIMATIO", "DIC", "DORMI", @@ -62,6 +64,7 @@ builtin_tokens = [("BUILTIN", i) for i in [ "LONGITVDO", "MAIVSCVLA", "MINVSCVLA", + "MVTA", "NECTE", "NVMERVS", "ORDINA", diff --git a/snippets/confla.cent b/snippets/confla.cent new file mode 100644 index 0000000..c0af401 --- /dev/null +++ b/snippets/confla.cent @@ -0,0 +1,4 @@ +DEFINI addi (a, b) VT { + REDI (a + b) +} +DIC (CONFLA([I, II, III, IV, V], I, addi)) diff --git a/snippets/confla.png b/snippets/confla.png new file mode 100644 index 0000000..5368f03 Binary files /dev/null and b/snippets/confla.png differ diff --git a/snippets/cribra.cent b/snippets/cribra.cent new file mode 100644 index 0000000..ef13766 --- /dev/null +++ b/snippets/cribra.cent @@ -0,0 +1,3 @@ +DIC (CRIBRA([I, II, III, IV, V, VI], FVNCTIO (x) VT { + REDI (x HAVD_PLVS III) +})) diff --git a/snippets/cribra.png b/snippets/cribra.png new file mode 100644 index 0000000..91dacf4 Binary files /dev/null and b/snippets/cribra.png differ diff --git a/snippets/mvta.cent b/snippets/mvta.cent new file mode 100644 index 0000000..6f20203 --- /dev/null +++ b/snippets/mvta.cent @@ -0,0 +1,4 @@ +DEFINI dbl (x) VT { + REDI (x + x) +} +DIC (MVTA([I, II, III, IV], dbl)) diff --git a/snippets/mvta.png b/snippets/mvta.png new file mode 100644 index 0000000..704afae Binary files /dev/null and b/snippets/mvta.png differ diff --git a/snippets/syntaxes/centvrion.sublime-syntax b/snippets/syntaxes/centvrion.sublime-syntax index 5cdb1d2..d2cfe32 100644 --- a/snippets/syntaxes/centvrion.sublime-syntax +++ b/snippets/syntaxes/centvrion.sublime-syntax @@ -70,7 +70,7 @@ contexts: scope: constant.language.centvrion builtins: - - match: '\b(ADDE|ADIVNGE|AVDI_NVMERVS|AVDI|AVSCVLTA|CLAVES|DECIMATIO|DIC|DORMI|EVERRE|FORTVITVS_NVMERVS|FORTVITA_ELECTIO|INSERE|IVNGE|LEGE|LITTERA|LONGITVDO|MAIVSCVLA|MINVSCVLA|NECTE|NVMERVS|ORDINA|PETE|PETITVR|QVAERE|SCINDE|SCRIBE|SEMEN|SENATVS|SVBSTITVE|TOLLE|TYPVS)\b' + - match: '\b(ADDE|ADIVNGE|AVDI_NVMERVS|AVDI|AVSCVLTA|CLAVES|CONFLA|CRIBRA|DECIMATIO|DIC|DORMI|EVERRE|FORTVITVS_NVMERVS|FORTVITA_ELECTIO|INSERE|IVNGE|LEGE|LITTERA|LONGITVDO|MAIVSCVLA|MINVSCVLA|MVTA|NECTE|NVMERVS|ORDINA|PETE|PETITVR|QVAERE|SCINDE|SCRIBE|SEMEN|SENATVS|SVBSTITVE|TOLLE|TYPVS)\b' scope: support.function.builtin.centvrion modules: diff --git a/tests/03_test_builtins.py b/tests/03_test_builtins.py index eef1ece..2961b20 100644 --- a/tests/03_test_builtins.py +++ b/tests/03_test_builtins.py @@ -86,6 +86,44 @@ builtin_tests = [ ("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 diff --git a/tests/12_test_failures.py b/tests/12_test_failures.py index 2a3cf84..7080037 100644 --- a/tests/12_test_failures.py +++ b/tests/12_test_failures.py @@ -75,6 +75,22 @@ error_tests = [ ("DEFINI bad (a) VT { REDI (VERITAS) }\nORDINA([I, II], bad)", CentvrionError), # ORDINA comparator wrong arity ("DEFINI bad (a, b) VT { REDI (V) }\nORDINA([I, II], bad)", CentvrionError), # ORDINA comparator returns non-bool ("ORDINA([I], V, V)", CentvrionError), # ORDINA too many args + ("MVTA([I, II])", CentvrionError), # MVTA too few args + ("MVTA([I, II], FVNCTIO (x) VT { REDI (x) }, V)", CentvrionError), # MVTA too many args + ("MVTA(I, FVNCTIO (x) VT { REDI (x) })", CentvrionError), # MVTA on non-array + ("MVTA([I, II], V)", CentvrionError), # MVTA function arg not a function + ("DEFINI bad (a, b) VT { REDI (a) }\nMVTA([I, II], bad)", CentvrionError), # MVTA function wrong arity + ("CRIBRA([I, II])", CentvrionError), # CRIBRA too few args + ("CRIBRA([I, II], FVNCTIO (x) VT { REDI (VERITAS) }, V)", CentvrionError), # CRIBRA too many args + ("CRIBRA(I, FVNCTIO (x) VT { REDI (VERITAS) })", CentvrionError), # CRIBRA on non-array + ("CRIBRA([I, II], V)", CentvrionError), # CRIBRA predicate not a function + ("DEFINI bad (a, b) VT { REDI (VERITAS) }\nCRIBRA([I, II], bad)", CentvrionError), # CRIBRA predicate wrong arity + ("DEFINI bad (x) VT { REDI (V) }\nCRIBRA([I, II], bad)", CentvrionError), # CRIBRA predicate returns non-bool + ("CONFLA([I, II], I)", CentvrionError), # CONFLA too few args + ("CONFLA([I, II], I, FVNCTIO (a, b) VT { REDI (a + b) }, V)", CentvrionError), # CONFLA too many args + ("CONFLA(I, I, FVNCTIO (a, b) VT { REDI (a + b) })", CentvrionError), # CONFLA on non-array + ("CONFLA([I, II], I, V)", CentvrionError), # CONFLA function arg not a function + ("DEFINI bad (a) VT { REDI (a) }\nCONFLA([I, II], I, bad)", CentvrionError), # CONFLA function wrong arity ("SENATVS(I)", CentvrionError), # SENATVS requires booleans ("SENATVS(VERITAS, I)", CentvrionError), # SENATVS mixed types ("SENATVS([I, II, III])", CentvrionError), # SENATVS array of non-bools diff --git a/vscode-extension/syntaxes/cent.tmLanguage.json b/vscode-extension/syntaxes/cent.tmLanguage.json index 6f820ba..eea8ede 100644 --- a/vscode-extension/syntaxes/cent.tmLanguage.json +++ b/vscode-extension/syntaxes/cent.tmLanguage.json @@ -65,7 +65,7 @@ "patterns": [ { "name": "support.function.builtin.cent", - "match": "\\b(ADDE|ADIVNGE|AVDI_NVMERVS|AVDI|AVSCVLTA|CLAVES|DECIMATIO|DIC|DORMI|EVERRE|FORTVITVS_NVMERVS|FORTVITA_ELECTIO|INSERE|IVNGE|LEGE|LITTERA|LONGITVDO|MAIVSCVLA|MINVSCVLA|NECTE|NVMERVS|ORDINA|PETE|PETITVR|QVAERE|SCINDE|SCRIBE|SEMEN|SENATVS|SVBSTITVE|TOLLE|TYPVS)\\b" + "match": "\\b(ADDE|ADIVNGE|AVDI_NVMERVS|AVDI|AVSCVLTA|CLAVES|CONFLA|CRIBRA|DECIMATIO|DIC|DORMI|EVERRE|FORTVITVS_NVMERVS|FORTVITA_ELECTIO|INSERE|IVNGE|LEGE|LITTERA|LONGITVDO|MAIVSCVLA|MINVSCVLA|MVTA|NECTE|NVMERVS|ORDINA|PETE|PETITVR|QVAERE|SCINDE|SCRIBE|SEMEN|SENATVS|SVBSTITVE|TOLLE|TYPVS)\\b" } ] },