🐐 LITTERA

This commit is contained in:
2026-04-24 16:45:23 +02:00
parent ea72c91870
commit 6d4a456010
12 changed files with 56 additions and 2 deletions

View File

@@ -366,6 +366,11 @@ Parses a Roman numeral string and returns its integer value. The argument must b
Returns the type of `value` as a string: `NVMERVS` (integer), `LITTERA` (string), `VERAX` (boolean), `CATALOGVS` (list), `FRACTIO` (fraction), `TABVLA` (dict), `FVNCTIO` (function), or `NVLLVS` (null). Returns the type of `value` as a string: `NVMERVS` (integer), `LITTERA` (string), `VERAX` (boolean), `CATALOGVS` (list), `FRACTIO` (fraction), `TABVLA` (dict), `FVNCTIO` (function), or `NVLLVS` (null).
### LITTERA
`LITTERA(value)`
Returns `value` formatted as the same display string `DIC` would print. Integers become Roman numerals (zero becomes `NVLLVS`), fractions use the `S`/`:`/`.`/`|` notation, booleans become `VERITAS`/`FALSITAS`, arrays are space-separated in brackets, and dicts use the `{ key VT value, ... }` form. Strings pass through unchanged. Respects `MAGNVM` and `SVBNVLLA` for large and negative numbers. Inverse of `NVMERVS` for integers: `NVMERVS(LITTERA(n)) == n`.
### DORMI ### DORMI
`DORMI(n)` `DORMI(n)`

View File

@@ -1441,6 +1441,10 @@ class BuiltIn(Node):
if isinstance(params[0], (ValList, ValStr, ValDict)): if isinstance(params[0], (ValList, ValStr, ValDict)):
return vtable, ValInt(len(params[0].value())) return vtable, ValInt(len(params[0].value()))
raise CentvrionError("LONGITVDO requires an array, string, or dict") raise CentvrionError("LONGITVDO requires an array, string, or dict")
case "LITTERA":
if len(params) != 1:
raise CentvrionError("LITTERA takes exactly I argument")
return vtable, ValStr(make_string(params[0], magnvm, svbnvlla))
case "CLAVES": case "CLAVES":
if not isinstance(params[0], ValDict): if not isinstance(params[0], ValDict):
raise CentvrionError("CLAVES requires a dict") raise CentvrionError("CLAVES requires a dict")

View File

@@ -237,6 +237,9 @@ def _emit_builtin(node, ctx):
case "LONGITVDO": case "LONGITVDO":
lines.append(f"CentValue {tmp} = cent_longitudo({param_vars[0]});") lines.append(f"CentValue {tmp} = cent_longitudo({param_vars[0]});")
case "LITTERA":
lines.append(f"CentValue {tmp} = cent_littera({param_vars[0]});")
case "FORTVITVS_NVMERVS": case "FORTVITVS_NVMERVS":
if not ctx.has_module("FORS"): if not ctx.has_module("FORS"):
lines.append('cent_runtime_error("FORS module required for FORTVITVS_NVMERVS");') lines.append('cent_runtime_error("FORS module required for FORTVITVS_NVMERVS");')

View File

