]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/GuardedExpressionGroup.java
(refs #7375) Replaced ExpressionDecorator by ExpressionTransformer
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / elaboration / expressions / GuardedExpressionGroup.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.continuations.ICont;
10 import org.simantics.scl.compiler.internal.codegen.references.IVal;
11 import org.simantics.scl.compiler.internal.codegen.ssa.exits.Throw;
12 import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;
13 import org.simantics.scl.compiler.types.Type;
14 import org.simantics.scl.compiler.types.Types;
15 import org.simantics.scl.compiler.types.exceptions.MatchException;
16
17 import gnu.trove.map.hash.TObjectIntHashMap;
18 import gnu.trove.set.hash.THashSet;
19 import gnu.trove.set.hash.TIntHashSet;
20
21 public class GuardedExpressionGroup extends Expression {
22     public GuardedExpression[] expressions;
23
24     public GuardedExpressionGroup(GuardedExpression[] expressions) {
25         this.expressions = expressions;
26     }
27
28     @Override
29     public void collectRefs(TObjectIntHashMap<Object> allRefs,
30             TIntHashSet refs) {
31         for(GuardedExpression expression : expressions) {
32             for(Expression guard : expression.guards)
33                 guard.collectRefs(allRefs, refs);
34             expression.value.collectRefs(allRefs, refs);
35         }
36     }
37
38     @Override
39     public void collectVars(TObjectIntHashMap<Variable> allVars,
40             TIntHashSet vars) {
41         for(GuardedExpression expression : expressions) {
42             for(Expression guard : expression.guards)
43                 guard.collectVars(allVars, vars);
44             expression.value.collectVars(allVars, vars);
45         }
46     }
47
48     @Override
49     protected void updateType() throws MatchException {
50         setType(expressions[0].value.getType());
51     }
52
53     @Override
54     public IVal toVal(CompilationContext context, CodeWriter w) {
55         CodeWriter success = w.createBlock(getType());
56         IVal result = success.getParameters()[0];
57         CodeWriter failure = w.createBlock();
58         compile(context, w, success.getContinuation(), failure.getContinuation());
59         w.continueAs(success);
60         failure.throw_(location, Throw.MatchingException, "Matching failure at: " + toString());
61         return result;
62         //throw new InternalCompilerError("GuardedExpressionGroup should be handled in match compilation.");
63     }
64
65     @Override
66     public void collectFreeVariables(THashSet<Variable> vars) {
67         for(GuardedExpression expression : expressions) {
68             for(Expression guard : expression.guards)
69                 guard.collectFreeVariables(vars);
70             expression.value.collectFreeVariables(vars);
71         }
72     }
73
74     @Override
75     public Expression simplify(SimplificationContext context) {
76         for(GuardedExpression expression : expressions) {
77             for(int i=0;i<expression.guards.length;++i)
78                 expression.guards[i] = expression.guards[i].simplify(context);
79             expression.value = expression.value.simplify(context);
80         }
81         return this;
82     }
83
84     @Override
85     public Expression resolve(TranslationContext context) {
86         for(GuardedExpression expression : expressions) {
87             for(int i=0;i<expression.guards.length;++i)
88                 expression.guards[i] = expression.guards[i].resolve(context);
89             expression.value = expression.value.resolve(context);
90         }
91         return this;
92     }
93     
94     @Override
95     public Expression checkBasicType(TypingContext context, Type requiredType) {
96         for(GuardedExpression expression : expressions) {
97             for(int i=0;i<expression.guards.length;++i)
98                 expression.guards[i] = expression.guards[i].checkType(context, Types.BOOLEAN);
99             expression.value = expression.value.checkType(context, requiredType);
100         }
101         return this;
102     }
103     
104     public void compile(CompilationContext context, CodeWriter firstWriter, ICont success,
105             ICont lastFailure) {
106         // Create all code blocks
107         CodeWriter[] writers = new CodeWriter[expressions.length];                
108         ICont[] failures = new ICont[expressions.length];
109         writers[0] = firstWriter;
110         failures[expressions.length-1] = lastFailure;
111         for(int i=1;i<expressions.length;++i) {
112             CodeWriter writer = firstWriter.createBlock();
113             writers[i] = writer;
114             failures[i-1] = writer.getContinuation();
115         }
116         
117         // Compile
118         for(int i=0;i<expressions.length;++i) {
119             CodeWriter w = writers[i];
120             ICont failure = failures[i];
121             
122             for(Expression guard : expressions[i].guards) {
123                 CodeWriter nextW = w.createBlock();
124                 w.if_(guard.toVal(context, w), nextW.getContinuation(), failure);
125                 w = nextW;
126             }
127             
128             w.jump(success, expressions[i].value.toVal(context, w));
129         }
130     }
131     
132     @Override
133     public Expression replace(ReplaceContext context) {
134         GuardedExpression[] newExpressions = new GuardedExpression[expressions.length];
135         for(int i=0;i<expressions.length;++i)
136             newExpressions[i] = expressions[i].replace(context);
137         return new GuardedExpressionGroup(newExpressions);            
138     }
139
140     @Override
141     public void collectEffects(THashSet<Type> effects) {
142         for(GuardedExpression ge : expressions) {
143             for(Expression guard : ge.guards)
144                 guard.collectEffects(effects);
145             ge.value.collectEffects(effects);
146         }
147     }
148     
149     @Override
150     public void setLocationDeep(long loc) {
151         if(location == Locations.NO_LOCATION) {
152             location = loc;
153             for(GuardedExpression expression : expressions)
154                 expression.setLocationDeep(loc);
155         }
156     }
157     
158     @Override
159     public void accept(ExpressionVisitor visitor) {
160         visitor.visit(this);
161     }
162
163     @Override
164     public void forVariables(VariableProcedure procedure) {
165         for(GuardedExpression expression : expressions)
166             expression.forVariables(procedure);
167     }
168
169     @Override
170     public Expression accept(ExpressionTransformer transformer) {
171         return transformer.transform(this);
172     }
173     
174     @Override
175     public int getSyntacticFunctionArity() {
176         return expressions[0].value.getSyntacticFunctionArity();
177     }
178 }