Fix ANSI test failures: LABELS.37–39, LOOP.1.40–43, LOOP.8.10#740
Open
blakemcbride wants to merge 1 commit into
Open
Fix ANSI test failures: LABELS.37–39, LOOP.1.40–43, LOOP.8.10#740blakemcbride wants to merge 1 commit into
blakemcbride wants to merge 1 commit into
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fix ANSI test failures: LABELS.37–39, LOOP.1.40–43, LOOP.8.10
Summary
Fixes 8 ANSI Common Lisp conformance test failures across three independent root causes. All 970 tests in the LABELS / LOOP / FLET / FUNCTION categories pass after the change; no regressions observed in a 1,500+ test sample.
Tests fixed
LABELS.37,LABELS.38,LABELS.39—(eq #'f #'f)within a singleLABELS/FLETbodyLOOP.1.40,LOOP.1.41,LOOP.1.42,LOOP.1.43— iteration variable value observed inFINALLYLOOP.8.10— compiler error onTas a form under certain representationsChanges
1.
src/org/armedbear/lisp/loop.lisp— LOOP iteration variable in FINALLYPer ANSI 6.1.2.1.1, the arithmetic stepping iteration variable must retain its last in-range value when the termination test fails, so
FINALLYsees the final valid value rather than the first out-of-range step.In
loop-sequencer, when an end-test is present the stepped value is now written into a gensym temporary first; the iteration variable is only updated after the end-test passes. When no end-test is present (or it is statically true), the original direct assignment is preserved to avoid unnecessary temporaries.2.
src/org/armedbear/lisp/compiler-pass2.lisp—T/NIL/keyword as a formcompile-formdispatchedT,NIL, and keywords through a generic path that could produce a stack value in the wrong representation (e.g. unboxed boolean where aLispObjectwas required, or vice versa), breaking compilation of forms such as(the (or fixnum (eql t)) t)that LOOP can generate.The symbol branch now handles
NIL,T, and keywords explicitly: it emits the appropriate boolean or boxed constant for the requested representation and converts as needed beforeemit-move-from-stack.3.
src/org/armedbear/lisp/compiler-pass2.lisp+jvm.lisp—#'fidentity for local functionsemit-load-local-functionwrapped each#'freference to a closure-carrying local function by callingLisp.makeCompiledClosure, which allocates a freshCompiledClosureon every call. Two#'freferences in the same body therefore produced non-EQobjects, failing(eq #'f #'f).Fix: cache the closure-wrapped function once per enclosing compiland.
jvm.lisp: added aclosure-cache-registersalist slot to thelocal-functiondefstruct, mapping enclosing compiland → JVM local register holding the wrapped closure.compiler-pass2.lisp:emit-cache-local-function-closurehelper: after a local function is compiled, if it needs closure wrapping, emit themakeCompiledClosurecall once, store the result in a fresh register, and record the register in the slot.p2-flet-node/p2-labels-nodeinvoke the helper for each local function.emit-load-local-functionconsults the cache first and reuses the stored register; it falls back to the original allocate-a-fresh-closure path when no cache entry exists (e.g. self-reference or non-closure cases).This preserves the existing fast path for non-closure local functions (a direct
getstaticof the compiled function field) while giving closure-carrying locals a stable identity within the enclosing method.Verification
PPRINT-LOGICAL-BLOCK.17) is pre-existing and unrelated to these changes.Files changed
src/org/armedbear/lisp/loop.lispsrc/org/armedbear/lisp/compiler-pass2.lispsrc/org/armedbear/lisp/jvm.lisp