Files
centvrion/DOCS.md
2026-04-25 20:33:03 +02:00

19 KiB
Raw Blame History

CENTVRION Language Reference

Full syntax documentation for the CENTVRION language. For the formal grammar, see language/main.pdf. For installation and a minimal example, see README.md.

Example code

Hello World

Hello World

Recursive Fibonacci number function

Fibonacci

Number guessing game

Number guessing game

Variables

Variables are set with the DESIGNA and VT keywords. Type is inferred.

Variable assignment

Variable can consist of lower-case letters, numbers, as well as _.

Compound assignment

AVGE (+=), MINVE (-=), MVLTIPLICA (*=) and DIVIDE (/=) are shorthand for updating a variable with an arithmetic operation:

Compound assignment

> VIII

x AVGE III is equivalent to DESIGNA x VT x + III; MINVE, MVLTIPLICA and DIVIDE expand the same way with subtraction, multiplication and division.

Destructuring

Multiple variables can be assigned at once by unpacking an array or multi-return function:

Destructuring function

The number of targets must match the length of the array. This also works with array literals:

Destructuring array

Data types

NVLLVS

NVLLVS is a special kind of data type in CENTVRION, similar to the null value in many other languages. NVLLVS can be 0 if evaluated as an int or float, or an empty string if evaluated as a string. NVLLVS cannot be evaluated as a boolean.

Strings

