@@ -1548,6 +1548,25 @@ let .lookup(tree: PBTree<k,v>, key: k, default: v): v = (
15481548 }
15491549);
15501550
1551+ # O(log N) Persistent Lookup
1552+ let .has-key(tree: PBTree<k,v>, key: k): Bool = (
1553+ match tree {
1554+ PBLeaf {} => false;
1555+ PBNode1 { k11=k1, v11=v1, left=left, right=right } => (
1556+ if key == k11 then true
1557+ else if key < k11 then left.has-key(key)
1558+ else right.has-key(key)
1559+ );
1560+ PBNode2 { k12=k1, v12=v1, k22=k2, v22=v2, left=left, mid=mid, right=right } => (
1561+ if key == k12 then true
1562+ else if key == k22 then true
1563+ else if key < k12 then left.has-key(key)
1564+ else if key < k22 then mid.has-key(key)
1565+ else right.has-key(key)
1566+ );
1567+ }
1568+ );
1569+
15511570# --- Internal Insert Mechanism ---
15521571
15531572# We need an intermediary state type to handle nodes splitting as they bubble up
@@ -5343,10 +5362,12 @@ let $"||"(lctx: Maybe<TypeContext>, rctx: Maybe<TypeContext>): Maybe<TypeContext
53435362
53445363let .phi-append(tctx-primary: TypeContext?, tctx-secondary: TypeContext?): TypeContext? = (
53455364 tctx-primary.with-pctx( tctx-primary.get-or(mk-tctx()).pctx.phi-append(tctx-secondary.get-or(mk-tctx()).pctx,false) )
5365+ #tctx-primary.with-pctx( tctx-primary.get-or(mk-tctx()).pctx.phi-append(tctx-secondary.get-or(mk-tctx()).pctx,false).prune-moved )
53465366);
53475367
53485368let .phi-append-dead-on-arrival(tctx-primary: TypeContext?, tctx-secondary: TypeContext?): TypeContext? = (
53495369 tctx-primary.with-pctx( tctx-primary.get-or(mk-tctx()).pctx.phi-append(tctx-secondary.get-or(mk-tctx()).pctx,true) )
5370+ # tctx-primary.with-pctx( tctx-primary.get-or(mk-tctx()).pctx.phi-append(tctx-secondary.get-or(mk-tctx()).pctx,true).prune-moved )
53505371);
53515372
53525373let .phi-append(tctx-primary: PBTree<U64,PhiContextRow>, tctx-secondary: PBTree<U64,PhiContextRow>, dead-on-arrival: Bool): PBTree<U64,PhiContextRow> = (
@@ -5492,6 +5513,77 @@ let .phi-move(tctx: TypeContext?, tt: Type, blame: AST): TypeContext? = (
54925513 tctx
54935514);
54945515
5516+ let .prune-moved(tctx: TypeContext?): TypeContext? = (
5517+ let inner-tctx = tctx.get-or(mk-tctx());
5518+ (let moved, let live) = inner-tctx.pctx.find-moved(mk-set(type(U64)), mk-set(type(U64)));
5519+ inner-tctx.pctx = inner-tctx.pctx.prune-moved(mk-pbtree(type(U64),type(PhiContextRow)), moved);
5520+ Some(inner-tctx)
5521+ );
5522+
5523+ let .prune-moved(pctx: PBTree<U64,PhiContextRow>): PBTree<U64,PhiContextRow> = (
5524+ (let moved, let live) = pctx.find-moved(mk-set(type(U64)), mk-set(type(U64)));
5525+ pctx.prune-moved(mk-pbtree(type(U64),type(PhiContextRow)), moved);
5526+ );
5527+
5528+ let .prune-moved(from: PBTree<U64,PhiContextRow>, to: PBTree<U64,PhiContextRow>, moved: Set<U64>): PBTree<U64,PhiContextRow> = (
5529+ match from {
5530+ PBLeaf{} => to;
5531+ PBNode1{ k11=k1, v11=v1, left=left, right=right } => (
5532+ if moved.has(k11) then ();
5533+ else if not to.has-key(k11) then to = to.bind(k11, v11);
5534+ to = left.prune-moved(to, moved);
5535+ to = right.prune-moved(to, moved);
5536+ to
5537+ );
5538+ PBNode2{ k12=k1, v12=v1, k22=k2, v22=v2, left=left, mid=mid, right=right } => (
5539+ if moved.has(k12) then ();
5540+ else if not to.has-key(k12) then to = to.bind(k12, v12);
5541+ if moved.has(k22) then ();
5542+ else if not to.has-key(k22) then to = to.bind(k22, v22);
5543+ to = left.prune-moved(to, moved);
5544+ to = mid.prune-moved(to, moved);
5545+ to = right.prune-moved(to, moved);
5546+ to
5547+ );
5548+ }
5549+ );
5550+
5551+ let .find-moved(tctx: PBTree<U64,PhiContextRow>, moved: Set<U64>, live: Set<U64>): (Set<U64>, Set<U64>) = (
5552+ match tctx {
5553+ PBLeaf{} => (moved, live);
5554+ PBNode1{ k11=k1, v11=v1, left=left, right=right } => (
5555+ if moved.has(k11) then ();
5556+ else if not live.has(k11) {
5557+ if v11.phi-tt-or-zero.is-linear-live
5558+ then live = live.bind(k11)
5559+ else moved = moved.bind(k11)
5560+ };
5561+ (moved, live) = left.find-moved(moved, live);
5562+ (moved, live) = right.find-moved(moved, live);
5563+ (moved, live)
5564+ );
5565+ PBNode2{ k12=k1, v12=v1, k22=k2, v22=v2, left=left, mid=mid, right=right } => (
5566+ if moved.has(k12) then ();
5567+ else if not live.has(k12) {
5568+ if v12.phi-tt-or-zero.is-linear-live
5569+ then live = live.bind(k12)
5570+ else moved = moved.bind(k12)
5571+ };
5572+ if moved.has(k22) then ();
5573+ else if not live.has(k22) {
5574+ if v22.phi-tt-or-zero.is-linear-live
5575+ then live = live.bind(k22)
5576+ else moved = moved.bind(k22)
5577+ };
5578+ (moved, live) = left.find-moved(moved, live);
5579+ (moved, live) = mid.find-moved(moved, live);
5580+ (moved, live) = right.find-moved(moved, live);
5581+ (moved, live)
5582+ );
5583+ }
5584+ );
5585+
5586+
54955587let .substitute(tctx: TypeContext?, tt: Vector<Type>): Vector<Type> = (
54965588 let next = mk-vector(type(Type));
54975589 for t in tt {
@@ -5752,7 +5844,7 @@ let .with-phi(tctx: TypeContext?, tt: Type, blame: AST): Type = (
57525844 tt = t2(c"Cons", tctx.with-phi(ct.l1,blame), tctx.with-phi(ct.l2,blame));
57535845 } else if tt.is-t(c"Phi::Id",1) {
57545846 let phi-state = tctx.lookup-phi(tt.slot(c"Phi::Id",1).l1.simple-id).phi-tt-or-zero;
5755- if not(non-zero(phi-state)) then fail("Could not find phi state \{tt} at \{blame.location}\n") ;
5847+ if not(non-zero(phi-state)) then phi- state = type-release-phi-moved ;
57565848 if tt.is-t(c"Phi::State",1) and tt.slot(c"Phi::State",1).l1 != phi-state
57575849 then tt = tt.without-slot(c"Phi::State",1) && t1(c"Phi::State", phi-state);
57585850 else if not tt.is-t(c"Phi::State",1)
@@ -6085,6 +6177,9 @@ let type-tail-position = t0(c"TailPosition");
60856177# new allocations = 0 (constant)
60866178let type-lazy = tv(c"lazy");
60876179
6180+ # new allocations = 0 (constant)
6181+ let type-release-phi-moved = t1(c"MustRelease::ToRelease",t1(c"Linear",t0(c"Phi::Moved")));
6182+
60886183# new allocations = 0 (constant)
60896184let type-type-string = t1(c"Type",t0(c"String"));
60906185
@@ -8115,7 +8210,7 @@ let maybe-retain(tctx: TypeContext?, term: AST): (TypeContext?, AST) = (
81158210let worst-phi-length = 0_sz;
81168211
81178212let phi-merge(tctx-globals: TypeContext?, tctx-primary: PBTree<U64,PhiContextRow>, tctx-secondary: PBTree<U64,PhiContextRow>, blame: AST): PBTree<U64,PhiContextRow> = (
8118- phi-merge-inner(tctx-globals, tctx-primary, tctx-secondary, blame, mk-vector(type(U64))).second
8213+ phi-merge-inner(tctx-globals, tctx-primary, tctx-secondary, blame, mk-vector(type(U64))).second.prune-moved
81198214);
81208215
81218216
@@ -8303,7 +8398,7 @@ let release-locals(tctx-before: TypeContext?, tctx-after: TypeContext?, term: AS
83038398 tctx-after.with-pctx(tctx-after-pctx);
83048399 tctx-before = tctx-before.phi-append(tctx-after);
83058400 if not(release-self) then (tctx-before, _) = tctx-before.resurrect(typeof-term(term), term);
8306- (tctx-before, term)
8401+ (tctx-before.prune-moved , term)
83078402);
83088403
83098404let specialize(key: CString, unify-ctx: TypeContext?, result-type: Type, term: AST): Nil = (
@@ -9263,6 +9358,7 @@ import SRC/tctx-phi-initialize.lsts;
92639358import SRC/tctx-misc-globals.lsts;
92649359import SRC/typecheck-infer-tctx.lsts;
92659360import SRC/tctx-move-diff.lsts;
9361+ import SRC/tctx-prune-moved.lsts;
92669362
92679363import SRC/unit-util.lsts;
92689364
0 commit comments