]> gerrit.simantics Code Review - simantics/platform.git/blob
ba982b1c6ab14c8fe886e318e471e42d4af54594
[simantics/platform.git] /
1 package org.simantics.scl.compiler.internal.elaboration.constraints;
2
3 import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
4 import org.simantics.scl.compiler.constants.ClassConstant;
5 import org.simantics.scl.compiler.constants.StringConstant;
6 import org.simantics.scl.compiler.elaboration.expressions.EApply;
7 import org.simantics.scl.compiler.elaboration.expressions.EConstant;
8 import org.simantics.scl.compiler.elaboration.expressions.ELiteral;
9 import org.simantics.scl.compiler.elaboration.java.Builtins;
10 import org.simantics.scl.compiler.elaboration.modules.TypeClass;
11 import org.simantics.scl.compiler.elaboration.modules.TypeClassInstance;
12 import org.simantics.scl.compiler.environment.Environment;
13 import org.simantics.scl.compiler.errors.Locations;
14 import org.simantics.scl.compiler.types.TApply;
15 import org.simantics.scl.compiler.types.TCon;
16 import org.simantics.scl.compiler.types.TFun;
17 import org.simantics.scl.compiler.types.TPred;
18 import org.simantics.scl.compiler.types.TUnion;
19 import org.simantics.scl.compiler.types.TVar;
20 import org.simantics.scl.compiler.types.Type;
21 import org.simantics.scl.compiler.types.Types;
22
23 import gnu.trove.map.hash.THashMap;
24
25 public class ConstraintEnvironment {
26     Environment environment;
27     
28     public ConstraintEnvironment(Environment environment) {
29         this.environment = environment;
30     }
31
32     public Superconstraint[] getSuperconstraints(TPred constraint) {
33         TypeClass tc = environment.getTypeClass(constraint.typeClass);
34         if(tc == null) {
35             throw new InternalCompilerError("Didn't find constraint " + constraint + ". Maybe Prelude is not loaded?");
36         }
37         if(tc.context.length == 0)
38             return Superconstraint.EMPTY_ARRAY;
39         Superconstraint[] result = new Superconstraint[tc.context.length];
40         for(int i=0;i<result.length;++i) {
41             result[i] = new Superconstraint(
42                     (TPred)tc.context[i].replace(tc.parameters, constraint.parameters),
43                     tc.superGenerators[i]
44                     );
45         }
46         return result;
47     }
48         
49     public Reduction reduce(TPred constraint) {
50         // VecComp
51         if(constraint.typeClass == Types.VEC_COMP) {
52             Type parameter = Types.canonical(constraint.parameters[0]);
53             if(parameter.isGround())
54                 return new Reduction(new ELiteral(new ClassConstant(Types.pred(Types.VEC_COMP, parameter), parameter)),
55                         Type.EMPTY_ARRAY, TPred.EMPTY_ARRAY);
56         }
57         // Serializable
58         if(constraint.typeClass == Types.SERIALIZABLE)
59             return ReduceSerializable.reduceSerializable(constraint.parameters[0]);
60         
61         // Typeable
62         else if(constraint.typeClass == Types.TYPEABLE) {
63             Type parameter = Types.canonical(constraint.parameters[0]);
64             if(parameter instanceof TCon) {
65                 TCon con = (TCon)parameter;                        
66                 return new Reduction(
67                         new EApply(Locations.NO_LOCATION,
68                                 new EConstant(Builtins.INSTANCE.getValue("TCon")),
69                                 new ELiteral(new StringConstant(con.module)),
70                                 new ELiteral(new StringConstant(con.name))),
71                                 Type.EMPTY_ARRAY, TPred.EMPTY_ARRAY);
72             }
73             else if(parameter instanceof TApply) {
74                 TApply apply = (TApply)parameter;
75                 return new Reduction(
76                         new EConstant(Builtins.INSTANCE.getValue("TApply")),
77                         Type.EMPTY_ARRAY, new TPred[] {
78                             Types.pred(Types.TYPEABLE, apply.function),
79                             Types.pred(Types.TYPEABLE, apply.parameter),
80                         });
81             }
82             else if(parameter instanceof TFun) {
83                 TFun fun = (TFun)parameter;
84                 return new Reduction(
85                         new EConstant(Builtins.INSTANCE.getValue("TFun")),
86                         Type.EMPTY_ARRAY, new TPred[] {
87                             Types.pred(Types.TYPEABLE, fun.domain),
88                             Types.pred(Types.TYPEABLE, fun.effect),
89                             Types.pred(Types.TYPEABLE, fun.range)
90                         });
91             }
92             else if(parameter instanceof TUnion) {
93                 TUnion union = (TUnion)parameter;
94                 
95                 /*TPred[] demands = new TPred[union.effects.length];
96                 for(int i=0;i<union.effects.length;++i)
97                     demands[i] = Types.pred(Types.TYPEABLE, union.effects[i]);*/
98                 if(union.effects.length == 0)
99                 return new Reduction(
100                             new EConstant(Builtins.INSTANCE.getValue("TPure")),
101                             Type.EMPTY_ARRAY,
102                             TPred.EMPTY_ARRAY);
103             }
104         }
105         
106         // Standard case
107         THashMap<TVar, Type> substitution = new THashMap<TVar, Type>(); 
108         for(TypeClassInstance inst : environment.getInstances(constraint.typeClass)) {
109             if(Types.match(inst.instance, constraint, substitution)) {
110                 TPred[] demands = new TPred[inst.context.length];
111                 for(int i=0;i<demands.length;++i) {
112                     demands[i] = (TPred)inst.context[i].replace(substitution);
113                 }
114                 Type[] parameters = new Type[inst.generatorParameters.length];
115                 for(int i=0;i<parameters.length;++i) {
116                     Type parameter = substitution.get(inst.generatorParameters[i]);
117                     if(parameter == null)
118                         parameter = inst.generatorParameters[i]; // TODO Is this correct?
119                     parameters[i] = parameter;
120                 }
121                 return new Reduction(new ELiteral(inst.generator), parameters, demands);
122             }
123             else
124                 substitution.clear();
125         }
126         return null;
127     }
128 }