Astreum

Language Reference

Concise reference for the Astreum language: grammar, built-ins, modules, CLI usage, and naming rules.

Grammar (informal/EBNF)

program     ::= expr
expr        ::= symbol | bytes | list
list        ::= "(" {expr} ")"

module      ::= "(" {definition} ")"
definition  ::= "(" expr expr ("def" | "import") ")"

fn-call     ::= "(" {arg} "(( " body ") (" params ") fn))"
sk-call     ::= "(" {arg} "(( " body ") sk))"

symbol      ::= nonspace-token without "(" ")" ";" "#;"
bytes       ::= decimal-integer literal (minimal two's complement when parsed)
comment     ::= ";" line | "#;" expr
  • Parentheses build lists; evaluation is postfix (last element drives behavior).
  • Integers become byte literals; symbols remain symbolic unless coerced (e.g., hex to bytes).

Built-in words

High-level forms:

  • def: bind a name in the current environment ((value name def)).
  • fn: create a function (((body) (params) fn)), parameters are symbols.
  • sk: build and run low-level code with $0, $1 placeholders.
  • import: load another module with a prefix ((prefix path import) or (prefix (id ref) import)).
  • ref: resolve an atom-stored expression list by id ((0x... ref)).
  • error: emitted as (error topic message); propagated as-is.

Low-level opcodes (used inside sk bodies):

  • Arithmetic/bitwise: add, nand.
  • Control: jump.
  • Heap: heap_get, heap_set.
  • Atoms: atom_slice, atom_link, atom_concat, atom_new, atom_load.
  • Operands are always bytes; integers are converted to bytes at parse time.

Module and import forms

  • Module file is a list of definitions: each (value name def) or (prefix path import).
  • Path imports accept symbols or bytes; quoted symbols are unwrapped (e.g., "./math.aex").
  • Reference imports use atom ids: (prefix (0x... ref) import).
  • Imported names are qualified: prefix.symbol. Intra-module symbols are rewritten to fully qualified names.
  • Circular imports are rejected via an active-stack check.

Command-line interface and flags

  • python main.py: launch interactive TUI.
  • python main.py --eval: enter evaluation mode (no TUI).
  • --script <path>: load a module file; default entry is main if --expr is not provided.
  • --expr "<postfix>": evaluate a postfix expression (e.g., "(1 2 add)" or "(a b main)" when a script is loaded).
  • At least one of --script or --expr is required in --eval mode.

Reserved words and naming rules

  • Reserved symbols: def, import, fn, sk, ref, error, low-level opcodes (add, nand, jump, heap_get, heap_set, atom_slice, atom_link, atom_concat, atom_new, atom_load).
  • Names must be symbols encoded as UTF-8; they may be qualified with dots (e.g., math.add).
  • Integers in source become bytes; hex-like symbols (0x...) are decoded to bytes when coerced.
  • Comments: ; for line comments, #; to skip an expression.