go: eval.sx — for / break / continue / inc-dec + 7 tests [nothing]
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 26s
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 26s
Phase 4 cont. go-eval-for handles all three for-header shapes:
for { ... } — infinite (cond defaults to true)
for cond { ... } — while-like (init=nil, post=nil)
for init ; cond ; post { ... } — C-style
Implementation:
* Run INIT (if any), extending env.
* Loop: eval COND. If false, exit with current env.
Eval body (a :block). Catch sentinels:
:return-value → propagate up
:break → exit loop with pre-break env
:continue → still runs POST, then re-loops
Otherwise: run POST, re-loop.
:break and :continue propagate as keyword sentinels through
go-eval-block alongside the existing :return-value sentinel. The
block returns whichever sentinel hit first; control-flow constructs
(for, switch, select) catch them.
inc-dec (x++ / x--) updates env via the same shadowing model used by
assign — `(go-env-extend env name (+ current 1))`.
**Iterative fact(5) = 120 and the classic sum-to-9 = 45 both
evaluate.** Demonstrates the for-loop machinery is solid enough for
real programs.
eval 40/40, total 417/417.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -348,6 +348,78 @@
|
||||
(body (nth stmt 4)))
|
||||
(go-env-extend env name (list :go-fn params body)))))
|
||||
|
||||
(define
|
||||
go-eval-inc-dec
|
||||
;; (:inc-dec OP EXPR) where OP is "++" or "--". EXPR should be (:var NAME).
|
||||
(fn (env stmt)
|
||||
(let ((op (nth stmt 1)) (operand (nth stmt 2)))
|
||||
(cond
|
||||
(not (and (list? operand) (= (first operand) :var)))
|
||||
(list :eval-error :unsupported-lhs operand)
|
||||
:else
|
||||
(let ((current (go-eval env operand)))
|
||||
(cond
|
||||
(go-eval-error? current) current
|
||||
:else
|
||||
(let ((new-val
|
||||
(cond
|
||||
(= op "++") (+ current 1)
|
||||
(= op "--") (- current 1)
|
||||
:else current)))
|
||||
(go-env-extend env (nth operand 1) new-val))))))))
|
||||
|
||||
(define
|
||||
go-eval-for
|
||||
;; (:for INIT COND POST BODY). Any may be nil.
|
||||
(fn (env stmt)
|
||||
(let ((init (nth stmt 1)) (cnd (nth stmt 2))
|
||||
(post (nth stmt 3)) (body (nth stmt 4)))
|
||||
(let ((env0
|
||||
(cond
|
||||
(= init nil) env
|
||||
:else (go-eval-stmt env init))))
|
||||
(cond
|
||||
(go-eval-error? env0) env0
|
||||
:else (go-for-loop env0 cnd post body))))))
|
||||
|
||||
(define
|
||||
go-for-loop
|
||||
(fn (env cnd post body)
|
||||
(let ((c
|
||||
(cond
|
||||
(= cnd nil) true
|
||||
:else (go-eval env cnd))))
|
||||
(cond
|
||||
(go-eval-error? c) c
|
||||
(not c) env
|
||||
:else
|
||||
(let ((r
|
||||
(cond
|
||||
(= body nil) env
|
||||
(and (list? body) (= (first body) :block))
|
||||
(go-eval-block env (nth body 1))
|
||||
:else env)))
|
||||
(cond
|
||||
(and (list? r) (= (first r) :return-value)) r
|
||||
(= r :break) env
|
||||
(= r :continue)
|
||||
(let ((env1
|
||||
(cond
|
||||
(= post nil) env
|
||||
:else (go-eval-stmt env post))))
|
||||
(cond
|
||||
(go-eval-error? env1) env1
|
||||
:else (go-for-loop env1 cnd post body)))
|
||||
(go-eval-error? r) r
|
||||
:else
|
||||
(let ((env1
|
||||
(cond
|
||||
(= post nil) r
|
||||
:else (go-eval-stmt r post))))
|
||||
(cond
|
||||
(go-eval-error? env1) env1
|
||||
:else (go-for-loop env1 cnd post body)))))))))
|
||||
|
||||
(define
|
||||
go-eval-stmt
|
||||
(fn (env stmt)
|
||||
@@ -372,6 +444,12 @@
|
||||
(go-eval-block env (nth stmt 1))
|
||||
(and (list? stmt) (= (first stmt) :if))
|
||||
(go-eval-if env stmt)
|
||||
(and (list? stmt) (= (first stmt) :for))
|
||||
(go-eval-for env stmt)
|
||||
(and (list? stmt) (= (first stmt) :break)) :break
|
||||
(and (list? stmt) (= (first stmt) :continue)) :continue
|
||||
(and (list? stmt) (= (first stmt) :inc-dec))
|
||||
(go-eval-inc-dec env stmt)
|
||||
(and (list? stmt) (= (first stmt) :func-decl))
|
||||
(go-eval-func-decl env stmt)
|
||||
:else
|
||||
@@ -389,6 +467,8 @@
|
||||
(let ((r (go-eval-stmt env (first stmts))))
|
||||
(cond
|
||||
(and (list? r) (= (first r) :return-value)) r
|
||||
(= r :break) r
|
||||
(= r :continue) r
|
||||
(go-eval-error? r) r
|
||||
:else (go-eval-block r (rest stmts)))))))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user