Import & Export
Stof can read and write any format it has an implementation for — JSON, YAML, TOML, and Stof itself out of the box, with richer formats like PDF or images available as libraries. Two of the mechanisms below run entirely inside a document and work fine in this browser sandbox; the file-based import statement needs a real filesystem, so those examples further down are reference material, not runnable.
Exporting: stringify and blobify
stringify(format, target) exports to a string; blobify(format, target) does the same as raw bytes — every format that supports stringify supports blobify, but it's up to the format implementation whether to support the other way around:
#[main]
fn main() {
const object = new {
a: "hello",
b: 42,
c: true,
};
const json: str = stringify("json", object);
const bytes: blob = blobify("json", object);
pln(json);
pln(bytes as str);
}Parsing at Runtime
parse(source, location, format) is the runtime counterpart to the import statement below — and because it just takes a string, it works fine sandboxed. This is the same self-modification idea from How Stof Works, made concrete: a document handing itself new logic while it runs.
#[main]
fn main() {
const stof = r#"
fn my_function() {
pln("Isn't this cool!");
}
"#;
parse(stof, self, format = "stof");
self.my_function();
}Worth being precise about what's actually sandboxed here: parse can add fields and functions to the document, but it can't reach outside it — no filesystem, no network, unless the host explicitly hands the document a library that provides one. A string full of Stof arriving from an untrusted source is safe to parse and run for exactly that reason.
The import Statement
import <optional format> "path.extension" as <optional location>
The plain form, import "file", assumes a .stof extension and parses into the current context (self):
Object: {
import "./docs.md";
// Object.md now holds the string contents of docs.md
fn markdown() -> str { self.md }
}
Relative Paths & Format Selection
Paths are relative to wherever the CLI or host was invoked from, though a leading ./ lets nested imports navigate correctly as they parse. The format is inferred from the file extension unless you specify one explicitly:
// format inferred from extension:
import "report.pdf";
// format forced explicitly — reads file.stof as plain text,
// not as Stof source:
import text "file.stof";
Import Location (as)
Without as, an import lands on the calling object. as lets you redirect it — but the path after as is always absolute, so it's easy to accidentally create a new root instead of a child of self:
// creates self.Object if needed:
import "./docs.md" as self.Object;
// creates a NEW DOCUMENT ROOT called Object — not the same thing:
import text "./docs.md" as Object;
Packages: the @ Shortcut
Each @ in an import path expands to stof/ — a lightweight convention for package-style imports, paired with the pkg format for importing a whole directory via its pkg.stof manifest:
import "@formata";
// equivalent to:
import "stof/formata.stof";
// pkg format reads an "import" field from stof/formata/pkg.stof
// and pulls in whatever paths it lists:
import pkg "@formata";