]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/elaboration/constraints/ConstraintEnvironment.java
Merge "List the unsatisfied dependencies in CanvasContext"
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / internal / elaboration / constraints / ConstraintEnvironment.java
1 package org.simantics.scl.compiler.internal.elaboration.constraints;
2
3 import java.util.ArrayList;
4
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;
24
25 import gnu.trove.map.hash.THashMap;
26
27 public class ConstraintEnvironment {
28     Environment environment;
29     
30     public ConstraintEnvironment(Environment environment) {
31         this.environment = environment;
32     }
33
34     public Superconstraint[] getSuperconstraints(TPred constraint) {
35         TypeClass tc = environment.getTypeClass(constraint.typeClass);
36         if(tc == null) {
37             throw new InternalCompilerError("Didn't find constraint " + constraint + ". Maybe Prelude is not loaded?");
38         }
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),
45                     tc.superGenerators[i]
46                     );
47         }
48         return result;
49     }
50         
51     public Reduction reduce(TPred constraint) {
52         // VecComp
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);
58         }
59         // Serializable
60         if(constraint.typeClass == Types.SERIALIZABLE)
61             return ReduceSerializable.reduceSerializable(constraint.parameters[0]);
62         
63         // Typeable
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;                        
68                 return new Reduction(
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);
74             }
75             else if(parameter instanceof TApply) {
76                 TApply apply = (TApply)parameter;
77                 return new Reduction(
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),
82                         });
83             }
84             else if(parameter instanceof TFun) {
85                 TFun fun = (TFun)parameter;
86                 return new Reduction(
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)
92                         });
93             }
94             else if(parameter instanceof TUnion) {
95                 TUnion union = (TUnion)parameter;
96                 
97                 if(union.effects.length == 0)
98                     return new Reduction(
99                             new EConstant(Builtins.INSTANCE.getValue("TPure")),
100                             Type.EMPTY_ARRAY,
101                             TPred.EMPTY_ARRAY);
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])
108                             });
109                 }
110             }
111         }
112         
113         // Standard case
114         THashMap<TVar, Type> substitution = new THashMap<TVar, Type>();
115         ArrayList<Reduction> reductions = new ArrayList<Reduction>(1); 
116         for(TypeClassInstance inst : environment.getInstances(constraint.typeClass)) {
117             if(Types.match(inst.instance, constraint, substitution)) {
118                 TPred[] demands = new TPred[inst.context.length];
119                 for(int i=0;i<demands.length;++i) {
120                     demands[i] = (TPred)inst.context[i].replace(substitution);
121                 }
122                 Type[] parameters = new Type[inst.generatorParameters.length];
123                 for(int i=0;i<parameters.length;++i) {
124                     Type parameter = substitution.get(inst.generatorParameters[i]);
125                     if(parameter == null)
126                         parameter = inst.generatorParameters[i]; // TODO Is this correct?
127                     parameters[i] = parameter;
128                 }
129                 reductions.add(new Reduction(new ELiteral(inst.generator), parameters, demands));
130             }
131             substitution.clear();
132         }
133         //System.out.println(constraint.typeClass + " -> " + reductions.size());
134         if(reductions.size() == 1)
135             return reductions.get(0);
136         else if(reductions.size() > 1) {
137             throw new InternalCompilerError("Found more than one matching instances for " + constraint.typeClass + ".");
138         }
139         return null;
140     }
141 }