]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/elaboration/constraints/ConstraintEnvironment.java
Fixed leftover problems in unification of *Array and Vector types
[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.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;
25
26 import gnu.trove.map.hash.THashMap;
27
28 public class ConstraintEnvironment {
29     CompilationContext compilationContext;
30     Environment environment;
31     
32     public ConstraintEnvironment(CompilationContext compilationContext) {
33         this.compilationContext = compilationContext;
34         this.environment = compilationContext.environment;
35     }
36
37     public Superconstraint[] getSuperconstraints(TPred constraint) {
38         TypeClass tc = environment.getTypeClass(constraint.typeClass);
39         if(tc == null) {
40             throw new InternalCompilerError("Didn't find constraint " + constraint + ". Maybe Prelude is not loaded?");
41         }
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),
48                     tc.superGenerators[i]
49                     );
50         }
51         return result;
52     }
53         
54     public Reduction reduce(long location, TPred constraint) {
55         // VecComp
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);
61         }
62         // Serializable
63         if(constraint.typeClass == Types.SERIALIZABLE)
64             return ReduceSerializable.reduceSerializable(constraint.parameters[0]);
65         
66         // Typeable
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;                        
71                 return new Reduction(
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);
77             }
78             else if(parameter instanceof TApply) {
79                 TApply apply = (TApply)parameter;
80                 return new Reduction(
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),
85                         });
86             }
87             else if(parameter instanceof TFun) {
88                 TFun fun = (TFun)parameter;
89                 return new Reduction(
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)
95                         });
96             }
97             else if(parameter instanceof TUnion) {
98                 TUnion union = (TUnion)parameter;
99                 
100                 if(union.effects.length == 0)
101                     return new Reduction(
102                             new EConstant(Builtins.INSTANCE.getValue("TPure")),
103                             Type.EMPTY_ARRAY,
104                             TPred.EMPTY_ARRAY);
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])
111                             });
112                 }
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])
120                             });
121                 }
122             }
123         }
124         
125         // Standard case
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);
133                 }
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;
140                 }
141                 reductions.add(new Reduction(new ELiteral(inst.generator), parameters, demands));
142             }
143             substitution.clear();
144         }
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) {
153                 if(first)
154                     first = false;
155                 else
156                     b.append(", ");
157                 b.append(reduction.generator);
158             }
159             compilationContext.errorLog.log(location, b.toString());
160         }
161         return null;
162     }
163 }