Built-in Functions

All builtins are restricted — scripts may call them but never reassign
or modify them. Call help() to list them from inside a script.

Output and inspection

print(value, ...) — prints values to stdout separated by spaces, followed by
a newline. Returns nil.

info(value) — returns a string containing the value’s type and description
info.

type(value) — returns the type name as a string.

len(value) — returns the size of an array, object, or string.

print("count", 42)        # count 42
print(type(42))           # int
print(len("abc"))         # 3
print(info([1, 2, 3]))    # type + description info

keys, values, has, items

Introspect an object’s contents:

  • keys(obj) — an array of the object’s key names (an object is required;
    passing an array errors).
  • values(obj) — an array of the object’s values, in the same order as
    keys.
  • items(obj) — an array of {key, value} objects, one per member —
    handy when you need both the key and its value together.
  • has(obj, key) — true if the object contains that key, otherwise false.
var user = {name: "Ada", age: 36, admin: false}

print(keys(user))         # e.g. ["admin", "name", "age"]  (any order)
print(values(user))       # e.g. [false, "Ada", 36]         (same order as keys)
print(has(user, "name"))  # true
print(has(user, "email")) # false
print(len(user))          # 3

var entries = items(user)         # array of {key, value} objects
print(entries[0].key)             # e.g. "age"
print(entries[0].value)           # e.g. 36

for (entry : items(user)) {
  print(entry.key, "=", entry.value)   # walk every member in one loop
}

Key order is not guaranteed — the engine stores object members in an
unordered structure, so keys() and values() may come back in any order.
values()[i] lines up with keys()[i] only by accident of a single
iteration, never as a contract: iterate with items() (or for (k, v : obj))
whenever key and value must stay paired.

The classic “look up by key” pattern is has + index:

var settings = {theme: "dark", volume: 80}
if (has(settings, "theme")) {
  print(settings["theme"])   # dark
}

keys / values / has are restricted globals, like all builtins — you
can call them but never reassign them.

Conversion

to_string(value)   # any value -> string
int(value)         # -> int
long(value)        # -> long
float(value)       # -> float
double(value)      # -> double
var i  = int("42")
var l  = long("3000000000")
var f  = float("3.14")
var d  = double("2.718")
var s  = to_string(42)

All five are also pipes that rewrite the receiver in place (see
Pipes):

var flt = 1.04
flt:int()   # flt -> 1

Values

version() — returns an array ["Scrii", <version>, <build date>].

var v = version()
print("Engine:", v[0], v[1], "built", v[2])

insert and erase

insert adds items to an array or object; erase removes items from an array
or object (or an entire variable). Both accept a single selector (one index
or key) or an array of selectors (several indices or keys at once).

Two distinct ways to use them:

Form Example Behavior
Builtin (bare name) a = erase(a, 1) Pure — returns the modified copy, does not change the argument
Pipe (colon) a:erase(1) In place — reassigns the receiver

Arrays and objects have value semantics, so the builtin returns a new
value that you must assign. The pipe form is the idiomatic in-place operator.

erase

Arrays — by index, or by an array of indices:

var a = [10, 20, 30, 40, 50]
erase(a, 1)          # pure: does NOT change a
print(a)             # [10, 20, 30, 40, 50]
a = erase(a, 1)      # assign the result
print(a)             # [10, 30, 40, 50]

var b = [10, 20, 30, 40, 50]
b = erase(b, [1, 3]) # remove indices 1 and 3
print(b)             # [10, 30, 50]

Objects — by key, or by an array of keys:

var o = {a: 1, b: 2, c: 3, d: 4}
o = erase(o, "b")        # remove one key
print(o)                 # {a: 1, c: 3, d: 4}

var o2 = {a: 1, b: 2, c: 3}
o2 = erase(o2, ["a", "c"])  # remove several keys
print(o2)                # {b: 2}

Variables:

erase(some_global)       # remove a top-level variable entirely
erase("other_global")    # same thing, with the name as a string

With one argument, erase deletes a top-level variable, not a value:
the argument is evaluated and its string value is used as the variable
name (erase(some_global) works when some_global holds a string; a
non-string argument is an error). Erasing a restricted name (like std or
a builtin) is refused.

