summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--chapter23/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java19
-rw-r--r--chapter24/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java19
-rw-r--r--chapter25/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java8
-rw-r--r--docs/chapter-backports.md23
-rw-r--r--skills/chapter25-codex-notes.md6
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.