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.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;
23 import gnu.trove.map.hash.TObjectIntHashMap;
24 import gnu.trove.set.hash.TIntHashSet;
27 * Generated maily from EPreLet
29 public class ELet extends Expression {
30 public Assignment[] assignments;
33 public ELet(long loc, Assignment[] assignments, Expression in) {
35 this.assignments = assignments;
40 public void collectVars(TObjectIntHashMap<Variable> allVars,
42 for(Assignment assign : assignments)
43 assign.value.collectVars(allVars, vars);
44 in.collectVars(allVars, vars);
48 protected void updateType() throws MatchException {
49 setType(in.getType());
56 public Expression simplify(SimplificationContext context) {
58 // Simplify assignments
59 for(Assignment assignment : assignments) {
60 assignment.value = assignment.value.simplify(context);
63 // Find strongly connected components
64 final TObjectIntHashMap<Variable> allVars = new TObjectIntHashMap<Variable>(
65 2*assignments.length, 0.5f, -1);
67 for(int i=0;i<assignments.length;++i)
68 for(Variable var : assignments[i].pattern.getFreeVariables())
70 final boolean isRecursive[] = new boolean[assignments.length];
71 final ArrayList<int[]> components = new ArrayList<int[]>(Math.max(10, assignments.length));
72 new StronglyConnectedComponents(assignments.length) {
74 protected int[] findDependencies(int u) {
75 TIntHashSet vars = new TIntHashSet();
76 assignments[u].value.collectVars(allVars, vars);
78 isRecursive[u] = true;
79 return vars.toArray();
83 protected void reportComponent(int[] component) {
84 components.add(component);
90 Expression result = in.simplify(context);
92 // Handle each component
93 for(int j=components.size()-1;j>=0;--j) {
94 int[] component = components.get(j);
95 boolean recursive = component.length > 1 || isRecursive[component[0]];
97 Assignment[] cAssignments = new Assignment[component.length];
98 for(int i=0;i<component.length;++i)
99 cAssignments[i] = assignments[component[i]];
100 result = new ELet(location, cAssignments, result);
103 Assignment assignment = assignments[component[0]];
104 Expression pattern = assignment.pattern;
106 if(pattern instanceof EVariable) {
107 EVariable pvar = (EVariable)pattern;
108 result = new ESimpleLet(location, pvar.variable, assignment.value, result);
111 result = new EMatch(location, new Expression[] {assignment.value},
112 new Case(new Expression[] {pattern}, result));
121 public Expression resolve(TranslationContext context) {
122 throw new InternalCompilerError("ELet should be already resolved.");
126 public Expression replace(ReplaceContext context) {
127 Assignment[] newAssignments = new Assignment[assignments.length];
128 for(int i=0;i<assignments.length;++i)
129 newAssignments[i] = assignments[i].replace(context);
130 Expression newIn = in.replace(context);
131 return new ELet(getLocation(), newAssignments, newIn);
135 public IVal toVal(CompilationContext context, CodeWriter w) {
136 // Create bound variables
137 BoundVar[] vars = new BoundVar[assignments.length];
138 for(int i=0;i<assignments.length;++i) {
139 Expression pattern = assignments[i].pattern;
140 if(!(pattern instanceof EVariable))
141 throw new InternalCompilerError("Cannot handle pattern targets in recursive assignments.");
142 vars[i] = new BoundVar(pattern.getType());
143 ((EVariable)pattern).getVariable().setVal(vars[i]);
147 RecursiveDefinitionWriter rdw = w.createRecursiveDefinition();
148 long range = Locations.NO_LOCATION;
149 for(Assignment assign2 : assignments) {
150 range = Locations.combine(range, assign2.pattern.location);
151 range = Locations.combine(range, assign2.value.location);
153 rdw.setLocation(range);
154 for(int i=0;i<assignments.length;++i) {
155 DecomposedExpression decomposed =
156 DecomposedExpression.decompose(context.errorLog, assignments[i].value);
157 CodeWriter newW = rdw.createFunction(vars[i],
158 decomposed.typeParameters,
160 decomposed.returnType,
161 decomposed.parameterTypes);
162 IVal[] parameters = newW.getParameters();
163 for(int j=0;j<parameters.length;++j)
164 decomposed.parameters[j].setVal(parameters[j]);
165 newW.return_(decomposed.body.toVal(context, newW));
167 return in.toVal(context, w);
170 private void checkAssignments(TypingContext context) {
171 for(Assignment assign : assignments)
172 assign.pattern = assign.pattern.checkTypeAsPattern(context, Types.metaVar(Kinds.STAR));
173 for(Assignment assign : assignments)
174 assign.value = assign.value.checkType(context, assign.pattern.getType());
178 public Expression inferType(TypingContext context) {
179 checkAssignments(context);
180 in = in.inferType(context);
185 public Expression checkBasicType(TypingContext context, Type requiredType) {
186 checkAssignments(context);
187 in = in.checkType(context, requiredType);
192 public Expression checkIgnoredType(TypingContext context) {
193 checkAssignments(context);
194 in = in.checkIgnoredType(context);
199 public void setLocationDeep(long loc) {
200 if(location == Locations.NO_LOCATION) {
202 for(Assignment assignment : assignments)
203 assignment.setLocationDeep(loc);
204 in.setLocationDeep(loc);
209 public void accept(ExpressionVisitor visitor) {
214 public Expression accept(ExpressionTransformer transformer) {
215 return transformer.transform(this);
219 public int getSyntacticFunctionArity() {
220 return in.getSyntacticFunctionArity();