]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ESimpleLambda.java
91de49eb2e3d455d0f93f777675f1d2df0daebb4
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / elaboration / expressions / ESimpleLambda.java
1 package org.simantics.scl.compiler.elaboration.expressions;
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.elaboration.contexts.ReplaceContext;
8 import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;
9 import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
10 import org.simantics.scl.compiler.elaboration.contexts.TypingContext;
11 import org.simantics.scl.compiler.errors.Locations;
12 import org.simantics.scl.compiler.internal.codegen.references.IVal;
13 import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;
14 import org.simantics.scl.compiler.internal.interpreted.IExpression;
15 import org.simantics.scl.compiler.internal.interpreted.ILambda;
16 import org.simantics.scl.compiler.top.ExpressionInterpretationContext;
17 import org.simantics.scl.compiler.top.SCLCompilerConfiguration;
18 import org.simantics.scl.compiler.types.Type;
19 import org.simantics.scl.compiler.types.Types;
20 import org.simantics.scl.compiler.types.exceptions.MatchException;
21 import org.simantics.scl.compiler.types.exceptions.UnificationException;
22 import org.simantics.scl.compiler.types.kinds.Kinds;
23 import org.simantics.scl.compiler.types.util.MultiFunction;
24
25 import gnu.trove.map.hash.TObjectIntHashMap;
26 import gnu.trove.set.hash.THashSet;
27 import gnu.trove.set.hash.TIntHashSet;
28
29 public class ESimpleLambda extends Expression {
30     public Variable parameter;
31     public Expression value;
32     public Type effect = Types.NO_EFFECTS;
33     
34     public ESimpleLambda(Variable parameter, Expression value) {
35         this.parameter = parameter;
36         this.value = value;
37     }
38     
39     public ESimpleLambda(Type effect, Variable parameter, Expression value) {
40         this.parameter = parameter;
41         this.value = value;
42         this.effect = effect;
43     }
44
45     public ESimpleLambda(long loc, Variable parameter, Expression value) {
46         super(loc);
47         this.parameter = parameter;
48         this.value = value;
49     }
50     
51     public ESimpleLambda(long loc, Variable parameter, Type effect, Expression value) {
52         super(loc);
53         this.parameter = parameter;
54         this.value = value;
55         this.effect = effect;
56     }
57
58         public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {
59         value.collectRefs(allRefs, refs);
60     }
61         
62         @Override
63         public void collectVars(TObjectIntHashMap<Variable> allVars,
64                 TIntHashSet vars) {
65             value.collectVars(allVars, vars);
66         }
67
68         public Expression decomposeMatching() {
69         value = value.decomposeMatching();
70         return this;
71     }
72
73         @Override
74         protected void updateType() throws MatchException {
75             setType(Types.functionE(Types.canonical(parameter.type),
76                     effect, value.getType()));
77         }
78         
79         @Override
80         public IVal toVal(CompilationContext context, CodeWriter w) {
81             return lambdaToVal(context, w);
82     }
83
84     @Override
85     public void collectFreeVariables(THashSet<Variable> vars) {
86         value.collectFreeVariables(vars);
87         vars.remove(parameter);
88     }
89
90     @Override
91     public Expression simplify(SimplificationContext context) {
92         value = value.simplify(context);
93         return this;
94     }
95
96     @Override
97     public Expression resolve(TranslationContext context) {
98         value = value.resolve(context);
99         return this;
100     }
101
102     @Override
103     public Expression replace(ReplaceContext context) {
104         Variable newParameter = parameter.copy();
105         context.varMap.put(parameter, new EVariable(newParameter));
106         ESimpleLambda result = new ESimpleLambda(getLocation(),
107                 newParameter, 
108                 effect.replace(context.tvarMap),
109                 value.replace(context));
110         // not absolutely needed, but maybe good for performance
111         context.varMap.remove(parameter); 
112         return result;
113     }
114         
115     public Type getLocalEffect() {
116         if(SCLCompilerConfiguration.DEBUG)
117             if(effect == null)
118                 throw new InternalCompilerError();
119         return effect;
120     }
121     
122     public void setEffect(Type effect) {
123         if(effect == null)
124             throw new InternalCompilerError();
125         this.effect = effect;
126     }
127     
128     @Override
129     public IExpression toIExpression(ExpressionInterpretationContext context) {
130         // Find parameters of the whole function definition
131         ArrayList<Variable> parameters = new ArrayList<Variable>(2);
132         parameters.add(parameter);
133         Expression cur = value;
134         while(true) {
135             if(cur instanceof ESimpleLambda) {
136                 ESimpleLambda lambda = (ESimpleLambda)cur;
137                 parameters.add(lambda.parameter);
138                 cur = lambda.value;
139             }
140             else if(cur instanceof ELambdaType) {
141                 cur = ((ELambdaType)cur).value;
142             }
143             else
144                 break;
145             
146         }
147         
148         // Free variables;
149         ExpressionInterpretationContext innerContext =  context.createNewContext();
150         THashSet<Variable> freeVariables = cur.getFreeVariables();
151         for(Variable parameter : parameters)
152             freeVariables.remove(parameter);
153         int i=0;
154         int[] inheritedVariableIds = new int[freeVariables.size()];
155         for(Variable var : freeVariables) {
156             innerContext.push(var);
157             inheritedVariableIds[i++] = context.getVariableId(var);
158         }
159         
160         // Parameters
161         for(Variable parameter : parameters)
162             innerContext.push(parameter);
163         
164         // Construct lambda
165         IExpression body = cur.toIExpression(innerContext); 
166         return new ILambda(inheritedVariableIds,
167                 parameters.size(),
168                 innerContext.getMaxVariableId(),
169                 body);
170     }
171     
172     public Expression checkBasicType(TypingContext context, Type requiredType) {
173         MultiFunction mfun;
174         try {
175             mfun = Types.unifyFunction(requiredType, 1);
176         } catch (UnificationException e) {
177             context.getErrorLog().log(location, "Required type is <" + requiredType + "> which is incompatible with lambda.");
178             setType(Types.metaVar(Kinds.STAR));
179             return this;
180         }
181         
182         context.pushEffectUpperBound(location, mfun.effect);
183         parameter.setType(mfun.parameterTypes[0]);
184         value = value.checkType(context, mfun.returnType);
185         effect = context.popEffectUpperBound();
186         return this;
187     }
188     
189     @Override
190     public Expression inferType(TypingContext context) {
191         effect = Types.metaVar(Kinds.EFFECT);
192         context.pushEffectUpperBound(location, effect);
193         if(parameter.type == null)
194             parameter.setType(Types.metaVar(Kinds.STAR));
195         value = value.checkType(context, Types.metaVar(Kinds.STAR));
196         context.popEffectUpperBound();
197         return this;
198     }
199
200     @Override
201     public boolean isEffectful() {
202         return false;
203     }
204     
205     @Override
206     public void collectEffects(THashSet<Type> effects) {
207     }
208     
209     @Override
210     public void setLocationDeep(long loc) {
211         if(location == Locations.NO_LOCATION) {
212             location = loc;
213             value.setLocationDeep(loc);
214         }
215     }
216     
217     @Override
218     public void accept(ExpressionVisitor visitor) {
219         visitor.visit(this);
220     }
221     
222     public Expression getValue() {
223         return value;
224     }
225     
226     public Variable getParameter() {
227         return parameter;
228     }
229
230     @Override
231     public void forVariables(VariableProcedure procedure) {
232         value.forVariables(procedure);
233     }
234     
235     @Override
236     public Expression accept(ExpressionTransformer transformer) {
237         return transformer.transform(this);
238     }
239     
240     @Override
241     public int getSyntacticFunctionArity() {
242         return 1 + value.getSyntacticFunctionArity();
243     }
244
245 }