]> gerrit.simantics Code Review - simantics/platform.git/blob
1a084b3666283ae79e6fa5758e6fec82d047aceb
[simantics/platform.git] /
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         public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {
49         value.collectRefs(allRefs, refs);
50         in.collectRefs(allRefs, refs);
51     }
52         
53         @Override
54         public void collectVars(TObjectIntHashMap<Variable> allVars,
55                 TIntHashSet vars) {
56             value.collectVars(allVars, vars);
57             in.collectVars(allVars, vars);
58         }
59
60     @Override
61     protected void updateType() throws MatchException {
62         setType(in.getType());
63     }
64     
65         @Override
66         public IVal toVal(CompilationContext context, CodeWriter w) {
67             IVal valueVal = value.toVal(context, w);
68             if(variable != null)
69                 variable.setVal(valueVal);
70         return in.toVal(context, w);
71     }
72
73     @Override
74     public void collectFreeVariables(THashSet<Variable> vars) {
75         value.collectFreeVariables(vars);
76         in.collectFreeVariables(vars);
77         vars.remove(variable);
78     }
79
80     @Override
81     public Expression simplify(SimplificationContext context) {
82         value = value.simplify(context);
83         if(value instanceof EConstant || value instanceof ELiteral) {
84             context.addInlinedVariable(variable, value);
85             return in.simplify(context);
86         }
87         in = in.simplify(context);
88         return this;
89     }
90
91     @Override
92     public Expression resolve(TranslationContext context) {
93         value = value.resolve(context);
94         in = in.resolve(context);
95         return this;
96     }
97
98     @Override
99     public Expression replace(ReplaceContext context) {
100         if(variable == null)
101             return new ESimpleLet(location,
102                     null, 
103                     value.replace(context), 
104                     in.replace(context));
105         else {
106             Variable newVariable = variable.copy();
107             context.varMap.put(variable, new EVariable(newVariable));
108             ESimpleLet result = new ESimpleLet(location, newVariable, 
109                     value.replace(context), 
110                     in.replace(context));
111             context.varMap.remove(variable);
112             return result;
113         }
114     }
115     
116     @Override
117     public void setLocationDeep(long loc) {
118         if(location == Locations.NO_LOCATION) {
119             location = loc;
120             value.setLocationDeep(loc);
121             in.setLocationDeep(loc);
122         }
123     }
124
125     @Override
126     public IExpression toIExpression(ExpressionInterpretationContext context) {
127         if(variable == null) {
128             IExpression valueI = value.toIExpression(context);
129             IExpression inI = in.toIExpression(context);
130             return new ISeq(valueI, inI);
131         }
132         else {
133             IExpression valueI = value.toIExpression(context);
134             int variableId = context.push(variable);
135             IExpression inI = in.toIExpression(context);
136             context.pop(variable);
137             return new ILet(variableId, valueI, inI);
138         }
139     }
140
141     private void checkBinding(TypingContext context) {
142         if(variable == null)
143             value = value.checkIgnoredType(context);
144         else if(variable.getType() == null) {
145             value = value.inferType(context);
146             variable.setType(value.getType());
147         }
148         else
149             value = value.checkType(context, variable.type);
150         /*else {
151             if(variable.getType() == null)
152                 variable.setType(Types.metaVar(Kinds.STAR));
153             value = value.checkType(context, variable.type);
154         }*/
155     }
156     
157     @Override
158     public Expression inferType(TypingContext context) {
159         checkBinding(context);
160         in = in.inferType(context);
161         return this;
162     }
163     
164     @Override
165     public Expression checkBasicType(TypingContext context, Type requiredType) {
166         checkBinding(context);
167         in = in.checkType(context, requiredType);
168         return this;
169     }
170     
171     @Override
172     public Expression checkIgnoredType(TypingContext context) {
173         checkBinding(context);
174         in = in.checkIgnoredType(context);
175         return this;
176     }
177
178     @Override
179     public void collectEffects(THashSet<Type> effects) {
180         value.collectEffects(effects);
181         in.collectEffects(effects);
182     }
183     
184     @Override
185     public void accept(ExpressionVisitor visitor) {
186         visitor.visit(this);
187     }
188     
189     public Expression getValue() {
190         return value;
191     }
192     
193     public Variable getVariable() {
194         return variable;
195     }
196     
197     public Expression getIn() {
198         return in;
199     }
200
201     @Override
202     public Expression accept(ExpressionTransformer transformer) {
203         return transformer.transform(this);
204     }
205
206     @Override
207     public int getSyntacticFunctionArity() {
208         return in.getSyntacticFunctionArity();
209     }
210 }