@@ -644,6 +644,10 @@ CentValue cent_longitudo(CentValue v) {
return cent_null(); /* unreachable; silences warning */ return cent_null(); /* unreachable; silences warning */
} }
CentValue cent_littera(CentValue v) {
return cent_str(cent_make_string(v));
}
CentValue cent_typvs(CentValue v) { CentValue cent_typvs(CentValue v) {
switch (v.type) { switch (v.type) {
case CENT_INT: return cent_str("NVMERVS"); case CENT_INT: return cent_str("NVMERVS");

View File

@@ -223,6 +223,7 @@ void cent_dic(CentValue v); /* DIC */
CentValue cent_avdi(void); /* AVDI */ CentValue cent_avdi(void); /* AVDI */
CentValue cent_avdi_numerus(void); /* AVDI_NVMERVS */ CentValue cent_avdi_numerus(void); /* AVDI_NVMERVS */
CentValue cent_longitudo(CentValue v); /* LONGITVDO */ CentValue cent_longitudo(CentValue v); /* LONGITVDO */
CentValue cent_littera(CentValue v); /* LITTERA */
CentValue cent_fortuitus_numerus(CentValue lo, CentValue hi); /* FORTVITVS_NVMERVS */ CentValue cent_fortuitus_numerus(CentValue lo, CentValue hi); /* FORTVITVS_NVMERVS */
CentValue cent_fortuita_electionis(CentValue lst); /* FORTVITA_ELECTIO */ CentValue cent_fortuita_electionis(CentValue lst); /* FORTVITA_ELECTIO */
CentValue cent_decimatio(CentValue lst); /* DECIMATIO */ CentValue cent_decimatio(CentValue lst); /* DECIMATIO */

View File

@@ -54,6 +54,7 @@ builtin_tokens = [("BUILTIN", i) for i in [
"EVERRE", "EVERRE",
"FORTVITVS_NVMERVS", "FORTVITVS_NVMERVS",
"FORTVITA_ELECTIO", "FORTVITA_ELECTIO",
"LITTERA",
"LONGITVDO", "LONGITVDO",
"NVMERVS", "NVMERVS",
"ORDINA", "ORDINA",

3
snippets/littera.cent Normal file
View File

@@ -0,0 +1,3 @@
DESIGNA n VT VII
DESIGNA s VT LITTERA(n) & " est septem"
DIC(s)

BIN
snippets/littera.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View File

@@ -70,7 +70,7 @@ contexts:
scope: constant.language.centvrion scope: constant.language.centvrion
builtins: builtins:
- match: '\b(ADIVNGE|AVDI_NVMERVS|AVDI|AVSCVLTA|CLAVES|DECIMATIO|DIC|DORMI|EVERRE|FORTVITVS_NVMERVS|FORTVITA_ELECTIO|LEGE|LONGITVDO|NVMERVS|ORDINA|PETE|PETITVR|QVAERE|SCINDE|SCRIBE|SEMEN|SENATVS|SVBSTITVE|TYPVS)\b' - match: '\b(ADIVNGE|AVDI_NVMERVS|AVDI|AVSCVLTA|CLAVES|DECIMATIO|DIC|DORMI|EVERRE|FORTVITVS_NVMERVS|FORTVITA_ELECTIO|LEGE|LITTERA|LONGITVDO|NVMERVS|ORDINA|PETE|PETITVR|QVAERE|SCINDE|SCRIBE|SEMEN|SENATVS|SVBSTITVE|TYPVS)\b'
scope: support.function.builtin.centvrion scope: support.function.builtin.centvrion
modules: modules:

View File

@@ -646,6 +646,38 @@ builtin_tests = [
("TYPVS(FVNCTIO () VT { REDI(I) })", Program([], [ExpressionStatement(BuiltIn("TYPVS", [Fvnctio([], [Redi([Numeral("I")])])]))]), ValStr("FVNCTIO")), ("TYPVS(FVNCTIO () VT { REDI(I) })", Program([], [ExpressionStatement(BuiltIn("TYPVS", [Fvnctio([], [Redi([Numeral("I")])])]))]), ValStr("FVNCTIO")),
# TYPVS: null # TYPVS: null
("TYPVS(NVLLVS)", Program([], [ExpressionStatement(BuiltIn("TYPVS", [Nullus()]))]), ValStr("NVLLVS")), ("TYPVS(NVLLVS)", Program([], [ExpressionStatement(BuiltIn("TYPVS", [Nullus()]))]), ValStr("NVLLVS")),
# LITTERA: integer → Roman numeral
("LITTERA(V)", Program([], [ExpressionStatement(BuiltIn("LITTERA", [Numeral("V")]))]), ValStr("V")),
# LITTERA: larger integer
("LITTERA(MCMLXXXIV)", Program([], [ExpressionStatement(BuiltIn("LITTERA", [Numeral("MCMLXXXIV")]))]), ValStr("MCMLXXXIV")),
# LITTERA: zero → NVLLVS
("LITTERA(I - I)", Program([], [ExpressionStatement(BuiltIn("LITTERA", [BinOp(Numeral("I"), Numeral("I"), "SYMBOL_MINUS")]))]), ValStr("NVLLVS")),
# LITTERA: string passthrough
('LITTERA("salve")', Program([], [ExpressionStatement(BuiltIn("LITTERA", [String("salve")]))]), ValStr("salve")),
# LITTERA: empty string
('LITTERA("")', Program([], [ExpressionStatement(BuiltIn("LITTERA", [String("")]))]), ValStr("")),
# LITTERA: VERITAS
("LITTERA(VERITAS)", Program([], [ExpressionStatement(BuiltIn("LITTERA", [Bool(True)]))]), ValStr("VERITAS")),
# LITTERA: FALSITAS
("LITTERA(FALSITAS)", Program([], [ExpressionStatement(BuiltIn("LITTERA", [Bool(False)]))]), ValStr("FALSITAS")),
# LITTERA: NVLLVS
("LITTERA(NVLLVS)", Program([], [ExpressionStatement(BuiltIn("LITTERA", [Nullus()]))]), ValStr("NVLLVS")),
# LITTERA: array of integers
("LITTERA([I, II, III])", Program([], [ExpressionStatement(BuiltIn("LITTERA", [DataArray([Numeral("I"), Numeral("II"), Numeral("III")])]))]), ValStr("[I II III]")),
# LITTERA: empty array
("LITTERA([])", Program([], [ExpressionStatement(BuiltIn("LITTERA", [DataArray([])]))]), ValStr("[]")),
# LITTERA: dict with string keys (make_string emits bare keys, not quoted — matches DIC's output)
('LITTERA(TABVLA {"a" VT I})', Program([], [ExpressionStatement(BuiltIn("LITTERA", [DataDict([(String("a"), Numeral("I"))])]))]), ValStr('{a VT I}')),
# LITTERA: fraction (requires FRACTIO module)
("CVM FRACTIO\nLITTERA(S)", Program([ModuleCall("FRACTIO")], [ExpressionStatement(BuiltIn("LITTERA", [Fractio("S")]))]), ValStr("S")),
# LITTERA: negative integer
("CVM SVBNVLLA\nLITTERA(-III)", Program([ModuleCall("SVBNVLLA")], [ExpressionStatement(BuiltIn("LITTERA", [UnaryMinus(Numeral("III"))]))]), ValStr("-III")),
# LITTERA: round-trips through NVMERVS
('NVMERVS(LITTERA(VII))', Program([], [ExpressionStatement(BuiltIn("NVMERVS", [BuiltIn("LITTERA", [Numeral("VII")])]))]), ValInt(7)),
# LITTERA: concatenated with a string via &
('LITTERA(V) & " est quinque"', Program([], [ExpressionStatement(BinOp(BuiltIn("LITTERA", [Numeral("V")]), String(" est quinque"), "SYMBOL_AMPERSAND"))]), ValStr("V est quinque")),
# LITTERA: via variable
("DESIGNA x VT IX\nLITTERA(x)", Program([], [Designa(ID("x"), Numeral("IX")), ExpressionStatement(BuiltIn("LITTERA", [ID("x")]))]), ValStr("IX")),
# QVAERE: basic literal match # QVAERE: basic literal match
('QVAERE("ab", "abcabc")', Program([], [ExpressionStatement(BuiltIn("QVAERE", [String("ab"), String("abcabc")]))]), ValList([ValStr("ab"), ValStr("ab")])), ('QVAERE("ab", "abcabc")', Program([], [ExpressionStatement(BuiltIn("QVAERE", [String("ab"), String("abcabc")]))]), ValList([ValStr("ab"), ValStr("ab")])),
# QVAERE: no match → empty list # QVAERE: no match → empty list

View File

@@ -72,6 +72,7 @@
"FORTVITA_ELECTIO": { "prefix": "FORTVITA_ELECTIO", "body": "FORTVITA_ELECTIO", "description": "pick a random element from an array (FORS module)" }, "FORTVITA_ELECTIO": { "prefix": "FORTVITA_ELECTIO", "body": "FORTVITA_ELECTIO", "description": "pick a random element from an array (FORS module)" },
"FORTVITVS_NVMERVS": { "prefix": "FORTVITVS_NVMERVS", "body": "FORTVITVS_NVMERVS", "description": "random integer in a range (FORS module)" }, "FORTVITVS_NVMERVS": { "prefix": "FORTVITVS_NVMERVS", "body": "FORTVITVS_NVMERVS", "description": "random integer in a range (FORS module)" },
"LEGE": { "prefix": "LEGE", "body": "LEGE", "description": "read file contents (SCRIPTA module)" }, "LEGE": { "prefix": "LEGE", "body": "LEGE", "description": "read file contents (SCRIPTA module)" },
"LITTERA": { "prefix": "LITTERA", "body": "LITTERA", "description": "coerce any value to its display string" },
"LONGITVDO": { "prefix": "LONGITVDO", "body": "LONGITVDO", "description": "length of array, string, or dict" }, "LONGITVDO": { "prefix": "LONGITVDO", "body": "LONGITVDO", "description": "length of array, string, or dict" },
"NVMERVS": { "prefix": "NVMERVS", "body": "NVMERVS", "description": "parse a Roman numeral string to an integer" }, "NVMERVS": { "prefix": "NVMERVS", "body": "NVMERVS", "description": "parse a Roman numeral string to an integer" },
"ORDINA": { "prefix": "ORDINA", "body": "ORDINA", "description": "sort an array in ascending order" }, "ORDINA": { "prefix": "ORDINA", "body": "ORDINA", "description": "sort an array in ascending order" },

View File

@@ -65,7 +65,7 @@
"patterns": [ "patterns": [
{ {
"name": "support.function.builtin.cent", "name": "support.function.builtin.cent",
"match": "\\b(ADIVNGE|AVDI_NVMERVS|AVDI|AVSCVLTA|CLAVES|DECIMATIO|DIC|DORMI|EVERRE|FORTVITVS_NVMERVS|FORTVITA_ELECTIO|LEGE|LONGITVDO|NVMERVS|ORDINA|PETE|PETITVR|QVAERE|SCINDE|SCRIBE|SEMEN|SENATVS|SVBSTITVE|TYPVS)\\b" "match": "\\b(ADIVNGE|AVDI_NVMERVS|AVDI|AVSCVLTA|CLAVES|DECIMATIO|DIC|DORMI|EVERRE|FORTVITVS_NVMERVS|FORTVITA_ELECTIO|LEGE|LITTERA|LONGITVDO|NVMERVS|ORDINA|PETE|PETITVR|QVAERE|SCINDE|SCRIBE|SEMEN|SENATVS|SVBSTITVE|TYPVS)\\b"
} }
] ]
}, },