Erasing a name shared through ref aliases tombstones the shared storage:
every alias reads nil afterwards instead of orphaned data — whether the
erased name was the original or one of the aliases (see
Sharing nested storage with ref):

var a = 4
ref b = a
erase("a")
print(b)                 # nil

In place with the pipe operator:

var a = [10, 20, 30, 40, 50]
a:erase(1)               # a -> [10, 30, 40, 50]
a:erase([1, 3])          # a -> [10, 50]

var o = {a: 1, b: 2, c: 3}
o:erase("b")             # o -> {a: 1, c: 3}
o:erase(["a", "c"])      # o -> {b: 2}

The selector array works the same whether it is written inline
(erase(a, [1, 3])) or passed as a variable:

var drop = [0, 2]
var nums = [7, 8, 9, 10]
nums = erase(nums, drop)   # [8, 10]
var gone = ["temp"]
var obj = {temp: 1, keep: 2}
obj = erase(obj, gone)     # {keep: 2}

insert

Arrays — a single item (optionally at an index):

var a = [1, 3]
a = insert(a, 2, 1)        # insert 2 at index 1 -> [1, 2, 3]
var b = [1, 2]
b = insert(b, 4)           # append (index defaults to the end) -> [1, 2, 4]

Arrays — splice an array of items (optionally at an index):

var c = [1, 4]
c = insert(c, [2, 3], 1)   # splice [2, 3] in at index 1 -> [1, 2, 3, 4]
var d = [1, 2]
d = insert(d, [3, 4])      # append the array -> [1, 2, 3, 4]

Objects — merge another object’s keys:

var x = {a: 1}
x = insert(x, {b: 2})      # merge -> {a: 1, b: 2}

In place with the pipe operator:

var a = [1, 3]
a:insert(2, 1)             # a -> [1, 2, 3]
a:insert([4, 5])           # a -> [1, 2, 3, 4, 5]

var o = {a: 1, b: 2}
o:insert({c: 3})           # o -> {a: 1, b: 2, c: 3}

When you insert an array without an index it is spliced (its elements are
appended), not added as a single nested element:

var e = [1, 2]
e = insert(e, [3, 4])    # [1, 2, 3, 4]  (spliced, not [1, 2, [3, 4]])

import

import(file) loads and executes another .scr file — see Import
for the full story (namespace merging, exports, search paths, collisions).

load_plugin / unload_plugin

Native plugins are covered on their own page: Native Plugins.
In short, load_plugin("./myplugin.so") registers restricted globals and
unload_plugin("./myplugin.so") removes them again.

pipe / pipe_remove

Pipes live on their own page: Pipes. In short,
pipe("twice", fn(n) { return n * 2 }) registers receiver:twice(args) and
pipe_remove("twice") unregisters it.

help

help() — returns a string listing the core builtins as name - description,
so you can see what’s available without guessing. Note the listing is captured
at registration time, so load_plugin / unload_plugin and the std module
are not part of it — use help(std) to browse those.

help(obj) — for an object or module, returns a string with the object’s
own description followed by one name - description line for each member.
Because every member carries a description line, you can see exactly what is
at that layer and never have to guess at its contents.

print(help())              # core builtins, one per line
print(help(std))           # every module + the OS basics on std
print(help(std.string))    # the string functions, one per line

The descriptions describe each member, so you can drill into the next
layer
: help() on a module shows its function names and purposes, and you
can then call help() on any nested member to keep descending:

print(help(std))           # ... string - String Manipulation, ...
print(help(std.string))    # ... upper - upper(s) - Converts string to uppercase, ...
var mods = [std.string, std.math]
print(help(mods[0]))       # same as help(std.string) — help also takes array elements

help(value) on any other value returns just that value’s own description
(empty for scalars and arrays unless they carry one via the -> describe
operator). Arrays are not listed element-by-element — to inspect an array,
pass each element, e.g. help(arr[i]).

Errors raised by builtins surface as script errors with a status code and a
message. See Error Handling.