# About `CENTVRION` is the programming language for the modern roman. # Documentation ## Example code ### Hello World ![Hello World](snippets/hello_world.png) ### Recursive Fibonacci number function ![Fibonacci](snippets/fibonacci.png) ### Number guessing game ![Number guessing game](snippets/guessing.png) ## Variables Variables are set with the `DESIGNA` and `VT` keywords. Type is inferred. ![Variable assignment](snippets/variable.png) Variable can consist of lower-case letters, numbers, as well as `_`. ### Compound assignment `AVGE` (+=) and `MINVE` (-=) are shorthand for incrementing or decrementing a variable: ![Compound assignment](snippets/compound.png) ``` > VIII ``` `x AVGE III` is equivalent to `DESIGNA x VT x + III`. ### Destructuring Multiple variables can be assigned at once by unpacking an array or multi-return function: ``` DEFINI pair (a, b) VT { REDI (a, b) } DESIGNA x, y VT INVOCA pair (III, VII) ``` The number of targets must match the length of the array. This also works with array literals: ``` DESIGNA a, b, c VT [I, II, III] ``` ## 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](snippets/string_literal.png) Strings are concatenated with `&`: ![String concatenation](snippets/string_concat.png) `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}`: ``` DESIGNA nomen VT "Marcus" DICE("Salve, {nomen}!") // → Salve, Marcus! DICE("Sum: {III + IV}") // → Sum: VII DICE("{nomen} has {V} cats") // → Marcus has V cats ``` 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}`. 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 `I`s, `X`s, `C`s or `M`s ). 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](snippets/array_literal.png) An array of integers can also be initialized with the `VSQVE` keyword: ![Array with VSQVE](snippets/array_vsqve.png) Individual elements can be accessed by index using square brackets. Indexing is 1-based, so `I` refers to the first element: ![Array indexing](snippets/array_index.png) ``` > I ``` ## Conditionals ### SI/TVNC If-then statements are denoted with the keywords `SI` (if) and `TVNC` (then). Thus, the code ![SI/TVNC](snippets/si_tvnc.png) 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` (<) and `PLVS` (>) function as inequality evaluation. ### ALVID When using `SI`/`TVNC` statements, you can also use `ALVID` as an "else". ![ALVID](snippets/alvid.png) ``` > I ``` `SI` statements may follow immediately after `ALVID`. ![ALVID SI](snippets/alvid_si.png) ``` > 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](snippets/boolean_ops.png) ``` > II ``` ## Loops ### DONICVM loops ![DONICVM loop](snippets/donicvm.png) ``` > XLV ``` ### DVM loops ![DVM loop](snippets/dvm.png) ``` > XI ``` ### AETERNVM loops `AETERNVM FACE { ... }` is shorthand for an infinite loop — equivalent to `DVM FALSITAS FACE { ... }` but without relying on `DVM`'s inverted condition. Exit the loop with `ERVMPE` (or `REDI` from inside a function). ![AETERNVM loop](snippets/aeternvm.png) ``` > X ``` ### PER loops ![PER loop](snippets/per.png) ``` > I > II > III > IV > V ``` ## 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](snippets/function.png) ``` > CXXI ``` ## Built-ins ### DICE `DICE(value, ...)` Prints one or more values to stdout, space-separated, with integers rendered as Roman numerals. Returns the printed string. ![DICE](snippets/dice.png) ### 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)` or `LONGITVDO(string)` Returns the length of `array` (element count) or `string` (character count) as an integer. ### 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. ## 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](snippets/module_decl.png) 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](snippets/fors.png) The `FORS` module allows you to add randomness to your `CENTVRION` program. It adds 4 new built-in functions: `FORTIS_NVMERVS int int`, `FORTIS_ELECTIONIS ['a]`, `DECIMATIO ['a]`, and `SEMEN int`. `FORTIS_NVMERVS int int` picks a random int in the (inclusive) range of the two given ints. `FORTIS_ELECTIONIS ['a]` picks a random element from the given array. `FORTIS_ELECTIONIS array` is identical to ```array[FORTIS_NVMERVS NVLLVS ((LONGITVDO array)-I)]```. `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](snippets/fractio.png) 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](snippets/magnvm.png) `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 `_`. ### SVBNVLLA ![CVM SVBNVLLA](snippets/svbnvlla.png) The `SVBNVLLA` module adds the ability to write negative numbers as `-II` instead of `NVLLVS-II`.