1 package org.simantics.scl.compiler.elaboration.expressions;
3 import java.util.ArrayList;
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;
24 import gnu.trove.map.hash.TObjectIntHashMap;
25 import gnu.trove.set.hash.THashSet;
26 import gnu.trove.set.hash.TIntHashSet;
29 * Generated maily from EPreLet
31 public class ELet extends Expression {
32 public Assignment[] assignments;
35 public ELet(long loc, Assignment[] assignments, Expression in) {
37 this.assignments = assignments;
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);
49 public void collectVars(TObjectIntHashMap<Variable> allVars,
51 for(Assignment assign : assignments)
52 assign.value.collectVars(allVars, vars);
53 in.collectVars(allVars, vars);
57 protected void updateType() throws MatchException {
58 setType(in.getType());
65 public Expression simplify(SimplificationContext context) {
67 // Simplify assignments
68 for(Assignment assignment : assignments) {
69 assignment.value = assignment.value.simplify(context);
72 // Find strongly connected components
73 final TObjectIntHashMap<Variable> allVars = new TObjectIntHashMap<Variable>(
74 2*assignments.length, 0.5f, -1);
76 for(int i=0;i<assignments.length;++i)
77 for(Variable var : assignments[i].pattern.getFreeVariables())
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) {
83 protected int[] findDependencies(int u) {
84 TIntHashSet vars = new TIntHashSet();
85 assignments[u].value.collectVars(allVars, vars);
87 isRecursive[u] = true;
88 return vars.toArray();
92 protected void reportComponent(int[] component) {
93 components.add(component);
99 Expression result = in.simplify(context);
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]];
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);
112 Assignment assignment = assignments[component[0]];
113 Expression pattern = assignment.pattern;
115 if(pattern instanceof EVariable) {
116 EVariable pvar = (EVariable)pattern;
117 result = new ESimpleLet(location, pvar.variable, assignment.value, result);
120 result = new EMatch(location, new Expression[] {assignment.value},
121 new Case(new Expression[] {pattern}, result));
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);
139 public Expression resolve(TranslationContext context) {
140 throw new InternalCompilerError("ELet should be already resolved.");
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);
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]);
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);
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,
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));
185 return in.toVal(context, w);
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());
196 public Expression inferType(TypingContext context) {
197 checkAssignments(context);
198 in = in.inferType(context);
203 public Expression checkBasicType(TypingContext context, Type requiredType) {
204 checkAssignments(context);
205 in = in.checkType(context, requiredType);
210 public Expression checkIgnoredType(TypingContext context) {
211 checkAssignments(context);
212 in = in.checkIgnoredType(context);
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);
225 public void collectEffects(THashSet<Type> effects) {
226 for(Assignment assignment : assignments) {
227 assignment.pattern.collectEffects(effects);
228 assignment.value.collectEffects(effects);
230 in.collectEffects(effects);
234 public void setLocationDeep(long loc) {
235 if(location == Locations.NO_LOCATION) {
237 for(Assignment assignment : assignments)
238 assignment.setLocationDeep(loc);
239 in.setLocationDeep(loc);
244 public void accept(ExpressionVisitor visitor) {
249 public void forVariables(VariableProcedure procedure) {
250 for(Assignment assignment : assignments)
251 assignment.forVariables(procedure);
252 in.forVariables(procedure);
256 public Expression accept(ExpressionTransformer transformer) {
257 return transformer.transform(this);
261 public int getSyntacticFunctionArity() {
262 return in.getSyntacticFunctionArity();