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:
@@ -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))
|
||||
|
||||
Reference in New Issue
Block a user