Astreum

Language Specification

This page summarizes the current Astreum script syntax and runtime semantics as implemented in the node tokenizer, parser, evaluators, and CLI module loader.

File structure

  • Scripts are list expressions where each element is a definition form: (value name def) or import form (prefix path import).
  • def entries bind name to the evaluated value; names must be UTF-8 symbols.
  • import entries load another module either from a path or a stored reference and nest it under prefix.
  • Modules are resolved relative to the current file directory; relative imports require a module directory to be known.
  • Within a module, local symbol references are rewritten to their fully qualified names to preserve intra-module links.

Lexical elements

  • Lists: Parentheses delimit lists; nested lists are allowed.
  • Symbols: Any non-whitespace, non-parenthesis token; symbols are not quoted unless used as string literals in imports.
  • Bytes: Decimal integers are parsed into minimal-width two's complement byte strings; hex-like symbols (e.g. 0xdead) are decoded when coerced to bytes.
  • Strings: Only used in imports; quoted symbols like "./math.ast" are unwrapped to plain paths.
  • Comments: ; starts a line comment; #; skips the next expression (block comment style).

Expressions and postfix evaluation

  • Lists evaluate in postfix form: the last element determines behavior (def, import, fn, sk, ref); otherwise each element is recursively evaluated and returned as a list.
  • Symbols resolve from the current environment; unresolved symbols raise evaluation errors.
  • (value name def) evaluates value, binds it to name in the current env, and yields the value.
  • (args ((body) (params) fn)) defines and immediately applies a high-level function; parameters bind to single-byte arguments.
  • (args ((body) sk)) builds low-level bytecode from body using placeholders $0, $1, … for the evaluated args, then runs it through the stack-based evaluator.

Modules: imports and definitions

  • Definitions: Each module element with trailing def must contain exactly three items (value, name, terminator).
  • Path imports: (prefix "./other.ast" import) or (prefix ./other.ast import) load another file; paths may be absolute or relative to the current module directory.
  • Reference imports: (prefix (0x… ref) import) loads a module expression stored in atoms by id.
  • Circular guard: The loader tracks an active stack of origins to prevent circular imports.
  • Environment result: Loaded modules produce an Env mapping of qualified names to expressions, ready for evaluation.

Namespaces

  • Imports prefix all definitions with prefix.; nested imports accumulate (e.g., importing math then referencing div yields math.div).
  • Within a module, symbol references are rewritten to their fully qualified names to keep intra-module links consistent under a prefix.
  • Environment keys are stored as UTF-8 bytes matching the qualified symbol name.

Error handling semantics

  • Errors are represented as the list (error <topic-bytes> <message-bytes>).
  • Parsing failures, unexpected tokens, arity mismatches, unbound symbols, meter exhaustion, and storage issues all produce error expressions.
  • Evaluation short-circuits when encountering an error expression and propagates it up the call stack.
  • script_eval wraps tokenization, parsing, and evaluation; it returns structured errors for empty sources or trailing tokens.