1 package org.simantics.scl.compiler.internal.elaboration.constraints;
3 import gnu.trove.map.hash.THashMap;
5 import org.cojen.classfile.TypeDesc;
6 import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
7 import org.simantics.scl.compiler.constants.ClassConstant;
8 import org.simantics.scl.compiler.constants.JavaConstructor;
9 import org.simantics.scl.compiler.constants.JavaStaticField;
10 import org.simantics.scl.compiler.constants.JavaStaticMethod;
11 import org.simantics.scl.compiler.constants.StringConstant;
12 import org.simantics.scl.compiler.elaboration.expressions.EApply;
13 import org.simantics.scl.compiler.elaboration.expressions.EConstant;
14 import org.simantics.scl.compiler.elaboration.expressions.ELiteral;
15 import org.simantics.scl.compiler.elaboration.java.Builtins;
16 import org.simantics.scl.compiler.elaboration.modules.TypeClass;
17 import org.simantics.scl.compiler.elaboration.modules.TypeClassInstance;
18 import org.simantics.scl.compiler.environment.Environment;
19 import org.simantics.scl.compiler.errors.Locations;
20 import org.simantics.scl.compiler.types.TApply;
21 import org.simantics.scl.compiler.types.TCon;
22 import org.simantics.scl.compiler.types.TFun;
23 import org.simantics.scl.compiler.types.TPred;
24 import org.simantics.scl.compiler.types.TUnion;
25 import org.simantics.scl.compiler.types.TVar;
26 import org.simantics.scl.compiler.types.Type;
27 import org.simantics.scl.compiler.types.Types;
29 public class ConstraintEnvironment {
30 Environment environment;
32 public ConstraintEnvironment(Environment environment) {
33 this.environment = environment;
36 public Superconstraint[] getSuperconstraints(TPred constraint) {
37 TypeClass tc = environment.getTypeClass(constraint.typeClass);
39 throw new InternalCompilerError("Didn't find constraint " + constraint + ". Maybe Prelude is not loaded?");
41 if(tc.context.length == 0)
42 return Superconstraint.EMPTY_ARRAY;
43 Superconstraint[] result = new Superconstraint[tc.context.length];
44 for(int i=0;i<result.length;++i) {
45 result[i] = new Superconstraint(
46 (TPred)tc.context[i].replace(tc.parameters, constraint.parameters),
53 private static final Type SERIALIZABLE_BOOLEAN = Types.pred(Types.SERIALIZABLE, Types.BOOLEAN);
54 private static final Type SERIALIZABLE_BYTE = Types.pred(Types.SERIALIZABLE, Types.BYTE);
55 private static final Type SERIALIZABLE_SHORT = Types.pred(Types.SERIALIZABLE, Types.SHORT);
56 private static final Type SERIALIZABLE_INTEGER = Types.pred(Types.SERIALIZABLE, Types.INTEGER);
57 private static final Type SERIALIZABLE_LONG = Types.pred(Types.SERIALIZABLE, Types.LONG);
58 private static final Type SERIALIZABLE_FLOAT = Types.pred(Types.SERIALIZABLE, Types.FLOAT);
59 private static final Type SERIALIZABLE_DOUBLE = Types.pred(Types.SERIALIZABLE, Types.DOUBLE);
60 private static final Type SERIALIZABLE_STRING = Types.pred(Types.SERIALIZABLE, Types.STRING);
62 private static final Type SERIALIZABLE_BOOLEAN_ARRAY = Types.pred(Types.SERIALIZABLE, Types.BOOLEAN_ARRAY);
63 private static final Type SERIALIZABLE_BYTE_ARRAY = Types.pred(Types.SERIALIZABLE, Types.BYTE_ARRAY);
64 private static final Type SERIALIZABLE_SHORT_ARRAY = Types.pred(Types.SERIALIZABLE, Types.SHORT_ARRAY);
65 private static final Type SERIALIZABLE_INTEGER_ARRAY = Types.pred(Types.SERIALIZABLE, Types.INTEGER_ARRAY);
66 private static final Type SERIALIZABLE_LONG_ARRAY = Types.pred(Types.SERIALIZABLE, Types.LONG_ARRAY);
67 private static final Type SERIALIZABLE_FLOAT_ARRAY = Types.pred(Types.SERIALIZABLE, Types.FLOAT_ARRAY);
68 private static final Type SERIALIZABLE_DOUBLE_ARRAY = Types.pred(Types.SERIALIZABLE, Types.DOUBLE_ARRAY);
70 private static final Type SERIALIZABLE_BOOLEAN_VECTOR = Types.pred(Types.SERIALIZABLE, Types.pred(Types.VECTOR, Types.BOOLEAN));
71 private static final Type SERIALIZABLE_BYTE_VECTOR = Types.pred(Types.SERIALIZABLE, Types.pred(Types.VECTOR, Types.BYTE));
72 private static final Type SERIALIZABLE_SHORT_VECTOR = Types.pred(Types.SERIALIZABLE, Types.pred(Types.VECTOR, Types.SHORT));
73 private static final Type SERIALIZABLE_INTEGER_VECTOR = Types.pred(Types.SERIALIZABLE, Types.pred(Types.VECTOR, Types.INTEGER));
74 private static final Type SERIALIZABLE_LONG_VECTOR = Types.pred(Types.SERIALIZABLE, Types.pred(Types.VECTOR, Types.LONG));
75 private static final Type SERIALIZABLE_FLOAT_VECTOR = Types.pred(Types.SERIALIZABLE, Types.pred(Types.VECTOR, Types.FLOAT));
76 private static final Type SERIALIZABLE_DOUBLE_VECTOR = Types.pred(Types.SERIALIZABLE, Types.pred(Types.VECTOR, Types.DOUBLE));
78 private static final Type SERIALIZABLE_TUPLE0 = Types.pred(Types.SERIALIZABLE, Types.tuple());
79 private static final Type SERIALIZABLE_VARIANT = Types.pred(Types.SERIALIZABLE, Types.VARIANT);
81 public Reduction reduce(TPred constraint) {
83 if(constraint.typeClass == Types.VEC_COMP) {
84 Type parameter = Types.canonical(constraint.parameters[0]);
85 if(parameter.isGround())
86 return new Reduction(new ELiteral(new ClassConstant(Types.pred(Types.VEC_COMP, parameter), parameter)),
87 Type.EMPTY_ARRAY, TPred.EMPTY_ARRAY);
90 if(constraint.typeClass == Types.SERIALIZABLE) {
91 Type parameter = Types.canonical(constraint.parameters[0]);
92 if(parameter instanceof TCon) {
93 TCon con = (TCon)parameter;
94 if(con == Types.DOUBLE)
96 new ELiteral(new JavaStaticField("org/simantics/databoard/Bindings", "DOUBLE", Types.NO_EFFECTS, TypeDesc.forClass("org/simantics/databoard/binding/DoubleBinding"), SERIALIZABLE_DOUBLE, -1)),
97 Type.EMPTY_ARRAY, TPred.EMPTY_ARRAY);
98 else if(con == Types.STRING)
100 new ELiteral(new JavaStaticField("org/simantics/databoard/Bindings", "STRING", Types.NO_EFFECTS, TypeDesc.forClass("org/simantics/databoard/binding/StringBinding"), SERIALIZABLE_STRING, -1)),
101 Type.EMPTY_ARRAY, TPred.EMPTY_ARRAY);
102 else if(con == Types.INTEGER)
103 return new Reduction(
104 new ELiteral(new JavaStaticField("org/simantics/databoard/Bindings", "INTEGER", Types.NO_EFFECTS, TypeDesc.forClass("org/simantics/databoard/binding/IntegerBinding"), SERIALIZABLE_INTEGER, -1)),
105 Type.EMPTY_ARRAY, TPred.EMPTY_ARRAY);
106 else if(con == Types.BOOLEAN)
107 return new Reduction(
108 new ELiteral(new JavaStaticField("org/simantics/databoard/Bindings", "BOOLEAN", Types.NO_EFFECTS, TypeDesc.forClass("org/simantics/databoard/binding/BooleanBinding"), SERIALIZABLE_BOOLEAN, -1)),
109 Type.EMPTY_ARRAY, TPred.EMPTY_ARRAY);
110 else if(con == Types.BYTE)
111 return new Reduction(
112 new ELiteral(new JavaStaticField("org/simantics/databoard/Bindings", "BYTE", Types.NO_EFFECTS, TypeDesc.forClass("org/simantics/databoard/binding/ByteBinding"), SERIALIZABLE_BYTE, -1)),
113 Type.EMPTY_ARRAY, TPred.EMPTY_ARRAY);
114 else if(con == Types.FLOAT)
115 return new Reduction(
116 new ELiteral(new JavaStaticField("org/simantics/databoard/Bindings", "FLOAT", Types.NO_EFFECTS, TypeDesc.forClass("org/simantics/databoard/binding/FloatBinding"), SERIALIZABLE_FLOAT, -1)),
117 Type.EMPTY_ARRAY, TPred.EMPTY_ARRAY);
118 else if(con == Types.LONG)
119 return new Reduction(
120 new ELiteral(new JavaStaticField("org/simantics/databoard/Bindings", "LONG", Types.NO_EFFECTS, TypeDesc.forClass("org/simantics/databoard/binding/LongBinding"), SERIALIZABLE_LONG, -1)),
121 Type.EMPTY_ARRAY, TPred.EMPTY_ARRAY);
122 else if(con == Types.tupleConstructor(0))
123 return new Reduction(
124 new ELiteral(new JavaStaticField("org/simantics/databoard/Bindings", "VOID", Types.NO_EFFECTS, TypeDesc.forClass("org/simantics/databoard/binding/Binding"), SERIALIZABLE_TUPLE0, -1)),
125 Type.EMPTY_ARRAY, TPred.EMPTY_ARRAY);
126 else if(con == Types.VARIANT)
127 return new Reduction(
128 new ELiteral(new JavaStaticField("org/simantics/databoard/Bindings", "VARIANT", Types.NO_EFFECTS, TypeDesc.forClass("org/simantics/databoard/binding/VariantBinding"), SERIALIZABLE_VARIANT, -1)),
129 Type.EMPTY_ARRAY, TPred.EMPTY_ARRAY);
130 else if(con == Types.DOUBLE_ARRAY)
131 return new Reduction(
132 new ELiteral(new JavaStaticField("org/simantics/databoard/Bindings", "DOUBLE_ARRAY", Types.NO_EFFECTS, TypeDesc.forClass("org/simantics/databoard/binding/ArrayBinding"), SERIALIZABLE_DOUBLE_ARRAY, -1)),
133 Type.EMPTY_ARRAY, TPred.EMPTY_ARRAY);
134 else if(con == Types.INTEGER_ARRAY)
135 return new Reduction(
136 new ELiteral(new JavaStaticField("org/simantics/databoard/Bindings", "INTEGER_ARRAY", Types.NO_EFFECTS, TypeDesc.forClass("org/simantics/databoard/binding/ArrayBinding"), SERIALIZABLE_INTEGER_ARRAY, -1)),
137 Type.EMPTY_ARRAY, TPred.EMPTY_ARRAY);
138 else if(con == Types.BOOLEAN_ARRAY)
139 return new Reduction(
140 new ELiteral(new JavaStaticField("org/simantics/databoard/Bindings", "BOOLEAN_ARRAY", Types.NO_EFFECTS, TypeDesc.forClass("org/simantics/databoard/binding/ArrayBinding"), SERIALIZABLE_BOOLEAN_ARRAY, -1)),
141 Type.EMPTY_ARRAY, TPred.EMPTY_ARRAY);
142 else if(con == Types.BYTE_ARRAY)
143 return new Reduction(
144 new ELiteral(new JavaStaticField("org/simantics/databoard/Bindings", "BYTE_ARRAY", Types.NO_EFFECTS, TypeDesc.forClass("org/simantics/databoard/binding/ArrayBinding"), SERIALIZABLE_BYTE_ARRAY, -1)),
145 Type.EMPTY_ARRAY, TPred.EMPTY_ARRAY);
146 else if(con == Types.FLOAT_ARRAY)
147 return new Reduction(
148 new ELiteral(new JavaStaticField("org/simantics/databoard/Bindings", "FLOAT_ARRAY", Types.NO_EFFECTS, TypeDesc.forClass("org/simantics/databoard/binding/ArrayBinding"), SERIALIZABLE_FLOAT_ARRAY, -1)),
149 Type.EMPTY_ARRAY, TPred.EMPTY_ARRAY);
150 else if(con == Types.LONG_ARRAY)
151 return new Reduction(
152 new ELiteral(new JavaStaticField("org/simantics/databoard/Bindings", "LONG_ARRAY", Types.NO_EFFECTS, TypeDesc.forClass("org/simantics/databoard/binding/ArrayBinding"), SERIALIZABLE_LONG_ARRAY, -1)),
153 Type.EMPTY_ARRAY, TPred.EMPTY_ARRAY);
155 else if(parameter instanceof TApply) {
156 TApply apply1 = (TApply)parameter;
157 Type f1 = Types.canonical(apply1.function);
158 Type p1 = Types.canonical(apply1.parameter);
159 if(f1 instanceof TCon) {
161 if(con == Types.LIST)
162 return new Reduction(
163 new ELiteral(new JavaConstructor("org/simantics/databoard/binding/impl/ArrayListBinding", Types.NO_EFFECTS,
164 Types.pred(Types.SERIALIZABLE, Types.list(p1)), Types.pred(Types.SERIALIZABLE, p1))),
165 Type.EMPTY_ARRAY, new TPred[] { Types.pred(Types.SERIALIZABLE, p1) });
166 else if(con == Types.MAYBE)
167 return new Reduction(
168 new ELiteral(new JavaConstructor("org/simantics/databoard/binding/impl/OptionalBindingDefault", Types.NO_EFFECTS,
169 Types.pred(Types.SERIALIZABLE, Types.apply(Types.MAYBE, p1)), Types.pred(Types.SERIALIZABLE, p1))),
170 Type.EMPTY_ARRAY, new TPred[] { Types.pred(Types.SERIALIZABLE, p1) });
171 else if(con == Types.VECTOR) {
172 if (p1 == Types.DOUBLE)
173 return new Reduction(
174 new ELiteral(new JavaStaticField("org/simantics/databoard/Bindings", "DOUBLE_ARRAY", Types.NO_EFFECTS, TypeDesc.forClass("org/simantics/databoard/binding/ArrayBinding"), SERIALIZABLE_DOUBLE_VECTOR, -1)),
175 Type.EMPTY_ARRAY, TPred.EMPTY_ARRAY);
176 else if(p1 == Types.INTEGER)
177 return new Reduction(
178 new ELiteral(new JavaStaticField("org/simantics/databoard/Bindings", "INTEGER_ARRAY", Types.NO_EFFECTS, TypeDesc.forClass("org/simantics/databoard/binding/ArrayBinding"), SERIALIZABLE_INTEGER_VECTOR, -1)),
179 Type.EMPTY_ARRAY, TPred.EMPTY_ARRAY);
180 else if(p1 == Types.BOOLEAN)
181 return new Reduction(
182 new ELiteral(new JavaStaticField("org/simantics/databoard/Bindings", "BOOLEAN_ARRAY", Types.NO_EFFECTS, TypeDesc.forClass("org/simantics/databoard/binding/ArrayBinding"), SERIALIZABLE_BOOLEAN_VECTOR, -1)),
183 Type.EMPTY_ARRAY, TPred.EMPTY_ARRAY);
184 else if(p1 == Types.BYTE)
185 return new Reduction(
186 new ELiteral(new JavaStaticField("org/simantics/databoard/Bindings", "BYTE_ARRAY", Types.NO_EFFECTS, TypeDesc.forClass("org/simantics/databoard/binding/ArrayBinding"), SERIALIZABLE_BYTE_VECTOR, -1)),
187 Type.EMPTY_ARRAY, TPred.EMPTY_ARRAY);
188 else if(p1 == Types.FLOAT)
189 return new Reduction(
190 new ELiteral(new JavaStaticField("org/simantics/databoard/Bindings", "FLOAT_ARRAY", Types.NO_EFFECTS, TypeDesc.forClass("org/simantics/databoard/binding/ArrayBinding"), SERIALIZABLE_FLOAT_VECTOR, -1)),
191 Type.EMPTY_ARRAY, TPred.EMPTY_ARRAY);
192 else if(p1 == Types.LONG)
193 return new Reduction(
194 new ELiteral(new JavaStaticField("org/simantics/databoard/Bindings", "LONG_ARRAY", Types.NO_EFFECTS, TypeDesc.forClass("org/simantics/databoard/binding/ArrayBinding"), SERIALIZABLE_LONG_VECTOR, -1)),
195 Type.EMPTY_ARRAY, TPred.EMPTY_ARRAY);
197 return new Reduction(
198 new ELiteral(new JavaStaticMethod("org/simantics/databoard/Bindings", "getArrayBinding", Types.NO_EFFECTS,
199 Types.pred(Types.SERIALIZABLE, Types.pred(Types.VECTOR, p1)), Types.pred(Types.SERIALIZABLE, p1))),
200 Type.EMPTY_ARRAY, new TPred[] { Types.pred(Types.SERIALIZABLE, p1) });
203 else if(f1 instanceof TApply) {
204 TApply apply2 = (TApply)parameter;
205 Type f2 = Types.canonical(apply2.function);
206 Type p2 = Types.canonical(apply2.parameter);
207 if(f2 instanceof TCon) {
209 /*if(con == Types.tupleConstructor(2)) {
210 return new Reduction(
211 new EConstant(Builtins.TUPLE_CONSTRUCTORS[2]new JavaConstructor("org/simantics/databoard/binding/impl/ArrayListBinding", Types.NO_EFFECTS,
212 Types.pred(Types.SERIALIZABLE, p1), Types.pred(Types.SERIALIZABLE, Types.list(p1)))),
214 new TPred[] { Types.pred(Types.SERIALIZABLE, p2), Types.pred(Types.SERIALIZABLE, p1) });
220 // Default to a binding as an ObjectVariantBinding
221 // This can be applied only if the type is ground type (i.e. does not contain type variables),
222 // because otherwise the Serializable instance could be provided as a parameter to the function
223 if(parameter.isGround())
224 return new Reduction(
225 new ELiteral(new JavaStaticField("org/simantics/databoard/Bindings", "OBJECT", Types.NO_EFFECTS,
226 TypeDesc.forClass("org/simantics/databoard/binding/VariantBinding"), Types.pred(Types.SERIALIZABLE, parameter), -1)),
227 Type.EMPTY_ARRAY, TPred.EMPTY_ARRAY);
231 else if(constraint.typeClass == Types.TYPEABLE) {
232 Type parameter = Types.canonical(constraint.parameters[0]);
233 if(parameter instanceof TCon) {
234 TCon con = (TCon)parameter;
235 return new Reduction(
236 new EApply(Locations.NO_LOCATION,
237 new EConstant(Builtins.INSTANCE.getValue("TCon")),
238 new ELiteral(new StringConstant(con.module)),
239 new ELiteral(new StringConstant(con.name))),
240 Type.EMPTY_ARRAY, TPred.EMPTY_ARRAY);
242 else if(parameter instanceof TApply) {
243 TApply apply = (TApply)parameter;
244 return new Reduction(
245 new EConstant(Builtins.INSTANCE.getValue("TApply")),
246 Type.EMPTY_ARRAY, new TPred[] {
247 Types.pred(Types.TYPEABLE, apply.function),
248 Types.pred(Types.TYPEABLE, apply.parameter),
251 else if(parameter instanceof TFun) {
252 TFun fun = (TFun)parameter;
253 return new Reduction(
254 new EConstant(Builtins.INSTANCE.getValue("TFun")),
255 Type.EMPTY_ARRAY, new TPred[] {
256 Types.pred(Types.TYPEABLE, fun.domain),
257 Types.pred(Types.TYPEABLE, fun.effect),
258 Types.pred(Types.TYPEABLE, fun.range)
261 else if(parameter instanceof TUnion) {
262 TUnion union = (TUnion)parameter;
264 /*TPred[] demands = new TPred[union.effects.length];
265 for(int i=0;i<union.effects.length;++i)
266 demands[i] = Types.pred(Types.TYPEABLE, union.effects[i]);*/
267 if(union.effects.length == 0)
268 return new Reduction(
269 new EConstant(Builtins.INSTANCE.getValue("TPure")),
276 THashMap<TVar, Type> substitution = new THashMap<TVar, Type>();
277 for(TypeClassInstance inst : environment.getInstances(constraint.typeClass)) {
278 if(Types.match(inst.instance, constraint, substitution)) {
279 TPred[] demands = new TPred[inst.context.length];
280 for(int i=0;i<demands.length;++i) {
281 demands[i] = (TPred)inst.context[i].replace(substitution);
283 Type[] parameters = new Type[inst.generatorParameters.length];
284 for(int i=0;i<parameters.length;++i) {
285 Type parameter = substitution.get(inst.generatorParameters[i]);
286 if(parameter == null)
287 parameter = inst.generatorParameters[i]; // TODO Is this correct?
288 parameters[i] = parameter;
290 return new Reduction(new ELiteral(inst.generator), parameters, demands);
293 substitution.clear();