]> gerrit.simantics Code Review - simantics/platform.git/blob
82df9000799336691ccd77ad4287c8384cc64959
[simantics/platform.git] /
1 package org.simantics.scl.compiler.internal.elaboration.constraints;
2
3 import org.cojen.classfile.TypeDesc;
4 import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
5 import org.simantics.scl.compiler.constants.ClassConstant;
6 import org.simantics.scl.compiler.constants.JavaConstructor;
7 import org.simantics.scl.compiler.constants.JavaStaticField;
8 import org.simantics.scl.compiler.constants.JavaStaticMethod;
9 import org.simantics.scl.compiler.constants.StringConstant;
10 import org.simantics.scl.compiler.elaboration.expressions.EApply;
11 import org.simantics.scl.compiler.elaboration.expressions.EConstant;
12 import org.simantics.scl.compiler.elaboration.expressions.ELiteral;
13 import org.simantics.scl.compiler.elaboration.java.Builtins;
14 import org.simantics.scl.compiler.elaboration.modules.TypeClass;
15 import org.simantics.scl.compiler.elaboration.modules.TypeClassInstance;
16 import org.simantics.scl.compiler.environment.Environment;
17 import org.simantics.scl.compiler.errors.Locations;
18 import org.simantics.scl.compiler.types.TApply;
19 import org.simantics.scl.compiler.types.TCon;
20 import org.simantics.scl.compiler.types.TFun;
21 import org.simantics.scl.compiler.types.TPred;
22 import org.simantics.scl.compiler.types.TUnion;
23 import org.simantics.scl.compiler.types.TVar;
24 import org.simantics.scl.compiler.types.Type;
25 import org.simantics.scl.compiler.types.Types;
26
27 import gnu.trove.map.hash.THashMap;
28
29 public class ConstraintEnvironment {
30     Environment environment;
31     
32     public ConstraintEnvironment(Environment environment) {
33         this.environment = environment;
34     }
35
36     public Superconstraint[] getSuperconstraints(TPred constraint) {
37         TypeClass tc = environment.getTypeClass(constraint.typeClass);
38         if(tc == null) {
39             throw new InternalCompilerError("Didn't find constraint " + constraint + ". Maybe Prelude is not loaded?");
40         }
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),
47                     tc.superGenerators[i]
48                     );
49         }
50         return result;
51     }
52     
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);
61     
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);
69     
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));
77     
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);
80     
81     public Reduction reduce(TPred constraint) {
82         // VecComp
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);
88         }
89         // Serializable
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)
95                     return new Reduction(
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)
99                     return new Reduction(
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);
154             }
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) {
160                     TCon con = (TCon)f1;
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);
196                         else
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) });
201                     }
202                 }
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) {
208                         TCon con = (TCon)f2;
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)))),
213                                     Type.EMPTY_ARRAY, 
214                                     new TPred[] { Types.pred(Types.SERIALIZABLE, p2), Types.pred(Types.SERIALIZABLE, p1) });
215                         }*/
216                     }
217                 }
218             }
219             
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);
228         }
229         
230         // Typeable
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);
241             }
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),
249                         });
250             }
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)
259                         });
260             }
261             else if(parameter instanceof TUnion) {
262                 TUnion union = (TUnion)parameter;
263                 
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")),
270                             Type.EMPTY_ARRAY,
271                             TPred.EMPTY_ARRAY);
272             }
273         }
274         
275         // Standard case
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);
282                 }
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;
289                 }
290                 return new Reduction(new ELiteral(inst.generator), parameters, demands);
291             }
292             else
293                 substitution.clear();
294         }
295         return null;
296     }
297 }