]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/elaboration/subsumption/SubSolver.java
Fixed all line endings of the repository
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / internal / elaboration / subsumption / SubSolver.java
index f9b5efc3bd3eb7eb3e68dc148f9f4d0496648a3f..40f8fdf6ada254b483a05e5f82666aac2af98a6d 100644 (file)
-package org.simantics.scl.compiler.internal.elaboration.subsumption;\r
-\r
-import java.util.ArrayDeque;\r
-import java.util.ArrayList;\r
-\r
-import org.simantics.scl.compiler.errors.ErrorLog;\r
-import org.simantics.scl.compiler.errors.Locations;\r
-import org.simantics.scl.compiler.internal.types.effects.EffectIdMap;\r
-import org.simantics.scl.compiler.types.TMetaVar;\r
-import org.simantics.scl.compiler.types.TUnion;\r
-import org.simantics.scl.compiler.types.Type;\r
-import org.simantics.scl.compiler.types.Types;\r
-import org.simantics.scl.compiler.types.util.Polarity;\r
-import org.simantics.scl.compiler.types.util.TypeUnparsingContext;\r
-\r
-import gnu.trove.map.hash.THashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-\r
-public class SubSolver {\r
-\r
-    public static final boolean DEBUG = false;\r
-    \r
-    long globalLoc;\r
-    ErrorLog errorLog;\r
-    ArrayList<Subsumption> subsumptions;\r
-    ArrayList<Type> potentialSingletonEffects;\r
-    EffectIdMap effectIds = new EffectIdMap();\r
-    THashMap<TMetaVar,Var> vars = new THashMap<TMetaVar,Var>();\r
-    ArrayDeque<Var> dirtyQueue = new ArrayDeque<Var>();\r
-    \r
-    TypeUnparsingContext tuc = new TypeUnparsingContext();\r
-    \r
-    public SubSolver(ErrorLog errorLog, ArrayList<Subsumption> subsumptions,\r
-            ArrayList<Type> potentialSingletonEffects,\r
-            long globalLoc) {\r
-        this.errorLog = errorLog;\r
-        this.subsumptions = subsumptions;\r
-        this.potentialSingletonEffects = potentialSingletonEffects;\r
-        this.globalLoc = globalLoc;\r
-        \r
-        //for(Subsumption sub : subsumptions)\r
-        //    System.out.println("[" + sub.a.toString(tuc) + " < " + sub.b.toString(tuc) + "]");\r
-    }    \r
-    \r
-    public void solve() {\r
-        //printSubsumptions();\r
-        createVar();\r
-        //print();\r
-        reduceChains();\r
-        propagateUpperBounds();\r
-        checkLowerBounds();\r
-        //errorFromUnsolvedEquations();\r
-        //System.out.println("--");\r
-        //print();\r
-    }\r
-    \r
-    private void markAllDirty() {\r
-        for(Var v : vars.values())\r
-            v.markDirty();\r
-    }\r
-    \r
-    private Var getOrCreateVar(TMetaVar mv) {\r
-        Var var = vars.get(mv);\r
-        if(var == null) {\r
-            var = new Var(mv, mv.toString(tuc).substring(1), this);\r
-            vars.put(mv, var);\r
-        }\r
-        return var;\r
-    }\r
-\r
-    private void addVar(Type t) {\r
-        t = Types.canonical(t);\r
-        if(t instanceof TMetaVar)\r
-            getOrCreateVar((TMetaVar)t);\r
-        else if(t instanceof TUnion)\r
-            for(Type c : ((TUnion)t).effects)\r
-                addVar(c);\r
-    }\r
-\r
-    ArrayList<TMetaVar> aVars = new ArrayList<TMetaVar>();\r
-    \r
-    private void addSubsumption(long loc, Type a, Type b) {\r
-        int aCons = effectIds.toId(a, aVars);\r
-        if(!aVars.isEmpty()) {\r
-            for(TMetaVar var : aVars)\r
-                getOrCreateVar((TMetaVar)var).addUpperBound(toVUnion(b));\r
-            aVars.clear();\r
-        }        \r
-        if(aCons != 0) {\r
-            VUnion u = toVUnion(b);\r
-            if(u.vars.isEmpty()) {\r
-                testSubsumption(loc, aCons, u.con);\r
-            }\r
-            else\r
-                u.makeLowerBound(aCons);\r
-        }\r
-    }\r
-\r
-    ArrayList<TMetaVar> bVars = new ArrayList<TMetaVar>();\r
-    \r
-    private VUnion toVUnion(Type a) {\r
-        int cons = effectIds.toId(a, bVars);\r
-        ArrayList<Var> vars = new ArrayList<Var>(bVars.size());\r
-        for(TMetaVar v : bVars)\r
-            vars.add(getOrCreateVar(v));\r
-        bVars.clear();\r
-        return new VUnion(cons, vars);\r
-    }\r
-\r
-    private void createVar() {\r
-        for(Subsumption sub : subsumptions)\r
-            addSubsumption(sub.loc, sub.a, sub.b);\r
-        for(Type t : potentialSingletonEffects)\r
-            addVar(t);\r
-    }\r
-    \r
-    private void reduceChains() {\r
-        markAllDirty();\r
-        while(true) {\r
-            Var v = dirtyQueue.poll();\r
-            if(v == null)\r
-                break;\r
-            \r
-            reduceChains(v);\r
-            v.dirty = false;\r
-        }\r
-    }\r
-    \r
-    private void reduceChains(Var v) {\r
-        if(v.constLowerBound == v.constUpperBound) {\r
-            v.replaceWith(v.constLowerBound);\r
-            return;\r
-        }\r
-        Polarity p = v.original.getPolarity();\r
-        if(!p.isNegative() && v.complexLowerBounds.isEmpty()) {\r
-            if(v.simpleLowerBounds.isEmpty()) {\r
-                if((v.constLowerBound&v.constUpperBound) != v.constLowerBound)\r
-                    errorLog.log(globalLoc, "Subsumption failed.");\r
-                v.replaceWith(v.constLowerBound);\r
-                return;\r
-            }\r
-            else if(v.simpleLowerBounds.size() == 1 && v.constLowerBound == 0) {\r
-                v.replaceDownwards(v.simpleLowerBounds.get(0));\r
-                return;\r
-            }\r
-        }\r
-        if(p == Polarity.NEGATIVE && v.complexUpperBounds.isEmpty()) {\r
-            if(v.simpleUpperBounds.isEmpty()) {\r
-                if((v.constLowerBound&v.constUpperBound) != v.constLowerBound)\r
-                    errorLog.log(globalLoc, "Subsumption failed.");\r
-                v.replaceWith(v.constUpperBound);\r
-                return;\r
-            }\r
-            else if(v.simpleUpperBounds.size() == 1 && v.constUpperBound == EffectIdMap.MAX) {\r
-                v.replaceUpwards(v.simpleUpperBounds.get(0));\r
-                return;\r
-            }\r
-        }\r
-    }\r
-    \r
-    private void propagateUpperBounds() {\r
-        markAllDirty();        \r
-        while(true) {\r
-            Var v = dirtyQueue.poll();\r
-            if(v == null)\r
-                break;\r
-            \r
-            int upperApprox = v.constUpperBound;\r
-            for(Var u : v.simpleUpperBounds)\r
-                upperApprox &= u.upperApprox;\r
-            for(VUnion u : v.complexUpperBounds)\r
-                upperApprox &= u.getUpperApprox();\r
-            \r
-            if(upperApprox != v.upperApprox) {\r
-                v.upperApprox = upperApprox;\r
-                for(Var u : v.simpleLowerBounds)\r
-                    u.markDirty();\r
-                for(VUnion u : v.complexLowerBounds)\r
-                    if(u.low != null)\r
-                        u.low.markDirty();\r
-            }   \r
-            \r
-            v.dirty = false;\r
-        }\r
-    }\r
-    \r
-    private void checkLowerBounds() {\r
-        THashSet<VUnion> lowerBounds = new THashSet<VUnion>(); \r
-        for(Var v : vars.values()) {\r
-            if((v.constLowerBound & v.upperApprox) != v.constLowerBound)\r
-                testSubsumption(globalLoc, v.constLowerBound, v.upperApprox);\r
-            for(VUnion u : v.complexLowerBounds)\r
-                if(u.low == null)\r
-                    lowerBounds.add(u);\r
-        }\r
-        for(VUnion u : lowerBounds)\r
-            if(u.getUpperApprox() != EffectIdMap.MAX)\r
-                errorLog.log(globalLoc, "Subsumption failed.");\r
-    }\r
-\r
-    private void errorFromUnsolvedEquations() {\r
-        for(Var v : vars.values()) {\r
-            if(!v.isFree()) {\r
-                errorLog.log(globalLoc, "Couldn't simplify all effect subsumptions away. " +\r
-                               "The current compiler cannot handle this situation. Try adding more type annotations.");\r
-                break;\r
-            }\r
-        }\r
-    }\r
-    \r
-    private void print() {\r
-        for(Var v : vars.values()) {\r
-            System.out.println(v.name + \r
-                    ", " + v.original.getPolarity() + \r
-                    (v.simpleLowerBounds.isEmpty() ? "" : ", simpleLowerRefs: " + v.simpleLowerBounds.size()) +  \r
-                    (v.complexLowerBounds.isEmpty() ? "" : ", complexLowerRefs: " + v.complexLowerBounds.size()) +\r
-                    ", " + v.original.getKind());\r
-            if(v.constLowerBound != EffectIdMap.MIN)\r
-                System.out.println("    > " + v.constLowerBound);\r
-            if(v.constUpperBound != EffectIdMap.MAX)\r
-                System.out.println("    < " + v.constUpperBound);\r
-            for(Var u : v.simpleUpperBounds)\r
-                System.out.println("    < " + u.name);\r
-            for(VUnion u : v.complexUpperBounds)\r
-                System.out.println("    << " + u);\r
-        }\r
-    }\r
-    \r
-    private void printSubsumptions() {\r
-        for(Subsumption sub : subsumptions)\r
-            System.out.println("[" + sub.a.toString(tuc) + " < " + sub.b.toString(tuc) + " : " + \r
-                    Locations.beginOf(sub.loc) + "," + Locations.endOf(sub.loc) + "]");\r
-    }\r
-\r
-    private void testSubsumption(long location, int a, int b) {\r
-        int extraEffects = a & (~b);\r
-        if(extraEffects != 0)\r
-            subsumptionFailed(location, extraEffects);\r
-    }\r
-    \r
-    private void subsumptionFailed(long location , int effects) {\r
-        errorLog.log(location, "Side-effect " + effectIds.toType(effects) + " is forbidden here.");\r
-    }\r
-}\r
+package org.simantics.scl.compiler.internal.elaboration.subsumption;
+
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+
+import org.simantics.scl.compiler.errors.ErrorLog;
+import org.simantics.scl.compiler.errors.Locations;
+import org.simantics.scl.compiler.internal.types.effects.EffectIdMap;
+import org.simantics.scl.compiler.types.TMetaVar;
+import org.simantics.scl.compiler.types.TUnion;
+import org.simantics.scl.compiler.types.Type;
+import org.simantics.scl.compiler.types.Types;
+import org.simantics.scl.compiler.types.util.Polarity;
+import org.simantics.scl.compiler.types.util.TypeUnparsingContext;
+
+import gnu.trove.map.hash.THashMap;
+import gnu.trove.set.hash.THashSet;
+
+public class SubSolver {
+
+    public static final boolean DEBUG = false;
+    
+    long globalLoc;
+    ErrorLog errorLog;
+    ArrayList<Subsumption> subsumptions;
+    ArrayList<Type> potentialSingletonEffects;
+    EffectIdMap effectIds = new EffectIdMap();
+    THashMap<TMetaVar,Var> vars = new THashMap<TMetaVar,Var>();
+    ArrayDeque<Var> dirtyQueue = new ArrayDeque<Var>();
+    
+    TypeUnparsingContext tuc = new TypeUnparsingContext();
+    
+    public SubSolver(ErrorLog errorLog, ArrayList<Subsumption> subsumptions,
+            ArrayList<Type> potentialSingletonEffects,
+            long globalLoc) {
+        this.errorLog = errorLog;
+        this.subsumptions = subsumptions;
+        this.potentialSingletonEffects = potentialSingletonEffects;
+        this.globalLoc = globalLoc;
+        
+        //for(Subsumption sub : subsumptions)
+        //    System.out.println("[" + sub.a.toString(tuc) + " < " + sub.b.toString(tuc) + "]");
+    }    
+    
+    public void solve() {
+        //printSubsumptions();
+        createVar();
+        //print();
+        reduceChains();
+        propagateUpperBounds();
+        checkLowerBounds();
+        //errorFromUnsolvedEquations();
+        //System.out.println("--");
+        //print();
+    }
+    
+    private void markAllDirty() {
+        for(Var v : vars.values())
+            v.markDirty();
+    }
+    
+    private Var getOrCreateVar(TMetaVar mv) {
+        Var var = vars.get(mv);
+        if(var == null) {
+            var = new Var(mv, mv.toString(tuc).substring(1), this);
+            vars.put(mv, var);
+        }
+        return var;
+    }
+
+    private void addVar(Type t) {
+        t = Types.canonical(t);
+        if(t instanceof TMetaVar)
+            getOrCreateVar((TMetaVar)t);
+        else if(t instanceof TUnion)
+            for(Type c : ((TUnion)t).effects)
+                addVar(c);
+    }
+
+    ArrayList<TMetaVar> aVars = new ArrayList<TMetaVar>();
+    
+    private void addSubsumption(long loc, Type a, Type b) {
+        int aCons = effectIds.toId(a, aVars);
+        if(!aVars.isEmpty()) {
+            for(TMetaVar var : aVars)
+                getOrCreateVar((TMetaVar)var).addUpperBound(toVUnion(b));
+            aVars.clear();
+        }        
+        if(aCons != 0) {
+            VUnion u = toVUnion(b);
+            if(u.vars.isEmpty()) {
+                testSubsumption(loc, aCons, u.con);
+            }
+            else
+                u.makeLowerBound(aCons);
+        }
+    }
+
+    ArrayList<TMetaVar> bVars = new ArrayList<TMetaVar>();
+    
+    private VUnion toVUnion(Type a) {
+        int cons = effectIds.toId(a, bVars);
+        ArrayList<Var> vars = new ArrayList<Var>(bVars.size());
+        for(TMetaVar v : bVars)
+            vars.add(getOrCreateVar(v));
+        bVars.clear();
+        return new VUnion(cons, vars);
+    }
+
+    private void createVar() {
+        for(Subsumption sub : subsumptions)
+            addSubsumption(sub.loc, sub.a, sub.b);
+        for(Type t : potentialSingletonEffects)
+            addVar(t);
+    }
+    
+    private void reduceChains() {
+        markAllDirty();
+        while(true) {
+            Var v = dirtyQueue.poll();
+            if(v == null)
+                break;
+            
+            reduceChains(v);
+            v.dirty = false;
+        }
+    }
+    
+    private void reduceChains(Var v) {
+        if(v.constLowerBound == v.constUpperBound) {
+            v.replaceWith(v.constLowerBound);
+            return;
+        }
+        Polarity p = v.original.getPolarity();
+        if(!p.isNegative() && v.complexLowerBounds.isEmpty()) {
+            if(v.simpleLowerBounds.isEmpty()) {
+                if((v.constLowerBound&v.constUpperBound) != v.constLowerBound)
+                    errorLog.log(globalLoc, "Subsumption failed.");
+                v.replaceWith(v.constLowerBound);
+                return;
+            }
+            else if(v.simpleLowerBounds.size() == 1 && v.constLowerBound == 0) {
+                v.replaceDownwards(v.simpleLowerBounds.get(0));
+                return;
+            }
+        }
+        if(p == Polarity.NEGATIVE && v.complexUpperBounds.isEmpty()) {
+            if(v.simpleUpperBounds.isEmpty()) {
+                if((v.constLowerBound&v.constUpperBound) != v.constLowerBound)
+                    errorLog.log(globalLoc, "Subsumption failed.");
+                v.replaceWith(v.constUpperBound);
+                return;
+            }
+            else if(v.simpleUpperBounds.size() == 1 && v.constUpperBound == EffectIdMap.MAX) {
+                v.replaceUpwards(v.simpleUpperBounds.get(0));
+                return;
+            }
+        }
+    }
+    
+    private void propagateUpperBounds() {
+        markAllDirty();        
+        while(true) {
+            Var v = dirtyQueue.poll();
+            if(v == null)
+                break;
+            
+            int upperApprox = v.constUpperBound;
+            for(Var u : v.simpleUpperBounds)
+                upperApprox &= u.upperApprox;
+            for(VUnion u : v.complexUpperBounds)
+                upperApprox &= u.getUpperApprox();
+            
+            if(upperApprox != v.upperApprox) {
+                v.upperApprox = upperApprox;
+                for(Var u : v.simpleLowerBounds)
+                    u.markDirty();
+                for(VUnion u : v.complexLowerBounds)
+                    if(u.low != null)
+                        u.low.markDirty();
+            }   
+            
+            v.dirty = false;
+        }
+    }
+    
+    private void checkLowerBounds() {
+        THashSet<VUnion> lowerBounds = new THashSet<VUnion>(); 
+        for(Var v : vars.values()) {
+            if((v.constLowerBound & v.upperApprox) != v.constLowerBound)
+                testSubsumption(globalLoc, v.constLowerBound, v.upperApprox);
+            for(VUnion u : v.complexLowerBounds)
+                if(u.low == null)
+                    lowerBounds.add(u);
+        }
+        for(VUnion u : lowerBounds)
+            if(u.getUpperApprox() != EffectIdMap.MAX)
+                errorLog.log(globalLoc, "Subsumption failed.");
+    }
+
+    private void errorFromUnsolvedEquations() {
+        for(Var v : vars.values()) {
+            if(!v.isFree()) {
+                errorLog.log(globalLoc, "Couldn't simplify all effect subsumptions away. " +
+                               "The current compiler cannot handle this situation. Try adding more type annotations.");
+                break;
+            }
+        }
+    }
+    
+    private void print() {
+        for(Var v : vars.values()) {
+            System.out.println(v.name + 
+                    ", " + v.original.getPolarity() + 
+                    (v.simpleLowerBounds.isEmpty() ? "" : ", simpleLowerRefs: " + v.simpleLowerBounds.size()) +  
+                    (v.complexLowerBounds.isEmpty() ? "" : ", complexLowerRefs: " + v.complexLowerBounds.size()) +
+                    ", " + v.original.getKind());
+            if(v.constLowerBound != EffectIdMap.MIN)
+                System.out.println("    > " + v.constLowerBound);
+            if(v.constUpperBound != EffectIdMap.MAX)
+                System.out.println("    < " + v.constUpperBound);
+            for(Var u : v.simpleUpperBounds)
+                System.out.println("    < " + u.name);
+            for(VUnion u : v.complexUpperBounds)
+                System.out.println("    << " + u);
+        }
+    }
+    
+    private void printSubsumptions() {
+        for(Subsumption sub : subsumptions)
+            System.out.println("[" + sub.a.toString(tuc) + " < " + sub.b.toString(tuc) + " : " + 
+                    Locations.beginOf(sub.loc) + "," + Locations.endOf(sub.loc) + "]");
+    }
+
+    private void testSubsumption(long location, int a, int b) {
+        int extraEffects = a & (~b);
+        if(extraEffects != 0)
+            subsumptionFailed(location, extraEffects);
+    }
+    
+    private void subsumptionFailed(long location , int effects) {
+        errorLog.log(location, "Side-effect " + effectIds.toType(effects) + " is forbidden here.");
+    }
+}