From a4994371c0b0fbea9d2802acc22d9cc3977a0de0 Mon Sep 17 00:00:00 2001 From: Cliff Click Date: Sun, 4 Oct 2026 13:30:41 -0700 Subject: Slides for 2026 REBASE --- .../main/java/com/seaofnodes/simple/Parser.java | 2 +- .../java/com/seaofnodes/simple/Chapter10Test.java | 7 +- .../main/java/com/seaofnodes/simple/Parser.java | 2 +- .../java/com/seaofnodes/simple/Chapter10Test.java | 4 +- .../main/java/com/seaofnodes/simple/Parser.java | 2 +- .../main/java/com/seaofnodes/simple/Parser.java | 2 +- .../main/java/com/seaofnodes/simple/Parser.java | 4 +- .../main/java/com/seaofnodes/simple/Parser.java | 4 +- .../main/java/com/seaofnodes/simple/Parser.java | 4 +- .../main/java/com/seaofnodes/simple/Parser.java | 4 +- .../main/java/com/seaofnodes/simple/Parser.java | 4 +- .../main/java/com/seaofnodes/simple/Parser.java | 4 +- .../main/java/com/seaofnodes/simple/Parser.java | 4 +- .../main/java/com/seaofnodes/simple/Parser.java | 4 +- .../main/java/com/seaofnodes/simple/Parser.java | 7 +- .../main/java/com/seaofnodes/simple/Parser.java | 7 +- .../main/java/com/seaofnodes/simple/Parser.java | 7 +- docs/2026_REBASE/README.md | 314 +++ docs/2026_REBASE/app.js | 303 +++ docs/2026_REBASE/assets/aliases-final.json | 406 +++ docs/2026_REBASE/assets/aliases-final.svg | 140 ++ docs/2026_REBASE/assets/arithmetic-final.json | 162 ++ docs/2026_REBASE/assets/arithmetic-final.svg | 94 + docs/2026_REBASE/assets/backend-encoded.txt | 14 + docs/2026_REBASE/assets/backend-registers.txt | 22 + docs/2026_REBASE/assets/backend-selected.txt | 30 + docs/2026_REBASE/assets/cliff-click-2020.jpeg | Bin 0 -> 408728 bytes .../assets/coffee-compiler-club-still.gif | Bin 0 -> 39680 bytes docs/2026_REBASE/assets/coffee-compiler-club.gif | Bin 0 -> 129460 bytes docs/2026_REBASE/assets/control-final.json | 588 +++++ docs/2026_REBASE/assets/control-final.svg | 171 ++ docs/2026_REBASE/assets/inline-final.json | 251 ++ docs/2026_REBASE/assets/inline-final.svg | 107 + docs/2026_REBASE/assets/memory-final.json | 1404 +++++++++++ docs/2026_REBASE/assets/memory-final.svg | 320 +++ docs/2026_REBASE/assets/rich-lattice.gv | 404 +++ docs/2026_REBASE/assets/rich-lattice.svg | 2579 ++++++++++++++++++++ docs/2026_REBASE/backend.js | 7 + docs/2026_REBASE/deck.js | 58 + docs/2026_REBASE/demos/aliases.smp | 5 + docs/2026_REBASE/demos/arithmetic.smp | 3 + docs/2026_REBASE/demos/backend.smp | 6 + docs/2026_REBASE/demos/control.smp | 9 + docs/2026_REBASE/demos/inline.smp | 3 + docs/2026_REBASE/demos/memory.smp | 10 + docs/2026_REBASE/demos/methods.smp | 11 + docs/2026_REBASE/demos/sccp.smp | 4 + docs/2026_REBASE/index.html | 41 + docs/2026_REBASE/language.js | 40 + docs/2026_REBASE/lattices.js | 128 + docs/2026_REBASE/slides.css | 38 + docs/2026_REBASE/slides.js | 214 ++ docs/2026_REBASE/stdlib.js | 17 + docs/2026_REBASE/tools/BackendDump.java | 45 + docs/2026_REBASE/tools/RichLattice.java | 59 + docs/2026_REBASE/tools/snapshot-library.py | 16 + docs/chapter-backports.md | 16 + graph/README.md | 2 +- graph/test_browser.py | 3 + graph/web/viewer.js | 4 +- 60 files changed, 8083 insertions(+), 37 deletions(-) create mode 100644 docs/2026_REBASE/README.md create mode 100644 docs/2026_REBASE/app.js create mode 100644 docs/2026_REBASE/assets/aliases-final.json create mode 100644 docs/2026_REBASE/assets/aliases-final.svg create mode 100644 docs/2026_REBASE/assets/arithmetic-final.json create mode 100644 docs/2026_REBASE/assets/arithmetic-final.svg create mode 100644 docs/2026_REBASE/assets/backend-encoded.txt create mode 100644 docs/2026_REBASE/assets/backend-registers.txt create mode 100644 docs/2026_REBASE/assets/backend-selected.txt create mode 100644 docs/2026_REBASE/assets/cliff-click-2020.jpeg create mode 100644 docs/2026_REBASE/assets/coffee-compiler-club-still.gif create mode 100644 docs/2026_REBASE/assets/coffee-compiler-club.gif create mode 100644 docs/2026_REBASE/assets/control-final.json create mode 100644 docs/2026_REBASE/assets/control-final.svg create mode 100644 docs/2026_REBASE/assets/inline-final.json create mode 100644 docs/2026_REBASE/assets/inline-final.svg create mode 100644 docs/2026_REBASE/assets/memory-final.json create mode 100644 docs/2026_REBASE/assets/memory-final.svg create mode 100644 docs/2026_REBASE/assets/rich-lattice.gv create mode 100644 docs/2026_REBASE/assets/rich-lattice.svg create mode 100644 docs/2026_REBASE/backend.js create mode 100644 docs/2026_REBASE/deck.js create mode 100644 docs/2026_REBASE/demos/aliases.smp create mode 100644 docs/2026_REBASE/demos/arithmetic.smp create mode 100644 docs/2026_REBASE/demos/backend.smp create mode 100644 docs/2026_REBASE/demos/control.smp create mode 100644 docs/2026_REBASE/demos/inline.smp create mode 100644 docs/2026_REBASE/demos/memory.smp create mode 100644 docs/2026_REBASE/demos/methods.smp create mode 100644 docs/2026_REBASE/demos/sccp.smp create mode 100644 docs/2026_REBASE/index.html create mode 100644 docs/2026_REBASE/language.js create mode 100644 docs/2026_REBASE/lattices.js create mode 100644 docs/2026_REBASE/slides.css create mode 100644 docs/2026_REBASE/slides.js create mode 100644 docs/2026_REBASE/stdlib.js create mode 100644 docs/2026_REBASE/tools/BackendDump.java create mode 100644 docs/2026_REBASE/tools/RichLattice.java create mode 100644 docs/2026_REBASE/tools/snapshot-library.py diff --git a/chapter11/src/main/java/com/seaofnodes/simple/Parser.java b/chapter11/src/main/java/com/seaofnodes/simple/Parser.java index 3b5f2721..df8d0b1c 100644 --- a/chapter11/src/main/java/com/seaofnodes/simple/Parser.java +++ b/chapter11/src/main/java/com/seaofnodes/simple/Parser.java @@ -611,7 +611,7 @@ public class Parser { Node prior = mem().keep(); Node st = new StoreNode(name,alias,prior,ptr,val).peephole(); mem(new MemMergeNode(prior,alias,st).peephole()); - prior.unkeep(); + if( prior.unkeep().isUnused() ) prior.kill(); } /** diff --git a/chapter11/src/test/java/com/seaofnodes/simple/Chapter10Test.java b/chapter11/src/test/java/com/seaofnodes/simple/Chapter10Test.java index 8bf1debe..9a5e4677 100644 --- a/chapter11/src/test/java/com/seaofnodes/simple/Chapter10Test.java +++ b/chapter11/src/test/java/com/seaofnodes/simple/Chapter10Test.java @@ -290,7 +290,8 @@ while( i.x < i.len ) { return sum; """); StopNode stop = parser.parse().iterate(); - assertEquals("return Phi(Loop16,0,(Phi(Loop,0,(Phi_x+1))+Phi_sum));", stop.toString()); + assertEquals("return Phi(Loop16,0,(Phi(Loop,0,(Phi_$2+1))+Phi_sum));", stop.toString()); + assertEquals(10L,Evaluator.evaluate(stop,5)); } @@ -549,8 +550,8 @@ return 0; if (arg) s.x=arg+1; else s.x=arg+2; return s; """).parse().iterate(); - // The initializing slice also remains live as the aggregate default. - assertEquals(2,countMemoryNodes(stop,StoreNode.class,new BitSet())); + // Releasing the old aggregate exposes the overwritten initializing Store. + assertEquals(1,countMemoryNodes(stop,StoreNode.class,new BitSet())); assertEquals(2L,((Evaluator.Obj)Evaluator.evaluate(stop,0)).fields()[0]); assertEquals(4L,((Evaluator.Obj)Evaluator.evaluate(stop,3)).fields()[0]); } diff --git a/chapter12/src/main/java/com/seaofnodes/simple/Parser.java b/chapter12/src/main/java/com/seaofnodes/simple/Parser.java index 0fa7ee0a..a25edeb1 100644 --- a/chapter12/src/main/java/com/seaofnodes/simple/Parser.java +++ b/chapter12/src/main/java/com/seaofnodes/simple/Parser.java @@ -602,7 +602,7 @@ public class Parser { Node prior = mem().keep(); Node st = new StoreNode(name,alias,glb,null,prior,ptr,val,init).peephole(); mem(new MemMergeNode(prior,alias,st).peephole()); - prior.unkeep(); + if( prior.unkeep().isUnused() ) prior.kill(); } /** diff --git a/chapter12/src/test/java/com/seaofnodes/simple/Chapter10Test.java b/chapter12/src/test/java/com/seaofnodes/simple/Chapter10Test.java index 55574c13..e5d9b882 100644 --- a/chapter12/src/test/java/com/seaofnodes/simple/Chapter10Test.java +++ b/chapter12/src/test/java/com/seaofnodes/simple/Chapter10Test.java @@ -549,8 +549,8 @@ return 0; if (arg) s.x=arg+1; else s.x=arg+2; return s; """).parse().iterate(); - // The initializing slice also remains live as the aggregate default. - assertEquals(2,countMemoryNodes(stop,StoreNode.class,new BitSet())); + // Releasing the old aggregate exposes the overwritten initializing Store. + assertEquals(1,countMemoryNodes(stop,StoreNode.class,new BitSet())); assertEquals(2L,((Evaluator.Obj)Evaluator.evaluate(stop,0)).fields()[0]); assertEquals(4L,((Evaluator.Obj)Evaluator.evaluate(stop,3)).fields()[0]); } diff --git a/chapter13/src/main/java/com/seaofnodes/simple/Parser.java b/chapter13/src/main/java/com/seaofnodes/simple/Parser.java index 32a85173..3c8d8f40 100644 --- a/chapter13/src/main/java/com/seaofnodes/simple/Parser.java +++ b/chapter13/src/main/java/com/seaofnodes/simple/Parser.java @@ -613,7 +613,7 @@ public class Parser { Node prior = mem().keep(); Node st = new StoreNode(name,alias,glb,ctrl(),prior,ptr,val,init).peephole(); mem(new MemMergeNode(prior,alias,st).peephole()); - prior.unkeep(); + if( prior.unkeep().isUnused() ) prior.kill(); } /** diff --git a/chapter14/src/main/java/com/seaofnodes/simple/Parser.java b/chapter14/src/main/java/com/seaofnodes/simple/Parser.java index bce192c2..4ab4d9ac 100644 --- a/chapter14/src/main/java/com/seaofnodes/simple/Parser.java +++ b/chapter14/src/main/java/com/seaofnodes/simple/Parser.java @@ -688,7 +688,7 @@ public class Parser { Node prior = mem().keep(); Node st = new StoreNode(name,alias,glb,ctrl(),prior,ptr,val,init).peephole(); mem(new MemMergeNode(prior,alias,st).peephole()); - prior.unkeep(); + if( prior.unkeep().isUnused() ) prior.kill(); } /** diff --git a/chapter15/src/main/java/com/seaofnodes/simple/Parser.java b/chapter15/src/main/java/com/seaofnodes/simple/Parser.java index 1fc6f312..a0c15ae3 100644 --- a/chapter15/src/main/java/com/seaofnodes/simple/Parser.java +++ b/chapter15/src/main/java/com/seaofnodes/simple/Parser.java @@ -738,7 +738,7 @@ public class Parser { mem(after.peephole()); out.unkeep(); nnn.unkeep(); - prior.unkeep(); + if( prior.unkeep().isUnused() ) prior.kill(); return ptr.unkeep(); } @@ -762,7 +762,7 @@ public class Parser { st.setDef(0,ctrl); st = st.peephole(); mem(new MemMergeNode(prior,alias,st).peephole()); - prior.unkeep(); + if( prior.unkeep().isUnused() ) prior.kill(); } /** diff --git a/chapter16/src/main/java/com/seaofnodes/simple/Parser.java b/chapter16/src/main/java/com/seaofnodes/simple/Parser.java index 97b29a37..deb359ce 100644 --- a/chapter16/src/main/java/com/seaofnodes/simple/Parser.java +++ b/chapter16/src/main/java/com/seaofnodes/simple/Parser.java @@ -824,7 +824,7 @@ public class Parser { mem(after.peephole()); out.unkeep(); nnn.unkeep(); - prior.unkeep(); + if( prior.unkeep().isUnused() ) prior.kill(); return ptr.unkeep(); } @@ -849,7 +849,7 @@ public class Parser { st.setDef(0,ctrl); st = st.peephole(); mem(new MemMergeNode(prior,alias,st).peephole()); - prior.unkeep(); + if( prior.unkeep().isUnused() ) prior.kill(); } /** diff --git a/chapter17a/src/main/java/com/seaofnodes/simple/Parser.java b/chapter17a/src/main/java/com/seaofnodes/simple/Parser.java index 23ed2fb8..f5c371cc 100644 --- a/chapter17a/src/main/java/com/seaofnodes/simple/Parser.java +++ b/chapter17a/src/main/java/com/seaofnodes/simple/Parser.java @@ -906,7 +906,7 @@ public class Parser { mem(after.peephole()); out.unkeep(); nnn.unkeep(); - prior.unkeep(); + prior.unkill(); return ptr.unkeep(); } @@ -931,7 +931,7 @@ public class Parser { st.setDef(0,ctrl); st = st.peephole(); mem(new MemMergeNode(prior,alias,st).peephole()); - prior.unkeep(); + prior.unkill(); } /** diff --git a/chapter17b/src/main/java/com/seaofnodes/simple/Parser.java b/chapter17b/src/main/java/com/seaofnodes/simple/Parser.java index 776aa91f..2d794aa5 100644 --- a/chapter17b/src/main/java/com/seaofnodes/simple/Parser.java +++ b/chapter17b/src/main/java/com/seaofnodes/simple/Parser.java @@ -1045,7 +1045,7 @@ public class Parser { mem(after.peephole()); out.unkeep(); nnn.unkeep(); - prior.unkeep(); + prior.unkill(); return ptr.unkeep(); } @@ -1070,7 +1070,7 @@ public class Parser { st.setDef(0,ctrl); st = st.peephole(); mem(new MemMergeNode(prior,alias,st).peephole()); - prior.unkeep(); + prior.unkill(); } /** diff --git a/chapter18/src/main/java/com/seaofnodes/simple/Parser.java b/chapter18/src/main/java/com/seaofnodes/simple/Parser.java index fb8e9a52..3e80aa60 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/Parser.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/Parser.java @@ -1241,7 +1241,7 @@ public class Parser { mem(after.peephole()); out.unkeep(); nnn.unkeep(); - prior.unkeep(); + prior.unkill(); return ptr.unkeep(); } @@ -1266,7 +1266,7 @@ public class Parser { st.setDef(0,ctrl); st = st.peephole(); mem(new MemMergeNode(prior,alias,st).peephole()); - prior.unkeep(); + prior.unkill(); } /** diff --git a/chapter19/src/main/java/com/seaofnodes/simple/Parser.java b/chapter19/src/main/java/com/seaofnodes/simple/Parser.java index b020ac4c..dde2d09b 100644 --- a/chapter19/src/main/java/com/seaofnodes/simple/Parser.java +++ b/chapter19/src/main/java/com/seaofnodes/simple/Parser.java @@ -1222,7 +1222,7 @@ public class Parser { mem(after.peephole()); out.unkeep(); nnn.unkeep(); - prior.unkeep(); + prior.unkill(); for( int i=0; i N ctrl(N n) { return _scope.ctrl(n); } public void parse() { + // Graph callbacks during scope setup need a source position. + _lexer = new Lexer(com.seaofnodes.simple.sys.SYS); _scope.define(ScopeNode.CTRL, Type.CONTROL , false, null, _lexer); _scope.define(ScopeNode.MEM0, TypeMem.BOT , false, null, _lexer); @@ -140,7 +142,6 @@ public class Parser { _scope.mem(con(TypeMem.BOT)); // Parse the sys import - _lexer = new Lexer(com.seaofnodes.simple.sys.SYS); while( !_lexer.isEOF() ) { parseStatement(); _lexer.skipWhiteSpace(); @@ -1309,7 +1310,7 @@ public class Parser { mem(after.peephole()); out.unkeep(); nnn.unkeep(); - prior.unkeep(); + prior.unkill(); for( int i=0; i N ctrl(N n) { return _scope.ctrl(n); } public void parse() { + // Graph callbacks during scope setup need a source position. + _lexer = new Lexer(com.seaofnodes.simple.sys.SYS); _scope.define(ScopeNode.CTRL, Type.CONTROL , false, null, _lexer); _scope.define(ScopeNode.MEM0, TypeMem.BOT , false, null, _lexer); @@ -141,7 +143,6 @@ public class Parser { _scope.mem(con(TypeMem.BOT)); // Parse the sys import - _lexer = new Lexer(com.seaofnodes.simple.sys.SYS); while( !_lexer.isEOF() ) { parseStatement(); _lexer.skipWhiteSpace(); @@ -1415,7 +1416,7 @@ public class Parser { mem(after.peephole()); out.unkeep(); nnn.unkeep(); - prior.unkeep(); + prior.unkill(); for( int i=0; i N ctrl(N n) { return _scope.ctrl(n); } public void parse() { + // Graph callbacks during scope setup need a source position. + _lexer = new Lexer(sys.SYS); _scope.define(ScopeNode.CTRL, Type.CONTROL , false, null, _lexer); _scope.define(ScopeNode.MEM0, TypeMem.BOT , false, null, _lexer); @@ -141,7 +143,6 @@ public class Parser { _scope.mem(con(TypeMem.BOT)); // Parse the sys import - _lexer = new Lexer(sys.SYS); while( !_lexer.isEOF() ) { parseStatement(); _lexer.skipWhiteSpace(); @@ -1473,7 +1474,7 @@ public class Parser { mem(after.peephole()); out.unkeep(); nnn.unkeep(); - prior.unkeep(); + prior.unkill(); for( int i=0; idocument.getElementById(id); + const presenter=new URLSearchParams(location.search).has("presenter"); + const state={index:0,step:0,demo:null,view:"example",backend:0,library:null,libraryWide:false,libraryScroll:0,methods:false}; + let held=0,started=null,toastTimeout,channel; + if(presenter) document.body.classList.add("presenter"); + try { channel=new BroadcastChannel("simple-rebase-"+location.pathname); } catch (_) {} + const current=()=>slides[state.index]; + const view=()=>current().views?.find(v=>v.id===state.view); + const steps=()=>view()?.steps??current().steps; + const elapsed=()=>held+(started===null?0:Date.now()-started); + const clock=ms=>Math.floor(ms/60000).toString().padStart(2,"0")+":"+Math.floor(ms/1000%60).toString().padStart(2,"0"); + const starts=i=>slides.slice(0,i).reduce((n,s)=>n+s.minutes,0); + function fit() { + const box=$("viewport").getBoundingClientRect(); + document.documentElement.style.setProperty("--scale",Math.min(box.width/1440,box.height/900)); + } + function readHash() { + const [id,step,tab]=location.hash.slice(1).split("/"); + const index=slides.findIndex(s=>s.id===id); + if(index>=0) { + state.index=index; + state.view=slides[index].views?.some(v=>v.id===tab)?tab:"example"; + state.step=Math.max(0,Math.min(steps(),Number(step)||0)); + state.demo=null; + } + } + function broadcast() { + if(!presenter && channel) channel.postMessage({type:"state",state:{...state},elapsed:elapsed(),running:started!==null}); + } + function render(remote=false) { + const s=current(), count=slides.filter(x=>!x.optional).length; + const v=view(), builds=steps(); + const tabs=s.views?'':""; + const number=s.optional?"BONUS":slides.slice(0,state.index+1).filter(x=>!x.optional).length; + $("slide").className="slide"+(s.still?" still":""); + $("slide").dataset.id=s.id; + $("slide").dataset.step=state.step; + $("slide").dataset.view=state.view; + $("slide").innerHTML='
'+R.escape(s.section)+''+tabs+''+(s.demo&&s.id!=="sccp"?"LIVE GRAPH":s.optional?"OPTIONAL":"REBASE 2026")+'
'+ + '
'+(v?v.body(state):s.body(state))+'
Simple / Cliff Click'+ + ''+Array.from({length:builds+1},(_,i)=>'').join("")+''+ + ''+R.escape(s.section)+' / '+number+'
'; + $("slide").querySelectorAll("[data-reveal]").forEach(el=>{ + const hidden=Number(el.dataset.reveal)>state.step; + el.classList.toggle("unrevealed",hidden); + el.setAttribute("aria-hidden",hidden?"true":"false"); + el.inert=hidden; + }); + $("slide").querySelectorAll(".state-card").forEach(card=>{ + const entries=card.querySelectorAll(".state"); + entries.forEach((el,i)=>{ + const active=i===Math.min(state.step,entries.length-1); + el.classList.toggle("active",active); + el.setAttribute("aria-hidden",String(!active)); + }); + }); + $("slide").querySelectorAll("[data-demo]").forEach(button=>{ + const active=button.dataset.demo===(state.demo||s.demo); + button.classList.toggle("active",active); + button.setAttribute("aria-pressed",String(active)); + }); + $("position").textContent=s.optional?"BONUS":number+" / "+count; + $("previous").disabled=state.index===0&&state.step===0; + $("next").disabled=state.index===slides.length-1&&state.step===builds; + $("notes-content").innerHTML=v?v.notes:s.notes; + const source=$("slide").querySelector('[data-library-scroll]'); + if(source) source.scrollTop=state.libraryScroll; + document.title=s.label+" · A Simple Tutorial"; + if(!remote) { + history.replaceState(null,"","#"+s.id+(v?"/"+state.step+"/"+v.id:state.step?"/"+state.step:"")); + broadcast(); + } + tick(); + fit(); + } + function go(id) { + const index=slides.findIndex(s=>s.id===id); + if(index<0) return; + state.index=index;state.step=0;state.demo=null;state.view="example";render(); + } + function move(direction,jump=false) { + const s=current(); + if(!jump && direction>0 && state.step0) {state.step--;render();return;} + let index=state.index+direction; + while(index>=0&&index=slides.length) return; + state.index=index;state.step=direction<0&&!jump?slides[index].steps:0;state.demo=null;state.view="example";render(); + } + function action(name,value,remote=false) { + if(presenter&&!remote&&channel) {channel.postMessage({type:"command",name,value});return;} + if(name==="next") move(1); + else if(name==="previous") move(-1); + else if(name==="next-slide") move(1,true); + else if(name==="previous-slide") move(-1,true); + else if(name==="goto") go(value); + else if(name==="demo") {state.demo=value;render();} + else if(name==="language") { + if(current().id!=="language") return; + if(value==="library-open") {state.library="sys";state.libraryScroll=0;} + else if(value==="library-close") {state.library=null;state.libraryWide=false;state.libraryScroll=0;} + else if(value==="library-width") state.libraryWide=!state.libraryWide; + else if(value==="methods-open" && state.step>=1) state.methods=true; + else if(value==="methods-close") state.methods=false; + else return; + render(); + const focus=value==="library-close"?'[data-language="library-open"]':value==="methods-close"?'[data-language="methods-open"]':value.startsWith("methods")?'[data-language="methods-close"]':'[data-language="library-close"]'; + $("slide").querySelector(focus)?.focus({preventScroll:true}); + } + else if(name==="library-path") { + if(current().id!=="language"||!R.libraryHasPath(value)) return; + state.library=value;state.libraryScroll=0;render(); + $("slide").querySelector('[data-library-scroll],.library-list')?.focus({preventScroll:true}); + } + else if(name==="library-scroll") { + if(current().id!=="language"||!Number.isFinite(value)||value<0) return; + state.libraryScroll=value; + const source=$("slide").querySelector('[data-library-scroll]'); + if(source && Math.abs(source.scrollTop-value)>1) source.scrollTop=value; + broadcast(); + } + else if(name==="backend") { + const index=Number(value); + if(current().id!=="backend"||!Number.isInteger(index)||index<0||index>state.step) return; + state.backend^=1<v.id===value)) return; + state.view=value;state.step=0;render(); + $("slide").querySelector('[data-view="'+value+'"]').focus({preventScroll:true}); + } + else if(name==="cycle-view"&¤t().views) { + const ids=["example",...current().views.map(v=>v.id)]; + action("view",ids[(ids.indexOf(state.view)+1)%ids.length],remote); + } + else if(name==="timer") { + if(started===null) started=Date.now(); + else {held=elapsed();started=null;} + tick();broadcast(); + } else if(name==="reset") {held=0;started=null;tick();broadcast();} + } + function tick() { + const s=current(), time=elapsed(), start=starts(state.index), end=start+s.minutes; + $("timer").textContent=(started===null?(held?"Resume ":"Start timer "):"Pause ")+clock(time); + $("pace").textContent=(presenter&&!channel?"Independent notes · ":"")+ + (s.optional?"Optional 2 min · replaces closing discussion":"Planned "+clock(start*60000)+"–"+clock(end*60000))+ + " · elapsed "+clock(time); + $("pace").classList.toggle("over",!s.optional&&time>end*60000); + } + function toast(message) { + clearTimeout(toastTimeout); + $("toast").textContent=message;$("toast").classList.add("show"); + toastTimeout=setTimeout(()=>$("toast").classList.remove("show"),2600); + } + function openDialog(content) { + $("dialog-content").innerHTML=content; + if(!$("dialog").open) $("dialog").showModal(); + } + async function copy(text,label) { + try { + if(!navigator.clipboard) throw new Error("No clipboard API"); + await navigator.clipboard.writeText(text); + toast(label+" copied"); + } catch (_) { + const field=document.createElement("textarea"); + field.value=text;field.style.cssText="position:fixed;left:-9999px"; + document.body.append(field);field.select(); + let ok=false; + try {ok=document.execCommand("copy");} catch (_) {} + field.remove(); + if(ok) toast(label+" copied"); + else { + openDialog('

Copy '+R.escape(label.toLowerCase())+'

Select and copy the text below.

'); + $("manual-copy").value=text;$("manual-copy").focus();$("manual-copy").select(); + } + } + } + function overview() { + openDialog('

The 30-minute route

'+slides.map(s=> + '').join("")+'
'); + } + function help() { + openDialog('

Presentation controls

'+[ + ["← / →","Previous / next build"],["Space","Next build"],["PgUp / PgDn","Previous / next slide"],["Home / End","Title / closing slide"], + ["L","Cycle example / lattice tabs"],["O","Slide overview (includes optional Chapter 25)"],["N","Toggle notes on this screen"],["P","Open synchronized presenter window"],["T","Start / pause the talk timer"],["F","Fullscreen"],["B","Blank the projection"],["Esc","Close a dialog or unblank"],["?","This help"] + ].map(([key,meaning])=>''+key+''+meaning+'').join("")+ + '

Builds advance only when you ask. The talk timer keeps running while you switch to the graph viewer. For demos: Copy code → switch to viewer → paste → Compile.

'); + } + function toggleNotes() { + if(presenter) return; + $("notes").hidden=!$("notes").hidden; + $("notes-toggle").setAttribute("aria-pressed",String(!$("notes").hidden)); + } + function openPresenter() { + const url=new URL(location.href);url.searchParams.set("presenter","1"); + const child=window.open(url,"simple-rebase-presenter","width=1400,height=850"); + if(!child) toast("Allow popups for presenter mode, or press N for notes."); + } + async function fullscreen() { + try {if(document.fullscreenElement) await document.exitFullscreen();else await document.documentElement.requestFullscreen();} + catch (_) {toast("Use your browser’s fullscreen command.");} + } + function blank() {$("blackout").hidden=!$("blackout").hidden;} + $("previous").addEventListener("click",()=>action("previous")); + $("next").addEventListener("click",()=>action("next")); + $("overview").addEventListener("click",overview); + $("help").addEventListener("click",help); + $("notes-toggle").addEventListener("click",toggleNotes); + $("presenter").addEventListener("click",openPresenter); + $("timer").addEventListener("click",()=>action("timer")); + $("timer-reset").addEventListener("click",()=>action("reset")); + $("fullscreen").addEventListener("click",fullscreen); + $("dialog-close").addEventListener("click",()=>$("dialog").close()); + $("dialog").addEventListener("click",e=>{if(e.target===$("dialog")) $("dialog").close();}); + document.addEventListener("click",e=>{ + const b=e.target.closest("[data-copy],[data-command],[data-graph],[data-goto],[data-demo],button[data-view],button[data-backend],[data-language],[data-library-path],[data-language-copy]"); + if(!b) return; + if(b.dataset.goto) {if($("dialog").open) $("dialog").close();action("goto",b.dataset.goto);} + if(b.dataset.demo) action("demo",b.dataset.demo); + if(b.dataset.backend!==undefined) action("backend",b.dataset.backend); + if(b.dataset.language) action("language",b.dataset.language); + if(b.dataset.libraryPath!==undefined) action("library-path",b.dataset.libraryPath); + if(b.dataset.languageCopy) copy(b.dataset.languageCopy==='methods'?R.library.methods:R.library.files[state.library],b.dataset.languageCopy==='methods'?'Methods example':'Source file'); + if(b.dataset.view) action("view",b.dataset.view); + if(b.dataset.copy) copy(R.demos.find(d=>d.id===b.dataset.copy).code,"Demo code"); + if(b.dataset.command) { + const d=R.demos.find(d=>d.id===b.dataset.command); + copy("make -C "+(d.viewerChapter||d.chapter)+" view","Viewer command"); + } + if(b.dataset.graph) { + const d=R.demos.find(d=>d.id===b.dataset.graph); + openDialog('

'+R.escape(d.title)+'

Captured final compiler graph for '+R.escape(d.title)+'

Captured from '+d.chapter+' after its viewer compilation phases. '+R.escape(d.inputs)+'.

Open full-size graph ↗

'); + } + }); + document.addEventListener("scroll",e=>{ + if(!e.target.matches?.('[data-library-scroll]')) return; + const top=e.target.scrollTop; + if(Math.abs(top-state.libraryScroll)>1) action("library-scroll",top); + },true); + document.addEventListener("keydown",e=>{ + if(e.ctrlKey||e.altKey||e.metaKey||e.repeat) return; + if(e.target.closest("textarea,input,select,[contenteditable=true]")) return; + if(!$("blackout").hidden) { + if(e.key==="b"||e.key==="B"||e.key==="Escape") {$("blackout").hidden=true;e.preventDefault();} + return; + } + if($("dialog").open) return; + if(e.target.closest('.library-text,.library-list') && ['ArrowUp','ArrowDown','ArrowLeft','ArrowRight','PageUp','PageDown','Home','End',' '].includes(e.key)) return; + let handled=true; + switch(e.key) { + case "ArrowRight": action("next");break; + case " ": if(e.target.closest("button,a")) {handled=false;break;} action("next");break; + case "ArrowLeft": action("previous");break; + case "PageDown": action("next-slide");break; + case "PageUp": action("previous-slide");break; + case "Home": action("goto","title");break; + case "End": action("goto","close");break; + case "o": case "O": overview();break; + case "l": case "L": action("cycle-view");break; + case "n": case "N": toggleNotes();break; + case "p": case "P": openPresenter();break; + case "t": case "T": action("timer");break; + case "f": case "F": fullscreen();break; + case "b": case "B": blank();break; + case "?": help();break; + case "Escape": if(!presenter) {$("notes").hidden=true;$("notes-toggle").setAttribute("aria-pressed","false");} break; + default: handled=false; + } + if(handled) e.preventDefault(); + }); + if(channel) channel.onmessage=e=>{ + const m=e.data; + if(m.type==="request"&&!presenter) broadcast(); + if(m.type==="command"&&!presenter) action(m.name,m.value,true); + if(m.type==="state"&&presenter) { + const changed=JSON.stringify(state)!==JSON.stringify(m.state); + const scrollOnly=changed && JSON.stringify({...state,libraryScroll:m.state.libraryScroll})===JSON.stringify(m.state); + Object.assign(state,m.state); + held=m.elapsed;started=m.running?Date.now():null; + if(changed && !scrollOnly) render(true); + else { + const source=$("slide").querySelector('[data-library-scroll]'); + if(scrollOnly && source) source.scrollTop=state.libraryScroll; + tick(); + } + } + }; + window.addEventListener("resize",fit); + window.addEventListener("hashchange",()=>{if(!presenter){readHash();render();}}); + readHash();render(); + if(presenter) {$("notes").hidden=false;if(channel) channel.postMessage({type:"request"});} + setInterval(()=>{tick();if(!presenter&&started!==null) broadcast();},1000); + // Small public surface for rehearsal and offline export tools. + R.go=id=>action("goto",id); + R.state=()=>({...state,elapsed:elapsed(),running:started!==null}); +})(); diff --git a/docs/2026_REBASE/assets/aliases-final.json b/docs/2026_REBASE/assets/aliases-final.json new file mode 100644 index 00000000..0a13477b --- /dev/null +++ b/docs/2026_REBASE/assets/aliases-final.json @@ -0,0 +1,406 @@ +{ + "ver": 1, + "comp": "rebase-aliases", + "step": 50, + "roots": [ + 2, + 3 + ], + "scope": 0, + "nodes": [ + { + "id": 2, + "label": "Start", + "type": "[ Ctrl, MemBot, int]", + "kind": "CTRL", + "edges": [ + { + "idx": 0, + "def": 0, + "role": "ASSOC", + "label": null + }, + { + "idx": 1, + "def": 0, + "role": "CTRL", + "label": null + }, + { + "idx": 2, + "def": 0, + "role": "CTRL", + "label": null + } + ], + "proj": null + }, + { + "id": 3, + "label": "Stop", + "type": "Bot", + "kind": "STOP", + "edges": [ + { + "idx": 0, + "def": 29, + "role": "CTRL", + "label": null + } + ], + "proj": null + }, + { + "id": 4, + "label": "Con", + "type": "0", + "kind": "DATA", + "edges": [ + { + "idx": 0, + "def": 2, + "role": "ASSOC", + "label": null + } + ], + "proj": null + }, + { + "id": 5, + "label": "Xctrl", + "type": "~Ctrl", + "kind": "CTRL", + "edges": [ + { + "idx": 0, + "def": 2, + "role": "ASSOC", + "label": null + } + ], + "proj": null + }, + { + "id": 6, + "label": "$ctrl", + "type": "Ctrl", + "kind": "CTRL", + "edges": [ + { + "idx": 0, + "def": 2, + "role": "CTRL", + "label": null + } + ], + "proj": { + "par": 2, + "idx": 0 + } + }, + { + "id": 7, + "label": "$mem", + "type": "MemBot", + "kind": "MEM", + "edges": [ + { + "idx": 0, + "def": 2, + "role": "MEM", + "label": null + } + ], + "proj": { + "par": 2, + "idx": 1 + } + }, + { + "id": 8, + "label": "arg", + "type": "int", + "kind": "DATA", + "edges": [ + { + "idx": 0, + "def": 2, + "role": "DATA", + "label": null + } + ], + "proj": { + "par": 2, + "idx": 2 + } + }, + { + "id": 12, + "label": "Con", + "type": "10", + "kind": "DATA", + "edges": [ + { + "idx": 0, + "def": 2, + "role": "ASSOC", + "label": null + } + ], + "proj": null + }, + { + "id": 13, + "label": "Con", + "type": "16", + "kind": "DATA", + "edges": [ + { + "idx": 0, + "def": 2, + "role": "ASSOC", + "label": null + } + ], + "proj": null + }, + { + "id": 14, + "label": "MemMerge", + "type": "MemBot", + "kind": "MEM", + "edges": [ + { + "idx": 0, + "def": 0, + "role": "CTRL", + "label": null + }, + { + "idx": 1, + "def": 0, + "role": "DATA", + "label": null + }, + { + "idx": 2, + "def": 7, + "role": "MEM", + "label": null + }, + { + "idx": 3, + "def": 7, + "role": "MEM", + "label": null + } + ], + "proj": null + }, + { + "id": 15, + "label": "new_Pair", + "type": "[ *Pair {int !x; int !y; }, MemBot]", + "kind": "DATA", + "edges": [ + { + "idx": 0, + "def": 6, + "role": "CTRL", + "label": null + }, + { + "idx": 1, + "def": 14, + "role": "MEM", + "label": null + }, + { + "idx": 2, + "def": 13, + "role": "DATA", + "label": null + }, + { + "idx": 3, + "def": 8, + "role": "DATA", + "label": null + }, + { + "idx": 4, + "def": 12, + "role": "DATA", + "label": null + } + ], + "proj": null + }, + { + "id": 16, + "label": "Pair", + "type": "*Pair {int !x; int !y; }", + "kind": "DATA", + "edges": [ + { + "idx": 0, + "def": 15, + "role": "DATA", + "label": null + } + ], + "proj": { + "par": 15, + "idx": 0 + } + }, + { + "id": 17, + "label": "$mem", + "type": "MemBot", + "kind": "MEM", + "edges": [ + { + "idx": 0, + "def": 15, + "role": "MEM", + "label": null + } + ], + "proj": { + "par": 15, + "idx": 1 + } + }, + { + "id": 21, + "label": "Con", + "type": "8", + "kind": "DATA", + "edges": [ + { + "idx": 0, + "def": 2, + "role": "ASSOC", + "label": null + } + ], + "proj": null + }, + { + "id": 22, + "label": "Con", + "type": "99", + "kind": "DATA", + "edges": [ + { + "idx": 0, + "def": 2, + "role": "ASSOC", + "label": null + } + ], + "proj": null + }, + { + "id": 23, + "label": "st_y", + "type": "MEM#3:[10-99]", + "kind": "MEM", + "edges": [ + { + "idx": 0, + "def": 0, + "role": "CTRL", + "label": null + }, + { + "idx": 1, + "def": 17, + "role": "MEM", + "label": null + }, + { + "idx": 2, + "def": 16, + "role": "DATA", + "label": null + }, + { + "idx": 3, + "def": 21, + "role": "DATA", + "label": null + }, + { + "idx": 4, + "def": 22, + "role": "DATA", + "label": null + } + ], + "proj": null + }, + { + "id": 24, + "label": "MemMerge", + "type": "MemBot", + "kind": "MEM", + "edges": [ + { + "idx": 0, + "def": 0, + "role": "CTRL", + "label": null + }, + { + "idx": 1, + "def": 7, + "role": "MEM", + "label": null + }, + { + "idx": 2, + "def": 17, + "role": "MEM", + "label": null + }, + { + "idx": 3, + "def": 23, + "role": "MEM", + "label": null + } + ], + "proj": null + }, + { + "id": 29, + "label": "Return", + "type": "[ Ctrl, MemBot, 0]", + "kind": "CTRL", + "edges": [ + { + "idx": 0, + "def": 6, + "role": "CTRL", + "label": null + }, + { + "idx": 1, + "def": 24, + "role": "MEM", + "label": null + }, + { + "idx": 2, + "def": 4, + "role": "DATA", + "label": null + } + ], + "proj": null + } + ], + "groups": [] +} diff --git a/docs/2026_REBASE/assets/aliases-final.svg b/docs/2026_REBASE/assets/aliases-final.svg new file mode 100644 index 00000000..f8b2af9e --- /dev/null +++ b/docs/2026_REBASE/assets/aliases-final.svg @@ -0,0 +1,140 @@ +#3[0] → #29 · CTRL#4[0] → #2 · ASSOC#5[0] → #2 · ASSOC#12[0] → #2 · ASSOC#13[0] → #2 · ASSOC#14[2] → #7 · MEM#14[3] → #7 · MEM#15[0] → #6 · CTRL#15[1] → #14 · MEM#15[2] → #13 · DATA#15[3] → #8 · DATA#15[4] → #12 · DATA#21[0] → #2 · ASSOC#22[0] → #2 · ASSOC#23[1] → #17 · MEM#23[2] → #16 · DATA#23[3] → #21 · DATA#23[4] → #22 · DATA#24[1] → #7 · MEM#24[2] → #17 · MEM#24[3] → #23 · MEM#29[0] → #6 · CTRL#29[1] → #24 · MEM#29[2] → #4 · DATAStart  #2[ Ctrl, MemBot, int]#2 Start +[ Ctrl, MemBot, int] + +[0] → — ASSOC +[1] → — CTRL +[2] → — CTRL012Stop  #3#3 Stop +Bot + +[0] → #29 CTRL0Con  #40#4 Con +0 + +[0] → #2 ASSOC0Xctrl  #5~Ctrl#5 Xctrl +~Ctrl + +[0] → #2 ASSOC0$ctrl  #6/0Ctrl#6 $ctrl +Projection 0 of #2 +Ctrl + +[0] → #2 CTRL$mem  #7/1MemBot#7 $mem +Projection 1 of #2 +MemBot + +[0] → #2 MEMarg  #8/2int#8 arg +Projection 2 of #2 +int + +[0] → #2 DATACon  #1210#12 Con +10 + +[0] → #2 ASSOC0Con  #1316#13 Con +16 + +[0] → #2 ASSOC0MemMerge  #14MemBot#14 MemMerge +MemBot + +[0] → — CTRL +[1] → — DATA +[2] → #7 MEM +[3] → #7 MEM0123new_Pair  #15[ *Pair {int !x; int !y; }, MemBot]#15 new_Pair +[ *Pair {int !x; int !y; }, MemBot] + +[0] → #6 CTRL +[1] → #14 MEM +[2] → #13 DATA +[3] → #8 DATA +[4] → #12 DATA01234Pair  #16/0*Pair {int !x; int !y; }#16 Pair +Projection 0 of #15 +*Pair {int !x; int !y; } + +[0] → #15 DATA$mem  #17/1MemBot#17 $mem +Projection 1 of #15 +MemBot + +[0] → #15 MEMCon  #218#21 Con +8 + +[0] → #2 ASSOC0Con  #2299#22 Con +99 + +[0] → #2 ASSOC0st_y  #23MEM#3:[10-99]#23 st_y +MEM#3:[10-99] + +[0] → — CTRL +[1] → #17 MEM +[2] → #16 DATA +[3] → #21 DATA +[4] → #22 DATA01234MemMerge  #24MemBot#24 MemMerge +MemBot + +[0] → — CTRL +[1] → #7 MEM +[2] → #17 MEM +[3] → #23 MEM0123Return  #29[ Ctrl, MemBot, 0]#29 Return +[ Ctrl, MemBot, 0] + +[0] → #6 CTRL +[1] → #24 MEM +[2] → #4 DATA012 diff --git a/docs/2026_REBASE/assets/arithmetic-final.json b/docs/2026_REBASE/assets/arithmetic-final.json new file mode 100644 index 00000000..8ac65d50 --- /dev/null +++ b/docs/2026_REBASE/assets/arithmetic-final.json @@ -0,0 +1,162 @@ +{ + "ver": 1, + "comp": "rebase-arithmetic", + "step": 50, + "roots": [ + 2, + 26 + ], + "scope": 0, + "nodes": [ + { + "id": 2, + "label": "Start", + "type": "[ Ctrl,IntBot]", + "kind": "CTRL", + "edges": [], + "proj": null + }, + { + "id": 3, + "label": "$ctrl", + "type": "Ctrl", + "kind": "CTRL", + "edges": [ + { + "idx": 0, + "def": 2, + "role": "CTRL", + "label": null + } + ], + "proj": { + "par": 2, + "idx": 0 + } + }, + { + "id": 4, + "label": "arg", + "type": "IntBot", + "kind": "DATA", + "edges": [ + { + "idx": 0, + "def": 2, + "role": "DATA", + "label": null + } + ], + "proj": { + "par": 2, + "idx": 1 + } + }, + { + "id": 19, + "label": "Con", + "type": "2", + "kind": "DATA", + "edges": [ + { + "idx": 0, + "def": 2, + "role": "ASSOC", + "label": null + } + ], + "proj": null + }, + { + "id": 20, + "label": "Mul", + "type": "IntBot", + "kind": "DATA", + "edges": [ + { + "idx": 0, + "def": 0, + "role": "CTRL", + "label": null + }, + { + "idx": 1, + "def": 4, + "role": "DATA", + "label": null + }, + { + "idx": 2, + "def": 19, + "role": "DATA", + "label": null + } + ], + "proj": null + }, + { + "id": 24, + "label": "Con", + "type": "6", + "kind": "DATA", + "edges": [ + { + "idx": 0, + "def": 2, + "role": "ASSOC", + "label": null + } + ], + "proj": null + }, + { + "id": 25, + "label": "Add", + "type": "IntBot", + "kind": "DATA", + "edges": [ + { + "idx": 0, + "def": 0, + "role": "CTRL", + "label": null + }, + { + "idx": 1, + "def": 20, + "role": "DATA", + "label": null + }, + { + "idx": 2, + "def": 24, + "role": "DATA", + "label": null + } + ], + "proj": null + }, + { + "id": 26, + "label": "Return", + "type": "[ Ctrl,IntBot]", + "kind": "CTRL", + "edges": [ + { + "idx": 0, + "def": 3, + "role": "CTRL", + "label": null + }, + { + "idx": 1, + "def": 25, + "role": "DATA", + "label": null + } + ], + "proj": null + } + ], + "groups": [] +} diff --git a/docs/2026_REBASE/assets/arithmetic-final.svg b/docs/2026_REBASE/assets/arithmetic-final.svg new file mode 100644 index 00000000..ae8452e1 --- /dev/null +++ b/docs/2026_REBASE/assets/arithmetic-final.svg @@ -0,0 +1,94 @@ +#19[0] → #2 · ASSOC#20[1] → #4 · DATA#20[2] → #19 · DATA#24[0] → #2 · ASSOC#25[1] → #20 · DATA#25[2] → #24 · DATA#26[0] → #3 · CTRL#26[1] → #25 · DATAStart  #2[ Ctrl,IntBot]#2 Start +[ Ctrl,IntBot] + +$ctrl  #3/0Ctrl#3 $ctrl +Projection 0 of #2 +Ctrl + +[0] → #2 CTRLarg  #4/1IntBot#4 arg +Projection 1 of #2 +IntBot + +[0] → #2 DATACon  #192#19 Con +2 + +[0] → #2 ASSOC0Mul  #20IntBot#20 Mul +IntBot + +[0] → — CTRL +[1] → #4 DATA +[2] → #19 DATA012Con  #246#24 Con +6 + +[0] → #2 ASSOC0Add  #25IntBot#25 Add +IntBot + +[0] → — CTRL +[1] → #20 DATA +[2] → #24 DATA012Return  #26[ Ctrl,IntBot]#26 Return +[ Ctrl,IntBot] + +[0] → #3 CTRL +[1] → #25 DATA01 diff --git a/docs/2026_REBASE/assets/backend-encoded.txt b/docs/2026_REBASE/assets/backend-encoded.txt new file mode 100644 index 00000000..ec1e9236 --- /dev/null +++ b/docs/2026_REBASE/assets/backend-encoded.txt @@ -0,0 +1,14 @@ + +--- { *Box {int !x; } int -> int #0}--------------------------- + arg:rsi,box:rdi +0000 488bc6 mov rax = rsi // def/empty1 #0 +0003 4883f800 test rax +0007 7d03 j>= L3 // L4 +L4: +0009 48f7d8 neg rax +L12: +L3: + :rax +000c 480107 add8 [rdi] += rax +000f c3 ret +--- --------------------------- diff --git a/docs/2026_REBASE/assets/backend-registers.txt b/docs/2026_REBASE/assets/backend-registers.txt new file mode 100644 index 00000000..d833b574 --- /dev/null +++ b/docs/2026_REBASE/assets/backend-registers.txt @@ -0,0 +1,22 @@ + +--- { *Box {int !x; } int -> int #0}--------------------------- + arg rsi + box rdi + r15 // r15 + r14 // r14 + r13 // r13 + r12 // r12 + rbp // rbp + rbx // rbx +0000 mov rax = rsi // def/empty1 #0 +0000 test rax +0000 j< L4 // L12 +L12: +0000 ?? JMP L3 +L4: +0001 neg rax +L3: + rax = phi( N20,N33 ) +0001 add8 [rdi] += rax +0001 ret rax [stk#33] rbx rbp r12 r13 r14 r15 +--- --------------------------- diff --git a/docs/2026_REBASE/assets/backend-selected.txt b/docs/2026_REBASE/assets/backend-selected.txt new file mode 100644 index 00000000..d09adc6b --- /dev/null +++ b/docs/2026_REBASE/assets/backend-selected.txt @@ -0,0 +1,30 @@ + 7 Start ____ ____ ____ [[ 6 11 15 18 22 ]] [ Ctrl, MemBot, int] + 11 Con 7 [[ 10 ]] int + 15 Con 7 [[ 14 ]] MemBot + 18 Con 7 [[ 17 ]] *Box + 22 Con 7 [[ 21 ]] $[ALL] + +--- { *Box {int !x; } int -> int #0}---------------------- + + 6 $fun0 ____ 7 [[ 5 10 14 17 21 ]] Ctrl + 10 arg 6 11 [[ 8 20 19 ]] int + 14 $mem 6 15 [[ 13 16 ]] MemBot + 17 box 6 18 [[ 16 ]] *Box + 21 $rpc 6 22 [[ 2 ]] $[ALL] + 8 test ____ 10 [[ 5 ]] bool + 20 neg ____ 10 [[ 19 ]] int + + 5 j< 6 8 [[ 4 12 ]] [ Ctrl, Ctrl] + + 12 False 5 [[ 3 ]] Ctrl + + 4 True 5 [[ 3 ]] Ctrl + + 3 Region ____ 4 12 [[ 2 19 ]] Ctrl + 19 Phi_ 3 20 10 [[ 16 2 ]] int + 16 add8 ____ 14 17 ____ 19 [[ 13 ]] #2:Bot + 13 MemMerg ____ 14 16 [[ 2 ]] MemBot + + 2 Return 3 13 19 21 [[ 1 ]] [ Ctrl, MemBot, int] +--- ---------------------- + 1 Stop 2 [[ ]] Bot diff --git a/docs/2026_REBASE/assets/cliff-click-2020.jpeg b/docs/2026_REBASE/assets/cliff-click-2020.jpeg new file mode 100644 index 00000000..8e1fd801 Binary files /dev/null and b/docs/2026_REBASE/assets/cliff-click-2020.jpeg differ diff --git a/docs/2026_REBASE/assets/coffee-compiler-club-still.gif b/docs/2026_REBASE/assets/coffee-compiler-club-still.gif new file mode 100644 index 00000000..16616ab9 Binary files /dev/null and b/docs/2026_REBASE/assets/coffee-compiler-club-still.gif differ diff --git a/docs/2026_REBASE/assets/coffee-compiler-club.gif b/docs/2026_REBASE/assets/coffee-compiler-club.gif new file mode 100644 index 00000000..b3d7e292 Binary files /dev/null and b/docs/2026_REBASE/assets/coffee-compiler-club.gif differ diff --git a/docs/2026_REBASE/assets/control-final.json b/docs/2026_REBASE/assets/control-final.json new file mode 100644 index 00000000..6161328b --- /dev/null +++ b/docs/2026_REBASE/assets/control-final.json @@ -0,0 +1,588 @@ +{ + "ver": 1, + "comp": "rebase-control", + "step": 64, + "roots": [ + 2, + 3 + ], + "scope": 0, + "nodes": [ + { + "id": 2, + "label": "Start", + "type": "[Ctrl,IntBot]", + "kind": "CTRL", + "edges": [], + "proj": null + }, + { + "id": 3, + "label": "Stop", + "type": "Bot", + "kind": "STOP", + "edges": [ + { + "idx": 0, + "def": 32, + "role": "CTRL", + "label": null + } + ], + "proj": null + }, + { + "id": 4, + "label": "$ctrl", + "type": "Ctrl", + "kind": "CTRL", + "edges": [ + { + "idx": 0, + "def": 2, + "role": "CTRL", + "label": null + } + ], + "proj": { + "par": 2, + "idx": 0 + } + }, + { + "id": 5, + "label": "arg", + "type": "IntBot", + "kind": "DATA", + "edges": [ + { + "idx": 0, + "def": 2, + "role": "DATA", + "label": null + } + ], + "proj": { + "par": 2, + "idx": 1 + } + }, + { + "id": 6, + "label": "Con", + "type": "0", + "kind": "DATA", + "edges": [ + { + "idx": 0, + "def": 2, + "role": "ASSOC", + "label": null + } + ], + "proj": null + }, + { + "id": 7, + "label": "LT", + "type": "IntBot", + "kind": "DATA", + "edges": [ + { + "idx": 0, + "def": 0, + "role": "CTRL", + "label": null + }, + { + "idx": 1, + "def": 5, + "role": "DATA", + "label": null + }, + { + "idx": 2, + "def": 6, + "role": "DATA", + "label": null + } + ], + "proj": null + }, + { + "id": 8, + "label": "If", + "type": "[Ctrl,Ctrl]", + "kind": "CTRL", + "edges": [ + { + "idx": 0, + "def": 4, + "role": "CTRL", + "label": null + }, + { + "idx": 1, + "def": 7, + "role": "DATA", + "label": null + } + ], + "proj": null + }, + { + "id": 9, + "label": "True", + "type": "Ctrl", + "kind": "CTRL", + "edges": [ + { + "idx": 0, + "def": 8, + "role": "CTRL", + "label": null + } + ], + "proj": { + "par": 8, + "idx": 0 + } + }, + { + "id": 10, + "label": "False", + "type": "Ctrl", + "kind": "CTRL", + "edges": [ + { + "idx": 0, + "def": 8, + "role": "CTRL", + "label": null + } + ], + "proj": { + "par": 8, + "idx": 1 + } + }, + { + "id": 12, + "label": "Minus", + "type": "IntBot", + "kind": "DATA", + "edges": [ + { + "idx": 0, + "def": 0, + "role": "CTRL", + "label": null + }, + { + "idx": 1, + "def": 5, + "role": "DATA", + "label": null + } + ], + "proj": null + }, + { + "id": 13, + "label": "Region", + "type": "Ctrl", + "kind": "REGION", + "edges": [ + { + "idx": 0, + "def": 0, + "role": "ASSOC", + "label": null + }, + { + "idx": 1, + "def": 9, + "role": "CTRL", + "label": null + }, + { + "idx": 2, + "def": 10, + "role": "CTRL", + "label": null + } + ], + "proj": null + }, + { + "id": 14, + "label": "Phi_n", + "type": "IntBot", + "kind": "PHI", + "edges": [ + { + "idx": 0, + "def": 13, + "role": "ASSOC", + "label": null + }, + { + "idx": 1, + "def": 12, + "role": "DATA", + "label": null + }, + { + "idx": 2, + "def": 5, + "role": "DATA", + "label": null + } + ], + "proj": null + }, + { + "id": 15, + "label": "Con", + "type": "0", + "kind": "DATA", + "edges": [ + { + "idx": 0, + "def": 2, + "role": "ASSOC", + "label": null + } + ], + "proj": null + }, + { + "id": 16, + "label": "Con", + "type": "0", + "kind": "DATA", + "edges": [ + { + "idx": 0, + "def": 2, + "role": "ASSOC", + "label": null + } + ], + "proj": null + }, + { + "id": 17, + "label": "Loop", + "type": "Ctrl", + "kind": "LOOP", + "edges": [ + { + "idx": 0, + "def": 0, + "role": "ASSOC", + "label": null + }, + { + "idx": 1, + "def": 13, + "role": "CTRL", + "label": null + }, + { + "idx": 2, + "def": 23, + "role": "CTRL", + "label": null + } + ], + "proj": null + }, + { + "id": 19, + "label": "Phi_i", + "type": "IntBot", + "kind": "PHI", + "edges": [ + { + "idx": 0, + "def": 17, + "role": "ASSOC", + "label": null + }, + { + "idx": 1, + "def": 16, + "role": "DATA", + "label": null + }, + { + "idx": 2, + "def": 27, + "role": "DATA", + "label": null + } + ], + "proj": null + }, + { + "id": 21, + "label": "LT", + "type": "IntBot", + "kind": "DATA", + "edges": [ + { + "idx": 0, + "def": 0, + "role": "CTRL", + "label": null + }, + { + "idx": 1, + "def": 19, + "role": "DATA", + "label": null + }, + { + "idx": 2, + "def": 14, + "role": "DATA", + "label": null + } + ], + "proj": null + }, + { + "id": 22, + "label": "If", + "type": "[Ctrl,Ctrl]", + "kind": "CTRL", + "edges": [ + { + "idx": 0, + "def": 17, + "role": "CTRL", + "label": null + }, + { + "idx": 1, + "def": 21, + "role": "DATA", + "label": null + } + ], + "proj": null + }, + { + "id": 23, + "label": "True", + "type": "Ctrl", + "kind": "CTRL", + "edges": [ + { + "idx": 0, + "def": 22, + "role": "CTRL", + "label": null + } + ], + "proj": { + "par": 22, + "idx": 0 + } + }, + { + "id": 24, + "label": "False", + "type": "Ctrl", + "kind": "CTRL", + "edges": [ + { + "idx": 0, + "def": 22, + "role": "CTRL", + "label": null + } + ], + "proj": { + "par": 22, + "idx": 1 + } + }, + { + "id": 26, + "label": "Con", + "type": "1", + "kind": "DATA", + "edges": [ + { + "idx": 0, + "def": 2, + "role": "ASSOC", + "label": null + } + ], + "proj": null + }, + { + "id": 27, + "label": "Add", + "type": "IntBot", + "kind": "DATA", + "edges": [ + { + "idx": 0, + "def": 0, + "role": "CTRL", + "label": null + }, + { + "idx": 1, + "def": 19, + "role": "DATA", + "label": null + }, + { + "idx": 2, + "def": 26, + "role": "DATA", + "label": null + } + ], + "proj": null + }, + { + "id": 28, + "label": "Phi_sum", + "type": "IntBot", + "kind": "PHI", + "edges": [ + { + "idx": 0, + "def": 17, + "role": "ASSOC", + "label": null + }, + { + "idx": 1, + "def": 15, + "role": "DATA", + "label": null + }, + { + "idx": 2, + "def": 31, + "role": "DATA", + "label": null + } + ], + "proj": null + }, + { + "id": 30, + "label": "Add", + "type": "IntBot", + "kind": "DATA", + "edges": [ + { + "idx": 0, + "def": 0, + "role": "CTRL", + "label": null + }, + { + "idx": 1, + "def": 28, + "role": "DATA", + "label": null + }, + { + "idx": 2, + "def": 19, + "role": "DATA", + "label": null + } + ], + "proj": null + }, + { + "id": 31, + "label": "Add", + "type": "IntBot", + "kind": "DATA", + "edges": [ + { + "idx": 0, + "def": 0, + "role": "CTRL", + "label": null + }, + { + "idx": 1, + "def": 30, + "role": "DATA", + "label": null + }, + { + "idx": 2, + "def": 26, + "role": "DATA", + "label": null + } + ], + "proj": null + }, + { + "id": 32, + "label": "Return", + "type": "[Ctrl,IntBot]", + "kind": "CTRL", + "edges": [ + { + "idx": 0, + "def": 24, + "role": "CTRL", + "label": null + }, + { + "idx": 1, + "def": 28, + "role": "DATA", + "label": null + } + ], + "proj": null + } + ], + "groups": [ + { + "id": 8, + "par": 0, + "nodes": [ + 7, + 8, + 9, + 10, + 12, + 13, + 14 + ] + }, + { + "id": 17, + "par": 0, + "nodes": [ + 17, + 19, + 21, + 22, + 23, + 24, + 27, + 28, + 30, + 31 + ] + } + ] +} diff --git a/docs/2026_REBASE/assets/control-final.svg b/docs/2026_REBASE/assets/control-final.svg new file mode 100644 index 00000000..32e933aa --- /dev/null +++ b/docs/2026_REBASE/assets/control-final.svg @@ -0,0 +1,171 @@ +#3[0] → #32 · CTRL#6[0] → #2 · ASSOC#7[1] → #5 · DATA#7[2] → #6 · DATA#8[0] → #4 · CTRL#8[1] → #7 · DATA#12[1] → #5 · DATA#13[1] → #9 · CTRL#13[2] → #10 · CTRL#14[1] → #12 · DATA#14[2] → #5 · DATA#15[0] → #2 · ASSOC#16[0] → #2 · ASSOC#17[1] → #13 · CTRL#17[2] → #23 · CTRL#19[1] → #16 · DATA#19[2] → #27 · DATA#21[1] → #19 · DATA#21[2] → #14 · DATA#22[0] → #17 · CTRL#22[1] → #21 · DATA#26[0] → #2 · ASSOC#27[1] → #19 · DATA#27[2] → #26 · DATA#28[1] → #15 · DATA#28[2] → #31 · DATA#30[1] → #28 · DATA#30[2] → #19 · DATA#31[1] → #30 · DATA#31[2] → #26 · DATA#32[0] → #24 · CTRL#32[1] → #28 · DATAStart  #2[Ctrl,IntBot]#2 Start +[Ctrl,IntBot] + +Stop  #3#3 Stop +Bot + +[0] → #32 CTRL0$ctrl  #4/0Ctrl#4 $ctrl +Projection 0 of #2 +Ctrl + +[0] → #2 CTRLarg  #5/1IntBot#5 arg +Projection 1 of #2 +IntBot + +[0] → #2 DATACon  #60#6 Con +0 + +[0] → #2 ASSOC0LT  #7IntBot#7 LT +IntBot + +[0] → — CTRL +[1] → #5 DATA +[2] → #6 DATA012If  #8[Ctrl,Ctrl]#8 If +[Ctrl,Ctrl] + +[0] → #4 CTRL +[1] → #7 DATA01True  #9/0Ctrl#9 True +Projection 0 of #8 +Ctrl + +[0] → #8 CTRLFalse  #10/1Ctrl#10 False +Projection 1 of #8 +Ctrl + +[0] → #8 CTRLMinus  #12IntBot#12 Minus +IntBot + +[0] → — CTRL +[1] → #5 DATA01Region  #13Ctrl#13 Region +Ctrl + +[0] → — ASSOC +[1] → #9 CTRL +[2] → #10 CTRL012Phi_n  #14IntBot#14 Phi_n +IntBot + +[0] → #13 ASSOC +[1] → #12 DATA +[2] → #5 DATA[0] → #13012Con  #150#15 Con +0 + +[0] → #2 ASSOC0Con  #160#16 Con +0 + +[0] → #2 ASSOC0Loop  #17Ctrl#17 Loop +Ctrl + +[0] → — ASSOC +[1] → #13 CTRL +[2] → #23 CTRL012Phi_i  #19IntBot#19 Phi_i +IntBot + +[0] → #17 ASSOC +[1] → #16 DATA +[2] → #27 DATA[0] → #17012LT  #21IntBot#21 LT +IntBot + +[0] → — CTRL +[1] → #19 DATA +[2] → #14 DATA012If  #22[Ctrl,Ctrl]#22 If +[Ctrl,Ctrl] + +[0] → #17 CTRL +[1] → #21 DATA01True  #23/0Ctrl#23 True +Projection 0 of #22 +Ctrl + +[0] → #22 CTRLFalse  #24/1Ctrl#24 False +Projection 1 of #22 +Ctrl + +[0] → #22 CTRLCon  #261#26 Con +1 + +[0] → #2 ASSOC0Add  #27IntBot#27 Add +IntBot + +[0] → — CTRL +[1] → #19 DATA +[2] → #26 DATA012Phi_sum  #28IntBot#28 Phi_sum +IntBot + +[0] → #17 ASSOC +[1] → #15 DATA +[2] → #31 DATA[0] → #17012Add  #30IntBot#30 Add +IntBot + +[0] → — CTRL +[1] → #28 DATA +[2] → #19 DATA012Add  #31IntBot#31 Add +IntBot + +[0] → — CTRL +[1] → #30 DATA +[2] → #26 DATA012Return  #32[Ctrl,IntBot]#32 Return +[Ctrl,IntBot] + +[0] → #24 CTRL +[1] → #28 DATA01If  #8If · 7 nodes−Fold regionLoop  #17Loop · 10 nodes−Fold region diff --git a/docs/2026_REBASE/assets/inline-final.json b/docs/2026_REBASE/assets/inline-final.json new file mode 100644 index 00000000..35e1568e --- /dev/null +++ b/docs/2026_REBASE/assets/inline-final.json @@ -0,0 +1,251 @@ +{ + "ver": 1, + "comp": "rebase-inline", + "step": 160, + "roots": [ + 3 + ], + "scope": 0, + "nodes": [ + { + "id": 2, + "label": "Start", + "type": "[ Ctrl, MemBot, int]", + "kind": "CTRL", + "edges": [ + { + "idx": 0, + "def": 0, + "role": "ASSOC", + "label": null + }, + { + "idx": 1, + "def": 0, + "role": "CTRL", + "label": null + }, + { + "idx": 2, + "def": 0, + "role": "CTRL", + "label": null + } + ], + "proj": null + }, + { + "id": 3, + "label": "Stop", + "type": "Bot", + "kind": "STOP", + "edges": [ + { + "idx": 0, + "def": 14, + "role": "CTRL", + "label": null + } + ], + "proj": null + }, + { + "id": 4, + "label": "Con", + "type": "0", + "kind": "DATA", + "edges": [ + { + "idx": 0, + "def": 2, + "role": "ASSOC", + "label": null + } + ], + "proj": null + }, + { + "id": 5, + "label": "Con", + "type": "null", + "kind": "DATA", + "edges": [ + { + "idx": 0, + "def": 2, + "role": "ASSOC", + "label": null + } + ], + "proj": null + }, + { + "id": 6, + "label": "Xctrl", + "type": "~Ctrl", + "kind": "CTRL", + "edges": [ + { + "idx": 0, + "def": 2, + "role": "ASSOC", + "label": null + } + ], + "proj": null + }, + { + "id": 7, + "label": "Con", + "type": "MemBot", + "kind": "MEM", + "edges": [ + { + "idx": 0, + "def": 2, + "role": "ASSOC", + "label": null + } + ], + "proj": null + }, + { + "id": 8, + "label": "main", + "type": "Ctrl", + "kind": "FUN", + "edges": [ + { + "idx": 0, + "def": 0, + "role": "ASSOC", + "label": null + }, + { + "idx": 1, + "def": 2, + "role": "CTRL", + "label": null + } + ], + "proj": null + }, + { + "id": 9, + "label": "Con", + "type": "$[ALL]", + "kind": "DATA", + "edges": [ + { + "idx": 0, + "def": 2, + "role": "ASSOC", + "label": null + } + ], + "proj": null + }, + { + "id": 10, + "label": "$rpc", + "type": "$[ALL]", + "kind": "PHI", + "edges": [ + { + "idx": 0, + "def": 8, + "role": "ASSOC", + "label": null + }, + { + "idx": 1, + "def": 9, + "role": "DATA", + "label": null + } + ], + "proj": null + }, + { + "id": 14, + "label": "Return", + "type": "[ Ctrl, MemBot, 11]", + "kind": "CTRL", + "edges": [ + { + "idx": 0, + "def": 8, + "role": "CTRL", + "label": null + }, + { + "idx": 1, + "def": 16, + "role": "MEM", + "label": null + }, + { + "idx": 2, + "def": 66, + "role": "DATA", + "label": null + }, + { + "idx": 3, + "def": 10, + "role": "DATA", + "label": null + } + ], + "proj": null + }, + { + "id": 16, + "label": "$mem", + "type": "MemBot", + "kind": "PHI", + "edges": [ + { + "idx": 0, + "def": 8, + "role": "ASSOC", + "label": null + }, + { + "idx": 1, + "def": 7, + "role": "MEM", + "label": null + } + ], + "proj": null + }, + { + "id": 66, + "label": "Con", + "type": "11", + "kind": "DATA", + "edges": [ + { + "idx": 0, + "def": 2, + "role": "ASSOC", + "label": null + } + ], + "proj": null + } + ], + "groups": [ + { + "id": 8, + "par": 0, + "nodes": [ + 8, + 10, + 14, + 16 + ] + } + ] +} diff --git a/docs/2026_REBASE/assets/inline-final.svg b/docs/2026_REBASE/assets/inline-final.svg new file mode 100644 index 00000000..bd862ec3 --- /dev/null +++ b/docs/2026_REBASE/assets/inline-final.svg @@ -0,0 +1,107 @@ +#3[0] → #14 · CTRL#4[0] → #2 · ASSOC#5[0] → #2 · ASSOC#6[0] → #2 · ASSOC#7[0] → #2 · ASSOC#8[1] → #2 · CTRL#9[0] → #2 · ASSOC#10[1] → #9 · DATA#14[0] → #8 · CTRL#14[1] → #16 · MEM#14[2] → #66 · DATA#14[3] → #10 · DATA#16[1] → #7 · MEM#66[0] → #2 · ASSOCStart  #2[ Ctrl, MemBot, int]#2 Start +[ Ctrl, MemBot, int] + +[0] → — ASSOC +[1] → — CTRL +[2] → — CTRL012Stop  #3#3 Stop +Bot + +[0] → #14 CTRL0Con  #40#4 Con +0 + +[0] → #2 ASSOC0Con  #5null#5 Con +null + +[0] → #2 ASSOC0Xctrl  #6~Ctrl#6 Xctrl +~Ctrl + +[0] → #2 ASSOC0Con  #7MemBot#7 Con +MemBot + +[0] → #2 ASSOC0main  #8Ctrl#8 main +Ctrl + +[0] → — ASSOC +[1] → #2 CTRL01Con  #9$[ALL]#9 Con +$[ALL] + +[0] → #2 ASSOC0$rpc  #10$[ALL]#10 $rpc +$[ALL] + +[0] → #8 ASSOC +[1] → #9 DATA[0] → #801Return  #14[ Ctrl, MemBot, 11]#14 Return +[ Ctrl, MemBot, 11] + +[0] → #8 CTRL +[1] → #16 MEM +[2] → #66 DATA +[3] → #10 DATA0123$mem  #16MemBot#16 $mem +MemBot + +[0] → #8 ASSOC +[1] → #7 MEM[0] → #801Con  #6611#66 Con +11 + +[0] → #2 ASSOC0main  #8main · 4 nodes−Fold region diff --git a/docs/2026_REBASE/assets/memory-final.json b/docs/2026_REBASE/assets/memory-final.json new file mode 100644 index 00000000..e2f378ed --- /dev/null +++ b/docs/2026_REBASE/assets/memory-final.json @@ -0,0 +1,1404 @@ +{ + "ver": 1, + "comp": "rebase-memory", + "step": 318, + "roots": [ + 2, + 3 + ], + "scope": 0, + "nodes": [ + { + "id": 2, + "label": "Start", + "type": "[ Ctrl, MemBot, int]", + "kind": "CTRL", + "edges": [ + { + "idx": 0, + "def": 0, + "role": "ASSOC", + "label": null + }, + { + "idx": 1, + "def": 0, + "role": "CTRL", + "label": null + }, + { + "idx": 2, + "def": 0, + "role": "CTRL", + "label": null + } + ], + "proj": null + }, + { + "id": 3, + "label": "Stop", + "type": "Bot", + "kind": "STOP", + "edges": [ + { + "idx": 0, + "def": 115, + "role": "CTRL", + "label": null + } + ], + "proj": null + }, + { + "id": 4, + "label": "Con", + "type": "0", + "kind": "DATA", + "edges": [ + { + "idx": 0, + "def": 2, + "role": "ASSOC", + "label": null + } + ], + "proj": null + }, + { + "id": 5, + "label": "Xctrl", + "type": "~Ctrl", + "kind": "CTRL", + "edges": [ + { + "idx": 0, + "def": 2, + "role": "ASSOC", + "label": null + } + ], + "proj": null + }, + { + "id": 6, + "label": "$ctrl", + "type": "Ctrl", + "kind": "CTRL", + "edges": [ + { + "idx": 0, + "def": 2, + "role": "CTRL", + "label": null + } + ], + "proj": { + "par": 2, + "idx": 0 + } + }, + { + "id": 7, + "label": "$mem", + "type": "MemBot", + "kind": "MEM", + "edges": [ + { + "idx": 0, + "def": 2, + "role": "MEM", + "label": null + } + ], + "proj": { + "par": 2, + "idx": 1 + } + }, + { + "id": 8, + "label": "arg", + "type": "int", + "kind": "DATA", + "edges": [ + { + "idx": 0, + "def": 2, + "role": "DATA", + "label": null + } + ], + "proj": { + "par": 2, + "idx": 2 + } + }, + { + "id": 12, + "label": "Con", + "type": "16", + "kind": "DATA", + "edges": [ + { + "idx": 0, + "def": 2, + "role": "ASSOC", + "label": null + } + ], + "proj": null + }, + { + "id": 13, + "label": "MemMerge", + "type": "MemBot", + "kind": "MEM", + "edges": [ + { + "idx": 0, + "def": 0, + "role": "CTRL", + "label": null + }, + { + "idx": 1, + "def": 0, + "role": "DATA", + "label": null + }, + { + "idx": 2, + "def": 7, + "role": "MEM", + "label": null + }, + { + "idx": 3, + "def": 7, + "role": "MEM", + "label": null + } + ], + "proj": null + }, + { + "id": 14, + "label": "new_Totals", + "type": "[ *Totals {int !sum; int !visits; }, MemBot]", + "kind": "DATA", + "edges": [ + { + "idx": 0, + "def": 6, + "role": "CTRL", + "label": null + }, + { + "idx": 1, + "def": 13, + "role": "MEM", + "label": null + }, + { + "idx": 2, + "def": 12, + "role": "DATA", + "label": null + }, + { + "idx": 3, + "def": 4, + "role": "DATA", + "label": null + }, + { + "idx": 4, + "def": 4, + "role": "DATA", + "label": null + } + ], + "proj": null + }, + { + "id": 15, + "label": "Totals", + "type": "*Totals {int !sum; int !visits; }", + "kind": "DATA", + "edges": [ + { + "idx": 0, + "def": 14, + "role": "DATA", + "label": null + } + ], + "proj": { + "par": 14, + "idx": 0 + } + }, + { + "id": 16, + "label": "$mem", + "type": "MemBot", + "kind": "MEM", + "edges": [ + { + "idx": 0, + "def": 14, + "role": "MEM", + "label": null + } + ], + "proj": { + "par": 14, + "idx": 1 + } + }, + { + "id": 18, + "label": "Con", + "type": "4", + "kind": "DATA", + "edges": [ + { + "idx": 0, + "def": 2, + "role": "ASSOC", + "label": null + } + ], + "proj": null + }, + { + "id": 24, + "label": "Con", + "type": "40", + "kind": "DATA", + "edges": [ + { + "idx": 0, + "def": 2, + "role": "ASSOC", + "label": null + } + ], + "proj": null + }, + { + "id": 26, + "label": "MemMerge", + "type": "MemBot", + "kind": "MEM", + "edges": [ + { + "idx": 0, + "def": 0, + "role": "CTRL", + "label": null + }, + { + "idx": 1, + "def": 0, + "role": "DATA", + "label": null + }, + { + "idx": 2, + "def": 0, + "role": "DATA", + "label": null + }, + { + "idx": 3, + "def": 0, + "role": "DATA", + "label": null + }, + { + "idx": 4, + "def": 7, + "role": "MEM", + "label": null + }, + { + "idx": 5, + "def": 7, + "role": "MEM", + "label": null + } + ], + "proj": null + }, + { + "id": 27, + "label": "new_ary_int", + "type": "[ *[int] {int #; int ![]; }, MemBot]", + "kind": "DATA", + "edges": [ + { + "idx": 0, + "def": 6, + "role": "CTRL", + "label": null + }, + { + "idx": 1, + "def": 26, + "role": "MEM", + "label": null + }, + { + "idx": 2, + "def": 24, + "role": "DATA", + "label": null + }, + { + "idx": 3, + "def": 18, + "role": "DATA", + "label": null + }, + { + "idx": 4, + "def": 4, + "role": "DATA", + "label": null + } + ], + "proj": null + }, + { + "id": 28, + "label": "[int]", + "type": "*[int] {int #; int ![]; }", + "kind": "DATA", + "edges": [ + { + "idx": 0, + "def": 27, + "role": "DATA", + "label": null + } + ], + "proj": { + "par": 27, + "idx": 0 + } + }, + { + "id": 29, + "label": "$mem", + "type": "MemBot", + "kind": "MEM", + "edges": [ + { + "idx": 0, + "def": 27, + "role": "MEM", + "label": null + } + ], + "proj": { + "par": 27, + "idx": 1 + } + }, + { + "id": 32, + "label": "Loop", + "type": "Ctrl", + "kind": "LOOP", + "edges": [ + { + "idx": 0, + "def": 0, + "role": "ASSOC", + "label": null + }, + { + "idx": 1, + "def": 6, + "role": "CTRL", + "label": null + }, + { + "idx": 2, + "def": 41, + "role": "CTRL", + "label": null + } + ], + "proj": null + }, + { + "id": 34, + "label": "Phi_i", + "type": "int", + "kind": "PHI", + "edges": [ + { + "idx": 0, + "def": 32, + "role": "ASSOC", + "label": null + }, + { + "idx": 1, + "def": 4, + "role": "DATA", + "label": null + }, + { + "idx": 2, + "def": 60, + "role": "DATA", + "label": null + } + ], + "proj": null + }, + { + "id": 35, + "label": "LT", + "type": "bool", + "kind": "DATA", + "edges": [ + { + "idx": 0, + "def": 0, + "role": "CTRL", + "label": null + }, + { + "idx": 1, + "def": 34, + "role": "DATA", + "label": null + }, + { + "idx": 2, + "def": 18, + "role": "DATA", + "label": null + } + ], + "proj": null + }, + { + "id": 40, + "label": "If", + "type": "[ Ctrl, Ctrl]", + "kind": "CTRL", + "edges": [ + { + "idx": 0, + "def": 32, + "role": "CTRL", + "label": null + }, + { + "idx": 1, + "def": 35, + "role": "DATA", + "label": null + } + ], + "proj": null + }, + { + "id": 41, + "label": "True", + "type": "Ctrl", + "kind": "CTRL", + "edges": [ + { + "idx": 0, + "def": 40, + "role": "CTRL", + "label": null + } + ], + "proj": { + "par": 40, + "idx": 0 + } + }, + { + "id": 42, + "label": "False", + "type": "Ctrl", + "kind": "CTRL", + "edges": [ + { + "idx": 0, + "def": 40, + "role": "CTRL", + "label": null + } + ], + "proj": { + "par": 40, + "idx": 1 + } + }, + { + "id": 46, + "label": "Con", + "type": "1", + "kind": "DATA", + "edges": [ + { + "idx": 0, + "def": 2, + "role": "ASSOC", + "label": null + } + ], + "proj": null + }, + { + "id": 51, + "label": "Con", + "type": "8", + "kind": "DATA", + "edges": [ + { + "idx": 0, + "def": 2, + "role": "ASSOC", + "label": null + } + ], + "proj": null + }, + { + "id": 52, + "label": "Con", + "type": "3", + "kind": "DATA", + "edges": [ + { + "idx": 0, + "def": 2, + "role": "ASSOC", + "label": null + } + ], + "proj": null + }, + { + "id": 53, + "label": "Shl", + "type": "int", + "kind": "DATA", + "edges": [ + { + "idx": 0, + "def": 0, + "role": "CTRL", + "label": null + }, + { + "idx": 1, + "def": 34, + "role": "DATA", + "label": null + }, + { + "idx": 2, + "def": 52, + "role": "DATA", + "label": null + } + ], + "proj": null + }, + { + "id": 54, + "label": "Add", + "type": "int", + "kind": "DATA", + "edges": [ + { + "idx": 0, + "def": 0, + "role": "CTRL", + "label": null + }, + { + "idx": 1, + "def": 53, + "role": "DATA", + "label": null + }, + { + "idx": 2, + "def": 51, + "role": "DATA", + "label": null + } + ], + "proj": null + }, + { + "id": 56, + "label": "Add", + "type": "int", + "kind": "DATA", + "edges": [ + { + "idx": 0, + "def": 0, + "role": "CTRL", + "label": null + }, + { + "idx": 1, + "def": 34, + "role": "DATA", + "label": null + }, + { + "idx": 2, + "def": 8, + "role": "DATA", + "label": null + } + ], + "proj": null + }, + { + "id": 57, + "label": "st_ary", + "type": "MEM#5:Bot", + "kind": "MEM", + "edges": [ + { + "idx": 0, + "def": 41, + "role": "CTRL", + "label": null + }, + { + "idx": 1, + "def": 124, + "role": "MEM", + "label": null + }, + { + "idx": 2, + "def": 28, + "role": "DATA", + "label": null + }, + { + "idx": 3, + "def": 54, + "role": "DATA", + "label": null + }, + { + "idx": 4, + "def": 56, + "role": "DATA", + "label": null + } + ], + "proj": null + }, + { + "id": 60, + "label": "Add", + "type": "int", + "kind": "DATA", + "edges": [ + { + "idx": 0, + "def": 0, + "role": "CTRL", + "label": null + }, + { + "idx": 1, + "def": 34, + "role": "DATA", + "label": null + }, + { + "idx": 2, + "def": 46, + "role": "DATA", + "label": null + } + ], + "proj": null + }, + { + "id": 65, + "label": "Loop", + "type": "Ctrl", + "kind": "LOOP", + "edges": [ + { + "idx": 0, + "def": 0, + "role": "ASSOC", + "label": null + }, + { + "idx": 1, + "def": 42, + "role": "CTRL", + "label": null + }, + { + "idx": 2, + "def": 74, + "role": "CTRL", + "label": null + } + ], + "proj": null + }, + { + "id": 67, + "label": "Phi_i", + "type": "int", + "kind": "PHI", + "edges": [ + { + "idx": 0, + "def": 65, + "role": "ASSOC", + "label": null + }, + { + "idx": 1, + "def": 4, + "role": "DATA", + "label": null + }, + { + "idx": 2, + "def": 103, + "role": "DATA", + "label": null + } + ], + "proj": null + }, + { + "id": 68, + "label": "LT", + "type": "bool", + "kind": "DATA", + "edges": [ + { + "idx": 0, + "def": 0, + "role": "CTRL", + "label": null + }, + { + "idx": 1, + "def": 67, + "role": "DATA", + "label": null + }, + { + "idx": 2, + "def": 18, + "role": "DATA", + "label": null + } + ], + "proj": null + }, + { + "id": 73, + "label": "If", + "type": "[ Ctrl, Ctrl]", + "kind": "CTRL", + "edges": [ + { + "idx": 0, + "def": 65, + "role": "CTRL", + "label": null + }, + { + "idx": 1, + "def": 68, + "role": "DATA", + "label": null + } + ], + "proj": null + }, + { + "id": 74, + "label": "True", + "type": "Ctrl", + "kind": "CTRL", + "edges": [ + { + "idx": 0, + "def": 73, + "role": "CTRL", + "label": null + } + ], + "proj": { + "par": 73, + "idx": 0 + } + }, + { + "id": 75, + "label": "False", + "type": "Ctrl", + "kind": "CTRL", + "edges": [ + { + "idx": 0, + "def": 73, + "role": "CTRL", + "label": null + } + ], + "proj": { + "par": 73, + "idx": 1 + } + }, + { + "id": 88, + "label": "Add", + "type": "int", + "kind": "DATA", + "edges": [ + { + "idx": 0, + "def": 0, + "role": "CTRL", + "label": null + }, + { + "idx": 1, + "def": 131, + "role": "DATA", + "label": null + }, + { + "idx": 2, + "def": 93, + "role": "DATA", + "label": null + } + ], + "proj": null + }, + { + "id": 91, + "label": "Shl", + "type": "int", + "kind": "DATA", + "edges": [ + { + "idx": 0, + "def": 0, + "role": "CTRL", + "label": null + }, + { + "idx": 1, + "def": 67, + "role": "DATA", + "label": null + }, + { + "idx": 2, + "def": 52, + "role": "DATA", + "label": null + } + ], + "proj": null + }, + { + "id": 92, + "label": "Add", + "type": "int", + "kind": "DATA", + "edges": [ + { + "idx": 0, + "def": 0, + "role": "CTRL", + "label": null + }, + { + "idx": 1, + "def": 91, + "role": "DATA", + "label": null + }, + { + "idx": 2, + "def": 51, + "role": "DATA", + "label": null + } + ], + "proj": null + }, + { + "id": 93, + "label": "ld_ary", + "type": "int", + "kind": "DATA", + "edges": [ + { + "idx": 0, + "def": 74, + "role": "CTRL", + "label": null + }, + { + "idx": 1, + "def": 124, + "role": "MEM", + "label": null + }, + { + "idx": 2, + "def": 28, + "role": "DATA", + "label": null + }, + { + "idx": 3, + "def": 92, + "role": "DATA", + "label": null + } + ], + "proj": null + }, + { + "id": 94, + "label": "st_sum", + "type": "MEM#2:Bot", + "kind": "MEM", + "edges": [ + { + "idx": 0, + "def": 0, + "role": "CTRL", + "label": null + }, + { + "idx": 1, + "def": 104, + "role": "MEM", + "label": null + }, + { + "idx": 2, + "def": 15, + "role": "DATA", + "label": null + }, + { + "idx": 3, + "def": 4, + "role": "DATA", + "label": null + }, + { + "idx": 4, + "def": 88, + "role": "DATA", + "label": null + } + ], + "proj": null + }, + { + "id": 99, + "label": "Add", + "type": "int", + "kind": "DATA", + "edges": [ + { + "idx": 0, + "def": 0, + "role": "CTRL", + "label": null + }, + { + "idx": 1, + "def": 138, + "role": "DATA", + "label": null + }, + { + "idx": 2, + "def": 46, + "role": "DATA", + "label": null + } + ], + "proj": null + }, + { + "id": 100, + "label": "st_visits", + "type": "MEM#3:Bot", + "kind": "MEM", + "edges": [ + { + "idx": 0, + "def": 0, + "role": "CTRL", + "label": null + }, + { + "idx": 1, + "def": 132, + "role": "MEM", + "label": null + }, + { + "idx": 2, + "def": 15, + "role": "DATA", + "label": null + }, + { + "idx": 3, + "def": 51, + "role": "DATA", + "label": null + }, + { + "idx": 4, + "def": 99, + "role": "DATA", + "label": null + } + ], + "proj": null + }, + { + "id": 103, + "label": "Add", + "type": "int", + "kind": "DATA", + "edges": [ + { + "idx": 0, + "def": 0, + "role": "CTRL", + "label": null + }, + { + "idx": 1, + "def": 67, + "role": "DATA", + "label": null + }, + { + "idx": 2, + "def": 46, + "role": "DATA", + "label": null + } + ], + "proj": null + }, + { + "id": 104, + "label": "MemPhi_2", + "type": "MEM#2:Bot", + "kind": "PHI", + "edges": [ + { + "idx": 0, + "def": 65, + "role": "ASSOC", + "label": null + }, + { + "idx": 1, + "def": 16, + "role": "MEM", + "label": null + }, + { + "idx": 2, + "def": 94, + "role": "MEM", + "label": null + } + ], + "proj": null + }, + { + "id": 106, + "label": "MemMerge", + "type": "MemBot", + "kind": "MEM", + "edges": [ + { + "idx": 0, + "def": 0, + "role": "CTRL", + "label": null + }, + { + "idx": 1, + "def": 7, + "role": "MEM", + "label": null + }, + { + "idx": 2, + "def": 104, + "role": "MEM", + "label": null + }, + { + "idx": 3, + "def": 132, + "role": "MEM", + "label": null + }, + { + "idx": 4, + "def": 29, + "role": "MEM", + "label": null + }, + { + "idx": 5, + "def": 124, + "role": "MEM", + "label": null + } + ], + "proj": null + }, + { + "id": 112, + "label": "Add", + "type": "int", + "kind": "DATA", + "edges": [ + { + "idx": 0, + "def": 0, + "role": "CTRL", + "label": null + }, + { + "idx": 1, + "def": 138, + "role": "DATA", + "label": null + }, + { + "idx": 2, + "def": 131, + "role": "DATA", + "label": null + } + ], + "proj": null + }, + { + "id": 115, + "label": "Return", + "type": "[ Ctrl, MemBot, int]", + "kind": "CTRL", + "edges": [ + { + "idx": 0, + "def": 75, + "role": "CTRL", + "label": null + }, + { + "idx": 1, + "def": 106, + "role": "MEM", + "label": null + }, + { + "idx": 2, + "def": 112, + "role": "DATA", + "label": null + } + ], + "proj": null + }, + { + "id": 124, + "label": "MemPhi_5", + "type": "MEM#5:Bot", + "kind": "PHI", + "edges": [ + { + "idx": 0, + "def": 32, + "role": "ASSOC", + "label": null + }, + { + "idx": 1, + "def": 29, + "role": "MEM", + "label": null + }, + { + "idx": 2, + "def": 57, + "role": "MEM", + "label": null + } + ], + "proj": null + }, + { + "id": 131, + "label": "Phi_sum", + "type": "int", + "kind": "PHI", + "edges": [ + { + "idx": 0, + "def": 65, + "role": "ASSOC", + "label": null + }, + { + "idx": 1, + "def": 4, + "role": "DATA", + "label": null + }, + { + "idx": 2, + "def": 88, + "role": "DATA", + "label": null + } + ], + "proj": null + }, + { + "id": 132, + "label": "MemPhi_3", + "type": "MEM#3:Bot", + "kind": "PHI", + "edges": [ + { + "idx": 0, + "def": 65, + "role": "ASSOC", + "label": null + }, + { + "idx": 1, + "def": 16, + "role": "MEM", + "label": null + }, + { + "idx": 2, + "def": 100, + "role": "MEM", + "label": null + } + ], + "proj": null + }, + { + "id": 138, + "label": "Phi_visits", + "type": "int", + "kind": "PHI", + "edges": [ + { + "idx": 0, + "def": 65, + "role": "ASSOC", + "label": null + }, + { + "idx": 1, + "def": 4, + "role": "DATA", + "label": null + }, + { + "idx": 2, + "def": 99, + "role": "DATA", + "label": null + } + ], + "proj": null + } + ], + "groups": [ + { + "id": 32, + "par": 0, + "nodes": [ + 32, + 34, + 35, + 40, + 41, + 42, + 53, + 54, + 56, + 57, + 60, + 124 + ] + }, + { + "id": 65, + "par": 0, + "nodes": [ + 65, + 67, + 68, + 73, + 74, + 75, + 88, + 91, + 92, + 93, + 94, + 99, + 100, + 103, + 104, + 112, + 131, + 132, + 138 + ] + } + ] +} diff --git a/docs/2026_REBASE/assets/memory-final.svg b/docs/2026_REBASE/assets/memory-final.svg new file mode 100644 index 00000000..205fea1b --- /dev/null +++ b/docs/2026_REBASE/assets/memory-final.svg @@ -0,0 +1,320 @@ +#3[0] → #115 · CTRL#4[0] → #2 · ASSOC#5[0] → #2 · ASSOC#12[0] → #2 · ASSOC#13[2] → #7 · MEM#13[3] → #7 · MEM#14[0] → #6 · CTRL#14[1] → #13 · MEM#14[2] → #12 · DATA#14[3] → #4 · DATA#14[4] → #4 · DATA#18[0] → #2 · ASSOC#24[0] → #2 · ASSOC#26[4] → #7 · MEM#26[5] → #7 · MEM#27[0] → #6 · CTRL#27[1] → #26 · MEM#27[2] → #24 · DATA#27[3] → #18 · DATA#27[4] → #4 · DATA#32[1] → #6 · CTRL#32[2] → #41 · CTRL#34[1] → #4 · DATA#34[2] → #60 · DATA#35[1] → #34 · DATA#35[2] → #18 · DATA#40[0] → #32 · CTRL#40[1] → #35 · DATA#46[0] → #2 · ASSOC#51[0] → #2 · ASSOC#52[0] → #2 · ASSOC#53[1] → #34 · DATA#53[2] → #52 · DATA#54[1] → #53 · DATA#54[2] → #51 · DATA#56[1] → #34 · DATA#56[2] → #8 · DATA#57[0] → #41 · CTRL#57[1] → #124 · MEM#57[2] → #28 · DATA#57[3] → #54 · DATA#57[4] → #56 · DATA#60[1] → #34 · DATA#60[2] → #46 · DATA#65[1] → #42 · CTRL#65[2] → #74 · CTRL#67[1] → #4 · DATA#67[2] → #103 · DATA#68[1] → #67 · DATA#68[2] → #18 · DATA#73[0] → #65 · CTRL#73[1] → #68 · DATA#88[1] → #131 · DATA#88[2] → #93 · DATA#91[1] → #67 · DATA#91[2] → #52 · DATA#92[1] → #91 · DATA#92[2] → #51 · DATA#93[0] → #74 · CTRL#93[1] → #124 · MEM#93[2] → #28 · DATA#93[3] → #92 · DATA#94[1] → #104 · MEM#94[2] → #15 · DATA#94[3] → #4 · DATA#94[4] → #88 · DATA#99[1] → #138 · DATA#99[2] → #46 · DATA#100[1] → #132 · MEM#100[2] → #15 · DATA#100[3] → #51 · DATA#100[4] → #99 · DATA#103[1] → #67 · DATA#103[2] → #46 · DATA#104[1] → #16 · MEM#104[2] → #94 · MEM#106[1] → #7 · MEM#106[2] → #104 · MEM#106[3] → #132 · MEM#106[4] → #29 · MEM#106[5] → #124 · MEM#112[1] → #138 · DATA#112[2] → #131 · DATA#115[0] → #75 · CTRL#115[1] → #106 · MEM#115[2] → #112 · DATA#124[1] → #29 · MEM#124[2] → #57 · MEM#131[1] → #4 · DATA#131[2] → #88 · DATA#132[1] → #16 · MEM#132[2] → #100 · MEM#138[1] → #4 · DATA#138[2] → #99 · DATAStart  #2[ Ctrl, MemBot, int]#2 Start +[ Ctrl, MemBot, int] + +[0] → — ASSOC +[1] → — CTRL +[2] → — CTRL012Stop  #3#3 Stop +Bot + +[0] → #115 CTRL0Con  #40#4 Con +0 + +[0] → #2 ASSOC0Xctrl  #5~Ctrl#5 Xctrl +~Ctrl + +[0] → #2 ASSOC0$ctrl  #6/0Ctrl#6 $ctrl +Projection 0 of #2 +Ctrl + +[0] → #2 CTRL$mem  #7/1MemBot#7 $mem +Projection 1 of #2 +MemBot + +[0] → #2 MEMarg  #8/2int#8 arg +Projection 2 of #2 +int + +[0] → #2 DATACon  #1216#12 Con +16 + +[0] → #2 ASSOC0MemMerge  #13MemBot#13 MemMerge +MemBot + +[0] → — CTRL +[1] → — DATA +[2] → #7 MEM +[3] → #7 MEM0123new_Totals  #14[ *Totals {int !sum; int !visits; }, MemBot]#14 new_Totals +[ *Totals {int !sum; int !visits; }, MemBot] + +[0] → #6 CTRL +[1] → #13 MEM +[2] → #12 DATA +[3] → #4 DATA +[4] → #4 DATA01234Totals  #15/0*Totals {int !sum; int !visits; }#15 Totals +Projection 0 of #14 +*Totals {int !sum; int !visits; } + +[0] → #14 DATA$mem  #16/1MemBot#16 $mem +Projection 1 of #14 +MemBot + +[0] → #14 MEMCon  #184#18 Con +4 + +[0] → #2 ASSOC0Con  #2440#24 Con +40 + +[0] → #2 ASSOC0MemMerge  #26MemBot#26 MemMerge +MemBot + +[0] → — CTRL +[1] → — DATA +[2] → — DATA +[3] → — DATA +[4] → #7 MEM +[5] → #7 MEM012345new_ary_int  #27[ *[int] {int #; int ![]; }, MemBot]#27 new_ary_int +[ *[int] {int #; int ![]; }, MemBot] + +[0] → #6 CTRL +[1] → #26 MEM +[2] → #24 DATA +[3] → #18 DATA +[4] → #4 DATA01234[int]  #28/0*[int] {int #; int ![]; }#28 [int] +Projection 0 of #27 +*[int] {int #; int ![]; } + +[0] → #27 DATA$mem  #29/1MemBot#29 $mem +Projection 1 of #27 +MemBot + +[0] → #27 MEMLoop  #32Ctrl#32 Loop +Ctrl + +[0] → — ASSOC +[1] → #6 CTRL +[2] → #41 CTRL012Phi_i  #34int#34 Phi_i +int + +[0] → #32 ASSOC +[1] → #4 DATA +[2] → #60 DATA[0] → #32012LT  #35bool#35 LT +bool + +[0] → — CTRL +[1] → #34 DATA +[2] → #18 DATA012If  #40[ Ctrl, Ctrl]#40 If +[ Ctrl, Ctrl] + +[0] → #32 CTRL +[1] → #35 DATA01True  #41/0Ctrl#41 True +Projection 0 of #40 +Ctrl + +[0] → #40 CTRLFalse  #42/1Ctrl#42 False +Projection 1 of #40 +Ctrl + +[0] → #40 CTRLCon  #461#46 Con +1 + +[0] → #2 ASSOC0Con  #518#51 Con +8 + +[0] → #2 ASSOC0Con  #523#52 Con +3 + +[0] → #2 ASSOC0Shl  #53int#53 Shl +int + +[0] → — CTRL +[1] → #34 DATA +[2] → #52 DATA012Add  #54int#54 Add +int + +[0] → — CTRL +[1] → #53 DATA +[2] → #51 DATA012Add  #56int#56 Add +int + +[0] → — CTRL +[1] → #34 DATA +[2] → #8 DATA012st_ary  #57MEM#5:Bot#57 st_ary +MEM#5:Bot + +[0] → #41 CTRL +[1] → #124 MEM +[2] → #28 DATA +[3] → #54 DATA +[4] → #56 DATA01234Add  #60int#60 Add +int + +[0] → — CTRL +[1] → #34 DATA +[2] → #46 DATA012Loop  #65Ctrl#65 Loop +Ctrl + +[0] → — ASSOC +[1] → #42 CTRL +[2] → #74 CTRL012Phi_i  #67int#67 Phi_i +int + +[0] → #65 ASSOC +[1] → #4 DATA +[2] → #103 DATA[0] → #65012LT  #68bool#68 LT +bool + +[0] → — CTRL +[1] → #67 DATA +[2] → #18 DATA012If  #73[ Ctrl, Ctrl]#73 If +[ Ctrl, Ctrl] + +[0] → #65 CTRL +[1] → #68 DATA01True  #74/0Ctrl#74 True +Projection 0 of #73 +Ctrl + +[0] → #73 CTRLFalse  #75/1Ctrl#75 False +Projection 1 of #73 +Ctrl + +[0] → #73 CTRLAdd  #88int#88 Add +int + +[0] → — CTRL +[1] → #131 DATA +[2] → #93 DATA012Shl  #91int#91 Shl +int + +[0] → — CTRL +[1] → #67 DATA +[2] → #52 DATA012Add  #92int#92 Add +int + +[0] → — CTRL +[1] → #91 DATA +[2] → #51 DATA012ld_ary  #93int#93 ld_ary +int + +[0] → #74 CTRL +[1] → #124 MEM +[2] → #28 DATA +[3] → #92 DATA0123st_sum  #94MEM#2:Bot#94 st_sum +MEM#2:Bot + +[0] → — CTRL +[1] → #104 MEM +[2] → #15 DATA +[3] → #4 DATA +[4] → #88 DATA01234Add  #99int#99 Add +int + +[0] → — CTRL +[1] → #138 DATA +[2] → #46 DATA012st_visits  #100MEM#3:Bot#100 st_visits +MEM#3:Bot + +[0] → — CTRL +[1] → #132 MEM +[2] → #15 DATA +[3] → #51 DATA +[4] → #99 DATA01234Add  #103int#103 Add +int + +[0] → — CTRL +[1] → #67 DATA +[2] → #46 DATA012MemPhi_2  #104MEM#2:Bot#104 MemPhi_2 +MEM#2:Bot + +[0] → #65 ASSOC +[1] → #16 MEM +[2] → #94 MEM[0] → #65012MemMerge  #106MemBot#106 MemMerge +MemBot + +[0] → — CTRL +[1] → #7 MEM +[2] → #104 MEM +[3] → #132 MEM +[4] → #29 MEM +[5] → #124 MEM012345Add  #112int#112 Add +int + +[0] → — CTRL +[1] → #138 DATA +[2] → #131 DATA012Return  #115[ Ctrl, MemBot, int]#115 Return +[ Ctrl, MemBot, int] + +[0] → #75 CTRL +[1] → #106 MEM +[2] → #112 DATA012MemPhi_5  #124MEM#5:Bot#124 MemPhi_5 +MEM#5:Bot + +[0] → #32 ASSOC +[1] → #29 MEM +[2] → #57 MEM[0] → #32012Phi_sum  #131int#131 Phi_sum +int + +[0] → #65 ASSOC +[1] → #4 DATA +[2] → #88 DATA[0] → #65012MemPhi_3  #132MEM#3:Bot#132 MemPhi_3 +MEM#3:Bot + +[0] → #65 ASSOC +[1] → #16 MEM +[2] → #100 MEM[0] → #65012Phi_visits  #138int#138 Phi_visits +int + +[0] → #65 ASSOC +[1] → #4 DATA +[2] → #99 DATA[0] → #65012Loop  #32Loop · 12 nodes−Fold regionLoop  #65Loop · 19 nodes−Fold region diff --git a/docs/2026_REBASE/assets/rich-lattice.gv b/docs/2026_REBASE/assets/rich-lattice.gv new file mode 100644 index 00000000..848bca82 --- /dev/null +++ b/docs/2026_REBASE/assets/rich-lattice.gv @@ -0,0 +1,404 @@ +digraph RichLattice { +graph [bgcolor="transparent", ranksep=0.35, nodesep=0.12, pad=0.08]; +node [shape=box, style="rounded,filled", fontname="Arial", fontsize=10, margin="0.06,0.04", color="#647674", penwidth=0.65]; +edge [arrowhead=none, color="#899895", penwidth=0.65]; +n0 [label="BOTTOM", tooltip="Type: Bot", fillcolor="#172e35", fontcolor="white"]; +n1 [label="Ctrl", tooltip="Type: Ctrl", fillcolor="#faedce", fontcolor="#172e35"]; +n2 [label="null", tooltip="Type: null", fillcolor="#faedce", fontcolor="#172e35"]; +n3 [label="ptr", tooltip="TypePtr: ptr", fillcolor="#cce4d6", fontcolor="#172e35"]; +n4 [label="nptr", tooltip="TypePtr: nptr", fillcolor="#cce4d6", fontcolor="#172e35"]; +n5 [label="i32", tooltip="TypeInteger: i32", fillcolor="#d3e7f5", fontcolor="#172e35"]; +n6 [label="i64", tooltip="TypeInteger: i64", fillcolor="#d3e7f5", fontcolor="#172e35"]; +n7 [label="bool", tooltip="TypeInteger: bool", fillcolor="#d3e7f5", fontcolor="#172e35"]; +n8 [label="i1", tooltip="TypeInteger: i1", fillcolor="#d3e7f5", fontcolor="#172e35"]; +n9 [label="u8", tooltip="TypeInteger: u8", fillcolor="#d3e7f5", fontcolor="#172e35"]; +n10 [label="0", tooltip="TypeInteger: 0", fillcolor="#d3e7f5", fontcolor="#172e35"]; +n11 [label="bool", tooltip="TypeInteger: bool", fillcolor="#d3e7f5", fontcolor="#172e35"]; +n12 [label="u8", tooltip="TypeInteger: u8", fillcolor="#d3e7f5", fontcolor="#172e35"]; +n13 [label="[1-255]", tooltip="TypeInteger: [1-255]", fillcolor="#d3e7f5", fontcolor="#172e35"]; +n14 [label="[-255-0]", tooltip="TypeInteger: [-255-0]", fillcolor="#d3e7f5", fontcolor="#172e35"]; +n15 [label="[-255--1]", tooltip="TypeInteger: [-255--1]", fillcolor="#d3e7f5", fontcolor="#172e35"]; +n16 [label="u8", tooltip="TypeInteger: u8", fillcolor="#d3e7f5", fontcolor="#172e35"]; +n17 [label="[1-255]", tooltip="TypeInteger: [1-255]", fillcolor="#d3e7f5", fontcolor="#172e35"]; +n18 [label="[-255-0]", tooltip="TypeInteger: [-255-0]", fillcolor="#d3e7f5", fontcolor="#172e35"]; +n19 [label="[-255--1]", tooltip="TypeInteger: [-255--1]", fillcolor="#d3e7f5", fontcolor="#172e35"]; +n20 [label="u8", tooltip="TypeInteger: u8", fillcolor="#d3e7f5", fontcolor="#172e35"]; +n21 [label="[1-255]", tooltip="TypeInteger: [1-255]", fillcolor="#d3e7f5", fontcolor="#172e35"]; +n22 [label="[-255-0]", tooltip="TypeInteger: [-255-0]", fillcolor="#d3e7f5", fontcolor="#172e35"]; +n23 [label="[-255--1]", tooltip="TypeInteger: [-255--1]", fillcolor="#d3e7f5", fontcolor="#172e35"]; +n24 [label="[1-255]", tooltip="TypeInteger: [1-255]", fillcolor="#d3e7f5", fontcolor="#172e35"]; +n25 [label="[-255-0]", tooltip="TypeInteger: [-255-0]", fillcolor="#d3e7f5", fontcolor="#172e35"]; +n26 [label="[-255--1]", tooltip="TypeInteger: [-255--1]", fillcolor="#d3e7f5", fontcolor="#172e35"]; +n27 [label="flt", tooltip="TypeFloat: flt", fillcolor="#c7eee9", fontcolor="#172e35"]; +n28 [label="f32", tooltip="TypeFloat: f32", fillcolor="#c7eee9", fontcolor="#172e35"]; +n29 [label="3.141592653589793", tooltip="TypeFloat: 3.141592653589793", fillcolor="#c7eee9", fontcolor="#172e35"]; +n30 [label="*void", tooltip="TypeMemPtr: *void", fillcolor="#cce4d6", fontcolor="#172e35"]; +n31 [label="PtrBot", tooltip="TypeMemPtr: PtrBot", fillcolor="#cce4d6", fontcolor="#172e35"]; +n32 [label="*test", tooltip="TypeMemPtr: *test {null !test; }", fillcolor="#cce4d6", fontcolor="#172e35"]; +n33 [label="*test", tooltip="TypeMemPtr: *test {null !test; }", fillcolor="#cce4d6", fontcolor="#172e35"]; +n34 [label="{0}", tooltip="TypeFunPtr: { i64 f32 -> i64 #0}", fillcolor="#dfd0ef", fontcolor="#172e35"]; +n35 [label="{b11}", tooltip="TypeFunPtr: { i64 f32 -> i64 #b11}?", fillcolor="#dfd0ef", fontcolor="#172e35"]; +n36 [label="FunBot", tooltip="TypeFunPtr: FunBot", fillcolor="#dfd0ef", fontcolor="#172e35"]; +n37 [label="{ALL}", tooltip="TypeFunPtr: { i64 -> Bot #ALL}?", fillcolor="#dfd0ef", fontcolor="#172e35"]; +n38 [label="{ALL}", tooltip="TypeFunPtr: { i64 i64 -> PtrBot #ALL}?", fillcolor="#dfd0ef", fontcolor="#172e35"]; +n39 [label="{0}", tooltip="TypeFunPtr: { i64 -> i32 #0}", fillcolor="#dfd0ef", fontcolor="#172e35"]; +n40 [label="{0}", tooltip="TypeFunPtr: { -> i32 #0}", fillcolor="#dfd0ef", fontcolor="#172e35"]; +n41 [label="{0}", tooltip="TypeFunPtr: { Top i64 -> i32 #0}", fillcolor="#dfd0ef", fontcolor="#172e35"]; +n42 [label="{0}", tooltip="TypeFunPtr: { i64 -> i32 #0}", fillcolor="#dfd0ef", fontcolor="#172e35"]; +n43 [label="{0}", tooltip="TypeFunPtr: { -> i32 #0}", fillcolor="#dfd0ef", fontcolor="#172e35"]; +n44 [label="{0}", tooltip="TypeFunPtr: { Bot i64 -> i32 #0}", fillcolor="#dfd0ef", fontcolor="#172e35"]; +n45 [label="#2:null", tooltip="TypeMem: #2:null", fillcolor="#a9c9e5", fontcolor="#172e35"]; +n46 [label="#2:0", tooltip="TypeMem: #2:0", fillcolor="#a9c9e5", fontcolor="#172e35"]; +n47 [label="MemBot", tooltip="TypeMem: MemBot", fillcolor="#a9c9e5", fontcolor="#172e35"]; +n48 [label="!test", tooltip="Field: !test:-2 : null", fillcolor="#e0ebc8", fontcolor="#172e35"]; +n49 [label="test", tooltip="Field: test:-2 : null", fillcolor="#e0ebc8", fontcolor="#172e35"]; +n50 [label="!flt ", tooltip="Field: !flt :-2 : f32", fillcolor="#e0ebc8", fontcolor="#172e35"]; +n51 [label="StructBot", tooltip="TypeStruct: StructBot", fillcolor="#e0ebc8", fontcolor="#172e35"]; +n52 [label="test", tooltip="TypeStruct: test {null !test; }", fillcolor="#e0ebc8", fontcolor="#172e35"]; +n53 [label="[]i64", tooltip="TypeStruct: []i64", fillcolor="#e0ebc8", fontcolor="#172e35"]; +n54 [label="[]u8", tooltip="TypeStruct: []u8", fillcolor="#e0ebc8", fontcolor="#172e35"]; +n55 [label="[]u8", tooltip="TypeStruct: [\"abc\"]", fillcolor="#e0ebc8", fontcolor="#172e35"]; +n56 [label="%SINT", tooltip="TypeStruct: %SINT {... }", fillcolor="#e0ebc8", fontcolor="#172e35"]; +n57 [label="%SFLT", tooltip="TypeStruct: %SFLT {... }", fillcolor="#e0ebc8", fontcolor="#172e35"]; +n58 [label="%SINT", tooltip="TypeStruct: %SINT {u32 !a; *%SFLT {... } !s2; ... }", fillcolor="#e0ebc8", fontcolor="#172e35"]; +n59 [label="%SFLT", tooltip="TypeStruct: %SFLT {f32 !b; *%SINT {u32 !a; *%SFLT {... } !s2; ... } !s1; ... }", fillcolor="#e0ebc8", fontcolor="#172e35"]; +n60 [label="%SFLT", tooltip="TypeStruct: %SFLT {f32 !b; *%SINT {u32 !a; *%SFLT !s2; } !s1; }", fillcolor="#e0ebc8", fontcolor="#172e35"]; +n61 [label="%SINT", tooltip="TypeStruct: %SINT {u32 !a; *%SFLT {f32 !b; *%SINT !s1; } !s2; }", fillcolor="#e0ebc8", fontcolor="#172e35"]; +n62 [label="calloc", tooltip="TypeStruct: calloc {{ i64 i64 -> PtrBot #ALL}? calloc; }", fillcolor="#e0ebc8", fontcolor="#172e35"]; +n63 [label="[BOT]", tooltip="TypeTuple: [BOT]", fillcolor="#f2d7e4", fontcolor="#172e35"]; +n64 [label="[ i64, *test {null !test; }]", tooltip="TypeTuple: [ i64, *test {null !test; }]", fillcolor="#f2d7e4", fontcolor="#172e35"]; +n65 [label="[ Ctrl, MemTop, i64]", tooltip="TypeTuple: [ Ctrl, MemTop, i64]", fillcolor="#f2d7e4", fontcolor="#172e35"]; +n66 [label="[ Ctrl, ~Ctrl]", tooltip="TypeTuple: [ Ctrl, ~Ctrl]", fillcolor="#f2d7e4", fontcolor="#172e35"]; +n67 [label="$[ALL]", tooltip="TypeRPC: $[ALL]", fillcolor="#f4d4b5", fontcolor="#172e35"]; +n68 [label="$[2]", tooltip="TypeRPC: $[2]", fillcolor="#f4d4b5", fontcolor="#172e35"]; +n69 [label="[\"abc\"]", tooltip="TypeConAryB: [\"abc\"]", fillcolor="#d9d5cc", fontcolor="#172e35"]; +n70 [label="[\"abcd\"]", tooltip="TypeConAryB: [\"abcd\"]", fillcolor="#d9d5cc", fontcolor="#172e35"]; +n71 [label="[i32]", tooltip="TypeConAryI: [i32]", fillcolor="#d9d5cc", fontcolor="#172e35"]; +n72 [label="TOP", tooltip="Type: Top", fillcolor="#172e35", fontcolor="white"]; +n73 [label="~Ctrl", tooltip="Type: ~Ctrl", fillcolor="#faedce", fontcolor="#172e35"]; +n74 [label="~nil", tooltip="Type: ~nil", fillcolor="#faedce", fontcolor="#172e35"]; +n75 [label="~ptr", tooltip="TypePtr: ~ptr", fillcolor="#cce4d6", fontcolor="#172e35"]; +n76 [label="~nptr", tooltip="TypePtr: ~nptr", fillcolor="#cce4d6", fontcolor="#172e35"]; +n77 [label="~i32", tooltip="TypeInteger: ~i32", fillcolor="#d3e7f5", fontcolor="#172e35"]; +n78 [label="~i64", tooltip="TypeInteger: ~i64", fillcolor="#d3e7f5", fontcolor="#172e35"]; +n79 [label="~bool", tooltip="TypeInteger: ~bool", fillcolor="#d3e7f5", fontcolor="#172e35"]; +n80 [label="~i1", tooltip="TypeInteger: ~i1", fillcolor="#d3e7f5", fontcolor="#172e35"]; +n81 [label="~u8", tooltip="TypeInteger: ~u8", fillcolor="#d3e7f5", fontcolor="#172e35"]; +n82 [label="0", tooltip="TypeInteger: 0", fillcolor="#d3e7f5", fontcolor="#172e35"]; +n83 [label="~bool", tooltip="TypeInteger: ~bool", fillcolor="#d3e7f5", fontcolor="#172e35"]; +n84 [label="~u8", tooltip="TypeInteger: ~u8", fillcolor="#d3e7f5", fontcolor="#172e35"]; +n85 [label="~[1-255]", tooltip="TypeInteger: ~[1-255]", fillcolor="#d3e7f5", fontcolor="#172e35"]; +n86 [label="~[-255-0]", tooltip="TypeInteger: ~[-255-0]", fillcolor="#d3e7f5", fontcolor="#172e35"]; +n87 [label="~[-255--1]", tooltip="TypeInteger: ~[-255--1]", fillcolor="#d3e7f5", fontcolor="#172e35"]; +n88 [label="~u8", tooltip="TypeInteger: ~u8", fillcolor="#d3e7f5", fontcolor="#172e35"]; +n89 [label="~[1-255]", tooltip="TypeInteger: ~[1-255]", fillcolor="#d3e7f5", fontcolor="#172e35"]; +n90 [label="~[-255-0]", tooltip="TypeInteger: ~[-255-0]", fillcolor="#d3e7f5", fontcolor="#172e35"]; +n91 [label="~[-255--1]", tooltip="TypeInteger: ~[-255--1]", fillcolor="#d3e7f5", fontcolor="#172e35"]; +n92 [label="~u8", tooltip="TypeInteger: ~u8", fillcolor="#d3e7f5", fontcolor="#172e35"]; +n93 [label="~[1-255]", tooltip="TypeInteger: ~[1-255]", fillcolor="#d3e7f5", fontcolor="#172e35"]; +n94 [label="~[-255-0]", tooltip="TypeInteger: ~[-255-0]", fillcolor="#d3e7f5", fontcolor="#172e35"]; +n95 [label="~[-255--1]", tooltip="TypeInteger: ~[-255--1]", fillcolor="#d3e7f5", fontcolor="#172e35"]; +n96 [label="~[1-255]", tooltip="TypeInteger: ~[1-255]", fillcolor="#d3e7f5", fontcolor="#172e35"]; +n97 [label="~[-255-0]", tooltip="TypeInteger: ~[-255-0]", fillcolor="#d3e7f5", fontcolor="#172e35"]; +n98 [label="~[-255--1]", tooltip="TypeInteger: ~[-255--1]", fillcolor="#d3e7f5", fontcolor="#172e35"]; +n99 [label="~flt", tooltip="TypeFloat: ~flt", fillcolor="#c7eee9", fontcolor="#172e35"]; +n100 [label="~f32", tooltip="TypeFloat: ~f32", fillcolor="#c7eee9", fontcolor="#172e35"]; +n101 [label="~*StructTop", tooltip="TypeMemPtr: ~*StructTop", fillcolor="#cce4d6", fontcolor="#172e35"]; +n102 [label="PtrTop", tooltip="TypeMemPtr: PtrTop", fillcolor="#cce4d6", fontcolor="#172e35"]; +n103 [label="~*test", tooltip="TypeMemPtr: ~*test {~nil test; ... }", fillcolor="#cce4d6", fontcolor="#172e35"]; +n104 [label="~*test", tooltip="TypeMemPtr: ~*test {~nil test; ... }", fillcolor="#cce4d6", fontcolor="#172e35"]; +n105 [label="{~0}", tooltip="TypeFunPtr: ~{ ~i64 ~f32 -> ~i64 #~0}", fillcolor="#dfd0ef", fontcolor="#172e35"]; +n106 [label="{~b11}", tooltip="TypeFunPtr: ~{ ~i64 ~f32 -> ~i64 #~b11}?", fillcolor="#dfd0ef", fontcolor="#172e35"]; +n107 [label="FunTop", tooltip="TypeFunPtr: FunTop", fillcolor="#dfd0ef", fontcolor="#172e35"]; +n108 [label="{~ALL}", tooltip="TypeFunPtr: ~{ ~i64 -> Top #~ALL}?", fillcolor="#dfd0ef", fontcolor="#172e35"]; +n109 [label="{~ALL}", tooltip="TypeFunPtr: ~{ ~i64 ~i64 -> PtrTop #~ALL}?", fillcolor="#dfd0ef", fontcolor="#172e35"]; +n110 [label="{~0}", tooltip="TypeFunPtr: ~{ ~i64 -> ~i32 #~0}", fillcolor="#dfd0ef", fontcolor="#172e35"]; +n111 [label="{~0}", tooltip="TypeFunPtr: ~{ -> ~i32 #~0}", fillcolor="#dfd0ef", fontcolor="#172e35"]; +n112 [label="{~0}", tooltip="TypeFunPtr: ~{ Bot ~i64 -> ~i32 #~0}", fillcolor="#dfd0ef", fontcolor="#172e35"]; +n113 [label="{~0}", tooltip="TypeFunPtr: ~{ ~i64 -> ~i32 #~0}", fillcolor="#dfd0ef", fontcolor="#172e35"]; +n114 [label="{~0}", tooltip="TypeFunPtr: ~{ -> ~i32 #~0}", fillcolor="#dfd0ef", fontcolor="#172e35"]; +n115 [label="{~0}", tooltip="TypeFunPtr: ~{ Top ~i64 -> ~i32 #~0}", fillcolor="#dfd0ef", fontcolor="#172e35"]; +n116 [label="#2:~nil", tooltip="TypeMem: #2:~nil", fillcolor="#a9c9e5", fontcolor="#172e35"]; +n117 [label="#2:0", tooltip="TypeMem: #2:0", fillcolor="#a9c9e5", fontcolor="#172e35"]; +n118 [label="MemTop", tooltip="TypeMem: MemTop", fillcolor="#a9c9e5", fontcolor="#172e35"]; +n119 [label="test", tooltip="Field: test:-2 : ~nil", fillcolor="#e0ebc8", fontcolor="#172e35"]; +n120 [label="!test", tooltip="Field: !test:-2 : ~nil", fillcolor="#e0ebc8", fontcolor="#172e35"]; +n121 [label="flt ", tooltip="Field: flt :-2 : ~f32", fillcolor="#e0ebc8", fontcolor="#172e35"]; +n122 [label="StructTop", tooltip="TypeStruct: StructTop", fillcolor="#e0ebc8", fontcolor="#172e35"]; +n123 [label="test", tooltip="TypeStruct: test {~nil test; ... }", fillcolor="#e0ebc8", fontcolor="#172e35"]; +n124 [label="[]i64", tooltip="TypeStruct: []i64", fillcolor="#e0ebc8", fontcolor="#172e35"]; +n125 [label="[]u8", tooltip="TypeStruct: []u8", fillcolor="#e0ebc8", fontcolor="#172e35"]; +n126 [label="[]u8", tooltip="TypeStruct: [\"abc\"]", fillcolor="#e0ebc8", fontcolor="#172e35"]; +n127 [label="%SINT", tooltip="TypeStruct: %SINT {}", fillcolor="#e0ebc8", fontcolor="#172e35"]; +n128 [label="%SFLT", tooltip="TypeStruct: %SFLT {}", fillcolor="#e0ebc8", fontcolor="#172e35"]; +n129 [label="%SINT", tooltip="TypeStruct: %SINT {~u32 a; ~*%SFLT {} s2; }", fillcolor="#e0ebc8", fontcolor="#172e35"]; +n130 [label="%SFLT", tooltip="TypeStruct: %SFLT {~f32 b; ~*%SINT {~u32 a; ~*%SFLT {} s2; } s1; }", fillcolor="#e0ebc8", fontcolor="#172e35"]; +n131 [label="%SFLT", tooltip="TypeStruct: %SFLT {~f32 b; ~*%SINT {~u32 a; ~*%SFLT s2; ... } s1; ... }", fillcolor="#e0ebc8", fontcolor="#172e35"]; +n132 [label="%SINT", tooltip="TypeStruct: %SINT {~u32 a; ~*%SFLT {~f32 b; ~*%SINT s1; ... } s2; ... }", fillcolor="#e0ebc8", fontcolor="#172e35"]; +n133 [label="calloc", tooltip="TypeStruct: calloc {~{ ~i64 ~i64 -> PtrTop #~ALL}? !calloc; ... }", fillcolor="#e0ebc8", fontcolor="#172e35"]; +n134 [label="[TOP]", tooltip="TypeTuple: [TOP]", fillcolor="#f2d7e4", fontcolor="#172e35"]; +n135 [label="[ ~i64, ~*test {~nil test; ... }]", tooltip="TypeTuple: [ ~i64, ~*test {~nil test; ... }]", fillcolor="#f2d7e4", fontcolor="#172e35"]; +n136 [label="[ ~Ctrl, MemBot, ~i64]", tooltip="TypeTuple: [ ~Ctrl, MemBot, ~i64]", fillcolor="#f2d7e4", fontcolor="#172e35"]; +n137 [label="[ ~Ctrl, Ctrl]", tooltip="TypeTuple: [ ~Ctrl, Ctrl]", fillcolor="#f2d7e4", fontcolor="#172e35"]; +n138 [label="$[]", tooltip="TypeRPC: $[]", fillcolor="#f4d4b5", fontcolor="#172e35"]; +n139 [label="$[-2]", tooltip="TypeRPC: $[-2]", fillcolor="#f4d4b5", fontcolor="#172e35"]; +n140 [label="[\"abc\"]", tooltip="TypeConAryB: [\"abc\"]", fillcolor="#d9d5cc", fontcolor="#172e35"]; +n141 [label="[\"abcd\"]", tooltip="TypeConAryB: [\"abcd\"]", fillcolor="#d9d5cc", fontcolor="#172e35"]; +n142 [label="[i32]", tooltip="TypeConAryI: [i32]", fillcolor="#d9d5cc", fontcolor="#172e35"]; +n1 -> n0; +n2 -> n31; +n2 -> n35; +n2 -> n37; +n2 -> n38; +n3 -> n0; +n4 -> n3; +n5 -> n6; +n6 -> n0; +n7 -> n9; +n8 -> n25; +n9 -> n5; +n10 -> n11; +n10 -> n12; +n10 -> n14; +n10 -> n82; +n11 -> n7; +n11 -> n20; +n12 -> n16; +n13 -> n12; +n13 -> n17; +n14 -> n18; +n15 -> n14; +n15 -> n19; +n16 -> n20; +n17 -> n16; +n17 -> n21; +n18 -> n22; +n19 -> n18; +n19 -> n23; +n20 -> n9; +n21 -> n20; +n21 -> n24; +n22 -> n25; +n23 -> n22; +n23 -> n26; +n24 -> n9; +n25 -> n5; +n26 -> n25; +n27 -> n0; +n28 -> n27; +n29 -> n27; +n30 -> n4; +n30 -> n31; +n31 -> n3; +n32 -> n33; +n33 -> n30; +n34 -> n4; +n34 -> n35; +n35 -> n36; +n36 -> n3; +n37 -> n36; +n38 -> n36; +n39 -> n34; +n39 -> n37; +n39 -> n42; +n39 -> n44; +n40 -> n39; +n40 -> n41; +n41 -> n42; +n41 -> n44; +n42 -> n43; +n43 -> n4; +n43 -> n36; +n44 -> n43; +n45 -> n47; +n46 -> n117; +n47 -> n0; +n48 -> n49; +n49 -> n0; +n50 -> n0; +n51 -> n0; +n52 -> n51; +n53 -> n51; +n54 -> n51; +n55 -> n51; +n56 -> n51; +n57 -> n51; +n58 -> n56; +n59 -> n57; +n60 -> n59; +n61 -> n58; +n62 -> n51; +n63 -> n0; +n64 -> n63; +n65 -> n63; +n66 -> n63; +n67 -> n0; +n68 -> n67; +n69 -> n13; +n69 -> n140; +n70 -> n13; +n70 -> n141; +n71 -> n13; +n71 -> n142; +n72 -> n48; +n72 -> n50; +n72 -> n73; +n72 -> n75; +n72 -> n78; +n72 -> n99; +n72 -> n118; +n72 -> n120; +n72 -> n121; +n72 -> n122; +n72 -> n134; +n72 -> n138; +n73 -> n1; +n74 -> n4; +n75 -> n76; +n75 -> n102; +n75 -> n107; +n76 -> n2; +n76 -> n40; +n76 -> n101; +n76 -> n105; +n76 -> n114; +n77 -> n81; +n77 -> n97; +n78 -> n77; +n79 -> n10; +n79 -> n13; +n79 -> n83; +n80 -> n10; +n80 -> n15; +n81 -> n79; +n81 -> n92; +n81 -> n96; +n82 -> n7; +n82 -> n8; +n83 -> n11; +n83 -> n17; +n83 -> n18; +n83 -> n82; +n84 -> n82; +n84 -> n85; +n85 -> n7; +n85 -> n140; +n85 -> n141; +n85 -> n142; +n86 -> n82; +n86 -> n87; +n87 -> n8; +n87 -> n26; +n88 -> n22; +n88 -> n84; +n88 -> n89; +n89 -> n11; +n89 -> n21; +n89 -> n85; +n90 -> n11; +n90 -> n86; +n90 -> n91; +n91 -> n23; +n91 -> n87; +n92 -> n83; +n92 -> n88; +n92 -> n93; +n93 -> n17; +n93 -> n89; +n94 -> n16; +n94 -> n90; +n94 -> n95; +n95 -> n19; +n95 -> n91; +n96 -> n69; +n96 -> n70; +n96 -> n71; +n96 -> n93; +n97 -> n80; +n97 -> n94; +n97 -> n98; +n98 -> n15; +n98 -> n95; +n99 -> n29; +n99 -> n100; +n100 -> n28; +n101 -> n32; +n101 -> n104; +n102 -> n74; +n102 -> n101; +n103 -> n30; +n104 -> n103; +n105 -> n110; +n106 -> n74; +n106 -> n105; +n107 -> n38; +n107 -> n40; +n107 -> n106; +n107 -> n108; +n107 -> n109; +n107 -> n114; +n108 -> n42; +n108 -> n74; +n108 -> n110; +n109 -> n36; +n109 -> n74; +n110 -> n111; +n111 -> n4; +n111 -> n36; +n112 -> n111; +n113 -> n37; +n113 -> n110; +n113 -> n112; +n114 -> n113; +n114 -> n115; +n115 -> n110; +n115 -> n112; +n116 -> n47; +n117 -> n47; +n118 -> n45; +n118 -> n46; +n118 -> n116; +n119 -> n0; +n120 -> n119; +n121 -> n0; +n122 -> n52; +n122 -> n53; +n122 -> n54; +n122 -> n55; +n122 -> n62; +n122 -> n123; +n122 -> n124; +n122 -> n125; +n122 -> n126; +n122 -> n127; +n122 -> n128; +n122 -> n133; +n123 -> n51; +n124 -> n51; +n125 -> n51; +n126 -> n51; +n127 -> n61; +n127 -> n129; +n128 -> n60; +n128 -> n130; +n129 -> n132; +n130 -> n131; +n131 -> n57; +n132 -> n56; +n133 -> n51; +n134 -> n64; +n134 -> n65; +n134 -> n66; +n134 -> n135; +n134 -> n136; +n134 -> n137; +n135 -> n63; +n136 -> n63; +n137 -> n63; +n138 -> n68; +n138 -> n139; +n139 -> n67; +n140 -> n24; +n141 -> n24; +n142 -> n24; +} diff --git a/docs/2026_REBASE/assets/rich-lattice.svg b/docs/2026_REBASE/assets/rich-lattice.svg new file mode 100644 index 00000000..2aecb147 --- /dev/null +++ b/docs/2026_REBASE/assets/rich-lattice.svg @@ -0,0 +1,2579 @@ + + + + + + +RichLattice + + +n0 + + +BOTTOM + + + + + +n1 + + +Ctrl + + + + + +n1->n0 + + + + +n2 + + +null + + + + + +n31 + + +PtrBot + + + + + +n2->n31 + + + + +n35 + + +{b11} + + + + + +n2->n35 + + + + +n37 + + +{ALL} + + + + + +n2->n37 + + + + +n38 + + +{ALL} + + + + + +n2->n38 + + + + +n3 + + +ptr + + + + + +n3->n0 + + + + +n4 + + +nptr + + + + + +n4->n3 + + + + +n5 + + +i32 + + + + + +n6 + + +i64 + + + + + +n5->n6 + + + + +n6->n0 + + + + +n7 + + +bool + + + + + +n9 + + +u8 + + + + + +n7->n9 + + + + +n8 + + +i1 + + + + + +n25 + + +[-255-0] + + + + + +n8->n25 + + + + +n9->n5 + + + + +n10 + + +0 + + + + + +n11 + + +bool + + + + + +n10->n11 + + + + +n12 + + +u8 + + + + + +n10->n12 + + + + +n14 + + +[-255-0] + + + + + +n10->n14 + + + + +n82 + + +0 + + + + + +n10->n82 + + + + +n11->n7 + + + + +n20 + + +u8 + + + + + +n11->n20 + + + + +n16 + + +u8 + + + + + +n12->n16 + + + + +n13 + + +[1-255] + + + + + +n13->n12 + + + + +n17 + + +[1-255] + + + + + +n13->n17 + + + + +n18 + + +[-255-0] + + + + + +n14->n18 + + + + +n15 + + +[-255--1] + + + + + +n15->n14 + + + + +n19 + + +[-255--1] + + + + + +n15->n19 + + + + +n16->n20 + + + + +n17->n16 + + + + +n21 + + +[1-255] + + + + + +n17->n21 + + + + +n22 + + +[-255-0] + + + + + +n18->n22 + + + + +n19->n18 + + + + +n23 + + +[-255--1] + + + + + +n19->n23 + + + + +n20->n9 + + + + +n21->n20 + + + + +n24 + + +[1-255] + + + + + +n21->n24 + + + + +n22->n25 + + + + +n23->n22 + + + + +n26 + + +[-255--1] + + + + + +n23->n26 + + + + +n24->n9 + + + + +n25->n5 + + + + +n26->n25 + + + + +n27 + + +flt + + + + + +n27->n0 + + + + +n28 + + +f32 + + + + + +n28->n27 + + + + +n29 + + +3.141592653589793 + + + + + +n29->n27 + + + + +n30 + + +*void + + + + + +n30->n4 + + + + +n30->n31 + + + + +n31->n3 + + + + +n32 + + +*test + + + + + +n33 + + +*test + + + + + +n32->n33 + + + + +n33->n30 + + + + +n34 + + +{0} + + + + + +n34->n4 + + + + +n34->n35 + + + + +n36 + + +FunBot + + + + + +n35->n36 + + + + +n36->n3 + + + + +n37->n36 + + + + +n38->n36 + + + + +n39 + + +{0} + + + + + +n39->n34 + + + + +n39->n37 + + + + +n42 + + +{0} + + + + + +n39->n42 + + + + +n44 + + +{0} + + + + + +n39->n44 + + + + +n40 + + +{0} + + + + + +n40->n39 + + + + +n41 + + +{0} + + + + + +n40->n41 + + + + +n41->n42 + + + + +n41->n44 + + + + +n43 + + +{0} + + + + + +n42->n43 + + + + +n43->n4 + + + + +n43->n36 + + + + +n44->n43 + + + + +n45 + + +#2:null + + + + + +n47 + + +MemBot + + + + + +n45->n47 + + + + +n46 + + +#2:0 + + + + + +n117 + + +#2:0 + + + + + +n46->n117 + + + + +n47->n0 + + + + +n48 + + +!test + + + + + +n49 + + +test + + + + + +n48->n49 + + + + +n49->n0 + + + + +n50 + + +!flt + + + + + +n50->n0 + + + + +n51 + + +StructBot + + + + + +n51->n0 + + + + +n52 + + +test + + + + + +n52->n51 + + + + +n53 + + +[]i64 + + + + + +n53->n51 + + + + +n54 + + +[]u8 + + + + + +n54->n51 + + + + +n55 + + +[]u8 + + + + + +n55->n51 + + + + +n56 + + +%SINT + + + + + +n56->n51 + + + + +n57 + + +%SFLT + + + + + +n57->n51 + + + + +n58 + + +%SINT + + + + + +n58->n56 + + + + +n59 + + +%SFLT + + + + + +n59->n57 + + + + +n60 + + +%SFLT + + + + + +n60->n59 + + + + +n61 + + +%SINT + + + + + +n61->n58 + + + + +n62 + + +calloc + + + + + +n62->n51 + + + + +n63 + + +[BOT] + + + + + +n63->n0 + + + + +n64 + + +[  i64, *test {null !test; }] + + + + + +n64->n63 + + + + +n65 + + +[  Ctrl, MemTop, i64] + + + + + +n65->n63 + + + + +n66 + + +[  Ctrl, ~Ctrl] + + + + + +n66->n63 + + + + +n67 + + +$[ALL] + + + + + +n67->n0 + + + + +n68 + + +$[2] + + + + + +n68->n67 + + + + +n69 + + +["abc"] + + + + + +n69->n13 + + + + +n140 + + +["abc"] + + + + + +n69->n140 + + + + +n70 + + +["abcd"] + + + + + +n70->n13 + + + + +n141 + + +["abcd"] + + + + + +n70->n141 + + + + +n71 + + +[i32] + + + + + +n71->n13 + + + + +n142 + + +[i32] + + + + + +n71->n142 + + + + +n72 + + +TOP + + + + + +n72->n48 + + + + +n72->n50 + + + + +n73 + + +~Ctrl + + + + + +n72->n73 + + + + +n75 + + +~ptr + + + + + +n72->n75 + + + + +n78 + + +~i64 + + + + + +n72->n78 + + + + +n99 + + +~flt + + + + + +n72->n99 + + + + +n118 + + +MemTop + + + + + +n72->n118 + + + + +n120 + + +!test + + + + + +n72->n120 + + + + +n121 + + +flt + + + + + +n72->n121 + + + + +n122 + + +StructTop + + + + + +n72->n122 + + + + +n134 + + +[TOP] + + + + + +n72->n134 + + + + +n138 + + +$[] + + + + + +n72->n138 + + + + +n73->n1 + + + + +n74 + + +~nil + + + + + +n74->n4 + + + + +n76 + + +~nptr + + + + + +n75->n76 + + + + +n102 + + +PtrTop + + + + + +n75->n102 + + + + +n107 + + +FunTop + + + + + +n75->n107 + + + + +n76->n2 + + + + +n76->n40 + + + + +n101 + + +~*StructTop + + + + + +n76->n101 + + + + +n105 + + +{~0} + + + + + +n76->n105 + + + + +n114 + + +{~0} + + + + + +n76->n114 + + + + +n77 + + +~i32 + + + + + +n81 + + +~u8 + + + + + +n77->n81 + + + + +n97 + + +~[-255-0] + + + + + +n77->n97 + + + + +n78->n77 + + + + +n79 + + +~bool + + + + + +n79->n10 + + + + +n79->n13 + + + + +n83 + + +~bool + + + + + +n79->n83 + + + + +n80 + + +~i1 + + + + + +n80->n10 + + + + +n80->n15 + + + + +n81->n79 + + + + +n92 + + +~u8 + + + + + +n81->n92 + + + + +n96 + + +~[1-255] + + + + + +n81->n96 + + + + +n82->n7 + + + + +n82->n8 + + + + +n83->n11 + + + + +n83->n17 + + + + +n83->n18 + + + + +n83->n82 + + + + +n84 + + +~u8 + + + + + +n84->n82 + + + + +n85 + + +~[1-255] + + + + + +n84->n85 + + + + +n85->n7 + + + + +n85->n140 + + + + +n85->n141 + + + + +n85->n142 + + + + +n86 + + +~[-255-0] + + + + + +n86->n82 + + + + +n87 + + +~[-255--1] + + + + + +n86->n87 + + + + +n87->n8 + + + + +n87->n26 + + + + +n88 + + +~u8 + + + + + +n88->n22 + + + + +n88->n84 + + + + +n89 + + +~[1-255] + + + + + +n88->n89 + + + + +n89->n11 + + + + +n89->n21 + + + + +n89->n85 + + + + +n90 + + +~[-255-0] + + + + + +n90->n11 + + + + +n90->n86 + + + + +n91 + + +~[-255--1] + + + + + +n90->n91 + + + + +n91->n23 + + + + +n91->n87 + + + + +n92->n83 + + + + +n92->n88 + + + + +n93 + + +~[1-255] + + + + + +n92->n93 + + + + +n93->n17 + + + + +n93->n89 + + + + +n94 + + +~[-255-0] + + + + + +n94->n16 + + + + +n94->n90 + + + + +n95 + + +~[-255--1] + + + + + +n94->n95 + + + + +n95->n19 + + + + +n95->n91 + + + + +n96->n69 + + + + +n96->n70 + + + + +n96->n71 + + + + +n96->n93 + + + + +n97->n80 + + + + +n97->n94 + + + + +n98 + + +~[-255--1] + + + + + +n97->n98 + + + + +n98->n15 + + + + +n98->n95 + + + + +n99->n29 + + + + +n100 + + +~f32 + + + + + +n99->n100 + + + + +n100->n28 + + + + +n101->n32 + + + + +n104 + + +~*test + + + + + +n101->n104 + + + + +n102->n74 + + + + +n102->n101 + + + + +n103 + + +~*test + + + + + +n103->n30 + + + + +n104->n103 + + + + +n110 + + +{~0} + + + + + +n105->n110 + + + + +n106 + + +{~b11} + + + + + +n106->n74 + + + + +n106->n105 + + + + +n107->n38 + + + + +n107->n40 + + + + +n107->n106 + + + + +n108 + + +{~ALL} + + + + + +n107->n108 + + + + +n109 + + +{~ALL} + + + + + +n107->n109 + + + + +n107->n114 + + + + +n108->n42 + + + + +n108->n74 + + + + +n108->n110 + + + + +n109->n36 + + + + +n109->n74 + + + + +n111 + + +{~0} + + + + + +n110->n111 + + + + +n111->n4 + + + + +n111->n36 + + + + +n112 + + +{~0} + + + + + +n112->n111 + + + + +n113 + + +{~0} + + + + + +n113->n37 + + + + +n113->n110 + + + + +n113->n112 + + + + +n114->n113 + + + + +n115 + + +{~0} + + + + + +n114->n115 + + + + +n115->n110 + + + + +n115->n112 + + + + +n116 + + +#2:~nil + + + + + +n116->n47 + + + + +n117->n47 + + + + +n118->n45 + + + + +n118->n46 + + + + +n118->n116 + + + + +n119 + + +test + + + + + +n119->n0 + + + + +n120->n119 + + + + +n121->n0 + + + + +n122->n52 + + + + +n122->n53 + + + + +n122->n54 + + + + +n122->n55 + + + + +n122->n62 + + + + +n123 + + +test + + + + + +n122->n123 + + + + +n124 + + +[]i64 + + + + + +n122->n124 + + + + +n125 + + +[]u8 + + + + + +n122->n125 + + + + +n126 + + +[]u8 + + + + + +n122->n126 + + + + +n127 + + +%SINT + + + + + +n122->n127 + + + + +n128 + + +%SFLT + + + + + +n122->n128 + + + + +n133 + + +calloc + + + + + +n122->n133 + + + + +n123->n51 + + + + +n124->n51 + + + + +n125->n51 + + + + +n126->n51 + + + + +n127->n61 + + + + +n129 + + +%SINT + + + + + +n127->n129 + + + + +n128->n60 + + + + +n130 + + +%SFLT + + + + + +n128->n130 + + + + +n132 + + +%SINT + + + + + +n129->n132 + + + + +n131 + + +%SFLT + + + + + +n130->n131 + + + + +n131->n57 + + + + +n132->n56 + + + + +n133->n51 + + + + +n134->n64 + + + + +n134->n65 + + + + +n134->n66 + + + + +n135 + + +[  ~i64, ~*test {~nil test; ... }] + + + + + +n134->n135 + + + + +n136 + + +[  ~Ctrl, MemBot, ~i64] + + + + + +n134->n136 + + + + +n137 + + +[  ~Ctrl, Ctrl] + + + + + +n134->n137 + + + + +n135->n63 + + + + +n136->n63 + + + + +n137->n63 + + + + +n138->n68 + + + + +n139 + + +$[-2] + + + + + +n138->n139 + + + + +n139->n67 + + + + +n140->n24 + + + + +n141->n24 + + + + +n142->n24 + + + + diff --git a/docs/2026_REBASE/backend.js b/docs/2026_REBASE/backend.js new file mode 100644 index 00000000..91ffb239 --- /dev/null +++ b/docs/2026_REBASE/backend.js @@ -0,0 +1,7 @@ +/* Generated by tools/BackendDump.java; Chapter 21, x86-64 System V. */ +window.REBASE.backend = { + source: "struct Box { int x; };\nreturn { !Box box, int arg ->\n int n = arg < 0 ? -arg : arg;\n box.x += n;\n return n;\n};\n", + selected: "id node inputs\n 7 StartNode _ _ _\n11 ConstantNode 7\n15 ConstantNode 7\n18 ConstantNode 7\n22 ConstantNode 7\n 6 FunX86 _ 7\n10 ParmX86:arg 6 11\n14 ParmX86:$mem 6 15\n17 ParmX86:box 6 18\n21 ParmX86:$rpc 6 22\n 8 CmpIX86 _ 10\n20 NegX86 _ 10\n 5 JmpX86 6 8\n12 CProjNode:False 5\n 4 CProjNode:True 5\n 3 RegionNode _ 4 12\n19 PhiNode 3 20 10\n16 MemAddX86 _ 14 17 _ 19\n13 MemMergeNode _ 14 16\n 2 RetX86 3 13 19 21\n 1 StopNode 2\n", + assembly: "\n--- { *Box {int !x; } int -> int #0}---------------------------\n arg rsi\n box rdi\n r15 // r15\n r14 // r14\n r13 // r13\n r12 // r12\n rbp // rbp\n rbx // rbx\n0000 mov rax = rsi // def/empty1 #0\n0000 test rax \n0000 j< L4 // L12\nL12:\n0000 ?? JMP L3\nL4:\n0001 neg rax \nL3:\n rax = phi( N20,N33 )\n0001 add8 [rdi] += rax \n0001 ret rax [stk#33] rbx rbp r12 r13 r14 r15 \n--- ---------------------------\n", + encoded: "\n--- { *Box {int !x; } int -> int #0}---------------------------\n arg:rsi,box:rdi\n0000 488bc6 mov rax = rsi // def/empty1 #0\n0003 4883f800 test rax \n0007 7d03 j>= L3 // L4\nL4:\n0009 48f7d8 neg rax \nL12:\nL3:\n :rax\n000c 480107 add8 [rdi] += rax \n000f c3 ret \n--- ---------------------------\n" +}; diff --git a/docs/2026_REBASE/deck.js b/docs/2026_REBASE/deck.js new file mode 100644 index 00000000..06a4e9d5 --- /dev/null +++ b/docs/2026_REBASE/deck.js @@ -0,0 +1,58 @@ +/* Plain scripts keep the deck usable from file:// as well as an HTTP server. */ +window.REBASE = { + "title": "A Simple Tutorial", + "speaker": "Cliff Click", + "youtube": "https://www.youtube.com/@compilers", + "repo": "https://github.com/SeaOfNodes/Simple", + "demos": [ + { + "id": "arithmetic", + "chapter": "chapter04", + "title": "Local rewrites, global payoff", + "code": "int x = arg + 0;\nint y = 1 + x + 2;\nreturn y + x + 3;\n", + "result": "2 * arg + 6", + "inputs": "arg = 0 → 6; arg = 5 → 16" + }, + { + "id": "control", + "chapter": "chapter08", + "title": "A value at every merge", + "code": "int n = arg;\nif( n < 0 ) n = -n;\nint sum = 0;\nint i = 0;\nwhile( i < n ) {\n i = i + 1;\n sum = sum + i;\n}\nreturn sum;\n", + "result": "Sum 1 … |arg|", + "inputs": "arg = 0 → 0; arg = 5 → 15; arg = -5 → 15" + }, + { + "id": "memory", + "chapter": "chapter17b", + "title": "Memory is dataflow, too", + "code": "struct Totals { int sum; int visits; };\nval t = new Totals;\nval data = new int[4];\nfor( int i = 0; i < data#; i++ )\n data[i] = arg + i;\nfor( int i = 0; i < data#; i++ ) {\n t.sum = t.sum + data[i];\n t.visits++;\n}\nreturn t.sum + t.visits;\n", + "result": "4 * arg + 10 (runtime result)", + "inputs": "arg = 0 → 10; arg = 5 → 30" + }, + { + "id": "aliases", + "chapter": "chapter17b", + "title": "One field changes. Another does not.", + "code": "struct Pair { int x; int y; };\nval p = new Pair { x = arg; y = 10; };\nint before = p.x;\np.y = 99;\nreturn p.x - before;\n", + "result": "return 0;", + "inputs": "Any arg → 0" + }, + { + "id": "inline", + "chapter": "chapter18", + "title": "Erase the call boundary", + "code": "val add1 = { int x -> x + 1; };\nval twice = { int x -> x * 2; };\nreturn twice(1 + add1(2)) + 3;\n", + "result": "return 11;", + "inputs": "Any arg → 11" + }, + { + "id": "sccp", + "chapter": "chapter24", + "viewerChapter": "chapter25", + "title": "Prove a loop-carried constant", + "code": "int x = 1;\nfor( int i = 0; i < arg; i++ )\n x = 2 - x;\nreturn x;\n", + "result": "Return value is always 1", + "inputs": "arg = 0 → 1; arg = 5 → 1" + } + ] +}; diff --git a/docs/2026_REBASE/demos/aliases.smp b/docs/2026_REBASE/demos/aliases.smp new file mode 100644 index 00000000..a8ee471f --- /dev/null +++ b/docs/2026_REBASE/demos/aliases.smp @@ -0,0 +1,5 @@ +struct Pair { int x; int y; }; +val p = new Pair { x = arg; y = 10; }; +int before = p.x; +p.y = 99; +return p.x - before; diff --git a/docs/2026_REBASE/demos/arithmetic.smp b/docs/2026_REBASE/demos/arithmetic.smp new file mode 100644 index 00000000..ef19a5bd --- /dev/null +++ b/docs/2026_REBASE/demos/arithmetic.smp @@ -0,0 +1,3 @@ +int x = arg + 0; +int y = 1 + x + 2; +return y + x + 3; diff --git a/docs/2026_REBASE/demos/backend.smp b/docs/2026_REBASE/demos/backend.smp new file mode 100644 index 00000000..de8f7665 --- /dev/null +++ b/docs/2026_REBASE/demos/backend.smp @@ -0,0 +1,6 @@ +struct Box { int x; }; +return { !Box box, int arg -> + int n = arg < 0 ? -arg : arg; + box.x += n; + return n; +}; diff --git a/docs/2026_REBASE/demos/control.smp b/docs/2026_REBASE/demos/control.smp new file mode 100644 index 00000000..6b7b1b17 --- /dev/null +++ b/docs/2026_REBASE/demos/control.smp @@ -0,0 +1,9 @@ +int n = arg; +if( n < 0 ) n = -n; +int sum = 0; +int i = 0; +while( i < n ) { + i = i + 1; + sum = sum + i; +} +return sum; diff --git a/docs/2026_REBASE/demos/inline.smp b/docs/2026_REBASE/demos/inline.smp new file mode 100644 index 00000000..9d38e5b0 --- /dev/null +++ b/docs/2026_REBASE/demos/inline.smp @@ -0,0 +1,3 @@ +val add1 = { int x -> x + 1; }; +val twice = { int x -> x * 2; }; +return twice(1 + add1(2)) + 3; diff --git a/docs/2026_REBASE/demos/memory.smp b/docs/2026_REBASE/demos/memory.smp new file mode 100644 index 00000000..466c0476 --- /dev/null +++ b/docs/2026_REBASE/demos/memory.smp @@ -0,0 +1,10 @@ +struct Totals { int sum; int visits; }; +val t = new Totals; +val data = new int[4]; +for( int i = 0; i < data#; i++ ) + data[i] = arg + i; +for( int i = 0; i < data#; i++ ) { + t.sum = t.sum + data[i]; + t.visits++; +} +return t.sum + t.visits; diff --git a/docs/2026_REBASE/demos/methods.smp b/docs/2026_REBASE/demos/methods.smp new file mode 100644 index 00000000..683540c3 --- /dev/null +++ b/docs/2026_REBASE/demos/methods.smp @@ -0,0 +1,11 @@ +struct Counter { + int n; + val add = { int delta -> + n += delta; + return self; + }; + val get = { -> return n; }; +}; +!Counter c = new Counter { n = arg; }; +c.add(3).add(4); +return c.get(); diff --git a/docs/2026_REBASE/demos/sccp.smp b/docs/2026_REBASE/demos/sccp.smp new file mode 100644 index 00000000..da91691d --- /dev/null +++ b/docs/2026_REBASE/demos/sccp.smp @@ -0,0 +1,4 @@ +int x = 1; +for( int i = 0; i < arg; i++ ) + x = 2 - x; +return x; diff --git a/docs/2026_REBASE/index.html b/docs/2026_REBASE/index.html new file mode 100644 index 00000000..4a95e27c --- /dev/null +++ b/docs/2026_REBASE/index.html @@ -0,0 +1,41 @@ + + + + + + + A Simple Tutorial · Cliff Click · REBASE 2026 + + + + + + + + + + +
+
+
+ + +
+
+ + + + diff --git a/docs/2026_REBASE/language.js b/docs/2026_REBASE/language.js new file mode 100644 index 00000000..d5e1079a --- /dev/null +++ b/docs/2026_REBASE/language.js @@ -0,0 +1,40 @@ +/* Chapter 22 library explorer and Chapter 23 methods example. No fetch needed. */ +(function () { + const R=window.REBASE, esc=R.escape, files=R.library.files; + const parent=path=>path.split('/').slice(0,-1).join('/'); + const button=(path,label,cls='')=>''; + R.libraryHasPath=path=>typeof path==='string' && (path==='' || Object.hasOwn(files,path) || Object.keys(files).some(file=>file.startsWith(path+'/'))); + function explorer(state) { + const path=state.library, isFile=Object.hasOwn(files,path); + let crumbs=button('','Standard library'); + path.split('/').filter(Boolean).forEach((part,i,parts)=>{ + crumbs+='/'+button(parts.slice(0,i+1).join('/'),esc(part)); + }); + let contents; + if(isFile) { + contents='
'+esc(files[path])+'
'; + } else { + const entries=new Map(), prefix=path?path+'/':''; + for(const file of Object.keys(files)) if(file.startsWith(prefix)) { + const rest=file.slice(prefix.length), name=rest.split('/')[0]; + entries.set(name,rest.includes('/')); + } + contents='
'+ + [...entries].sort(([a,ad],[b,bd])=>Number(bd)-Number(ad)||a.localeCompare(b)).map(([name,dir])=> + button(prefix+name,''+(dir?'DIR':'SMP')+''+esc(name)+(dir?'/':'')+''+(dir?'›':'↗')+'','library-entry')).join('')+'
'; + } + return '
'+(isFile?'':'')+'

Chapter 25 · '+esc(R.library.origin)+'

'+contents+'
'; + } + function intro(which,state) { + const methods=which==='methods'; + return '
'; + } + function methods(state) { + return '
23 · Counter
'+esc(R.library.methods)+'

c.add(3).add(4) passes c as self.
The program returns arg + 7.

'; + } + R.languageBody=state=>'

The language starts
using its compiler.

'+ + (state.library===null?intro('library',state):explorer(state))+ + (state.library!==null && state.libraryWide?'':state.methods?methods(state):intro('methods',state))+'
'; +})(); diff --git a/docs/2026_REBASE/lattices.js b/docs/2026_REBASE/lattices.js new file mode 100644 index 00000000..2e7da4a4 --- /dev/null +++ b/docs/2026_REBASE/lattices.js @@ -0,0 +1,128 @@ +/* Presentation-sized views of the chapter lattices. Lines run down the order. + * Focused views deliberately omit other domains; see README.md for sources. + */ +(function () { + const R=window.REBASE, esc=R.escape; + const text=(x,y,s,cls='')=>''+esc(s)+''; + const edge=(x,y,a,b)=>''; + function node(x,y,label,kind='integer',width=150) { + return ''+text(x,y+8,label); + } + function svg(label,body) { + return ''+esc(label)+''+body+''; + } + function early(control) { + let s=edge(450,58,130,control?127:227)+edge(130,control?373:273,450,442)+ + edge(450,58,450,127)+edge(450,373,450,442)+edge(450,58,760,127)+edge(760,373,450,442); + for(const x of [295,450,605]) s+=edge(450,173,x,227)+edge(x,273,450,327); + s+=edge(760,173,760,227)+edge(760,273,760,327); + if(control) s+=edge(130,173,130,327); + s+=node(450,35,'⊤','global',65)+node(450,465,'⊥','global',65)+ + node(450,150,'⊤:int')+node(295,250,'−1', 'integer',80)+node(450,250,'0','integer',80)+node(605,250,'1','integer',80)+node(450,350,'⊥:int')+ + node(760,150,'⊤:tuple','tuple')+node(760,250,'[T₀, …, Tₙ]','tuple',200)+node(760,350,'⊥:tuple','tuple'); + s+=control?node(130,150,'⊤:ctrl','control')+node(130,350,'⊥:ctrl','control')+text(130,207,'unreachable','hint')+text(130,405,'reachable','hint'):node(130,250,'ctrl','control'); + return svg(control?'Chapter 8: control, flat integers, and tuples':'Chapter 4: control, flat integers, and tuples',s); + } + function domains() { + const ds=[['Control','ctrl','control'],['Integers','int','integer'],['Pointers','ptr','pointer'],['Structs','struct','struct'],['Memory','mem','memory'],['Tuples','tuple','tuple']]; + let s=''; + ds.forEach(([name,suffix,kind],i)=>{ + const x=75+i*150; + s+=edge(450,58,x,137)+(suffix==='mem'?'':edge(x,183,x,327))+edge(x,373,450,442)+ + node(x,160,'⊤:'+suffix,kind,134)+node(x,350,'⊥:'+suffix,kind,134)+''+text(x,115,name,'domain-name'); + if(suffix==='mem') { + s+=edge(x,183,x-38,237)+edge(x,183,x+38,237)+edge(x-38,263,x,327)+edge(x+38,263,x,327); + s+=node(x-38,250,'#2',kind,58)+node(x+38,250,'#3',kind,58); + } else if(suffix!=='ctrl') { + s+=''+text(x,258,'…','ellipsis'); + } + }); + s+=node(450,35,'⊤','global',65)+node(450,465,'⊥','global',65); + return svg('Chapter 11 domain overview; interiors elided except two memory aliases',s); + } + function contents() { + let s=edge(450,78,450,147)+edge(450,193,250,257)+edge(450,193,650,257)+edge(250,303,450,367)+edge(650,303,450,367)+edge(450,413,450,442); + s+=node(450,55,'MEM#2 : ⊤:int','memory',290)+node(450,170,'MEM#2 : [1, 0]','memory',300)+ + node(250,280,'MEM#2 : 0','memory',220)+node(650,280,'MEM#2 : 1','memory',220)+ + node(450,390,'MEM#2 : [0, 1]','memory',300)+node(450,465,'MEM#2 : ⊥:int','memory',290); + return svg('A slice of typed memory: fixed alias 2, integer contents, selected elements',s); + } + function ranges(optimistic=false) { + let s=edge(450,58,450,127)+edge(450,173,250,227)+edge(450,173,650,227)+edge(250,273,450,327)+edge(650,273,450,327)+edge(450,373,450,442); + if(optimistic) s+=''+text(735,127,'start → 1','solve-label'); + s+=node(450,35,'⊤:int','integer',170)+node(450,150,'[1, 0]','integer',180)+ + node(250,250,'0','integer',100)+node(650,250,'1',optimistic?'chosen':'integer',100)+ + node(450,350,'[0, 1]','integer',180)+node(450,465,'⊥:int','integer',170); + return svg('Selected integer-range lattice elements: dual ranges above constants, ordinary ranges below',s); + } + function functions() { + let s=edge(450,83,240,207)+edge(450,83,660,207)+edge(240,253,450,367)+edge(660,253,450,367); + s+=node(450,60,'∅','function',130)+node(240,230,'{add1}','chosen',190)+node(660,230,'{twice}','function',190)+node(450,390,'{add1, twice}','function',280); + s+=text(450,465,'Target-set projection; meet = union','hint'); + return svg('Function target-set lattice restricted to two targets, with signature, return type, and nullability fixed',s); + } + const point=(title,body)=>'

'+title+'

'+body+'

'; + function page(title,subtitle,picture,points,caption) { + return '

'+title+'

'+subtitle+'

'+picture+'
'+caption+'

⊤ above ⊥ · lines show lattice order · meet moves downward to the greatest lower bound

'; + } + const views={ + early:{id:'lattice',label:'Lattice',steps:0, + body:()=>page('Types describe possible values.','Chapter 4 · one lattice, several domains',early(false),[ + point('Constants are types.','arg : ⊥:int
3 : 3'), + point('Meet combines alternatives.','1 ∧ 1 = 1
1 ∧ 2 = ⊥:int'), + point('Every node computes a type.','A constant result can replace the node. Tuples meet element by element.') + ],'Other integer constants and tuple interiors are omitted.'), + notes:'

Lattice · about 30 seconds of this demo slot

These are abstract values, not the Java class hierarchy. Show global top/bottom versus domain top/bottom. Chapter 4 has one control element, flat integer constants, and tuples. AddNode.compute evaluates constant operands; meet is the operation for combining alternatives, not integer addition. Return to Example for the local rewrites.

'}, + control:{id:'lattice',label:'Lattice',steps:0, + body:()=>page('Reachability is a type, too.','Chapter 8 · the Chapter 6 control lattice carries through loops',early(true),[ + point('Control gains a dual.','⊤:ctrl = unreachable
⊥:ctrl = reachable'), + point('A Phi meets live inputs.','Phi(1, 2) : ⊥:int
A dead predecessor contributes no value.'), + point('Loops close the cycle.','The backedge is another input. Lazy Phis allow construction before that input exists.') + ],'The integer lattice is still flat here; ranges arrive in Chapter 14.'), + notes:'

Lattice · about 30 seconds of this demo slot

Only the control branch changed from the preceding diagram. Region computes reachability; Region removes dead predecessors and their Phi inputs; Phi meets the remaining value types. A loop introduces a cycle in the graph, not another type domain. Optimistic solving comes later, in Chapter 24.

'}, + domains:{id:'domains',label:'Domains',steps:0, + body:()=>page('Memory joins the type lattice.','Chapter 11 · six domains under the same global bounds',domains(),[ + point('Memory has alias slices.','MEM#2 ∧ MEM#3 = ⊥:mem
In this chapter the alias elements are flat.'), + point('Pointers carry structure.','Nullability and struct field types participate in the lattice; tuples contain types recursively.'), + point('A MemMerge is an IR node.','It carries several dependency slices. Its inputs are not a meet of distinct aliases.') + ],'Domain interiors are elided; #2 and #3 stand for two of many aliases.'), + notes:'

Domain overview · about 20 seconds

This is specifically Chapter 11: control, integers, pointers, structs, memory, and tuples. The boxes with ellipses abbreviate each domain, not extra lattice elements. Memory slices in 11 are flat aliases; typed contents arrive in Chapter 15. Distinguish the TypeMem meet from the MemMerge dependency node we just inspected.

'}, + contents:{id:'contents',label:'Memory types',steps:0, + body:()=>page('Memory carries facts about contents.','Chapters 15–17b · one alias, with integer ranges from Chapter 14',contents(),[ + point('Fix the alias; vary its contents.','MEM#2 : T
The contents have their own lattice.'), + point('Meet the stored-value types.','MEM#2:0 ∧ MEM#2:1
= MEM#2:[0,1]'), + point('Types and dependencies cooperate.','The type bounds values in a slice. Memory edges and pointer identity determine which Store a Load can see.') + ],'Selected elements for alias #2 only; other aliases and memory bounds omitted.'), + notes:'

Typed contents · about 20 seconds

Chapter 15 adds TypeMem contents, using the integer ranges introduced in Chapter 14. This is a fixed-alias, integer-contents slice of the larger lattice. The top and bottom pictured belong to those integer contents, not global memory top and bottom. The contents type summarizes allocated objects in that alias; it does not name the object selected by p.x. Return to Examples and connect this to the independent p.y Store.

'}, + ranges:{id:'ranges',label:'Ranges',steps:0, + body:()=>page('Refine the integer domain.','Chapter 14 · constants become singleton ranges',ranges(),[ + point('Meet takes the bounding interval.','0 ∧ 1 = [0,1]
[a,b] ∧ [c,d]
= [min(a,c), max(b,d)]'), + point('Dual swaps the endpoints.','dual([0,1]) = [1,0]
High ranges live above constants.'), + point('The interface stays the same.','Meet, dual, and transfer functions extend to richer types. Floats add another domain.') + ],'A selected sublattice, not all intervals. Lines may span omitted elements.'), + notes:'

Ranges · optional 15–20 seconds

Show the 0/1 diamond, with [0,1] below and its dual [1,0] above. The high side is an algebraic dual, not a second collection of runtime intervals. These selected elements omit other ranges and the float domain. Keep this quick: it supplies the picture needed again at SCCP.

'}, + functions:{id:'lattice',label:'Lattice',steps:0, + body:()=>page('A function value has a target set.','Chapter 18 · hold signature, result type, and nullability fixed',functions(),[ + point('Merge alternatives by union.','{add1} ∧ {twice}
= {add1, twice}'), + point('A singleton identifies the callee.','One known target makes direct linking possible. Trivial inlining also checks usage and recursion.'), + point('The full type has more components.','Argument tuple, return type, nullability, and target bits all participate. Only the target-set projection is drawn.') + ],'Restricted to two possible targets. The empty set is top in this projection.'), + notes:'

Function targets · about 30 seconds of this demo slot

TypeFunPtr meets target bits with bitwise OR. For this drawing fix the other components, including an int return type, and restrict the universe to the two named functions. This is not the complete function-pointer lattice or a diagram of function subtyping. The concrete demo calls each singleton directly; it does not form the two-target union. Connect singleton information to the additional single-use and non-recursion checks for inlining.

'}, + rich:{id:'rich',label:'Rich lattice',steps:0, + body:()=>'

Rich lattice

Control · integer ranges · floats · nullability · pointers · function targets · memory · structs · tuples · return addresses · constant arrays

Chapter 24 type ordering: 143 representative types and their duals across all type families, connected by 256 order edges, from global top to global bottom.

It’s just a lattice.So the fixed-point theory works.

It’s a rich lattice.So we get rich results.

Chapter 24’s actual type ordering · representative elements across every family · click for full size

', + notes:'

Rich lattice

Pull back from the little integer diamond to the full range of type families. This diagram is generated from Chapter 24 Type.gather(), including duals, and the actual isa/meet ordering: 143 representative types, 256 transitively reduced order edges. It samples each family; it does not enumerate every interval, function target set, or recursive aggregate. An edge can span elements outside the sample. Repeated compact labels can hide differing type components; opening the SVG gives full-type tooltips.

The two messages are: it is just a lattice, so the monotone fixed-point framework applies; it is a rich lattice, so the result contains far more than integer constants. Reachability, ranges, nullability, memory contents, and callable targets all participate. The usual monotonicity and convergence conditions still matter. The arrows here are lattice order, not IR dependencies.

'}, + sccp:{id:'lattice',label:'Lattice',steps:0, + body:()=>page('Solve the cycle from the high side.','Chapter 24 · the integer lattice is already available',ranges(true),[ + point('Seed unknown results at top.','Phi(1, ⊤:int) = 1'), + point('The backedge confirms it.','2 − 1 = 1
Phi(1, 1) = 1'), + point('Propagate to a fixed point.','Types descend as reachable information arrives. Control types decide which predecessors contribute.') + ],'Orange shows an analysis update; gray lines show the selected lattice order.'), + notes:'

SCCP lattice · about 30 seconds of this two-minute slot

Reuse the range picture, now showing the descent from integer top to 1. The loop Phi and subtraction both settle at 1. Global top may be used to initialize an untyped result; the picture projects onto the integer domain. Contrast with seeding at integer bottom, which cannot discover this invariant. Lattice order and the direction of solving are distinct from the graph viewer’s use-to-definition arrows.

'} + }; + const attach=(id,items)=>{R.slides.find(s=>s.id===id).views=items.map(key=>views[key]);}; + attach('arithmetic',['early']); + attach('control',['control']); + attach('memory',['domains','contents','ranges']); + attach('inline',['functions']); + attach('sccp',['rich']); +})(); diff --git a/docs/2026_REBASE/slides.css b/docs/2026_REBASE/slides.css new file mode 100644 index 00000000..67605fec --- /dev/null +++ b/docs/2026_REBASE/slides.css @@ -0,0 +1,38 @@ +:root{color-scheme:light;--paper:#f5f3ec;--ink:#172e35;--muted:#53656a;--accent:#086c60;--orange:#c95932;--line:#cbd3cd;--blue:#24648a;--purple:#715694;--scale:1} +.two-up.language-layout{margin-top:24px}.language-layout.library-wide{grid-template-columns:1fr}.panel.language-panel{height:530px;min-width:0;padding:0}.language-flip{display:flex;flex-direction:column;justify-content:space-between;width:100%;height:100%;padding:29px;text-align:left;border:0;background:transparent}.language-flip:disabled{opacity:1;cursor:default}.language-face,.language-title,.language-paragraph{display:block}.language-title{font-size:28px;font-weight:bold;line-height:1.14}.language-paragraph{font-size:24px;line-height:1.4;margin-top:23px}.language-hello{display:block;font:23px/1.5 Consolas,monospace;margin:28px 0}.language-face .cycle{font-size:22px}.panel.library-panel,.panel.methods-panel{padding:18px;display:flex;flex-direction:column}.library-toolbar{display:flex;gap:8px;align-items:center;flex-shrink:0}.library-toolbar button{font-size:16px;padding:8px 10px}.library-toolbar strong{font-size:19px;flex:1;text-align:center}.library-crumbs{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin-top:10px;flex-shrink:0}.library-crumbs button{font:17px Consolas,monospace;padding:5px;border:0;background:transparent}.library-crumbs span{color:var(--muted)}.panel .library-origin{font-size:14px;color:var(--muted);margin:5px 0 12px}.library-list{min-height:0;overflow:auto;flex:1}.library-entry{display:flex;align-items:center;gap:16px;width:100%;text-align:left;border:0;border-radius:0;border-bottom:1px solid var(--line);padding:8px 12px;font:19px Consolas,monospace;background:transparent}.file-kind{font:12px Arial,sans-serif;color:var(--muted);width:30px}.file-arrow{margin-left:auto;color:var(--accent)}.panel .library-text{flex:1;min-height:0;max-width:100%;overflow:auto;overscroll-behavior:contain;white-space:pre;margin:0;padding:14px;background:#152e36;color:#ecf1e8;border-radius:5px;font:17px/1.45 Consolas,monospace;tab-size:4}.library-text:focus-visible,.library-list:focus-visible{outline:2px solid var(--orange);outline-offset:2px}.panel .methods-source{flex:1;min-height:0;overflow:auto;font:20px/1.38 Consolas,monospace;white-space:pre;margin:18px 0 10px}.panel .methods-caption{font-size:19px;line-height:1.4;border-top:1px solid var(--line);padding-top:10px} +.slide h2.sccp-title{font-size:48px}.rich-lattice-page h2{font-size:52px}.rich-domains{font-size:20px;line-height:1.4;color:var(--muted);margin-top:12px}.rich-lattice-link{display:block;margin-top:12px}.rich-lattice-image{display:block;width:100%;height:455px;object-fit:contain}.rich-takeaways{display:grid;grid-template-columns:1fr 1fr;gap:40px;margin-top:12px}.rich-takeaways p{font-size:32px;font-weight:bold;border-top:3px solid var(--accent);padding-top:12px}.rich-takeaways small{display:block;font-size:26px;font-weight:normal;margin-top:4px}.rich-caption{font-size:16px;color:var(--muted);margin-top:16px} +.backend-source{font:20px/1.4 Consolas,monospace;margin:16px 0 0;white-space:pre-wrap;color:var(--blue)}.pipeline.backend-pipeline{margin-top:18px}.pipeline-card.backend-card{padding:0;height:502px;min-width:0}.backend-flip{display:flex;flex-direction:column;justify-content:space-between;width:100%;height:100%;border:0;padding:26px;text-align:left;background:transparent;border-radius:8px}.backend-flip:disabled{opacity:1;cursor:default}.backend-face,.backend-title,.backend-discussion,.backend-card .number{display:block}.backend-title{font-size:28px;font-weight:bold;line-height:1.14;letter-spacing:-.02em;margin-bottom:18px}.backend-discussion{font-size:23px;line-height:1.4}.flip-hint{display:block;font-size:14px;color:var(--accent);margin-top:12px}.flipped .backend-flip{padding:15px 16px}.dump-heading{display:block;font-size:18px;font-weight:bold;margin-bottom:12px;color:var(--accent)}.backend-card .backend-dump{border:0;padding:0;margin:0;font:14px/1.27 Consolas,"Liberation Mono",monospace;white-space:pre-wrap;overflow-wrap:anywhere;color:var(--ink)}.backend-card .backend-dump.selected{font-size:14.5px;line-height:1.25}.backend-card .backend-dump.encoded{font-size:16px;line-height:1.3}.backend-dump strong{color:var(--orange);font-weight:bold}.lower-line.backend-provenance{margin-top:15px}.backend-provenance p{font-size:18px}.backend-provenance .chips span{font-size:16px;padding:6px 12px} +*{box-sizing:border-box}body{margin:0;background:#dfe4df;color:var(--ink);font-family:Arial,Helvetica,sans-serif}button,a,input{touch-action:manipulation}button{font:inherit;cursor:pointer}button:focus-visible,a:focus-visible,textarea:focus-visible{outline:3px solid #e17d39;outline-offset:5px}button:disabled{opacity:.4;cursor:default}a{color:var(--accent);text-underline-offset:5px}button{border:1px solid var(--line);background:var(--paper);color:var(--ink);border-radius:6px;padding:9px 14px}button:hover:not(:disabled){background:#e0e9e2}button.primary{background:var(--accent);color:#fff;border-color:var(--accent)}button.primary:hover{background:#09584f} +#viewport{position:fixed;inset:0 0 54px;overflow:hidden}.slide{position:absolute;left:50%;top:50%;width:1440px;height:900px;transform:translate(-50%,-50%) scale(var(--scale));background:var(--paper);padding:54px 72px 64px;overflow:hidden;box-shadow:0 20px 80px #172e3518;display:flex;flex-direction:column} +.slide:not(.still) .slide-content{animation:arrive .3s ease-out}@keyframes arrive{from{opacity:0;transform:translateY(9px)}to{opacity:1;transform:none}} +.kicker{display:flex;justify-content:space-between;align-items:center;font-size:17px;letter-spacing:.12em;text-transform:uppercase;font-weight:700;margin-bottom:30px}.kicker .tag{border:1px solid var(--accent);padding:7px 11px;border-radius:30px;color:var(--accent);letter-spacing:.05em;font-size:14px} +h1,h2,h3,p{margin:0}h1{font-size:100px;line-height:.99;letter-spacing:-.055em;font-weight:750}h2{font-size:62px;line-height:1.04;letter-spacing:-.04em;font-weight:700}h3{font-size:28px;letter-spacing:-.02em;line-height:1.14}p{font-size:25px;line-height:1.4}.muted{color:var(--muted)}.accent{color:var(--accent)}.orange{color:var(--orange)}.eyebrow{font-size:16px;font-weight:bold;text-transform:uppercase;letter-spacing:.13em;color:var(--muted);margin-bottom:14px} +.slide-content{flex:1;min-height:0}.footer{position:absolute;bottom:25px;left:72px;right:72px;border-top:1px solid var(--line);padding-top:13px;display:flex;justify-content:space-between;font-size:15px;color:var(--muted)}.footer strong{color:var(--ink)}.build-dots{display:flex;gap:7px}.build-dots i{width:7px;height:7px;border-radius:50%;background:#c9d1ca}.build-dots i.on{background:var(--accent)} +.title-layout{display:grid;grid-template-columns:1.2fr .8fr;gap:82px;height:100%;align-items:center}.title-copy h1{font-size:116px;line-height:.98}.title-copy .subtitle{font-size:29px;line-height:1.35;max-width:650px;margin-top:30px}.speaker{margin-top:55px}.speaker strong{font-size:30px;display:block}.speaker span{font-size:19px;display:block;margin-top:9px;color:var(--muted)}.portrait{width:100%;height:610px;object-fit:cover;object-position:50% 35%;border-radius:3px}.photo-caption{font-size:14px;color:var(--muted);margin-top:12px}.title-line{width:74px;height:6px;background:var(--orange);margin-bottom:30px} +.title-repo{position:absolute;left:72px;bottom:82px;font:23px Consolas,monospace} +.bio-grid{display:grid;grid-template-columns:1.1fr .9fr;gap:60px;align-items:center;margin-top:35px}.bio-list{list-style:none;padding:0;margin:35px 0 30px}.bio-list li{border-top:1px solid var(--line);padding:18px 0;font-size:25px;line-height:1.35}.bio-list small{display:block;font-size:20px;color:var(--muted);margin-top:6px}.club-image{width:100%;height:340px;object-fit:contain;mix-blend-mode:multiply}.club-caption{font-size:20px;margin:20px 0;text-align:center}.link-row{display:flex;gap:12px;flex-wrap:wrap;margin-top:22px}.link-row a{font-size:20px;padding:12px 16px;border:1px solid var(--line);border-radius:5px;text-decoration:none}.link-row a:hover{background:#e0e9e2} +.demo-layout{display:grid;grid-template-columns:1.03fr .97fr;gap:46px;margin-top:27px}.demo-code{background:#152e36;color:#ecf1e8;border-radius:9px;overflow:hidden;box-shadow:0 10px 25px #122b3410}.code-head{display:flex;justify-content:space-between;align-items:center;padding:13px 20px;background:#203d46;font:16px Consolas,monospace;color:#bdcec8}.code-head button{font-family:Arial,sans-serif;font-size:15px;background:#2e5356;color:#fff;border-color:#638582;padding:6px 13px}.demo-code pre{padding:24px 23px;margin:0;font:25px/1.5 Consolas,"Liberation Mono",monospace;tab-size:4;white-space:pre-wrap;overflow-wrap:normal}.demo-code.long pre{font-size:22px;line-height:1.45}.comment{color:#a6c0b5}.demo-actions{display:flex;gap:10px;margin-top:14px;flex-wrap:wrap}.demo-actions button,.demo-actions a{font-size:17px}.demo-actions a{display:inline-flex;align-items:center;padding:9px 2px}.launch{font:18px Consolas,monospace;display:block;margin-top:17px;color:var(--muted)}.demo-right{padding-top:5px}.thesis{font-size:28px;line-height:1.35;max-width:580px;margin-bottom:23px} +.fact{border-top:1px solid var(--line);padding:14px 0;display:flex;align-items:baseline;gap:18px}.fact b{font-size:18px;color:var(--accent);min-width:65px}.fact span{font-size:22px;line-height:1.32}.result{background:#e2ebe2;border-left:5px solid var(--accent);padding:19px 22px;margin-top:22px}.result strong{font:30px/1.3 Consolas,monospace}.result small{font-size:17px;display:block;margin-top:10px;color:var(--muted)}.watch{margin-top:20px;font-size:19px;line-height:1.45;color:var(--muted)}.watch strong{color:var(--ink)}.demo-tabs{display:flex;gap:8px;margin-top:17px}.demo-tabs button{font-size:16px}.demo-tabs button.active{background:var(--accent);color:white} +[data-reveal]{transition:opacity .25s,transform .25s}[data-reveal].unrevealed{opacity:.12;transform:translateY(5px)}.state-card{border:1px solid var(--line);padding:20px;border-radius:7px;margin-top:20px;background:#ffffff50}.state-card .state{display:none}.state-card .state.active{display:block}.formula{font:34px/1.5 Consolas,monospace}.formula small{font-size:19px;display:block;color:var(--muted)}.svg-graph{width:100%;height:235px;overflow:visible}.svg-graph text{font-family:Consolas,monospace;fill:var(--ink);font-size:20px}.svg-graph .node{fill:#e9efea;stroke:var(--accent);stroke-width:2}.svg-graph .phi{fill:#eee7f5;stroke:var(--purple)}.svg-graph .ctrl{fill:#faedce;stroke:#b88228}.svg-graph .edge{fill:none;stroke:#587075;stroke-width:2}.svg-graph .memory-edge{stroke:var(--blue);stroke-width:3}.graph-caption{font-size:15px;color:var(--muted);text-align:center} +.pipeline{display:grid;grid-template-columns:repeat(3,1fr);gap:22px;margin-top:44px}.pipeline-card{position:relative;border:1px solid var(--line);padding:27px 26px;min-height:380px;background:#ffffff50;border-radius:8px}.pipeline-card .number{font:56px/1 Consolas,monospace;color:var(--accent);margin-bottom:24px}.pipeline-card h3{margin-bottom:18px}.pipeline-card p{font-size:23px}.pipeline-card code{display:block;border-top:1px solid var(--line);margin-top:25px;padding-top:20px;font:21px/1.7 Consolas,monospace;color:var(--blue)}.lower-line{display:flex;justify-content:space-between;align-items:center;margin-top:30px}.chips{display:flex;gap:12px}.chips span{font-size:20px;border:1px solid var(--line);padding:9px 17px;border-radius:30px} +.two-up{display:grid;grid-template-columns:1fr 1fr;gap:36px;margin-top:38px}.panel{background:#ffffff60;border:1px solid var(--line);border-radius:8px;padding:29px;min-height:400px}.panel .eyebrow{color:var(--accent)}.panel pre{font:23px/1.5 Consolas,monospace;white-space:pre-wrap;margin:28px 0}.panel p{font-size:24px}.cycle{display:flex;align-items:center;justify-content:center;gap:16px;margin:26px 0;font:22px Consolas,monospace}.cycle span{padding:15px;background:#e1eae2;border:1px solid var(--line);border-radius:6px}.cycle b{color:var(--orange)}.statement{font-size:30px;line-height:1.4;margin-top:32px} +.sccp-table{width:100%;border-collapse:collapse;margin-top:24px;font-size:24px}.sccp-table th,.sccp-table td{text-align:left;padding:16px;border-bottom:1px solid var(--line)}.sccp-table th{font-size:17px;text-transform:uppercase;color:var(--muted);letter-spacing:.08em}.sccp-table td:not(:first-child){font-family:Consolas,monospace}.sccp-table tr:last-child td{color:var(--accent);font-weight:bold}.sccp-warning{font-size:21px;margin-top:28px;line-height:1.4}.takeaway-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:32px;margin:45px 0}.takeaway-grid div{border-top:4px solid var(--accent);padding-top:23px}.takeaway-grid h3{font-size:33px;margin-bottom:15px}.takeaway-grid p{font-size:25px}.repo-link{font:27px Consolas,monospace}.optional-link{font-size:19px;margin-top:23px;display:block}.module-diagram{display:flex;gap:25px;align-items:center;justify-content:center;margin:38px 0}.module-diagram div{padding:25px;border:1px solid var(--line);border-radius:7px;background:#fff8;font-size:25px;line-height:1.5}.module-diagram b{font-size:35px;color:var(--orange)} +#controls{position:fixed;bottom:0;height:54px;left:0;right:0;display:flex;gap:7px;justify-content:center;align-items:center;background:#f5f3eced;border-top:1px solid var(--line);z-index:5}#controls button{font-size:13px;padding:6px 11px}#position{font:13px Consolas,monospace;min-width:82px;text-align:center}.control-divider{height:20px;border-left:1px solid var(--line);margin:0 6px}#notes{position:fixed;z-index:8;right:20px;bottom:70px;width:min(650px,90vw);max-height:70vh;overflow:auto;padding:24px;background:#fffdf7;border:1px solid var(--line);box-shadow:0 15px 70px #102d3540;border-radius:10px;font-size:18px;line-height:1.5}#notes p,#notes li{font-size:18px;line-height:1.5}#notes ol{padding-left:24px}#notes li{margin:12px 0}.notes-toolbar{display:flex;gap:10px;align-items:center}.notes-toolbar strong{flex:1}.notes-toolbar button{font-size:13px}#pace{margin:16px 0;padding:10px;background:#e2ebe2;font:16px Consolas,monospace}#pace.over{background:#ffe5d6}#notes-content h3{font-size:23px;margin-bottom:15px} +dialog{border:1px solid var(--line);border-radius:12px;background:var(--paper);color:var(--ink);max-width:min(1150px,95vw);max-height:90vh;width:950px;padding:34px}dialog::backdrop{background:#0b202dcc;backdrop-filter:blur(5px)}.dialog-close{float:right;font-size:26px;padding:1px 10px}dialog h2{font-size:34px;margin:5px 0 20px}dialog p{font-size:19px;line-height:1.5;margin:12px 0}dialog .overview-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:10px}dialog .overview-grid button{text-align:left;padding:16px;line-height:1.5}dialog .overview-grid small{display:block;color:var(--muted)}dialog img{max-width:100%;max-height:68vh;display:block;margin:auto;object-fit:contain}dialog textarea{width:100%;height:250px;font:18px/1.5 Consolas,monospace;padding:15px}.keys{display:grid;grid-template-columns:130px 1fr;gap:13px;font-size:18px}kbd{font-family:Consolas,monospace;background:#e2e7df;padding:3px 7px;border-radius:4px}#toast{position:fixed;left:50%;bottom:73px;transform:translateX(-50%);padding:12px 22px;border-radius:8px;background:#172e35;color:white;z-index:30;opacity:0;pointer-events:none;transition:opacity .15s}#toast.show{opacity:1}#blackout{position:fixed;inset:0;background:#000;z-index:50} +body.presenter #viewport{right:390px}body.presenter #notes{display:block;top:15px;right:15px;bottom:69px;width:360px;max-height:none;box-shadow:none;padding:20px}body.presenter .notes-toolbar{flex-wrap:wrap}body.presenter .notes-toolbar strong{flex-basis:100%}body.presenter #controls{right:390px}body.presenter #notes-toggle,body.presenter #presenter,body.presenter #fullscreen{display:none}body.presenter #notes p,body.presenter #notes li{font-size:16px}body.presenter #notes-content h3{font-size:21px} +#slide[data-id="title"] .kicker .tag{visibility:hidden} +.view-tabs{display:flex;gap:5px;letter-spacing:0;text-transform:none}.view-tabs button{font-size:16px;padding:8px 12px}.view-tabs button[aria-pressed="true"]{background:var(--accent);border-color:var(--accent);color:white} +.lattice-page h2{font-size:55px}.lattice-subtitle{font-size:23px;color:var(--muted);margin-top:16px}.lattice-layout{display:grid;grid-template-columns:900px 1fr;gap:30px;margin-top:24px;align-items:start}.lattice-layout figure{margin:0}.lattice-svg{display:block;width:900px;height:500px}.lattice-svg text{font:25px Arial,Helvetica,sans-serif;fill:var(--ink)}.lattice-svg .hint{font-size:21px;fill:var(--muted)}.lattice-svg .domain-name{font-size:21px;font-weight:bold}.lattice-svg .ellipsis{font-size:32px;fill:var(--muted)}.lat-edge{stroke:#7d9090;stroke-width:2;fill:none}.lat-node{stroke-width:1.7;fill:#e5edf1;stroke:var(--blue)}.lat-node.control{fill:#faedce;stroke:#b88228}.lat-node.tuple{fill:#f4e2eb;stroke:#99617f}.lat-node.pointer{fill:#cce4d6;stroke:#267654}.lat-node.struct{fill:#e2edd7;stroke:#648539}.lat-node.memory{fill:#dbe8f4;stroke:#24648a}.lat-node.function{fill:#e9e1f2;stroke:#715694}.lat-node.global{fill:var(--ink);stroke:var(--ink)}.lat-node.global+text{fill:white}.lat-node.chosen{fill:#f9e3d6;stroke:var(--orange);stroke-width:3}.lat-elided{fill:var(--paper);stroke:var(--line);stroke-dasharray:4 4}.lat-solve{stroke:var(--orange);stroke-width:4;fill:none;stroke-dasharray:9 5}.lattice-svg .solve-label{font-size:22px;fill:var(--orange)}.lattice-layout figcaption{font-size:18px;line-height:1.35;color:var(--muted);margin:12px 0 0;text-align:center}.lattice-point{border-top:2px solid var(--line);padding:17px 0}.lattice-point h3{font-size:25px;line-height:1.15;margin-bottom:12px}.lattice-point p{font-size:22px;line-height:1.35}.lattice-point code{font:19px/1.5 Consolas,monospace}.lattice-legend{font-size:19px;color:var(--muted);margin-top:21px} +#slide[data-id="control"] .svg-graph{height:190px} +.demo-code.long pre{font-size:24px;line-height:1.4} +.pending-link{display:inline-flex;align-items:center;font-size:18px;color:var(--muted);padding:12px 0} +@media(prefers-reduced-motion:reduce){*,*::before,*::after{animation:none!important;transition:none!important}.unrevealed{transform:none!important}} +@media(max-width:650px){#controls{gap:3px}#controls button{padding:6px 8px}#presenter{display:none}.control-divider{margin:0 2px}.keys{grid-template-columns:95px 1fr}dialog{padding:24px}dialog .overview-grid{grid-template-columns:1fr}} +@media print{body{background:white}#viewport{position:static;overflow:visible}.slide{position:relative;left:auto;top:auto;transform:none;width:100%;height:auto;min-height:95vh;box-shadow:none;break-after:page}.slide:not(.still) .slide-content{animation:none}#controls,#notes,#toast,dialog,#blackout{display:none!important}[data-reveal].unrevealed{opacity:1;transform:none}.state-card .state:last-child{display:block}.state-card .state:not(:last-child){display:none}@page{size:landscape;margin:10mm}} + +.result math{font-size:30px;math-style:normal;text-align:left;margin:0} +#slide[data-id="control"] .result{padding:12px 22px;margin-top:14px} + +.memory-partition{margin:0 0 16px}.memory-partition svg{display:block;width:100%;height:auto}.memory-partition text{font:25px Consolas,monospace;fill:var(--ink)}.memory-partition .partition-title{font:bold 24px Arial,sans-serif}.memory-partition .partition-detail{font:17px Arial,sans-serif;fill:var(--muted)}.alias-x{fill:#d9e9dd}.alias-y{fill:#e8e0f1;transition:fill .25s}.alias-y.touched{fill:#f4cba9}.alias-rest{fill:#dfe8ef}.partition-outline{fill:none;stroke:#6b8285;stroke-width:2}.memory-partition figcaption{font-size:20px;line-height:1.35;color:var(--muted);text-align:center;margin-top:5px} + +.research-note{font-size:17px;line-height:1.4;margin-top:16px;padding-top:10px;border-top:1px solid var(--line);color:var(--muted)} diff --git a/docs/2026_REBASE/slides.js b/docs/2026_REBASE/slides.js new file mode 100644 index 00000000..fc54dc41 --- /dev/null +++ b/docs/2026_REBASE/slides.js @@ -0,0 +1,214 @@ +/* Content and speaker notes. Durations exclude the optional Chapter 25 slide. */ +(function () { + const R = window.REBASE; + const esc = s => String(s).replaceAll("&","&").replaceAll("<","<").replaceAll(">",">").replaceAll('"',"""); + const external = (url, text, cls="") => ''+text+''; + const demo = id => R.demos.find(d => d.id === id); + function source(id, long=false) { + const d=demo(id); + return '
'+d.chapter+' / '+id+'.smp
'+esc(d.code)+'
'+ + (id==='sccp'?'':'')+ + 'Source ↗
make -C '+(d.viewerChapter||d.chapter)+' view
'; + } + function result(id, label, formula) { + const d=demo(id); + return '
'+(formula||''+esc(d.result)+'')+''+esc(label||d.inputs)+'
'; + } + function states(items) { + return '
'+items.map((item,i)=>'
'+item+'
').join('')+'
'; + } + function backendCard(state, index, title, discussion, flow, kind, caption) { + const flipped=!!(state.backend & (1<line.trim().replace(/ {2,}/g,' ').replace(/-{4,}/g,'---')).join('\n'); + const dump=text.split('\n').map(line=>{ + const hot=/NegX86|MemAddX86|\bneg\b|\badd8\b/.test(line); + return hot?''+esc(line)+'':esc(line); + }).join('\n'); + return '
'+ + '
'; + } + function memoryPartition(state) { + const array=state.demo==='memory', x=array?'Totals.sum':'Pair.x', y=array?'Totals.visits':'Pair.y'; + return '
Equivalence classes partition whole memory'+ + 'Whole memory'+ + ''+ + ''+ + ''+ + ''+ + ''+x+'all instances'+ + ''+y+'all instances'+ + 'all the rest'+(array?'including data[]':'other locations')+''+ + '
Disjoint classes; together, all memory.
Same class may alias. Different classes cannot.
'; + } + function graph(kind) { + const start=''; + if(kind==='loop') return start+ + ''+ + ''+ + 'Loop'+ + 'Phi_i'+ + '0'+ + 'Add'+ + '1'; + if(kind==='phi') return start+ + ''+ + 'n'+ + '-n'+ + 'Region'+ + 'Phi_n'; + return start+ + ''+ + 'arg'+ + '2'+ + '6'+ + 'Mul'+ + 'Add

Arrows point from uses to definitions.

'; + } + const links=()=>''; + const notes = (lead, beats, extra="") => '

'+lead+'

    '+beats.map(b=>'
  1. '+b+'
  2. ').join('')+'
'+extra; + R.slides=[ + { + id:'title',label:'A Simple Tutorial',section:'REBASE 2026',minutes:1,steps:0,still:true, + body:()=>'

A Simple
Tutorial.

An open-source, all-Java compiler
modeled after Java’s C2.

Cliff ClickSea of Nodes · from source to machine code
Cliff Click seated on outdoor stone steps

REBASE / SPLASH · 2026

'+external(R.repo,'github.com/SeaOfNodes/Simple','title-repo'), + notes:notes('An executable compiler tutorial',[ + 'Assume SSA and compiler background. Simple is a small language used to explain a real optimizing compiler architecture.', + 'The compiler is written in Java, modeled on C2, and open source. The teaching unit is a complete compiler snapshot, with runnable tests and an explanation.', + 'Today: four live graphs, then the path to machine code. Keep the title still; advance when ready.' + ]) + }, + { + id:'bio',label:'Who am I?',section:'Cliff Click',minutes:1,steps:0, + body:()=>'

Who am I?

Cliff Click

  • HotSpot’s original C2 compilerSea of Nodes, optimization, and the JVM
  • Azul, H2O, and half a dozen other startupsJVMs, low-pause GC, and distributed computing
  • Coffee Compiler ClubFounder and host · language implementation discussions
'+links()+'
Coffee Compiler Club logo

People who enjoy talking about compilers.

', + notes:notes('Keep the biography to a minute',[ + 'Select two relevant facts: original C2 and Sea of Nodes; subsequent JVM and runtime work at Azul.', + 'Coffee Compiler Club is the community connection. Point to the YouTube channel and invite people to email for a Discord invite.', + 'Transition: rather than describe the entire compiler, watch four graph transformations.' + ],'

Short bio adapted from the supplied 2024 biography.

') + }, + { + id:'arithmetic',label:'1–4 · Parsing and peepholes',section:'Chapters 1–4',minutes:5,steps:2,demo:'arithmetic', + body:()=>'

Parse straight into
an optimized graph.

'+source('arithmetic')+'

SSA construction and local rewriting happen together.

'+graph('arithmetic')+'
WatchIdentity removal → reassociation → constant folding.
'+result('arithmetic','Expected optimized expression; inspect the actual graph in the viewer.')+'
', + notes:notes('Live demo 1 · leave at 07:00',[ + '0:00–0:45: Show the Lattice tab briefly, then return to Example and predict the source result. No separate AST is needed for this construction. The chapter boundary is intentionally tiny.', + '0:45–1:15: Copy code. In a terminal at the repository root run make -C chapter04 view. Paste into the viewer and Compile.', + '1:15–4:15: Use Next/Right to observe a few enclosing peepholes: arg+0 disappears, constants reassociate, and repeated arg becomes multiplication. Point to types on nodes and uses pointing to definitions.', + '4:15–5:00: Jump Last; the result is 2*arg+6. Return to slides. Before launching the next chapter, stop this viewer with Ctrl+C in its terminal.' + ],'

Fallback: “Final graph” is a captured compiler graph. Advance builds to reveal the conclusion. No need to step through all 51 captured frames.

') + }, + { + id:'control',label:'5–8 · Control and loops',section:'Chapters 5–8',minutes:5,steps:2,demo:'control', + body:state=>'

Control flow is
part of the graph.

'+source('control',true)+'

'+(state.step===0?'Regions merge control.
Phis select the corresponding values.':'Loop is a Region.
Phi_i merges entry and backedge.')+'

'+graph(state.step===0?'phi':'loop')+'
LoopsA backedge supplies another Phi input. Construction can be incomplete.
'+result('control',null,'sum=∑i=1|arg|i')+'
', + notes:notes('Live demo 2 · leave at 12:00',[ + '0:00–0:45: Briefly show the Lattice tab: control now has live/dead types. Return to Example. A branch chooses abs(arg); the loop accumulates integers from 1 through abs(arg). Build 1 shows the absolute-value Phi; highlight the corresponding branch in the source. Build 2 switches to Loop, Phi_i, and Add(i,1). Build 3 keeps that graph and reveals the sigma sum. The counter sketch omits the Loop control predecessors.', + '0:45–1:15: Stop the prior viewer. Run make -C chapter08 view; paste this example and Compile.', + '1:15–4:15: Find the initial Region/Phi, then the Loop and its backedge. Show the loop-carried i and sum values. Explain lazy Phi creation and how the backedge supplies the next iteration. Fold/unfold the loop for context.', + '4:15–5:00: Jump Last and trace the exit value. For arg=5 the result is 1+2+3+4+5=15. The viewer shows compilation, not the iterations of runtime execution.' + ],'

Chapters 5/6 introduce branches and dead control; 7/8 introduce loops and lazy Phis. Avoid walking every frame.

') + }, + { + id:'memory',label:'9–17b · Values, memory, scheduling',section:'Chapters 9–17b',minutes:5,steps:2,demo:'aliases', + body:state=>'

Memory is dataflow, too.

'+source(state.demo||'aliases',true)+'

Partition memory into
equivalence classes.

'+memoryPartition(state)+states(state.demo==='memory'?[ + '
data[i]Array element memory is another slice.
', + '
t.sum / t.visitsSeparate field classes carry separate dependencies.
', + '
4*arg + 10Runtime result; the graph still contains loops.
' + ]:[ + '
p.x → Pair.xAll Pair.x fields share one equivalence class.
', + '
p.y = 99 → Pair.yOnly this slice changes; Pair.x is untouched.
', + '
p.x − before → 0The short example isolates this fold.
' + ])+'

'+(state.demo==='memory'?'Inspect: two loops, array Loads/Stores, and blue memory edges.
Runtime result: 4*arg+10.':'Inspect: writing p.y leaves p.x unchanged.
Result: 0.')+'

Simple type-based aliasing approached the RLE limit.
'+external('https://people.cs.umass.edu/~moss/papers/pldi-1998-tbaa.pdf#page=8','Diwan et al., PLDI \u201998 · 8 Modula-3 programs')+'

', + notes:notes('Live demo 3 · leave at 17:00',[ + '0:00–0:45: Briefly show Domains and Memory types, then return to Examples. Use the partition picture: Pair.x, Pair.y, and the rest are disjoint equivalence classes whose union is whole memory. The classes group locations across all instances, not one class per object.', + '0:45–1:15: Run make -C chapter17b view. Paste Short alias example. Show that p.y changes while p.x does not, and the result becomes zero.', + '1:15–3:15: Trace the Loads and Store through their field equivalence classes. Same-class accesses may alias; different classes cannot. MemMerge recombines the slices without emitting an instruction. Explain why writing p.y does not clobber p.x. Read-only access would not make a Load independent of memory.', + '3:15–4:30: Switch back to this slide, select Array + object loops, Copy code, then compile it in the same viewer. Jump Last, fold/unfold the loops, and inspect loop-carried memory and the sum and visits aliases.', + '4:30–5:00: GCM uses these dependencies to choose legal placements; it does not guess ordering from source order. Return to slides.' + ],'

The graph viewer captures parsing/optimization/type checking, not GCM execution. The large graph has 54 nodes at its final checkpoint; do not step through all 319 frames.

Research context: Diwan, McKinley, and Moss, Type-Based Alias Analysis, PLDI 1998, sections 3.5–3.6 (p. 113). A runtime upper bound left at most an average 2.5% more heap loads eliminable beyond their analysis on eight Modula-3 benchmarks. This is a load-elimination bound, not a speedup percentage. More static opportunities did not translate into corresponding runtime gains. This supports choosing useful, inexpensive alias distinctions; it does not establish that this exact equivalence-class scheme is optimal for Java. The study is a close match to the recalled oracle experiment, not an identified IBM/Java paper.

') + }, + { + id:'inline',label:'18 · Functions and Calls',section:'Chapter 18',minutes:5,steps:2,demo:'inline', + body:state=>'

Functions and Calls

'+source('inline')+'

'+[ + 'Declare and define functions.
Parse their bodies and calls.
Build the graph as we go.', + 'Trivial inlining:
erase the call boundary
with simple graph rewrites.', + 'Fun is a Region.
Parm is a Phi.
The familiar rules still apply.' + ][state.step]+ '

'+states([ + '
twice(1 + add1(2)) + 3Two functions. Two call sites.
', + '
(1 + (2 + 1)) * 2 + 3Splice control, arguments, memory, and results.
', + '
return 11;Ordinary constant folding finishes the job.
' + ])+(state.step===0?'
FunctionsFun, Parm, Return
CallsCall, CallEnd
':'
ProofOne target, one use of its function pointer, no self-recursive inline.
')+result('inline')+'
', + notes:notes('Live demo 4 · leave at 22:00',[ + '0:00–0:45: Introduce function definitions and calls: parsing builds Fun, Parm, Return, Call, and CallEnd nodes. The whole top-level body is an implicit main. Each explicit function has a Fun, Parms, and one merged Return. Briefly show the Lattice tab and its singleton function targets, then return to Example. The second build shows trivial inlining by simple graph rewrites.', + '0:45–1:15: Stop the prior viewer. Run make -C chapter18 view; paste and Compile.', + '1:15–4:15: Find a Call/CallEnd and the function entry. Look for the FOLDING label while a single-use function is being inlined. Follow one parameter becoming the caller argument and the Return value taking the place of the call result. Gather → rewrite → release makes the local edit visible.', + '4:15–5:00: Jump Last. Both call boundaries are gone and the return value is 11. This example moves single-caller bodies; it does not demonstrate cloning for multi-callsite inlining.' + ],'

If tracing takes too long, show the captured final graph and use the three schematic builds on the slide.

') + }, + { + id:'backend',label:'19–21 · From IR to instructions',section:'Chapters 19–21',minutes:2,steps:2, + body:state=>'

Give the graph a machine.

'+esc(R.backend.source.trim().split('\n').map(line=>line.trim()).reduce((text,line,i)=>text+(i===0?'':i===2?'\n    ':' ')+line,''))+'
'+ + backendCard(state,0,'Select instructions','Match ideal nodes to machine operations. Carry operand and calling-convention constraints.','Ideal graph
↓
Machine graph','selected','Selected graph')+ + backendCard(state,1,'Allocate registers','Build live ranges and interference. Coalesce, color, split, and spill.','Virtual values
↓
Registers + stack','assembly','Allocated assembly')+ + backendCard(state,2,'Encode and execute','Lay out code, emit instruction bytes, resolve relocations, and build object files.','Scheduled instructions
↓
Executable code','encoded','Instruction bytes')+ + '

One program · x86-64 System V · Chapter 21 compiler

x86-64ARM64RISC-V
', + notes:notes('Two minutes for the backend',[ + '19: instruction selection happens before GCM. Target nodes still carry dependencies. Matching can absorb a Load into an arithmetic instruction.', + 'Click each revealed column to flip between discussion and its captured dump; click again to return. Flips persist across builds and synchronize with the presenter window. The returned function receives an existing writable Box, so there is no allocation or calloc lead-in. It adds abs(arg) into box.x and returns that same value.', + 'All three captures use the Chapter 21 compiler at the corresponding phase: Chapters 19 and 20 do not yet select unary Minus. The selected table includes every node and input slot, with concrete Java class names instead of shortened op labels; types and redundant use lists are omitted. Follow NegX86 #20, Phi #19, and MemAddX86 #16. Load + Add + Store become one read-modify-write instruction.', + '20: global graph coloring, with register masks and calling conventions. Legality first; spill quality is a separate question. ARM joins the existing x86/RISC-V ports here.', + 'The middle capture is CodeGen.asm() immediately after register allocation: arg is rsi, box is rdi, and the result is rax. Labels show ordered blocks; the Phi coalesces into rax. Offsets and the ?? jump are provisional here, and the return still displays callee-save bookkeeping.', + '21: actual instruction encodings and object output. Distinguish native execution from ARM/RISC-V test evaluators; the encoders are shared, but selection and allocation remain in chapter snapshots.', + 'The final CodeGen.asm() capture follows encode(): 48f7d8 is neg rax; 480107 is add qword [rdi], rax. Layout reverses the branch to j>= and removes the extra jump. Hex is shown in memory byte order. The printer labels the compare-with-zero as test; 4883f800 actually encodes cmp rax, 0. Only whitespace and long divider rules are compacted in these assembly displays; raw dumps and a regeneration tool are included in the deck.' + ],'

Target time: 24:00. This is a progression, not a claim that the three phases exhaust the backend pipeline.

') + }, + { + id:'language',label:'22–23 · I/O, methods, types',section:'Chapters 22–23',minutes:2,steps:1, + body:state=>R.languageBody(state), + notes:notes('Language features stress the representation',[ + '22: printing is a real chain of function and field accesses, ending at a C ABI boundary. Show how much existing infrastructure participates in one line of code.', + 'Click the Chapter 22 column to browse the bundled Chapter 25 standard library. Start in sys; Up reaches the root and sys.smp. Open adt for bitset.smp, or io.smp, aryu8.smp, and libc.smp to connect the library to language features. Breadcrumbs and Up navigate folders or leave a file; Discussion restores the original column. Full width gives long files more room. File contents scroll and can be copied. This is a snapshot of the latest chapter, including features beyond Chapter 22.', + '23: methods add a self parameter. A struct contains a function whose signature mentions the struct; types themselves become cyclic.', + 'Click the Chapter 23 column for a complete Counter class and calls, validated with the Chapter 23 compiler and evaluator. n is an instance field; new initializes it to arg. add mutates n and returns self, so calls can chain; get reads n. The result is arg + 7. Discussion restores the conceptual explanation.', + 'The interesting point for this audience is preserving canonical type identity and lattice operations while the representation becomes recursive.' + ],'

Target time: 26:00. No extra live demo is budgeted.

') + }, + { + id:'sccp',label:'24 · Sparse Conditional Constant Propagation',section:'Chapter 24',minutes:2,steps:2,demo:'sccp', + body:()=>'

Sparse Conditional Constant Propagation

'+source('sccp')+'

This one stays on the slide. The loop’s return value is always 1.

The lattice and transfer functions are already there.

'+states([ + '
Phi(1, ⊥) = ⊥Pessimistic propagation gets stuck.
', + '
Phi(1, ⊤) = 1Start at the top; propagate reachable information.
', + '
2 − 1 = 1The backedge confirms the invariant.
' + ])+'
ValueInitialFixed point
Loop Phi⊤1
2 − Phi⊤1

After SCCP, the program is fully typed.
SCCP is the type analysis pass.

', + notes:notes('Optimism earns its keep',[ + 'Use the source as a concrete loop, but the equations are SSA pseudocode. The pessimistic fixed point cannot discover x=1 through the cycle.', + 'For this talk, Copy viewer command launches make -C chapter25 view. Chapter 25 demonstrates the same SCCP example using its separately compiled standard library, avoiding Chapter 24’s thousands of library capture frames. The slide topic and lattice remain Chapter 24.', + 'Use Rich lattice for the big picture, then return to Example. The entry value sharpens the Phi to 1; the backedge evaluates to 1 and confirms it. Explain the direction of monotonicity, not just “assume it works.”', + 'Control propagation makes the solve conditional. Chapter 24 also discovers interprocedural call-graph edges; Chapter 18’s local linking was only the beginning.' + ],'

Target time: 28:00. Continue to the closing slide, or use Overview → Chapter 25 if two minutes remain and replace the closing discussion.

') + }, + { + id:'modules',label:'25 · Optional: separate compilation',section:'Chapter 25 · optional',minutes:0,steps:1,optional:true, + body:()=>'

What survives
separate compilation?

Library source
Types + ideal IR
→
Object file
Native code + .simple
→
Client compilation
Import + optimize

Imported functions can participate in optimization.

Identity crosses a boundary.

Types, aliases, and function indices must be reconciled between units.

Information arrives late.

SSA construction, forward types, and constructor memory need stronger contracts.

', + notes:notes('Optional · spend at most two minutes',[ + 'This is outside the default 30-minute path. Use it instead of the final two-minute discussion, not in addition.', + 'The object contains both native code and a .simple section with types and ideal IR. Imported IR can be optimized and inlined in the client.', + 'The compiler must reconcile global identities and incomplete information. This is why Chapter 25 is more than an object writer. Do not attempt its whole architecture here.' + ]) + }, + { + id:'close',label:'Takeaways and discussion',section:'A Simple Tutorial',minutes:2,steps:0, + body:()=>'

One graph.
Many compiler lessons.

Build

Construct SSA directly.
Make dependencies explicit.

Rewrite

Use types and local rules.
Iterate to a fixed point.

Lower

Keep the graph useful
all the way to code.

Read a chapter. Run it. Watch what changes.

'+links()+'', + notes:notes('Leave room for the room',[ + 'Each chapter is a runnable compiler snapshot, not a diff that needs the final compiler to make sense.', + 'Invite questions about where the unified graph helps and where it imposes costs. There is no need to sell a universal IR winner.', + 'Point people to the repository, chapter READMEs, and Coffee Compiler Club. Stop at 30:00.' + ]) + } + ]; + R.escape=esc; +})(); diff --git a/docs/2026_REBASE/stdlib.js b/docs/2026_REBASE/stdlib.js new file mode 100644 index 00000000..22c92fe4 --- /dev/null +++ b/docs/2026_REBASE/stdlib.js @@ -0,0 +1,17 @@ +/* Generated by tools/snapshot-library.py; local source snapshot. */ +window.REBASE.library = { + "origin": "chapter25/src/main/smp", + "files": { + "sys.smp": "\n// top-level default standard library import\n\nval adt = adt; // Abstract Data Types\nval ary = ary; // Array utilities\nval aryi64 = aryi64; // Variable sized array of i64\nval aryu8 = aryu8; // Variable sized array of u8\nval char = char; // Character utilities\nval io = io; // IO library\nval libc = libc; // libc FFI bindings\nval scan = scan; // A simple string parser\n", + "sys/adt/bitset.smp": "\n// A set of non-negative integers, represented one bit per value.\nstruct bitset {\n i64[] !_bits;\n\n new bitset = { ->\n _bits = new i64[1];\n };\n\n // Return 0 for missing, non-zero for true\n val get = { int bit ->\n if( (bit >> 6) >= _bits# ) return false;\n i64 mask = 1 << (bit & 63);\n return (_bits[bit >> 6] & mask);\n };\n\n val _grow = { int bit ->\n int x = bit >> 6;\n int len = _bits#;\n if( x < len ) return self;\n while( x >= len ) len *= 2;\n var bits = new i64[len];\n for( int i=0; i<_bits#; i++ )\n bits[i] = _bits[i];\n _bits = bits;\n return self;\n };\n\n // Set\n val set = { int bit ->\n i64 mask = 1 << (bit & 63);\n _grow(bit)._bits[bit >> 6] |= mask;\n return self;\n };\n\n // Test and set\n val tset = { int bit ->\n int idx = bit >> 6;\n i64 mask = 1 << (bit & 63);\n if( _grow(bit)._bits[idx] & mask )\n return true; // Already set\n _bits[idx] |= mask;\n return false; // Was false (and now set)\n };\n\n val clr = { int bit ->\n if( (bit >> 6) >= _bits# ) return self;\n i64 mask = 1 << (bit & 63);\n _bits[bit >> 6] &= (mask ^ -1);\n return self;\n };\n\n val clear = { ->\n for( int i=0; i<_bits#; i++ ) _bits[i] = 0;\n return self;\n };\n};\n", + "sys/adt.smp": "\n// Abstract data types.\nval bitset = bitset;\n", + "sys/ary.smp": "\n// Array utilities\n\n// Copy byte array contents. Copies the shorter of the buffers and len\nval copy = { u8[] dst, int doff, u8[~] src, int soff, int len ->\n if( len > dst# - doff ) len = dst# - doff;\n if( len > src# - soff ) len = src# - soff;\n for( int i=0; i0 for first non-matching byte. Returns <0 or >0 for\n// the larger array after that, or 0 if both arrays are fully equal.\nval cmp = { u8[~] src1, u32 off1, u8[~] src2, u32 off2, u32 len ->\n u32 len1 = len > src1# - off1 ? src1# - off1 : len;\n u32 len2 = len > src2# - off2 ? src2# - off2 : len;\n u32 max = len1 > len2 ? len2 : len1;\n for( int i=0; i\n buf = b;\n };\n\n // Grow as needed\n val _grow = { int len2 ->\n if( len+len2 < buf# ) return self;\n int newlen = buf# * 2;\n while( len+len2 >= newlen ) newlen *= 2;\n i64[] !buf2 = new i64[newlen];\n for( int i=0; i\n _grow(1).buf[len++] = c;\n self;\n };\n\n val get = { int index -> return buf[index]; };\n\n // Write the bracketed array-list form to aryu8.\n val str = { ->\n // TODO: clunky default constructor syntax\n var str = new aryu8().add('[');\n for( int i=0; i\n i64 tmp = buf[i];\n buf[i] = buf[j];\n buf[j] = tmp;\n self;\n };\n};\n\n\n\n// Parse a comma-separated list of numbers, wrapped with square brackets,\n// with optional whitespace e.g. \"[ -17, 0,99,12456789 ] \".\n// parseAryI64 & aryi64.str are bijections modulo whitespace.\n// Returns null if the parse failed, without giving a clue as to why.\nval parseAryI64 = { u8[~] str ->\n !scan !s = new scan(str);\n if( !s.match('[') ) return null;\n // Array of parsed results\n var nums = new aryi64(new i64[1]);\n\n // Parse a list of numbers\n if( s.match(']') ) // Handle the empty list\n return nums;\n\n // Parse number commas \"123, \" until something else\n while( s.x < s.buf# ) {\n nums.add(s.number());\n if( s.bad ) return null;\n if( !s.match(',') )\n break;\n };\n // Close the list\n if( !s.match(']') ) return null;\n s.skip();\n return s.x == s.buf# ? nums : null;\n};\n\nval copy = { i64[] dst, int doff, i64[~] src, int soff, int len ->\n for( int i=0; i buf = new u8[1]; };\n\n // Grow as needed\n val _grow = { int len2 ->\n if( len+len2 < buf# ) return self;\n int newlen = buf# * 2;\n while( len+len2 >= newlen ) newlen *= 2;\n u8[] !buf2 = new u8[newlen];\n ary.copy(buf2,0,buf,0,buf#);\n buf = buf2;\n self;\n };\n\n val clear = { -> len = 0; self; };\n\n // Add a character to aryu8\n val add = { u8 c ->\n _grow(1).buf[len++] = c;\n self;\n };\n\n // Add all of a plain array to the aryu8\n val addAry = { u8[~] xs ->\n _grow(xs#);\n ary.copy(buf,len,xs,0,xs#);\n len += xs#;\n self;\n };\n\n // Remove x bytes from the tail.\n val undo = { int x ->\n len = len >= x ? len-x : 0;\n self;\n };\n\n // Print ASCII number into aryu8\n val num = { i64 x ->\n if( !x ) { add('0'); return self; }\n if( x < 0 ) { add('-'); x = -x; }\n i64 ten = 1, log = 0;\n while( ten <= x ) { ten *= 10; log++; }\n for( int i=0; i\n i64 ptr = buf; // Cast buffer pointer to i64 for native C call\n libc.write(fd,ptr,len);\n };\n};\n\n\n// Parse one integer, ignore trailing data; returns 0 with an empty string.\n// If you want a more robust parsing, use the `scan` class\nval atoi = { u8[~] str ->\n int x = 0;\n while( x < str# && str[x] <= ' ' ) x++;\n if( x == str# ) return 0;\n bool neg = false;\n if( str[x]=='-' ) { neg=true; x++; }\n i64 n = 0;\n while( x < str# && '0' <= str[x] <= '9' )\n n = n*10 + str[x++]-'0';\n return neg ? -n : n;\n};\n\n// Zero-terminate string for libc strings. No error checking, just copies and\n// appends a zero.\n{ u8[~] -> u8[] } str0 = { u8[~] str ->\n u8[] !strz = new u8[str#+1];\n ary.copy(strz,0,str,0,str#);\n strz[str#] = '\\0';\n strz;\n};\n", + "sys/char.smp": "\nval toupper = { u8 c ->\n return c >= 'a' && c <= 'z' ? c - ('a' - 'A') : c;\n};\n\nval tolower = { u8 c ->\n return c >= 'A' && c <= 'Z' ? c + ('a' - 'A') : c;\n};\n", + "sys/io.smp": "\n// Simple I/O Library\n\n// Write byte array to stdout\nval p = { u8[~] str -> write(1,str); };\nval p_noInline = { u8[~] str -> write(1,str); };\n\n// Return fd contents as a u8[].\nval read = { i32 fd ->\n var buf = new u8[8*1024];\n i64 ptr = buf;\n int len = 0;\n while( true ) {\n i32 rez = libc.read(fd,ptr,buf#);\n if( rez > buf# ) libc._exit(libc.errno());\n len += rez;\n if( rez < buf# )\n break;\n libc._exit(-2); // Need to implement for more than 8K input\n }\n var out = new u8[len];\n ary.copy(out,0,buf,0,len);\n};\n\n// Write all of str to fd.\nval write = { i32 fd, u8[~] str ->\n i64 ptr = str; // Convert array pointer to a i64 for the native call\n libc.write(fd,ptr,str#);\n};\n\n// Write all of str to fd.\nval writeOff = { i32 fd, u8[~] str, u32 off, u32 len ->\n i64 ptr = str; // Convert array pointer to a i64 for the native call\n ptr += off; // Skip offset\n // Cap at available length\n if( len > str# - off ) len = str# - off;\n // Do the write\n libc.write(fd,ptr,len);\n};\n\n// Return stdin as a u8[].\nval stdin = { -> read(0); };\n\n// Create file for writing. Return fd, or -1 and errno has the error code\nval create = { u8[~] str ->\n i64 ptr = sys.aryu8.str0(str);\n i32 perms = 6*64 + 6*8 + 6; // 0666\n return libc.creat(ptr, perms);\n};\n\n// Open file for reading. Return fd, or -1 and errno has the error code\nval open = { u8[~] str ->\n i64 ptr = sys.aryu8.str0(str);\n return libc.open(ptr, sys.libc.O_RDONLY, 0);\n};\n\n// Close an open fd. Return 0, or -1 and errno has the error code\nval close = { i32 fd -> return libc.close(fd); };\n\n// Remove a file. Return 0, or -1 and errno has the error code\nval remove = { u8[~] str ->\n i64 ptr = sys.aryu8.str0(str);\n return libc.unlink(ptr);\n};\n", + "sys/libc.smp": "\n// libc bindings:\n// https://www.man7.org/linux/man-pages/man2/.2.html\n\n// The buffers are int-versions of zero-terminated strings.\n// int buf = aryu8.str0(\"some_file\");\n// buf mode perm-> fd\n{ i64 i32 i32 -> i32 } open = \"C\";\n// buf perm -> fd\n{ i64 i32 -> i32 } creat = \"C\";\n\n// fd buf len -> len\n{ i32 i64 u32 -> i32 } write = \"C\";\n// fd buf len -> len\n{ i32 i64 u32 -> i32 } read = \"C\";\n// fd -> err\n{ i32 -> i32 } close = \"C\";\n// path -> err\n{ i64 -> i32 } unlink = \"C\";\n\ni32 O_RDONLY = 0;\ni32 O_WRONLY = 1;\ni32 O_RDWR = 2;\ni32 O_CREAT = 512; // 02000 on x86_64-pc-cygwin\ni32 O_TRUNC = 1024; // 04000 on x86_64-pc-cygwin\n\ni32 STDIN = 0;\ni32 STDOUT = 1;\ni32 STDERR = 2;\n\n// status\n{ i32 -> i32 } _exit = \"C\";\n// errno is not an ordinary C data symbol; read it through the native runtime.\n{ i32 } simple_errno = \"C\";\nval errno = { -> simple_errno(); };\n// addr len prot flags fd off -> void*\n{ i64 i64 i32 i32 i32 i32 -> i64 } mmap = \"C\";\n// mmap flags\ni32 PROT_EXEC = 4;\ni32 PROT_READ = 1;\ni32 PROT_WRITE= 2;\ni32 PROT_NONE = 0;\ni32 MAP_PRIVATE = 2;\ni32 MAP_ANON = 32;\n", + "sys/scan.smp": "\n// Scanner; a simple string parser.\nstruct scan {\n int !x; // Cursor\n bool !bad; // True after a malformed token\n u8[~] buf; // Buffer to parse\n\n new scan = { u8[~] b -> buf = b; };\n\n // Skip whitespace\n val skip = { ->\n while( x < buf# && buf[x] <= ' ' )\n x++;\n return self;\n };\n\n // True if find required character, and skip it; else False.\n val match = { u8 c ->\n skip();\n if( x >= buf# ) return false;\n if( buf[x] != c ) return false;\n x++;\n return true;\n };\n\n // Parse a simple number\n val number = { ->\n skip();\n bool neg = match('-');\n if( x >= buf# || buf[x] < '0' || '9' < buf[x] ) {\n bad = true;\n return 0;\n }\n i64 n = 0;\n while( x < buf# && '0' <= buf[x] & buf[x] <= '9' )\n n = n*10 + (buf[x++] - '0');\n return neg ? -n : n;\n };\n};\n" + }, + "methods": "struct Counter {\n int n;\n val add = { int delta ->\n n += delta;\n return self;\n };\n val get = { -> return n; };\n};\n!Counter c = new Counter { n = arg; };\nc.add(3).add(4);\nreturn c.get();\n" +}; diff --git a/docs/2026_REBASE/tools/BackendDump.java b/docs/2026_REBASE/tools/BackendDump.java new file mode 100644 index 00000000..faac89a4 --- /dev/null +++ b/docs/2026_REBASE/tools/BackendDump.java @@ -0,0 +1,45 @@ +import com.seaofnodes.simple.codegen.CodeGen; +import com.seaofnodes.simple.node.*; +import java.nio.file.*; +import java.util.regex.Pattern; + +/** Run from the repo root with Chapter 21's built classes on the classpath. */ +public class BackendDump { + static String js(String s) { + return "\""+s.replace("\\","\\\\").replace("\"","\\\"") + .replace("\r", "").replace("\n","\\n")+"\""; + } + public static void main(String[] args) throws Exception { + Path deck=Path.of("docs/2026_REBASE"); + String source=Files.readString(deck.resolve("demos/backend.smp")); + CodeGen code=new CodeGen(source).parse().opto().typeCheck().loopTree() + .instSelect("x86_64_v2","SystemV"); + String selected=code.toString(); + // Every row from the whole graph, in printer order. Show concrete Java + // classes and every input slot; omit types and redundant use lists. + StringBuilder compact=new StringBuilder("id node inputs\n"); + var rows=Pattern.compile("(?m)^\\s*(\\d+) ").matcher(selected); + int count=0; + while(rows.find()) { + Node n=code.f(Integer.parseInt(rows.group(1))); + String name=n.getClass().getSimpleName(); + if(n instanceof ParmNode || n instanceof CProjNode) name+=":"+n.label(); + compact.append(String.format("%2d %-16s",n._nid,name)); + for(int i=0;i "#d3e7f5"; + case "TypeFloat" -> "#c7eee9"; + case "TypePtr", "TypeMemPtr" -> "#cce4d6"; + case "TypeFunPtr" -> "#dfd0ef"; + case "TypeMem" -> "#a9c9e5"; + case "TypeStruct", "Field" -> "#e0ebc8"; + case "TypeTuple" -> "#f2d7e4"; + case "TypeRPC" -> "#f4d4b5"; + default -> name.startsWith("TypeConAry") ? "#d9d5cc" : "#faedce"; + }; + } + public static void main(String[] args) throws Exception { + var types=new ArrayList<>(new LinkedHashSet<>(Arrays.asList(Type.gather()))); + int size=types.size(); + boolean[][] above=new boolean[size][size]; + for(int i=0;i n").append(j).append(";\n");edges++;} + } + dot.append("}\n"); + Files.writeString(Path.of("docs/2026_REBASE/assets/rich-lattice.gv"),dot); + System.out.println(size+" representative types; "+edges+" order edges (transitively reduced)."); + } +} diff --git a/docs/2026_REBASE/tools/snapshot-library.py b/docs/2026_REBASE/tools/snapshot-library.py new file mode 100644 index 00000000..dee09d2f --- /dev/null +++ b/docs/2026_REBASE/tools/snapshot-library.py @@ -0,0 +1,16 @@ +"""Bundle the current Chapter 25 stdlib and methods example for offline browsing.""" +from pathlib import Path +import json + +deck = Path(__file__).resolve().parents[1] +repo = deck.parents[1] +source = repo / "chapter25/src/main/smp" +paths = [source / "sys.smp", *sorted((source / "sys").rglob("*.smp"))] +files = {path.relative_to(source).as_posix(): path.read_text(encoding="utf-8") for path in paths} +bundle = {"origin": "chapter25/src/main/smp", "files": files, + "methods": (deck / "demos/methods.smp").read_text(encoding="utf-8")} +(deck / "stdlib.js").write_text( + "/* Generated by tools/snapshot-library.py; local source snapshot. */\n" + "window.REBASE.library = " + json.dumps(bundle, ensure_ascii=False, indent=2) + ";\n", + encoding="utf-8", newline="\n") +print(f"Bundled {len(files)} standard-library files and the methods example.") diff --git a/docs/chapter-backports.md b/docs/chapter-backports.md index 67920ba5..a8be1e24 100644 --- a/docs/chapter-backports.md +++ b/docs/chapter-backports.md @@ -642,6 +642,22 @@ The top-level runner accepts explicit chapter lists, e.g. ## Validation record +- **Unused parser memory aggregates, Chapters 11-24 (2026-10-03).** Release + temporary prior-memory keeps with dead-node cleanup after publishing the new + memory value. Flattening a MemMerge could remove its last real use while the + parser kept it alive; plain `unkeep()` then left it unused and off the worklist. + The Chapter 17b presentation alias example's MemMerge#18 now disappears. + Its partial allocation input (#14) remains: null default means uncovered + aliases, so it cannot be replaced with whole memory just because its covered + slices coincide. Chapter 25's different construction sites were not changed. + Make builds passed in all affected chapters; complete suites passed in 11 + (163 tests) and 12 (177). Existing Chapter10/11 tests passed in 13-24, plus + Chapter15/16 tests where present and Chapter17a/17b tests in 17b. Updated + earlier graph-shape expectations for the newly eliminated initializing Store + and a different equivalent Phi name. Direct graph checks and evaluator runs + passed for both presentation memory examples; their JSON/SVG captures were + regenerated. Logs: `build/rebase-talk/memory-cleanup/`. + - **Chapter 25 historical String fixtures (2026-10-02).** Added an explicit constructor initializing the required non-null `cs` field in `Chapter21Test-testStringExport.smp`, `Chapter21AllocTest-testString.smp`, and diff --git a/graph/README.md b/graph/README.md index d52ecfeb..8577f509 100644 --- a/graph/README.md +++ b/graph/README.md @@ -28,7 +28,7 @@ python -m http.server 8000 --bind 127.0.0.1 --directory graph/web Then launch Java with `-Dsimple.graph.url=http://127.0.0.1:8000/index.html`. The compiler WebSocket still uses port 12345; run one viewer session at a time. -The initial program compiles on connection. For another program, click **Compile** +The viewer starts idle. Enter a program and click **Compile** or press **Ctrl+Enter** (**Cmd+Enter** on macOS). Use the arrows to step through frames (Left/Right arrow keys perform the same steps, including animation stages), the first/last buttons to jump to either end, or enter a frame number diff --git a/graph/test_browser.py b/graph/test_browser.py index aa1015e1..b95e4555 100644 --- a/graph/test_browser.py +++ b/graph/test_browser.py @@ -55,6 +55,9 @@ def check(chapter, browser_name): return raise AssertionError("Peephole did not reach a stable frame") page.goto(url) + page.wait_for_function('connection === "Connected" && rendererReady') + assert page.evaluate('!compiling && !done && frames.length === 0') + page.locator("#compile").click() page.wait_for_function("done && current === 0 && !rendering", timeout=15000) assert page.locator("#graph svg g.node").count() > 0 assert page.locator("#doPrev").is_disabled() diff --git a/graph/web/viewer.js b/graph/web/viewer.js index 6309deae..4412817e 100644 --- a/graph/web/viewer.js +++ b/graph/web/viewer.js @@ -71,7 +71,7 @@ function updateUI() { status.textContent = failure || (connection !== "Connected" ? connection : !rendererReady ? "Connected; initializing graph renderer..." : busy ? busy : compiling ? "Compiling... " + frames.length + " frames received" : - done ? frames.length + " frames ready" : "Connected"); + done ? frames.length + " frames ready" : "Ready. Enter a program and click Compile."); const at = wanted >= 0 ? wanted : current; if (document.activeElement !== frameNo) frameNo.value = String(at + 1); frameNo.max = scrub.max = String(Math.max(1, frames.length)); @@ -365,7 +365,7 @@ try { socket.onmessage = event => { const message = event.data; if (message === "!") { - get_program(); + updateUI(); } else if (message === "#") { done = true; compiling = false; -- cgit v1.2.3