go: eval.sx — method dispatch + unary + e2e programs + 14 tests; Phase 4 bar crossed [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. The crossings:
* Method dispatch — Methods record under #method/TYPE/NAME (same
mangled-key scheme the type checker uses, intentionally so eval
and type checker can converge on a shared method-table protocol
later). go-eval-method-call: lookup the receiver type's method,
bind receiver param to the struct value, evaluate body. Value and
pointer receivers treated the same in v0 (pointer semantics not
modelled yet).
* Method-call dispatch — In go-eval's :app branch, head=:select
routes to go-eval-method-call. If the receiver is not a struct,
falls back to the field-as-callable path.
* Unary prefix ops — go-eval's :app branch checks for 1-arg :var
head with op name "-" / "+" / "!". (Other unary ops like
*p / &v / <-ch / ^x deferred until pointer / channel / bitwise
semantics arrive.)
End-to-end programs verified:
* recursive fib(10) = 55
* struct + method + iterative loop (counter bump 7 times)
* linear search (returns index or -1)
* factorial via method on Counter (= 120)
* count odd numbers in 1..10 = 5
**Phase 4 acceptance bar (80+) crossed: eval 80/80, total 457/457.**
Remaining Phase 4 work (closures, multi-return, full slice triple,
pointer semantics) refines but doesn't gate Phase 5 (goroutines).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -380,6 +380,93 @@
|
||||
:go-struct "Point"
|
||||
(list (list "x" 4) (list "y" 6))))
|
||||
|
||||
(go-eval-test
|
||||
"method: p.Sum() = 3"
|
||||
(let
|
||||
((env (go-eval-program go-env-empty (list (go-parse "type Point struct { x, y int }") (go-parse "func (p Point) Sum() int { return p.x + p.y }") (go-parse "p := Point{1, 2}")))))
|
||||
(go-eval env (go-parse "p.Sum()")))
|
||||
3)
|
||||
|
||||
(go-eval-test
|
||||
"method: p.Add(5) = 6 (with arg)"
|
||||
(let
|
||||
((env (go-eval-program go-env-empty (list (go-parse "type Point struct { x, y int }") (go-parse "func (p Point) Add(d int) int { return p.x + d }") (go-parse "p := Point{1, 2}")))))
|
||||
(go-eval env (go-parse "p.Add(5)")))
|
||||
6)
|
||||
|
||||
(go-eval-test
|
||||
"method: pointer receiver works value-style in v0"
|
||||
(let
|
||||
((env (go-eval-program go-env-empty (list (go-parse "type Point struct { x, y int }") (go-parse "func (p *Point) GetX() int { return p.x }") (go-parse "p := Point{1, 2}")))))
|
||||
(go-eval env (go-parse "p.GetX()")))
|
||||
1)
|
||||
|
||||
(go-eval-test
|
||||
"method: missing method → :no-such-method"
|
||||
(let
|
||||
((env (go-eval-program go-env-empty (list (go-parse "type Point struct { x, y int }") (go-parse "p := Point{1, 2}")))))
|
||||
(go-eval env (go-parse "p.Ghost()")))
|
||||
(list :eval-error :no-such-method "Point" "Ghost"))
|
||||
|
||||
(go-eval-test
|
||||
"unary: -x"
|
||||
(go-eval (go-env-extend go-env-empty "x" 5) (go-parse "-x"))
|
||||
-5)
|
||||
|
||||
(go-eval-test "unary: !true → false" (gtev go-env-empty "!true") false)
|
||||
|
||||
(go-eval-test "unary: !false → true" (gtev go-env-empty "!false") true)
|
||||
|
||||
(go-eval-test
|
||||
"unary: -3 + 5 = 2 (unary binds tighter)"
|
||||
(gtev go-env-empty "-3 + 5")
|
||||
2)
|
||||
|
||||
(go-eval-test
|
||||
"e2e: count odd numbers in 1..10 = 5"
|
||||
(let
|
||||
((env (go-eval-program go-env-empty
|
||||
(list (go-parse "odds := 0")
|
||||
(go-parse "i := 1")
|
||||
(go-parse "for i <= 10 { odds = odds + 1; i = i + 2 }")))))
|
||||
(go-env-lookup env "odds"))
|
||||
5)
|
||||
|
||||
(go-eval-test
|
||||
"e2e: factorial via method on Counter"
|
||||
(let
|
||||
((env (go-eval-program go-env-empty (list (go-parse "type Acc struct { v int }") (go-parse "func (a Acc) Mul(x int) Acc { return Acc{a.v * x} }") (go-parse "a := Acc{1}") (go-parse "for i := 1; i <= 5; i++ { a = a.Mul(i) }")))))
|
||||
(go-eval env (go-parse "a.v")))
|
||||
120)
|
||||
|
||||
(go-eval-test
|
||||
"e2e: recursive fibonacci fib(10) = 55"
|
||||
(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(10)")))
|
||||
55)
|
||||
|
||||
(go-eval-test
|
||||
"e2e: struct + method + iterative loop"
|
||||
(let
|
||||
((env (go-eval-program go-env-empty (list (go-parse "type Counter struct { n int }") (go-parse "func (c Counter) Bump() Counter { return Counter{c.n + 1} }") (go-parse "c := Counter{0}") (go-parse "for i := 0; i < 7; i++ { c = c.Bump() }")))))
|
||||
(go-eval env (go-parse "c.n")))
|
||||
7)
|
||||
|
||||
(go-eval-test
|
||||
"e2e: linear search returns index"
|
||||
(let
|
||||
((env (go-eval-program go-env-builtins (list (go-parse "func find(a []int, x int) int { for i := 0; i < len(a); i++ { if a[i] == x { return i } } ; return -1 }") (go-parse "nums := []int{10, 20, 30, 40}")))))
|
||||
(go-eval env (go-parse "find(nums, 30)")))
|
||||
2)
|
||||
|
||||
(go-eval-test
|
||||
"e2e: linear search returns -1 when missing"
|
||||
(let
|
||||
((env (go-eval-program go-env-builtins (list (go-parse "func find(a []int, x int) int { for i := 0; i < len(a); i++ { if a[i] == x { return i } } ; return -1 }") (go-parse "nums := []int{10, 20, 30}")))))
|
||||
(go-eval env (go-parse "find(nums, 99)")))
|
||||
-1)
|
||||
|
||||
(define
|
||||
go-eval-test-summary
|
||||
(str "eval " go-eval-test-pass "/" go-eval-test-count))
|
||||
|
||||
Reference in New Issue
Block a user