-
Notifications
You must be signed in to change notification settings - Fork 0
Standard Library
Stdlib modules are imported using the std: prefix:
import "std:strings"
import { repeat, join } from "std:strings"
import "std:math" as math
Built-in functions are always available — no import needed.
| Function | Description |
|---|---|
print(x) |
Print value to stdout. Accepts exactly one argument — use string interpolation or str() to combine values. |
str(x) |
Convert any value to its string representation |
type(x) |
Return type name: "nil", "bool", "float", "int", "string", "list", "map", "record", "function", "error". A bare numeric literal is "float", not "number"
|
len(x) |
Length of list or string. Returns an int — it returned a float in v3, changed in v4.0 |
has_key(map, key) |
true if key is present in map (O(1)) |
keys(map) |
List of all keys in a map |
values(map) |
List of all values in a map |
list_push(list, v) |
Append v to list in place; returns the same list. xs = list_push(xs, v) reads functional and is not — use the bare form |
copy(value) |
Deep copy of a list, map or record (5.13.0). Preserves shared structure rather than expanding it, terminates on a cycle, and refuses a value holding a function, channel, coroutine or task |
list_pop(list) |
Remove and return the last element |
input(prompt) |
Read a line from stdin (blocked by sandbox by default) |
clock() |
Current time in milliseconds since epoch |
read_file(path) |
Read file contents as string |
write_file(path, content) |
Write string to file |
append_file(path, content) |
Append string to file |
exists(path) |
true if path exists |
mkdir(path) |
Create directory |
list_dir(path) |
List filenames in directory |
type() returns "number" for float values (42, 3.14) and "int" for integer literals (42i). type() returns "error" for err records returned by stdlib functions.
std:runtime.typeof(value) returns even more granular types: "int" vs "float".
Containers alias — assignment binds, it does not copy.
let b = agives a second name for one list, map or record: mutating through either is visible through both, at any depth and across a call boundary.copy(value)is how you hand a container somewhere without it being changed underneath you. A workflowstatecell is the exception — it owns its value, so writing a container into a cell stores a copy and reading one hands a copy back.
import "std:strings" as strings
| Function | Description |
|---|---|
upper(s) |
Convert to uppercase |
lower(s) |
Convert to lowercase |
trim(s) |
Strip leading/trailing whitespace |
split(s, delim) |
Split string into list |
join(list, delim) |
Join list into string |
contains(s, sub) |
Check if substring present |
replace(s, old, new) |
Replace all occurrences of old with new
|
repeat(s, n) |
Repeat string n times |
is_blank(s) |
True if empty or only whitespace |
import "std:strings" as s
print(s.upper("hello")) // "HELLO"
print(s.split("a,b,c", ",")) // ["a", "b", "c"]
print(s.join(["a", "b"], "-")) // "a-b"
print(s.repeat("ha", 3)) // "hahaha"
import "std:collections" as col
| Function | Description |
|---|---|
map(list, fn) |
Apply function to each element, return new list |
filter(list, fn) |
Keep elements where fn returns truthy |
reduce(list, fn, initial) |
Accumulate with binary function |
push(list, value) |
Append to list in-place; returns the list |
pop(list) |
Remove and return last element |
first(list) |
First element |
last(list) |
Last element |
list_sum(list) |
Sum of all numbers |
import "std:collections" as col
let nums = [1, 2, 3, 4, 5]
print(col.map(nums, fn(x) { return x * 2 })) // [2, 4, 6, 8, 10]
print(col.filter(nums, fn(x) { return x > 2 })) // [3, 4, 5]
print(col.reduce(nums, fn(a, x) { return a + x }, 0)) // 15
import "std:json" as json
| Function | Description |
|---|---|
parse(s) |
Decode JSON string — JSON objects become maps, arrays become lists |
stringify(value) |
Encode Nodus value to JSON string |
parse_int(s) |
Parse a decimal string as an integer |
Important: json.parse returns a map (not a record) for JSON objects. Use bracket notation to access fields:
import "std:json" as json
let data = json.parse('{"name": "Alice", "age": 30}')
print(data["name"]) // "Alice" ← bracket notation required
print(data["age"]) // 30
import "std:math" as math
| Function | Description |
|---|---|
abs(x) |
Absolute value |
min(a, b) |
Minimum of two values |
max(a, b) |
Maximum of two values |
floor(x) |
Floor (round down). Returns an int
|
ceil(x) |
Ceiling (round up). Returns an int
|
sqrt(x) |
Square root |
pow(base, exp) |
Exponentiation |
random() |
Random float in [0, 1) |
is_int(x) |
True if value is an integer |
is_float(x) |
True if value is a float |
is_numeric(x) |
True if value is int or float |
import "std:math" as math
print(math.abs(-5)) // 5
print(math.sqrt(16)) // 4.0
print(math.max(3, 7)) // 7
import "std:fs" as fs
| Function | Description |
|---|---|
read(path) |
Read file contents as string |
write(path, content) |
Write string to file |
append(path, content) |
Append string to file |
exists(path) |
Returns true if path exists |
listdir(path) |
Returns list of filenames in directory |
ensure_dir(path) |
Create the directory if it does not exist, idempotently; returns the path. An existing directory succeeds and missing parents are created. A file at the target is io_error. Before 5.13.0 it reported success for every failure |
import "std:fs" as fs
if (fs.exists("data.json")) {
let content = fs.read("data.json")
print(content)
}
Path manipulation helpers. These are global builtins, not module functions.
| Built-in | Description |
|---|---|
path_join(a, b) |
Join two path segments |
path_dirname(p) |
Directory part of path |
path_basename(p) |
Filename part of path |
path_ext(p) |
File extension |
path_stem(p) |
Filename without extension |
import "std:memory" as mem
Shared runtime key-value store. Without a session it is process-local; in server sessions it is session-local.
| Function | Description |
|---|---|
get(key) |
Read value or nil
|
put(key, value) |
Store JSON-safe value; returns it |
delete(key) |
Remove key; returns true if existed |
keys() |
List all keys |
has(key) |
true if get(key) != nil
|
share(ns, key, val) |
Store in namespace ns (key prefixed {ns}::) |
recall_from(ns, key) |
Read from namespace ns
|
recall_all(ns) |
All keys and values in namespace ns
|
import "std:memory" as mem
mem.put("count", 0)
mem.put("count", mem.get("count") + 1)
mem.share("session", "user_id", "alice")
print(mem.recall_from("session", "user_id")) // "alice"
import "std:runtime" as rt
| Function | Description |
|---|---|
fn_name(fn) |
Function name string |
fn_arity(fn) |
Parameter count |
fn_module(fn) |
Defining module path |
fields(record) |
List of record field names |
has(record_or_module, name) |
Field/export existence check |
module_fields(module) |
List of exported names |
stack_depth() |
Current call stack depth |
stack_frame(index) |
Frame record with name, module, path, line, column
|
typeof(value) |
Granular type: "int", "float", "string", etc. |
tasks() |
List of tracked coroutine tasks |
scheduler() |
Scheduler counters and queue sizes |
time_ms() |
Runtime clock in milliseconds |
import "std:runtime" as rt
fn add(a, b) { return a + b }
print(rt.fn_name(add)) // "add"
print(rt.fn_arity(add)) // 2
print(rt.typeof(42)) // "float"
print(rt.typeof(42i)) // "int"
import "std:async" as async
Coroutine and channel helpers. See Coroutines and Channels for detailed usage.
| Function | Description |
|---|---|
sleep(ms) |
Suspend current coroutine for ms ms |
parallel(tasks) |
Spawn all and run event loop |
series(tasks) |
Run tasks sequentially |
queue() |
New channel |
worker_pool(worker, count) |
Channel serviced by N workers |
pipeline(stages) |
{input, output} channel pipeline |
import "std:tool" as tool
MCP-compatible tool registry. Tool names must use dotted namespacing (e.g. "myapp.search"). A plain name like "search" returns a registration error.
| Function | Description |
|---|---|
register(opts) |
Register a tool. opts map: name (required, dotted), handler (required), description, schema, effects, returns_schema, version, tags
|
invoke(name, args) |
Call a registered tool by name |
lookup(name) |
Return tool metadata map or err |
list_tools(filter?) |
List registered tools (optional filter string) |
has(name) |
true if tool is registered |
unregister(name) |
Remove a registered tool |
import "std:tool" as tool
tool.register({
"name": "myapp.greet",
"handler": fn(args) { return "hello " + args["name"] },
"description": "Greet a user"
})
let result = tool.invoke("myapp.greet", {"name": "Alice"})
print(result) // "hello Alice"
import "std:http" as http
HTTP client. Requires httpx (included in nodus-lang dependencies).
| Function | Description |
|---|---|
get(url, opts?) |
HTTP GET |
post(url, opts?) |
HTTP POST |
put(url, opts?) |
HTTP PUT |
delete(url, opts?) |
HTTP DELETE |
patch(url, opts?) |
HTTP PATCH |
request(method, url, opts?) |
Generic HTTP request |
Response records have fields: status, body, headers, url, method, ok, is_redirect, is_client_error, is_server_error, plus method fields json(), header(name).
Options: json, text, bytes (body), headers, query, auth_bearer, auth_basic, timeout_ms, follow_redirects, verify_tls.
import "std:http" as http
let r = http.get("https://api.example.com/data")
if (r.ok) {
let data = r.json()
print(data["result"])
}
Errors return an err record with kind: "http_error" and a category field: network, timeout, client_error, server_error, decode_error, or redirect_error.
import "std:subprocess" as proc
| Function | Description |
|---|---|
run(argv, opts?) |
Run process synchronously; returns result record |
shell(command, opts?) |
Run shell command synchronously |
spawn(argv, opts?) |
Spawn process; returns handle with channels |
shell_quote(string) |
Platform-safe shell quoting |
Result record fields: stdout, stderr, exit_code, duration_ms, command. Err records use kind: "subprocess_error".
import "std:subprocess" as proc
let r = proc.run(["ls", "-la"])
print(r.stdout)
import "std:time" as time
Datetime and duration library.
| Function | Description |
|---|---|
now() |
Current datetime in local timezone |
now_in(zone) |
Current datetime in named timezone |
at(year, month, day, ...) |
Construct datetime |
from_epoch_ms(ms) |
Datetime from epoch milliseconds |
from_iso8601(s) |
Parse ISO 8601 string |
to_epoch_ms(dt) |
Convert datetime to epoch milliseconds |
to_iso8601(dt) |
Format datetime as ISO 8601 |
duration_between(a, b) |
Duration between two datetimes |
import "std:hash" as hash
Cryptographic hashing. Hash functions return a hash record — call .to_hex() to get a hex string.
| Function | Description |
|---|---|
sha256(data) |
SHA-256 hash record |
sha512(data) |
SHA-512 hash record |
md5(data) |
MD5 hash record |
hmac_sha256(key, data) |
HMAC-SHA256 hash record |
compare(a, b) |
Constant-time comparison of two hash values |
import "std:hash" as hash
let h = hash.sha256("hello world")
print(h.to_hex()) // "b94d27b9..."
print(h.to_base64()) // base64 encoding
import "std:encoding" as enc
| Function | Description |
|---|---|
base64_encode(s) |
Base64-encode a string |
base64_decode(s) |
Decode a base64 string |
hex_encode(s) |
Hex-encode a string (lowercase) |
hex_decode(s) |
Decode a hex string |
url_encode(s) |
URL percent-encode |
import "std:secrets" as secrets
| Function | Description |
|---|---|
random_bytes(n) |
n cryptographically random bytes |
token_hex(n) |
n-byte token as hex string |
token_base64(n) |
n-byte token as base64 |
uuid_v4() |
Random UUID v4 string |
uuid_v7() |
Time-ordered UUID v7 string |
import "std:test" as test
Full test framework. Run tests with nodus test [path].
| Function | Description |
|---|---|
test.suite(name, fn) |
Declare a test suite |
test.case(name, fn) |
Declare a test case |
test.assert(val) |
Assert truthy |
test.assert_eq(a, b) |
Assert equality |
test.assert_err(val) |
Assert value is an err record |
test.assert_ok(val) |
Assert value is not an err record |
test.assert_throws(fn) |
Assert function throws |
test.skip(name, fn) |
Skip a test case |
test.advance_clock(ms) |
Advance virtual clock (async tests) |
test.flush_async() |
Flush pending async tasks |
import "std:bool" as bool
| Function | Description |
|---|---|
equal(x, bool_value) |
Strict boolean equality (x must match the exact boolean value) |
Use bool.equal(x, true) when you need strict boolean checking instead of truthiness.
import "std:identity" as identity
Execution identity and trace propagation.
| Function | Description |
|---|---|
trace_id() |
Current trace ID (nil if not set) |
session_id() |
Current session ID |
execution_unit_id() |
Unique ID for this VM instance |
Set the trace ID from the host: NodusRuntime.set_trace_id(id).
import "std:effects" as effects
Exactly-once effect tracking.
| Function | Description |
|---|---|
effect_action_id(type, payload, scope) |
Compute deterministic action ID |
effect_pending(id, hash) |
Mark effect as pending |
effect_resolve(id) |
Check if effect was already completed |
effect_complete(id, status, result) |
Mark effect as complete |
effect_store_size() |
Number of tracked effects |
import "std:sys" as sys
Versioned syscall dispatch. Provides a uniform {status, data, error, trace_id} envelope.
| Function | Description |
|---|---|
call(name, payload) |
Dispatch a registered syscall by name |
list() |
List all registered syscall names |
Built-in syscalls: sys.v1.memory.get, sys.v1.memory.put, sys.v1.memory.delete, sys.v1.memory.recall_from.
import "std:retry" as retry
Requires nodus-retry (included as a required dependency since v4.0).
| Function | Description |
|---|---|
call(fn, policy) |
Call fn with retry policy. Policy map: max_attempts, delay_ms, backoff, retry_on
|
import "std:circuit_breaker" as cb
Requires nodus-circuit-breaker (optional; returns {kind: "dependency_error"} map when not installed).
| Function | Description |
|---|---|
create(name, opts?) |
Create a circuit breaker |
call(name, fn) |
Call fn through the named circuit breaker |
state(name) |
Return current state: "closed", "open", "half_open"
|
reset(name) |
Force circuit breaker to closed state |
import "std:agent" as agent
AI agent dispatch wrapper. Register agent handlers via the embedding API.
| Function | Description |
|---|---|
call(name, payload) |
Call a registered agent handler |
available() |
List registered agent names |
describe(name) |
Agent metadata or nil
|
All stdlib modules support both full and destructured imports:
// full namespace
import "std:strings" as s
s.upper("hello")
// selective
import { upper, lower } from "std:strings"
upper("hello")
Nodus v5.15.0 — Release · GitHub · Issues · Changelog
Opcode set frozen at v1.0. See Bytecode Reference for the freeze declaration.
Getting Started
Language Reference
- Syntax Reference
- Type System
- Control Flow
- Functions
- Modules and Imports
- Error Handling
- Coroutines and Channels
- Workflows and Task Graphs
- Standard Library
Tooling
Embedding
Project