1 package org.simantics.scl.compiler.internal.elaboration.constraints;
3 import java.util.ArrayList;
5 import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
6 import org.simantics.scl.compiler.constants.ClassConstant;
7 import org.simantics.scl.compiler.constants.StringConstant;
8 import org.simantics.scl.compiler.elaboration.expressions.EApply;
9 import org.simantics.scl.compiler.elaboration.expressions.EConstant;
10 import org.simantics.scl.compiler.elaboration.expressions.ELiteral;
11 import org.simantics.scl.compiler.elaboration.java.Builtins;
12 import org.simantics.scl.compiler.elaboration.modules.TypeClass;
13 import org.simantics.scl.compiler.elaboration.modules.TypeClassInstance;
14 import org.simantics.scl.compiler.environment.Environment;
15 import org.simantics.scl.compiler.errors.Locations;
16 import org.simantics.scl.compiler.types.TApply;
17 import org.simantics.scl.compiler.types.TCon;
18 import org.simantics.scl.compiler.types.TFun;
19 import org.simantics.scl.compiler.types.TPred;
20 import org.simantics.scl.compiler.types.TUnion;
21 import org.simantics.scl.compiler.types.TVar;
22 import org.simantics.scl.compiler.types.Type;
23 import org.simantics.scl.compiler.types.Types;
25 import gnu.trove.map.hash.THashMap;
27 public class ConstraintEnvironment {
28 Environment environment;
30 public ConstraintEnvironment(Environment environment) {
31 this.environment = environment;
34 public Superconstraint[] getSuperconstraints(TPred constraint) {
35 TypeClass tc = environment.getTypeClass(constraint.typeClass);
37 throw new InternalCompilerError("Didn't find constraint " + constraint + ". Maybe Prelude is not loaded?");
39 if(tc.context.length == 0)
40 return Superconstraint.EMPTY_ARRAY;
41 Superconstraint[] result = new Superconstraint[tc.context.length];
42 for(int i=0;i<result.length;++i) {
43 result[i] = new Superconstraint(
44 (TPred)tc.context[i].replace(tc.parameters, constraint.parameters),
51 public Reduction reduce(TPred constraint) {
53 if(constraint.typeClass == Types.VEC_COMP) {
54 Type parameter = Types.canonical(constraint.parameters[0]);
55 if(parameter.isGround())
56 return new Reduction(new ELiteral(new ClassConstant(Types.pred(Types.VEC_COMP, parameter), parameter)),
57 Type.EMPTY_ARRAY, TPred.EMPTY_ARRAY);
60 if(constraint.typeClass == Types.SERIALIZABLE)
61 return ReduceSerializable.reduceSerializable(constraint.parameters[0]);
64 else if(constraint.typeClass == Types.TYPEABLE) {
65 Type parameter = Types.canonical(constraint.parameters[0]);
66 if(parameter instanceof TCon) {
67 TCon con = (TCon)parameter;
69 new EApply(Locations.NO_LOCATION,
70 new EConstant(Builtins.INSTANCE.getValue("TCon")),
71 new ELiteral(new StringConstant(con.module)),
72 new ELiteral(new StringConstant(con.name))),
73 Type.EMPTY_ARRAY, TPred.EMPTY_ARRAY);
75 else if(parameter instanceof TApply) {
76 TApply apply = (TApply)parameter;
78 new EConstant(Builtins.INSTANCE.getValue("TApply")),
79 Type.EMPTY_ARRAY, new TPred[] {
80 Types.pred(Types.TYPEABLE, apply.function),
81 Types.pred(Types.TYPEABLE, apply.parameter),
84 else if(parameter instanceof TFun) {
85 TFun fun = (TFun)parameter;
87 new EConstant(Builtins.INSTANCE.getValue("TFun")),
88 Type.EMPTY_ARRAY, new TPred[] {
89 Types.pred(Types.TYPEABLE, fun.domain),
90 Types.pred(Types.TYPEABLE, fun.effect),
91 Types.pred(Types.TYPEABLE, fun.range)
94 else if(parameter instanceof TUnion) {
95 TUnion union = (TUnion)parameter;
97 if(union.effects.length == 0)
99 new EConstant(Builtins.INSTANCE.getValue("TPure")),
102 else if(union.effects.length == 2) {
103 return new Reduction(
104 new EConstant(Builtins.INSTANCE.getValue("TUnion2")),
105 Type.EMPTY_ARRAY, new TPred[] {
106 Types.pred(Types.TYPEABLE, union.effects[0]),
107 Types.pred(Types.TYPEABLE, union.effects[1])
110 else if(union.effects.length == 3) {
111 return new Reduction(
112 new EConstant(Builtins.INSTANCE.getValue("TUnion3")),
113 Type.EMPTY_ARRAY, new TPred[] {
114 Types.pred(Types.TYPEABLE, union.effects[0]),
115 Types.pred(Types.TYPEABLE, union.effects[1]),
116 Types.pred(Types.TYPEABLE, union.effects[2])
123 THashMap<TVar, Type> substitution = new THashMap<TVar, Type>();
124 ArrayList<Reduction> reductions = new ArrayList<Reduction>(1);
125 for(TypeClassInstance inst : environment.getInstances(constraint.typeClass)) {
126 if(Types.match(inst.instance, constraint, substitution)) {
127 TPred[] demands = new TPred[inst.context.length];
128 for(int i=0;i<demands.length;++i) {
129 demands[i] = (TPred)inst.context[i].replace(substitution);
131 Type[] parameters = new Type[inst.generatorParameters.length];
132 for(int i=0;i<parameters.length;++i) {
133 Type parameter = substitution.get(inst.generatorParameters[i]);
134 if(parameter == null)
135 parameter = inst.generatorParameters[i]; // TODO Is this correct?
136 parameters[i] = parameter;
138 reductions.add(new Reduction(new ELiteral(inst.generator), parameters, demands));
140 substitution.clear();
142 //System.out.println(constraint.typeClass + " -> " + reductions.size());
143 if(reductions.size() == 1)
144 return reductions.get(0);
145 else if(reductions.size() > 1) {
146 throw new InternalCompilerError("Found more than one matching instances for " + constraint.typeClass + ".");