]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/elaboration/matching2/PatternMatchingCompiler2.java
(refs #7278, refs #7279) Small fixes to InternalCompilerExceptions
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / internal / elaboration / matching2 / PatternMatchingCompiler2.java
index 7849300deb594b23dc3834af60a1393490656ff7..8ca51b275f900a439d5b7a5025ab3d2e96444588 100644 (file)
-package org.simantics.scl.compiler.internal.elaboration.matching2;\r
-\r
-import java.util.ArrayList;\r
-import java.util.Arrays;\r
-import java.util.List;\r
-\r
-import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;\r
-import org.simantics.scl.compiler.constants.Constant;\r
-import org.simantics.scl.compiler.elaboration.expressions.EApply;\r
-import org.simantics.scl.compiler.elaboration.expressions.EApplyType;\r
-import org.simantics.scl.compiler.elaboration.expressions.EAsPattern;\r
-import org.simantics.scl.compiler.elaboration.expressions.EConstant;\r
-import org.simantics.scl.compiler.elaboration.expressions.EExternalConstant;\r
-import org.simantics.scl.compiler.elaboration.expressions.ELiteral;\r
-import org.simantics.scl.compiler.elaboration.expressions.EVariable;\r
-import org.simantics.scl.compiler.elaboration.expressions.EViewPattern;\r
-import org.simantics.scl.compiler.elaboration.expressions.Expression;\r
-import org.simantics.scl.compiler.elaboration.modules.SCLValue;\r
-import org.simantics.scl.compiler.elaboration.modules.TypeConstructor;\r
-import org.simantics.scl.compiler.environment.Environment;\r
-import org.simantics.scl.compiler.internal.codegen.continuations.Branch;\r
-import org.simantics.scl.compiler.internal.codegen.continuations.ICont;\r
-import org.simantics.scl.compiler.internal.codegen.references.IVal;\r
-import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;\r
-import org.simantics.scl.compiler.types.TCon;\r
-import org.simantics.scl.compiler.types.Types;\r
-import org.simantics.scl.compiler.types.exceptions.MatchException;\r
-\r
-import gnu.trove.map.hash.THashMap;\r
-\r
-public class PatternMatchingCompiler2 {\r
-\r
-    private static class ExpressionMatrix {\r
-        final CodeWriter w;\r
-        final IVal[] scrutinee;\r
-        final List<Row2> rows = new ArrayList<Row2>();\r
-\r
-        public ExpressionMatrix(CodeWriter w, IVal[] scrutinee) {\r
-            this.w = w;\r
-            this.scrutinee = scrutinee;\r
-        }\r
-    }\r
-\r
-    public static IVal[] replace(IVal[] vals, int columnToReplace, IVal ... substitution) {\r
-        IVal[] newVals = new IVal[vals.length-1+substitution.length];\r
-        int j=0;\r
-        for(int i=0;i<columnToReplace;++i)\r
-            newVals[j++] = vals[i];\r
-        for(int i=0;i<substitution.length;++i)\r
-            newVals[j++] = substitution[i];\r
-        for(int i=columnToReplace+1;i<vals.length;++i)\r
-            newVals[j++] = vals[i];\r
-        return newVals;\r
-    }\r
-\r
-    private static void splitByConstructors(CodeWriter w, final Environment env, IVal[] scrutinee, ICont failure, List<Row2> rows, int columnId) {\r
-        THashMap<Object, ExpressionMatrix> matrixMap = new THashMap<Object, ExpressionMatrix>();\r
-        ArrayList<Branch> branches = new ArrayList<Branch>();\r
-        ArrayList<ExpressionMatrix> matrices = new ArrayList<ExpressionMatrix>();\r
-        \r
-        /*System.out.println("---");\r
-        for(Row row : rows) {\r
-            for(Expression e : row.patterns)\r
-                System.out.print(e + " ");\r
-            System.out.println();\r
-        }*/\r
-\r
-        int i;\r
-        for(i=0;i<rows.size();++i) {\r
-            Row2 row = rows.get(i);\r
-            Expression pattern = row.patterns[columnId];\r
-            while(true) {\r
-                if(pattern instanceof EApplyType)\r
-                    pattern = ((EApplyType)pattern).getExpression();\r
-                else if(pattern instanceof EAsPattern) {\r
-                    EAsPattern asPattern = (EAsPattern)pattern;\r
-                    pattern = asPattern.getPattern();\r
-                    asPattern.getVariable().setVal(scrutinee[columnId]);\r
-                }\r
-                else\r
-                    break;\r
-                row.patterns[columnId] = pattern;\r
-            }\r
-            if(pattern instanceof EVariable)\r
-                break;\r
-            else if(pattern instanceof EApply) {\r
-                EApply applyConstructor = (EApply)pattern;\r
-                Expression constructor_ = applyConstructor.getFunction();\r
-                while(constructor_ instanceof EApplyType)\r
-                    constructor_ = ((EApplyType)constructor_).getExpression();\r
-                Expression[] parameters = applyConstructor.getParameters();\r
-                // TODO How type parameters are handled???\r
-                if(constructor_ instanceof EConstant) {\r
-                    SCLValue constructor = ((EConstant)constructor_).getValue();\r
-    \r
-                    ExpressionMatrix matrix = matrixMap.get(constructor.getName());\r
-                    if(matrix == null) {\r
-                        CodeWriter newW = w.createBlock(Types.getTypes(parameters));\r
-                        branches.add(new Branch((Constant)constructor.getValue(), newW.getContinuation()));\r
-                        matrix = new ExpressionMatrix(newW, replace(scrutinee, columnId, newW.getParameters()));\r
-                        matrices.add(matrix);\r
-                        matrixMap.put(constructor.getName(), matrix);\r
-                    }\r
-                    matrix.rows.add(row.replace(columnId, parameters));\r
-                }\r
-                else if(constructor_ instanceof ELiteral) {\r
-                    Constant constructor = ((ELiteral)constructor_).getValue();\r
-                    \r
-                    ExpressionMatrix matrix = matrixMap.get(constructor);\r
-                    if(matrix == null) {\r
-                        CodeWriter newW = w.createBlock(Types.getTypes(parameters));\r
-                        branches.add(new Branch(constructor, newW.getContinuation()));\r
-                        matrix = new ExpressionMatrix(newW, replace(scrutinee, columnId, newW.getParameters()));\r
-                        matrices.add(matrix);\r
-                        matrixMap.put(constructor, matrix);\r
-                    }\r
-                    matrix.rows.add(row.replace(columnId, parameters));\r
-                }\r
-            }\r
-            else if(pattern instanceof EConstant) {\r
-                EConstant applyConstructor = (EConstant)pattern;\r
-                SCLValue constructor = applyConstructor.getValue();\r
-\r
-                ExpressionMatrix matrix = matrixMap.get(constructor.getName());\r
-                if(matrix == null) {\r
-                    CodeWriter newW = w.createBlock();\r
-                    branches.add(new Branch((Constant)constructor.getValue(), newW.getContinuation()));\r
-                    matrix = new ExpressionMatrix(newW, replace(scrutinee, columnId, newW.getParameters()));\r
-                    matrices.add(matrix);\r
-                    matrixMap.put(constructor.getName(), matrix);\r
-                }\r
-                matrix.rows.add(row.replace(columnId, Expression.EMPTY_ARRAY));\r
-            }\r
-            else if(pattern instanceof ELiteral) {\r
-                ELiteral literal = (ELiteral)pattern;\r
-                Constant constructor = literal.getValue();\r
-\r
-                ExpressionMatrix matrix = matrixMap.get(constructor);\r
-                if(matrix == null) {\r
-                    CodeWriter newW = w.createBlock();\r
-                    branches.add(new Branch(constructor, newW.getContinuation()));\r
-                    matrix = new ExpressionMatrix(newW, replace(scrutinee, columnId, newW.getParameters()));\r
-                    matrices.add(matrix);\r
-                    matrixMap.put(constructor, matrix);\r
-                }\r
-                matrix.rows.add(row.replace(columnId, Expression.EMPTY_ARRAY));\r
-            }\r
-            else if(pattern instanceof EExternalConstant) {\r
-                EExternalConstant constant = (EExternalConstant)pattern;\r
-                Constant constructor = w.getModuleWriter().getExternalConstant(constant.getValue(), constant.getType());\r
-\r
-                ExpressionMatrix matrix = matrixMap.get(constructor);\r
-                if(matrix == null) {\r
-                    CodeWriter newW = w.createBlock();\r
-                    branches.add(new Branch(constructor, newW.getContinuation()));\r
-                    matrix = new ExpressionMatrix(newW, replace(scrutinee, columnId, newW.getParameters()));\r
-                    matrices.add(matrix);\r
-                    matrixMap.put(constructor, matrix);\r
-                }\r
-                matrix.rows.add(row.replace(columnId, Expression.EMPTY_ARRAY));\r
-            }\r
-            else\r
-                throw new InternalCompilerError("Cannot handle an instance of " + pattern.getClass().getSimpleName() + " in a pattern.");\r
-        }\r
-        if(i < rows.size()) {\r
-            CodeWriter newW = w.createBlock();\r
-            ICont cont = newW.getContinuation();\r
-            branches.add(new Branch(null, cont));\r
-            split(newW, env, scrutinee, failure, rows.subList(i, rows.size()));\r
-            failure = cont;\r
-        }\r
-        else {\r
-            TCon con;\r
-            try {\r
-                con = Types.getConstructor(scrutinee[columnId].getType());\r
-            } catch (MatchException e) {\r
-                throw new InternalCompilerError(e);\r
-            }\r
-            TypeConstructor cons = (TypeConstructor)env.getTypeDescriptor(con);\r
-            int maxBranchCount = cons.isOpen ? Integer.MAX_VALUE \r
-                    : cons.constructors.length;\r
-            if(branches.size() < maxBranchCount)\r
-                branches.add(new Branch(null, failure));\r
-        }\r
-\r
-        for(ExpressionMatrix mx : matrices)\r
-            split(mx.w, env, mx.scrutinee, failure, mx.rows);\r
-        w.switch_(scrutinee[columnId], branches.toArray(new Branch[branches.size()]));\r
-    }\r
-\r
-    private static void splitByViewPattern(CodeWriter w, Environment env, IVal[] scrutinee, ICont failure, List<Row2> rows, int viewPatternColumn) {\r
-        Row2 firstRow = rows.get(0);\r
-        EViewPattern firstViewPattern = (EViewPattern)firstRow.patterns[viewPatternColumn];\r
-        firstRow.patterns[viewPatternColumn] = firstViewPattern.pattern;\r
-        int i;\r
-        for(i=1;i<rows.size();++i) {\r
-            Row2 row = rows.get(i);\r
-            Expression pattern = row.patterns[viewPatternColumn];\r
-            while(true) {\r
-                if(pattern instanceof EApplyType)\r
-                    pattern = ((EApplyType)pattern).getExpression();\r
-                else if(pattern instanceof EAsPattern) {\r
-                    EAsPattern asPattern = (EAsPattern)pattern;\r
-                    pattern = asPattern.getPattern();\r
-                    asPattern.getVariable().setVal(scrutinee[viewPatternColumn]);\r
-                }\r
-                else\r
-                    break;\r
-                row.patterns[viewPatternColumn] = pattern;\r
-            }\r
-            if(!(pattern instanceof EViewPattern))\r
-                break;\r
-            EViewPattern otherViewPattern = (EViewPattern)pattern;\r
-            if(!otherViewPattern.expression.equalsExpression(firstViewPattern.expression))\r
-                break;\r
-            row.patterns[viewPatternColumn] = otherViewPattern.pattern;\r
-        }\r
-        \r
-        IVal[] newScrutinee = Arrays.copyOf(scrutinee, scrutinee.length);\r
-        newScrutinee[viewPatternColumn] =\r
-                w.apply(firstViewPattern.location,\r
-                        firstViewPattern.expression.toVal(env, w),\r
-                        scrutinee[viewPatternColumn]);\r
-        if(i == rows.size()) {\r
-            split(w, env, newScrutinee, failure, rows);\r
-        }\r
-        else {\r
-            CodeWriter cont = w.createBlock();\r
-            split(w, env, newScrutinee, cont.getContinuation(), rows.subList(0, i));\r
-            split(cont, env, scrutinee, failure, rows.subList(i, rows.size()));\r
-        }\r
-    }\r
-\r
-    public static void split(CodeWriter w, Environment env, IVal[] scrutinee, ICont failure, List<Row2> rows) {\r
-        Row2 firstRow = rows.get(0);\r
-        Expression[] patterns = firstRow.patterns;\r
-        if(scrutinee.length != patterns.length)\r
-            throw new InternalCompilerError("Scrutinee and patterns have a different length");\r
-        \r
-        // Find a non-variable pattern and split by it\r
-        int viewPatternColumn = -1;\r
-        for(int i=0;i<patterns.length;++i) {\r
-            Expression pattern = patterns[i];\r
-            if(pattern instanceof EViewPattern) {\r
-                if(viewPatternColumn == -1)\r
-                    viewPatternColumn = i;\r
-            }\r
-            else if(!(pattern instanceof EVariable)) {\r
-                splitByConstructors(w, env, scrutinee, failure, rows, i);\r
-                return;\r
-            }\r
-        }\r
-        \r
-        if(viewPatternColumn >= 0) {\r
-            splitByViewPattern(w, env, scrutinee, failure, rows, viewPatternColumn);\r
-            return;\r
-        }\r
-\r
-        // The first row has only variable patterns: no matching needed\r
-        for(int i=0;i<patterns.length;++i)\r
-            ((EVariable)patterns[i]).getVariable().setVal(scrutinee[i]);\r
-        w.jump(firstRow.continuation);\r
-    }\r
-}\r
+package org.simantics.scl.compiler.internal.elaboration.matching2;
+
+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.compilation.CompilationContext;
+import org.simantics.scl.compiler.constants.Constant;
+import org.simantics.scl.compiler.elaboration.expressions.EApply;
+import org.simantics.scl.compiler.elaboration.expressions.EApplyType;
+import org.simantics.scl.compiler.elaboration.expressions.EAsPattern;
+import org.simantics.scl.compiler.elaboration.expressions.EConstant;
+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.modules.SCLValue;
+import org.simantics.scl.compiler.elaboration.modules.TypeConstructor;
+import org.simantics.scl.compiler.internal.codegen.continuations.Branch;
+import org.simantics.scl.compiler.internal.codegen.continuations.ICont;
+import org.simantics.scl.compiler.internal.codegen.references.IVal;
+import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;
+import org.simantics.scl.compiler.types.TCon;
+import org.simantics.scl.compiler.types.Types;
+import org.simantics.scl.compiler.types.exceptions.MatchException;
+
+import gnu.trove.map.hash.THashMap;
+
+public class PatternMatchingCompiler2 {
+
+    private static class ExpressionMatrix {
+        final CodeWriter w;
+        final IVal[] scrutinee;
+        final List<Row2> rows = new ArrayList<Row2>();
+
+        public ExpressionMatrix(CodeWriter w, IVal[] scrutinee) {
+            this.w = w;
+            this.scrutinee = scrutinee;
+        }
+    }
+
+    public static IVal[] replace(IVal[] vals, int columnToReplace, IVal ... substitution) {
+        IVal[] newVals = new IVal[vals.length-1+substitution.length];
+        int j=0;
+        for(int i=0;i<columnToReplace;++i)
+            newVals[j++] = vals[i];
+        for(int i=0;i<substitution.length;++i)
+            newVals[j++] = substitution[i];
+        for(int i=columnToReplace+1;i<vals.length;++i)
+            newVals[j++] = vals[i];
+        return newVals;
+    }
+
+    private static void splitByConstructors(CodeWriter w, final CompilationContext context, IVal[] scrutinee, ICont failure, List<Row2> rows, int columnId) {
+        THashMap<Object, ExpressionMatrix> matrixMap = new THashMap<Object, ExpressionMatrix>();
+        ArrayList<Branch> branches = new ArrayList<Branch>();
+        ArrayList<ExpressionMatrix> matrices = new ArrayList<ExpressionMatrix>();
+        
+        /*System.out.println("---");
+        for(Row row : rows) {
+            for(Expression e : row.patterns)
+                System.out.print(e + " ");
+            System.out.println();
+        }*/
+
+        int i;
+        for(i=0;i<rows.size();++i) {
+            Row2 row = rows.get(i);
+            Expression pattern = row.patterns[columnId];
+            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[columnId]);
+                }
+                else
+                    break;
+                row.patterns[columnId] = pattern;
+            }
+            if(pattern instanceof EVariable)
+                break;
+            else if(pattern instanceof EApply) {
+                EApply applyConstructor = (EApply)pattern;
+                Expression constructor_ = applyConstructor.getFunction();
+                while(constructor_ instanceof EApplyType)
+                    constructor_ = ((EApplyType)constructor_).getExpression();
+                Expression[] parameters = applyConstructor.getParameters();
+                // 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));
+                }
+            }
+            else if(pattern instanceof EConstant) {
+                EConstant applyConstructor = (EConstant)pattern;
+                SCLValue constructor = applyConstructor.getValue();
+
+                ExpressionMatrix matrix = matrixMap.get(constructor.getName());
+                if(matrix == null) {
+                    CodeWriter newW = w.createBlock();
+                    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, Expression.EMPTY_ARRAY));
+            }
+            else if(pattern instanceof ELiteral) {
+                ELiteral literal = (ELiteral)pattern;
+                Constant constructor = literal.getValue();
+
+                ExpressionMatrix matrix = matrixMap.get(constructor);
+                if(matrix == null) {
+                    CodeWriter newW = w.createBlock();
+                    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, Expression.EMPTY_ARRAY));
+            }
+            else if(pattern instanceof EExternalConstant) {
+                EExternalConstant constant = (EExternalConstant)pattern;
+                Constant constructor = w.getModuleWriter().getExternalConstant(constant.getValue(), constant.getType());
+
+                ExpressionMatrix matrix = matrixMap.get(constructor);
+                if(matrix == null) {
+                    CodeWriter newW = w.createBlock();
+                    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, Expression.EMPTY_ARRAY));
+            }
+            else
+                throw new InternalCompilerError("Cannot handle an instance of " + pattern.getClass().getSimpleName() + " in a pattern.");
+        }
+        if(i < rows.size()) {
+            CodeWriter newW = w.createBlock();
+            ICont cont = newW.getContinuation();
+            branches.add(new Branch(null, cont));
+            split(newW, context, scrutinee, failure, rows.subList(i, rows.size()));
+            failure = cont;
+        }
+        else {
+            TCon con;
+            try {
+                con = Types.getConstructor(scrutinee[columnId].getType());
+            } catch (MatchException e) {
+                throw new InternalCompilerError(e);
+            }
+            TypeConstructor cons = (TypeConstructor)context.environment.getTypeDescriptor(con);
+            int maxBranchCount = cons.isOpen ? Integer.MAX_VALUE 
+                    : cons.constructors.length;
+            if(branches.size() < maxBranchCount)
+                branches.add(new Branch(null, failure));
+        }
+
+        for(ExpressionMatrix mx : matrices)
+            split(mx.w, context, mx.scrutinee, failure, mx.rows);
+        w.switch_(scrutinee[columnId], branches.toArray(new Branch[branches.size()]));
+    }
+
+    private static void splitByViewPattern(CodeWriter w, CompilationContext context, IVal[] scrutinee, ICont failure, List<Row2> rows, int viewPatternColumn) {
+        Row2 firstRow = rows.get(0);
+        EViewPattern firstViewPattern = (EViewPattern)firstRow.patterns[viewPatternColumn];
+        firstRow.patterns[viewPatternColumn] = firstViewPattern.pattern;
+        int i;
+        for(i=1;i<rows.size();++i) {
+            Row2 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(context, w),
+                        scrutinee[viewPatternColumn]);
+        if(i == rows.size()) {
+            split(w, context, newScrutinee, failure, rows);
+        }
+        else {
+            CodeWriter cont = w.createBlock();
+            split(w, context, newScrutinee, cont.getContinuation(), rows.subList(0, i));
+            split(cont, context, scrutinee, failure, rows.subList(i, rows.size()));
+        }
+    }
+
+    public static void split(CodeWriter w, CompilationContext context, IVal[] scrutinee, ICont failure, List<Row2> rows) {
+        Row2 firstRow = rows.get(0);
+        Expression[] patterns = firstRow.patterns;
+        if(scrutinee.length != patterns.length)
+            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) {
+            Expression pattern = patterns[i];
+            if(pattern instanceof EViewPattern) {
+                if(viewPatternColumn == -1)
+                    viewPatternColumn = i;
+            }
+            else if(!(pattern instanceof EVariable)) {
+                splitByConstructors(w, context, scrutinee, failure, rows, i);
+                return;
+            }
+        }
+        
+        if(viewPatternColumn >= 0) {
+            splitByViewPattern(w, context, scrutinee, failure, rows, viewPatternColumn);
+            return;
+        }
+
+        // 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]);
+        w.jump(firstRow.continuation);
+    }
+}