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