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