--- /dev/null
+package org.simantics.scl.compiler.elaboration.expressions;\r
+\r
+import gnu.trove.map.hash.THashMap;\r
+import gnu.trove.procedure.TObjectObjectProcedure;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;\r
+import org.simantics.scl.compiler.elaboration.errors.NotPatternException;\r
+import org.simantics.scl.compiler.elaboration.expressions.block.LetStatement;\r
+import org.simantics.scl.compiler.elaboration.expressions.lhstype.FunctionDefinitionLhs;\r
+import org.simantics.scl.compiler.elaboration.expressions.lhstype.LhsType;\r
+import org.simantics.scl.compiler.errors.Locations;\r
+\r
+public class EPreLet extends ASTExpression {\r
+\r
+ List<LetStatement> assignments;\r
+ Expression in;\r
+ \r
+ public EPreLet(List<LetStatement> assignments, Expression in) {\r
+ this.assignments = assignments;\r
+ this.in = in;\r
+ }\r
+ \r
+ @Override\r
+ public Expression resolve(final TranslationContext context) {\r
+ context.pushFrame();\r
+ THashMap<String, ArrayList<LetStatement>> functionDefinitions =\r
+ new THashMap<String, ArrayList<LetStatement>>();\r
+ ArrayList<LetStatement> otherDefinitions = new ArrayList<LetStatement>();\r
+ final THashMap<String, Variable> localVars = new THashMap<String, Variable>();\r
+ try {\r
+ for(LetStatement assign : assignments) {\r
+ LhsType lhsType = assign.pattern.getLhsType();\r
+ if(!(assign.pattern instanceof EVar) && lhsType instanceof FunctionDefinitionLhs) {\r
+ String name = ((FunctionDefinitionLhs)lhsType).functionName;\r
+ ArrayList<LetStatement> group = functionDefinitions.get(name);\r
+ if(group == null) {\r
+ group = new ArrayList<LetStatement>(2);\r
+ functionDefinitions.put(name, group);\r
+ }\r
+ group.add(assign);\r
+ localVars.put(name, context.newVariable(name));\r
+ }\r
+ else {\r
+ otherDefinitions.add(assign);\r
+ assign.pattern = assign.pattern.resolveAsPattern(context);\r
+ }\r
+ }\r
+ } catch (NotPatternException e) {\r
+ context.getErrorLog().log(e.getExpression().location, "Not a pattern.");\r
+ return new EError();\r
+ }\r
+ \r
+ final ArrayList<Assignment> as = new ArrayList<Assignment>(functionDefinitions.size() + otherDefinitions.size());\r
+ functionDefinitions.forEachEntry(new TObjectObjectProcedure<String, ArrayList<LetStatement>>() {\r
+ @Override\r
+ public boolean execute(String name, ArrayList<LetStatement> cases) {\r
+ as.add(new Assignment(\r
+ new EVariable(cases.size()==1 ? cases.get(0).pattern.location : location, localVars.get(name)), \r
+ context.translateCases(cases)));\r
+ return true;\r
+ }\r
+ });\r
+ for(LetStatement stat : otherDefinitions)\r
+ as.add(new Assignment(\r
+ stat.pattern /* already resolved above */, \r
+ stat.value.resolve(context)));\r
+ Expression inExpr = in.resolve(context);\r
+ context.popFrame();\r
+ \r
+ ELet result = new ELet(location, as.toArray(new Assignment[as.size()]), inExpr);\r
+ /*System.out.println("-----------------------------------------");\r
+ System.out.println(this);\r
+ System.out.println("-----------------------------------------");\r
+ System.out.println(result);\r
+ System.out.println("-----------------------------------------");*/\r
+ return result;\r
+ }\r
+\r
+ @Override\r
+ public void setLocationDeep(long loc) {\r
+ if(location == Locations.NO_LOCATION) {\r
+ location = loc;\r
+ for(LetStatement assignment : assignments)\r
+ assignment.setLocationDeep(loc);\r
+ in.setLocationDeep(loc);\r
+ }\r
+ }\r
+ \r
+ @Override\r
+ public Expression accept(ExpressionTransformer transformer) {\r
+ return transformer.transform(this);\r
+ }\r
+\r
+}\r