Recover agent-loop progress: lua/prolog/forth/erlang/haskell phases 1-2

Salvaged from worktree-agent-* branches killed during sx-tree MCP outage:
- lua: tokenizer + parser + phase-2 transpile (~157 tests)
- prolog: tokenizer + parser + unification (72 tests, plan update lost to WIP)
- forth: phase-1 reader/interpreter + phase-2 colon/VARIABLE (134 tests)
- erlang: tokenizer + parser (114 tests)
- haskell: tokenizer + parse tests (43 tests)

Cherry-picked file contents only, not branch history, to avoid pulling in
unrelated ocaml-vm merge commits that were in those branches' bases.
This commit is contained in:
2026-04-24 16:03:00 +00:00
parent e274878052
commit 99753580b4
32 changed files with 7803 additions and 36 deletions

104
lib/forth/reader.sx Normal file
View File

@@ -0,0 +1,104 @@
;; Forth reader — whitespace-delimited tokens.
(define
forth-whitespace?
(fn (ch) (or (= ch " ") (or (= ch "\t") (or (= ch "\n") (= ch "\r"))))))
(define
forth-tokens-loop
(fn
(src n i buf out)
(if
(>= i n)
(if (> (len buf) 0) (concat out (list buf)) out)
(let
((ch (char-at src i)))
(if
(forth-whitespace? ch)
(if
(> (len buf) 0)
(forth-tokens-loop src n (+ i 1) "" (concat out (list buf)))
(forth-tokens-loop src n (+ i 1) buf out))
(forth-tokens-loop src n (+ i 1) (str buf ch) out))))))
(define
forth-tokens
(fn (src) (forth-tokens-loop src (len src) 0 "" (list))))
(define
forth-digit-value
(fn
(ch base)
(let
((code (char-code ch)) (cc (char-code (downcase ch))))
(let
((v (if (and (>= code 48) (<= code 57)) (- code 48) (if (and (>= cc 97) (<= cc 122)) (+ 10 (- cc 97)) -1))))
(if (and (>= v 0) (< v base)) v nil)))))
(define
forth-parse-digits-loop
(fn
(src n i base acc)
(if
(>= i n)
acc
(let
((d (forth-digit-value (char-at src i) base)))
(if
(nil? d)
nil
(forth-parse-digits-loop src n (+ i 1) base (+ (* acc base) d)))))))
(define
forth-parse-digits
(fn
(src base)
(if
(= (len src) 0)
nil
(forth-parse-digits-loop src (len src) 0 base 0))))
(define
forth-strip-prefix
(fn
(s)
(if
(<= (len s) 1)
(list s 0)
(let
((c (char-at s 0)))
(if
(= c "$")
(list (substring s 1 (len s)) 16)
(if
(= c "%")
(list (substring s 1 (len s)) 2)
(if (= c "#") (list (substring s 1 (len s)) 10) (list s 0))))))))
(define
forth-parse-number
(fn
(tok base)
(let
((n (len tok)))
(if
(= n 0)
nil
(if
(and
(= n 3)
(and (= (char-at tok 0) "'") (= (char-at tok 2) "'")))
(char-code (char-at tok 1))
(let
((neg? (and (> n 1) (= (char-at tok 0) "-"))))
(let
((s1 (if neg? (substring tok 1 n) tok)))
(let
((pair (forth-strip-prefix s1)))
(let
((s (first pair)) (b-override (nth pair 1)))
(let
((b (if (= b-override 0) base b-override)))
(let
((v (forth-parse-digits s b)))
(if (nil? v) nil (if neg? (- 0 v) v)))))))))))))