]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/elaboration/constraints/ConstraintSet.java
migrated to svn revision 33108
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / internal / elaboration / constraints / ConstraintSet.java
1 package org.simantics.scl.compiler.internal.elaboration.constraints;
2
3 import java.util.ArrayList;
4
5 import org.simantics.scl.compiler.elaboration.expressions.ELiteral;
6 import org.simantics.scl.compiler.elaboration.expressions.EVariable;
7 import org.simantics.scl.compiler.elaboration.expressions.Variable;
8 import org.simantics.scl.compiler.errors.Locations;
9 import org.simantics.scl.compiler.types.TCon;
10 import org.simantics.scl.compiler.types.TPred;
11 import org.simantics.scl.compiler.types.Types;
12
13 import gnu.trove.map.hash.THashMap;
14 import gnu.trove.set.hash.THashSet;
15
16 class ConstraintSet {
17     
18     private static int id = 0;
19     
20     final ConstraintEnvironment environment;
21     
22     /**
23      * Collection of all active (solved or unsolved) constraints.
24      */
25     final THashMap<TCon, ArrayList<Constraint>> constraints = new THashMap<TCon, ArrayList<Constraint>>();
26     
27     /**
28      * Set of currently unsolved constraints.
29      */
30     THashSet<Constraint> unsolved = new THashSet<Constraint>();
31     
32     /**
33      * These are constraints that are explicitly required in the code
34      */
35     final ArrayList<Constraint> needed = new ArrayList<Constraint>();
36     
37     public ConstraintSet(ConstraintEnvironment environment) {
38         this.environment = environment;
39     }
40
41     private ArrayList<Constraint> getConstraintList(TCon typeClass) {
42         ArrayList<Constraint> cl = constraints.get(typeClass);
43         if(cl == null) {
44             cl = new ArrayList<Constraint>(2);
45             constraints.put(typeClass, cl);
46         }
47         return cl;
48     }
49     
50     public void addDemand(EVariable demand) {
51         Constraint constraint = addConstraint(demand.getLocation(), (TPred)demand.getType());
52         demand.setVariable(constraint.evidence);
53         needed.add(constraint);
54     }
55     
56     private Constraint addConstraint(long demandLocation, TPred constraint) {        
57         ArrayList<Constraint> cl = getConstraintList(constraint.typeClass); 
58         for(Constraint c : cl) {
59             if(Types.equals(constraint, c.constraint)) {
60                 return c;
61             }
62         }      
63         Constraint newConstraint = newConstraint(demandLocation, constraint);        
64         cl.add(newConstraint);
65         unsolved.add(newConstraint);
66         return newConstraint;
67     }
68     
69     private void addSuperconstraints(Constraint constraint) {
70         scloop: for(Superconstraint superconstraint : environment.getSuperconstraints(constraint.constraint)) {
71             TPred sc = superconstraint.superconstraint;
72             ArrayList<Constraint> cl = getConstraintList(sc.typeClass);
73             for(Constraint c : cl) {
74                 if(c.state < Constraint.STATE_HAS_SUBCLASS &&
75                         Types.equals(sc, c.constraint)) {
76                     unsolved.remove(c);                        
77                     c.setGenerator(Constraint.STATE_HAS_SUBCLASS,                            
78                             new ELiteral(constraint.demandLocation, superconstraint.generator), constraint.constraint.parameters, constraint);
79                     continue scloop;
80                 }
81             }
82             Constraint newConstraint = newConstraint(constraint.demandLocation, sc);
83             newConstraint.setGenerator(Constraint.STATE_HAS_SUBCLASS, 
84                     new ELiteral(constraint.demandLocation, superconstraint.generator), constraint.constraint.parameters, constraint);
85             cl.add(newConstraint);
86         }
87     }
88     
89     private Constraint newConstraint(long demandLocation, TPred constraint) {
90         Variable evidence = new Variable("ev" + (++id));
91         evidence.setType(constraint);
92         Constraint newConstraint = new Constraint(constraint, evidence, demandLocation);
93         addSuperconstraints(newConstraint);
94         return newConstraint;
95     }
96     
97     public void reduce() {
98         while(!unsolved.isEmpty()) {
99             THashSet<Constraint> temp = unsolved;
100             unsolved = new THashSet<Constraint>();
101             for(Constraint c : temp) {
102                 if(c.state == Constraint.STATE_UNSOLVED) {
103                     Reduction reduction = environment.reduce(c.constraint);
104                     if(reduction != null) {
105                         TPred[] demands = reduction.demands;
106                         if(demands.length == 0)
107                             c.setGenerator(Constraint.STATE_HAS_INSTANCE, reduction.generator, reduction.parameters, Constraint.EMPTY_ARRAY);
108                         else {
109                             Constraint[] dependsOn = new Constraint[demands.length];
110                             for(int i=0;i<demands.length;++i)
111                                 dependsOn[i] = addConstraint(c.demandLocation, demands[i]);
112                             c.setGenerator(Constraint.STATE_HAS_INSTANCE, reduction.generator, reduction.parameters, dependsOn);
113                         }
114                     }
115                 }
116             }
117         }
118     }
119     
120     public void collect(ArrayList<Constraint> unsolvedConstraints, ArrayList<Constraint> solvedConstraints) {
121         for(Constraint n : needed)
122             n.collect(environment, unsolvedConstraints, solvedConstraints);
123     }
124     
125     public Constraint addGiven(TPred c) {
126         Constraint result = addConstraint(Locations.NO_LOCATION, c);
127         result.state = Constraint.STATE_GIVEN;
128         result.generator = Constraint.GIVEN_GENERATOR;
129         return result;
130     }
131 }