Skip to main content

Standard Library (Std)

Std is the one library that never needs to be named — Std.pln(...) and pln(...) call the same function. Every other library needs its own prefix (Time.now(), Http.fetch(...)), but anything shown here works bare.

One distinction worth keeping straight: this page is about library functions, which never need a receiver. A document function always does — self.myFunc(), super.myFunc(), through a variable, whatever fits — because it belongs to a specific node in the graph, not to the runtime itself.

Output

pln(..) -> void

Prints all arguments to the standard output stream — this is what every other page's examples have been using the whole time.

pln.stof
#[main]
fn main() {
  pln("hello, world");
}
Output

err(..) -> void

Same as pln, but to the error stream instead of standard output.

err.stof
#[main]
fn main() {
  err("hello, world");
}
Output

str(..) -> str

Formats all arguments the same way pln would, but returns the result as a string instead of printing it.

str.stof
#[main]
fn main() {
  pln(str("hello, world"));
}
Output

dbg(..) -> void

Prints all arguments as debug output. Depending on how the host environment wires up logging, this may not surface in every output stream pln does — worth checking your browser console too if it looks quiet.

dbg.stof
#[main]
fn main() {
  dbg("hello, world");
}
Output

Logging

The five log_* functions map onto the standard levels from Rust's log crate. Same caveat as dbg — whether these are visible depends on what the host has configured to receive them.

log_info(..) -> void

log-info.stof
#[main]
fn main() {
  log_info("we just did something cool");
}
Output

log_debug(..) -> void

log-debug.stof
#[main]
fn main() {
  log_debug("this is what just happened, in case you need to debug me");
}
Output

log_warn(..) -> void

log-warn.stof
#[main]
fn main() {
  log_warn("we encountered something, but are handling it");
}
Output

log_error(..) -> void

log-error.stof
#[main]
fn main() {
  log_error("we have a problem");
}
Output

log_trace(..) -> void

log-trace.stof
#[main]
fn main() {
  log_trace("tracing through this code path");
}
Output

Debugging & Tracing

Three deeper introspection tools — expect dense, VM-level output that looks different every run. That's normal; these aren't meant to be tidy.

peek(..) -> void

Prints your arguments, then a trace of the current process and the next instructions about to execute. Pass a trailing integer to control how many.

peek.stof
#[main]
fn main() {
  peek("getting here");
}
Output

trace(..) -> void

Like peek, but shows the instructions that already ran leading up to this point, instead of what's coming next.

trace.stof
#[main]
fn main() {
  trace("getting here");
}
Output

dbg_tracestack() -> void

Prints a snapshot of the current stack, with no arguments needed.

dbg-tracestack.stof
#[main]
fn main() {
  dbg_tracestack();
}
Output

Assertions

Every one of these throws when the check fails — wrap the failing case in try/catch if you want execution to continue past it, same as anywhere else in Stof.

assert(value: unknown = false) -> void

assert.stof
#[main]
fn main() {
  assert(true);
  pln('first assertion passed');

  try { assert(false); }
  catch { pln('assert(false) throws'); }
}
Output

assert_eq(first: unknown, second: unknown) -> void

assert-eq.stof
#[main]
fn main() {
  assert_eq('a', 'a');
  pln('equal values pass');

  try { assert_eq(43, 42); }
  catch { pln('unequal values throw'); }
}
Output

assert_neq(first: unknown, second: unknown) -> void

assert-neq.stof
#[main]
fn main() {
  assert_neq('a', 'b');
  pln('different values pass');

  try { assert_neq(34, 34); }
  catch { pln('equal values throw'); }
}
Output

assert_not(value: unknown = true) -> void

assert-not.stof
#[main]
fn main() {
  assert_not(false);
  pln('falsy value passes');

  try { assert_not(true); }
  catch { pln('truthy value throws'); }
}
Output

Errors & Process Control

throw(value: unknown = "Error") -> void

Throws any value, not just a string — the mechanism behind every try/catch example on the Error Handling page.

throw.stof
#[main]
fn main() {
  try { throw("error message"); }
  catch (msg: str) { pln('caught:', msg); }
}
Output

exit(..) -> void

Immediately halts the current process — nothing after it in the same process runs. Pass a promise to terminate that process's execution instead of the current one.

exit.stof
#[main]
fn main() {
  pln('before exit');
  exit();
  pln('after exit — never runs');
}
Output

Parsing & Exporting

parse(source: str | blob, context: str | obj = self, format: str = "stof", profile: str = "prod") -> bool

Covered in depth on Import & Export — the runtime counterpart to the import statement, and it works fine sandboxed since it's just operating on a string.

parse.stof
#[main]
fn main() {
  parse('fn hello() -> str { "hello" }');
  pln(self.hello());
}
Output

stringify(format: str = "json", context: obj = null) -> str

Exports a string. Lossy for anything the target format can't represent — JSON has no concept of units, for instance, so they're silently dropped.

stringify.stof
#[main]
fn main() {
  const object = new { x: 3.14km, y: 42m };
  pln(stringify("json", object));
}
Output

blobify(format: str = "json", context: obj = null) -> blob

Same idea as stringify, exporting raw bytes instead of a string.

blobify.stof
#[main]
fn main() {
  const object = new { x: 3.14km, y: 42m };
  const bytes = blobify("json", object);
  pln(bytes.len() > 0, bytes as str);
}
Output

Constructing Collections

Mostly useful for building an empty collection, or building one from values you already have in hand rather than writing out literal syntax.

list(..) -> list

