]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EMatch.java
SCL compiler generates line numbers to bytecode
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / elaboration / expressions / EMatch.java
1 package org.simantics.scl.compiler.elaboration.expressions;
2
3 import java.util.ArrayList;
4
5 import org.simantics.scl.compiler.compilation.CompilationContext;
6 import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext;
7 import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;
8 import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
9 import org.simantics.scl.compiler.elaboration.contexts.TypingContext;
10 import org.simantics.scl.compiler.errors.Locations;
11 import org.simantics.scl.compiler.internal.codegen.references.IVal;
12 import org.simantics.scl.compiler.internal.codegen.ssa.exits.Throw;
13 import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;
14 import org.simantics.scl.compiler.internal.elaboration.matching.PatternMatchingCompiler;
15 import org.simantics.scl.compiler.internal.elaboration.matching.Row;
16 import org.simantics.scl.compiler.types.Type;
17 import org.simantics.scl.compiler.types.Types;
18 import org.simantics.scl.compiler.types.kinds.Kinds;
19
20 public class EMatch extends Expression {
21
22     public Expression[] scrutinee;
23     public Case[] cases;
24     
25     public EMatch(Expression[] scrutinee, Case ... cases) {
26         this.scrutinee = scrutinee;
27         this.cases = cases;
28     }
29     
30     public EMatch(Expression scrutinee, Case ... cases) {
31         this(new Expression[] {scrutinee}, cases);
32     }
33
34     public EMatch(long loc, Expression[] scrutinee, Case ... cases) {
35         super(loc);
36         this.scrutinee = scrutinee;
37         this.cases = cases;
38     }
39
40     @Override
41     protected void updateType() {
42         setType(cases[0].value.getType());
43     }
44
45     @Override
46     public IVal toVal(CompilationContext context, CodeWriter w) {
47         ArrayList<Row> rows = new ArrayList<Row>(cases.length);
48         for(Case case_ : cases)
49             rows.add(new Row(case_.patterns, case_.value));
50
51         IVal[] scrutineeVals = new IVal[scrutinee.length];
52         for(int i=0;i<scrutinee.length;++i)
53             scrutineeVals[i] = scrutinee[i].toVal(context, w);
54
55         CodeWriter joinPoint = w.createBlock(getType());
56         CodeWriter failurePoint = w.createBlock(); // TODO generate only one failurePoint per function
57         PatternMatchingCompiler.split(location, w, context, scrutineeVals, joinPoint.getContinuation(), failurePoint.getContinuation(), rows);
58         failurePoint.throw_(location, Throw.MatchingException, "Matching failure at: " + toString());
59         w.continueAs(joinPoint);
60         return w.getParameters()[0];
61     }
62     
63     @Override
64     public Expression simplify(SimplificationContext context) {
65         for(int i=0;i<scrutinee.length;++i)
66             scrutinee[i] = scrutinee[i].simplify(context);
67         for(Case case_ : cases)
68             case_.simplify(context);                    
69         if(cases.length == 1 && scrutinee.length == 1) {
70             Case case_ = cases[0];
71             Expression pattern = case_.patterns[0];
72             if(case_.patterns[0] instanceof EVariable
73                     && !(case_.value instanceof GuardedExpressionGroup)) {
74                 Variable var = ((EVariable)pattern).variable;
75                 return new ESimpleLet(var, scrutinee[0], case_.value);
76             }
77         }
78         return this;
79     }
80
81     @Override
82     public Expression resolve(TranslationContext context) {
83         for(int i=0;i<scrutinee.length;++i)
84             scrutinee[i] = scrutinee[i].resolve(context);
85         for(Case case_ : cases)
86             case_.resolve(context);
87         return this;
88     }
89     
90     @Override
91     public void setLocationDeep(long loc) {
92         if(location == Locations.NO_LOCATION) {
93             location = loc;
94             for(Case case_ : cases)
95                 case_.setLocationDeep(loc);
96             for(Expression e : scrutinee)
97                 e.setLocationDeep(loc);
98         }
99     }
100     
101     @Override
102     public Expression replace(ReplaceContext context) {
103         Expression[] newScrutinee = new Expression[scrutinee.length];
104         for(int i=0;i<scrutinee.length;++i)
105             newScrutinee[i] = scrutinee[i].replace(context);
106         Case[] newCases = new Case[cases.length];
107         for(int i=0;i<cases.length;++i)
108             newCases[i] = cases[i].replace(context);
109         return new EMatch(getLocation(), newScrutinee, newCases);
110     }
111     
112     @Override
113     public Expression checkBasicType(TypingContext context, Type requiredType) {
114         Type[] scrutineeTypes = new Type[scrutinee.length];
115         for(int i=0;i<scrutinee.length;++i) {
116             scrutinee[i] = scrutinee[i].checkType(context, Types.metaVar(Kinds.STAR));
117             scrutineeTypes[i] = scrutinee[i].getType();
118         }
119         for(Case case_ : cases)
120             case_.checkType(context, scrutineeTypes, requiredType);
121         setType(requiredType);
122         return this;
123     }
124     
125     @Override
126     public Expression checkIgnoredType(TypingContext context) {
127         Type[] scrutineeTypes = new Type[scrutinee.length];
128         for(int i=0;i<scrutinee.length;++i) {
129             scrutinee[i] = scrutinee[i].checkType(context, Types.metaVar(Kinds.STAR));
130             scrutineeTypes[i] = scrutinee[i].getType();
131         }
132         for(Case case_ : cases)
133             case_.checkIgnoredType(context, scrutineeTypes);
134         setType(Types.UNIT);
135         return this;
136     }
137     
138     @Override
139     public void accept(ExpressionVisitor visitor) {
140         visitor.visit(this);
141     }
142     
143     public Expression[] getScrutinee() {
144         return scrutinee;
145     }
146     
147     public Case[] getCases() {
148         return cases;
149     }
150     
151     @Override
152     public Expression accept(ExpressionTransformer transformer) {
153         return transformer.transform(this);
154     }
155
156     @Override
157     public int getSyntacticFunctionArity() {
158         int result = 0;
159         for(Case case_ : cases)
160             result = Math.max(result, case_.value.getSyntacticFunctionArity());
161         return result;
162     }
163 }