1 package org.simantics.scl.compiler.internal.elaboration.constraints;
3 import gnu.trove.map.hash.THashMap;
4 import gnu.trove.set.hash.THashSet;
6 import java.util.ArrayList;
8 import org.simantics.scl.compiler.elaboration.expressions.ELiteral;
9 import org.simantics.scl.compiler.elaboration.expressions.EVariable;
10 import org.simantics.scl.compiler.elaboration.expressions.Variable;
11 import org.simantics.scl.compiler.errors.Locations;
12 import org.simantics.scl.compiler.types.TCon;
13 import org.simantics.scl.compiler.types.TPred;
14 import org.simantics.scl.compiler.types.Types;
18 private static int id = 0;
20 final ConstraintEnvironment environment;
23 * Collection of all active (solved or unsolved) constraints.
25 final THashMap<TCon, ArrayList<Constraint>> constraints = new THashMap<TCon, ArrayList<Constraint>>();
28 * Set of currently unsolved constraints.
30 THashSet<Constraint> unsolved = new THashSet<Constraint>();
33 * These are constraints that are explicitly required in the code
35 final ArrayList<Constraint> needed = new ArrayList<Constraint>();
37 public ConstraintSet(ConstraintEnvironment environment) {
38 this.environment = environment;
41 private ArrayList<Constraint> getConstraintList(TCon typeClass) {
42 ArrayList<Constraint> cl = constraints.get(typeClass);
44 cl = new ArrayList<Constraint>(2);
45 constraints.put(typeClass, cl);
50 public void addDemand(EVariable demand) {
51 Constraint constraint = addConstraint(demand.getLocation(), (TPred)demand.getType());
52 demand.setVariable(constraint.evidence);
53 needed.add(constraint);
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)) {
63 Constraint newConstraint = newConstraint(demandLocation, constraint);
64 cl.add(newConstraint);
65 unsolved.add(newConstraint);
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)) {
77 c.setGenerator(Constraint.STATE_HAS_SUBCLASS,
78 new ELiteral(constraint.demandLocation, superconstraint.generator), constraint.constraint.parameters, constraint);
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);
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);
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);
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);
120 public void collect(ArrayList<Constraint> unsolvedConstraints, ArrayList<Constraint> solvedConstraints) {
121 for(Constraint n : needed)
122 n.collect(environment, unsolvedConstraints, solvedConstraints);
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;