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