--- /dev/null
+package org.simantics.scl.compiler.internal.elaboration.constraints;\r
+\r
+import java.util.ArrayList;\r
+\r
+import org.simantics.scl.compiler.constants.Constant;\r
+import org.simantics.scl.compiler.elaboration.expressions.EApply;\r
+import org.simantics.scl.compiler.elaboration.expressions.EApplyType;\r
+import org.simantics.scl.compiler.elaboration.expressions.ELiteral;\r
+import org.simantics.scl.compiler.elaboration.expressions.EVariable;\r
+import org.simantics.scl.compiler.elaboration.expressions.Expression;\r
+import org.simantics.scl.compiler.elaboration.expressions.Variable;\r
+import org.simantics.scl.compiler.internal.codegen.utils.TransientClassBuilder;\r
+import org.simantics.scl.compiler.top.SCLCompilerConfiguration;\r
+import org.simantics.scl.compiler.types.TPred;\r
+import org.simantics.scl.compiler.types.Type;\r
+import org.simantics.scl.compiler.types.Types;\r
+import org.simantics.scl.compiler.types.util.Typed;\r
+import org.simantics.scl.runtime.tuple.Tuple0;\r
+\r
+public class Constraint implements Typed {\r
+ public static final Constraint[] EMPTY_ARRAY = new Constraint[0];\r
+ \r
+ public static final int STATE_UNSOLVED = 0;\r
+ public static final int STATE_HAS_INSTANCE = 1;\r
+ public static final int STATE_HAS_SUBCLASS = 2;\r
+ public static final int STATE_GIVEN = 3;\r
+ \r
+ public static final Expression GIVEN_GENERATOR = new ELiteral(new Constant(Types.UNIT) {\r
+ @Override\r
+ public Object realizeValue(TransientClassBuilder classBuilder) {\r
+ return Tuple0.INSTANCE;\r
+ } \r
+ });\r
+ \r
+ public TPred constraint;\r
+ int state = STATE_UNSOLVED;\r
+ public final Variable evidence;\r
+ Expression generator;\r
+ Type[] generatorParameters;\r
+ Constraint[] dependsOn;\r
+ boolean handled;\r
+ long demandLocation;\r
+ \r
+ public Constraint(TPred constraint, Variable evidence, long demandLocation) {\r
+ if(SCLCompilerConfiguration.DEBUG) {\r
+ if(constraint == null || evidence == null)\r
+ throw new NullPointerException();\r
+ }\r
+ this.constraint = constraint;\r
+ this.evidence = evidence;\r
+ this.demandLocation = demandLocation;\r
+ }\r
+ \r
+ public void setGenerator(int newState, Expression generator, Type[] generatorParameters, Constraint ... dependsOn) {\r
+ if(SCLCompilerConfiguration.DEBUG) {\r
+ if(generator == null)\r
+ throw new NullPointerException();\r
+ for(Type generatorParameter : generatorParameters)\r
+ if(generatorParameter == null)\r
+ throw new NullPointerException();\r
+ }\r
+ this.state = newState;\r
+ this.generator = generator;\r
+ this.dependsOn = dependsOn;\r
+ this.generatorParameters = generatorParameters;\r
+ }\r
+\r
+ public Expression generate(long loc) {\r
+ Expression result = generator;\r
+ for(Type p : generatorParameters)\r
+ result = new EApplyType(loc, result, p);\r
+ for(Constraint dep : dependsOn) {\r
+ result = new EApply(loc, result, new EVariable(loc, dep.evidence));\r
+ }\r
+ return result;\r
+ }\r
+ \r
+ public void collect(ConstraintEnvironment environment, ArrayList<Constraint> unsolvedConstraints, ArrayList<Constraint> solvedConstraints) {\r
+ if(!handled) {\r
+ switch(state) {\r
+ case STATE_UNSOLVED:\r
+ unsolvedConstraints.add(this);\r
+ break;\r
+ case STATE_HAS_SUBCLASS:\r
+ // Try to find constant evidence and prefer that\r
+ // to subclass\r
+ {\r
+ Reduction reduction = environment.reduce(constraint);\r
+ if(reduction != null && reduction.demands.length == 0) {\r
+ generator = reduction.generator;\r
+ generatorParameters = reduction.parameters;\r
+ dependsOn = Constraint.EMPTY_ARRAY;\r
+ state = STATE_HAS_INSTANCE;\r
+ }\r
+ }\r
+ // Intentionally no break\r
+ case STATE_HAS_INSTANCE:\r
+ for(Constraint dep : dependsOn)\r
+ dep.collect(environment, unsolvedConstraints, solvedConstraints);\r
+ solvedConstraints.add(this);\r
+ break;\r
+ }\r
+ handled = true;\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public Type getType() {\r
+ return constraint;\r
+ }\r
+ \r
+ public long getDemandLocation() {\r
+ return demandLocation;\r
+ }\r
+}
\ No newline at end of file