62bbe45b94f1988d7dfebf87b906d44e4d3bd6ae
[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 collectVars(TObjectIntHashMap<Variable> allVars,
30             TIntHashSet vars) {
31         for(GuardedExpression expression : expressions) {
32             for(Expression guard : expression.guards)
33                 guard.collectVars(allVars, vars);
34             expression.value.collectVars(allVars, vars);
35         }
36     }
37
38     @Override
39     protected void updateType() throws MatchException {
40         setType(expressions[0].value.getType());
41     }
42
43     @Override
44     public IVal toVal(CompilationContext context, CodeWriter w) {
45         CodeWriter success = w.createBlock(getType());
46         IVal result = success.getParameters()[0];
47         CodeWriter failure = w.createBlock();
48         compile(context, w, success.getContinuation(), failure.getContinuation());
49         w.continueAs(success);
50         failure.throw_(location, Throw.MatchingException, "Matching failure at: " + toString());
51         return result;
52         //throw new InternalCompilerError("GuardedExpressionGroup should be handled in match compilation.");
53     }
54
55     @Override
56     public void collectFreeVariables(THashSet<Variable> vars) {
57         for(GuardedExpression expression : expressions) {
58             for(Expression guard : expression.guards)
59                 guard.collectFreeVariables(vars);
60             expression.value.collectFreeVariables(vars);
61         }
62     }
63
64     @Override
65     public Expression simplify(SimplificationContext context) {
66         for(GuardedExpression expression : expressions) {
67             for(int i=0;i<expression.guards.length;++i)
68                 expression.guards[i] = expression.guards[i].simplify(context);
69             expression.value = expression.value.simplify(context);
70         }
71         return this;
72     }
73
74     @Override
75     public Expression resolve(TranslationContext context) {
76         for(GuardedExpression expression : expressions) {
77             for(int i=0;i<expression.guards.length;++i)
78                 expression.guards[i] = expression.guards[i].resolve(context);
79             expression.value = expression.value.resolve(context);
80         }
81         return this;
82     }
83     
84     @Override
85     public Expression checkBasicType(TypingContext context, Type requiredType) {
86         for(GuardedExpression expression : expressions) {
87             for(int i=0;i<expression.guards.length;++i)
88                 expression.guards[i] = expression.guards[i].checkType(context, Types.BOOLEAN);
89             expression.value = expression.value.checkType(context, requiredType);
90         }
91         return this;
92     }
93     
94     public void compile(CompilationContext context, CodeWriter firstWriter, ICont success,
95             ICont lastFailure) {
96         // Create all code blocks
97         CodeWriter[] writers = new CodeWriter[expressions.length];                
98         ICont[] failures = new ICont[expressions.length];
99         writers[0] = firstWriter;
100         failures[expressions.length-1] = lastFailure;
101         for(int i=1;i<expressions.length;++i) {
102             CodeWriter writer = firstWriter.createBlock();
103             writers[i] = writer;
104             failures[i-1] = writer.getContinuation();
105         }
106         
107         // Compile
108         for(int i=0;i<expressions.length;++i) {
109             CodeWriter w = writers[i];
110             ICont failure = failures[i];
111             
112             for(Expression guard : expressions[i].guards) {
113                 CodeWriter nextW = w.createBlock();
114                 w.if_(guard.toVal(context, w), nextW.getContinuation(), failure);
115                 w = nextW;
116             }
117             
118             w.jump(success, expressions[i].value.toVal(context, w));
119         }
120     }
121     
122     @Override
123     public Expression replace(ReplaceContext context) {
124         GuardedExpression[] newExpressions = new GuardedExpression[expressions.length];
125         for(int i=0;i<expressions.length;++i)
126             newExpressions[i] = expressions[i].replace(context);
127         return new GuardedExpressionGroup(newExpressions);            
128     }
129     
130     @Override
131     public void setLocationDeep(long loc) {
132         if(location == Locations.NO_LOCATION) {
133             location = loc;
134             for(GuardedExpression expression : expressions)
135                 expression.setLocationDeep(loc);
136         }
137     }
138     
139     @Override
140     public void accept(ExpressionVisitor visitor) {
141         visitor.visit(this);
142     }
143
144     @Override
145     public Expression accept(ExpressionTransformer transformer) {
146         return transformer.transform(this);
147     }
148     
149     @Override
150     public int getSyntacticFunctionArity() {
151         return expressions[0].value.getSyntacticFunctionArity();
152     }
153 }