]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ESimpleLet.java
8e73b2392fd3add380c8e656df2eae19777c2211
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / elaboration / expressions / ESimpleLet.java
1 package org.simantics.scl.compiler.elaboration.expressions;\r
2 \r
3 import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext;\r
4 import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;\r
5 import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;\r
6 import org.simantics.scl.compiler.elaboration.contexts.TypingContext;\r
7 import org.simantics.scl.compiler.environment.Environment;\r
8 import org.simantics.scl.compiler.errors.Locations;\r
9 import org.simantics.scl.compiler.internal.codegen.references.IVal;\r
10 import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;\r
11 import org.simantics.scl.compiler.internal.elaboration.utils.ExpressionDecorator;\r
12 import org.simantics.scl.compiler.internal.interpreted.IExpression;\r
13 import org.simantics.scl.compiler.internal.interpreted.ILet;\r
14 import org.simantics.scl.compiler.internal.interpreted.ISeq;\r
15 import org.simantics.scl.compiler.top.ExpressionInterpretationContext;\r
16 import org.simantics.scl.compiler.types.Type;\r
17 import org.simantics.scl.compiler.types.exceptions.MatchException;\r
18 \r
19 import gnu.trove.map.hash.TObjectIntHashMap;\r
20 import gnu.trove.set.hash.THashSet;\r
21 import gnu.trove.set.hash.TIntHashSet;\r
22 \r
23 public class ESimpleLet extends Expression {\r
24     Variable variable; // may be null\r
25     Expression value;\r
26     Expression in;\r
27     \r
28     public ESimpleLet(Variable variable, Expression value, Expression in) {\r
29         if(value == null)\r
30             throw new NullPointerException();\r
31         if(in == null)\r
32             throw new NullPointerException();\r
33         this.variable = variable;\r
34         this.value = value;\r
35         this.in = in;\r
36     }\r
37 \r
38     public ESimpleLet(long loc, Variable variable, Expression value, Expression in) {\r
39         super(loc);\r
40         if(value == null)\r
41             throw new NullPointerException();\r
42         if(in == null)\r
43             throw new NullPointerException();\r
44         this.variable = variable;\r
45         this.value = value;\r
46         this.in = in;\r
47     }\r
48 \r
49         public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {\r
50         value.collectRefs(allRefs, refs);\r
51         in.collectRefs(allRefs, refs);\r
52     }\r
53         \r
54         @Override\r
55         public void collectVars(TObjectIntHashMap<Variable> allVars,\r
56                 TIntHashSet vars) {\r
57             value.collectVars(allVars, vars);\r
58             in.collectVars(allVars, vars);\r
59         }\r
60 \r
61     @Override\r
62     protected void updateType() throws MatchException {\r
63         setType(in.getType());\r
64     }\r
65     \r
66         @Override\r
67         public IVal toVal(Environment env, CodeWriter w) {\r
68             IVal valueVal = value.toVal(env, w);\r
69             if(variable != null)\r
70                 variable.setVal(valueVal);\r
71         return in.toVal(env, w);\r
72     }\r
73 \r
74     @Override\r
75     public void collectFreeVariables(THashSet<Variable> vars) {\r
76         value.collectFreeVariables(vars);\r
77         in.collectFreeVariables(vars);\r
78         vars.remove(variable);\r
79     }\r
80 \r
81     @Override\r
82     public Expression simplify(SimplificationContext context) {\r
83         value = value.simplify(context);\r
84         if(value instanceof EConstant || value instanceof ELiteral) {\r
85             context.addInlinedVariable(variable, value);\r
86             return in.simplify(context);\r
87         }\r
88         in = in.simplify(context);\r
89         return this;\r
90     }\r
91 \r
92     @Override\r
93     public Expression resolve(TranslationContext context) {\r
94         value = value.resolve(context);\r
95         in = in.resolve(context);\r
96         return this;\r
97     }\r
98 \r
99     @Override\r
100     public Expression replace(ReplaceContext context) {\r
101         if(variable == null)\r
102             return new ESimpleLet(location,\r
103                     null, \r
104                     value.replace(context), \r
105                     in.replace(context));\r
106         else {\r
107             Variable newVariable = variable.copy();\r
108             context.varMap.put(variable, new EVariable(newVariable));\r
109             ESimpleLet result = new ESimpleLet(location, newVariable, \r
110                     value.replace(context), \r
111                     in.replace(context));\r
112             context.varMap.remove(variable);\r
113             return result;\r
114         }\r
115     }\r
116     \r
117     @Override\r
118     public void setLocationDeep(long loc) {\r
119         if(location == Locations.NO_LOCATION) {\r
120             location = loc;\r
121             value.setLocationDeep(loc);\r
122             in.setLocationDeep(loc);\r
123         }\r
124     }\r
125 \r
126     @Override\r
127     public IExpression toIExpression(ExpressionInterpretationContext context) {\r
128         if(variable == null) {\r
129             IExpression valueI = value.toIExpression(context);\r
130             IExpression inI = in.toIExpression(context);\r
131             return new ISeq(valueI, inI);\r
132         }\r
133         else {\r
134             IExpression valueI = value.toIExpression(context);\r
135             int variableId = context.push(variable);\r
136             IExpression inI = in.toIExpression(context);\r
137             context.pop(variable);\r
138             return new ILet(variableId, valueI, inI);\r
139         }\r
140     }\r
141 \r
142     private void checkBinding(TypingContext context) {\r
143         if(variable == null)\r
144             value = value.checkIgnoredType(context);\r
145         else if(variable.getType() == null) {\r
146             value = value.inferType(context);\r
147             variable.setType(value.getType());\r
148         }\r
149         else\r
150             value = value.checkType(context, variable.type);\r
151         /*else {\r
152             if(variable.getType() == null)\r
153                 variable.setType(Types.metaVar(Kinds.STAR));\r
154             value = value.checkType(context, variable.type);\r
155         }*/\r
156     }\r
157     \r
158     @Override\r
159     public Expression inferType(TypingContext context) {\r
160         checkBinding(context);\r
161         in = in.inferType(context);\r
162         return this;\r
163     }\r
164     \r
165     @Override\r
166     public Expression checkBasicType(TypingContext context, Type requiredType) {\r
167         checkBinding(context);\r
168         in = in.checkType(context, requiredType);\r
169         return this;\r
170     }\r
171     \r
172     @Override\r
173     public Expression checkIgnoredType(TypingContext context) {\r
174         checkBinding(context);\r
175         in = in.checkIgnoredType(context);\r
176         return this;\r
177     }\r
178 \r
179     @Override\r
180     public Expression decorate(ExpressionDecorator decorator) {\r
181         value = value.decorate(decorator);\r
182         in = in.decorate(decorator);\r
183         return decorator.decorate(this);\r
184     }\r
185 \r
186     @Override\r
187     public void collectEffects(THashSet<Type> effects) {\r
188         value.collectEffects(effects);\r
189         in.collectEffects(effects);\r
190     }\r
191     \r
192     @Override\r
193     public void accept(ExpressionVisitor visitor) {\r
194         visitor.visit(this);\r
195     }\r
196     \r
197     public Expression getValue() {\r
198         return value;\r
199     }\r
200     \r
201     public Variable getVariable() {\r
202         return variable;\r
203     }\r
204     \r
205     public Expression getIn() {\r
206         return in;\r
207     }\r
208 \r
209     @Override\r
210     public void forVariables(VariableProcedure procedure) {\r
211         value.forVariables(procedure);\r
212         in.forVariables(procedure);\r
213     }\r
214     \r
215     @Override\r
216     public Expression accept(ExpressionTransformer transformer) {\r
217         return transformer.transform(this);\r
218     }\r
219 \r
220 }\r