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