list.stof
#[main]
fn main() {
  pln(list(1, 2, 3));
}
Output

map(..) -> map

Takes tuples of key/value pairs.

map.stof
#[main]
fn main() {
  pln(str(map(("a", 1), ("b", 2))));
}
Output

set(..) -> set

set.stof
#[main]
fn main() {
  pln(str(set(1, 2, 3)));
}
Output

Values & Memory

copy(val: unknown) -> unknown

A real deep copy — for an object, every field, function, and nested piece of data underneath it, recursively.

copy.stof
#[main]
fn main() {
  const a = {1, 2, 3};
  const b = copy(a);
  b.clear();
  pln(str(a), str(b));
}
Output

swap(first: unknown, second: unknown) -> void

Swaps two values in place — needs & on value types, the same reference operator from Variables & References, since a plain value type would just swap two disposable copies.

swap.stof
#[main]
fn main() {
  let a = 42;
  let b = -55;
  swap(&a, &b);
  pln(a, b);
}
Output

min(..) -> unknown

If an argument is a collection, only the values inside it are considered — not the collection as a whole.

min.stof
#[main]
fn main() {
  pln(str(min(1km, 2m, 3mm)));
}
Output

max(..) -> unknown

max.stof
#[main]
fn main() {
  pln(str(max(1km, 2m, 3mm)));
}
Output

drop(..) -> bool | list

Covered in depth on Document Memory Management — drops fields, functions, objects, or data from the graph, running #[dropped] on anything that has it. Given several things to drop at once, returns a list of one bool per item.

drop.stof
#[main]
fn main() {
  const func = () => {};
  const object = new {};
  self.field = 42;

  const results = drop("self.field", func, object);
  pln(results);
}
Output

shallow_drop(..) -> bool | list

Same as drop, except if a dropped field pointed to an object, only the field is removed — the object itself stays in the graph. Useful when more than one field might point at the same object and you only want to disconnect this one.

shallow-drop.stof
#[main]
fn main() {
  self.field = new {};
  const object = self.field;

  shallow_drop("self.field");
  pln(self.contains("field"), object.exists());
}
Output

Introspection

Mostly useful for writing code that has to reason about the document generically — a validator, a debugging tool, anything that can't assume a fixed shape ahead of time.

funcs(attributes: str | list | set = null) -> list

Every function in the graph, optionally filtered to only those carrying a given attribute.

funcs.stof
#[main]
#[main_or_test]
fn main() {
  pln(funcs("main_or_test").len());
}
Output

callstack() -> list

A list of function pointers currently on the stack — last one is this, the function calling callstack() itself.

callstack.stof
fn inner() {
  for (const func in callstack()) {
      pln(func.obj().path(), func.name());
  }
}

#[main]
fn main() {
  self.inner();
}
Output

graph_id() -> str

A unique ID string for this graph/document.

graph-id.stof
#[main]
fn main() {
  pln(graph_id().len() > 10);
}
Output

format(format: str) -> bool

Is a given format loaded and available for parse/stringify/blobify?

format.stof
#[main]
fn main() {
  pln(format("json"), format("docx"));
}
Output

format_content_type(format: str) -> str

The HTTP content-type header value for a loaded format — useful if you're serving Stof-produced data over the wire.

format-content-type.stof
#[main]
fn main() {
  pln(format_content_type("json"));
}
Output

formats() -> set

Every format currently available to use.

formats.stof
#[main]
fn main() {
  pln(formats().contains("json"));
}
Output

lib(lib: str, func?: str) -> bool

Is a library — and optionally a specific function on it — loaded?

lib.stof
#[main]
fn main() {
  pln(lib("Std"), lib("Render"));
  pln(lib("Num", "abs"));
}
Output

libs() -> set

Every library currently available.

libs.stof
#[main]
fn main() {
  pln(libs().superset({"Std", "Fn", "Num", "Set"}));
}
Output

prof(name: str) -> bool

Was this graph parsed under a given profile name? Profiles are how parse's profile parameter tags a parse for later inspection.

prof.stof
#[main]
fn main() {
  pln(prof('test'), prof('prod'));
}
Output

Environment

These four require the system feature flag, which reads and writes real process environment variables — not something a browser sandbox can meaningfully do, so these are reference-only rather than runnable here.

const host = env("HOST");

const vars: map = env_vars();

set_env("HOST", "localhost");

remove_env("HOST");

Timing

sleep(time: ms) -> void

Pauses the current process for at least the given duration — possibly longer, never less. Other processes keep making progress while this one sleeps, same cooperative model as Async.

sleep.stof
#[main]
fn main() {
  const start = Time.now();
  sleep(50ms);
  pln(Time.diff(start) >= 50);
}
Output

IDs & Text Helpers

nanoid(length: int = 21) -> str

A URL-safe random ID — collision probability is low and drops further as length increases.

nanoid.stof
#[main]
fn main() {
  pln(nanoid() != nanoid(33));
}
Output

xml(text: str, tag: str) -> str

Wraps a string in an XML tag — a small formatting helper, nothing more.

xml.stof
#[main]
fn main() {
  pln(xml("hello, world", "msg"));
}
Output

prompt(text: str = '', tag?: str) -> prompt

Builds a prompt value — a small tree of tagged text, meant for assembling structured prompts for AI contexts. += appends a nested prompt as a child.

prompt.stof
#[main]
fn main() {
  let p = prompt(tag = 'instruction');
  p += prompt('do a thing', 'sub');
  p += prompt('another thing', 'sub');
  pln(p as str);
}
Output