🐐 Array functions
This commit is contained in:
15
README.md
15
README.md
@@ -361,6 +361,21 @@ Returns the keys of `dict` as an array.
|
||||
|
||||
Sorts an array in ascending order. Returns a new sorted array. All elements must be the same type — integers, fractions, or strings. Integers and fractions sort numerically; strings sort lexicographically.
|
||||
|
||||
### ADDE
|
||||
`ADDE(array, value)`
|
||||
|
||||
Returns a new array with `value` appended at the end. The original array is unchanged.
|
||||
|
||||
### TOLLE
|
||||
`TOLLE(array, idx)`
|
||||
|
||||
Returns a new array with the element at 1-based position `idx` removed. The index must be an integer in the range `[I, LONGITVDO(array)]`; out-of-range indices raise an error.
|
||||
|
||||
### INSERE
|
||||
`INSERE(array, idx, value)`
|
||||
|
||||
Returns a new array with `value` inserted at 1-based position `idx`, shifting later elements one position to the right. The index must be an integer in the range `[I, LONGITVDO(array) + I]`; passing `LONGITVDO(array) + I` is equivalent to `ADDE`.
|
||||
|
||||
### SENATVS
|
||||
`SENATVS(bool, ...)` or `SENATVS([bool])`
|
||||
|
||||
|
||||
@@ -1496,6 +1496,32 @@ class BuiltIn(Node):
|
||||
case "EVERRE":
|
||||
print("\033[2J\033[H", end="", flush=True)
|
||||
return vtable, ValNul()
|
||||
case "ADDE":
|
||||
if len(params) != 2:
|
||||
raise CentvrionError("ADDE takes exactly II arguments")
|
||||
if not isinstance(params[0], ValList):
|
||||
raise CentvrionError("ADDE requires an array")
|
||||
return vtable, ValList(list(params[0].value()) + [params[1]])
|
||||
case "TOLLE":
|
||||
if len(params) != 2:
|
||||
raise CentvrionError("TOLLE takes exactly II arguments")
|
||||
if not isinstance(params[0], ValList):
|
||||
raise CentvrionError("TOLLE requires an array")
|
||||
items = list(params[0].value())
|
||||
idx = _to_index_int(params[1])
|
||||
if idx < 1 or idx > len(items):
|
||||
raise CentvrionError(f"Index {idx} out of range for array of length {len(items)}")
|
||||
return vtable, ValList(items[:idx - 1] + items[idx:])
|
||||
case "INSERE":
|
||||
if len(params) != 3:
|
||||
raise CentvrionError("INSERE takes exactly III arguments")
|
||||
if not isinstance(params[0], ValList):
|
||||
raise CentvrionError("INSERE requires an array")
|
||||
items = list(params[0].value())
|
||||
idx = _to_index_int(params[1])
|
||||
if idx < 1 or idx > len(items) + 1:
|
||||
raise CentvrionError(f"Index {idx} out of range for array of length {len(items)}")
|
||||
return vtable, ValList(items[:idx - 1] + [params[2]] + items[idx - 1:])
|
||||
case "ORDINA":
|
||||
if not isinstance(params[0], ValList):
|
||||
raise CentvrionError("ORDINA requires an array")
|
||||
|
||||
@@ -313,6 +313,15 @@ def _emit_builtin(node, ctx):
|
||||
case "ORDINA":
|
||||
lines.append(f"CentValue {tmp} = cent_ordina({param_vars[0]});")
|
||||
|
||||
case "ADDE":
|
||||
lines.append(f"CentValue {tmp} = cent_adde({param_vars[0]}, {param_vars[1]});")
|
||||
|
||||
case "TOLLE":
|
||||
lines.append(f"CentValue {tmp} = cent_tolle({param_vars[0]}, {param_vars[1]});")
|
||||
|
||||
case "INSERE":
|
||||
lines.append(f"CentValue {tmp} = cent_insere({param_vars[0]}, {param_vars[1]}, {param_vars[2]});")
|
||||
|
||||
case "EVERRE":
|
||||
lines.append("cent_everre();")
|
||||
lines.append(f"CentValue {tmp} = cent_null();")
|
||||
|
||||
@@ -848,6 +848,56 @@ CentValue cent_ordina(CentValue lst) {
|
||||
return result;
|
||||
}
|
||||
|
||||
static long _index_arg(CentValue idx, const char *name) {
|
||||
if (idx.type == CENT_INT)
|
||||
return idx.ival;
|
||||
if (idx.type == CENT_FRAC && idx.fval.den == 1)
|
||||
return idx.fval.num;
|
||||
cent_type_error(name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
CentValue cent_adde(CentValue lst, CentValue v) {
|
||||
if (lst.type != CENT_LIST)
|
||||
cent_type_error("'ADDE' requires a list");
|
||||
int len = lst.lval.len;
|
||||
CentValue result = cent_list_new(len + 1);
|
||||
for (int i = 0; i < len; i++)
|
||||
cent_list_push(&result, lst.lval.items[i]);
|
||||
cent_list_push(&result, v);
|
||||
return result;
|
||||
}
|
||||
|
||||
CentValue cent_tolle(CentValue lst, CentValue idx) {
|
||||
if (lst.type != CENT_LIST)
|
||||
cent_type_error("'TOLLE' requires a list");
|
||||
long i = _index_arg(idx, "'TOLLE' index must be an integer");
|
||||
int len = lst.lval.len;
|
||||
if (i < 1 || i > len)
|
||||
cent_runtime_error("'TOLLE' index out of range");
|
||||
CentValue result = cent_list_new(len - 1);
|
||||
for (int j = 0; j < len; j++)
|
||||
if (j != i - 1)
|
||||
cent_list_push(&result, lst.lval.items[j]);
|
||||
return result;
|
||||
}
|
||||
|
||||
CentValue cent_insere(CentValue lst, CentValue idx, CentValue v) {
|
||||
if (lst.type != CENT_LIST)
|
||||
cent_type_error("'INSERE' requires a list");
|
||||
long i = _index_arg(idx, "'INSERE' index must be an integer");
|
||||
int len = lst.lval.len;
|
||||
if (i < 1 || i > len + 1)
|
||||
cent_runtime_error("'INSERE' index out of range");
|
||||
CentValue result = cent_list_new(len + 1);
|
||||
for (int j = 0; j < i - 1; j++)
|
||||
cent_list_push(&result, lst.lval.items[j]);
|
||||
cent_list_push(&result, v);
|
||||
for (int j = i - 1; j < len; j++)
|
||||
cent_list_push(&result, lst.lval.items[j]);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Array helpers */
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
@@ -239,6 +239,9 @@ CentValue cent_senatus(CentValue *args, int n); /* SENATVS */
|
||||
CentValue cent_typvs(CentValue v); /* TYPVS */
|
||||
void cent_dormi(CentValue n); /* DORMI */
|
||||
CentValue cent_ordina(CentValue lst); /* ORDINA */
|
||||
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 */
|
||||
CentValue cent_lege(CentValue path); /* LEGE */
|
||||
void cent_scribe(CentValue path, CentValue content); /* SCRIBE */
|
||||
void cent_adivnge(CentValue path, CentValue content); /* ADIVNGE */
|
||||
|
||||
@@ -46,6 +46,7 @@ keyword_tokens = [("KEYWORD_"+i, i) for i in [
|
||||
]]
|
||||
|
||||
builtin_tokens = [("BUILTIN", i) for i in [
|
||||
"ADDE",
|
||||
"AVDI_NVMERVS",
|
||||
"AVDI",
|
||||
"CLAVES",
|
||||
@@ -55,6 +56,7 @@ builtin_tokens = [("BUILTIN", i) for i in [
|
||||
"EVERRE",
|
||||
"FORTVITVS_NVMERVS",
|
||||
"FORTVITA_ELECTIO",
|
||||
"INSERE",
|
||||
"LITTERA",
|
||||
"LONGITVDO",
|
||||
"MAIVSCVLA",
|
||||
@@ -63,6 +65,7 @@ builtin_tokens = [("BUILTIN", i) for i in [
|
||||
"ORDINA",
|
||||
"SEMEN",
|
||||
"SENATVS",
|
||||
"TOLLE",
|
||||
"TYPVS",
|
||||
"LEGE",
|
||||
"SCRIBE",
|
||||
|
||||
@@ -70,7 +70,7 @@ contexts:
|
||||
scope: constant.language.centvrion
|
||||
|
||||
builtins:
|
||||
- match: '\b(ADIVNGE|AVDI_NVMERVS|AVDI|AVSCVLTA|CLAVES|DECIMATIO|DIC|DORMI|EVERRE|FORTVITVS_NVMERVS|FORTVITA_ELECTIO|LEGE|LITTERA|LONGITVDO|MAIVSCVLA|MINVSCVLA|NVMERVS|ORDINA|PETE|PETITVR|QVAERE|SCINDE|SCRIBE|SEMEN|SENATVS|SVBSTITVE|TYPVS)\b'
|
||||
- match: '\b(ADDE|ADIVNGE|AVDI_NVMERVS|AVDI|AVSCVLTA|CLAVES|DECIMATIO|DIC|DORMI|EVERRE|FORTVITVS_NVMERVS|FORTVITA_ELECTIO|INSERE|LEGE|LITTERA|LONGITVDO|MAIVSCVLA|MINVSCVLA|NVMERVS|ORDINA|PETE|PETITVR|QVAERE|SCINDE|SCRIBE|SEMEN|SENATVS|SVBSTITVE|TOLLE|TYPVS)\b'
|
||||
scope: support.function.builtin.centvrion
|
||||
|
||||
modules:
|
||||
|
||||
@@ -76,6 +76,30 @@ builtin_tests = [
|
||||
("CVM FRACTIO\nORDINA([III, S, II])", Program([ModuleCall("FRACTIO")], [ExpressionStatement(BuiltIn("ORDINA", [DataArray([Numeral("III"), Fractio("S"), Numeral("II")])]))]), ValList([ValFrac(Fraction(1, 2)), ValInt(2), ValInt(3)])),
|
||||
# ORDINA: array passed via variable
|
||||
("DESIGNA x VT [III, I, II]\nORDINA(x)", Program([], [Designa(ID("x"), DataArray([Numeral("III"), Numeral("I"), Numeral("II")])), ExpressionStatement(BuiltIn("ORDINA", [ID("x")]))]), ValList([ValInt(1), ValInt(2), ValInt(3)])),
|
||||
# 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
|
||||
("ADDE([], V)", Program([], [ExpressionStatement(BuiltIn("ADDE", [DataArray([]), Numeral("V")]))]), ValList([ValInt(5)])),
|
||||
# ADDE: heterogeneous types are allowed
|
||||
('ADDE([I, II], "x")', Program([], [ExpressionStatement(BuiltIn("ADDE", [DataArray([Numeral("I"), Numeral("II")]), String("x")]))]), ValList([ValInt(1), ValInt(2), ValStr("x")])),
|
||||
# ADDE: print form to confirm output rendering
|
||||
("DIC(ADDE([I, II], III))", Program([], [ExpressionStatement(BuiltIn("DIC", [BuiltIn("ADDE", [DataArray([Numeral("I"), Numeral("II")]), Numeral("III")])]))]), ValStr("[I II III]"), "[I II III]\n"),
|
||||
# TOLLE: remove middle element
|
||||
("TOLLE([I, II, III], II)", Program([], [ExpressionStatement(BuiltIn("TOLLE", [DataArray([Numeral("I"), Numeral("II"), Numeral("III")]), Numeral("II")]))]), ValList([ValInt(1), ValInt(3)])),
|
||||
# TOLLE: remove first element
|
||||
("TOLLE([I, II, III], I)", Program([], [ExpressionStatement(BuiltIn("TOLLE", [DataArray([Numeral("I"), Numeral("II"), Numeral("III")]), Numeral("I")]))]), ValList([ValInt(2), ValInt(3)])),
|
||||
# TOLLE: remove last element
|
||||
("TOLLE([I, II, III], III)", Program([], [ExpressionStatement(BuiltIn("TOLLE", [DataArray([Numeral("I"), Numeral("II"), Numeral("III")]), Numeral("III")]))]), ValList([ValInt(1), ValInt(2)])),
|
||||
# TOLLE: single-element array → empty
|
||||
("TOLLE([V], I)", Program([], [ExpressionStatement(BuiltIn("TOLLE", [DataArray([Numeral("V")]), Numeral("I")]))]), ValList([])),
|
||||
# INSERE: insert into middle
|
||||
("INSERE([I, III], II, II)", Program([], [ExpressionStatement(BuiltIn("INSERE", [DataArray([Numeral("I"), Numeral("III")]), Numeral("II"), Numeral("II")]))]), ValList([ValInt(1), ValInt(2), ValInt(3)])),
|
||||
# INSERE: insert at front
|
||||
("INSERE([II, III], I, I)", Program([], [ExpressionStatement(BuiltIn("INSERE", [DataArray([Numeral("II"), Numeral("III")]), Numeral("I"), Numeral("I")]))]), ValList([ValInt(1), ValInt(2), ValInt(3)])),
|
||||
# INSERE: insert at len+1 (== append)
|
||||
("INSERE([I, II], III, III)", Program([], [ExpressionStatement(BuiltIn("INSERE", [DataArray([Numeral("I"), Numeral("II")]), Numeral("III"), Numeral("III")]))]), ValList([ValInt(1), ValInt(2), ValInt(3)])),
|
||||
# INSERE: into empty array at idx 1
|
||||
("INSERE([], I, V)", Program([], [ExpressionStatement(BuiltIn("INSERE", [DataArray([]), Numeral("I"), Numeral("V")]))]), ValList([ValInt(5)])),
|
||||
# TYPVS: integer
|
||||
("TYPVS(V)", Program([], [ExpressionStatement(BuiltIn("TYPVS", [Numeral("V")]))]), ValStr("NVMERVS")),
|
||||
# TYPVS: string
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
"patterns": [
|
||||
{
|
||||
"name": "support.function.builtin.cent",
|
||||
"match": "\\b(ADIVNGE|AVDI_NVMERVS|AVDI|AVSCVLTA|CLAVES|DECIMATIO|DIC|DORMI|EVERRE|FORTVITVS_NVMERVS|FORTVITA_ELECTIO|LEGE|LITTERA|LONGITVDO|MAIVSCVLA|MINVSCVLA|NVMERVS|ORDINA|PETE|PETITVR|QVAERE|SCINDE|SCRIBE|SEMEN|SENATVS|SVBSTITVE|TYPVS)\\b"
|
||||
"match": "\\b(ADDE|ADIVNGE|AVDI_NVMERVS|AVDI|AVSCVLTA|CLAVES|DECIMATIO|DIC|DORMI|EVERRE|FORTVITVS_NVMERVS|FORTVITA_ELECTIO|INSERE|LEGE|LITTERA|LONGITVDO|MAIVSCVLA|MINVSCVLA|NVMERVS|ORDINA|PETE|PETITVR|QVAERE|SCINDE|SCRIBE|SEMEN|SENATVS|SVBSTITVE|TOLLE|TYPVS)\\b"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user