diff --git a/README.md b/README.md index e80507f..dc043ee 100644 --- a/README.md +++ b/README.md @@ -309,6 +309,11 @@ Returns the keys of `dict` as an array. 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. +### TYPVS +`TYPVS(value)` + +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). + ## Modules Modules are additions to the base `CENTVRION` syntax. They add or change certain features. Modules are included in your code by having diff --git a/centvrion/ast_nodes.py b/centvrion/ast_nodes.py index 4c6df95..ef926e7 100644 --- a/centvrion/ast_nodes.py +++ b/centvrion/ast_nodes.py @@ -1121,6 +1121,13 @@ class BuiltIn(Node): case "EVERRO": print("\033[2J\033[H", end="", flush=True) return vtable, ValNul() + case "TYPVS": + type_map = { + ValInt: "NVMERVS", ValStr: "LITTERA", ValBool: "VERAX", + ValList: "CATALOGVS", ValFrac: "FRACTIO", ValDict: "TABVLA", + ValFunc: "FVNCTIO", ValNul: "NVLLVS", + } + return vtable, ValStr(type_map[type(params[0])]) case _: raise NotImplementedError(self.builtin) diff --git a/centvrion/compiler/emit_expr.py b/centvrion/compiler/emit_expr.py index 1d635d9..33dda29 100644 --- a/centvrion/compiler/emit_expr.py +++ b/centvrion/compiler/emit_expr.py @@ -255,6 +255,9 @@ def _emit_builtin(node, ctx): lines.append("cent_everro();") lines.append(f"CentValue {tmp} = cent_null();") + case "TYPVS": + lines.append(f"CentValue {tmp} = cent_typvs({param_vars[0]});") + case _: raise NotImplementedError(node.builtin) diff --git a/centvrion/compiler/runtime/cent_runtime.c b/centvrion/compiler/runtime/cent_runtime.c index c7099a4..9b602fa 100644 --- a/centvrion/compiler/runtime/cent_runtime.c +++ b/centvrion/compiler/runtime/cent_runtime.c @@ -545,6 +545,20 @@ CentValue cent_longitudo(CentValue v) { return cent_null(); /* unreachable; silences warning */ } +CentValue cent_typvs(CentValue v) { + switch (v.type) { + case CENT_INT: return cent_str("NVMERVS"); + case CENT_STR: return cent_str("LITTERA"); + case CENT_BOOL: return cent_str("VERAX"); + case CENT_LIST: return cent_str("CATALOGVS"); + case CENT_FRAC: return cent_str("FRACTIO"); + case CENT_DICT: return cent_str("TABVLA"); + case CENT_FUNC: return cent_str("FVNCTIO"); + case CENT_NULL: return cent_str("NVLLVS"); + } + return cent_str("IGNOTA"); /* unreachable */ +} + CentValue cent_fortis_numerus(CentValue lo, CentValue hi) { if (lo.type != CENT_INT || hi.type != CENT_INT) cent_type_error("'FORTIS_NVMERVS' requires two integers"); diff --git a/centvrion/compiler/runtime/cent_runtime.h b/centvrion/compiler/runtime/cent_runtime.h index 673a9c8..db1ae68 100644 --- a/centvrion/compiler/runtime/cent_runtime.h +++ b/centvrion/compiler/runtime/cent_runtime.h @@ -220,6 +220,7 @@ CentValue cent_decimatio(CentValue lst); /* DECIMATIO */ void cent_semen(CentValue seed); /* SEMEN */ void cent_everro(void); /* EVERRO */ CentValue cent_senatus(CentValue *args, int n); /* SENATVS */ +CentValue cent_typvs(CentValue v); /* TYPVS */ /* ------------------------------------------------------------------ */ /* Array helpers */ diff --git a/centvrion/lexer.py b/centvrion/lexer.py index 6a46c80..e55f22e 100644 --- a/centvrion/lexer.py +++ b/centvrion/lexer.py @@ -49,7 +49,8 @@ builtin_tokens = [("BUILTIN", i) for i in [ "FORTIS_ELECTIONIS", "LONGITVDO", "SEMEN", - "SENATVS" + "SENATVS", + "TYPVS" ]] data_tokens = [ diff --git a/tests.py b/tests.py index a064a17..e11437f 100644 --- a/tests.py +++ b/tests.py @@ -567,6 +567,24 @@ builtin_tests = [ ("SENATVS([FALSITAS, FALSITAS, VERITAS])", Program([], [ExpressionStatement(BuiltIn("SENATVS", [DataArray([Bool(False), Bool(False), Bool(True)])]))]), ValBool(False)), # SENATVS: array input, empty → FALSITAS ("SENATVS([])", Program([], [ExpressionStatement(BuiltIn("SENATVS", [DataArray([])]))]), ValBool(False)), + # TYPVS: integer + ("TYPVS(V)", Program([], [ExpressionStatement(BuiltIn("TYPVS", [Numeral("V")]))]), ValStr("NVMERVS")), + # TYPVS: string + ('TYPVS("hello")', Program([], [ExpressionStatement(BuiltIn("TYPVS", [String("hello")]))]), ValStr("LITTERA")), + # TYPVS: boolean + ("TYPVS(VERITAS)", Program([], [ExpressionStatement(BuiltIn("TYPVS", [Bool(True)]))]), ValStr("VERAX")), + # TYPVS: list + ("TYPVS([I, II])", Program([], [ExpressionStatement(BuiltIn("TYPVS", [DataArray([Numeral("I"), Numeral("II")])]))]), ValStr("CATALOGVS")), + # TYPVS: empty list + ("TYPVS([])", Program([], [ExpressionStatement(BuiltIn("TYPVS", [DataArray([])]))]), ValStr("CATALOGVS")), + # TYPVS: fraction + ("CVM FRACTIO\nTYPVS(S)", Program([ModuleCall("FRACTIO")], [ExpressionStatement(BuiltIn("TYPVS", [Fractio("S")]))]), ValStr("FRACTIO")), + # TYPVS: dict + ("TYPVS(TABVLA {})", Program([], [ExpressionStatement(BuiltIn("TYPVS", [DataDict([])]))]), ValStr("TABVLA")), + # TYPVS: function + ("TYPVS(FVNCTIO () VT { REDI(I) })", Program([], [ExpressionStatement(BuiltIn("TYPVS", [Fvnctio([], [Redi([Numeral("I")])])]))]), ValStr("FVNCTIO")), + # TYPVS: null + ("TYPVS(NVLLVS)", Program([], [ExpressionStatement(BuiltIn("TYPVS", [Nullus()]))]), ValStr("NVLLVS")), ] class TestBuiltins(unittest.TestCase):