1 package org.simantics.scl.compiler.elaboration.expressions;
\r
3 import gnu.trove.map.hash.TObjectIntHashMap;
\r
4 import gnu.trove.set.hash.THashSet;
\r
5 import gnu.trove.set.hash.TIntHashSet;
\r
7 import java.util.ArrayList;
\r
9 import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
\r
10 import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext;
\r
11 import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;
\r
12 import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
\r
13 import org.simantics.scl.compiler.elaboration.contexts.TypingContext;
\r
14 import org.simantics.scl.compiler.environment.Environment;
\r
15 import org.simantics.scl.compiler.errors.Locations;
\r
16 import org.simantics.scl.compiler.internal.codegen.references.BoundVar;
\r
17 import org.simantics.scl.compiler.internal.codegen.references.IVal;
\r
18 import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;
\r
19 import org.simantics.scl.compiler.internal.codegen.writer.RecursiveDefinitionWriter;
\r
20 import org.simantics.scl.compiler.internal.elaboration.decomposed.DecomposedExpression;
\r
21 import org.simantics.scl.compiler.internal.elaboration.utils.ExpressionDecorator;
\r
22 import org.simantics.scl.compiler.internal.elaboration.utils.StronglyConnectedComponents;
\r
23 import org.simantics.scl.compiler.types.Type;
\r
24 import org.simantics.scl.compiler.types.Types;
\r
25 import org.simantics.scl.compiler.types.exceptions.MatchException;
\r
26 import org.simantics.scl.compiler.types.kinds.Kinds;
\r
28 public class ELet extends Expression {
\r
29 public Assignment[] assignments;
\r
30 public Expression in;
\r
32 public ELet(long loc, Assignment[] assignments, Expression in) {
\r
34 this.assignments = assignments;
\r
39 public void collectRefs(final TObjectIntHashMap<Object> allRefs, final TIntHashSet refs) {
\r
40 for(Assignment assign : assignments)
\r
41 assign.value.collectRefs(allRefs, refs);
\r
42 in.collectRefs(allRefs, refs);
\r
46 public void collectVars(TObjectIntHashMap<Variable> allVars,
\r
48 for(Assignment assign : assignments)
\r
49 assign.value.collectVars(allVars, vars);
\r
50 in.collectVars(allVars, vars);
\r
54 protected void updateType() throws MatchException {
\r
55 setType(in.getType());
\r
62 public Expression simplify(SimplificationContext context) {
\r
64 // Simplify assignments
\r
65 for(Assignment assignment : assignments) {
\r
66 assignment.value = assignment.value.simplify(context);
\r
69 // Find strongly connected components
\r
70 final TObjectIntHashMap<Variable> allVars = new TObjectIntHashMap<Variable>(
\r
71 2*assignments.length, 0.5f, -1);
\r
73 for(int i=0;i<assignments.length;++i)
\r
74 for(Variable var : assignments[i].pattern.getFreeVariables())
\r
75 allVars.put(var, i);
\r
76 final boolean isRecursive[] = new boolean[assignments.length];
\r
77 final ArrayList<int[]> components = new ArrayList<int[]>(Math.max(10, assignments.length));
\r
78 new StronglyConnectedComponents(assignments.length) {
\r
80 protected int[] findDependencies(int u) {
\r
81 TIntHashSet vars = new TIntHashSet();
\r
82 assignments[u].value.collectVars(allVars, vars);
\r
83 if(vars.contains(u))
\r
84 isRecursive[u] = true;
\r
85 return vars.toArray();
\r
89 protected void reportComponent(int[] component) {
\r
90 components.add(component);
\r
96 Expression result = in.simplify(context);
\r
98 // Handle each component
\r
99 for(int j=components.size()-1;j>=0;--j) {
\r
100 int[] component = components.get(j);
\r
101 boolean recursive = component.length > 1 || isRecursive[component[0]];
\r
103 Assignment[] cAssignments = new Assignment[component.length];
\r
104 for(int i=0;i<component.length;++i)
\r
105 cAssignments[i] = assignments[component[i]];
\r
106 result = new ELet(location, cAssignments, result);
\r
109 Assignment assignment = assignments[component[0]];
\r
110 Expression pattern = assignment.pattern;
\r
112 if(pattern instanceof EVariable) {
\r
113 EVariable pvar = (EVariable)pattern;
\r
114 result = new ESimpleLet(location, pvar.variable, assignment.value, result);
\r
117 result = new EMatch(location, new Expression[] {assignment.value},
\r
118 new Case(new Expression[] {pattern}, result));
\r
127 public void collectFreeVariables(THashSet<Variable> vars) {
\r
128 in.collectFreeVariables(vars);
\r
129 for(Assignment assign : assignments)
\r
130 assign.value.collectFreeVariables(vars);
\r
131 for(Assignment assign : assignments)
\r
132 assign.pattern.removeFreeVariables(vars);
\r
136 public Expression resolve(TranslationContext context) {
\r
137 throw new InternalCompilerError("ELet should be already resolved.");
\r
141 public Expression replace(ReplaceContext context) {
\r
142 Assignment[] newAssignments = new Assignment[assignments.length];
\r
143 for(int i=0;i<assignments.length;++i)
\r
144 newAssignments[i] = assignments[i].replace(context);
\r
145 Expression newIn = in.replace(context);
\r
146 return new ELet(getLocation(), newAssignments, newIn);
\r
150 public IVal toVal(Environment env, CodeWriter w) {
\r
151 // Create bound variables
\r
152 BoundVar[] vars = new BoundVar[assignments.length];
\r
153 for(int i=0;i<assignments.length;++i) {
\r
154 Expression pattern = assignments[i].pattern;
\r
155 if(!(pattern instanceof EVariable))
\r
156 throw new InternalCompilerError("Cannot handle pattern targets in recursive assignments.");
\r
157 vars[i] = new BoundVar(pattern.getType());
\r
158 ((EVariable)pattern).getVariable().setVal(vars[i]);
\r
162 RecursiveDefinitionWriter rdw = w.createRecursiveDefinition();
\r
163 long range = Locations.NO_LOCATION;
\r
164 for(Assignment assign2 : assignments) {
\r
165 range = Locations.combine(range, assign2.pattern.location);
\r
166 range = Locations.combine(range, assign2.value.location);
\r
168 rdw.setLocation(range);
\r
169 for(int i=0;i<assignments.length;++i) {
\r
170 DecomposedExpression decomposed =
\r
171 DecomposedExpression.decompose(assignments[i].value);
\r
172 CodeWriter newW = rdw.createFunction(vars[i],
\r
173 decomposed.typeParameters,
\r
175 decomposed.returnType,
\r
176 decomposed.parameterTypes);
\r
177 IVal[] parameters = newW.getParameters();
\r
178 for(int j=0;j<parameters.length;++j)
\r
179 decomposed.parameters[j].setVal(parameters[j]);
\r
180 newW.return_(decomposed.body.toVal(env, newW));
\r
182 return in.toVal(env, w);
\r
185 private void checkAssignments(TypingContext context) {
\r
186 for(Assignment assign : assignments)
\r
187 assign.pattern = assign.pattern.checkTypeAsPattern(context, Types.metaVar(Kinds.STAR));
\r
188 for(Assignment assign : assignments)
\r
189 assign.value = assign.value.checkType(context, assign.pattern.getType());
\r
193 public Expression inferType(TypingContext context) {
\r
194 checkAssignments(context);
\r
195 in = in.inferType(context);
\r
200 public Expression checkBasicType(TypingContext context, Type requiredType) {
\r
201 checkAssignments(context);
\r
202 in = in.checkType(context, requiredType);
\r
207 public Expression decorate(ExpressionDecorator decorator) {
\r
208 in = in.decorate(decorator);
\r
209 for(Assignment assignment : assignments)
\r
210 assignment.decorate(decorator);
\r
211 return decorator.decorate(this);
\r
215 public void collectEffects(THashSet<Type> effects) {
\r
216 for(Assignment assignment : assignments) {
\r
217 assignment.pattern.collectEffects(effects);
\r
218 assignment.value.collectEffects(effects);
\r
220 in.collectEffects(effects);
\r
224 public void setLocationDeep(long loc) {
\r
225 if(location == Locations.NO_LOCATION) {
\r
227 for(Assignment assignment : assignments)
\r
228 assignment.setLocationDeep(loc);
\r
229 in.setLocationDeep(loc);
\r
234 public void accept(ExpressionVisitor visitor) {
\r
235 visitor.visit(this);
\r
239 public void forVariables(VariableProcedure procedure) {
\r
240 for(Assignment assignment : assignments)
\r
241 assignment.forVariables(procedure);
\r
242 in.forVariables(procedure);
\r
246 public Expression accept(ExpressionTransformer transformer) {
\r
247 return transformer.transform(this);
\r