Evaluate non-array ISeq forms (cons/concat/lazy-seq) as calls (jolt-2rx)

eval-form treated only a reader LIST (a Janet array) as a call; a runtime-built
list — a plist or lazy-seq from cons/concat/list or ~@ (list?/seq? true but
array? false) — fell through to self-eval. So (eval (cons '+ '(1 2))) returned
the list as data instead of 3, and a macro whose output contained such a subform
left it unevaluated. Add a plist?/lazy-seq? branch that coerces to the element
array via d-realize and dispatches through eval-list; an empty list self-evals.

The analyzer already punts these forms to the interpreter (analyze's :else ->
uncompilable -> interpreter fallback), so this one interpreter branch fixes the
correctness bug across the eval and macro-expansion paths; compiling them
directly (vs punting) would be a separate perf change. Verified: conformance
355/355, syntax-quote ~@ splice, list values unchanged.
This commit is contained in:
Yogthos 2026-06-15 10:27:34 -04:00
parent a2c4fe317b
commit 80aae55977
2 changed files with 27 additions and 0 deletions

View file

@ -0,0 +1,19 @@
# Specification: a non-array ISeq (plist/lazy-seq, e.g. from cons/concat/list or
# ~@) used as a FORM is evaluated as a call, not returned as self-evaluating data
# (jolt-2rx). The interpreter only treated a reader LIST (Janet array) as a call;
# a runtime-built list (a plist/lazy-seq table) fell through to self-eval, so
# (eval (cons '+ '(1 2))) returned the list instead of 3. The analyzer already
# punts such forms to the interpreter, so the fix lives in eval-form.
(use ../support/harness)
(defspec "ISeq call forms (jolt-2rx)"
["eval a cons'd call" "3" "(eval (cons (quote +) (quote (1 2))))"]
["eval a list-built call" "6" "(eval (list (quote +) 1 2 3))"]
["eval a concat'd call" "10" "(eval (concat (list (quote +)) (list 1 2 3 4)))"]
["nested cons'd subform" "7" "(eval (list (quote +) 3 (cons (quote +) (quote (1 3)))))"]
["empty list self-evals" "()" "(eval (list))"]
["macro output via cons" "3" "(do (defmacro mc [] (cons (quote +) (quote (1 2)))) (mc))"]
["macro output via concat" "6" "(do (defmacro mk [] (concat (list (quote +)) (list 1 2 3))) (mk))"]
# regressions: vectors/quoted-data are NOT calls
["vector value self-evals" "[1 2 3]" "(eval (vec [1 2 3]))"]
["quoted list of data" "(quote (1 2 3))" "(quote (1 2 3))"])