1 package org.simantics.scl.compiler.internal.elaboration.constraints;
3 import java.util.ArrayList;
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;
20 public class Constraint implements Typed {
21 public static final Constraint[] EMPTY_ARRAY = new Constraint[0];
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;
28 public static final Expression GIVEN_GENERATOR = new ELiteral(new Constant(Types.UNIT) {
30 public Object realizeValue(TransientClassBuilder classBuilder) {
31 return Tuple0.INSTANCE;
35 public TPred constraint;
36 int state = STATE_UNSOLVED;
37 public final Variable evidence;
39 Type[] generatorParameters;
40 Constraint[] dependsOn;
44 public Constraint(TPred constraint, Variable evidence, long demandLocation) {
45 if(SCLCompilerConfiguration.DEBUG) {
46 if(constraint == null || evidence == null)
47 throw new NullPointerException();
49 this.constraint = constraint;
50 this.evidence = evidence;
51 this.demandLocation = demandLocation;
54 public void setGenerator(int newState, Expression generator, Type[] generatorParameters, Constraint ... dependsOn) {
55 if(SCLCompilerConfiguration.DEBUG) {
57 throw new NullPointerException();
58 for(Type generatorParameter : generatorParameters)
59 if(generatorParameter == null)
60 throw new NullPointerException();
62 this.state = newState;
63 this.generator = generator;
64 this.dependsOn = dependsOn;
65 this.generatorParameters = generatorParameters;
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));
78 public void collect(ConstraintEnvironment environment, ArrayList<Constraint> unsolvedConstraints, ArrayList<Constraint> solvedConstraints) {
82 unsolvedConstraints.add(this);
84 case STATE_HAS_SUBCLASS:
85 // Try to find constant evidence and prefer that
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;
96 // Intentionally no break
97 case STATE_HAS_INSTANCE:
98 for(Constraint dep : dependsOn)
99 dep.collect(environment, unsolvedConstraints, solvedConstraints);
100 solvedConstraints.add(this);
108 public Type getType() {
112 public long getDemandLocation() {
113 return demandLocation;