jolt/.dirge/memory/PITFALLS.md
Yogthos a8c453183f Phase 4: Macro expansion in compiler
- resolve-macro: resolve symbols to macro vars via ctx
- Macro expansion in analyze-form: detects macro heads, expands, re-analyzes
- compile-ast: emits Janet data structures with resolved core fn values
- compile-and-eval uses compile-ast (no source parse roundtrip)
- eval-string routes macros through compiler (expanded at analyze time)
- Fix - mapping: core-sub (core-- doesn't exist)
- All 317 tests pass + 6 new Phase 4 macro tests
2026-06-02 15:43:08 -04:00

1.4 KiB

Janet eval scope & source-to-source failure: (eval '(core-inc 1)) fails with "unknown symbol core-inc" even when the file does (use ./core). Janet's eval runs in the default environment and doesn't see use-imported symbols. NEVER emit Janet source strings for eval. Instead emit Janet data structures where function VALUES are embedded directly: [core-inc 1] not "(core-inc 1)". Use a core-fn-values table to resolve names at compile time. The (parse s) function returns [symbol, error-position] — must use parser pipeline for proper eval: parser/new→consume→eof→produce→eval. Without parser/eof, numbers/literals return nil from produce. Janet's eval also doesn't support special forms natively in data structures — (eval [if true 1 2]) fails with "unknown symbol if". Must parse strings, not eval tuples. § When you need to mutate a local with set, use (var x nil) not (def x nil). def creates constants — (set ns-name ...) on a def fails with "cannot set constant". This hit us in loader.janet ns-name extraction loop. § core-renames MUST match actual function names defined in core.janet. "-" maps to core-sub NOT core--. "not" maps to core-not (defined as (defn core-not ...)). Missing entries cause silent nil returns. When adding to core-renames, grep core.janet for the actual (defn core-XXX ...) or (def core-XXX ...) name. Then add matching entry to core-fn-values.