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