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.TIntHashSet;
23 public class EIf extends Expression {
24 public Expression condition;
25 public Expression then_;
26 public Expression else_; // may be null
28 public EIf(Expression condition, Expression then_, Expression else_) {
29 this.condition = condition;
34 public EIf(long loc, Expression condition, Expression then_, Expression else_) {
36 this.condition = condition;
42 public void collectVars(TObjectIntHashMap<Variable> allVars,
44 condition.collectVars(allVars, vars);
45 then_.collectVars(allVars, vars);
47 else_.collectVars(allVars, vars);
51 protected void updateType() throws MatchException {
52 setType(then_.getType());
56 public IVal toVal(CompilationContext context, CodeWriter w) {
57 IVal conditionVal = condition.toVal(context, w);
58 CodeWriter joinPoint = w.createBlock(getType());
59 CodeWriter thenBlock = w.createBlock();
61 CodeWriter elseBlock = w.createBlock();
62 w.if_(conditionVal, thenBlock.getContinuation(), elseBlock.getContinuation());
64 IVal elseVal = else_.toVal(context, elseBlock);
65 elseBlock.jump(joinPoint.getContinuation(), elseVal);
68 w.if_(conditionVal, thenBlock.getContinuation(), joinPoint.getContinuation());
70 IVal thenVal = then_.toVal(context, thenBlock);
71 thenBlock.jump(joinPoint.getContinuation(), thenVal);
72 w.continueAs(joinPoint);
74 return w.getParameters()[0];
78 public Expression simplify(SimplificationContext context) {
79 condition = condition.simplify(context);
80 then_ = then_.simplify(context);
82 else_ = else_.simplify(context);
87 public Expression resolve(TranslationContext context) {
88 condition = condition.resolve(context);
89 then_ = then_.resolve(context);
91 else_ = else_.resolve(context);
96 public Expression replace(ReplaceContext context) {
97 return new EIf(condition.replace(context),
98 then_.replace(context),
99 else_ == null ? null : else_.replace(context));
103 public Expression checkBasicType(TypingContext context, Type requiredType) {
104 condition = condition.checkType(context, Types.BOOLEAN);
105 then_ = then_.checkType(context, requiredType);
107 else_ = else_.checkType(context, requiredType);
109 context.getErrorLog().log(location, "Else branch is required because the return value of the if expression is used.");
114 public Expression checkIgnoredType(TypingContext context) {
115 condition = condition.checkType(context, Types.BOOLEAN);
116 then_ = then_.checkIgnoredType(context);
118 else_ = else_.checkIgnoredType(context);
123 public boolean isEffectful() {
124 return condition.isEffectful() || then_.isEffectful() || (else_ != null && else_.isEffectful());
128 public void setLocationDeep(long loc) {
129 if(location == Locations.NO_LOCATION) {
131 condition.setLocationDeep(loc);
132 then_.setLocationDeep(loc);
134 else_.setLocationDeep(loc);
139 public void accept(ExpressionVisitor visitor) {
144 public IExpression toIExpression(ExpressionInterpretationContext target) {
145 return new IIf(condition.toIExpression(target), then_.toIExpression(target),
146 else_ != null ? else_.toIExpression(target) : new IConstant(Tuple0.INSTANCE));
150 public Expression accept(ExpressionTransformer transformer) {
151 return transformer.transform(this);
155 public int getSyntacticFunctionArity() {
156 return Math.max(then_.getSyntacticFunctionArity(), else_.getSyntacticFunctionArity());