go: eval.sx scaffold — literals + vars + binops + 25 tests; Phase 3 closed [nothing]
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 24s
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 24s
Phase 3 — bidirectional type checker — is fully ticked (short-decl
was already implemented). Phase 4 starts here.
lib/go/eval.sx single judgment:
(go-eval ENV EXPR) → VALUE | (list :eval-error TAG ...)
ENV is an association list of (NAME VALUE) bindings — same shape as
the type checker's ctx, but the entries are runtime values. Values
are represented directly in SX: integers/floats as SX numbers,
strings as SX strings, booleans as true/false, nil as nil. Composite
values (slices/maps/structs/pointers/channels) arrive in later slices.
First-slice coverage:
* go-env-empty / -lookup / -extend
* Literal decoding:
decimal (with underscores)
hex (0x.. / 0X..)
oct (0o.. / 0O..)
bin (0b.. / 0B..)
via go-hex-digit-value (explicit char equality — SX's nth on
strings returns single-char strings, not numeric codes; the
arithmetic-on-char-codes pattern from the OCaml kernel ports
doesn't work here).
* Identifier lookup with predeclared true / false / nil.
* Binops: + - * / and the six comparison ops and && / ||.
* Errors as (:eval-error TAG ...) sentinels.
Statements (block / return / short-decl / assign), control flow
(if / for), and function application / closures arrive in subsequent
slices.
eval 25/25, total 402/402.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
215
lib/go/eval.sx
Normal file
215
lib/go/eval.sx
Normal file
@@ -0,0 +1,215 @@
|
||||
;; lib/go/eval.sx — Go tree-walk evaluator.
|
||||
;;
|
||||
;; (go-eval ENV EXPR) → VALUE | (list :eval-error TAG ...)
|
||||
;;
|
||||
;; ENV is an association list of (NAME VALUE) bindings. Per-block scope
|
||||
;; via fresh extension. Values:
|
||||
;; integers → SX numbers (decimal/hex/oct/bin literals all decoded)
|
||||
;; strings → SX strings
|
||||
;; booleans → SX true/false
|
||||
;; nil → SX nil
|
||||
;; Composite Go values (slices, maps, structs, pointers, channels)
|
||||
;; arrive in later slices.
|
||||
|
||||
(define go-env-empty (list))
|
||||
|
||||
(define
|
||||
go-env-lookup
|
||||
(fn
|
||||
(env name)
|
||||
(cond
|
||||
(= (len env) 0)
|
||||
nil
|
||||
(= (first (first env)) name)
|
||||
(nth (first env) 1)
|
||||
:else (go-env-lookup (rest env) name))))
|
||||
|
||||
(define go-env-extend (fn (env name value) (cons (list name value) env)))
|
||||
|
||||
(define
|
||||
go-eval-error?
|
||||
(fn
|
||||
(x)
|
||||
(and
|
||||
(list? x)
|
||||
(not (= (len x) 0))
|
||||
(= (first x) :eval-error))))
|
||||
|
||||
;; ── literal parsing ──────────────────────────────────────────────
|
||||
|
||||
(define
|
||||
go-hex-digit-value
|
||||
(fn
|
||||
(c)
|
||||
(cond
|
||||
(= c "0")
|
||||
0
|
||||
(= c "1")
|
||||
1
|
||||
(= c "2")
|
||||
2
|
||||
(= c "3")
|
||||
3
|
||||
(= c "4")
|
||||
4
|
||||
(= c "5")
|
||||
5
|
||||
(= c "6")
|
||||
6
|
||||
(= c "7")
|
||||
7
|
||||
(= c "8")
|
||||
8
|
||||
(= c "9")
|
||||
9
|
||||
(= c "a")
|
||||
10
|
||||
(= c "b")
|
||||
11
|
||||
(= c "c")
|
||||
12
|
||||
(= c "d")
|
||||
13
|
||||
(= c "e")
|
||||
14
|
||||
(= c "f")
|
||||
15
|
||||
(= c "A")
|
||||
10
|
||||
(= c "B")
|
||||
11
|
||||
(= c "C")
|
||||
12
|
||||
(= c "D")
|
||||
13
|
||||
(= c "E")
|
||||
14
|
||||
(= c "F")
|
||||
15
|
||||
:else -1)))
|
||||
|
||||
(define
|
||||
go-parse-radix-from
|
||||
(fn
|
||||
(v start radix)
|
||||
(define
|
||||
grf-loop
|
||||
(fn
|
||||
(i acc)
|
||||
(cond
|
||||
(>= i (len v))
|
||||
acc
|
||||
(= (nth v i) "_")
|
||||
(grf-loop (+ i 1) acc)
|
||||
:else (let
|
||||
((d (go-hex-digit-value (nth v i))))
|
||||
(cond
|
||||
(or (< d 0) (>= d radix))
|
||||
acc
|
||||
:else (grf-loop (+ i 1) (+ (* acc radix) d)))))))
|
||||
(grf-loop start 0)))
|
||||
|
||||
(define
|
||||
go-parse-int-literal
|
||||
(fn
|
||||
(v)
|
||||
(cond
|
||||
(and
|
||||
(>= (len v) 2)
|
||||
(= (nth v 0) "0")
|
||||
(or (= (nth v 1) "x") (= (nth v 1) "X")))
|
||||
(go-parse-radix-from v 2 16)
|
||||
(and
|
||||
(>= (len v) 2)
|
||||
(= (nth v 0) "0")
|
||||
(or (= (nth v 1) "b") (= (nth v 1) "B")))
|
||||
(go-parse-radix-from v 2 2)
|
||||
(and
|
||||
(>= (len v) 2)
|
||||
(= (nth v 0) "0")
|
||||
(or (= (nth v 1) "o") (= (nth v 1) "O")))
|
||||
(go-parse-radix-from v 2 8)
|
||||
:else (go-parse-radix-from v 0 10))))
|
||||
|
||||
(define
|
||||
go-eval-literal
|
||||
(fn
|
||||
(v)
|
||||
(let
|
||||
((k (go-classify-literal-string v)))
|
||||
(cond (= k :int) (go-parse-int-literal v) (= k :string) v :else v))))
|
||||
|
||||
;; ── binary ops ───────────────────────────────────────────────────
|
||||
|
||||
(define
|
||||
go-eval-binop
|
||||
(fn
|
||||
(op l r)
|
||||
(cond
|
||||
(= op "+")
|
||||
(+ l r)
|
||||
(= op "-")
|
||||
(- l r)
|
||||
(= op "*")
|
||||
(* l r)
|
||||
(= op "/")
|
||||
(/ l r)
|
||||
(= op "==")
|
||||
(= l r)
|
||||
(= op "!=")
|
||||
(not (= l r))
|
||||
(= op "<")
|
||||
(< l r)
|
||||
(= op "<=")
|
||||
(<= l r)
|
||||
(= op ">")
|
||||
(> l r)
|
||||
(= op ">=")
|
||||
(>= l r)
|
||||
(= op "&&")
|
||||
(and l r)
|
||||
(= op "||")
|
||||
(or l r)
|
||||
:else (list :eval-error :unsupported-binop op))))
|
||||
|
||||
;; ── main eval ────────────────────────────────────────────────────
|
||||
|
||||
(define
|
||||
go-eval
|
||||
(fn
|
||||
(env expr)
|
||||
(cond
|
||||
(and (list? expr) (= (first expr) :literal))
|
||||
(go-eval-literal (nth expr 1))
|
||||
(and (list? expr) (= (first expr) :var))
|
||||
(let
|
||||
((name (nth expr 1)))
|
||||
(cond
|
||||
(= name "true")
|
||||
true
|
||||
(= name "false")
|
||||
false
|
||||
(= name "nil")
|
||||
nil
|
||||
:else (let
|
||||
((v (go-env-lookup env name)))
|
||||
(cond (= v nil) (list :eval-error :unbound name) :else v))))
|
||||
(and
|
||||
(list? expr)
|
||||
(= (first expr) :app)
|
||||
(list? (nth expr 1))
|
||||
(= (first (nth expr 1)) :var)
|
||||
(= (len (nth expr 2)) 2))
|
||||
(let
|
||||
((op (nth (nth expr 1) 1))
|
||||
(args (nth expr 2)))
|
||||
(let
|
||||
((lv (go-eval env (first args)))
|
||||
(rv (go-eval env (nth args 1))))
|
||||
(cond
|
||||
(go-eval-error? lv)
|
||||
lv
|
||||
(go-eval-error? rv)
|
||||
rv
|
||||
:else (go-eval-binop op lv rv))))
|
||||
:else (list :eval-error :unsupported-eval expr))))
|
||||
Reference in New Issue
Block a user