cl: block + return-from — 13 new tests (140 eval, 312 total green)

Sentinel propagation in cl-eval-body; cl-eval-block catches matching
sentinels; BLOCK/RETURN-FROM/RETURN dispatch added to cl-eval-list.
Parser: CL strings now {:cl-type "string"} dicts for proper CL semantics.
This commit is contained in:
2026-05-05 10:57:33 +00:00
parent 3f8fe41d4d
commit ce7243a1fb
4 changed files with 76 additions and 6 deletions

View File

@@ -37,15 +37,19 @@
;; ── body evaluation ───────────────────────────────────────────────
(define cl-block-return?
(fn (v) (and (dict? v) (= (get v "cl-type") "block-return"))))
(define cl-eval-body
(fn (forms env)
(cond
((= (len forms) 0) nil)
((= (len forms) 1) (cl-eval (nth forms 0) env))
(:else
(do
(cl-eval (nth forms 0) env)
(cl-eval-body (rest forms) env))))))
(let ((result (cl-eval (nth forms 0) env)))
(if (cl-block-return? result)
result
(cl-eval-body (rest forms) env)))))))
;; ── lambda-list binding helpers ───────────────────────────────────
@@ -266,6 +270,24 @@
{:cl-type "function" :builtin-fn (get cl-builtins name)}))
(keys cl-builtins))
;; ── BLOCK / RETURN-FROM ───────────────────────────────────────────
(define cl-eval-block
(fn (args env)
(let ((name (nth args 0))
(body (rest args)))
(let ((result (cl-eval-body body env)))
(if (and (cl-block-return? result)
(= (get result "name") name))
(get result "value")
result)))))
(define cl-eval-return-from
(fn (args env)
(let ((name (nth args 0))
(val (if (> (len args) 1) (cl-eval (nth args 1) env) nil)))
{:cl-type "block-return" :name name :value val})))
;; ── special form evaluators ───────────────────────────────────────
(define cl-eval-if
@@ -541,6 +563,11 @@
((= head "LOCALLY") (cl-eval-body args env))
((= head "EVAL-WHEN") (cl-eval-eval-when args env))
((= head "DEFUN") (cl-eval-defun args env))
((= head "BLOCK") (cl-eval-block args env))
((= head "RETURN-FROM") (cl-eval-return-from args env))
((= head "RETURN")
(let ((val (if (> (len args) 0) (cl-eval (nth args 0) env) nil)))
{:cl-type "block-return" :name nil :value val}))
((= head "DEFVAR") (cl-eval-defvar args env false))
((= head "DEFPARAMETER") (cl-eval-defvar args env true))
((= head "DEFCONSTANT") (cl-eval-defvar args env true))