]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ELet.java
bbbc25c4de4ed7e7841172fb44f96834c5a15b85
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / elaboration / expressions / ELet.java
1 package org.simantics.scl.compiler.elaboration.expressions;\r
2 \r
3 import java.util.ArrayList;\r
4 \r
5 import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;\r
6 import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext;\r
7 import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;\r
8 import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;\r
9 import org.simantics.scl.compiler.elaboration.contexts.TypingContext;\r
10 import org.simantics.scl.compiler.environment.Environment;\r
11 import org.simantics.scl.compiler.errors.Locations;\r
12 import org.simantics.scl.compiler.internal.codegen.references.BoundVar;\r
13 import org.simantics.scl.compiler.internal.codegen.references.IVal;\r
14 import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;\r
15 import org.simantics.scl.compiler.internal.codegen.writer.RecursiveDefinitionWriter;\r
16 import org.simantics.scl.compiler.internal.elaboration.decomposed.DecomposedExpression;\r
17 import org.simantics.scl.compiler.internal.elaboration.utils.ExpressionDecorator;\r
18 import org.simantics.scl.compiler.internal.elaboration.utils.StronglyConnectedComponents;\r
19 import org.simantics.scl.compiler.types.Type;\r
20 import org.simantics.scl.compiler.types.Types;\r
21 import org.simantics.scl.compiler.types.exceptions.MatchException;\r
22 import org.simantics.scl.compiler.types.kinds.Kinds;\r
23 \r
24 import gnu.trove.map.hash.TObjectIntHashMap;\r
25 import gnu.trove.set.hash.THashSet;\r
26 import gnu.trove.set.hash.TIntHashSet;\r
27 \r
28 public class ELet extends Expression {\r
29     public Assignment[] assignments;\r
30     public Expression in;\r
31     \r
32     public ELet(long loc, Assignment[] assignments, Expression in) {\r
33         super(loc);\r
34         this.assignments = assignments;\r
35         this.in = in;\r
36     }\r
37 \r
38     @Override\r
39     public void collectRefs(final TObjectIntHashMap<Object> allRefs, final TIntHashSet refs) {\r
40         for(Assignment assign : assignments)\r
41             assign.value.collectRefs(allRefs, refs);\r
42         in.collectRefs(allRefs, refs);\r
43     }\r
44     \r
45     @Override\r
46     public void collectVars(TObjectIntHashMap<Variable> allVars,\r
47             TIntHashSet vars) {\r
48         for(Assignment assign : assignments)\r
49             assign.value.collectVars(allVars, vars);\r
50         in.collectVars(allVars, vars);\r
51     }\r
52     \r
53     @Override\r
54     protected void updateType() throws MatchException {\r
55         setType(in.getType());\r
56     }\r
57    \r
58     /**\r
59      * Splits let \r
60      */\r
61     @Override\r
62     public Expression simplify(SimplificationContext context) {\r
63         \r
64         // Simplify assignments\r
65         for(Assignment assignment : assignments) {\r
66             assignment.value = assignment.value.simplify(context);\r
67         }\r
68         \r
69         // Find strongly connected components\r
70         final TObjectIntHashMap<Variable> allVars = new TObjectIntHashMap<Variable>(\r
71                 2*assignments.length, 0.5f, -1);\r
72 \r
73         for(int i=0;i<assignments.length;++i)\r
74             for(Variable var : assignments[i].pattern.getFreeVariables())\r
75                 allVars.put(var, i);\r
76         final boolean isRecursive[] = new boolean[assignments.length];\r
77         final ArrayList<int[]> components = new ArrayList<int[]>(Math.max(10, assignments.length)); \r
78         new StronglyConnectedComponents(assignments.length) {\r
79             @Override\r
80             protected int[] findDependencies(int u) {\r
81                 TIntHashSet vars = new TIntHashSet();\r
82                 assignments[u].value.collectVars(allVars, vars);\r
83                 if(vars.contains(u))\r
84                     isRecursive[u] = true;\r
85                 return vars.toArray();\r
86             }\r
87 \r
88             @Override\r
89             protected void reportComponent(int[] component) {\r
90                 components.add(component);\r
91             }\r
92 \r
93         }.findComponents();\r
94 \r
95         // Simplify in\r
96         Expression result = in.simplify(context);\r
97         \r
98         // Handle each component\r
99         for(int j=components.size()-1;j>=0;--j) {\r
100             int[] component = components.get(j);\r
101             boolean recursive = component.length > 1 || isRecursive[component[0]];\r
102             if(recursive) {\r
103                 Assignment[] cAssignments = new Assignment[component.length];\r
104                 for(int i=0;i<component.length;++i)\r
105                     cAssignments[i] = assignments[component[i]];\r
106                 result = new ELet(location, cAssignments, result);\r
107             }\r
108             else {\r
109                 Assignment assignment = assignments[component[0]];\r
110                 Expression pattern = assignment.pattern;\r
111                 \r
112                 if(pattern instanceof EVariable) {\r
113                     EVariable pvar = (EVariable)pattern;\r
114                     result = new ESimpleLet(location, pvar.variable, assignment.value, result);\r
115                 }\r
116                 else {\r
117                     result = new EMatch(location, new Expression[] {assignment.value},\r
118                                     new Case(new Expression[] {pattern}, result));\r
119                 }\r
120             }\r
121         }\r
122         \r
123         return result;\r
124     }\r
125 \r
126     @Override\r
127     public void collectFreeVariables(THashSet<Variable> vars) {\r
128         in.collectFreeVariables(vars);\r
129         for(Assignment assign : assignments)\r
130             assign.value.collectFreeVariables(vars);\r
131         for(Assignment assign : assignments) \r
132             assign.pattern.removeFreeVariables(vars);\r
133     }\r
134 \r
135     @Override\r
136     public Expression resolve(TranslationContext context) {\r
137         throw new InternalCompilerError("ELet should be already resolved.");\r
138     }\r
139     \r
140     @Override\r
141     public Expression replace(ReplaceContext context) {\r
142         Assignment[] newAssignments = new Assignment[assignments.length];\r
143         for(int i=0;i<assignments.length;++i)\r
144             newAssignments[i] = assignments[i].replace(context);            \r
145         Expression newIn = in.replace(context);\r
146         return new ELet(getLocation(), newAssignments, newIn);\r
147     }\r
148     \r
149     @Override\r
150     public IVal toVal(Environment env, CodeWriter w) {\r
151         // Create bound variables\r
152         BoundVar[] vars = new BoundVar[assignments.length];\r
153         for(int i=0;i<assignments.length;++i) {\r
154             Expression pattern = assignments[i].pattern;\r
155             if(!(pattern instanceof EVariable))\r
156                 throw new InternalCompilerError("Cannot handle pattern targets in recursive assignments.");\r
157             vars[i] = new BoundVar(pattern.getType());\r
158             ((EVariable)pattern).getVariable().setVal(vars[i]);\r
159         }\r
160         \r
161         // Create values\r
162         RecursiveDefinitionWriter rdw = w.createRecursiveDefinition();\r
163         long range = Locations.NO_LOCATION;\r
164         for(Assignment assign2 : assignments) {\r
165             range = Locations.combine(range, assign2.pattern.location);\r
166             range = Locations.combine(range, assign2.value.location);\r
167         }\r
168         rdw.setLocation(range);\r
169         for(int i=0;i<assignments.length;++i) {\r
170             DecomposedExpression decomposed = \r
171                     DecomposedExpression.decompose(assignments[i].value);\r
172             CodeWriter newW = rdw.createFunction(vars[i], \r
173                     decomposed.typeParameters,\r
174                     decomposed.effect,\r
175                     decomposed.returnType, \r
176                     decomposed.parameterTypes);\r
177             IVal[] parameters = newW.getParameters();\r
178             for(int j=0;j<parameters.length;++j)\r
179                 decomposed.parameters[j].setVal(parameters[j]);\r
180             newW.return_(decomposed.body.toVal(env, newW));\r
181         }\r
182         return in.toVal(env, w);\r
183     }\r
184         \r
185     private void checkAssignments(TypingContext context) {\r
186         for(Assignment assign : assignments)\r
187             assign.pattern = assign.pattern.checkTypeAsPattern(context, Types.metaVar(Kinds.STAR));\r
188         for(Assignment assign : assignments)\r
189             assign.value = assign.value.checkType(context, assign.pattern.getType());\r
190     }\r
191     \r
192     @Override\r
193     public Expression inferType(TypingContext context) {\r
194         checkAssignments(context);\r
195         in = in.inferType(context);\r
196         return this;\r
197     }\r
198     \r
199     @Override\r
200     public Expression checkBasicType(TypingContext context, Type requiredType) {\r
201         checkAssignments(context);\r
202         in = in.checkType(context, requiredType);\r
203         return this;\r
204     }\r
205     \r
206     @Override\r
207     public Expression checkIgnoredType(TypingContext context) {\r
208         checkAssignments(context);\r
209         in = in.checkIgnoredType(context);\r
210         return this;\r
211     }\r
212 \r
213     @Override\r
214     public Expression decorate(ExpressionDecorator decorator) {\r
215         in = in.decorate(decorator);\r
216         for(Assignment assignment : assignments)\r
217             assignment.decorate(decorator);\r
218         return decorator.decorate(this);\r
219     }\r
220 \r
221     @Override\r
222     public void collectEffects(THashSet<Type> effects) {\r
223         for(Assignment assignment : assignments) {\r
224             assignment.pattern.collectEffects(effects);\r
225             assignment.value.collectEffects(effects);\r
226         }\r
227         in.collectEffects(effects);\r
228     }\r
229     \r
230     @Override\r
231     public void setLocationDeep(long loc) {\r
232         if(location == Locations.NO_LOCATION) {\r
233             location = loc;\r
234             for(Assignment assignment : assignments)\r
235                 assignment.setLocationDeep(loc);\r
236             in.setLocationDeep(loc);\r
237         }\r
238     }\r
239     \r
240     @Override\r
241     public void accept(ExpressionVisitor visitor) {\r
242         visitor.visit(this);\r
243     }\r
244 \r
245     @Override\r
246     public void forVariables(VariableProcedure procedure) {\r
247         for(Assignment assignment : assignments)\r
248             assignment.forVariables(procedure);\r
249         in.forVariables(procedure);\r
250     }\r
251     \r
252     @Override\r
253     public Expression accept(ExpressionTransformer transformer) {\r
254         return transformer.transform(this);\r
255     }\r
256 \r
257 }\r