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