]> gerrit.simantics Code Review - simantics/platform.git/blob
a218b95c38bf04913f983ba5c0978cb169b16e34
[simantics/platform.git] /
1 package org.simantics.scl.compiler.elaboration.expressions;\r
2 \r
3 import gnu.trove.map.hash.TObjectIntHashMap;\r
4 import gnu.trove.set.hash.THashSet;\r
5 import gnu.trove.set.hash.TIntHashSet;\r
6 \r
7 import java.util.ArrayList;\r
8 \r
9 import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext;\r
10 import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;\r
11 import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;\r
12 import org.simantics.scl.compiler.elaboration.contexts.TypingContext;\r
13 import org.simantics.scl.compiler.environment.Environment;\r
14 import org.simantics.scl.compiler.errors.Locations;\r
15 import org.simantics.scl.compiler.internal.codegen.references.IVal;\r
16 import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;\r
17 import org.simantics.scl.compiler.internal.elaboration.matching.PatternMatchingCompiler;\r
18 import org.simantics.scl.compiler.internal.elaboration.matching.Row;\r
19 import org.simantics.scl.compiler.internal.elaboration.utils.ExpressionDecorator;\r
20 import org.simantics.scl.compiler.types.Type;\r
21 import org.simantics.scl.compiler.types.Types;\r
22 import org.simantics.scl.compiler.types.kinds.Kinds;\r
23 \r
24 public class EMatch extends Expression {\r
25 \r
26     public Expression[] scrutinee;\r
27     public Case[] cases;\r
28     \r
29     public EMatch(Expression[] scrutinee, Case ... cases) {\r
30         this.scrutinee = scrutinee;\r
31         this.cases = cases;\r
32     }\r
33     \r
34     public EMatch(Expression scrutinee, Case ... cases) {\r
35         this(new Expression[] {scrutinee}, cases);\r
36     }\r
37 \r
38     public EMatch(long loc, Expression[] scrutinee, Case ... cases) {\r
39         super(loc);\r
40         this.scrutinee = scrutinee;\r
41         this.cases = cases;\r
42     }\r
43 \r
44         public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {\r
45         for(Expression s : scrutinee)\r
46             s.collectRefs(allRefs, refs);\r
47         for(Case case_ : cases)\r
48             case_.collectRefs(allRefs, refs);\r
49     }\r
50         \r
51         @Override\r
52         public void collectVars(TObjectIntHashMap<Variable> allVars,\r
53                 TIntHashSet vars) {\r
54             for(Expression s : scrutinee)\r
55             s.collectVars(allVars, vars);\r
56             for(Case case_ : cases)\r
57             case_.collectVars(allVars, vars);\r
58         }\r
59         \r
60         @Override\r
61         protected void updateType() {\r
62             setType(cases[0].value.getType());\r
63         }\r
64 \r
65         @Override\r
66         public IVal toVal(Environment env, CodeWriter w) {\r
67             ArrayList<Row> rows = new ArrayList<Row>(cases.length);\r
68             for(Case case_ : cases)\r
69                 rows.add(new Row(case_.patterns, case_.value));\r
70             \r
71             IVal[] scrutineeVals = new IVal[scrutinee.length];\r
72             for(int i=0;i<scrutinee.length;++i)\r
73                 scrutineeVals[i] = scrutinee[i].toVal(env, w);\r
74             \r
75             CodeWriter joinPoint = w.createBlock(getType());\r
76             CodeWriter failurePoint = w.createBlock(); // TODO generate only one failurePoint per function\r
77             PatternMatchingCompiler.split(w, env, scrutineeVals, joinPoint.getContinuation(), failurePoint.getContinuation(), rows);\r
78             failurePoint.throw_(location, "Matching failure at: " + toString());\r
79             w.continueAs(joinPoint);\r
80             return w.getParameters()[0];\r
81     }\r
82 \r
83     @Override\r
84     public void collectFreeVariables(THashSet<Variable> vars) {\r
85         for(Expression s : scrutinee)\r
86             s.collectFreeVariables(vars);\r
87         for(Case case_ : cases)\r
88             case_.collectFreeVariables(vars);\r
89     }\r
90     \r
91     @Override\r
92     public Expression simplify(SimplificationContext context) {\r
93         for(int i=0;i<scrutinee.length;++i)\r
94             scrutinee[i] = scrutinee[i].simplify(context);\r
95         for(Case case_ : cases)\r
96             case_.simplify(context);                    \r
97         if(cases.length == 1 && scrutinee.length == 1) {\r
98             Case case_ = cases[0];\r
99             Expression pattern = case_.patterns[0];\r
100             if(case_.patterns[0] instanceof EVariable\r
101                     && !(case_.value instanceof GuardedExpressionGroup)) {\r
102                 Variable var = ((EVariable)pattern).variable;\r
103                 return new ESimpleLet(var, scrutinee[0], case_.value);\r
104             }\r
105         }\r
106         return this;\r
107     }\r
108 \r
109     @Override\r
110     public Expression resolve(TranslationContext context) {\r
111         for(int i=0;i<scrutinee.length;++i)\r
112             scrutinee[i] = scrutinee[i].resolve(context);\r
113         for(Case case_ : cases)\r
114             case_.resolve(context);\r
115         return this;\r
116     }\r
117     \r
118     @Override\r
119     public void setLocationDeep(long loc) {\r
120         if(location == Locations.NO_LOCATION) {\r
121             location = loc;\r
122             for(Case case_ : cases)\r
123                 case_.setLocationDeep(loc);\r
124             for(Expression e : scrutinee)\r
125                 e.setLocationDeep(loc);\r
126         }\r
127     }\r
128     \r
129     @Override\r
130     public Expression replace(ReplaceContext context) {\r
131         Expression[] newScrutinee = new Expression[scrutinee.length];\r
132         for(int i=0;i<scrutinee.length;++i)\r
133             newScrutinee[i] = scrutinee[i].replace(context);\r
134         Case[] newCases = new Case[cases.length];\r
135         for(int i=0;i<cases.length;++i)\r
136             newCases[i] = cases[i].replace(context);\r
137         return new EMatch(getLocation(), newScrutinee, newCases);\r
138     }\r
139     \r
140     @Override\r
141     public Expression checkBasicType(TypingContext context, Type requiredType) {\r
142         Type[] scrutineeTypes = new Type[scrutinee.length];\r
143         for(int i=0;i<scrutinee.length;++i) {\r
144             scrutinee[i] = scrutinee[i].checkType(context, Types.metaVar(Kinds.STAR));\r
145             scrutineeTypes[i] = scrutinee[i].getType();\r
146         }\r
147         for(Case case_ : cases)\r
148             case_.checkType(context, scrutineeTypes, requiredType);\r
149         setType(requiredType);\r
150         return this;\r
151     }\r
152 \r
153     @Override\r
154     public Expression decorate(ExpressionDecorator decorator) {\r
155         for(int i=0;i<scrutinee.length;++i)\r
156             scrutinee[i] = scrutinee[i].decorate(decorator);\r
157         for(Case case_ : cases)\r
158             case_.decorate(decorator);\r
159         return decorator.decorate(this);\r
160     }\r
161 \r
162     @Override\r
163     public void collectEffects(THashSet<Type> effects) {\r
164         for(Expression s : scrutinee)\r
165             s.collectEffects(effects);\r
166         for(Case case_ : cases) {\r
167             for(Expression pattern : case_.patterns)\r
168                 pattern.collectEffects(effects);\r
169             case_.value.collectEffects(effects);\r
170         }\r
171     }\r
172     \r
173     @Override\r
174     public void accept(ExpressionVisitor visitor) {\r
175         visitor.visit(this);\r
176     }\r
177     \r
178     public Expression[] getScrutinee() {\r
179         return scrutinee;\r
180     }\r
181     \r
182     public Case[] getCases() {\r
183         return cases;\r
184     }\r
185 \r
186     @Override\r
187     public void forVariables(VariableProcedure procedure) {\r
188         for(Expression s : scrutinee)\r
189             s.forVariables(procedure);\r
190         for(Case case_ : cases)\r
191             case_.forVariables(procedure);\r
192     }\r
193     \r
194     @Override\r
195     public Expression accept(ExpressionTransformer transformer) {\r
196         return transformer.transform(this);\r
197     }\r
198 \r
199 }\r