1 package org.simantics.scl.compiler.internal.elaboration.constraints;
\r
3 import java.util.ArrayList;
\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
20 public class Constraint implements Typed {
\r
21 public static final Constraint[] EMPTY_ARRAY = new Constraint[0];
\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
28 public static final Expression GIVEN_GENERATOR = new ELiteral(new Constant(Types.UNIT) {
\r
30 public Object realizeValue(TransientClassBuilder classBuilder) {
\r
31 return Tuple0.INSTANCE;
\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
42 long demandLocation;
\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
49 this.constraint = constraint;
\r
50 this.evidence = evidence;
\r
51 this.demandLocation = demandLocation;
\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
62 this.state = newState;
\r
63 this.generator = generator;
\r
64 this.dependsOn = dependsOn;
\r
65 this.generatorParameters = generatorParameters;
\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
78 public void collect(ConstraintEnvironment environment, ArrayList<Constraint> unsolvedConstraints, ArrayList<Constraint> solvedConstraints) {
\r
81 case STATE_UNSOLVED:
\r
82 unsolvedConstraints.add(this);
\r
84 case STATE_HAS_SUBCLASS:
\r
85 // Try to find constant evidence and prefer that
\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
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
108 public Type getType() {
\r
112 public long getDemandLocation() {
\r
113 return demandLocation;
\r