]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/contexts/SimplificationContext.java
e983e1277e0a93f27ab0964e3083ecf588583531
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / elaboration / contexts / SimplificationContext.java
1 package org.simantics.scl.compiler.elaboration.contexts;
2
3 import gnu.trove.list.array.TLongArrayList;
4 import gnu.trove.map.hash.THashMap;
5
6 import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
7 import org.simantics.scl.compiler.common.names.Name;
8 import org.simantics.scl.compiler.constants.Constant;
9 import org.simantics.scl.compiler.elaboration.expressions.Case;
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.EError;
13 import org.simantics.scl.compiler.elaboration.expressions.EIf;
14 import org.simantics.scl.compiler.elaboration.expressions.ELambda;
15 import org.simantics.scl.compiler.elaboration.expressions.ELiteral;
16 import org.simantics.scl.compiler.elaboration.expressions.EMatch;
17 import org.simantics.scl.compiler.elaboration.expressions.ESimpleLambda;
18 import org.simantics.scl.compiler.elaboration.expressions.EVariable;
19 import org.simantics.scl.compiler.elaboration.expressions.Expression;
20 import org.simantics.scl.compiler.elaboration.expressions.Variable;
21 import org.simantics.scl.compiler.elaboration.java.Builtins;
22 import org.simantics.scl.compiler.elaboration.modules.SCLValue;
23 import org.simantics.scl.compiler.environment.Environment;
24 import org.simantics.scl.compiler.errors.ErrorLog;
25 import org.simantics.scl.compiler.errors.Locations;
26 import org.simantics.scl.compiler.internal.codegen.types.JavaReferenceValidator;
27 import org.simantics.scl.compiler.internal.codegen.types.JavaTypeTranslator;
28 import org.simantics.scl.compiler.types.Type;
29 import org.simantics.scl.compiler.types.Types;
30 import org.simantics.scl.compiler.types.exceptions.MatchException;
31 import org.simantics.scl.compiler.types.util.MultiFunction;
32
33 public class SimplificationContext implements EnvironmentalContext {
34     Environment environment;
35     ErrorLog errorLog;
36     
37     public static final Name MAP_LIST = Name.create("Prelude", "mapList");
38     public static final Name GUARD_LIST = Name.create("Prelude", "guardList");
39     public static final Name CONCAT_MAP = Name.create("Prelude", "concatMap");
40     public static final Name EMPTY_LIST = Name.create("Prelude", "emptyList");
41     public static final Name SINGLETON_LIST = Name.create("Prelude", "singletonList");    
42     public static final Name APPEND_LIST = Name.create("Prelude", "appendList");
43     public static final Name ADD_LIST = Name.create("Prelude", "addList");
44     public static final Name FROM_INTEGER = Name.create("Prelude", "fromInteger");
45     public static final Name FROM_DOUBLE = Name.create("Prelude", "fromDouble");
46     
47     THashMap<Name, SCLValue> constants = new THashMap<Name, SCLValue>();
48     THashMap<Variable, Expression> inlinedVariables = new THashMap<Variable, Expression>();
49     
50     TLongArrayList locatableStack = new TLongArrayList();
51     long locatable;
52     JavaTypeTranslator javaTypeTranslator;
53     JavaReferenceValidator<?, ?, ?, ?> validator;
54     
55     public SimplificationContext(Environment environment, ErrorLog errorLog, 
56             JavaTypeTranslator javaTypeTranslator, JavaReferenceValidator<?, ?, ?, ?> validator) {
57         this.environment = environment;
58         this.errorLog = errorLog;
59         this.javaTypeTranslator = javaTypeTranslator;
60         this.validator = validator;         
61     }
62     
63     public Environment getEnvironment() {
64         return environment;
65     }
66     
67     public ErrorLog getErrorLog() {
68         return errorLog;
69     }
70     
71     public void pushLocation(long loc) {
72         locatableStack.add(locatable);
73         locatable = loc;
74     }
75     
76     public void popLocation() {
77         locatable = locatableStack.removeAt(locatableStack.size()-1);
78     }
79     
80     public SCLValue getValue(Name name) {
81         if(constants.containsKey(name))
82             return constants.get(name);
83         SCLValue value = environment.getValue(name);
84         if(value == null)
85             errorLog.log(locatable, "Couldn't find " + name + ".");
86         constants.put(name, value);
87         return value;
88     }
89     
90     public Expression getConstant(Name name, Type ... typeParameters) {
91         SCLValue value = getValue(name);
92         if(value == null)
93             return new EError(locatable);
94         return new EConstant(value, typeParameters);
95     }
96     
97     public Expression apply(Expression f, Expression ... ps) {
98         Expression result = f;
99         Type type = f.getType();
100         for(Expression p : ps) {
101             result = new EApply(locatable, result, p);
102             MultiFunction mfun;
103             try {
104                 mfun = Types.matchFunction(type, 1);
105             } catch (MatchException e) {
106                 throw new InternalCompilerError(e);
107             }
108             type = mfun.returnType;
109             result.setType(type);
110         }
111         return result;
112     }
113     
114     public Expression tuple(Expression ... cs) {
115         if(cs.length == 1)
116             return cs[0];
117         Type[] typeParameters = new Type[cs.length];
118         for(int i=0;i<cs.length;++i)
119             typeParameters[i] = cs[i].getType();
120         Expression result = new EConstant(locatable, Builtins.TUPLE_CONSTRUCTORS[cs.length], typeParameters);
121         for(Expression c : cs)
122             result = new EApply(locatable, result, c);
123         result.setType(Types.tuple(Types.getTypes(cs)));
124         return result;
125     }
126
127     public Expression var(Variable var) {
128         EVariable result =  new EVariable(locatable, var);
129         result.setType(var.getType());
130         return result;
131     }
132     
133     public Expression simpleLambda(Variable var, Expression val) {
134         ESimpleLambda result = new ESimpleLambda(var, val);
135         result.setType(Types.function(var.getType(), val.getType()));
136         return result;
137     }
138     
139     public Expression lambda(Expression pat, Expression val) {
140         return new ELambda(locatable,  pat, val);
141     }
142     
143     public Expression lambda(Case ... cases) {
144         return new ELambda(locatable, cases);
145     }
146     
147     /*
148     public Expression constant(SCLValue value) {
149         Expression result = new EConstant(loc, value);
150         result.setType(value.getType());
151         return result;
152     }
153     
154     public Expression constant(SCLValue value, Type ... typeParameters) {
155         Expression result = constant(value);
156         for(Type typeParameter : typeParameters)
157             result = new EApplyType(loc, result, typeParameter);
158         result.setType(Types.instantiate(value.getType(), typeParameters));
159         return result;
160     }
161     */
162     
163     public Expression if_(Expression condition, Expression then_, Expression else_) {
164         return new EIf(locatable, condition, then_, else_);
165     }
166     
167     public Expression mapList(Expression f, Expression l) {
168         try {
169             MultiFunction mfun = Types.matchFunction(f.getType(), 1);
170             return apply(getConstant(MAP_LIST, new Type[] {mfun.parameterTypes[0], mfun.returnType}), f, l);
171         } catch (MatchException e) {
172             throw new InternalCompilerError(e);
173         }
174     }
175     
176     public Expression guardList(Expression cond) {
177         return apply(getConstant(GUARD_LIST), cond);
178     }
179
180     public Expression concatMap(Expression f, Expression l) {
181         try {
182             MultiFunction mfun = Types.matchFunction(f.getType(), 1);
183             return apply(getConstant(CONCAT_MAP, new Type[] {
184                     mfun.parameterTypes[0], mfun.effect,
185                     Types.matchApply(Types.LIST, mfun.returnType)}
186             ), f, l);
187         } catch (MatchException e) {
188             throw new InternalCompilerError(e);
189         }
190     }
191     
192     public Expression emptyList(Type type) {
193         return getConstant(EMPTY_LIST, type);
194     }
195     
196     public Expression singletonList(Expression e) {
197         return apply(getConstant(SINGLETON_LIST, e.getType()), e);
198     }
199
200     public Expression match(Expression scrutinee, Expression pattern, Expression value) {
201         Case case_ = new Case(pattern, value);
202         return new EMatch(scrutinee, new Case[] { case_ });        
203     }
204     
205     public Expression match(Expression scrutinee, Case ... cases) {
206         return new EMatch(scrutinee, cases);
207     }
208
209     public Expression literal(Constant constant) {
210         return new ELiteral(constant);
211     }
212     
213     @SuppressWarnings({ "unchecked" })
214     public JavaReferenceValidator<Object,Object,Object,Object> getJavaReferenceValidator() {
215         return (JavaReferenceValidator<Object,Object,Object,Object>)validator;
216     }
217     
218     public JavaTypeTranslator getJavaTypeTranslator() {
219         return javaTypeTranslator;
220     }
221
222     /**
223      * Variable added to the context will be inlined to the
224      * given expression in subsequent simplifications. It is assumed
225      * that the value is already simplified.
226      */
227     public void addInlinedVariable(Variable variable, Expression value) {
228         inlinedVariables.put(variable, value);        
229     }
230
231     public Expression getInlinedValue(Variable variable) {
232         return inlinedVariables.get(variable);
233     }
234
235     public EVariable blank() {
236         return new EVariable(new Variable("_"));
237     }
238
239     public Expression conditionalExecution(Expression condition, Expression continuation) {
240         return new EIf(condition, continuation, new EConstant(Builtins.TUPLE_CONSTRUCTORS[0]));
241     }
242     
243     public Expression iteratedExecution(Expression list, Variable variable, Expression continuation) {
244         return new EApply(
245                 Locations.NO_LOCATION,
246                 Types.PROC,
247                 getConstant(Name.create("Prelude", "iterList"), variable.getType(), Types.PROC, Types.tupleConstructor(0)),
248                 new Expression[] {
249                     new ESimpleLambda(Types.PROC, variable, continuation), 
250                     list
251                 }
252                 );
253     }
254
255     public Expression iteratedVectorExecution(EApply vector, Variable variable,
256             Expression continuation) {
257         return new EApply(
258                 Locations.NO_LOCATION,
259                 Types.PROC,
260                 getConstant(Name.create("Vector", "iterVector"), variable.getType(), Types.PROC, Types.tupleConstructor(0)),
261                 new Expression[] {
262                     new ESimpleLambda(Types.PROC, variable, continuation), 
263                     vector
264                 }
265                 );
266     }
267
268     public Expression[] vars(Variable[] parameters) {
269         Expression[] result = new Expression[parameters.length];
270         for(int i=0;i<parameters.length;++i)
271             result[i] = new EVariable(parameters[i]);
272         return result;
273     }
274 }