Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/shdown/calx
bc-like programming language
https://github.com/shdown/calx
Last synced: 3 months ago
JSON representation
bc-like programming language
- Host: GitHub
- URL: https://github.com/shdown/calx
- Owner: shdown
- License: mit
- Created: 2019-11-28T22:55:59.000Z (almost 5 years ago)
- Default Branch: master
- Last Pushed: 2022-01-21T15:35:30.000Z (almost 3 years ago)
- Last Synced: 2024-04-14T04:49:38.909Z (7 months ago)
- Language: C
- Homepage:
- Size: 126 KB
- Stars: 6
- Watchers: 2
- Forks: 0
- Open Issues: 10
-
Metadata Files:
- Readme: README.md
- License: LICENSE.MIT
Awesome Lists containing this project
README
[![Build Status](https://travis-ci.org/shdown/calx.svg?branch=master)](https://travis-ci.org/shdown/calx)
This is an attempt to make a modern replacement for `bc`, while preserving its best features, such
as big-decimal numbers and explicit support for interactivity in the language.calx’s motto is: **“deterministic and predictable output, not forecasting weather on Mars.”**
# Building calx
You will need:
* a GNU C-compatible compiler, such as GNU GCC or Clang;
* CMake;
* the GNU readline library.To build calx, simply clone this repository and run the following in its root:
```
git submodule update --init && cmake -DCMAKE_BUILD_TYPE=Release . && make
```
This will build the `./calx` binary.# Calx by example
## Values and types
Calx programs operate on *values*. Each value has a *type*, which can be one of the following:
* nil;
* flag;
* number;
* string;
* list;
* dict;
* function;
* weak reference.## Expressions, statements, expression statements
There are *expressions* and *statements*.
Expression is when you compute the value of something; `2+2` and `f(x)` are expressions.
Statement is when you *do* something; `a:=2;`, `x+=1;`, `return 2+2;` and `if(x!=1){x*=2;}` are
statements.Now, an *expression statement* is a statement consisting solely of an expression.
In other words, an *expression statement* is when an expression is followed by a semicolon.
Note that a fake semicolon is inserted in this context after a line break, a `}`, and the
end-of-file.In calx, the value of an expression statement is not *simply* evaluated and then discarded, as, for
example, in C-family languages, but also gets printed. Let’s test it:
```
≈≈> 2+2 # <- a fake semicolon is inserted here by the lexer
4
```## Scope, global and local variables
Calx has lexical, function-wide scope with hoisting (much like pre-ES6 JavaScript). However, unlike
JavaScript, it has no support for closures, although functions can be nested.A global variable is declared or assigned to with the following syntax: `NAME = VALUE;`.
Let’s test it:
```
≈≈> var = 5
≈≈> var
5
```Attempt to load the value of an undefined global variable throws a runtime error. Let’s test it:
```
≈≈> var2
Runtime error: undefined global 'var2'
Stack trace (most recent first):
>>> at (input):1:
var2
```A local variable is declared with the following syntax: `NAME := VALUE;`.
A local variable always has function scope. Note here that any chunk (a program with body) is a
function with zero parameters, and each line in the interactive mode is compiled as a separate
chunk. Let’s test it:
```
≈≈> var2 := 9; var2
9
≈≈> var2
Runtime error: undefined global 'var2'
Stack trace (most recent first):
>>> at (input):1:
var2
```Note that the `NAME = VALUE;` statement just assigns another value to an existing local variable if
such exists in the current scope.## Functions
Functions are defined with the following syntax: `fun NAME(PARAMS) { BODY }`. Let’s test it:
```
≈≈> fun myfunc(x, y) { return 2*x*y }
≈≈> myfunc(5, 6)
60
```Without an explicit `return` statement, a function returns `nil`. The `nil` value does not get
printed in the “expression statement” context, so you can declare “procedures” — functions that do
things as opposed to compute things — using this syntax as well.Remember functions are just ordinary values; you can, for example, pass them to other functions
just as well as numbers. The `fun NAME` statement is just an assignment: it is equivalent to
`NAME = ;`.As a test, let's use the built-in `Dasm` function that prints opcode listing for a function:
```
≈≈> Dasm(myfunc)
0 | OP_FUNCTION 0, 1
1 | OP_LOAD_CONST 0, 0
2 | OP_LOAD_LOCAL 0, 0
3 | OP_AOP 12, 0
4 | OP_LOAD_LOCAL 0, 1
5 | OP_AOP 12, 0
6 | OP_RETURN 0, 0
7 | OP_LOAD_CONST 0, 1
8 | OP_RETURN 0, 0
```### Is it possible to create a local function?
Yes:
```
≈≈> f := nil; fun f(x) { return 2*x }; f(3)
6
≈≈> f(3)
Runtime error: undefined global 'f'
Stack trace (most recent first):
>>> at (input):1:
f(3)
```## Operators and grouping
There are binary and unary operators. All operators have priority; binary operators also have
associativity (either left-to-right or right-to-left). Expression can be grouped with parentheses.In the tables below, operations with higher priority are done first.
### List of binary operators
Associativity defaults to “left-to-right”; see “types” below for the meaning of the “type” column.
| Spelling | Meaning | Type | Priority | Associativity |
| -------- | -------------------- | ------------ | -------- | ------------- |
| `+` | Sum | Rational | 19 | |
| `-` | Difference | Rational | 19 | |
| `*` | Product | Rational | 20 | |
| `/` | Quotient | Rational | 20 | |
| `**` | Power | Rational | 21 | Right-to-left |
| `//` | Quotient (integral) | Integral | 20 | |
| `%` | Remainder (integral) | Integral | 20 | |
| `\|` | Bitwise “OR” | Bitwise | 13 | |
| `&` | Bitwise “AND” | Bitwise | 14 | |
| `^` | Bitwise “XOR” | Bitwise | 15 | |
| `<<` | Bitwise left shift | Bitwise | 18 | |
| `>>` | Bitwise right shift | Bitwise | 18 | |
| `<` | Less | Comparative | 17 | |
| `<=` | Less or equals | Comparative | 17 | |
| `>` | Greater | Comparative | 17 | |
| `>=` | Greater or equals | Comparative | 17 | |
| `~` | Concatenation | Omnivorous | 10 | |
| `\|\|` | Logical “OR” | Omnivorous | 11 | |
| `&&` | Logical “AND” | Omnivorous | 12 | |
| `==` | Equals | Omnivorous | 16 | |
| `!=` | Not equals | Omnivorous | 16 | |#### Types
- **Rational**: expect both of their operands to be numbers; throw otherwise. Also throw if one of
the operands is not in the domain of operator: `/` throws if the right operand is zero; `**` throws
if the right operand is non-integer, or if the right operand is negative (it is assumed that
`0 ** 0` is `1`).- **Integral**: expect both of their operands to be numbers; throw otherwise. Then, assuming the
left and right operands were `left` and `right`, correspondingly, the result is
`TO_INTEGER(OPERATION(TO_INTEGER(left), TO_INTEGER(right)))`. These operators throw if one of the
operands is not in the domain of the operator: `//` and `%` throw if `TO_INTEGER(right)` is zero.
See below for the definition of the `TO_INTEGER` function.- **Bitwise**: expect both of their operands to be numbers; throw otherwise. Then, assuming the
left and right operands were `left` and `right`, correspondingly, the result is
`OPERATION(TO_UINT32(left), TO_UINT32(right))`. The left and right shift operations return zero if
`TO_UINT32(right) >= 32`. See below for the definition of the `TO_UINT32` function.- **Comparative**: expect their operands to be “meaningfully comparable”; currently, this means that
they must either be both numbers, or be both strings. Throw otherwise.- **Omnivorous**: work with operands of any types.
#### Discussion
The `/` operator is the only one whose result depends on the *scale* (see the section on it below);
other always return the exact result.The concatenation operator, assuming its left and right operands were `left` and `right`,
correspondingly, returns `CONCATENATE_STRINGS(TO_STRING(left), TO_STRING(right))`. See below for the
definition of the `TO_STRING` function.The logical “OR” operator, assuming its left and right operands were `left` and `right`, returns
`left` if `TO_FLAG(left)` is `true`; otherwise, it returns `right`.The logical “AND” operator, assuming its left and right operands were `left` and `right`, returns
`left` if `TO_FLAG(left) ` is `false`; otherwise, it returns `right`.The `==` and `!=` operators compare their operands in the following way:
* if the values are of different types, they compare as “not equal”;
* number, string, flag and nil values compare “by value”;
* values of other types compare “by identity” (read “by pointer”).### List of unary operators
| Spelling | Meaning | Priority |
| -------- | -------------------- | -------- |
| `-` | Negation | 50 |
| `!` | Logical “NOT” | 50 |
| `@` | Length | 60 |The negation operator expects its operand to be number; throws otherwise.
The logical “NOT” operator works with operand of any type. Assuming the operand was `x`, the result
is `BOOL_NOT(TO_FLAG(x))`. See below for the definition of the `TO_FLAG` function.The length operator returns the length of a list, a dict, or a string; throws if the operand is
neither.## Compound assignments
For each binary operator with spelling ``, there is a corresponding *compound assignment*
statement with the following syntax: `LHS = VALUE;`. For example, to add something to a
variable, use `NAME += VALUE;`.## The scale
The scale can be thought of as a global variable that sets the precision of the result of `/`
(division) operator. It also sets the precision of the results of various built-in analytic
functions.Precision means decimal places, and thus can not be negative.
Its value can be read via the following call: `Scale()`. It returns the current precision as a number.
Its value can be set via the following call: `Scale(n)`.
## Lists
Lists are lists of values. `[]`, `[12]`, `[12, 34]`, `[12, 34, 56]` expressions all create new lists
with the specified elements.### Get element
To get an element of the list by index, use `list[index]` syntax. `index` must be number;
otherwise, this construct throws.If `index >= 0` and {`TO_INTEGER(index)` is a valid list index}, then the result is the value behind that index.
Otherwise, the result is `nil`.
See below for the definition of the `TO_INTEGER` function.
Let’s test it:
```
≈≈> xs = [1, 2, 3]
≈≈> xs[0]
1
≈≈> xs[0.9]
1
≈≈> xs[1]
2
≈≈> xs[2]
3
≈≈> xs[3]
≈≈> xs[-1]
≈≈> xs[-0.1]
≈≈> xs["test"]
Runtime error: attempt to index list with string (expected number)
Stack trace (most recent first):
>>> at (input):1:
xs["test"]
```### Set element/push element back
To set list element by index, use `list[index] = value` syntax. `index` must be number; otherwise,
this construct throws.If `index >= 0` and {`TO_INTEGER(index)` is a valid list index}, then the value behind that index is altered.
If `TO_INTEGER(index)` equals to the size of the list, a new element is pushed to the back of the list.
Otherwise, this construct throws.
See below for the definition of the `TO_INTEGER` function.
### Get size
To get the size of the list, use the `@` operator:
```
≈≈> @[12, 34]
2
```### Pop element
Use the built-in `Pop` function to pop the last element off the list:
```
≈≈> xs = [1, 2, 3]
≈≈> Pop(xs)
3
≈≈> Pop(xs)
2
≈≈> Pop(xs)
1
≈≈> Pop(xs)
Runtime error: the list is empty
Stack trace (most recent first):
>>> at (input):1:
Pop(xs)
```## Dicts
Dicts are mappings from strings to values. `{}`, `{"x": 1}`, `{"x": 1, "y": 2}` expressions all
create new dicts with the specified entries.### Get size
To get the size (the number of entries) of the dict, use the `@` operator:
```
≈≈> @{"a": 1, "b": 2}
2
```### Get element
To get the value behind a key, use `dict[key]` syntax. `key` must be string;
otherwise, this construct throws. If there is no such key, the result is `nil`.There is a shortcut notation for constant keys that are valid identifiers: `dict.ident` is
equivalent to `dict["ident"]`.Let’s test it:
```
≈≈> d = {"key1": 1, "key2": true, "key3": "str"}
≈≈> d["key1"]
1
≈≈> d.key1
1
≈≈> d.key2
true
≈≈> d.key3
str
≈≈> d.key4
≈≈> d[0]
Runtime error: attempt to index dict with number (expected string)
Stack trace (most recent first):
>>> at (input):1:
d[0]
```### Set element
To alter the value behind a key or insert a new entry, use `dict[key] = value` syntax. `key` must be
string; otherwise, this construct throws.Let’s test it:
```
≈≈> d = {"key1": 1, "key2": true, "key3": "str"}
≈≈> d.key3 = 3
≈≈> d["key4"] = 4
≈≈> d.key3; d.key4
3
4
```### Remove element
To remove an entry from a dict behind a key, use `RemoveKey(dict, key)`.
If there is no entry with the key given, this function does nothing.Let’s test it:
```
≈≈> d = {"key1": 1, "key2": 2}
≈≈> RemoveKey(d, "key1")
≈≈> d
{"key2": 2}
≈≈> RemoveKey(d, "z")
≈≈> d
{"key2": 2}
```### Iterate over keys
```
≈≈> d = {"key1": 1, "key2": true, "key3": "str"}
≈≈> for (k := NextKey(d, nil); k; k = NextKey(d, k)) { k ~ " => " ~ d[k] }
key3 => str
key2 => true
key1 => 1
```Note that the order of keys is unspecified.
## Numbers
Numbers are just numbers, big-decimal and having both integer and fractional parts of potentially
unlimited length:
```
≈≈> 123456789123456789123456789123456789.0123456789012345678901234567890123456789
123456789123456789123456789123456789.0123456789012345678901234567890123456789
```You can also optionally separate their digits with a single quote symbol:
```
≈≈> 1'000'000
1000000
```## Strings
Strings are just immutable arrays of bytes. String literals must always use double quotes; single
quotes are not supported:```
≈≈> "test"
test
```### Escapes
The following escapes in string literals are supported:
| Spelling | C equivalent |
| -------- | -------------------- |
| `\\` | `\\` |
| `\a` | `\a` |
| `\b` | `\b` |
| `\e` | `\033` |
| `\f` | `\f` |
| `\n` | `\n` |
| `\r` | `\r` |
| `\t` | `\t` |
| `\v` | `\v` |
| `\"` | `\"` |
| `\0` | `\0` |
| `\x##` | `\x##` |where `##` means two hexadecimal digits (both lower- and uppercase letters are accepted).
### Get size
To get the size (the number of bytes) of the string, use the `@` operator:
```
≈≈> @"test"
4
≈≈> @"ш"
2
```### Get byte
To get string byte by index, use `str[index]` syntax. `index` must be number;
otherwise, this construct throws.If `index >= 0` and {`TO_INTEGER(index)` is a valid string index}, then the result is a single-byte
string.Otherwise, the result is `nil`.
See below for the definition of the `TO_INTEGER` function.
Let’s test it:
```
≈≈> "abcde"[3]
d
≈≈> "abcde"[100]
≈≈> "abcde"["x"]
Runtime error: attempt to index string with string (expected number)
Stack trace (most recent first):
>>> at (input):1:
"abcde"["x"]
```## Literals of other types
`nil` is the literal of nil type.
`true` and `false` are literals of flag type.
## Truthiness
We say the value `x` is truthy iff `TO_FLAG(x)` returns true.
See below for the definition of the `TO_FLAG` function.
## `if` statement
An `if` statement, in its base form, has the following syntax: `if (CONDITION) { BODY }`.
It executes `BODY` if `TO_FLAG(CONDITION)` is `true`.Another form is has the following syntax: `if (CONDITION) { BODY_1 } else { BODY_2 }`.
It executes `BODY_1` if `TO_FLAG(CONDITION)` is `true`, and `BODY_2` otherwise.After the `if` clause (and before the `else` clause, if any), any number of `elif` (meaning "else if") clauses may be inserted;
an `elif` clause has the following syntax: `elif (COND) { BODY }`. Such a clause means that, if the conditions of all the previous
`if`/`elif` clauses were false so that their bodies were not executed, then `COND` must be evaluated, and, if `TO_FLAG(COND)` is `true`,
`BODY` of this `elif` clause should be executed, and body of `else` clause, if any, should not.Following is an example of an `if` statement with an `elif` clause:
```
≈≈> if (2+2 == 2) {
×⋅⋅⋅> "two"
×⋅⋅⋅> } elif (2+2 == 4) {
×⋅⋅⋅> "four"
×⋅⋅⋅> } else {
×⋅⋅⋅> "neither"
×⋅⋅⋅> }
four
```Overall, the semantics of an `if` statement is the following:
1. Evaluate the condition of the `if` clause; if truthy, execute the body of the `if` clause and go
to step 4.2. If has no more `elif` clauses, then go to step 4. Otherwise, evaluate the condition of the
next `elif` clause; if truthy, execute the body of that `elif` clause and go to step 4.
Otherwise, repeat step 2.3. If an `else` clause is present, then execute its body.
4. The execution of the statement is done.
## `while` statement
The `while` statement has the following syntax: `while (CONDITION) { BODY }`.
Its semantics is the following:
1. Evaluate the condition. If truthy, then execute the body and repeat step 1.
2. The execution of the statement is done.
## `for` statement
The `for` statement has the following syntax: `for (PRE; COND; POST) { BODY }`.
In the notation above:
* both `PRE` and `POST` must be “maybe-expr-or-assignment-type statements”, where a “maybe-expr-or-assignment-type statement” is either of:
- an empty statement;
- an expression statement;
- an assignment statement, including a compound assignment statement;
* `COND` must be either empty or an expression.Its semantics is the following:
1. Execute the `PRE` statement.
2. If `COND` is present, then evaluate it and, if not truthy, go to step 6.
3. Execute `BODY`.
4. Execute the `POST` statement.
5. Go to step 2.
6. The execution of the statement is done.
## `return` statement
The `return EXPRESSION;` statement evaluates `EXPRESSION` and returns its value from the innermost
function.The `return;` statement is equivalent to `return nil;`.
## `break` statement
The `break;` statement breaks out of the innermost `while` or `for` loop.
For `while` loop, it means the control flow jumps to the step 2; for `for` loop, it means the
control flow jumps to the step 6.## `continue` statement
The `continue;` statement forces the next ieration of the innermost `while` or `for` loop.
For `while` loop, it means the control flow jumps to the step 1; for `for` loop, it means the
control flow jumps to the step 4.## Semicolon insertion rules
A semicolon inserted anywhere outside of an expression before:
* a line break;
* an end-of-input;
* a `}` lexeme.## Special functions used in this document
### `TO_INTEGER`
This function can only be applied to a number. It truncates the fractional part of the number;
in other words, it rounds the number towards zero.### `TO_UINT32`
This function can only be applied to a number.
`TO_INT32(x)` returns `TO_INTEGER(x)` modulo `2 ** 32`; the result is always non-negative and less
than `2 ** 32`.### `TO_STRING`
The behavior of this function depends on the type of its argument:
* for string, it returns the value unmodified;
* for number, it returns its string representation;
* for flag, it returns either `"true"` or `"false"`;
* for nil, it returns `""`;
* for list, it returns `""`;
* for dict, it returns `""`;
* for function, it returns `""`;
* for weak reference, it returns `""`.### `TO_FLAG`
`TO_FLAG(x)` returns `false` if `x` is either `false` or `nil`; otherwise, it returns `true`.
## Built-in functions
### `Dasm`
`Dasm(f)` prints out the disassembly (bytecode listing) of a bytecode function `f`.
Returns `nil`.
### `Kind`
`Kind(v)` returns the name of the type of `v`:
* for string, it returns `"string"`;
* for number, it returns `"number"`;
* for flag, it returns `"flag"`;
* for nil, it returns `"nil"`;
* for list, it returns `"list"`;
* for dict, it returns `"dict"`;
* for function, it returns `"function"`.
* for weak reference, it returns `"weakref"`.### `Pop`
`Pop(L)` pops an element from the back of the list `L` and returns the element.
Throws if `L` is empty.
### `Input`
`Input()` asks the user to enter a line and returns it as a string.
If the user refused, an empty string is returned.
### `Ord`
`Ord(c)`, where `c` is a one-byte string, returns the numeric value of that byte.
### `Chr`
`Chr(n)` returns a character (a single-byte string) by its numeric value `n`.
### `Error`
`Error(s)`, where `s` is a string, throws an error with message `s`.
### `RawRead`
`RawRead(s)`, where `s` is a (single-byte) string, behaves in either of the following ways,
depending on the value of `s`:* If `s` is `"L"`, then the function reads a line from stdin, and returns the line **with**
the trailing line break, if any; on I/O error, or if the end-of-file is reached, returns an empty
string.* If `s` is `"s"`, then the function reads a line from stdin, and returns the line **without** the
trailing line break; on I/O error, or if the end-of-file is reached, returns an empty string.* If `s` is `"B"`, then the function reads a single byte from stdin, and returns a single-byte
string with that byte; on I/O error, or if the end-of-file is reached, returns an empty string.* Otherwise, it throws.
### `RawWrite`
`RawWrite(s)`, where `s` is a string, prints `s` to stdout without trailing newline.
Returns `nil`.
### `Scale`
`Scale()` returns the current scale as a number.
`Scale(n)`, where `n` is a number, sets the current scale to `n`.
For what scale is, see the “The scale” section.
### `Where`
`Where()` prints out the stack trace.
Returns `nil`.
### `Random32`
`Random32()` returns a random 32-bit unsigned integer.
### `LoadString`
`LoadString(s)`, where `s` is a string, compiles `s` as a code, and returns the compiled function.
Throws if compilation fails.
For example, `Eval` in calx can be implemented as follows:
```
fun Eval(s) {
return LoadString(s)()
}
```### `Require`
`Require(s)`, where `s` is a string, tries to load and evaluate contents of file `.calx`
from the directory `$CALX_PATH` (the value of `CALX_PATH` environment variable).If `$CALX_PATH` was not defined or was empty, throws.
If `s` contains a prohibited character (including `/`, `.`, `\0`), throws.
### `NextKey`
`NextKey(d,k)`, where `d` is a dict and `k` is either string or nil, returns the "next" key
after `k` (or, if `k` is nil, the "first" key) in dict `d`; or, if there is no such ("next"/"first")
key, returns `nil`.The total order on keys is defined on any version of a dict; it may potentially be changed every
time a dict is mutated.### `RemoveKey`
`RemoveKey(d,k)`, where `d` is a dict and `k` is a string, removes the entry with key `k` from `d`,
if any.### `ToNumber`
`ToNumber(s)`, where `s` is a string, parses `s` as a decimal number and returns the result.
Throws if the string cannot be parsed as decimal number.
### `Encode`
`Encode(x,b)` is equivalent to `Encode(x,b,0)`.
`Encode(x,b,n)`, where:
* `x` is a number;
* `b` is integer number such that `2 <= b <= 36`;
* `n` is non-negative integer number,returns the string representation of `x` in base `b` with `n` digits in the fractional part.
Note that not any decimal number has finite representation in any base; see, for example,
`Encode(0.1, 3, 100)`.### `Decode`
`Decode(s,b)`, where:
* `s` is a string;
* `b` is integer number such that `2 <= b <= 36`,parses `s` as a number in base `b`, truncating at `Scale()` decimal places (see the documentation
for the `Scale()` function).Throws if `s` cannot be parsed as number in base `b`.
Note that not any number in any base has finite decimal representation; see, for example,
`Decode("0.1", 3)`.### `NumDigits`
`NumDigits(x,s)`, where `x` is a number and `s` is a string, behaves in either of the following
ways, depending on the value of `s`:* If `s` is `"i"`, it returns the number of significant digits in the integer part of `x`.
* If `s` is `"f"`, it returns the number of significant digits in the fractional part of `x`.
* If `s` is `"+"`, it returns `NumDigits(x, "i") + NumDigits(x, "f")`.
* Otherwise, it throws.### `Wref`
`Wref(x)`, where `x` is a weakrefable value (currently, either list or dict value), returns a new
weak reference to `x`.### `Wvalue`
`Wvalue(w)`, where `w` is a weak reference, returns the value behind the reference, or, if the value
has been garbage collected, returns `nil`.### `Clock`
`Clock()` returns time, in seconds, since some fixed point in the past (before the start of the
program).### `UpScale`
`UpScale(x,n)`, where `x` is a number and `n` is non-negative integer number, returns `x*(10**n)`.
### `DownScale`
`DownScale(x,n)`, where `x` is a number and `n` is non-negative integer number, returns `x/(10**n)`.
### `trunc`
`trunc(x)`, where `x` is a number, truncates the fractiotal part of `x`; in other words, it rounds
it towards zero.### `floor`
`floor(x)`, where `x` is a number, rounds `x` towards negative infinity.
### `ceil`
`ceil(x)`, where `x` is a number, rounds `x` away from zero (towards infinity whose sign corresponds
to the sign of `x`).### `round`
`round(x)`, where `x` is a number, rounds `x` to the nearest, ties away from zero.
### `frac`
`frac(x)`, where `x` is a number, returns the fractional part of `x`. Formally, for
non-negative `x`, it returns `x - trunc(x)`; for negative `x`, it returns `x + trunc(x)`.### `ToString`
The behavior of `ToString(x)` is equivalent to that of the special function `TO_STRING(x)`; see the
section on special functions for more information.### `Assert`
`Assert(cond)` throws if `!cond`.
### `abs`
`abs(x)`, where `x` is a number, returns the absolute value of `x`.
### `mod`
`mod(x,y)`, where `x` and `y` are integer numbers, `y > 0`, returns the
“canonical” representation of x modulo y: the integer in `[0; y)` congruent to `x` modulo `y`.### `div_ceil`
`div_ceil(a,b)`, where `a`,`b` are non-negative integers, `b` is non-zero, returns
`a//b` if `(a%b)==0`, otherwise it returns `a//b + 1`.### `fact`
`fact(n)`, where `n` is non-negative integer number, returns the factorial of `n`.
### `choice`
`choice(n,k)`, where `n` and `k` are non-negative integer numbers, returns `C(n,k)`.
### `fdiv`
`fdiv(x,y)`, where `x` and `y` are numbers, returns `trunc(x / y)`.
### `fmod`
`fmod(x,y)`, where `x` and `y` are numbers, returns `x - y * trunc(x / y)`.
### `gcd`
`gcd(u,v)`, where `u` and `v` are integer numbers, returns the greatest common divisor of `u` and `v`.
### `lcm`
`lcm(u,v)`, where `u` and `v` are integer numbers, returns the least common multiple of `u` and `v`.
### `mod_pow`
`mod_pow(b,e,m)`, where `b`,`e`,`m` are non-negative integers, `m` is non-zero, returns `(b**e)%m`.
### `random_bits`
`random_bits(n)`, where `n` is non-negative integer, returns a random number in `[0; 2**n-1]`.
### `random_mod`
`random_mod(n)`, where `n` is positive integer, returns a random number in `[0; n-1]`.
### `random_range`
`random_range(lb,rb)`, where `lb`,`rb` are integers, `lb=2`,
returns the `n`-th root of `x`, rounded down, with precision
specified by the current scale (see the documentation on the `Scale()` function).If `n` is even and `x` is negative, it throws.
### `sqrt`
`sqrt(x)` is equivalent to `nth_root(x,2)`.
### `cbrt`
`cbrt(x)` is equivalent to `nth_root(x,3)`.