🐐 NVMERVS
This commit is contained in:
@@ -339,6 +339,11 @@ Sorts an array in ascending order. Returns a new sorted array. All elements must
|
|||||||
|
|
||||||
Returns VERITAS if a strict majority of the arguments are VERITAS, FALSITAS otherwise. Also accepts a single array of booleans. All values must be booleans. Ties return FALSITAS.
|
Returns VERITAS if a strict majority of the arguments are VERITAS, FALSITAS otherwise. Also accepts a single array of booleans. All values must be booleans. Ties return FALSITAS.
|
||||||
|
|
||||||
|
### NVMERVS
|
||||||
|
`NVMERVS(string)`
|
||||||
|
|
||||||
|
Parses a Roman numeral string and returns its integer value. The argument must be a string containing a valid Roman numeral. Respects the `MAGNVM` and `SVBNVLLA` modules for large and negative numbers respectively.
|
||||||
|
|
||||||
### TYPVS
|
### TYPVS
|
||||||
`TYPVS(value)`
|
`TYPVS(value)`
|
||||||
|
|
||||||
|
|||||||
@@ -1185,6 +1185,13 @@ class BuiltIn(Node):
|
|||||||
raise CentvrionError(f"Invalid numeral input: {raw!r}")
|
raise CentvrionError(f"Invalid numeral input: {raw!r}")
|
||||||
case "AVDI":
|
case "AVDI":
|
||||||
return vtable, ValStr(input())
|
return vtable, ValStr(input())
|
||||||
|
case "NVMERVS":
|
||||||
|
if len(params) != 1:
|
||||||
|
raise CentvrionError("NVMERVS takes exactly I argument")
|
||||||
|
val = params[0]
|
||||||
|
if not isinstance(val, ValStr):
|
||||||
|
raise CentvrionError(f"NVMERVS expects a string, got {type(val).__name__}")
|
||||||
|
return vtable, ValInt(num_to_int(val.value(), magnvm, svbnvlla))
|
||||||
case "DIC":
|
case "DIC":
|
||||||
print_string = ' '.join(
|
print_string = ' '.join(
|
||||||
make_string(i, magnvm, svbnvlla) for i in params
|
make_string(i, magnvm, svbnvlla) for i in params
|
||||||
|
|||||||
@@ -297,6 +297,13 @@ def _emit_builtin(node, ctx):
|
|||||||
lines.append(f"cent_adivnge({param_vars[0]}, {param_vars[1]});")
|
lines.append(f"cent_adivnge({param_vars[0]}, {param_vars[1]});")
|
||||||
lines.append(f"CentValue {tmp} = cent_null();")
|
lines.append(f"CentValue {tmp} = cent_null();")
|
||||||
|
|
||||||
|
case "NVMERVS":
|
||||||
|
if len(param_vars) != 1:
|
||||||
|
lines.append(f'cent_runtime_error("NVMERVS takes exactly I argument");')
|
||||||
|
lines.append(f"CentValue {tmp} = cent_null();")
|
||||||
|
else:
|
||||||
|
lines.append(f"CentValue {tmp} = cent_numerus({param_vars[0]});")
|
||||||
|
|
||||||
case "QVAERE":
|
case "QVAERE":
|
||||||
lines.append(f"CentValue {tmp} = cent_qvaere({param_vars[0]}, {param_vars[1]});")
|
lines.append(f"CentValue {tmp} = cent_qvaere({param_vars[0]}, {param_vars[1]});")
|
||||||
|
|
||||||
|
|||||||
@@ -569,6 +569,12 @@ CentValue cent_avdi_numerus(void) {
|
|||||||
return cent_int(cent_roman_to_int(s.sval));
|
return cent_int(cent_roman_to_int(s.sval));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CentValue cent_numerus(CentValue s) {
|
||||||
|
if (s.type != CENT_STR)
|
||||||
|
cent_type_error("'NVMERVS' expects a string");
|
||||||
|
return cent_int(cent_roman_to_int(s.sval));
|
||||||
|
}
|
||||||
|
|
||||||
CentValue cent_longitudo(CentValue v) {
|
CentValue cent_longitudo(CentValue v) {
|
||||||
if (v.type == CENT_LIST) return cent_int(v.lval.len);
|
if (v.type == CENT_LIST) return cent_int(v.lval.len);
|
||||||
if (v.type == CENT_STR) return cent_int((long)strlen(v.sval));
|
if (v.type == CENT_STR) return cent_int((long)strlen(v.sval));
|
||||||
|
|||||||
@@ -232,6 +232,7 @@ CentValue cent_ordina(CentValue lst); /* ORDINA */
|
|||||||
CentValue cent_lege(CentValue path); /* LEGE */
|
CentValue cent_lege(CentValue path); /* LEGE */
|
||||||
void cent_scribe(CentValue path, CentValue content); /* SCRIBE */
|
void cent_scribe(CentValue path, CentValue content); /* SCRIBE */
|
||||||
void cent_adivnge(CentValue path, CentValue content); /* ADIVNGE */
|
void cent_adivnge(CentValue path, CentValue content); /* ADIVNGE */
|
||||||
|
CentValue cent_numerus(CentValue s); /* NVMERVS */
|
||||||
CentValue cent_qvaere(CentValue pattern, CentValue text); /* QVAERE */
|
CentValue cent_qvaere(CentValue pattern, CentValue text); /* QVAERE */
|
||||||
CentValue cent_svbstitve(CentValue pattern, CentValue replacement, CentValue text); /* SVBSTITVE */
|
CentValue cent_svbstitve(CentValue pattern, CentValue replacement, CentValue text); /* SVBSTITVE */
|
||||||
CentValue cent_scinde(CentValue str, CentValue delim); /* SCINDE */
|
CentValue cent_scinde(CentValue str, CentValue delim); /* SCINDE */
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ builtin_tokens = [("BUILTIN", i) for i in [
|
|||||||
"FORTVITVS_NVMERVS",
|
"FORTVITVS_NVMERVS",
|
||||||
"FORTVITA_ELECTIO",
|
"FORTVITA_ELECTIO",
|
||||||
"LONGITVDO",
|
"LONGITVDO",
|
||||||
|
"NVMERVS",
|
||||||
"ORDINA",
|
"ORDINA",
|
||||||
"SEMEN",
|
"SEMEN",
|
||||||
"SENATVS",
|
"SENATVS",
|
||||||
|
|||||||
@@ -346,20 +346,21 @@ class Parser():
|
|||||||
def parens(tokens):
|
def parens(tokens):
|
||||||
return tokens[1]
|
return tokens[1]
|
||||||
|
|
||||||
@self.pg.production('dict_items : ')
|
|
||||||
@self.pg.production('dict_items : expression KEYWORD_VT expression')
|
@self.pg.production('dict_items : expression KEYWORD_VT expression')
|
||||||
@self.pg.production('dict_items : expression KEYWORD_VT expression SYMBOL_COMMA dict_items')
|
@self.pg.production('dict_items : expression KEYWORD_VT expression SYMBOL_COMMA opt_newline dict_items')
|
||||||
def dict_items(calls):
|
def dict_items(calls):
|
||||||
if len(calls) == 0:
|
if len(calls) == 3:
|
||||||
return []
|
|
||||||
elif len(calls) == 3:
|
|
||||||
return [(calls[0], calls[2])]
|
return [(calls[0], calls[2])]
|
||||||
else:
|
else:
|
||||||
return [(calls[0], calls[2])] + calls[4]
|
return [(calls[0], calls[2])] + calls[5]
|
||||||
|
|
||||||
@self.pg.production('expression : KEYWORD_TABVLA SYMBOL_LCURL dict_items SYMBOL_RCURL')
|
@self.pg.production('expression : KEYWORD_TABVLA SYMBOL_LCURL opt_newline SYMBOL_RCURL')
|
||||||
|
def dict_literal_empty(tokens):
|
||||||
|
return ast_nodes.DataDict([])
|
||||||
|
|
||||||
|
@self.pg.production('expression : KEYWORD_TABVLA SYMBOL_LCURL opt_newline dict_items opt_newline SYMBOL_RCURL')
|
||||||
def dict_literal(tokens):
|
def dict_literal(tokens):
|
||||||
return ast_nodes.DataDict(tokens[2])
|
return ast_nodes.DataDict(tokens[3])
|
||||||
|
|
||||||
@self.pg.production('expression : SYMBOL_LBRACKET array_items SYMBOL_RBRACKET')
|
@self.pg.production('expression : SYMBOL_LBRACKET array_items SYMBOL_RBRACKET')
|
||||||
def array(tokens):
|
def array(tokens):
|
||||||
|
|||||||
@@ -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|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|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:
|
||||||
|
|||||||
27
tests.py
27
tests.py
@@ -638,6 +638,14 @@ builtin_tests = [
|
|||||||
('SVBSTITVE("(a)(b)", "\\2\\1", "ab")', Program([], [ExpressionStatement(BuiltIn("SVBSTITVE", [String("(a)(b)"), String("\\2\\1"), String("ab")]))]), ValStr("ba")),
|
('SVBSTITVE("(a)(b)", "\\2\\1", "ab")', Program([], [ExpressionStatement(BuiltIn("SVBSTITVE", [String("(a)(b)"), String("\\2\\1"), String("ab")]))]), ValStr("ba")),
|
||||||
# SVBSTITVE: backreference with unmatched group (ignored)
|
# SVBSTITVE: backreference with unmatched group (ignored)
|
||||||
('SVBSTITVE("(a)(b)?", "\\1\\2", "a")', Program([], [ExpressionStatement(BuiltIn("SVBSTITVE", [String("(a)(b)?"), String("\\1\\2"), String("a")]))]), ValStr("a")),
|
('SVBSTITVE("(a)(b)?", "\\1\\2", "a")', Program([], [ExpressionStatement(BuiltIn("SVBSTITVE", [String("(a)(b)?"), String("\\1\\2"), String("a")]))]), ValStr("a")),
|
||||||
|
# NVMERVS: basic conversion
|
||||||
|
('NVMERVS("XIV")', Program([], [ExpressionStatement(BuiltIn("NVMERVS", [String("XIV")]))]), ValInt(14)),
|
||||||
|
# NVMERVS: simple single numeral
|
||||||
|
('NVMERVS("I")', Program([], [ExpressionStatement(BuiltIn("NVMERVS", [String("I")]))]), ValInt(1)),
|
||||||
|
# NVMERVS: large numeral
|
||||||
|
('NVMERVS("MMMCMXCIX")', Program([], [ExpressionStatement(BuiltIn("NVMERVS", [String("MMMCMXCIX")]))]), ValInt(3999)),
|
||||||
|
# NVMERVS: subtractive form
|
||||||
|
('NVMERVS("IX")', Program([], [ExpressionStatement(BuiltIn("NVMERVS", [String("IX")]))]), ValInt(9)),
|
||||||
# SCINDE: basic split
|
# SCINDE: basic split
|
||||||
('SCINDE("a,b,c", ",")', Program([], [ExpressionStatement(BuiltIn("SCINDE", [String("a,b,c"), String(",")]))]), ValList([ValStr("a"), ValStr("b"), ValStr("c")])),
|
('SCINDE("a,b,c", ",")', Program([], [ExpressionStatement(BuiltIn("SCINDE", [String("a,b,c"), String(",")]))]), ValList([ValStr("a"), ValStr("b"), ValStr("c")])),
|
||||||
# SCINDE: no match (delimiter not found)
|
# SCINDE: no match (delimiter not found)
|
||||||
@@ -668,6 +676,9 @@ error_tests = [
|
|||||||
("DIC(M + M + M + M)", CentvrionError), # output > 3999 without MAGNVM
|
("DIC(M + M + M + M)", CentvrionError), # output > 3999 without MAGNVM
|
||||||
("IIII", CentvrionError), # invalid Roman numeral in source
|
("IIII", CentvrionError), # invalid Roman numeral in source
|
||||||
("FORTVITVS_NVMERVS(I, X)", CentvrionError), # requires FORS module
|
("FORTVITVS_NVMERVS(I, X)", CentvrionError), # requires FORS module
|
||||||
|
('NVMERVS(I)', CentvrionError), # NVMERVS expects a string, not int
|
||||||
|
('NVMERVS("ABC")', CentvrionError), # invalid Roman numeral string
|
||||||
|
('NVMERVS("XIV", "IX")', CentvrionError), # too many args
|
||||||
("DEFINI f (x) VT { REDI(x) }\nINVOCA f (I, II)", CentvrionError), # too many args
|
("DEFINI f (x) VT { REDI(x) }\nINVOCA f (I, II)", CentvrionError), # too many args
|
||||||
("DEFINI f (x, y) VT { REDI(x) }\nINVOCA f (I)", CentvrionError), # too few args
|
("DEFINI f (x, y) VT { REDI(x) }\nINVOCA f (I)", CentvrionError), # too few args
|
||||||
("DEFINI f () VT { REDI(I) }\nINVOCA f (I)", CentvrionError), # args to zero-param function
|
("DEFINI f () VT { REDI(I) }\nINVOCA f (I)", CentvrionError), # args to zero-param function
|
||||||
@@ -2236,6 +2247,22 @@ dict_tests = [
|
|||||||
('TABVLA {"x" VT I + II}',
|
('TABVLA {"x" VT I + II}',
|
||||||
Program([], [ExpressionStatement(DataDict([(String("x"), BinOp(Numeral("I"), Numeral("II"), "SYMBOL_PLUS"))]))]),
|
Program([], [ExpressionStatement(DataDict([(String("x"), BinOp(Numeral("I"), Numeral("II"), "SYMBOL_PLUS"))]))]),
|
||||||
ValDict({"x": ValInt(3)})),
|
ValDict({"x": ValInt(3)})),
|
||||||
|
# empty dict with newline
|
||||||
|
('TABVLA {\n}',
|
||||||
|
Program([], [ExpressionStatement(DataDict([]))]),
|
||||||
|
ValDict({})),
|
||||||
|
# single entry with surrounding newlines
|
||||||
|
('TABVLA {\n"a" VT I\n}',
|
||||||
|
Program([], [ExpressionStatement(DataDict([(String("a"), Numeral("I"))]))]),
|
||||||
|
ValDict({"a": ValInt(1)})),
|
||||||
|
# multiple entries with newlines after commas
|
||||||
|
('TABVLA {\n"a" VT I,\n"b" VT II\n}',
|
||||||
|
Program([], [ExpressionStatement(DataDict([(String("a"), Numeral("I")), (String("b"), Numeral("II"))]))]),
|
||||||
|
ValDict({"a": ValInt(1), "b": ValInt(2)})),
|
||||||
|
# newlines around every delimiter
|
||||||
|
('TABVLA {\n"a" VT I,\n"b" VT II,\n"c" VT III\n}',
|
||||||
|
Program([], [ExpressionStatement(DataDict([(String("a"), Numeral("I")), (String("b"), Numeral("II")), (String("c"), Numeral("III"))]))]),
|
||||||
|
ValDict({"a": ValInt(1), "b": ValInt(2), "c": ValInt(3)})),
|
||||||
]
|
]
|
||||||
|
|
||||||
class TestDict(unittest.TestCase):
|
class TestDict(unittest.TestCase):
|
||||||
|
|||||||
@@ -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|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|LONGITVDO|NVMERVS|ORDINA|PETE|PETITVR|QVAERE|SCINDE|SCRIBE|SEMEN|SENATVS|SVBSTITVE|TYPVS)\\b"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user