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.compilation.CompilationContext;
7 import org.simantics.scl.compiler.constants.ClassConstant;
8 import org.simantics.scl.compiler.constants.StringConstant;
9 import org.simantics.scl.compiler.elaboration.expressions.EApply;
10 import org.simantics.scl.compiler.elaboration.expressions.EConstant;
11 import org.simantics.scl.compiler.elaboration.expressions.ELiteral;
12 import org.simantics.scl.compiler.elaboration.java.Builtins;
13 import org.simantics.scl.compiler.elaboration.modules.TypeClass;
14 import org.simantics.scl.compiler.elaboration.modules.TypeClassInstance;
15 import org.simantics.scl.compiler.environment.Environment;
16 import org.simantics.scl.compiler.errors.Locations;
17 import org.simantics.scl.compiler.types.TApply;
18 import org.simantics.scl.compiler.types.TCon;
19 import org.simantics.scl.compiler.types.TFun;
20 import org.simantics.scl.compiler.types.TPred;
21 import org.simantics.scl.compiler.types.TUnion;
22 import org.simantics.scl.compiler.types.TVar;
23 import org.simantics.scl.compiler.types.Type;
24 import org.simantics.scl.compiler.types.Types;
26 import gnu.trove.map.hash.THashMap;
28 public class ConstraintEnvironment {
29 CompilationContext compilationContext;
30 Environment environment;
32 public ConstraintEnvironment(CompilationContext compilationContext) {
33 this.compilationContext = compilationContext;
34 this.environment = compilationContext.environment;
37 public Superconstraint[] getSuperconstraints(TPred constraint) {
38 TypeClass tc = environment.getTypeClass(constraint.typeClass);
40 throw new InternalCompilerError("Didn't find constraint " + constraint + ". Maybe Prelude is not loaded?");
42 if(tc.context.length == 0)
43 return Superconstraint.EMPTY_ARRAY;
44 Superconstraint[] result = new Superconstraint[tc.context.length];
45 for(int i=0;i<result.length;++i) {
46 result[i] = new Superconstraint(
47 (TPred)tc.context[i].replace(tc.parameters, constraint.parameters),
54 public Reduction reduce(long location, TPred constraint) {
56 if(constraint.typeClass == Types.VEC_COMP) {
57 Type parameter = Types.canonical(constraint.parameters[0]);
58 if(parameter.isGround())
59 return new Reduction(new ELiteral(new ClassConstant(Types.pred(Types.VEC_COMP, parameter), parameter)),
60 Type.EMPTY_ARRAY, TPred.EMPTY_ARRAY);
63 if(constraint.typeClass == Types.SERIALIZABLE)
64 return ReduceSerializable.reduceSerializable(constraint.parameters[0]);
67 else if(constraint.typeClass == Types.TYPEABLE) {
68 Type parameter = Types.canonical(constraint.parameters[0]);
69 if(parameter instanceof TCon) {
70 TCon con = (TCon)parameter;
72 new EApply(Locations.NO_LOCATION,
73 new EConstant(Builtins.INSTANCE.getValue("TCon")),
74 new ELiteral(new StringConstant(con.module)),
75 new ELiteral(new StringConstant(con.name))),
76 Type.EMPTY_ARRAY, TPred.EMPTY_ARRAY);
78 else if(parameter instanceof TApply) {
79 TApply apply = (TApply)parameter;
81 new EConstant(Builtins.INSTANCE.getValue("TApply")),
82 Type.EMPTY_ARRAY, new TPred[] {
83 Types.pred(Types.TYPEABLE, apply.function),
84 Types.pred(Types.TYPEABLE, apply.parameter),
87 else if(parameter instanceof TFun) {
88 TFun fun = (TFun)parameter;
90 new EConstant(Builtins.INSTANCE.getValue("TFun")),
91 Type.EMPTY_ARRAY, new TPred[] {
92 Types.pred(Types.TYPEABLE, fun.domain),
93 Types.pred(Types.TYPEABLE, fun.effect),
94 Types.pred(Types.TYPEABLE, fun.range)
97 else if(parameter instanceof TUnion) {
98 TUnion union = (TUnion)parameter;
100 if(union.effects.length == 0)
101 return new Reduction(
102 new EConstant(Builtins.INSTANCE.getValue("TPure")),
105 else if(union.effects.length == 2) {
106 return new Reduction(
107 new EConstant(Builtins.INSTANCE.getValue("TUnion2")),
108 Type.EMPTY_ARRAY, new TPred[] {
109 Types.pred(Types.TYPEABLE, union.effects[0]),
110 Types.pred(Types.TYPEABLE, union.effects[1])
113 else if(union.effects.length == 3) {
114 return new Reduction(
115 new EConstant(Builtins.INSTANCE.getValue("TUnion3")),
116 Type.EMPTY_ARRAY, new TPred[] {
117 Types.pred(Types.TYPEABLE, union.effects[0]),
118 Types.pred(Types.TYPEABLE, union.effects[1]),
119 Types.pred(Types.TYPEABLE, union.effects[2])
126 THashMap<TVar, Type> substitution = new THashMap<TVar, Type>();
127 ArrayList<Reduction> reductions = new ArrayList<Reduction>(1);
128 for(TypeClassInstance inst : environment.getInstances(constraint.typeClass)) {
129 if(Types.match(inst.instance, constraint, substitution)) {
130 TPred[] demands = new TPred[inst.context.length];
131 for(int i=0;i<demands.length;++i) {
132 demands[i] = (TPred)inst.context[i].replace(substitution);
134 Type[] parameters = new Type[inst.generatorParameters.length];
135 for(int i=0;i<parameters.length;++i) {
136 Type parameter = substitution.get(inst.generatorParameters[i]);
137 if(parameter == null)
138 parameter = inst.generatorParameters[i]; // TODO Is this correct?
139 parameters[i] = parameter;
141 reductions.add(new Reduction(new ELiteral(inst.generator), parameters, demands));
143 substitution.clear();
145 //System.out.println(constraint.typeClass + " -> " + reductions.size());
146 if(reductions.size() == 1)
147 return reductions.get(0);
148 else if(reductions.size() > 1) {
149 StringBuilder b = new StringBuilder();
150 b.append("Found more than one matching instances for ").append(constraint.typeClass).append(": ");
151 boolean first = true;
152 for(Reduction reduction : reductions) {
157 b.append(reduction.generator);
159 compilationContext.errorLog.log(location, b.toString());