🐐 ORDINA
This commit is contained in:
@@ -304,6 +304,11 @@ Returns the length of `array` (element count), `string` (character count), or `d
|
|||||||
|
|
||||||
Returns the keys of `dict` as an array.
|
Returns the keys of `dict` as an array.
|
||||||
|
|
||||||
|
### ORDINA
|
||||||
|
`ORDINA(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.
|
||||||
|
|
||||||
### SENATVS
|
### SENATVS
|
||||||
`SENATVS(bool, ...)` or `SENATVS([bool])`
|
`SENATVS(bool, ...)` or `SENATVS([bool])`
|
||||||
|
|
||||||
|
|||||||
@@ -1122,6 +1122,17 @@ class BuiltIn(Node):
|
|||||||
case "EVERRO":
|
case "EVERRO":
|
||||||
print("\033[2J\033[H", end="", flush=True)
|
print("\033[2J\033[H", end="", flush=True)
|
||||||
return vtable, ValNul()
|
return vtable, ValNul()
|
||||||
|
case "ORDINA":
|
||||||
|
if not isinstance(params[0], ValList):
|
||||||
|
raise CentvrionError("ORDINA requires an array")
|
||||||
|
items = list(params[0].value())
|
||||||
|
if not items:
|
||||||
|
return vtable, ValList([])
|
||||||
|
all_numeric = all(isinstance(i, (ValInt, ValFrac)) for i in items)
|
||||||
|
all_string = all(isinstance(i, ValStr) for i in items)
|
||||||
|
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 "TYPVS":
|
case "TYPVS":
|
||||||
type_map = {
|
type_map = {
|
||||||
ValInt: "NVMERVS", ValStr: "LITTERA", ValBool: "VERAX",
|
ValInt: "NVMERVS", ValStr: "LITTERA", ValBool: "VERAX",
|
||||||
|
|||||||
@@ -251,6 +251,9 @@ def _emit_builtin(node, ctx):
|
|||||||
case "CLAVES":
|
case "CLAVES":
|
||||||
lines.append(f"CentValue {tmp} = cent_dict_keys({param_vars[0]});")
|
lines.append(f"CentValue {tmp} = cent_dict_keys({param_vars[0]});")
|
||||||
|
|
||||||
|
case "ORDINA":
|
||||||
|
lines.append(f"CentValue {tmp} = cent_ordina({param_vars[0]});")
|
||||||
|
|
||||||
case "EVERRO":
|
case "EVERRO":
|
||||||
lines.append("cent_everro();")
|
lines.append("cent_everro();")
|
||||||
lines.append(f"CentValue {tmp} = cent_null();")
|
lines.append(f"CentValue {tmp} = cent_null();")
|
||||||
|
|||||||
@@ -633,6 +633,36 @@ void cent_semen(CentValue seed) {
|
|||||||
srand((unsigned)seed.ival);
|
srand((unsigned)seed.ival);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int _ordina_comparator(const void *a, const void *b) {
|
||||||
|
const CentValue *va = (const CentValue *)a;
|
||||||
|
const CentValue *vb = (const CentValue *)b;
|
||||||
|
if ((va->type == CENT_INT || va->type == CENT_FRAC) &&
|
||||||
|
(vb->type == CENT_INT || vb->type == CENT_FRAC)) {
|
||||||
|
long an, ad, bn, bd;
|
||||||
|
to_frac(*va, &an, &ad);
|
||||||
|
to_frac(*vb, &bn, &bd);
|
||||||
|
long lhs = an * bd;
|
||||||
|
long rhs = bn * ad;
|
||||||
|
return (lhs > rhs) - (lhs < rhs);
|
||||||
|
}
|
||||||
|
if (va->type == CENT_STR && vb->type == CENT_STR)
|
||||||
|
return strcmp(va->sval, vb->sval);
|
||||||
|
cent_type_error("'ORDINA' requires all elements to be the same type");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
CentValue cent_ordina(CentValue lst) {
|
||||||
|
if (lst.type != CENT_LIST)
|
||||||
|
cent_type_error("'ORDINA' requires a list");
|
||||||
|
int len = lst.lval.len;
|
||||||
|
CentValue result = cent_list_new(len);
|
||||||
|
for (int i = 0; i < len; i++)
|
||||||
|
cent_list_push(&result, lst.lval.items[i]);
|
||||||
|
if (len > 1)
|
||||||
|
qsort(result.lval.items, len, sizeof(CentValue), _ordina_comparator);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
/* Array helpers */
|
/* Array helpers */
|
||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
|
|||||||
@@ -222,6 +222,7 @@ void cent_everro(void); /* EVERRO */
|
|||||||
CentValue cent_senatus(CentValue *args, int n); /* SENATVS */
|
CentValue cent_senatus(CentValue *args, int n); /* SENATVS */
|
||||||
CentValue cent_typvs(CentValue v); /* TYPVS */
|
CentValue cent_typvs(CentValue v); /* TYPVS */
|
||||||
void cent_dormi(CentValue n); /* DORMI */
|
void cent_dormi(CentValue n); /* DORMI */
|
||||||
|
CentValue cent_ordina(CentValue lst); /* ORDINA */
|
||||||
|
|
||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
/* Array helpers */
|
/* Array helpers */
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ builtin_tokens = [("BUILTIN", i) for i in [
|
|||||||
"FORTIS_NVMERVS",
|
"FORTIS_NVMERVS",
|
||||||
"FORTIS_ELECTIONIS",
|
"FORTIS_ELECTIONIS",
|
||||||
"LONGITVDO",
|
"LONGITVDO",
|
||||||
|
"ORDINA",
|
||||||
"SEMEN",
|
"SEMEN",
|
||||||
"SENATVS",
|
"SENATVS",
|
||||||
"TYPVS"
|
"TYPVS"
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ contexts:
|
|||||||
scope: constant.language.centvrion
|
scope: constant.language.centvrion
|
||||||
|
|
||||||
builtins:
|
builtins:
|
||||||
- match: '\b(AVDI_NVMERVS|AVDI|CLAVES|DECIMATIO|DICE|EVERRO|FORTIS_NVMERVS|FORTIS_ELECTIONIS|LONGITVDO|SEMEN|SENATVS)\b'
|
- match: '\b(AVDI_NVMERVS|AVDI|CLAVES|DECIMATIO|DICE|EVERRO|FORTIS_NVMERVS|FORTIS_ELECTIONIS|LONGITVDO|ORDINA|SEMEN|SENATVS)\b'
|
||||||
scope: support.function.builtin.centvrion
|
scope: support.function.builtin.centvrion
|
||||||
|
|
||||||
modules:
|
modules:
|
||||||
|
|||||||
23
tests.py
23
tests.py
@@ -568,6 +568,26 @@ builtin_tests = [
|
|||||||
("SENATVS([FALSITAS, FALSITAS, VERITAS])", Program([], [ExpressionStatement(BuiltIn("SENATVS", [DataArray([Bool(False), Bool(False), Bool(True)])]))]), ValBool(False)),
|
("SENATVS([FALSITAS, FALSITAS, VERITAS])", Program([], [ExpressionStatement(BuiltIn("SENATVS", [DataArray([Bool(False), Bool(False), Bool(True)])]))]), ValBool(False)),
|
||||||
# SENATVS: array input, empty → FALSITAS
|
# SENATVS: array input, empty → FALSITAS
|
||||||
("SENATVS([])", Program([], [ExpressionStatement(BuiltIn("SENATVS", [DataArray([])]))]), ValBool(False)),
|
("SENATVS([])", Program([], [ExpressionStatement(BuiltIn("SENATVS", [DataArray([])]))]), ValBool(False)),
|
||||||
|
# ORDINA: sort integers
|
||||||
|
("ORDINA([III, I, II])", Program([], [ExpressionStatement(BuiltIn("ORDINA", [DataArray([Numeral("III"), Numeral("I"), Numeral("II")])]))]), ValList([ValInt(1), ValInt(2), ValInt(3)])),
|
||||||
|
# ORDINA: sort strings
|
||||||
|
('ORDINA(["c", "a", "b"])', Program([], [ExpressionStatement(BuiltIn("ORDINA", [DataArray([String("c"), String("a"), String("b")])]))]), ValList([ValStr("a"), ValStr("b"), ValStr("c")])),
|
||||||
|
# ORDINA: empty list
|
||||||
|
("ORDINA([])", Program([], [ExpressionStatement(BuiltIn("ORDINA", [DataArray([])]))]), ValList([])),
|
||||||
|
# ORDINA: single element
|
||||||
|
("ORDINA([V])", Program([], [ExpressionStatement(BuiltIn("ORDINA", [DataArray([Numeral("V")])]))]), ValList([ValInt(5)])),
|
||||||
|
# ORDINA: already sorted
|
||||||
|
("ORDINA([I, II, III])", Program([], [ExpressionStatement(BuiltIn("ORDINA", [DataArray([Numeral("I"), Numeral("II"), Numeral("III")])]))]), ValList([ValInt(1), ValInt(2), ValInt(3)])),
|
||||||
|
# ORDINA: duplicates
|
||||||
|
("ORDINA([II, I, II])", Program([], [ExpressionStatement(BuiltIn("ORDINA", [DataArray([Numeral("II"), Numeral("I"), Numeral("II")])]))]), ValList([ValInt(1), ValInt(2), ValInt(2)])),
|
||||||
|
# ORDINA: negative numbers
|
||||||
|
("CVM SVBNVLLA\nORDINA([-II, III, -I])", Program([ModuleCall("SVBNVLLA")], [ExpressionStatement(BuiltIn("ORDINA", [DataArray([UnaryMinus(Numeral("II")), Numeral("III"), UnaryMinus(Numeral("I"))])]))]), ValList([ValInt(-2), ValInt(-1), ValInt(3)])),
|
||||||
|
# ORDINA: fractions only
|
||||||
|
("CVM FRACTIO\nORDINA([IIIS, S, IIS])", Program([ModuleCall("FRACTIO")], [ExpressionStatement(BuiltIn("ORDINA", [DataArray([Fractio("IIIS"), Fractio("S"), Fractio("IIS")])]))]), ValList([ValFrac(Fraction(1, 2)), ValFrac(Fraction(5, 2)), ValFrac(Fraction(7, 2))])),
|
||||||
|
# ORDINA: mixed integers and fractions
|
||||||
|
("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)])),
|
||||||
# TYPVS: integer
|
# TYPVS: integer
|
||||||
("TYPVS(V)", Program([], [ExpressionStatement(BuiltIn("TYPVS", [Numeral("V")]))]), ValStr("NVMERVS")),
|
("TYPVS(V)", Program([], [ExpressionStatement(BuiltIn("TYPVS", [Numeral("V")]))]), ValStr("NVMERVS")),
|
||||||
# TYPVS: string
|
# TYPVS: string
|
||||||
@@ -629,6 +649,9 @@ error_tests = [
|
|||||||
("DECIMATIO([I, II, III])", CentvrionError), # FORS required for DECIMATIO
|
("DECIMATIO([I, II, III])", CentvrionError), # FORS required for DECIMATIO
|
||||||
("CVM FORS\nDECIMATIO(I)", CentvrionError), # DECIMATIO requires an array
|
("CVM FORS\nDECIMATIO(I)", CentvrionError), # DECIMATIO requires an array
|
||||||
("LONGITVDO(I)", CentvrionError), # LONGITVDO on non-array
|
("LONGITVDO(I)", CentvrionError), # LONGITVDO on non-array
|
||||||
|
("ORDINA(I)", CentvrionError), # ORDINA on non-array
|
||||||
|
('ORDINA([I, "a"])', CentvrionError), # ORDINA mixed types
|
||||||
|
("DESIGNA x VT I\nORDINA(x)", CentvrionError), # ORDINA on id (non-array)
|
||||||
("SENATVS(I)", CentvrionError), # SENATVS requires booleans
|
("SENATVS(I)", CentvrionError), # SENATVS requires booleans
|
||||||
("SENATVS(VERITAS, I)", CentvrionError), # SENATVS mixed types
|
("SENATVS(VERITAS, I)", CentvrionError), # SENATVS mixed types
|
||||||
("SENATVS([I, II, III])", CentvrionError), # SENATVS array of non-bools
|
("SENATVS([I, II, III])", CentvrionError), # SENATVS array of non-bools
|
||||||
|
|||||||
Reference in New Issue
Block a user