1 package org.simantics.scl.compiler.elaboration.expressions;
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;
20 import gnu.trove.map.hash.TObjectIntHashMap;
21 import gnu.trove.set.hash.THashSet;
22 import gnu.trove.set.hash.TIntHashSet;
24 public class EIf extends Expression {
25 public Expression condition;
26 public Expression then_;
27 public Expression else_; // may be null
29 public EIf(Expression condition, Expression then_, Expression else_) {
30 this.condition = condition;
35 public EIf(long loc, Expression condition, Expression then_, Expression else_) {
37 this.condition = condition;
42 public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {
43 condition.collectRefs(allRefs, refs);
44 then_.collectRefs(allRefs, refs);
46 else_.collectRefs(allRefs, refs);
50 public void collectVars(TObjectIntHashMap<Variable> allVars,
52 condition.collectVars(allVars, vars);
53 then_.collectVars(allVars, vars);
55 else_.collectVars(allVars, vars);
59 protected void updateType() throws MatchException {
60 setType(then_.getType());
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();
69 CodeWriter elseBlock = w.createBlock();
70 w.if_(conditionVal, thenBlock.getContinuation(), elseBlock.getContinuation());
72 IVal elseVal = else_.toVal(context, elseBlock);
73 elseBlock.jump(joinPoint.getContinuation(), elseVal);
76 w.if_(conditionVal, thenBlock.getContinuation(), joinPoint.getContinuation());
78 IVal thenVal = then_.toVal(context, thenBlock);
79 thenBlock.jump(joinPoint.getContinuation(), thenVal);
80 w.continueAs(joinPoint);
82 return w.getParameters()[0];
86 public void collectFreeVariables(THashSet<Variable> vars) {
87 condition.collectFreeVariables(vars);
88 then_.collectFreeVariables(vars);
90 else_.collectFreeVariables(vars);
94 public Expression simplify(SimplificationContext context) {
95 condition = condition.simplify(context);
96 then_ = then_.simplify(context);
98 else_ = else_.simplify(context);
103 public Expression resolve(TranslationContext context) {
104 condition = condition.resolve(context);
105 then_ = then_.resolve(context);
107 else_ = else_.resolve(context);
112 public Expression replace(ReplaceContext context) {
113 return new EIf(condition.replace(context),
114 then_.replace(context),
115 else_ == null ? null : else_.replace(context));
119 public Expression checkBasicType(TypingContext context, Type requiredType) {
120 condition = condition.checkType(context, Types.BOOLEAN);
121 then_ = then_.checkType(context, requiredType);
123 else_ = else_.checkType(context, requiredType);
125 context.getErrorLog().log(location, "Else branch is required because the return value of the if expression is used.");
130 public Expression checkIgnoredType(TypingContext context) {
131 condition = condition.checkType(context, Types.BOOLEAN);
132 then_ = then_.checkIgnoredType(context);
134 else_ = else_.checkIgnoredType(context);
139 public boolean isEffectful() {
140 return condition.isEffectful() || then_.isEffectful() || (else_ != null && else_.isEffectful());
144 public void collectEffects(THashSet<Type> effects) {
145 condition.collectEffects(effects);
146 then_.collectEffects(effects);
148 else_.collectEffects(effects);
152 public void setLocationDeep(long loc) {
153 if(location == Locations.NO_LOCATION) {
155 condition.setLocationDeep(loc);
156 then_.setLocationDeep(loc);
158 else_.setLocationDeep(loc);
163 public void accept(ExpressionVisitor visitor) {
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));
174 public Expression accept(ExpressionTransformer transformer) {
175 return transformer.transform(this);
179 public int getSyntacticFunctionArity() {
180 return Math.max(then_.getSyntacticFunctionArity(), else_.getSyntacticFunctionArity());