]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/elaboration/matching/PatternMatchingCompiler.java
Merged changes from feature/scl to master.
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / internal / elaboration / matching / PatternMatchingCompiler.java
index 7f200a11c40167e48875f48ddc97d614ffeb33af..9bf056bef825fe3a6c3db4e0cbef0fed1572c6eb 100644 (file)
@@ -1,6 +1,7 @@
 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;
@@ -12,6 +13,7 @@ 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.expressions.GuardedExpressionGroup;
 import org.simantics.scl.compiler.elaboration.modules.SCLValue;
@@ -52,7 +54,7 @@ public class PatternMatchingCompiler {
         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>();
@@ -87,19 +89,34 @@ public class PatternMatchingCompiler {
                 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;
@@ -160,7 +177,7 @@ public class PatternMatchingCompiler {
             } 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)
@@ -172,21 +189,76 @@ public class PatternMatchingCompiler {
         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) {