]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/elaboration/constraints/ConstraintSet.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / internal / elaboration / constraints / ConstraintSet.java
diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/elaboration/constraints/ConstraintSet.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/elaboration/constraints/ConstraintSet.java
new file mode 100644 (file)
index 0000000..1473ab9
--- /dev/null
@@ -0,0 +1,131 @@
+package org.simantics.scl.compiler.internal.elaboration.constraints;
+
+import gnu.trove.map.hash.THashMap;
+import gnu.trove.set.hash.THashSet;
+
+import java.util.ArrayList;
+
+import org.simantics.scl.compiler.elaboration.expressions.ELiteral;
+import org.simantics.scl.compiler.elaboration.expressions.EVariable;
+import org.simantics.scl.compiler.elaboration.expressions.Variable;
+import org.simantics.scl.compiler.errors.Locations;
+import org.simantics.scl.compiler.types.TCon;
+import org.simantics.scl.compiler.types.TPred;
+import org.simantics.scl.compiler.types.Types;
+
+class ConstraintSet {
+    
+    private static int id = 0;
+    
+    final ConstraintEnvironment environment;
+    
+    /**
+     * Collection of all active (solved or unsolved) constraints.
+     */
+    final THashMap<TCon, ArrayList<Constraint>> constraints = new THashMap<TCon, ArrayList<Constraint>>();
+    
+    /**
+     * Set of currently unsolved constraints.
+     */
+    THashSet<Constraint> unsolved = new THashSet<Constraint>();
+    
+    /**
+     * These are constraints that are explicitly required in the code
+     */
+    final ArrayList<Constraint> needed = new ArrayList<Constraint>();
+    
+    public ConstraintSet(ConstraintEnvironment environment) {
+        this.environment = environment;
+    }
+
+    private ArrayList<Constraint> getConstraintList(TCon typeClass) {
+        ArrayList<Constraint> cl = constraints.get(typeClass);
+        if(cl == null) {
+            cl = new ArrayList<Constraint>(2);
+            constraints.put(typeClass, cl);
+        }
+        return cl;
+    }
+    
+    public void addDemand(EVariable demand) {
+        Constraint constraint = addConstraint(demand.getLocation(), (TPred)demand.getType());
+        demand.setVariable(constraint.evidence);
+        needed.add(constraint);
+    }
+    
+    private Constraint addConstraint(long demandLocation, TPred constraint) {        
+        ArrayList<Constraint> cl = getConstraintList(constraint.typeClass); 
+        for(Constraint c : cl) {
+            if(Types.equals(constraint, c.constraint)) {
+                return c;
+            }
+        }      
+        Constraint newConstraint = newConstraint(demandLocation, constraint);        
+        cl.add(newConstraint);
+        unsolved.add(newConstraint);
+        return newConstraint;
+    }
+    
+    private void addSuperconstraints(Constraint constraint) {
+        scloop: for(Superconstraint superconstraint : environment.getSuperconstraints(constraint.constraint)) {
+            TPred sc = superconstraint.superconstraint;
+            ArrayList<Constraint> cl = getConstraintList(sc.typeClass);
+            for(Constraint c : cl) {
+                if(c.state < Constraint.STATE_HAS_SUBCLASS &&
+                        Types.equals(sc, c.constraint)) {
+                    unsolved.remove(c);                        
+                    c.setGenerator(Constraint.STATE_HAS_SUBCLASS,                            
+                            new ELiteral(constraint.demandLocation, superconstraint.generator), constraint.constraint.parameters, constraint);
+                    continue scloop;
+                }
+            }
+            Constraint newConstraint = newConstraint(constraint.demandLocation, sc);
+            newConstraint.setGenerator(Constraint.STATE_HAS_SUBCLASS, 
+                    new ELiteral(constraint.demandLocation, superconstraint.generator), constraint.constraint.parameters, constraint);
+            cl.add(newConstraint);
+        }
+    }
+    
+    private Constraint newConstraint(long demandLocation, TPred constraint) {
+        Variable evidence = new Variable("ev" + (++id));
+        evidence.setType(constraint);
+        Constraint newConstraint = new Constraint(constraint, evidence, demandLocation);
+        addSuperconstraints(newConstraint);
+        return newConstraint;
+    }
+    
+    public void reduce() {
+        while(!unsolved.isEmpty()) {
+            THashSet<Constraint> temp = unsolved;
+            unsolved = new THashSet<Constraint>();
+            for(Constraint c : temp) {
+                if(c.state == Constraint.STATE_UNSOLVED) {
+                    Reduction reduction = environment.reduce(c.constraint);
+                    if(reduction != null) {
+                        TPred[] demands = reduction.demands;
+                        if(demands.length == 0)
+                            c.setGenerator(Constraint.STATE_HAS_INSTANCE, reduction.generator, reduction.parameters, Constraint.EMPTY_ARRAY);
+                        else {
+                            Constraint[] dependsOn = new Constraint[demands.length];
+                            for(int i=0;i<demands.length;++i)
+                                dependsOn[i] = addConstraint(c.demandLocation, demands[i]);
+                            c.setGenerator(Constraint.STATE_HAS_INSTANCE, reduction.generator, reduction.parameters, dependsOn);
+                        }
+                    }
+                }
+            }
+        }
+    }
+    
+    public void collect(ArrayList<Constraint> unsolvedConstraints, ArrayList<Constraint> solvedConstraints) {
+        for(Constraint n : needed)
+            n.collect(environment, unsolvedConstraints, solvedConstraints);
+    }
+    
+    public Constraint addGiven(TPred c) {
+        Constraint result = addConstraint(Locations.NO_LOCATION, c);
+        result.state = Constraint.STATE_GIVEN;
+        result.generator = Constraint.GIVEN_GENERATOR;
+        return result;
+    }
+}