Builtin functions
The core namespace is not an actual module but refers to the set of builtin functions and properties available to ucode
scripts.
Methods
arrtoip(arr) → {string}nullable
Convert the given input array of byte values to an IP address string.
Input arrays of length 4 are converted to IPv4 addresses, arrays of length 16 to IPv6 ones. All other lengths are rejected. If any array element is not an integer or exceeds the range 0..255 (inclusive), the array is rejected.
Returns a string containing the formatted IP address. Returns null
if the input array was invalid.
Name | Type | Description |
---|---|---|
arr | number[] | The byte array to convert into an IP address string. |
arrtoip([ 192, 168, 1, 1 ]) // "192.168.1.1"
arrtoip([ 254, 128, 0, 0, 0, 0, 0, 0, 252, 84, 0, 255, 254, 130, 171, 189 ])
// "fe80::fc54:ff:fe82:abbd"
arrtoip([ 1, 2, 3]) // null (invalid length)
arrtoip([ 1, "2", -5, 300 ]) // null (invalid values)
arrtoip("123") // null (not an array)
assert(cond, messageopt)
Raise an exception with the given message parameter when the value in cond
is not truish.
When message
is omitted, the default value is Assertion failed
.
Name | Type | Description |
---|---|---|
cond | * | The value to check for truthiness. |
message | string | (optional) The message to include in the exception. |
When the condition is falsy.
assert(true, "This is true"); // No exception is raised
assert(false); // Exception is raised with the default message "Assertion failed"
b64dec(str) → {string}nullable
Decodes the given base64 encoded string and returns the decoded result.
- If non-whitespace, non-base64 characters are encountered, if invalid padding or trailing garbage is found, the function returns
null
. - If a non-string argument is given, the function returns
null
.
Name | Type | Description |
---|---|---|
str | string | The base64 encoded string to decode. |
b64dec("VGhpcyBpcyBhIHRlc3Q="); // Returns "This is a test"
b64dec(123); // Returns null
b64dec("XXX"); // Returns null
b64enc(str) → {string}nullable
Encodes the given string into base64 and returns the resulting string.
- If a non-string argument is given, the function returns
null
.
Name | Type | Description |
---|---|---|
str | string | The string to encode. |
b64enc("This is a test"); // Returns "VGhpcyBpcyBhIHRlc3Q="
b64enc(123); // Returns null
call(fn, ctxopt, scopeopt, …argopt) → {*}
Calls the given function value with a modified environment.
The given ctx
argument is used as this
context for the invoked function and the given scope
value as global environment. Any further arguments are passed to the invoked function as-is.
When ctx
is omitted or null
, the function will get invoked with this
being null
.
When scope
is omitted or null
, the function will get executed with the current global environment of the running program. When scope
is set to a dictionary, the dictionary is used as global function environment.
When the scope
dictionary has no prototype, the current global environment will be set as prototype, means the scope will inherit from it.
When a scope prototype is set, it is kept. This allows passing an isolated (sandboxed) function scope without access to the global environment.
Any further argument is forwarded as-is to the invoked function as function call argument.
Returns null
if the given function value fn
is not callable.
Returns the return value of the invoked function in all other cases.
Forwards exceptions thrown by the invoked function.
Name | Type | Description |
---|---|---|
fn | function | Function value to call. |
ctx | * | (optional, default: null )
|
scope | Object | (optional, default: null )Global environment for the invoked function. |
arg | * | (optional, repeatable) Additional arguments to pass to the invoked function. |
// Override this context
call(function() { printf("%J\n", this) }); // null
call(function() { printf("%J\n", this) }, null); // null
call(function() { printf("%J\n", this) }, { x: 1 }); // { "x": 1 }
call(function() { printf("%J\n", this) }, { x: 2 }); // { "x": 2 }
// Run with default scope
global.a = 1;
call(function() { printf("%J\n", a) }); // 1
// Override scope, inherit from current global scope (implicit)
call(function() { printf("%J\n", a) }, null, { a: 2 }); // 2
// Override scope, inherit from current global scope (explicit)
call(function() { printf("%J\n", a) }, null,
proto({ a: 2 }, global)); // 2
// Override scope, don't inherit (pass `printf()` but not `a`)
call(function() { printf("%J\n", a) }, null,
proto({}, { printf })); // null
// Forward arguments
x = call((x, y, z) => x * y * z, null, null, 2, 3, 4); // x = 24
chr(…n1) → {string}
Converts each given numeric value to a byte and return the resulting string. Invalid numeric values or values < 0 result in \0
bytes, values larger than 255 are truncated to 255.
Returns a new strings consisting of the given byte values.
Name | Type | Description |
---|---|---|
n1 | number | (repeatable) The numeric values. |
chr(65, 98, 99); // "Abc"
chr(-1, 300); // string consisting of an `0x0` and a `0xff` byte
clock(monotonicopt) → {number[]}nullable
Reads the current second and microsecond value of the system clock.
By default, the realtime clock is queried which might skew forwards or backwards due to NTP changes, system sleep modes etc. If a truish value is passed as argument, the monotonic system clock is queried instead, which will return the monotonically increasing time since some arbitrary point in the past (usually the system boot time).
Returns a two element array containing the full seconds as the first element and the nanosecond fraction as the second element.
Returns null
if a monotonic clock value is requested and the system does not implement this clock type.
Name | Type | Description |
---|---|---|
monotonic | boolean | (optional) Whether to query the monotonic system clock. |
clock(); // [ 1647954926, 798269464 ]
clock(true); // [ 474751, 527959975 ]
die(msg)
Raise an exception with the given message and abort execution.
Name | Type | Description |
---|---|---|
msg | string | The error message. |
The error with the given message.
die(msg);
exists(obj, key) → {boolean}
Check whether the given key exists within the given object value.
Returns true
if the given key is present within the object passed as the first argument, otherwise false
.
Name | Type | Description |
---|---|---|
obj | Object | The input object. |
key | string | The key to check for existence. |
let x = { foo: true, bar: false, qrx: null };
exists(x, 'foo'); // true
exists(x, 'qrx'); // true
exists(x, 'baz'); // false
exit(n)
Terminate the interpreter with the given exit code.
This function does not return.
Name | Type | Description |
---|---|---|
n | number | The exit code. |
exit();
exit(5);
filter(arr, fn) → {Array}
Filter the array passed as the first argument by invoking the function specified in the second argument for each array item.
If the invoked function returns a truthy result, the item is retained, otherwise, it is dropped. The filter function is invoked with three arguments:
- The array value
- The current index
- The array being filtered
(Note that the map
function behaves similarly to filter
with respect to its fn
parameters.)
Returns a new array containing only retained items, in the same order as the input array.
Name | Type | Description |
---|---|---|
arr | Array | The input array. |
fn | function | The filter function. |
// filter out any empty string:
a = filter(["foo", "", "bar", "", "baz"], length)
// a = ["foo", "bar", "baz"]
// filter out any non-number type:
a = filter(["foo", 1, true, null, 2.2], function(v) {
return (type(v) == "int" || type(v) == "double");
});
// a = [1, 2.2]
gc(operationopt, argumentopt) → {boolean|number}nullable
Interacts with the mark and sweep garbage collector of the running ucode virtual machine.
Depending on the given operation
string argument, the meaning of argument
and the function return value differs.
The following operations are defined:
collect
- Perform a complete garbage collection cycle, returnstrue
.start
- (Re-)start periodic garbage collection,argument
is an optional integer in the range1..65535
specifying the interval. Defaults to1000
if omitted. Returnstrue
if the periodic GC was previously stopped and is now started or if the interval changed. Returnsfalse
otherwise.stop
- Stop periodic garbage collection. Returnstrue
if the periodic GC was previously started and is now stopped,false
otherwise.count
- Count the amount of active complex object references in the VM context, returns the counted amount.
If the operation
argument is omitted, the default is collect
.
Name | Type | Description |
---|---|---|
operation | string | (optional) The operation to perform. |
argument | * | (optional) The argument for the operation. |
gc(); // true
gc("start"); // true
gc("count"); // 42
getenv(nameopt) → {string|Object<string: string>}
Query an environment variable or then entire environment.
Returns the value of the given environment variable, or - if omitted - a dictionary containing all environment variables.
Name | Type | Description |
---|---|---|
name | string | (optional) The name of the environment variable. |
gmtime(epochopt) → {TimeSpec}
Like localtime()
but interpreting the given epoch value as UTC time.
See localtime() for details on the return value.
Name | Type | Description |
---|---|---|
epoch | number | (optional) The epoch timestamp. |
gmtime(1647953502);
// Returns:
// {
// sec: 42,
// min: 51,
// hour: 13,
// mday: 22,
// mon: 3,
// year: 2022,
// wday: 2,
// yday: 81,
// isdst: 0
// }
hex(x) → {number}
Converts the given hexadecimal string into a number.
Returns the resulting integer value or NaN
if the input value cannot be interpreted as hexadecimal number.
Name | Type | Description |
---|---|---|
x | * | The hexadecimal string to be converted. |
hexdec(hexstring, skipcharsopt) → {string}nullable
Decodes the given hexadecimal digit string into a byte string, optionally skipping specified characters.
If the characters to skip are not specified, a default of " \t\n"
is used.
Returns null if the input string contains invalid characters or an uneven amount of hex digits.
Returns the decoded byte string on success.
Name | Type | Description |
---|---|---|
hexstring | string | The hexadecimal digit string to decode. |
skipchars | string | (optional) The characters to skip during decoding. |
hexdec("48656c6c6f20776f726c64210a"); // "Hello world!\n"
hexdec("44:55:66:77:33:44", ":"); // "DUfw3D"
hexenc(val) → {string}
Encodes the given byte string into a hexadecimal digit string, converting the input value to a string if needed.
Name | Type | Description |
---|---|---|
val | string | The byte string to encode. |
hexenc("Hello world!\n"); // "48656c6c6f20776f726c64210a"
include(path, scopeopt)
Evaluate and include the file at the given path and optionally override the execution scope with the given scope object.
By default, the file is executed within the same scope as the calling include()
, but by passing an object as the second argument, it is possible to extend the scope available to the included file.
This is useful to supply additional properties as global variables to the included code. To sandbox included code, that is giving it only access to explicitly provided properties, the proto()
function can be used to create a scope object with an empty prototype.
Name | Type | Description |
---|---|---|
path | string | The path to the file to be included. |
scope | Object | (optional) The optional scope object to override the execution scope. |
// Load and execute "foo.uc" immediately
include("./foo.uc")
// Execute the "supplemental.ucode" in an extended scope and make the "foo"
// and "bar" properties available as global variables
include("./supplemental.uc", {
foo: true,
bar: 123
})
// Execute the "untrusted.ucode" in a sandboxed scope and make the "foo" and
// "bar" variables as well as the "print" function available to it.
// By assigning an empty prototype object to the scope, included code has no
// access to other global values anymore.
include("./untrusted.uc", proto({
foo: true,
bar: 123,
print: print
}, {}))
index(arr_or_str, needle) → {number}nullable
Finds the given value passed as the second argument within the array or string specified in the first argument.
Returns the first matching array index or first matching string offset or -1
if the value was not found.
Returns null
if the first argument was neither an array nor a string.
Name | Type | Description |
---|---|---|
arr_or_str | Array | | The array or string to search for the value. |
needle | * | The value to find within the array or string. |
index("Hello hello hello", "ll") // 2
index([ 1, 2, 3, 1, 2, 3, 1, 2, 3 ], 2) // 1
index("foo", "bar") // -1
index(["Red", "Blue", "Green"], "Brown") // -1
index(123, 2) // null
int(x, baseopt) → {number}
Converts the given value to an integer, using an optional base.
Returns NaN
if the value is not convertible.
Name | Type | Description |
---|---|---|
x | * | The value to be converted to an integer. |
base | int | (optional) The base into which the value is to be converted, the default is 10. Note that the base parameter is ignored if the |
int("123") // Returns 123
int("123", 10) // 123
int("10 or more") // 10
int("12.3") // 12
int("123", 7) // 66
int("abc", 16) // 2748
int("xyz", 36) // 44027
int(10.10, "2") // 10, the invalid base is ignored
int("xyz", 16) // NaN, bad value
int("1010", "2") // NaN, bad base
iptoarr(address) → {number[]}nullable
Convert the given IP address string to an array of byte values.
IPv4 addresses result in arrays of 4 integers while IPv6 ones in arrays containing 16 integers. The resulting array can be turned back into IP address strings using the inverse arrtoip()
function.
Returns an array containing the address byte values. Returns null
if the given argument is not a string or an invalid IP.
Name | Type | Description |
---|---|---|
address | string | The IP address string to convert. |
iptoarr("192.168.1.1") // [ 192, 168, 1, 1 ]
iptoarr("fe80::fc54:ff:fe82:abbd") // [ 254, 128, 0, 0, 0, 0, 0, 0, 252, 84,
// 0, 255, 254, 130, 171, 189 ])
iptoarr("foo") // null (invalid address)
iptoarr(123) // null (not a string)
join(sep, arr) → {string}nullable
Joins the array passed as the second argument into a string, using the separator passed in the first argument as glue.
Returns null
if the second argument is not an array.
Name | Type | Description |
---|---|---|
sep | string | The separator to be used in joining the array elements. |
arr | Array | The array to be joined into a string. |
json(str_or_resource) → {*}
Parse the given string or resource as JSON and return the resulting value.
If the input argument is a plain string, it is directly parsed as JSON.
If an array, object or resource value is given, this function will attempt to invoke a read()
method on it to read chunks of input text to incrementally parse as JSON data. Reading will stop if the object's read()
method returns either null
or an empty string.
Throws an exception on parse errors, trailing garbage, or premature EOF.
Returns the parsed JSON data.
Name | Type | Description |
---|---|---|
str_or_resource | string | The string or resource object to be parsed as JSON. |
json('{"a":true, "b":123}') // { "a": true, "b": 123 }
json('[1,2,') // Throws an exception
import { open } from 'fs';
let fd = open('example.json', 'r');
json(fd); // will keep invoking `fd.read()` until EOF and
// incrementally parse each read chunk.
let x = proto(
[ '{"foo":', 'true, ', '"bar":', 'false}' ],
{ read: function() { return shift(this) } }
);
json(x); // will keep invoking `x.read()` until array
// is empty incrementally parse each piece
keys(obj) → {Array}nullable
Enumerates all object key names.
Returns an array of all key names present in the passed object. Returns null
if the given argument is not an object.
Name | Type | Description |
---|---|---|
obj | object | The object from which to retrieve the key names. |
lc(s) → {string}nullable
Convert the given string to lowercase and return the resulting string.
Returns null
if the given argument could not be converted to a string.
Name | Type | Description |
---|---|---|
s | string | The input string. |
The lowercase string.
lc("HeLLo WoRLd!"); // "hello world!"
length(x) → {number}nullable
Determine the length of the given object, array or string.
Returns the length of the given value.
- For strings, the length is the amount of bytes within the string
- For arrays, the length is the amount of array elements
- For objects, the length is defined as the amount of keys
Returns null
if the given argument is not an object, array or string.
Name | Type | Description |
---|---|---|
x | Object | | The input object, array, or string. |
- The length of the input.
length("test") // 4
length([true, false, null, 123, "test"]) // 5
length({foo: true, bar: 123, baz: "test"}) // 3
length({}) // 0
length(true) // null
length(10.0) // null
loadfile(path, optionsopt) → {function}
Compiles the given file into a ucode program and returns the resulting program entry function.
See loadstring()
for details.
Returns the compiled program entry function.
Throws an exception on compilation or file I/O errors.
Name | Type | Description |
---|---|---|
path | string | The path of the file to compile. |
options | ParseConfig | (optional) The options for compilation. |
loadfile("./templates/example.uc"); // function main() { ... }
loadstring(code, optionsopt) → {function}
Compiles the given code string into a ucode program and returns the resulting program entry function.
The optional options
dictionary overrides parse and compile options.
- If a non-string
code
argument is given, it is implicitly converted to a string value first. - If
options
is omitted or a non-object value, the compile options of the running ucode program are reused.
See ParseConfig for known keys within the options
object. Unrecognized keys are ignored, unspecified options default to those of the running program.
Returns the compiled program entry function.
Throws an exception on compilation errors.
Name | Type | Description |
---|---|---|
code | string | The code string to compile. |
options | ParseConfig | (optional) The options for compilation. |
let fn1 = loadstring("Hello, {{ name }}", { raw_mode: false });
global.name = "Alice";
fn1(); // prints `Hello, Alice`
let fn2 = loadstring("return 1 + 2;", { raw_mode: true });
fn2(); // 3
localtime(epochopt) → {TimeSpec}
Return the given epoch timestamp (or now, if omitted) as a dictionary containing broken-down date and time information according to the local system timezone.
See TimeSpec for a description of the fields.
Note that in contrast to the underlying localtime(3)
C library function, the values for mon
, wday
, and yday
are 1-based, and the year
is 1900-based.
Name | Type | Description |
---|---|---|
epoch | number | (optional) The epoch timestamp. |
localtime(1647953502);
// Returns:
// {
// sec: 42,
// min: 51,
// hour: 13,
// mday: 22,
// mon: 3,
// year: 2022,
// wday: 2,
// yday: 81,
// isdst: 0
// }
ltrim(s, copt) → {string}
Trim any of the specified characters from the start of the string. If the second argument is omitted, trims the characters (space), '\t', '\r', and '\n'.
Returns the left trimmed string.
Name | Type | Description |
---|---|---|
s | string | The input string. |
c | string | (optional) The characters to trim. |
ltrim(" foo \n") // "foo \n"
ltrim("--bar--", "-") // "bar--"
map(arr, fn) → {Array}
Transform the array passed as the first argument by invoking the function specified in the second argument for each array item.
The mapping function is invoked with three arguments (see examples, below, for some possibly counterintuitive usage):
- The array value
- The current index
- The array being filtered
(Note that the filter
function behaves similarly to map
with respect to its fn
parameters.)
Returns a new array of the same length as the input array containing the transformed values.
Name | Type | Description |
---|---|---|
arr | Array | The input array. |
fn | function | The mapping function. |
// turn into an array of string lengths:
a = map(["Apple", "Banana", "Bean"], length);
// a = [5, 6, 4]
// map to type names:
a = map(["foo", 1, true, null, 2.2], type);
// a = ["string", "int", "bool", null, "double"]
// attempt to naively use built-in 'int' to map an array:
a = map(["x", "2", "11", "7"], int)
// a = [NaN, NaN, 3, NaN]
//
// This is a direct result of 'int' being provided the second, index parameter
// for its base value in the conversion.
//
// The resulting calls to 'int' are as follows:
// int("x", 0, [...]) - convert "x" to base 0, 'int' ignores the third value
// int("2", 1, [...]) - convert "2" to base 1, digit out of range, so NaN
// int("11", 2, [...]) - convert "11" to base 2, produced unexpected 3
// int("7", 3, [...]) - convert "7" to base 3, digit out of range, NaN again
// remedy this by using an arrow function to ensure the proper base value
// (in this case, the default of 10) is passed to 'int':
a = map(["x", "2", "1", "7"], (x) => int(x))
// a = [NaN, 2, 1, 7]
// convert base-2 values:
a = map(["22", "1010", "0001", "0101"], (x) => int(x, 2))
// a = [NaN, 10, 1, 5]
match(str, pattern) → {Array}nullable
Match the given string against the regular expression pattern specified as the second argument.
If the passed regular expression uses the g
flag, the return value will be an array of arrays describing all found occurrences within the string.
Without the g
modifier, an array describing the first match is returned.
Returns null
if the pattern was not found within the given string.
Name | Type | Description |
---|---|---|
str | string | The string to be matched against the pattern. |
pattern | RegExp | The regular expression pattern. |
match("foobarbaz", /b.(.)/) // ["bar", "r"]
match("foobarbaz", /b.(.)/g) // [["bar", "r"], ["baz", "z"]]
max(…valopt) → {*}
Return the largest value among all parameters passed to the function.
Name | Type | Description |
---|---|---|
val | * | (optional, repeatable) The values to compare. |
max(5, 2.1, 3, "abc", 0.3); // Returns 5
max(1, "abc"); // Returns 1 (!)
max("1", "abc"); // Returns "abc"
max("def", "abc", "ghi"); // Returns "ghi"
max(true, false); // Returns true
min(…valopt) → {*}
Return the smallest value among all parameters passed to the function.
Name | Type | Description |
---|---|---|
val | * | (optional, repeatable) The values to compare. |
min(5, 2.1, 3, "abc", 0.3); // Returns 0.3
min(1, "abc"); // Returns 1
min("1", "abc"); // Returns "1"
min("def", "abc", "ghi"); // Returns "abc"
min(true, false); // Returns false
ord(s, offsetopt) → {number}nullable
Without further arguments, this function returns the byte value of the first character in the given string.
If an offset argument is supplied, the byte value of the character at this position is returned. If an invalid index is supplied, the function will return null
. Negative index entries are counted towards the end of the string, e.g. -2
will return the value of the second last character.
Returns the byte value of the character. Returns null
if the offset is invalid or if the input is not a string.
Name | Type | Description |
---|---|---|
s | string | The input string. |
offset | number | (optional) The offset of the character. |
ord("Abc"); // 65
ord("Abc", 0); // 65
ord("Abc", 1); // 98
ord("Abc", 2); // 99
ord("Abc", 10); // null
ord("Abc", -10); // null
ord("Abc", "nan"); // null
pop(arr) → {*}
Pops the last item from the given array and returns it.
Returns null
if the array was empty or if a non-array argument was passed.
Name | Type | Description |
---|---|---|
arr | Array | The input array. |
let x = [ 1, 2, 3 ];
pop(x); // 3
print(x, "\n"); // [ 1, 2 ]
print(…values) → {number}
Print any of the given values to stdout.
The print()
function writes a string representation of each given argument to stdout and returns the amount of bytes written.
String values are printed as-is, integer and double values are printed in decimal notation, boolean values are printed as true
or false
while arrays and objects are converted to their JSON representation before being written to the standard output. The null
value is represented by an empty string so print(null)
would print nothing. Resource values are printed in the form <type address>
, e.g. <fs.file 0x7f60f0981760>
.
If resource, array or object values contain a tostring()
function in their prototypes, then this function is invoked to obtain an alternative string representation of the value.
Examples:
print(1 != 2); // Will print 'true'
print(0xff); // Will print '255'
print(2e3); // Will print '2000'
print(null); // Will print nothing
print({ hello: true, world: 123 }); // Will print '{ "hello": true, "world": 123 }'
print([1,2,3]); // Will print '[ 1, 2, 3 ]'
print(proto({ foo: "bar" }, // Will print 'MyObj'
{ tostring: () => "MyObj" })); // instead of '{ "foo": "bar" }'
Returns the amount of bytes printed.
Name | Type | Description |
---|---|---|
values | * | (repeatable) Arbitrary values to print |
printf(fmt, …Arguments) → {number}
Formats the given arguments according to the given format string and outputs the result to stdout.
Ucode supports a restricted subset of the formats allowed by the underlying libc's printf()
implementation, namely it allows the d
, i
, o
, u
, x
, X
, e
, E
, f
, F
, g
, G
, c
and s
conversions.
Additionally, an ucode specific J
format is implemented, which causes the corresponding value to be formatted as JSON string. By prefixing the J
format letter with a precision specifier, the resulting JSON output will be pretty printed. A precision of 0
will use tabs for indentation, any other positive precision will use that many spaces for indentation while a negative or omitted precision specifier will turn off pretty printing.
Other format specifiers such as n
or z
are not accepted and returned verbatim. Format specifiers including *
directives are rejected as well.
Returns the number of bytes written to the standard output.
Name | Type | Description |
---|---|---|
fmt | string | The format string. |
Arguments | * | (repeatable) to be formatted. |
{%
printf("Hello %s\n", "world"); // Hello world
printf("%08x\n", 123); // 0000007b
printf("%c%c%c\n", 65, 98, 99); // Abc
printf("%g\n", 10 / 3.0); // 3.33333
printf("%2$d %1$d\n", 12, 34); // 34 12
printf("%J", [1,2,3]); // [ 1, 2, 3 ]
printf("%.J", [1,2,3]);
// [
// 1,
// 2,
// 3
// ]
printf("%.2J", [1,2,3]);
// [
// 1,
// 2,
// 3
// ]
%}
proto(val, protoopt) → {Object}nullable
Get or set the prototype of the array or object value val
.
When invoked without a second argument, the function returns the current prototype of the value in val
or null
if there is no prototype or if the given value is neither an object nor an array.
When invoked with a second prototype argument, the given proto
value is set as the prototype on the array or object in val
.
Throws an exception if the given prototype value is not an object.
Name | Type | Description |
---|---|---|
val | Array | | The array or object value. |
proto | Object | (optional) The optional prototype object. |
const arr = [1, 2, 3];
proto(arr); // Returns the current prototype of the array (null by default)
proto(arr, { foo: true }); // Sets the given object as the prototype of the array
push(arr, …valuesopt) → {*}
Pushes the given argument(s) to the given array.
Returns the last pushed value.
Name | Type | Description |
---|---|---|
arr | Array | The array to push values to. |
values | * | (optional, repeatable) The values to push. |
let x = [ 1, 2, 3 ];
push(x, 4, 5, 6); // 6
print(x, "\n"); // [ 1, 2, 3, 4, 5, 6 ]
regexp(source, flagsopt) → {RegExp}
Construct a regular expression instance from the given source
pattern string and any flags optionally specified by the flags
argument.
- Throws a type error exception if
flags
is not a string or if the string inflags
contains unrecognized regular expression flag characters. - Throws a syntax error when the pattern in
source
cannot be compiled into a valid regular expression.
Returns the compiled regular expression value.
Name | Type | Description |
---|---|---|
source | string | The pattern string. |
flags | string | (optional) The optional regular expression flags. |
regexp('foo.*bar', 'is'); // equivalent to /foo.*bar/is
regexp('foo.*bar', 'x'); // throws a "Type error: Unrecognized flag character 'x'" exception
regexp('foo.*('); // throws a "Syntax error: Unmatched ( or \( exception"
render(path_or_func, scope_or_fnarg1opt, fnarg2opt, …fnargNopt) → {string}
When invoked with a string value as the first argument, the function acts like include()
but captures the output of the included file as a string and returns the captured contents.
The second argument is treated as the scope.
When invoked with a function value as the first argument, render()
calls the given function and passes all subsequent arguments to it.
Any output produced by the called function is captured and returned as a string. The return value of the called function is discarded.
Name | Type | Description |
---|---|---|
path_or_func | string | | The path to the file or the function to be rendered. |
scope_or_fnarg1 | Object | | (optional) The optional scope or the first argument for the function. |
fnarg2 | * | (optional) The second argument for the function. |
fnargN | * | (optional, repeatable) Additional arguments for the function. |
// Renders template file with given scope and captures the output as a string
const output = render("./template.uc", { foo: "bar" });
// Calls a function, captures the output, and returns it as a string
const result = render(function(name) {
printf("Hello, %s!\n", name);
}, "Alice");
replace(str, pattern, replace, limitopt) → {string}
Replace occurrences of the specified pattern in the string passed as the first argument.
- The pattern value may be either a regular expression or a plain string.
- The replace value may be a function which is invoked for each found pattern or any other value which is converted into a plain string and used as replacement.
- When an optional limit is specified, substitutions are performed only that many times.
- If the pattern is a regular expression and not using the
g
flag, then only the first occurrence in the string is replaced. - If the
g
flag is used or if the pattern is not a regular expression, all occurrences are replaced. - If the replace value is a callback function, it is invoked with the found substring as the first and any capture group values as subsequent parameters.
- If the replace value is a string, specific substrings are substituted before it is inserted into the result.
Returns a new string with the pattern replaced.
Name | Type | Description |
---|---|---|
str | string | The string in which to replace occurrences. |
pattern | RegExp | | The pattern to be replaced. |
replace | function | | The replacement value. |
limit | number | (optional) The optional limit of substitutions. |
replace("barfoobaz", /(f)(o+)/g, "[$$|$`|$&|$'|$1|$2|$3]") // bar[$|bar|foo|baz|f|oo|$3]baz
replace("barfoobaz", /(f)(o+)/g, uc) // barFOObaz
replace("barfoobaz", "a", "X") // bXrfoobXz
replace("barfoobaz", /(.)(.)(.)/g, function(m, c1, c2, c3) {
return c3 + c2 + c1;
}) // raboofzab
replace("aaaaa", "a", "x", 3) // xxxaa
replace("foo bar baz", /[ao]/g, "x", 3) // fxx bxr baz
require(name) → {*}
Load and evaluate ucode scripts or shared library extensions.
The require()
function expands each member of the global REQUIRE_SEARCH_PATH
array to a filesystem path by replacing the *
placeholder with a slash-separated version of the given dotted module name and subsequently tries to load a file at the resulting location.
If a file is found at one of the search path locations, it is compiled and evaluated or loaded via the C runtime's dlopen()
function, depending on whether the found file is a ucode script or a compiled dynamic library.
The resulting program function of the compiled/loaded module is then subsequently executed with the current global environment, without a this
context and without arguments.
Finally, the return value of the invoked program function is returned back by require()
to the caller.
By default, modules are cached in the global modules
dictionary and subsequent attempts to require the same module will return the cached module dictionary entry without re-evaluating the module.
To force reloading a module, the corresponding entry from the global modules
dictionary can be deleted.
To preload a module or to provide a "virtual" module without a corresponding filesystem resource, an entry can be manually added to the global modules
dictionary.
Summarized, the require()
function can be roughly described by the following code:
function require(name) {
if (exists(modules, name))
return modules[name];
for (const item in REQUIRE_SEARCH_PATH) {
const modpath = replace(item, '*', replace(name, '.', '/'));
const entryfunc = loadfile(modpath, { raw_mode: true });
if (entryfunc) {
const modval = entryfunc();
modules[name] = modval;
return modval;
}
}
die(`Module ${name} not found`);
}
Due to the fact that require()
is a runtime operation, module source code is only lazily evaluated/loaded upon invoking the first require invocation, which might lead to situations where errors in module sources are only reported much later throughout the program execution. Unless runtime loading of modules is absolutely required, e.g. to conditionally load extensions, the compile time import
syntax should be preferred.
Returns the module value (typically an object) on success.
Throws an exception if the module function threw an exception.
Throws an exception if no matching module could be found, if the module contains syntax errors or upon other I/O related problems.
Name | Type | Description |
---|---|---|
name | string | The name of the module to require in dotted notation. |
// Require the `example/acme.uc` or `example/acme.so` module
const acme = require('example.acme');
// Requiring the same name again will yield the cached instance
const acme2 = require('example.acme');
assert(acme === acme2);
// Deleting the module dictionary entry will force a reload
delete modules['example.acme'];
const acme3 = require('example.acme');
assert(acme !== acme3);
// Preloading a "virtual" module
modules['example.test'] = {
hello: function() { print("This is the example module\n"); }
};
const test = require('example.test');
test.hello(); // will print "This is the example module"
reverse(arr_or_str) → {Array|string}nullable
Reverse the order of the given input array or string.
If an array is passed, returns the array in reverse order. If a string is passed, returns the string with the sequence of the characters reversed.
Returns the reversed array or string. Returns null
if neither an array nor a string were passed.
Name | Type | Description |
---|---|---|
arr_or_str | Array | | The input array or string. |
reverse([1, 2, 3]); // [ 3, 2, 1 ]
reverse("Abc"); // "cbA"
rindex(arr_or_str, needle) → {number}nullable
Finds the given value passed as the second argument within the array or string specified in the first argument.
Returns the last matching array index or last matching string offset or -1
if the value was not found.
Returns null
if the first argument was neither an array nor a string.
Name | Type | Description |
---|---|---|
arr_or_str | Array | | The array or string to search for the value. |
needle | * | The value to find within the array or string. |
rindex("Hello hello hello", "ll") // 14
rindex([ 1, 2, 3, 1, 2, 3, 1, 2, 3 ], 2) // 7
rindex("foo", "bar") // -1
rindex(["Red", "Blue", "Green"], "Brown") // -1
rindex(123, 2) // null
rtrim(str, copt) → {string}
Trim any of the specified characters from the end of the string. If the second argument is omitted, trims the characters (space), '\t', '\r', and '\n'.
Returns the right trimmed string.
Name | Type | Description |
---|---|---|
str | string | The input string. |
c | string | (optional) The characters to trim. |
rtrim(" foo \n") // " foo"
rtrim("--bar--", "-") // "--bar"
shift(arr) → {*}
Pops the first item from the given array and returns it.
Returns null
if the array was empty or if a non-array argument was passed.
Name | Type | Description |
---|---|---|
arr | Array | The array from which to pop the first item. |
let x = [ 1, 2, 3 ];
shift(x); // 1
print(x, "\n"); // [ 2, 3 ]
signal(signal, handleropt) → {function|string}
Set or query process signal handler function.
When invoked with two arguments, a signal specification and a signal handler value, this function configures a new process signal handler.
When invoked with one argument, a signal specification, this function returns the currently configured handler for the given signal.
The signal specification might either be an integer signal number or a string value containing a signal name (with or without "SIG" prefix). Signal names are treated case-insensitively.
The signal handler might be either a callable function value or one of the two special string values "ignore"
and "default"
. Passing "ignore"
will mask the given process signal while "default"
will restore the operating systems default behaviour for the given signal.
In case a callable handler function is provided, it is invoked at the earliest opportunity after receiving the corresponding signal from the operating system. The invoked function will receive a single argument, the number of the signal it is invoked for.
Note that within the ucode VM, process signals are not immediately delivered, instead the VM keeps track of received signals and delivers them to the ucode script environment at the next opportunity, usually before executing the next byte code instruction. This means that if a signal is received while performing a computationally expensive operation in C mode, such as a complex regexp match, the corresponding ucode signal handler will only be invoked after that operation concluded and control flow returns to the VM.
Returns the signal handler function or one of the special values "ignore"
or "default"
corresponding to the given signal specification.
Returns null
if an invalid signal spec or signal handler was provided.
Returns null
if changing the signal action failed, e.g. due to insufficient permission, or when attempting to ignore a non-ignorable signal.
Name | Type | Description |
---|---|---|
signal | number | | The signal to query/set handler for. |
handler | function | | (optional) The signal handler to install for the given signal. |
// Ignore signals
signal('INT', 'ignore'); // "ignore"
signal('SIGINT', 'ignore'); // "ignore" (equivalent to 'INT')
signal('sigterm', 'ignore'); // "ignore" (signal names are case insensitive)
signal(9, 'ignore'); // null (SIGKILL cannot be ignored)
// Restore signal default behavior
signal('INT', 'default'); // "default"
signal('foobar', 'default'); // null (unknown signal name)
signal(-313, 'default'); // null (invalid signal number)
// Set custom handler function
function intexit(signo) {
printf("I received signal number %d\n", signo);
exit(1);
}
signal('SIGINT', intexit); // returns intexit
signal('SIGINT') == intexit; // true
sleep(milliseconds) → {boolean}
Pause execution for the given amount of milliseconds.
Name | Type | Description |
---|---|---|
milliseconds | number | The amount of milliseconds to sleep. |
sleep(1000); // Sleeps for 1 second
slice(arr, offopt, endopt) → {Array}
Performs a shallow copy of a portion of the source array, as specified by the start and end offsets. The original array is not modified.
Returns a new array containing the copied elements, if any. Returns null
if the given source argument is not an array value.
Name | Type | Description |
---|---|---|
arr | Array | The source array to be copied. |
off | number | (optional) The index of the first element to copy. |
end | number | (optional) The index of the first element to exclude from the returned array. |
slice([1, 2, 3]) // [1, 2, 3]
slice([1, 2, 3], 1) // [2, 3]
slice([1, 2, 3], -1) // [3]
slice([1, 2, 3], -3, -1) // [1, 2]
slice([1, 2, 3], 10) // []
slice([1, 2, 3], 2, 1) // []
slice("invalid", 1, 2) // null
sort(arr, fnopt) → {Array}
Sort the given array according to the given sort function. If no sort function is provided, a default ascending sort order is applied.
The input array is sorted in-place, no copy is made.
The custom sort function is repeatedly called until the entire array is sorted. It will receive two values as arguments and should return a value lower than, larger than or equal to zero depending on whether the first argument is smaller, larger or equal to the second argument respectively.
Returns the sorted input array.
Name | Type | Description |
---|---|---|
arr | Array | The input array to be sorted. |
fn | function | (optional) The sort function. |
sort([8, 1, 5, 9]) // [1, 5, 8, 9]
sort(["Bean", "Orange", "Apple"], function(a, b) {
return length(a) - length(b);
}) // ["Bean", "Apple", "Orange"]
sourcepath(depthopt, dironlyopt) → {string}nullable
Determine the path of the source file currently being executed by ucode.
Name | Type | Description |
---|---|---|
depth | number | (optional, default: 0 )The depth to walk up the call stack. |
dironly | boolean | (optional) Whether to return only the directory portion of the source file path. |
sourcepath(); // Returns the path of the currently executed file
sourcepath(1); // Returns the path of the parent source file
sourcepath(2, true); // Returns the directory portion of the grandparent source file path
splice(arr, off, lenopt, …elementsopt) → {*}
Removes the elements designated by off
and len
from the given array, and replaces them with the additional arguments passed, if any.
The array grows or shrinks as necessary.
Returns the modified input array.
Name | Type | Description |
---|---|---|
arr | Array | The input array to be modified. |
off | number | The index to start removing elements. |
len | number | (optional) The number of elements to remove. |
elements | * | (optional, repeatable) The elements to insert. |
let x = [ 1, 2, 3, 4 ];
splice(x, 1, 2, "a", "b", "c"); // [ 1, "a", "b", "c", 4 ]
print(x, "\n"); // [ 1, "a", "b", "c", 4 ]
split(str, sep, limitopt) → {Array}
Split the given string using the separator passed as the second argument and return an array containing the resulting pieces.
If a limit argument is supplied, the resulting array contains no more than the given amount of entries, that means the string is split at most limit - 1
times total.
The separator may either be a plain string or a regular expression.
Returns a new array containing the resulting pieces.
Name | Type | Description |
---|---|---|
str | string | The input string to be split. |
sep | string | | The separator. |
limit | number | (optional) The limit on the number of splits. |
split("foo,bar,baz", ",") // ["foo", "bar", "baz"]
split("foobar", "") // ["f", "o", "o", "b", "a", "r"]
split("foo,bar,baz", /[ao]/) // ["f", "", ",b", "r,b", "z"]
split("foo=bar=baz", "=", 2) // ["foo", "bar=baz"]
sprintf(fmt, …Arguments) → {string}
Formats the given arguments according to the given format string.
See printf()
for details.
Returns the formatted string.
Name | Type | Description |
---|---|---|
fmt | string | The format string. |
Arguments | * | (repeatable) to be formatted. |
sprintf("Hello %s", "world"); // "Hello world"
sprintf("%08x", 123); // "0000007b"
sprintf("%c%c%c", 65, 98, 99); // "Abc"
sprintf("%g", 10 / 3.0); // "3.33333"
sprintf("%2$d %1$d", 12, 34); // "34 12"
sprintf("%J", [1,2,3]); // "[1,2,3]"
substr(str, off, lenopt) → {string}
Extracts a substring out of str
and returns it. First character is at offset zero.
- If
off
is negative, starts that far back from the end of the string. - If
len
is omitted, returns everything through the end of the string. - If
len
is negative, leaves that many characters off the string end.
Returns the extracted substring.
Name | Type | Description |
---|---|---|
str | string | The input string. |
off | number | The starting offset. |
len | number | (optional) The length of the substring. |
s = "The black cat climbed the green tree";
substr(s, 4, 5); // black
substr(s, 4, -11); // black cat climbed the
substr(s, 14); // climbed the green tree
substr(s, -4); // tree
substr(s, -4, 2); // tr
system(command, timeoutopt) → {number}
Executes the given command, waits for completion, and returns the resulting exit code.
The command argument may be either a string, in which case it is passed to /bin/sh -c
, or an array, which is directly converted into an execv()
argument vector.
- If the program terminated normally, a positive integer holding the program's
exit()
code is returned. - If the program was terminated by an uncaught signal, a negative signal number is returned.
- If the optional timeout argument is specified, the program is terminated by
SIGKILL
after that many milliseconds if it doesn't complete within the timeout.
Omitting the timeout argument or passing 0
disables the command timeout.
Returns the program exit code.
Name | Type | Description |
---|---|---|
command | string | | The command to be executed. |
timeout | number | (optional) The optional timeout in milliseconds. |
// Execute through `/bin/sh`
// prints "Hello world" to stdout and returns 3
system("echo 'Hello world' && exit 3");
// Execute argument vector
// prints the UNIX timestamp to stdout and returns 0
system(["/usr/bin/date", "+%s"]);
// Apply a timeout
// returns -9
system("sleep 3 && echo 'Success'", 1000);
time() → {number}
Returns the current UNIX epoch.
time(); // 1598043054
timegm(datetimespec) → {number}nullable
Like timelocal()
but interpreting the given date time specification as UTC time.
See timelocal() for details.
Name | Type | Description |
---|---|---|
datetimespec | TimeSpec | The broken-down date and time dictionary. |
timegm({ "sec": 42, "min": 51, "hour": 13, "mday": 22, "mon": 3, "year": 2022, "isdst": 0 });
// Returns 1647953502
timelocal(datetimespec) → {number}nullable
Performs the inverse operation of localtime() by taking a broken-down date and time dictionary and transforming it into an epoch value according to the local system timezone.
The wday
and yday
fields of the given date time specification are ignored. Field values outside of their valid range are internally normalized, e.g. October 40th is interpreted as November 9th.
Returns the resulting epoch value or null if the input date time dictionary was invalid or if the date time specification cannot be represented as epoch value.
Name | Type | Description |
---|---|---|
datetimespec | TimeSpec | The broken-down date and time dictionary. |
timelocal({ "sec": 42, "min": 51, "hour": 13, "mday": 22, "mon": 3, "year": 2022, "isdst": 0 });
// Returns 1647953502
trace(level)
Enables or disables VM opcode tracing.
When invoked with a positive non-zero level, opcode tracing is enabled and debug information is printed to stderr as the program is executed.
Invoking trace()
with zero as an argument turns off opcode tracing.
Name | Type | Description |
---|---|---|
level | number | The level of tracing to enable. |
trace(1); // Enables opcode tracing
trace(0); // Disables opcode tracing
trim(str, copt) → {string}
Trim any of the specified characters in c
from the start and end of str
. If the second argument is omitted, trims the characters, (space),
\t
, \r
, and \n
.
Returns the trimmed string.
Name | Type | Description |
---|---|---|
str | string | The string to be trimmed. |
c | string | (optional) The characters to be trimmed from the start and end of the string. |
type(x) → {string}nullable
Query the type of the given value.
Returns the type of the given value as a string which might be one of "function"
, "object"
, "array"
, "double"
, "int"
, or "bool"
.
Returns null
when no value or null
is passed.
Name | Type | Description |
---|---|---|
x | * | The value to determine the type of. |
uc(str) → {string}nullable
Converts the given string to uppercase and returns the resulting string.
Returns null if the given argument could not be converted to a string.
Name | Type | Description |
---|---|---|
str | * | The string to be converted to uppercase. |
uc("hello"); // "HELLO"
uc(123); // null
uchr(…Numeric) → {string}
Converts each given numeric value to an UTF-8 multibyte sequence and returns the resulting string.
Invalid numeric values or values outside the range 0
..0x10FFFF
are represented by the unicode replacement character 0xFFFD
.
Returns a new UTF-8 encoded string consisting of unicode characters corresponding to the given numeric codepoints.
Name | Type | Description |
---|---|---|
Numeric | number | (repeatable) values to convert. |
uchr(0x2600, 0x26C6, 0x2601); // "☀⛆☁"
uchr(-1, 0x20ffff, "foo"); // "���"
uniq(array) → {Array}nullable
Returns a new array containing all unique values of the given input array.
- The order is preserved, and subsequent duplicate values are skipped.
- If a non-array argument is given, the function returns
null
.
Name | Type | Description |
---|---|---|
array | Array | The input array. |
uniq([1, true, "foo", 2, true, "bar", "foo"]); // Returns [1, true, "foo", 2, "bar"]
uniq("test"); // Returns null
unshift(arr, …Values) → {*}
Add the given values to the beginning of the array passed via first argument.
Returns the last value added to the array.
Name | Type | Description |
---|---|---|
arr | Array | The array to which the values will be added. |
Values | * | (repeatable) to add. |
let x = [ 3, 4, 5 ];
unshift(x, 1, 2); // 2
print(x, "\n"); // [ 1, 2, 3, 4, 5 ]
values(obj) → {Array}nullable
Returns an array containing all values of the given object.
Returns null if no object was passed.
Name | Type | Description |
---|---|---|
obj | * | The object from which to extract values. |
values({ foo: true, bar: false }); // [true, false]
warn(…x) → {number}
Print any of the given values to stderr. Arrays and objects are converted to their JSON representation.
Returns the amount of bytes printed.
Name | Type | Description |
---|---|---|
x | * | (repeatable) The values to be printed. |
warn("Hello", "world"); // Print "Helloworld" to stderr
warn({ key: "value" }); // Print JSON representation of the object to stderr
wildcard(subject, pattern, nocaseopt) → {boolean}
Match the given subject against the supplied wildcard (file glob) pattern.
- If a truthy value is supplied as the third argument, case-insensitive matching is performed.
- If a non-string value is supplied as the subject, it is converted into a string before being matched.
Returns true
when the value matched the given pattern, otherwise false
.
Name | Type | Description |
---|---|---|
subject | * | The subject to match against the wildcard pattern. |
pattern | string | The wildcard pattern. |
nocase | boolean | (optional) Whether to perform case-insensitive matching. |
wildcard("file.txt", "*.txt"); // Returns true
wildcard("file.txt", "*.TXT", true); // Returns true (case-insensitive match)
wildcard("file.txt", "*.jpg"); // Returns false
Type Definitions
ParseConfig: Object
A parse configuration is a plain object describing options to use when compiling ucode at runtime. It is expected as parameter by the loadfile() and loadstring() functions.
All members of the parse configuration object are optional and will default to the state of the running ucode file if omitted.
Name | Type | Description |
---|---|---|
lstrip_blocks | boolean | Whether to strip whitespace preceding template directives. See Whitespace handling. |
trim_blocks | boolean | Whether to trim trailing newlines following template directives. See Whitespace handling. |
strict_declarations | boolean | Whether to compile the code in strict mode ( |
raw_mode | boolean | Whether to compile the code in plain script mode ( |
module_search_path | string[] | Override the module search path for compile time imports while compiling the ucode source. |
force_dynlink_list | string[] | List of module names assumed to be dynamic library extensions, allows compiling ucode source with import statements referring to |
TimeSpec: Object
A time spec is a plain object describing a point in time, it is returned by the gmtime() and localtime() functions and expected as parameter by the complementary timegm() and timelocal() functions.
When returned by gmtime()
or localtime()
, all members of the object will be initialized, when passed as argument to timegm()
or timelocal()
, most member values are optional.
Name | Type | Description |
---|---|---|
sec | number | Seconds (0..60) |
min | number | Minutes (0..59) |
hour | number | Hours (0..23) |
mday | number | Day of month (1..31) |
mon | number | Month (1..12) |
year | number | Year (>= 1900) |
wday | number | Day of week (1..7, Sunday = 7) |
yday | number | Day of year (1-366, Jan 1st = 1) |
isdst | number | Daylight saving time in effect (yes = 1) |