Astreum

Language Tour

Walk through the core language constructs with short, runnable snippets that match the tokenizer, parser, and evaluators.

Stack and basic operators

Expressions are postfix: operators read their operands from the stack.

(1 2 add)          ; pushes 1, pushes 2, adds -> 3 bytes
(1 2 nand)         ; bitwise NAND of the two operands
(1 5 jump)         ; pop target and jump within low-level code
  • Integers become minimal-width two's complement bytes; all ops work on bytes.
  • Low-level ops include add, nand, jump, heap_get, heap_set, atom helpers, and error paths.

Defining functions

Use postfix def to bind names; fn builds a high-level function.

(
  ((( $0 $1 add ) (a b) fn) sum def)   ; sum returns a + b
  ((5 6 sum) result def)               ; result -> 11 bytes
)
  • (value name def) evaluates value then binds it to name.
  • ((body) (params) fn) creates a callable; parameters bind to single-byte arguments.

Working with modules and import

Place helpers under a prefix with import. Paths can be relative or absolute; refs load stored atoms.

; modules/math.aex
(
  ((( $0 $1 add ) (x y) fn) add def)
)

; src/main.aex
(
  (math "../modules/math.aex" import)
  ((( math.add ) (a b) fn) main def)
)
  • (prefix path import) qualifies imported symbols (e.g., math.add).
  • Within a module, symbol references are rewritten to their fully qualified names to keep links intact.

Comments

(1 2 add) ; line comment to end of line
#;(1 2 add)   ; skips the entire next expression
(1 #;(2 3 add) 4 add) ; the middle expression is skipped
  • ; starts a line comment.
  • #; skips the following expression (block-style).

Simple standard library examples

Out of the box, byte-level helpers are available in low-level code:

  • heap_get/heap_set: scratch storage with byte keys/values.
  • atom_slice/atom_concat/atom_new/atom_load: manipulate stored atoms (bytes, symbols, lists).
  • nand and add: bitwise NAND and integer addition.

Compose these via sk to build custom low-level routines from high-level expressions.

Small end-to-end example

Compute (a + b) + (c + d) with an imported helper:

; modules/math.aex
(
  ((( $0 $1 add ) (x y) fn) add def)
)

; src/main.aex
(
  (math "../modules/math.aex" import)
  (((( $0 $1 add ) (a b) fn) pair def)
   ((( math.add (a b pair) add ) (a b c d) fn) main def))
)
  • main expects four args; it uses pair to add them in pairs, then math.add to add the intermediate results.
  • The result is a bytes value produced by the low-level add opcode.