--- /dev/null
+package org.simantics.scl.compiler.internal.elaboration.constraints2;
+
+import gnu.trove.map.hash.THashMap;
+import gnu.trove.procedure.TObjectProcedure;
+
+import java.util.ArrayList;
+
+import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
+import org.simantics.scl.compiler.elaboration.modules.TypeClass;
+import org.simantics.scl.compiler.types.TCon;
+import org.simantics.scl.compiler.types.TPred;
+import org.simantics.scl.compiler.types.TVar;
+import org.simantics.scl.compiler.types.Type;
+import org.simantics.scl.compiler.types.Types;
+import org.simantics.scl.compiler.types.util.TypeUnparsingContext;
+
+class ConstraintStore {
+
+ private final ConstraintSolver solver;
+ private final TypeClass typeClass;
+ private final THashMap<Type, ArrayList<ConstraintHandle>> constraintsByHead =
+ new THashMap<Type, ArrayList<ConstraintHandle>>();
+ private final ArrayList<ConstraintHandle> constraintsWithoutHead =
+ new ArrayList<ConstraintHandle>();
+
+ public ConstraintStore(ConstraintSolver solver, TCon typeClassCon) {
+ this.solver = solver;
+ this.typeClass = solver.environment.getTypeClass(typeClassCon);
+ if(this.typeClass == null)
+ throw new InternalCompilerError("Didn't find type class " + typeClassCon + ".");
+ }
+
+ private ArrayList<ConstraintHandle> getConstraintListFor(TPred pred) {
+ Type head = head(pred);
+ if(head instanceof TCon || head instanceof TVar) {
+ ArrayList<ConstraintHandle> result = constraintsByHead.get(head);
+ if(result == null) {
+ result = new ArrayList<ConstraintHandle>(2);
+ constraintsByHead.put(head, result);
+ }
+ return result;
+ }
+ else
+ return constraintsWithoutHead;
+ }
+
+ public ConstraintHandle addConstraint(TPred pred, long demandLocation) {
+ // Try to find an existing ConstraintHandle for the predicate
+ ArrayList<ConstraintHandle> handles = getConstraintListFor(pred);
+ for(ConstraintHandle handle : handles)
+ if(equals(pred.parameters, handle.constraint.parameters))
+ return handle;
+
+ // Create a new ConstraintHandle
+ ConstraintHandle handle = new ConstraintHandle(pred, demandLocation);
+ handles.add(handle);
+ addSuperDemands(handle);
+ return handle;
+ }
+
+ private void addSuperDemands(ConstraintHandle handle) {
+ for(int i=0;i<typeClass.context.length;++i) {
+ TPred superPred = (TPred)
+ typeClass.context[i].replace(typeClass.parameters, handle.constraint.parameters);
+ ConstraintHandle superHandle = solver.addDemand(superPred, handle.demandLocation);
+ superHandle.setResolution(new ConstraintResolution(
+ typeClass.superGenerators[i], handle.constraint.parameters,
+ new ConstraintHandle[] {handle}, ConstraintResolution.SUPERCLASS_PRIORITY));
+ }
+ }
+
+ private static Type head(TPred pred) {
+ return pred.parameters[0].head();
+ }
+
+ private static boolean equals(Type[] a, Type[] b) {
+ for(int i=0;i<a.length;++i)
+ if(!Types.equals(a[i], b[i]))
+ return false;
+ return true;
+ }
+
+ public void print(final TypeUnparsingContext tuc) {
+ constraintsByHead.forEachValue(new TObjectProcedure<ArrayList<ConstraintHandle>>() {
+ @Override
+ public boolean execute(ArrayList<ConstraintHandle> constraintHandles) {
+ for(ConstraintHandle constraintHandle : constraintHandles)
+ System.out.println(constraintHandle.toString(tuc));
+ return true;
+ }
+ });
+ for(ConstraintHandle constraintHandle : constraintsWithoutHead)
+ System.out.println(constraintHandle.toString(tuc));
+ }
+
+}