Skip to content

Fix ANSI test failures: LABELS.37–39, LOOP.1.40–43, LOOP.8.10#740

Open
blakemcbride wants to merge 1 commit into
armedbear:masterfrom
blakemcbride:labels-loop-fixes
Open

Fix ANSI test failures: LABELS.37–39, LOOP.1.40–43, LOOP.8.10#740
blakemcbride wants to merge 1 commit into
armedbear:masterfrom
blakemcbride:labels-loop-fixes

Conversation

@blakemcbride
Copy link
Copy Markdown

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 single LABELS/FLET body
  • LOOP.1.40, LOOP.1.41, LOOP.1.42, LOOP.1.43 — iteration variable value observed in FINALLY
  • LOOP.8.10 — compiler error on T as a form under certain representations

Changes

1. src/org/armedbear/lisp/loop.lisp — LOOP iteration variable in FINALLY

Per ANSI 6.1.2.1.1, the arithmetic stepping iteration variable must retain its last in-range value when the termination test fails, so FINALLY sees 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.lispT/NIL/keyword as a form

compile-form dispatched T, NIL, and keywords through a generic path that could produce a stack value in the wrong representation (e.g. unboxed boolean where a LispObject was 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 before emit-move-from-stack.

3. src/org/armedbear/lisp/compiler-pass2.lisp + jvm.lisp#'f identity for local functions

emit-load-local-function wrapped each #'f reference to a closure-carrying local function by calling Lisp.makeCompiledClosure, which allocates a fresh CompiledClosure on every call. Two #'f references in the same body therefore produced non-EQ objects, failing (eq #'f #'f).

Fix: cache the closure-wrapped function once per enclosing compiland.

  • jvm.lisp: added a closure-cache-registers alist slot to the local-function defstruct, mapping enclosing compiland → JVM local register holding the wrapped closure.
  • compiler-pass2.lisp:
    • New emit-cache-local-function-closure helper: after a local function is compiled, if it needs closure wrapping, emit the makeCompiledClosure call once, store the result in a fresh register, and record the register in the slot.
    • p2-flet-node / p2-labels-node invoke the helper for each local function.
    • emit-load-local-function consults 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 getstatic of the compiled function field) while giving closure-carrying locals a stable identity within the enclosing method.

Verification

  • All 8 originally-failing target tests pass (interpreted and compiled).
  • 970 tests across LABELS / LOOP / FLET / FUNCTION: 0 failures, 0 regressions.
  • 559 / 560 tests across HANDLER / CATCH / BLOCK / TAGBODY / LET / DESTRUCTURING / MULTIPLE-VALUE pass; the one failure (PPRINT-LOGICAL-BLOCK.17) is pre-existing and unrelated to these changes.

Files changed

  • src/org/armedbear/lisp/loop.lisp
  • src/org/armedbear/lisp/compiler-pass2.lisp
  • src/org/armedbear/lisp/jvm.lisp

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant