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