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