--- /dev/null
+package org.simantics.scl.compiler.internal.elaboration.subsumption2;
+
+import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
+import org.simantics.scl.compiler.internal.types.effects.EffectIdMap;
+import org.simantics.scl.compiler.types.TMetaVar;
+import org.simantics.scl.compiler.types.exceptions.UnificationException;
+import org.simantics.scl.compiler.types.util.Polarity;
+
+public class SubsumptionGraph {
+ public static final int REMOVED = Integer.MAX_VALUE-1;
+
+ public static class LowerBoundSource {
+ public final long location;
+ public final int lower;
+ public final LowerBoundSource next;
+ public LowerBoundSource(long location, int lower, LowerBoundSource next) {
+ this.location = location;
+ this.lower = lower;
+ this.next = next;
+ }
+ }
+
+ public static abstract class Node {
+ int lowerBound = EffectIdMap.MIN;
+ int upperBound = EffectIdMap.MAX;
+ Sub lower;
+ LowerBoundSource lowerBoundSource;
+
+ public void addLowerBoundSource(long location, int lower) {
+ lowerBoundSource = new LowerBoundSource(location, lower, lowerBoundSource);
+ }
+ }
+
+ public static class VarNode extends Node {
+ TMetaVar origin;
+ Sub upper;
+ PartOfUnion partOf;
+ int index;
+
+ public VarNode(TMetaVar origin) {
+ this.origin = origin;
+ }
+
+ public Polarity getPolarity() {
+ return origin.getPolarity();
+ }
+
+ public void replaceBy(VarNode replacement) {
+ try {
+ origin.setRef(replacement.origin);
+ } catch(UnificationException e) {
+ throw new InternalCompilerError(e);
+ }
+ {
+ Sub last = null;
+ for(Sub cur=upper;cur!=null;cur=cur.aNext) {
+ cur.a = replacement;
+ last = cur;
+ }
+ if(last != null) {
+ last.aNext = replacement.upper;
+ if(last.aNext != null)
+ last.aNext.aPrev = last;
+ replacement.upper = upper;
+ }
+
+ last = null;
+ for(Sub cur=lower;cur!=null;cur=cur.bNext) {
+ cur.b = replacement;
+ last = cur;
+ }
+ if(last != null) {
+ last.bNext = replacement.lower;
+ if(last.bNext != null)
+ last.bNext.bPrev = last;
+ replacement.lower = lower;
+ }
+ }
+ {
+ PartOfUnion last = null;
+ for(PartOfUnion cur=partOf;cur!=null;cur=cur.bNext) {
+ cur.a = replacement;
+ last = cur;
+ }
+ if(last != null) {
+ last.aNext = replacement.partOf;
+ if(last.aNext != null)
+ last.aNext.bPrev = last;
+ replacement.partOf = partOf;
+ }
+ }
+ index = REMOVED;
+ }
+
+ public void removeConstantNode(EffectIdMap effectIds, int constValue) {
+ try {
+ origin.setRef(effectIds.toType(constValue));
+ } catch (UnificationException e) {
+ throw new InternalCompilerError(e);
+ }
+ for(Sub cur=lower;cur!=null;cur=cur.bNext)
+ cur.detachA();
+ for(Sub cur=upper;cur!=null;cur=cur.aNext)
+ cur.detachB();
+ for(PartOfUnion cur=partOf;cur!=null;cur=cur.aNext) {
+ cur.detachB();
+ cur.b.constPart |= constValue;
+ }
+ index = REMOVED;
+ }
+ }
+
+ public static class UnionNode extends Node {
+ long location;
+ PartOfUnion parts;
+ int constPart;
+
+ public UnionNode(long location, int constPart) {
+ this.location = location;
+ this.constPart = constPart;
+ this.lowerBound = constPart;
+ }
+
+ public void remove() {
+ for(Sub cur=lower;cur!=null;cur=cur.bNext)
+ cur.detachA();
+ for(PartOfUnion cur=parts;cur!=null;cur=cur.bNext)
+ cur.detachA();
+ constPart = REMOVED;
+ }
+ }
+
+ public static class Sub {
+ VarNode a;
+ Node b;
+ Sub aNext;
+ Sub aPrev;
+ Sub bNext;
+ Sub bPrev;
+
+ public Sub(VarNode a, Node b) {
+ this.a = a;
+ this.b = b;
+
+ aNext = a.upper;
+ if(aNext != null)
+ aNext.aPrev = this;
+ a.upper = this;
+
+ bNext = b.lower;
+ if(bNext != null)
+ bNext.bPrev = this;
+ b.lower = this;
+ }
+
+ public void detachA() {
+ if(aNext != null)
+ aNext.aPrev = aPrev;
+ if(aPrev != null)
+ aPrev.aNext = aNext;
+ else
+ a.upper = aNext;
+ }
+
+ public void detachB() {
+ if(bNext != null)
+ bNext.bPrev = bPrev;
+ if(bPrev != null)
+ bPrev.bNext = bNext;
+ else
+ b.lower = bNext;
+ }
+
+ public void remove() {
+ detachA();
+ detachB();
+ }
+ }
+
+ public static class PartOfUnion {
+ VarNode a;
+ UnionNode b;
+ PartOfUnion aNext;
+ PartOfUnion aPrev;
+ PartOfUnion bNext;
+ PartOfUnion bPrev;
+
+ public PartOfUnion(VarNode a, UnionNode b) {
+ this.a = a;
+ this.b = b;
+
+ aNext = a.partOf;
+ if(aNext != null)
+ aNext.aPrev = this;
+ a.partOf = this;
+
+ bNext = b.parts;
+ if(bNext != null)
+ bNext.bPrev = this;
+ b.parts = this;
+ }
+
+ public void detachA() {
+ if(aNext != null)
+ aNext.aPrev = aPrev;
+ if(aPrev != null)
+ aPrev.aNext = aNext;
+ else
+ a.partOf = aNext;
+ }
+
+ public void detachB() {
+ if(bNext != null)
+ bNext.bPrev = bPrev;
+ if(bPrev != null)
+ bPrev.bNext = bNext;
+ else
+ b.parts = bNext;
+ }
+
+ public void remove() {
+ detachA();
+ detachB();
+ }
+
+ }
+}