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

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:
2026-05-27 21:17:26 +00:00
parent ff9abe3ae6
commit 1340c2626b
5 changed files with 329 additions and 33 deletions

View File

@@ -90,6 +90,62 @@
true)
;; ── 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
go-eval-test-summary
(str "eval " go-eval-test-pass "/" go-eval-test-count))