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;
43 public void collectVars(TObjectIntHashMap<Variable> allVars,
45 condition.collectVars(allVars, vars);
46 then_.collectVars(allVars, vars);
48 else_.collectVars(allVars, vars);
52 protected void updateType() throws MatchException {
53 setType(then_.getType());
57 public IVal toVal(CompilationContext context, CodeWriter w) {
58 IVal conditionVal = condition.toVal(context, w);
59 CodeWriter joinPoint = w.createBlock(getType());
60 CodeWriter thenBlock = w.createBlock();
62 CodeWriter elseBlock = w.createBlock();
63 w.if_(conditionVal, thenBlock.getContinuation(), elseBlock.getContinuation());
65 IVal elseVal = else_.toVal(context, elseBlock);
66 elseBlock.jump(joinPoint.getContinuation(), elseVal);
69 w.if_(conditionVal, thenBlock.getContinuation(), joinPoint.getContinuation());
71 IVal thenVal = then_.toVal(context, thenBlock);
72 thenBlock.jump(joinPoint.getContinuation(), thenVal);
73 w.continueAs(joinPoint);
75 return w.getParameters()[0];
79 public void collectFreeVariables(THashSet<Variable> vars) {
80 condition.collectFreeVariables(vars);
81 then_.collectFreeVariables(vars);
83 else_.collectFreeVariables(vars);
87 public Expression simplify(SimplificationContext context) {
88 condition = condition.simplify(context);
89 then_ = then_.simplify(context);
91 else_ = else_.simplify(context);
96 public Expression resolve(TranslationContext context) {
97 condition = condition.resolve(context);
98 then_ = then_.resolve(context);
100 else_ = else_.resolve(context);
105 public Expression replace(ReplaceContext context) {
106 return new EIf(condition.replace(context),
107 then_.replace(context),
108 else_ == null ? null : else_.replace(context));
112 public Expression checkBasicType(TypingContext context, Type requiredType) {
113 condition = condition.checkType(context, Types.BOOLEAN);
114 then_ = then_.checkType(context, requiredType);
116 else_ = else_.checkType(context, requiredType);
118 context.getErrorLog().log(location, "Else branch is required because the return value of the if expression is used.");
123 public Expression checkIgnoredType(TypingContext context) {
124 condition = condition.checkType(context, Types.BOOLEAN);
125 then_ = then_.checkIgnoredType(context);
127 else_ = else_.checkIgnoredType(context);
132 public boolean isEffectful() {
133 return condition.isEffectful() || then_.isEffectful() || (else_ != null && else_.isEffectful());
137 public void setLocationDeep(long loc) {
138 if(location == Locations.NO_LOCATION) {
140 condition.setLocationDeep(loc);
141 then_.setLocationDeep(loc);
143 else_.setLocationDeep(loc);
148 public void accept(ExpressionVisitor visitor) {
153 public IExpression toIExpression(ExpressionInterpretationContext target) {
154 return new IIf(condition.toIExpression(target), then_.toIExpression(target),
155 else_ != null ? else_.toIExpression(target) : new IConstant(Tuple0.INSTANCE));
159 public Expression accept(ExpressionTransformer transformer) {
160 return transformer.transform(this);
164 public int getSyntacticFunctionArity() {
165 return Math.max(then_.getSyntacticFunctionArity(), else_.getSyntacticFunctionArity());