]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EIf.java
Merge "Ensure GetElementClassRequest is not constructed without elementFactory"
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / elaboration / expressions / EIf.java
1 package org.simantics.scl.compiler.elaboration.expressions;
2
3 import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext;
4 import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;
5 import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
6 import org.simantics.scl.compiler.elaboration.contexts.TypingContext;
7 import org.simantics.scl.compiler.environment.Environment;
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.IConstant;
13 import org.simantics.scl.compiler.internal.interpreted.IExpression;
14 import org.simantics.scl.compiler.internal.interpreted.IIf;
15 import org.simantics.scl.compiler.top.ExpressionInterpretationContext;
16 import org.simantics.scl.compiler.types.Type;
17 import org.simantics.scl.compiler.types.Types;
18 import org.simantics.scl.compiler.types.exceptions.MatchException;
19 import org.simantics.scl.runtime.tuple.Tuple0;
20
21 import gnu.trove.map.hash.TObjectIntHashMap;
22 import gnu.trove.set.hash.THashSet;
23 import gnu.trove.set.hash.TIntHashSet;
24
25 public class EIf extends Expression {
26     public Expression condition;
27     public Expression then_;
28     public Expression else_; // may be null
29     
30     public EIf(Expression condition, Expression then_, Expression else_) {
31         this.condition = condition;
32         this.then_ = then_;
33         this.else_ = else_;
34     }
35
36     public EIf(long loc, Expression condition, Expression then_, Expression else_) {
37         super(loc);
38         this.condition = condition;
39         this.then_ = then_;
40         this.else_ = else_;
41     }
42
43         public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {
44         condition.collectRefs(allRefs, refs);
45         then_.collectRefs(allRefs, refs);
46         if(else_ != null)
47             else_.collectRefs(allRefs, refs);
48     }
49
50         @Override
51         public void collectVars(TObjectIntHashMap<Variable> allVars,
52                 TIntHashSet vars) {
53             condition.collectVars(allVars, vars);
54         then_.collectVars(allVars, vars);
55         if(else_ != null)
56             else_.collectVars(allVars, vars);
57         }
58
59         @Override
60         protected void updateType() throws MatchException {
61             setType(then_.getType());
62         }
63         
64         @Override
65         public IVal toVal(Environment env, CodeWriter w) {
66         IVal conditionVal = condition.toVal(env, w); 
67         CodeWriter joinPoint = w.createBlock(getType());
68         CodeWriter thenBlock = w.createBlock();
69         if(else_ != null) {
70             CodeWriter elseBlock = w.createBlock();        
71             w.if_(conditionVal, thenBlock.getContinuation(), elseBlock.getContinuation());
72                 
73             IVal elseVal = else_.toVal(env, elseBlock);
74             elseBlock.jump(joinPoint.getContinuation(), elseVal);
75         }
76         else {
77             w.if_(conditionVal, thenBlock.getContinuation(), joinPoint.getContinuation());
78         }
79         IVal thenVal = then_.toVal(env, thenBlock);
80         thenBlock.jump(joinPoint.getContinuation(), thenVal);
81         w.continueAs(joinPoint);
82         
83         return w.getParameters()[0];
84     }
85
86     @Override
87     public void collectFreeVariables(THashSet<Variable> vars) {
88         condition.collectFreeVariables(vars);
89         then_.collectFreeVariables(vars);
90         if(else_ != null)
91             else_.collectFreeVariables(vars);
92     }
93
94     @Override
95     public Expression simplify(SimplificationContext context) {
96         condition = condition.simplify(context);
97         then_ = then_.simplify(context);
98         if(else_ != null)
99             else_ = else_.simplify(context);
100         return this;
101     }
102
103     @Override
104     public Expression resolve(TranslationContext context) {
105         condition = condition.resolve(context);
106         then_ = then_.resolve(context);
107         if(else_ != null)
108             else_ = else_.resolve(context);
109         return this;
110     }
111
112     @Override
113     public Expression replace(ReplaceContext context) {
114         return new EIf(condition.replace(context), 
115                 then_.replace(context), 
116                 else_ == null ? null : else_.replace(context));
117     }
118     
119     @Override
120     public Expression checkBasicType(TypingContext context, Type requiredType) {
121         condition = condition.checkType(context, Types.BOOLEAN);
122         then_ = then_.checkType(context, requiredType);
123         if(else_ != null)
124             else_ = else_.checkType(context, requiredType);
125         else
126             context.getErrorLog().log(location, "Else branch is required because the return value of the if expression is used.");
127         return this;
128     }
129     
130     @Override
131     public Expression checkIgnoredType(TypingContext context) {
132         condition = condition.checkType(context, Types.BOOLEAN);
133         then_ = then_.checkIgnoredType(context);
134         if(else_ != null)
135             else_ = else_.checkIgnoredType(context);
136         return this;
137     }
138     
139     @Override
140     public Expression decorate(ExpressionDecorator decorator) {
141         condition = condition.decorate(decorator);
142         then_ = then_.decorate(decorator);
143         if(else_ != null)
144             else_ = else_.decorate(decorator);        
145         return decorator.decorate(this);
146     }
147     
148     @Override
149     public boolean isEffectful() {
150         return condition.isEffectful() || then_.isEffectful() || (else_ != null && else_.isEffectful());
151     }
152
153     @Override
154     public void collectEffects(THashSet<Type> effects) {
155         condition.collectEffects(effects);
156         then_.collectEffects(effects);
157         if(else_ != null)
158             else_.collectEffects(effects);
159     }
160     
161     @Override
162     public void setLocationDeep(long loc) {
163         if(location == Locations.NO_LOCATION) {
164             location = loc;
165             condition.setLocationDeep(loc);
166             then_.setLocationDeep(loc);
167             if(else_ != null)
168                 else_.setLocationDeep(loc);
169         }
170     }
171     
172     @Override
173     public void accept(ExpressionVisitor visitor) {
174         visitor.visit(this);
175     }
176     
177     @Override
178     public IExpression toIExpression(ExpressionInterpretationContext target) {
179         return new IIf(condition.toIExpression(target), then_.toIExpression(target), 
180                 else_ != null ? else_.toIExpression(target) : new IConstant(Tuple0.INSTANCE));
181     }
182
183     @Override
184     public void forVariables(VariableProcedure procedure) {
185         condition.forVariables(procedure);
186         then_.forVariables(procedure);
187         if(else_ != null)
188             else_.forVariables(procedure);
189     }
190     @Override
191     public Expression accept(ExpressionTransformer transformer) {
192         return transformer.transform(this);
193     }
194
195     @Override
196     public int getSyntacticFunctionArity() {
197         return Math.max(then_.getSyntacticFunctionArity(), else_.getSyntacticFunctionArity());
198     }
199 }