Repository navigation
Standard Library
- IO / Introspection
- Loading / Modules
- Error Handling
- Constructors
- Length
- Iteration
- List Ops
- Map Ops
- Data Quality-of-Life
- String Ops
- List Utilities
- Path Ops
- Date / Time
- Filesystem
- Formatting
- JSON
- Time
- Promises
- Math Functions
- Math Constants
- Conversion
- Memory Management
- Safety Controls
- Network I/O
These functions are registered by cs_register_stdlib(vm).
Prints values separated by spaces and ends with newline.
Returns one of:
"nil" "bool" "int" "float" "string" "list" "map" "strbuf" "range" "function" "native" "promise"
Boolean type-checking functions:
is_nil(value) -> boolis_bool(value) -> boolis_int(value) -> boolis_float(value) -> boolis_string(value) -> boolis_list(value) -> boolis_map(value) -> boolis_function(value) -> boolis_promise(value) -> bool
Example:
if (is_int(x) || is_float(x)) {
print("x is a number");
}Returns environment variable value or nil if missing.
- If
condis falsy → runtime error - Optional second argument string overrides error message
Runs a file. Returns true on success, nil/error on failure.
Runs a file once per resolved path.
- Subsequent calls with the same resolved path return the cached exports without re-running.
- Returns the module's
exportsmap.
Like require(), but returns nil if the file doesn't exist instead of throwing an error.
If the file exists, it behaves like require() and returns the module exports.
Creates a standardized error object with:
-
msg- Error message -
code- Error code (defaults to"ERROR"if omitted) -
stack- List of stack frame strings
Returns true if value is an error object (has msg and code fields).
Example:
fn validate(x) {
if (x < 0) {
throw error("Invalid value: must be non-negative", "INVALID_ARG");
}
}
try {
validate(-5);
} catch (e) {
if (is_error(e)) {
print("Error:", e.msg);
print("Code:", e.code);
}
}Formats an error object (as produced by error()) into a human-readable string.
Current format is a single line: [CODE] message. Stack traces are available on err.stack.
Global map of common error codes (strings), intended to be used with error(msg, code).
Works for:
- string: number of bytes
- list: element count
- map: entry count
- strbuf: byte length Else returns 0.
Returns a lazy range object (iterable) without allocating a list:
-
range(5)→ yields0, 1, 2, 3, 4 -
range(2, 7)→ yields2, 3, 4, 5, 6 -
range(0, 10, 2)→ yields0, 2, 4, 6, 8 -
range(10, 0, -2)→ yields10, 8, 6, 4, 2
Default step is 1. Step cannot be 0.
Example:
for i in range(10) {
print(i);
}Appends all elements from other_list onto list (in-place).
Returns the first index of value, or -1 if not found.
Sorts the list in-place.
- Default sort supports numbers, strings, bools, and nil (matching types only).
- Optional
cmp(a, b)should return negative/zero/positive like C's comparator. - Optional
algoselects the algorithm:"insertion","quick","merge".
Examples:
sort(xs); // insertion sort (default)
sort(xs, "quick");
sort(xs, "merge");
fn desc(a, b) { return b - a; }
sort(xs, desc, "quick");Returns a list of [index, value] pairs.
let xs = ["a", "b"];
print(enumerate(xs)); // [[0, "a"], [1, "b"]]Pairs elements by index up to the shorter list length.
print(zip([1, 2], ["x", "y", "z"])); // [[1, "x"], [2, "y"]]Returns true if any element is truthy (or satisfies pred).
any([nil, 0, 3]) // true
any([1, 3, 5], fn(x) => x % 2 == 0) // falseReturns true if all elements are truthy (or satisfy pred).
all([1, 2, 3]) // true
all([1, 2, 3], fn(x) => x < 3) // falseReturns a new list with elements that satisfy pred.
filter([1, 2, 3, 4], fn(x) => x % 2 == 0) // [2, 4]Returns a new list with mapper applied to each element.
map([1, 2, 3], fn(x) => x * 2) // [2, 4, 6]Reduces a list left-to-right. If init is omitted, uses the first element.
reduce([1, 2, 3], fn(a, b) => a + b) // 6
reduce([1, 2, 3], fn(a, b) => a + b, 10) // 16Inserts value at position index, shifting existing elements.
Removes and returns the element at index.
Returns a new list containing length elements starting at start.
Deletes a key from the map.
Returns a list of all values in the map.
Returns a list of [key, value] pairs.
Alias for values(). Returns all values as a list for convenient iteration.
Returns a shallow copy:
- Lists: creates new list with same elements
- Maps: creates new map with same key-value pairs
- Other types: returns the value as-is
Returns a deep copy with cycle detection:
- Lists and maps are recursively copied
- Handles self-referential structures
- Other types: returns the value as-is
Reverses a list in-place.
Returns a new reversed list without modifying the original.
Checks if item exists:
- Lists: checks for element
- Maps: checks for key
- Strings: checks for substring
Example:
let original = [1, [2, 3], 4];
let shallow = copy(original);
let deep = deepcopy(original);
shallow[1][0] = 99; // Modifies original[1][0]
deep[1][1] = 88; // Does not affect original
reverse([1, 2, 3]); // Returns [3, 2, 1], in-place
let rev = reversed([1, 2, 3]); // original unchanged
print(contains([1, 2, 3], 2)); // true
print(contains({"a": 1}, "a")); // true
print(contains("hello", "ell")); // trueReturns first index or -1.
Replaces all occurrences of old with rep.
- If
oldis empty, returns original string.
Splits on a string separator.
- If
sepis empty, returns[s].
Returns true if sub appears anywhere in s.
Counts non-overlapping occurrences of sub. If sub is empty, returns 0.
Pads on the left until width is reached.
Pads on the right until width is reached.
Returns the reversed string (byte-wise).
Regex uses POSIX Extended Regular Expressions (ERE). Invalid patterns raise a runtime error. On Windows builds, regex functions may be unavailable.
Returns true if any match is found.
Returns true only if the entire string matches.
Returns a match object or nil if no match:
-
start(int) - byte index of match start -
end(int) - byte index of match end -
match(string) - matched text -
groups(list) - capture groups (nilfor unmatched groups)
Returns a list of match objects with the same shape as regex_find.
Replaces all matches with a literal replacement string. Capture expansion (like $1) is not supported.
Example:
let text = "foo-123-bar";
print(regex_is_match("[0-9]+", text));
let m = regex_find("([0-9]+)", text);
print(m.start, m.end, m["match"], m.groups[0]);
let all = regex_find_all("[0-9]+", "a1 b22 c333");
print(len(all));
print(regex_replace("[0-9]+", "a1b22c", "#"));Returns substring starting at start with length characters.
Joins list elements into a string with the given separator.
Returns a new list with duplicates removed (preserves order).
Flattens one level of nested lists.
Splits into sublists of at most size elements.
Removes nil values.
Sums numeric elements (ignores nil). Returns nil if any non-number is present.
Removes leading and trailing whitespace.
Removes leading whitespace only.
Removes trailing whitespace only.
Converts string to lowercase (ASCII only).
Converts string to uppercase (ASCII only).
Returns true if string starts with the given prefix.
Returns true if string ends with the given suffix.
Returns a new string with s repeated count times.
Splits the string on \n or \r\n. An empty trailing line is preserved.
Example:
let text = " Hello World ";
print(str_trim(text)); // "Hello World"
print(str_lower("HELLO")); // "hello"
print(str_upper("hello")); // "HELLO"
print(str_startswith("test", "te")); // true
print(str_endswith("test", "st")); // true
print(str_repeat("ab", 3)); // "ababab"
print(split_lines("a\n b\r\n")); // ["a", " b", ""]Joins with / when needed.
Returns directory portion:
- no slash →
.
Returns the current Unix time in milliseconds.
Returns the current Unix time in seconds.
Returns local time as a map with fields:
-
year,month,day -
hour,minute,second,ms -
wday(0=Sunday),yday(1-366) -
is_dst(bool),is_utc(bool)
Same as datetime_now() but in UTC (is_utc = true).
Converts a Unix milliseconds timestamp to local time.
Converts a Unix milliseconds timestamp to UTC.
Example:
let ms = unix_ms();
let local = datetime_now();
let utc = datetime_utc();
let epoch = datetime_from_unix_ms_utc(0);
print(ms, local, utc, epoch);-
/x→/ -
a/b→a
Returns last path component.
Returns extension without dot, or "" if none.
Reads a file and returns its contents as a string. Returns nil if the file can't be read.
Writes data to path (overwrites). Returns true on success.
Returns true if the path exists.
Returns true if the path exists and is a directory.
Returns true if the path exists and is a regular file.
Returns a list of entry names (not full paths). Returns nil if the directory can't be opened.
Creates a directory. Returns true on success (or if it already exists).
Removes a file or an empty directory. Returns true on success.
Renames or moves a file or directory. Returns true on success.
Returns the VM's current working directory (used for resolving relative paths).
Sets the VM's current working directory for future relative paths. Returns true on success.
Supported specifiers:
-
%dexpects int -
%bexpects bool -
%sexpects string -
%vaccepts any value (uses a generic repr)
Literal percent: %%
Example:
print(fmt("x=%d ok=%b name=%s", 10, true, "frank"));Parses JSON into CupidScript values:
-
null→nil -
true/false→bool - numbers →
intorfloat - strings →
string - arrays →
list - objects →
map
Serializes a value to JSON. Supports nil, bool, int, float, string, list, map.
Example:
let obj = {"name": "frank", "age": 30, "tags": ["a", "b"]};
let s = json_stringify(obj);
let back = json_parse(s);
print(back.name);Milliseconds timestamp:
- Uses
gettimeofdayon POSIX - Uses
clock()fallback on Windows build
Returns a promise that resolves after ms milliseconds.
await sleep(10);If ms <= 0, the promise resolves immediately.
Creates a new pending promise.
Resolves a promise. Returns true if it was pending.
Rejects a promise. Returns true if it was pending.
Checks if a value is a promise.
Returns absolute value. Preserves type (int → int, float → float).
Returns minimum of one or more numbers. Accepts int and/or float.
Returns maximum of one or more numbers. Accepts int and/or float.
Rounds down to nearest integer. Accepts int or float, always returns int.
Rounds up to nearest integer. Accepts int or float, always returns int.
Rounds to nearest integer (0.5 rounds away from zero). Returns int.
Returns square root. Accepts int or float, always returns float.
Returns base raised to exp power. Accepts int or float, returns float.
Returns sine of x (radians). Accepts int or float.
Returns cosine of x (radians). Accepts int or float.
Returns tangent of x (radians). Accepts int or float.
Returns natural logarithm of x (base
Returns
Returns a pseudo-random float in the range
The constant
The constant
Example:
let x = sqrt(16); // 4.0
let y = pow(2, 8); // 256.0
let z = abs(-42); // 42
let m = min(3, 7, 2); // 2
let s = sin(PI / 2); // ~1.0
let c = cos(0); // 1.0
let t = tan(0); // 0.0
let l = log(E); // ~1.0
let ex = exp(1); // ~2.71828
let r = random(); // [0, 1)Converts a value to integer:
-
int→ returns as-is -
float→ truncates toward zero (3.9 → 3, -3.9 → -3) -
bool→0or1 -
string→ parses decimal integer, returnsnilif invalid - Otherwise →
nil
Converts any value to its string representation.
Manually triggers garbage collection cycle detection. Returns the number of cycles collected.
Returns GC statistics as a map:
-
tracked- Number of tracked objects (lists/maps) -
collections- Total collections performed -
collected- Total objects collected -
allocations- Total allocations since VM start
Returns current GC configuration:
-
threshold- Collection threshold (0 = disabled) -
alloc_trigger- Allocation trigger interval (0 = disabled)
Sets GC configuration from a map with optional fields:
-
threshold(int) -
alloc_trigger(int)
Returns true.
Sets both values directly. Returns true.
Auto-GC Policy:
- GC can run when tracked objects >=
threshold - GC can run every
alloc_triggerallocations - Both policies can be enabled simultaneously
- Setting either value to
0disables that policy
See Implementation Notes for details.
Scripts can configure their own execution limits:
Sets maximum execution time in milliseconds. Script aborts if exceeded.
set_timeout(30000); // Allow 30 seconds for batch processingSets maximum instruction count. Script aborts if exceeded.
set_instruction_limit(100000000); // Allow 100M instructionsReturns current timeout in milliseconds (0 = unlimited).
Returns current instruction limit (0 = unlimited).
Returns number of instructions executed in current script run.
Example:
// Check if we need more time for heavy processing
if (get_instruction_count() > get_instruction_limit() / 2) {
print("Warning: approaching instruction limit");
set_instruction_limit(get_instruction_limit() * 2);
}// Connect to a server
let sock = await tcp_connect("example.com", 80);
// Send data
await socket_send(sock, "GET / HTTP/1.1\r\nHost: example.com\r\n\r\n");
// Receive data
let response = await socket_recv(sock, 4096);
// Close socket
socket_close(sock);let server = tcp_listen("0.0.0.0", 8080);
print("Listening on port 8080...");
let client = await socket_accept(server);
let data = await socket_recv(client, 1024);
await socket_send(client, "HTTP/1.1 200 OK\r\n\r\nHello!");
socket_close(client);
socket_close(server);// Connect with TLS
let sock = tls_connect("example.com", 443);
// Check if secure
print(socket_is_secure(sock)); // true
// Get TLS info
let info = tls_info(sock);
print(info.version); // "TLSv1.3"
print(info.cipher); // "TLS_AES_256_GCM_SHA384"
// Upgrade existing connection (STARTTLS)
let smtp = tcp_connect("smtp.example.com", 587);
socket_send(smtp, "STARTTLS\r\n");
tls_upgrade(smtp); // Now encrypted
socket_close(sock);// HTTP request
let resp = http_get("http://example.com");
// HTTPS request (automatic TLS)
let resp = http_get("https://api.example.com/data");
print(resp.status); // 200
print(resp.body);
// POST request
let resp = http_post("https://api.example.com/data", json_stringify({key: "value"}));
// Full control
let resp = http_request({
method: "PUT",
url: "https://api.example.com/users/1",
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer token123"
},
body: json_stringify({name: "bob"}),
timeout: 10000,
follow_redirects: true,
verify_ssl: true // default, set false to skip cert verification
});let parts = url_parse("http://user:pass@example.com:8080/path?q=1");
// {scheme: "http", user: "user", pass: "pass", host: "example.com", port: 8080, path: "/path", query: "q=1"}
let url = url_build({scheme: "https", host: "api.example.com", path: "/v1/users"});
// "https://api.example.com/v1/users"net_set_default_timeout(60000); // 60 second default timeout