]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/elaboration/constraints/Constraint.java
c49167508bb74a83cfa8298c8da70a3c1085a99f
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / internal / elaboration / constraints / Constraint.java
1 package org.simantics.scl.compiler.internal.elaboration.constraints;
2
3 import java.util.ArrayList;
4
5 import org.simantics.scl.compiler.constants.Constant;
6 import org.simantics.scl.compiler.elaboration.expressions.EApply;
7 import org.simantics.scl.compiler.elaboration.expressions.EApplyType;
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.Expression;
11 import org.simantics.scl.compiler.elaboration.expressions.Variable;
12 import org.simantics.scl.compiler.internal.codegen.utils.TransientClassBuilder;
13 import org.simantics.scl.compiler.top.SCLCompilerConfiguration;
14 import org.simantics.scl.compiler.types.TPred;
15 import org.simantics.scl.compiler.types.Type;
16 import org.simantics.scl.compiler.types.Types;
17 import org.simantics.scl.compiler.types.util.Typed;
18 import org.simantics.scl.runtime.tuple.Tuple0;
19
20 public class Constraint implements Typed {
21     public static final Constraint[] EMPTY_ARRAY = new Constraint[0];
22     
23     public static final int STATE_UNSOLVED = 0;
24     public static final int STATE_HAS_INSTANCE = 1;
25     public static final int STATE_HAS_SUBCLASS = 2;
26     public static final int STATE_GIVEN = 3;
27     
28     public static final Expression GIVEN_GENERATOR = new ELiteral(new Constant(Types.UNIT) {
29         @Override
30         public Object realizeValue(TransientClassBuilder classBuilder) {
31             return Tuple0.INSTANCE;
32         }        
33     });
34     
35     public TPred constraint;
36     int state = STATE_UNSOLVED;
37     public final Variable evidence;
38     Expression generator;
39     Type[] generatorParameters;
40     Constraint[] dependsOn;
41     boolean handled;
42     long demandLocation;
43            
44     public Constraint(TPred constraint, Variable evidence, long demandLocation) {
45         if(SCLCompilerConfiguration.DEBUG) {
46             if(constraint == null || evidence == null)
47                 throw new NullPointerException();
48         }
49         this.constraint = constraint;
50         this.evidence = evidence;
51         this.demandLocation = demandLocation;
52     }
53     
54     public void setGenerator(int newState, Expression generator, Type[] generatorParameters, Constraint ... dependsOn) {
55         if(SCLCompilerConfiguration.DEBUG) {
56             if(generator == null)
57                 throw new NullPointerException();
58             for(Type generatorParameter : generatorParameters)
59                 if(generatorParameter == null)
60                     throw new NullPointerException();
61         }
62         this.state = newState;
63         this.generator = generator;
64         this.dependsOn = dependsOn;
65         this.generatorParameters = generatorParameters;
66     }
67
68     public Expression generate(long loc) {
69         Expression result = generator;
70         for(Type p : generatorParameters)
71             result = new EApplyType(loc, result, p);
72         for(Constraint dep : dependsOn) {
73             result = new EApply(loc, result, new EVariable(loc, dep.evidence));
74         }
75         return result;
76     }
77     
78     public void collect(ConstraintEnvironment environment, ArrayList<Constraint> unsolvedConstraints, ArrayList<Constraint> solvedConstraints) {
79         if(!handled) {
80             switch(state) {
81             case STATE_UNSOLVED:
82                 unsolvedConstraints.add(this);
83                 break;
84             case STATE_HAS_SUBCLASS:
85                 // Try to find constant evidence and prefer that
86                 // to subclass
87                 {
88                     Reduction reduction = environment.reduce(constraint);
89                     if(reduction != null && reduction.demands.length == 0) {
90                         generator = reduction.generator;
91                         generatorParameters = reduction.parameters;
92                         dependsOn = Constraint.EMPTY_ARRAY;
93                         state = STATE_HAS_INSTANCE;
94                     }
95                 }
96                 // Intentionally no break
97             case STATE_HAS_INSTANCE:
98                 for(Constraint dep : dependsOn)
99                     dep.collect(environment, unsolvedConstraints, solvedConstraints);
100                 solvedConstraints.add(this);
101                 break;
102             }
103             handled = true;
104         }
105     }
106
107     @Override
108     public Type getType() {
109         return constraint;
110     }
111     
112     public long getDemandLocation() {
113         return demandLocation;
114     }
115 }