diff options
5 files changed, 72 insertions, 3 deletions
diff --git a/chapter23/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java b/chapter23/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java index 88ac35c5..82631121 100644 --- a/chapter23/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java +++ b/chapter23/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java @@ -57,6 +57,13 @@ public class TypeFunPtr extends TypeNil { // All fields directly listed public static TypeFunPtr make( byte nil, boolean open, Type[] sig, Type ret, long fidxs ) { + // Trim trailing args which match the implicit default. + Type def = open ? Type.BOTTOM : Type.TOP; + int nargs = sig.length; + while( nargs > 0 && sig[nargs-1] == def ) + nargs--; + if( nargs != sig.length ) + sig = nargs == 0 ? TEMPTY : Arrays.copyOf(sig,nargs); TypeFunPtr fun = malloc(nil,open,sig,ret,fidxs); TypeFunPtr f2 = fun.intern(); if( f2==fun ) return fun; @@ -79,7 +86,17 @@ public class TypeFunPtr extends TypeNil { public static TypeFunPtr TEST0 = make((byte)3,false,TINTMEM,TypeInteger.BOT, 3); public static TypeFunPtr MAIN = make((byte)3,false,TINT ,Type.BOTTOM,-1); // Main can return anything public static TypeFunPtr CALLOC= make((byte)3,false,TINTINT,TypeMemPtr .BOT,-1); - public static void gather(ArrayList<Type> ts) { ts.add(TEST); ts.add(TEST0); ts.add(BOT); ts.add(MAIN);ts.add(CALLOC); } + public static void gather(ArrayList<Type> ts) { + ts.add(TEST); ts.add(TEST0); ts.add(BOT); ts.add(MAIN); ts.add(CALLOC); + // Explicit trailing defaults must agree with the implicit argument tail. + for( boolean open : new boolean[]{false,true} ) { + Type def = open ? Type.BOTTOM : Type.TOP; + ts.add(make((byte)2,open,TINT,TypeInteger.I32,1)); + ts.add(make((byte)2,open,new Type[]{TypeInteger.BOT,def,def},TypeInteger.I32,1)); + ts.add(make((byte)2,open,new Type[]{def,def},TypeInteger.I32,1)); + ts.add(make((byte)2,open,new Type[]{def,TypeInteger.BOT},TypeInteger.I32,1)); + } + } @Override Type xmeet(Type t) { diff --git a/chapter24/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java b/chapter24/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java index 2e957005..9fb86d96 100644 --- a/chapter24/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java +++ b/chapter24/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java @@ -57,6 +57,13 @@ public class TypeFunPtr extends TypeNil { // All fields directly listed public static TypeFunPtr make( byte nil, boolean open, Type[] sig, Type ret, long fidxs ) { + // Trim trailing args which match the implicit default. + Type def = open ? Type.BOTTOM : Type.TOP; + int nargs = sig.length; + while( nargs > 0 && sig[nargs-1] == def ) + nargs--; + if( nargs != sig.length ) + sig = nargs == 0 ? TEMPTY : Arrays.copyOf(sig,nargs); TypeFunPtr fun = malloc(nil,open,sig,ret,fidxs); TypeFunPtr f2 = fun.intern(); if( f2==fun ) return fun; @@ -79,7 +86,17 @@ public class TypeFunPtr extends TypeNil { public static TypeFunPtr TEST0 = make((byte)3,false,TINTMEM,TypeInteger.BOT, 3); public static TypeFunPtr MAIN = make((byte)3,false,TINT ,Type.BOTTOM,-1); // Main can return anything public static TypeFunPtr CALLOC= make((byte)3,false,TINTINT,TypeMemPtr .BOT,-1); - public static void gather(ArrayList<Type> ts) { ts.add(TEST); ts.add(TEST0); ts.add(BOT); ts.add(MAIN);ts.add(CALLOC); } + public static void gather(ArrayList<Type> ts) { + ts.add(TEST); ts.add(TEST0); ts.add(BOT); ts.add(MAIN); ts.add(CALLOC); + // Explicit trailing defaults must agree with the implicit argument tail. + for( boolean open : new boolean[]{false,true} ) { + Type def = open ? Type.BOTTOM : Type.TOP; + ts.add(make((byte)2,open,TINT,TypeInteger.I32,1)); + ts.add(make((byte)2,open,new Type[]{TypeInteger.BOT,def,def},TypeInteger.I32,1)); + ts.add(make((byte)2,open,new Type[]{def,def},TypeInteger.I32,1)); + ts.add(make((byte)2,open,new Type[]{def,TypeInteger.BOT},TypeInteger.I32,1)); + } + } @Override Type xmeet(Type t) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java b/chapter25/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java index fdf7fe2f..a553f90e 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java @@ -110,6 +110,14 @@ public class TypeFunPtr extends TypeNil { ts.add(make1((byte)2,true, new Type[]{TypeInteger.BOT, TypeScalar.BOT}, TypeInteger.BOT, 65)); + // Explicit trailing defaults must agree with the implicit argument tail. + for( boolean open : new boolean[]{false,true} ) { + Type def = open ? TypeScalar.BOT : TypeScalar.TOP; + ts.add(make1((byte)2,open,TINT,TypeInteger.I32,1)); + ts.add(make1((byte)2,open,new Type[]{TypeInteger.BOT,def,def},TypeInteger.I32,1)); + ts.add(make1((byte)2,open,new Type[]{def,def},TypeInteger.I32,1)); + ts.add(make1((byte)2,open,new Type[]{def,TypeInteger.BOT},TypeInteger.I32,1)); + } } private static final Type[] ARG_EMPTY = new Type[0]; diff --git a/docs/chapter-backports.md b/docs/chapter-backports.md index eae47295..74a181f8 100644 --- a/docs/chapter-backports.md +++ b/docs/chapter-backports.md @@ -72,7 +72,6 @@ Chapter 25 suite, including `make -j 4 tests`. | Register allocation and spilling | 20 onward | Need constrained-register/spill regressions; changed golden spill counts are insufficient evidence. | | Conditional Store and array Load control | Memory/arrays chapters | Reproduce under the earlier alias model before extracting fixes from the new memory implementation. | | SCCP dependencies, function revival, reachability | 24; some foundations may fit 18 | Separate old-IR corrections from new Guard/Escape/BulkMemPhi and external-caller machinery. | -| Lattice fixes in `7f3b8856` | Owning type introduction | The commit mixes TypeFunPtr, TypeMem, and new XInt/escape-summary behavior. Not a generic earlier-lattice patch. | | TypeScalar, numeric modes, guards, symbolic fields, open/forward types | Revisit earlier homes later | A connected incomplete-types architecture, including phase ordering and errors. | | BulkMemPhi/MemPhi, private constructor memory, allocation helpers | Revisit memory / constructors / methods | Move invariants and regressions together. | | Serialization, global identity remapping, module escape summaries | Separate compilation | Remain with modules. | @@ -117,6 +116,28 @@ Historical results below are dated evidence, not a substitute for a fresh baseline. Logs live in ignored build directories and may no longer exist. Reusable implementation lessons are in `skills/chapter25-codex-notes.md`. +### TypeFunPtr normalization: complete locally, 2026-09-20 + +Backported the trailing-default normalization from `7f3b8856` to 23-24, where +open/closed function argument tails first appear. Their complete `make` factory +trims trailing BOTTOM arguments for open signatures and TOP arguments for closed +signatures before interning; the existing meet uses that factory too. Raw cyclic +allocation stays unchanged. Earlier chapters use fixed TypeTuple signatures. +Chapter 25 already normalizes with scalar BOT/TOP and retains its implementation. + +Added only `gather` cases in 23-25: open/closed signatures, repeated trailing +defaults, all-default signatures, and defaults before a real argument. No new +test methods or files. The expanded existing lattice-law tests also passed +before the 23-24 fix; these cases extend coverage rather than prove an old law +failure. The other changes in `7f3b8856` concern Chapter 25's TypeMem final flags +and XInt sets, already fixed there; neither representation exists earlier. + +Fresh baselines and forced-rebuild validation passed `make -j 4 tests` in +23 (416 + 1), 24 (439 + 1), and 25 (449 total), with assertions enabled. +Focused TypeTest runs also passed all six tests in each chapter. Edited files +are LF-only and `git diff --check` passes. Logs: +`chapter25/build/tfp-normalization/{baseline,repro,validate}.log`. + ### Scheduling without isPinned: complete locally, 2026-09-20 Removed `isPinned()` and all overrides in 11-25. Early scheduling walks inputs, diff --git a/skills/chapter25-codex-notes.md b/skills/chapter25-codex-notes.md index fd5ab9d9..4fb182ff 100644 --- a/skills/chapter25-codex-notes.md +++ b/skills/chapter25-codex-notes.md @@ -228,6 +228,12 @@ Consequences: that path deterministically by interning a BOTTOM-field struct before meeting two float-constant variants; `TypeTest.testCyclicLeafKinds` in 23-25 checks the resulting field, canonical identity, and meet/dual behavior. +- Function signatures acquire implicit open/closed argument tails in 23. + Normalize trailing defaults before interning: global BOTTOM/TOP in 23-24, + scalar BOT/TOP in 25. Preserve defaults before a later non-default argument. + Keep normalization out of raw cyclic allocation, whose child slots are still + incomplete. Add representative signatures to `TypeFunPtr.gather` for the + existing lattice-law tests; no separate test harness is needed. - The type lattice must remain complete, symmetric, and bounded. Run TypeTest after changing Type/Field equality, hashing, duality, meet/join, interning, serialization, or gather sets. |