Strings are written as text in quotes (' or ").

String literal

Strings are concatenated with &:

String concatenation

NVLLVS coerces to an empty string when used with &. Note: + is for arithmetic only — using it on strings raises an error.

String Interpolation

Double-quoted strings support interpolation with {expression}:

String interpolation

Any expression can appear inside {}. Values are coerced to strings the same way as with & (integers become Roman numerals, booleans become VERITAS/FALSITAS, etc.).

Single-quoted strings do not interpolate — '{nomen}' is the literal text {nomen}. Use {{ and }} for literal braces in double-quoted strings: "use {{braces}}"use {braces}.

String Indexing and Slicing

Strings support the same indexing and slicing syntax as arrays. Indexing is 1-based and returns a single-character string:

String indexing

> S
> L

Slicing uses VSQVE with inclusive bounds, returning a substring:

String slicing

> ALV

Integer modulo is RELIQVVM: VII RELIQVVM III evaluates to I. Under the FRACTIO module it returns a fraction, so IIIS RELIQVVM IS is S (i.e. 1/2).

Integers

Integers must be written in roman numerals using the following symbols:

Symbol Value
I 1
V 5
X 10
L 50
C 100
D 500
M 1000

Each of the symbols written by themself is equal to the value of the symbol. Different symbols written from largest to smallest are equal to the sum of the symbols. Two to three of the same symbol written consecutively is equal to the sum of those symbols (only true for Is, Xs, Cs or Ms ). A single I written before a V or X is equal to 1 less than the value of the second symbol. Similarly, an X written before a L or C is 10 less than the second symbol, and a C written before a D or M is 100 less than the second symbol.

Because of the restrictions of roman numerals, numbers above 3.999 are impossible to write in the base CENTVRION syntax. If numbers of that size are required, see the MAGNVM module.

The number 0 can be expressed with the keyword NVLLVS.

Negative numbers

Negative numbers can be expressed as NVLLVS minus the value. For an explicit definition of negative numbers, see the SVBNVLLA module.

Floats

The base CENTVRION syntax does not allow for floats. However, the FRACTIO module adds a syntax for fractions.

Booleans

Booleans are denoted with the keywords VERITAS for true and FALSITAS for false.

Arrays

Arrays are defined using square brackets ([]) and commas (,):

Array literal

An array of integers can also be initialized with the VSQVE keyword. The range is inclusive on both ends:

Array with VSQVE

> [I, II, III, IV, V, VI, VII, VIII, IX, X]

Individual elements can be accessed by index using square brackets. Indexing is 1-based, so I refers to the first element:

Array indexing

> I

Arrays are concatenated with @:

Array concatenation

> [I, II, III, IV, V]

Both operands must be arrays — using @ on non-arrays raises an error.

A sub-array can be extracted with VSQVE inside the index brackets. Both bounds are inclusive and 1-based:

Array slicing

> [XX, XXX, XL]

Dicts (TABVLA)

Dicts are key-value maps created with the TABVLA keyword and curly braces:

Dict creation

Keys must be strings or integers. Values are accessed and assigned with square brackets:

Dict access

Iterating over a dict with PER loops over its keys:

Dict iteration

LONGITVDO(dict) returns the number of entries. CLAVES(dict) returns the keys as an array.

Conditionals

SI/TVNC

If-then statements are denoted with the keywords SI (if) and TVNC (then). Thus, the code

SI/TVNC

Will return I (1), as the conditional evaluates x to be true.

Boolean expressions

In conditionals, EST functions as an equality evaluation, DISPAR as not-equal, and MINVS (<), PLVS (>), HAVD_PLVS (≤), and HAVD_MINVS (≥) function as inequality evaluation.

ALIVD

When using SI/TVNC statements, you can also use ALIVD as an "else".

ALIVD

> I

SI statements may follow immediately after ALIVD.

ALIVD SI

> II

Boolean operators

The keyword ET can be used as a boolean "and". The keyword AVT can be used as a boolean "or".

Boolean operators

> II

Loops

DONICVM loops

DONICVM loop

> LV

An optional GRADV clause sets the stride. The step must be a nonzero integer expression; positive values ascend, negative values descend, and the endpoint is included only when the stride lands on it exactly.

DONICVM with GRADV

> XXV

DVM loops

DVM loop

> XI

AETERNVM loops

AETERNVM FAC { ... } is shorthand for an infinite loop — equivalent to DVM FALSITAS FAC { ... } but without relying on DVM's inverted condition. Exit the loop with ERVMPE (or REDI from inside a function).

AETERNVM loop

> X

PER loops

PER loop

> I
> II
> III
> IV
> V

Variables can be unpacked in PER loops, similar to DESIGNA destructuring:

PER destructuring

> III
> VII

Error handling

Errors can be caught using TEMPTA (temptare = to try) and CAPE (capere = to catch). The CAPE block binds the error message to a variable as a string.

TEMPTA / CAPE

> Division by zero

If the try block succeeds, the catch block is skipped. If an error occurs in the catch block, it propagates up. TEMPTA/CAPE blocks can be nested.

Functions

Functions are defined with the DEFINI and VT keywords. The REDI keyword is used to return. REDI can also be used to end the program, if used outside of a function.

Calling a function is done with the INVOCA keyword.

Function definition

> CXXI

First-class functions

Functions are first-class values in CENTVRION. They can be assigned to variables, passed as arguments, returned from functions, and stored in arrays or dicts.

Anonymous functions are created with the FVNCTIO keyword:

FVNCTIO

> XIV

INVOCA accepts any expression as the callee, not just a name:

INVOCA expressions

> VI
> VI
> XVI

Note: CENTVRION does not have closures. When a function is called, it receives a copy of the caller's scope, not the scope where it was defined. Variables from a function's definition site are only available if they also exist in the caller's scope at call time.

Built-ins

DIC

DIC(value, ...)

Prints one or more values to stdout, space-separated, with integers rendered as Roman numerals. Returns the printed string.

DIC

AVDI

AVDI()

Reads one line from stdin and returns it as a string.

AVDI_NVMERVS

AVDI_NVMERVS()

Reads one line from stdin, parses it as a Roman numeral, and returns it as an integer. Raises an error if the input is not a valid numeral.

CONTINVA

CONTINVA

Skips the rest of the current loop body and continues to the next iteration (DVM or PER). Has no meaningful return value.

ERVMPE

ERVMPE

Breaks out of the current loop (DVM or PER). Has no meaningful return value.

LONGITVDO

LONGITVDO(array), LONGITVDO(string), or LONGITVDO(dict)

Returns the length of array (element count), string (character count), or dict (entry count) as an integer.

CLAVES

CLAVES(dict)

Returns the keys of dict as an array.

ORDINA

ORDINA(array) or ORDINA(array, comparator)

Sorts an array. Returns a new sorted array; the original is unchanged.

Without a comparator, sorts in ascending order. All elements must be the same type — integers, fractions, or strings. Integers and fractions sort numerically; strings sort lexicographically.

With a comparator, the type-uniformity rule is dropped — the comparator decides ordering. The comparator must be a function of exactly two parameters and must return VERAX. comparator(a, b) returns VERITAS iff a should come before b; two elements are treated as equal when both comparator(a, b) and comparator(b, a) are FALSITAS.

ORDINA with comparator

> [V III II I]

MVTA

MVTA(array, fn)

Returns a new array obtained by applying fn to every element of array. The original array is unchanged. fn must be a function of exactly one parameter; its return value is unrestricted, so MVTA may produce an array of a different element type than its input.

MVTA doubling each element

> [II IV VI VIII]

CRIBRA

CRIBRA(array, predicate)

Returns a new array containing the elements of array for which predicate returns VERITAS, in their original order. The original array is unchanged. predicate must be a function of exactly one parameter and must return VERAX.

CRIBRA keeping elements ≤ III

> [I II III]

CONFLA

CONFLA(array, initial, fn)

Left fold: starts with initial as the accumulator, then for each element e of array updates the accumulator to fn(acc, e), and returns the final accumulator. The original array is unchanged. fn must be a function of exactly two parameters. If array is empty, initial is returned unchanged.

CONFLA summing elements

> XVI

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.

NECTE

NECTE(array1, array2)

Weaves two arrays together into a new array of two-element pair arrays. The two inputs must have equal length; mismatched lengths raise an error.

IVNGE

IVNGE(keys, values)

Builds a dict by yoking two parallel arrays — the i-th element of keys becomes the key for the i-th element of values. The two arrays must have equal length. Keys must be strings or integers. If keys contains duplicates, the later value wins.

SENATVS

SENATVS(bool, ...) or SENATVS([bool])

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(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).

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(n)

Sleeps for n seconds, where n is an integer, fraction, or NVLLVS (treated as 0). Returns nothing meaningful.

QVAERE

QVAERE(pattern, string)

Returns an array of all non-overlapping matches of the regex pattern in string. Both arguments must be strings. Patterns use extended regular expression syntax with Roman numeral quantifiers ({III} for exactly 3, {II,V} for 25, {III,} for 3 or more). Returns an empty array if there are no matches. Raises an error if the pattern is invalid.

SVBSTITVE

SVBSTITVE(pattern, replacement, string)

Replaces all non-overlapping matches of the regex pattern in string with replacement. All three arguments must be strings. The replacement string supports backreferences (\I, \II, etc.) to captured groups. Returns the resulting string. Raises an error if the pattern is invalid.

SCINDE

SCINDE(string, delimiter)

Splits string by delimiter and returns an array of substrings. Both arguments must be strings. If the delimiter is not found, returns a single-element array containing the original string. If the delimiter is an empty string, splits into individual characters.

MAIVSCVLA

MAIVSCVLA(string)

Returns a new string with every ASCII letter az replaced by its uppercase counterpart AZ. All other bytes (digits, punctuation, non-ASCII) pass through unchanged.

MINVSCVLA

MINVSCVLA(string)

Returns a new string with every ASCII letter AZ replaced by its lowercase counterpart az. All other bytes (digits, punctuation, non-ASCII) pass through unchanged.

Modules

Modules are additions to the base CENTVRION syntax. They add or change certain features. Modules are included in your code by having

Module declaration

In the beginning of your source file.

Vnlike many other programming languages with modules, the modules in CENTVRION are not libraries that can be "imported" from other scripts written in the language. They are features of the compiler, disabled by default.

FORS

CVM FORS

The FORS module allows you to add randomness to your CENTVRION program. It adds 4 new built-in functions: FORTVITVS_NVMERVS(int, int), FORTVITA_ELECTIO(['a]), DECIMATIO(['a]), and SEMEN(int).

FORTVITVS_NVMERVS(int, int) picks a random int in the (inclusive) range of the two given ints.

FORTVITA_ELECTIO(['a]) picks a random element from the given array. FORTVITA_ELECTIO(array) is identical to array[FORTVITVS_NVMERVS(I, LONGITVDO(array))].

DECIMATIO(['a]) returns a copy of the given array with a random tenth of its elements removed. Arrays with fewer than 10 elements are returned unchanged.

SEMEN(int) seeds the random number generator for reproducibility.

FRACTIO

CVM FRACTIO

The FRACTIO module adds floats, in the form of base 12 fractions.

In the FRACTIO module, . represents 1/12, : represents 1/6 and S represents 1/2. The symbols must be written from highest to lowest. So 3/4 would be written as "S:.".

Fractions can be written as an extension of integers. So 3.5 would be "IIIS".

The symbol | can be used to denote that the following fraction symbols are 1 "level down" in base 12. So after the first |, the fraction symbols denote 144ths instead of 12ths. So 7 and 100/144 would be "VIIS:|::", as "7 + 100/144" is also "7+8/12+4/144".

A single "set" of fraction symbols can only represent up to 11/12, as 12/12 can be written as 1.

MAGNVM

CVM MAGNVM

MAGNVM adds the ability to write integers larger than MMMCMXCIX (3.999) in your code, by adding the thousands operator, "_".

When _ is added after a numeric symbol, the symbol becomes 1.000 times larger. The operator can be added to the same symbol multiple times. So "V_" is 5.000, and "V__" is 5.000.000. The strict rules for integers still apply, so 4.999 cannot be written as "IV_", but must instead be written as "MV_CMXCIX".

All integer symbols except I may be given a _.

SCRIPTA

CVM SCRIPTA

The SCRIPTA module adds file I/O to your CENTVRION program. It adds 3 new built-in functions: LEGE, SCRIBE, and ADIVNGE.

LEGE(string) reads the contents of the file at the given path and returns them as a string.

SCRIBE(string, string) writes the second argument to the file at the path given by the first argument, overwriting any existing content.

ADIVNGE(string, string) appends the second argument to the file at the path given by the first argument.

RETE

CVM RETE

The RETE module adds networking to your CENTVRION program.

PETE(string) performs an HTTP GET request to the given URL and returns the response body as a string.

PETITVR(string, function) registers a GET handler for the given path. The handler function receives a single argument: a dictionary with keys "via" (the request path), "quaestio" (query string), and "methodus" (HTTP method). The handler's return value becomes the response body (200 OK). Unmatched paths return a 404.

AVSCVLTA(integer) starts an HTTP server on the given port. This call blocks indefinitely, serving registered routes. Routes must be registered with PETITVR before calling AVSCVLTA. Ports above 3999 require the MAGNVM module.

SVBNVLLA

CVM SVBNVLLA

The SVBNVLLA module adds the ability to write negative numbers as -II instead of NVLLVS-II.