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.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;
24 import gnu.trove.map.hash.TObjectIntHashMap;
25 import gnu.trove.set.hash.THashSet;
26 import gnu.trove.set.hash.TIntHashSet;
28 public class ELet extends Expression {
29 public Assignment[] assignments;
32 public ELet(long loc, Assignment[] assignments, Expression in) {
34 this.assignments = assignments;
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);
46 public void collectVars(TObjectIntHashMap<Variable> allVars,
48 for(Assignment assign : assignments)
49 assign.value.collectVars(allVars, vars);
50 in.collectVars(allVars, vars);
54 protected void updateType() throws MatchException {
55 setType(in.getType());
62 public Expression simplify(SimplificationContext context) {
64 // Simplify assignments
65 for(Assignment assignment : assignments) {
66 assignment.value = assignment.value.simplify(context);
69 // Find strongly connected components
70 final TObjectIntHashMap<Variable> allVars = new TObjectIntHashMap<Variable>(
71 2*assignments.length, 0.5f, -1);
73 for(int i=0;i<assignments.length;++i)
74 for(Variable var : assignments[i].pattern.getFreeVariables())
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) {
80 protected int[] findDependencies(int u) {
81 TIntHashSet vars = new TIntHashSet();
82 assignments[u].value.collectVars(allVars, vars);
84 isRecursive[u] = true;
85 return vars.toArray();
89 protected void reportComponent(int[] component) {
90 components.add(component);
96 Expression result = in.simplify(context);
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]];
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);
109 Assignment assignment = assignments[component[0]];
110 Expression pattern = assignment.pattern;
112 if(pattern instanceof EVariable) {
113 EVariable pvar = (EVariable)pattern;
114 result = new ESimpleLet(location, pvar.variable, assignment.value, result);
117 result = new EMatch(location, new Expression[] {assignment.value},
118 new Case(new Expression[] {pattern}, result));
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);
136 public Expression resolve(TranslationContext context) {
137 throw new InternalCompilerError("ELet should be already resolved.");
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);
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]);
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);
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,
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));
182 return in.toVal(env, w);
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());
193 public Expression inferType(TypingContext context) {
194 checkAssignments(context);
195 in = in.inferType(context);
200 public Expression checkBasicType(TypingContext context, Type requiredType) {
201 checkAssignments(context);
202 in = in.checkType(context, requiredType);
207 public Expression checkIgnoredType(TypingContext context) {
208 checkAssignments(context);
209 in = in.checkIgnoredType(context);
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);
222 public void collectEffects(THashSet<Type> effects) {
223 for(Assignment assignment : assignments) {
224 assignment.pattern.collectEffects(effects);
225 assignment.value.collectEffects(effects);
227 in.collectEffects(effects);
231 public void setLocationDeep(long loc) {
232 if(location == Locations.NO_LOCATION) {
234 for(Assignment assignment : assignments)
235 assignment.setLocationDeep(loc);
236 in.setLocationDeep(loc);
241 public void accept(ExpressionVisitor visitor) {
246 public void forVariables(VariableProcedure procedure) {
247 for(Assignment assignment : assignments)
248 assignment.forVariables(procedure);
249 in.forVariables(procedure);
253 public Expression accept(ExpressionTransformer transformer) {
254 return transformer.transform(this);
258 public int getSyntacticFunctionArity() {
259 return in.getSyntacticFunctionArity();