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