Namespaces¶
A namespace groups related macros, constants, and nested namespaces. Defined with ns:
ns stl {
def loop {
;$ - dw
}
}
Inside the block, all defs, nss, and constants belong to the enclosing path. The example above defines stl.loop.
Nesting¶
Namespaces nest naturally:
ns hex {
ns pointers {
def write_hex { ... } // fully qualified: hex.pointers.write_hex
}
}
Dotted access¶
Outside the defining namespace, use the full dotted path:
stl.startup // unambiguous, absolute
hex.pointers.write_hex
Inside a namespace, references resolve in the order:
Leading dot (
.name) — current namespace.Leading double-dot (
..name) — parent namespace.Absolute (
top.middle.leaf) — searched from the root.Bare word (
name) — current namespace first, then ancestors, then global.
ns hex {
def helper {}
ns add {
def step1 { ..helper } // ..helper = hex.helper
def step2 { .helper } // .helper = hex.add.helper (not the outer one!)
def step3 { hex.helper } // absolute
def step4 { helper } // bare: tries hex.add.helper, then hex.helper, then helper
}
}
The single-dot semantics catch newcomers off guard: .helper inside hex.add means hex.add.helper, not hex.helper. Use ..helper (one extra dot) to reach the parent.
Same namespace, multiple blocks¶
A namespace may be re-opened with another ns name { ... } block. The contents merge.
ns hex {
def add dst, src { ... }
}
ns hex { // re-opens; doesn't replace
def sub dst, src { ... }
}
Both hex.add and hex.sub exist after the assembler sees both blocks. This pattern is used throughout the STL to group related macros across header sections within a single file.
Top-level (no namespace)¶
Constants like dw and dbit live at the top level in runlib.fj, outside any ns block. They are referenced bare from anywhere:
dw = 2 * w
dbit = w + #w