]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EIf.java
(refs #7498) Bugfixing implementation of skeleton refs
[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 public class EIf extends Expression {
21     public Expression condition;
22     public Expression then_;
23     public Expression else_; // may be null
24     
25     public EIf(Expression condition, Expression then_, Expression else_) {
26         this.condition = condition;
27         this.then_ = then_;
28         this.else_ = else_;
29     }
30
31     public EIf(long loc, Expression condition, Expression then_, Expression else_) {
32         super(loc);
33         this.condition = condition;
34         this.then_ = then_;
35         this.else_ = else_;
36     }
37
38     @Override
39     protected void updateType() throws MatchException {
40         setType(then_.getType());
41     }
42
43     @Override
44     public IVal toVal(CompilationContext context, CodeWriter w) {
45         IVal conditionVal = condition.toVal(context, w); 
46         CodeWriter joinPoint = w.createBlock(getType());
47         CodeWriter thenBlock = w.createBlock();
48         if(else_ != null) {
49             CodeWriter elseBlock = w.createBlock();        
50             w.if_(conditionVal, thenBlock.getContinuation(), elseBlock.getContinuation());
51                 
52             IVal elseVal = else_.toVal(context, elseBlock);
53             elseBlock.jump(joinPoint.getContinuation(), elseVal);
54         }
55         else {
56             w.if_(conditionVal, thenBlock.getContinuation(), joinPoint.getContinuation());
57         }
58         IVal thenVal = then_.toVal(context, thenBlock);
59         thenBlock.jump(joinPoint.getContinuation(), thenVal);
60         w.continueAs(joinPoint);
61         
62         return w.getParameters()[0];
63     }
64
65     @Override
66     public Expression simplify(SimplificationContext context) {
67         condition = condition.simplify(context);
68         then_ = then_.simplify(context);
69         if(else_ != null)
70             else_ = else_.simplify(context);
71         return this;
72     }
73
74     @Override
75     public Expression resolve(TranslationContext context) {
76         condition = condition.resolve(context);
77         then_ = then_.resolve(context);
78         if(else_ != null)
79             else_ = else_.resolve(context);
80         return this;
81     }
82
83     @Override
84     public Expression replace(ReplaceContext context) {
85         return new EIf(condition.replace(context), 
86                 then_.replace(context), 
87                 else_ == null ? null : else_.replace(context));
88     }
89     
90     @Override
91     public Expression checkBasicType(TypingContext context, Type requiredType) {
92         condition = condition.checkType(context, Types.BOOLEAN);
93         then_ = then_.checkType(context, requiredType);
94         if(else_ != null)
95             else_ = else_.checkType(context, requiredType);
96         else
97             context.getErrorLog().log(location, "Else branch is required because the return value of the if expression is used.");
98         return this;
99     }
100     
101     @Override
102     public Expression checkIgnoredType(TypingContext context) {
103         condition = condition.checkType(context, Types.BOOLEAN);
104         then_ = then_.checkIgnoredType(context);
105         if(else_ != null)
106             else_ = else_.checkIgnoredType(context);
107         return this;
108     }
109     
110     @Override
111     public boolean isEffectful() {
112         return condition.isEffectful() || then_.isEffectful() || (else_ != null && else_.isEffectful());
113     }
114     
115     @Override
116     public void setLocationDeep(long loc) {
117         if(location == Locations.NO_LOCATION) {
118             location = loc;
119             condition.setLocationDeep(loc);
120             then_.setLocationDeep(loc);
121             if(else_ != null)
122                 else_.setLocationDeep(loc);
123         }
124     }
125     
126     @Override
127     public void accept(ExpressionVisitor visitor) {
128         visitor.visit(this);
129     }
130     
131     @Override
132     public IExpression toIExpression(ExpressionInterpretationContext target) {
133         return new IIf(condition.toIExpression(target), then_.toIExpression(target), 
134                 else_ != null ? else_.toIExpression(target) : new IConstant(Tuple0.INSTANCE));
135     }
136
137     @Override
138     public Expression accept(ExpressionTransformer transformer) {
139         return transformer.transform(this);
140     }
141
142     @Override
143     public int getSyntacticFunctionArity() {
144         return Math.max(then_.getSyntacticFunctionArity(), else_.getSyntacticFunctionArity());
145     }
146 }