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