package org.simantics.scl.compiler.internal.elaboration.matching;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
import org.simantics.scl.compiler.elaboration.expressions.EExternalConstant;
import org.simantics.scl.compiler.elaboration.expressions.ELiteral;
import org.simantics.scl.compiler.elaboration.expressions.EVariable;
+import org.simantics.scl.compiler.elaboration.expressions.EViewPattern;
import org.simantics.scl.compiler.elaboration.expressions.Expression;
import org.simantics.scl.compiler.elaboration.expressions.GuardedExpressionGroup;
import org.simantics.scl.compiler.elaboration.modules.SCLValue;
return newVals;
}
- private static void split(CodeWriter w, final Environment env, IVal[] scrutinee, final ICont success, ICont failure, List<Row> rows, int columnId) {
+ private static void splitByConstructors(CodeWriter w, final Environment env, IVal[] scrutinee, final ICont success, ICont failure, List<Row> rows, int columnId) {
THashMap<Object, ExpressionMatrix> matrixMap = new THashMap<Object, ExpressionMatrix>();
ArrayList<Branch> branches = new ArrayList<Branch>();
ArrayList<ExpressionMatrix> matrices = new ArrayList<ExpressionMatrix>();
Expression constructor_ = applyConstructor.getFunction();
while(constructor_ instanceof EApplyType)
constructor_ = ((EApplyType)constructor_).getExpression();
- SCLValue constructor = ((EConstant)constructor_).getValue();
- // TODO How type parameters are handled???
Expression[] parameters = applyConstructor.getParameters();
-
- ExpressionMatrix matrix = matrixMap.get(constructor.getName());
- if(matrix == null) {
- CodeWriter newW = w.createBlock(Types.getTypes(parameters));
- branches.add(new Branch((Constant)constructor.getValue(), newW.getContinuation()));
- matrix = new ExpressionMatrix(newW, replace(scrutinee, columnId, newW.getParameters()));
- matrices.add(matrix);
- matrixMap.put(constructor.getName(), matrix);
+ // TODO How type parameters are handled???
+ if(constructor_ instanceof EConstant) {
+ SCLValue constructor = ((EConstant)constructor_).getValue();
+
+ ExpressionMatrix matrix = matrixMap.get(constructor.getName());
+ if(matrix == null) {
+ CodeWriter newW = w.createBlock(Types.getTypes(parameters));
+ branches.add(new Branch((Constant)constructor.getValue(), newW.getContinuation()));
+ matrix = new ExpressionMatrix(newW, replace(scrutinee, columnId, newW.getParameters()));
+ matrices.add(matrix);
+ matrixMap.put(constructor.getName(), matrix);
+ }
+ matrix.rows.add(row.replace(columnId, parameters));
+ }
+ else if(constructor_ instanceof ELiteral) {
+ Constant constructor = ((ELiteral)constructor_).getValue();
+
+ ExpressionMatrix matrix = matrixMap.get(constructor);
+ if(matrix == null) {
+ CodeWriter newW = w.createBlock(Types.getTypes(parameters));
+ branches.add(new Branch(constructor, newW.getContinuation()));
+ matrix = new ExpressionMatrix(newW, replace(scrutinee, columnId, newW.getParameters()));
+ matrices.add(matrix);
+ matrixMap.put(constructor, matrix);
+ }
+ matrix.rows.add(row.replace(columnId, parameters));
}
- matrix.rows.add(row.replace(columnId, parameters));
}
else if(pattern instanceof EConstant) {
EConstant applyConstructor = (EConstant)pattern;
} catch (MatchException e) {
throw new InternalCompilerError();
}
- TypeConstructor cons = env.getTypeConstructor(con);
+ TypeConstructor cons = (TypeConstructor)env.getTypeDescriptor(con);
int maxBranchCount = cons.isOpen ? Integer.MAX_VALUE
: cons.constructors.length;
if(branches.size() < maxBranchCount)
w.switch_(scrutinee[columnId], branches.toArray(new Branch[branches.size()]));
}
+ private static void splitByViewPattern(CodeWriter w, Environment env, IVal[] scrutinee, ICont success,
+ ICont failure, List<Row> rows, int viewPatternColumn) {
+ Row firstRow = rows.get(0);
+ EViewPattern firstViewPattern = (EViewPattern)firstRow.patterns[viewPatternColumn];
+ firstRow.patterns[viewPatternColumn] = firstViewPattern.pattern;
+ int i;
+ for(i=1;i<rows.size();++i) {
+ Row row = rows.get(i);
+ Expression pattern = row.patterns[viewPatternColumn];
+ while(true) {
+ if(pattern instanceof EApplyType)
+ pattern = ((EApplyType)pattern).getExpression();
+ else if(pattern instanceof EAsPattern) {
+ EAsPattern asPattern = (EAsPattern)pattern;
+ pattern = asPattern.getPattern();
+ asPattern.getVariable().setVal(scrutinee[viewPatternColumn]);
+ }
+ else
+ break;
+ row.patterns[viewPatternColumn] = pattern;
+ }
+ if(!(pattern instanceof EViewPattern))
+ break;
+ EViewPattern otherViewPattern = (EViewPattern)pattern;
+ if(!otherViewPattern.expression.equalsExpression(firstViewPattern.expression))
+ break;
+ row.patterns[viewPatternColumn] = otherViewPattern.pattern;
+ }
+
+ IVal[] newScrutinee = Arrays.copyOf(scrutinee, scrutinee.length);
+ newScrutinee[viewPatternColumn] =
+ w.apply(firstViewPattern.location,
+ firstViewPattern.expression.toVal(env, w),
+ scrutinee[viewPatternColumn]);
+ if(i == rows.size()) {
+ split(w, env, newScrutinee, success, failure, rows);
+ }
+ else {
+ CodeWriter cont = w.createBlock();
+ split(w, env, newScrutinee, success, cont.getContinuation(), rows.subList(0, i));
+ split(cont, env, scrutinee, success, failure, rows.subList(i, rows.size()));
+ }
+ }
+
public static void split(CodeWriter w, Environment env, IVal[] scrutinee, ICont success, ICont failure, List<Row> rows) {
Row firstRow = rows.get(0);
Expression[] patterns = firstRow.patterns;
if(scrutinee.length != patterns.length)
- throw new InternalCompilerError();
+ throw new InternalCompilerError("Scrutinee and patterns have a different length");
// Find a non-variable pattern and split by it
+ int viewPatternColumn = -1;
for(int i=0;i<patterns.length;++i) {
- if(!(patterns[i] instanceof EVariable)) {
- split(w, env, scrutinee, success, failure, rows, i);
+ Expression pattern = patterns[i];
+ if(pattern instanceof EViewPattern) {
+ if(viewPatternColumn == -1)
+ viewPatternColumn = i;
+ }
+ else if(!(pattern instanceof EVariable)) {
+ splitByConstructors(w, env, scrutinee, success, failure, rows, i);
return;
}
}
+
+ if(viewPatternColumn >= 0) {
+ splitByViewPattern(w, env, scrutinee, success, failure, rows, viewPatternColumn);
+ return;
+ }
- // No matching needed
+ // The first row has only variable patterns: no matching needed
for(int i=0;i<patterns.length;++i)
((EVariable)patterns[i]).getVariable().setVal(scrutinee[i]);
if(firstRow.value instanceof GuardedExpressionGroup) {