go: eval.sx — stmts + function application; recursive fib evaluates + 8 tests [nothing]
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 28s
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 28s
Phase 4 cont. go-eval-stmt dispatches on: :return → wraps value in (:return-value V) sentinel :var-decl → bind each NAME via go-eval-var-decl :short-decl → bind each (:var NAME) lhs to corresponding expr value :assign → immutable-env shadowing (true mutation deferred) :block → run stmts via go-eval-block, propagating :return-value :if / :else → cond-driven dispatch :func-decl → bind name to (list :go-fn PARAMS BODY) else → expression statement, evaluate for side effects go-eval-call extends the CALLER's env with param-names → arg-values (dynamic-scope-ish — closures don't capture lexical env yet), runs the body block, catches :return-value and unwraps. **Recursive fib(5) = 5 evaluates correctly.** Recursion works because top-level func bindings are in the calling env before the recursive call happens. True lexical closures (let bind sees outer var; assignments visible to nested funcs) need an env-cell model with mutation; deferred to a later slice. eval 33/33, total 410/410. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
269
lib/go/eval.sx
269
lib/go/eval.sx
@@ -174,6 +174,238 @@
|
|||||||
|
|
||||||
;; ── main eval ────────────────────────────────────────────────────
|
;; ── main eval ────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
(define
|
||||||
|
go-eval-binop-ops
|
||||||
|
(list "+" "-" "*" "/" "==" "!=" "<" "<=" ">" ">=" "&&" "||"))
|
||||||
|
|
||||||
|
(define
|
||||||
|
go-is-eval-binop?
|
||||||
|
(fn (head args)
|
||||||
|
(and (list? head) (= (first head) :var)
|
||||||
|
(= (len args) 2)
|
||||||
|
(some (fn (op) (= op (nth head 1))) go-eval-binop-ops))))
|
||||||
|
|
||||||
|
(define
|
||||||
|
go-eval-args
|
||||||
|
;; Returns a list of arg values or a (:eval-error ...).
|
||||||
|
(fn (env args)
|
||||||
|
(cond
|
||||||
|
(or (= args nil) (= (len args) 0)) (list)
|
||||||
|
:else
|
||||||
|
(let ((v (go-eval env (first args))))
|
||||||
|
(cond
|
||||||
|
(go-eval-error? v) v
|
||||||
|
:else
|
||||||
|
(let ((rest-vs (go-eval-args env (rest args))))
|
||||||
|
(cond
|
||||||
|
(go-eval-error? rest-vs) rest-vs
|
||||||
|
:else (cons v rest-vs))))))))
|
||||||
|
|
||||||
|
(define
|
||||||
|
go-flatten-param-names
|
||||||
|
;; PARAMS is a list of (:field NAMES TYPE) groups; return a flat name list.
|
||||||
|
(fn (params)
|
||||||
|
(cond
|
||||||
|
(or (= params nil) (= (len params) 0)) (list)
|
||||||
|
:else
|
||||||
|
(let ((field (first params)))
|
||||||
|
(let ((names (nth field 1)))
|
||||||
|
(go-name-concat names (go-flatten-param-names (rest params))))))))
|
||||||
|
|
||||||
|
(define
|
||||||
|
go-name-concat
|
||||||
|
(fn (a b)
|
||||||
|
(cond
|
||||||
|
(= (len a) 0) b
|
||||||
|
:else (cons (first a) (go-name-concat (rest a) b)))))
|
||||||
|
|
||||||
|
(define
|
||||||
|
go-bind-names
|
||||||
|
(fn (env names vals)
|
||||||
|
(cond
|
||||||
|
(= (len names) 0) env
|
||||||
|
:else
|
||||||
|
(go-bind-names
|
||||||
|
(go-env-extend env (first names) (first vals))
|
||||||
|
(rest names) (rest vals)))))
|
||||||
|
|
||||||
|
(define
|
||||||
|
go-eval-call
|
||||||
|
;; Apply a callable VAL to ARG-EXPRS in CALLER-ENV. Result is the
|
||||||
|
;; function's return value or a (:eval-error ...).
|
||||||
|
;;
|
||||||
|
;; Closure semantics: the function value carries no captured env in v0
|
||||||
|
;; (dynamic scope wrt outer bindings). Recursion at top level works
|
||||||
|
;; because the calling env already has the function bound. Nested
|
||||||
|
;; lexical closures arrive in a later slice.
|
||||||
|
(fn (caller-env callee-val args)
|
||||||
|
(cond
|
||||||
|
(not (and (list? callee-val) (= (first callee-val) :go-fn)))
|
||||||
|
(list :eval-error :not-callable callee-val)
|
||||||
|
:else
|
||||||
|
(let ((params (nth callee-val 1)) (body (nth callee-val 2)))
|
||||||
|
(let ((arg-vals (go-eval-args caller-env args)))
|
||||||
|
(cond
|
||||||
|
(go-eval-error? arg-vals) arg-vals
|
||||||
|
:else
|
||||||
|
(let ((param-names (go-flatten-param-names params)))
|
||||||
|
(cond
|
||||||
|
(not (= (len param-names) (len arg-vals)))
|
||||||
|
(list :eval-error :arity-mismatch
|
||||||
|
(len param-names) (len arg-vals))
|
||||||
|
:else
|
||||||
|
(let ((call-env
|
||||||
|
(go-bind-names caller-env param-names arg-vals)))
|
||||||
|
(cond
|
||||||
|
(= body nil) nil
|
||||||
|
(and (list? body) (= (first body) :block))
|
||||||
|
(let ((r (go-eval-block call-env (nth body 1))))
|
||||||
|
(cond
|
||||||
|
(and (list? r) (= (first r) :return-value))
|
||||||
|
(nth r 1)
|
||||||
|
(go-eval-error? r) r
|
||||||
|
:else nil))
|
||||||
|
:else nil))))))))))
|
||||||
|
|
||||||
|
(define
|
||||||
|
go-eval-var-decl
|
||||||
|
;; (:var-decl (:field NAMES TYPE) EXPRS) — bind each NAME to either
|
||||||
|
;; the corresponding EXPR's value or nil (zero-init when no EXPRS).
|
||||||
|
(fn (env stmt)
|
||||||
|
(let ((field (nth stmt 1)) (exprs (nth stmt 2)))
|
||||||
|
(let ((names (nth field 1)))
|
||||||
|
(cond
|
||||||
|
(or (= exprs nil) (= (len exprs) 0))
|
||||||
|
(go-bind-names env names
|
||||||
|
(go-zeros (len names)))
|
||||||
|
:else
|
||||||
|
(let ((vals (go-eval-args env exprs)))
|
||||||
|
(cond
|
||||||
|
(go-eval-error? vals) vals
|
||||||
|
:else (go-bind-names env names vals))))))))
|
||||||
|
|
||||||
|
(define
|
||||||
|
go-zeros (fn (n) (cond (<= n 0) (list) :else (cons nil (go-zeros (- n 1))))))
|
||||||
|
|
||||||
|
(define
|
||||||
|
go-eval-short-decl
|
||||||
|
;; (:short-decl LHS-LIST EXPRS) — LHS list of (:var NAME) nodes.
|
||||||
|
(fn (env stmt)
|
||||||
|
(let ((lhs-list (nth stmt 1)) (exprs (nth stmt 2)))
|
||||||
|
(let ((names
|
||||||
|
(map (fn (lhs)
|
||||||
|
(cond
|
||||||
|
(and (list? lhs) (= (first lhs) :var))
|
||||||
|
(nth lhs 1)
|
||||||
|
:else :unknown))
|
||||||
|
lhs-list)))
|
||||||
|
(let ((vals (go-eval-args env exprs)))
|
||||||
|
(cond
|
||||||
|
(go-eval-error? vals) vals
|
||||||
|
:else (go-bind-names env names vals)))))))
|
||||||
|
|
||||||
|
(define
|
||||||
|
go-eval-assign
|
||||||
|
;; v0: assignment shadows via env extension (immutable env model).
|
||||||
|
;; Mutation through closures deferred.
|
||||||
|
(fn (env stmt)
|
||||||
|
(let ((lhs-list (nth stmt 1)) (rhs-list (nth stmt 2)))
|
||||||
|
(let ((vals (go-eval-args env rhs-list)))
|
||||||
|
(cond
|
||||||
|
(go-eval-error? vals) vals
|
||||||
|
:else
|
||||||
|
(go-eval-assign-pairs env lhs-list vals))))))
|
||||||
|
|
||||||
|
(define
|
||||||
|
go-eval-assign-pairs
|
||||||
|
(fn (env lhs-list vals)
|
||||||
|
(cond
|
||||||
|
(= (len lhs-list) 0) env
|
||||||
|
:else
|
||||||
|
(let ((lhs (first lhs-list)))
|
||||||
|
(cond
|
||||||
|
(and (list? lhs) (= (first lhs) :var))
|
||||||
|
(go-eval-assign-pairs
|
||||||
|
(go-env-extend env (nth lhs 1) (first vals))
|
||||||
|
(rest lhs-list) (rest vals))
|
||||||
|
:else (list :eval-error :unsupported-lhs lhs))))))
|
||||||
|
|
||||||
|
(define
|
||||||
|
go-eval-if
|
||||||
|
(fn (env stmt)
|
||||||
|
(let ((cnd (nth stmt 1)) (then (nth stmt 2)) (els (nth stmt 3)))
|
||||||
|
(let ((c (go-eval env cnd)))
|
||||||
|
(cond
|
||||||
|
(go-eval-error? c) c
|
||||||
|
c (go-eval-stmt env then)
|
||||||
|
(not (= els nil)) (go-eval-stmt env els)
|
||||||
|
:else env)))))
|
||||||
|
|
||||||
|
(define
|
||||||
|
go-eval-func-decl
|
||||||
|
(fn (env stmt)
|
||||||
|
(let ((name (nth stmt 1)) (params (nth stmt 2))
|
||||||
|
(body (nth stmt 4)))
|
||||||
|
(go-env-extend env name (list :go-fn params body)))))
|
||||||
|
|
||||||
|
(define
|
||||||
|
go-eval-stmt
|
||||||
|
(fn (env stmt)
|
||||||
|
(cond
|
||||||
|
(and (list? stmt) (= (first stmt) :return))
|
||||||
|
(let ((exprs (nth stmt 1)))
|
||||||
|
(cond
|
||||||
|
(or (= exprs nil) (= (len exprs) 0))
|
||||||
|
(list :return-value nil)
|
||||||
|
:else
|
||||||
|
(let ((v (go-eval env (first exprs))))
|
||||||
|
(cond
|
||||||
|
(go-eval-error? v) v
|
||||||
|
:else (list :return-value v)))))
|
||||||
|
(and (list? stmt) (= (first stmt) :var-decl))
|
||||||
|
(go-eval-var-decl env stmt)
|
||||||
|
(and (list? stmt) (= (first stmt) :short-decl))
|
||||||
|
(go-eval-short-decl env stmt)
|
||||||
|
(and (list? stmt) (= (first stmt) :assign))
|
||||||
|
(go-eval-assign env stmt)
|
||||||
|
(and (list? stmt) (= (first stmt) :block))
|
||||||
|
(go-eval-block env (nth stmt 1))
|
||||||
|
(and (list? stmt) (= (first stmt) :if))
|
||||||
|
(go-eval-if env stmt)
|
||||||
|
(and (list? stmt) (= (first stmt) :func-decl))
|
||||||
|
(go-eval-func-decl env stmt)
|
||||||
|
:else
|
||||||
|
(let ((v (go-eval env stmt)))
|
||||||
|
(cond
|
||||||
|
(go-eval-error? v) v
|
||||||
|
:else env)))))
|
||||||
|
|
||||||
|
(define
|
||||||
|
go-eval-block
|
||||||
|
(fn (env stmts)
|
||||||
|
(cond
|
||||||
|
(or (= stmts nil) (= (len stmts) 0)) env
|
||||||
|
:else
|
||||||
|
(let ((r (go-eval-stmt env (first stmts))))
|
||||||
|
(cond
|
||||||
|
(and (list? r) (= (first r) :return-value)) r
|
||||||
|
(go-eval-error? r) r
|
||||||
|
:else (go-eval-block r (rest stmts)))))))
|
||||||
|
|
||||||
|
(define
|
||||||
|
go-eval-program
|
||||||
|
;; Evaluate a sequence of top-level forms in ENV. Returns the final
|
||||||
|
;; env (or :eval-error / :return-value if either propagates).
|
||||||
|
(fn (env forms)
|
||||||
|
(cond
|
||||||
|
(or (= forms nil) (= (len forms) 0)) env
|
||||||
|
:else
|
||||||
|
(let ((r (go-eval-stmt env (first forms))))
|
||||||
|
(cond
|
||||||
|
(and (list? r) (= (first r) :return-value)) r
|
||||||
|
(go-eval-error? r) r
|
||||||
|
:else (go-eval-program r (rest forms)))))))
|
||||||
|
|
||||||
(define
|
(define
|
||||||
go-eval
|
go-eval
|
||||||
(fn
|
(fn
|
||||||
@@ -185,31 +417,26 @@
|
|||||||
(let
|
(let
|
||||||
((name (nth expr 1)))
|
((name (nth expr 1)))
|
||||||
(cond
|
(cond
|
||||||
(= name "true")
|
(= name "true") true
|
||||||
true
|
(= name "false") false
|
||||||
(= name "false")
|
(= name "nil") nil
|
||||||
false
|
|
||||||
(= name "nil")
|
|
||||||
nil
|
|
||||||
:else (let
|
:else (let
|
||||||
((v (go-env-lookup env name)))
|
((v (go-env-lookup env name)))
|
||||||
(cond (= v nil) (list :eval-error :unbound name) :else v))))
|
(cond (= v nil) (list :eval-error :unbound name) :else v))))
|
||||||
(and
|
(and (list? expr) (= (first expr) :app))
|
||||||
(list? expr)
|
(let ((head (nth expr 1)) (args (nth expr 2)))
|
||||||
(= (first expr) :app)
|
(cond
|
||||||
(list? (nth expr 1))
|
(go-is-eval-binop? head args)
|
||||||
(= (first (nth expr 1)) :var)
|
(let ((op (nth head 1)))
|
||||||
(= (len (nth expr 2)) 2))
|
(let ((lv (go-eval env (first args)))
|
||||||
(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))))
|
(rv (go-eval env (nth args 1))))
|
||||||
(cond
|
(cond
|
||||||
(go-eval-error? lv)
|
(go-eval-error? lv) lv
|
||||||
lv
|
(go-eval-error? rv) rv
|
||||||
(go-eval-error? rv)
|
|
||||||
rv
|
|
||||||
:else (go-eval-binop op lv rv))))
|
:else (go-eval-binop op lv rv))))
|
||||||
|
:else
|
||||||
|
(let ((callee (go-eval env head)))
|
||||||
|
(cond
|
||||||
|
(go-eval-error? callee) callee
|
||||||
|
:else (go-eval-call env callee args)))))
|
||||||
:else (list :eval-error :unsupported-eval expr))))
|
:else (list :eval-error :unsupported-eval expr))))
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"language": "go",
|
"language": "go",
|
||||||
"total_pass": 402,
|
"total_pass": 410,
|
||||||
"total": 402,
|
"total": 410,
|
||||||
"suites": [
|
"suites": [
|
||||||
{"name":"lex","pass":129,"total":129,"status":"ok"},
|
{"name":"lex","pass":129,"total":129,"status":"ok"},
|
||||||
{"name":"parse","pass":176,"total":176,"status":"ok"},
|
{"name":"parse","pass":176,"total":176,"status":"ok"},
|
||||||
{"name":"types","pass":72,"total":72,"status":"ok"},
|
{"name":"types","pass":72,"total":72,"status":"ok"},
|
||||||
{"name":"eval","pass":25,"total":25,"status":"ok"},
|
{"name":"eval","pass":33,"total":33,"status":"ok"},
|
||||||
{"name":"runtime","pass":0,"total":0,"status":"pending"},
|
{"name":"runtime","pass":0,"total":0,"status":"pending"},
|
||||||
{"name":"stdlib","pass":0,"total":0,"status":"pending"},
|
{"name":"stdlib","pass":0,"total":0,"status":"pending"},
|
||||||
{"name":"e2e","pass":0,"total":0,"status":"pending"}
|
{"name":"e2e","pass":0,"total":0,"status":"pending"}
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
# Go-on-SX Scoreboard
|
# Go-on-SX Scoreboard
|
||||||
|
|
||||||
**Total: 402 / 402 tests passing**
|
**Total: 410 / 410 tests passing**
|
||||||
|
|
||||||
| | Suite | Pass | Total |
|
| | Suite | Pass | Total |
|
||||||
|---|---|---|---|
|
|---|---|---|---|
|
||||||
| ✅ | lex | 129 | 129 |
|
| ✅ | lex | 129 | 129 |
|
||||||
| ✅ | parse | 176 | 176 |
|
| ✅ | parse | 176 | 176 |
|
||||||
| ✅ | types | 72 | 72 |
|
| ✅ | types | 72 | 72 |
|
||||||
| ✅ | eval | 25 | 25 |
|
| ✅ | eval | 33 | 33 |
|
||||||
| ⬜ | runtime | 0 | 0 |
|
| ⬜ | runtime | 0 | 0 |
|
||||||
| ⬜ | stdlib | 0 | 0 |
|
| ⬜ | stdlib | 0 | 0 |
|
||||||
| ⬜ | e2e | 0 | 0 |
|
| ⬜ | e2e | 0 | 0 |
|
||||||
|
|||||||
@@ -90,6 +90,62 @@
|
|||||||
true)
|
true)
|
||||||
|
|
||||||
;; ── report ──────────────────────────────────────────────────────
|
;; ── report ──────────────────────────────────────────────────────
|
||||||
|
(go-eval-test
|
||||||
|
"var-decl: var x = 5 — env has x=5"
|
||||||
|
(go-env-lookup
|
||||||
|
(go-eval-program go-env-empty (list (go-parse "var x = 5")))
|
||||||
|
"x")
|
||||||
|
5)
|
||||||
|
|
||||||
|
(go-eval-test
|
||||||
|
"short-decl: a, b := 3, 4 — env has both"
|
||||||
|
(let
|
||||||
|
((env (go-eval-program go-env-empty (list (go-parse "a, b := 3, 4")))))
|
||||||
|
(list (go-env-lookup env "a") (go-env-lookup env "b")))
|
||||||
|
(list 3 4))
|
||||||
|
|
||||||
|
(go-eval-test
|
||||||
|
"assign: x = 5 then x → 5"
|
||||||
|
(let
|
||||||
|
((env (go-eval-program (go-env-extend go-env-empty "x" 1) (list (go-parse "x = 5")))))
|
||||||
|
(go-env-lookup env "x"))
|
||||||
|
5)
|
||||||
|
|
||||||
|
(go-eval-test
|
||||||
|
"if: true branch evaluates"
|
||||||
|
(let
|
||||||
|
((env (go-eval-program (go-env-extend go-env-empty "x" 0) (list (go-parse "if true { x = 1 }")))))
|
||||||
|
(go-env-lookup env "x"))
|
||||||
|
1)
|
||||||
|
|
||||||
|
(go-eval-test
|
||||||
|
"if-else: false → else branch"
|
||||||
|
(let
|
||||||
|
((env (go-eval-program (go-env-extend go-env-empty "x" 0) (list (go-parse "if false { x = 1 } else { x = 2 }")))))
|
||||||
|
(go-env-lookup env "x"))
|
||||||
|
2)
|
||||||
|
|
||||||
|
(go-eval-test
|
||||||
|
"fn: define + call — double(7) = 14"
|
||||||
|
(let
|
||||||
|
((env (go-eval-program go-env-empty (list (go-parse "func double(x int) int { return x * 2 }")))))
|
||||||
|
(go-eval env (go-parse "double(7)")))
|
||||||
|
14)
|
||||||
|
|
||||||
|
(go-eval-test
|
||||||
|
"fn: add(2, 3) = 5"
|
||||||
|
(let
|
||||||
|
((env (go-eval-program go-env-empty (list (go-parse "func add(x, y int) int { return x + y }")))))
|
||||||
|
(go-eval env (go-parse "add(2, 3)")))
|
||||||
|
5)
|
||||||
|
|
||||||
|
(go-eval-test
|
||||||
|
"fn: recursive fib(5) = 5"
|
||||||
|
(let
|
||||||
|
((env (go-eval-program go-env-empty (list (go-parse "func fib(n int) int { if n < 2 { return n } return fib(n-1) + fib(n-2) }")))))
|
||||||
|
(go-eval env (go-parse "fib(5)")))
|
||||||
|
5)
|
||||||
|
|
||||||
(define
|
(define
|
||||||
go-eval-test-summary
|
go-eval-test-summary
|
||||||
(str "eval " go-eval-test-pass "/" go-eval-test-count))
|
(str "eval " go-eval-test-pass "/" go-eval-test-count))
|
||||||
|
|||||||
@@ -270,19 +270,20 @@ Progress-log line → push `origin/loops/go`.
|
|||||||
- [x] Scaffold: env-as-value, literal decoding (decimal/hex/oct/bin
|
- [x] Scaffold: env-as-value, literal decoding (decimal/hex/oct/bin
|
||||||
with underscores), variable lookup (incl. predeclared true/false/nil),
|
with underscores), variable lookup (incl. predeclared true/false/nil),
|
||||||
arithmetic + comparison + logical binops. eval suite at 25/25.
|
arithmetic + comparison + logical binops. eval suite at 25/25.
|
||||||
- [ ] Statement evaluation: block / return / short-decl / assign /
|
- [/] Statement evaluation: block / return / short-decl / assign /
|
||||||
var-decl / if / for / break / continue.
|
var-decl / if done; for / break / continue pending.
|
||||||
- [ ] Variables as mutable cells; pointer semantics: `&x` returns the
|
- [ ] Variables as mutable cells; pointer semantics: `&x` returns the
|
||||||
cell, `*p` dereferences.
|
cell, `*p` dereferences.
|
||||||
- [ ] Slices: triple (length, capacity, backing-vector). `append`
|
- [ ] Slices: triple (length, capacity, backing-vector). `append`
|
||||||
honours capacity-grow per spec.
|
honours capacity-grow per spec.
|
||||||
- [ ] Maps: SX dict + key-type metadata.
|
- [ ] Maps: SX dict + key-type metadata.
|
||||||
- [ ] Structs: SX dict + type tag. Methods looked up via type's table.
|
- [ ] Structs: SX dict + type tag. Methods looked up via type's table.
|
||||||
- [ ] Functions: closures over enclosing scope; multiple return values.
|
- [/] Functions: top-level definition + call (incl. recursion via the
|
||||||
|
calling env). Lexical closures and multiple return values pending.
|
||||||
- [ ] Channels: stub (Phase 5 wires them).
|
- [ ] Channels: stub (Phase 5 wires them).
|
||||||
- Tests: arithmetic, control flow, recursion, closures, slices, maps,
|
- Tests: arithmetic, control flow, recursion, closures, slices, maps,
|
||||||
structs, methods, pointer semantics, multiple-return.
|
structs, methods, pointer semantics, multiple-return.
|
||||||
- **Acceptance:** eval/ suite at 80+ tests. Current: 25/25. No concurrency yet.
|
- **Acceptance:** eval/ suite at 80+ tests. Current: 33/33. No concurrency yet.
|
||||||
|
|
||||||
### Phase 5 — Goroutines + channels + select (`lib/go/sched.sx`) ⬜
|
### Phase 5 — Goroutines + channels + select (`lib/go/sched.sx`) ⬜
|
||||||
- **Independent implementation.** Do NOT use lib/guest/scheduler/ — that
|
- **Independent implementation.** Do NOT use lib/guest/scheduler/ — that
|
||||||
@@ -566,6 +567,18 @@ Minimal repro: see `lib/go/lex.sx#gl-oct-digit?` and `#gl-match-op`.
|
|||||||
|
|
||||||
_Newest first. Append one dated entry per commit._
|
_Newest first. Append one dated entry per commit._
|
||||||
|
|
||||||
|
- 2026-05-27 — Phase 4 cont.: statements + function application.
|
||||||
|
`go-eval-stmt` handles `:return` (propagates a `:return-value`
|
||||||
|
sentinel up through blocks), `:var-decl`, `:short-decl`, `:assign`
|
||||||
|
(immutable-env shadowing), `:block`, `:if`/`:else`, and `:func-decl`
|
||||||
|
(binds a `:go-fn` value). `go-eval-call` extends the caller's env
|
||||||
|
with params → arg values, runs the body block, unwraps the return.
|
||||||
|
**Recursive `fib(5) = 5` evaluates correctly** — recursion works
|
||||||
|
because top-level funcs are bound in the calling env before any
|
||||||
|
recursive call happens; the func value carries no captured env in
|
||||||
|
v0 (dynamic-scope-ish), so true lexical closures wait for a later
|
||||||
|
slice. +8 tests, eval 33/33, total 410/410. `[nothing]` — pure eval
|
||||||
|
composition.
|
||||||
- 2026-05-27 — **Phase 3 ticked; Phase 4 scaffold.** Short-decl `:=`
|
- 2026-05-27 — **Phase 3 ticked; Phase 4 scaffold.** Short-decl `:=`
|
||||||
marked done (was already covered by go-check-short-decl from the
|
marked done (was already covered by go-check-short-decl from the
|
||||||
decl-checking iteration). New `lib/go/eval.sx`: env-as-value (same
|
decl-checking iteration). New `lib/go/eval.sx`: env-as-value (same
|
||||||
|
|||||||
Reference in New Issue
Block a user