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