]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/translation/CHRTranslation.java
Merged changes from feature/scl to master.
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / elaboration / chr / translation / CHRTranslation.java
diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/translation/CHRTranslation.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/translation/CHRTranslation.java
new file mode 100644 (file)
index 0000000..1410671
--- /dev/null
@@ -0,0 +1,142 @@
+package org.simantics.scl.compiler.elaboration.chr.translation;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Arrays;\r
+\r
+import org.simantics.scl.compiler.elaboration.chr.CHRLiteral;\r
+import org.simantics.scl.compiler.elaboration.chr.CHRQuery;\r
+import org.simantics.scl.compiler.elaboration.chr.CHRRule;\r
+import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint;\r
+import org.simantics.scl.compiler.elaboration.chr.relations.SpecialCHRRelation;\r
+import org.simantics.scl.compiler.elaboration.chr.relations.UnresolvedCHRRelation;\r
+import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;\r
+import org.simantics.scl.compiler.elaboration.expressions.EApply;\r
+import org.simantics.scl.compiler.elaboration.expressions.EBinary;\r
+import org.simantics.scl.compiler.elaboration.expressions.EVar;\r
+import org.simantics.scl.compiler.elaboration.expressions.Expression;\r
+import org.simantics.scl.compiler.elaboration.expressions.block.CHRStatement;\r
+import org.simantics.scl.compiler.elaboration.expressions.block.ConstraintStatement;\r
+import org.simantics.scl.compiler.elaboration.expressions.list.ListAssignment;\r
+import org.simantics.scl.compiler.elaboration.expressions.list.ListGenerator;\r
+import org.simantics.scl.compiler.elaboration.expressions.list.ListGuard;\r
+import org.simantics.scl.compiler.elaboration.expressions.list.ListQualifier;\r
+import org.simantics.scl.compiler.environment.AmbiguousNameException;\r
+import org.simantics.scl.compiler.environment.Environments;\r
+import org.simantics.scl.compiler.errors.Locations;\r
+import org.simantics.scl.compiler.internal.parsing.types.TypeAst;\r
+\r
+public class CHRTranslation {\r
+\r
+    private static CHRLiteral convertExpression(boolean isHead, Expression expression) {\r
+        if(isHead)\r
+            return new CHRLiteral(expression.location, SpecialCHRRelation.CHECK, new Expression[] {expression}, false, false);\r
+        else\r
+            return new CHRLiteral(expression.location, SpecialCHRRelation.EXECUTE, new Expression[] {expression}, false, false);\r
+    }\r
+\r
+    private static CHRLiteral convertConstraint(boolean remove, boolean negated, Expression expression) {\r
+        ArrayList<Expression> parameters = new ArrayList<Expression>(4);\r
+        while(expression instanceof EApply) {\r
+            EApply apply = (EApply)expression;\r
+            for(int i=apply.parameters.length-1;i>=0;--i)\r
+                parameters.add(apply.parameters[i]);\r
+            expression = apply.function;\r
+        }\r
+        EVar var = (EVar)expression;\r
+        Expression[] parametersArray = new Expression[parameters.size()];\r
+        for(int i=0,j=parametersArray.length-1;i<parametersArray.length;++i,--j)\r
+            parametersArray[i] = parameters.get(j);\r
+        return new CHRLiteral(expression.location, new UnresolvedCHRRelation(var.location, var.name), parametersArray, remove, negated);\r
+    }\r
+    \r
+    private static CHRLiteral convertListQualifier(TranslationContext context, boolean isHead, ListQualifier qualifier) {\r
+        if(qualifier instanceof ListGuard) {\r
+            Expression originalExpression = ((ListGuard)qualifier).condition;\r
+            if(originalExpression instanceof EVar && ((EVar)originalExpression).name.equals("True"))\r
+                return null;\r
+            Expression currentExpression = originalExpression;\r
+            boolean remove = false;\r
+            boolean negated = false;\r
+            if(currentExpression instanceof EBinary) {\r
+                EBinary binary = (EBinary)currentExpression;\r
+                if(binary.negation==null || !binary.rights.isEmpty())\r
+                    return convertExpression(isHead, originalExpression);\r
+                currentExpression = binary.left;\r
+                remove = true;\r
+            }\r
+            else if(currentExpression instanceof EApply) {\r
+                EApply apply = (EApply)currentExpression;\r
+                if(apply.function instanceof EVar && ((EVar)apply.function).name.equals("not")) {\r
+                    negated = true;\r
+                    if(apply.parameters.length == 1)\r
+                        currentExpression = apply.parameters[0];\r
+                    else {\r
+                        currentExpression = new EApply(\r
+                                Locations.combine(apply.parameters[0].location, apply.parameters[apply.parameters.length-1].location),\r
+                                apply.parameters[0],\r
+                                Arrays.copyOfRange(apply.parameters, 1, apply.parameters.length));\r
+                    }\r
+                }\r
+            }\r
+            if(isConstraint(context, currentExpression))\r
+                return convertConstraint(remove, negated, currentExpression);\r
+            else\r
+                return convertExpression(isHead, originalExpression);\r
+        }\r
+        else if(qualifier instanceof ListAssignment) {\r
+            ListAssignment assignment = (ListAssignment)qualifier;\r
+            return new CHRLiteral(assignment.location, SpecialCHRRelation.EQUALS, new Expression[] {\r
+                    assignment.pattern, assignment.value \r
+            }, false, false);\r
+        }\r
+        else if(qualifier instanceof ListGenerator) {\r
+            ListGenerator generator = (ListGenerator)qualifier;\r
+            return new CHRLiteral(generator.location, SpecialCHRRelation.MEMBER, new Expression[] {\r
+                    generator.pattern, generator.value\r
+            }, false, false);\r
+        }\r
+        else {\r
+            context.getErrorLog().log(qualifier.location, "Invalid CHR literal.");\r
+            return null;\r
+        }\r
+    }\r
+    \r
+    private static boolean isConstraint(TranslationContext context, Expression expression) {\r
+        while(expression instanceof EApply)\r
+            expression = ((EApply)expression).function;\r
+        if(!(expression instanceof EVar))\r
+            return false;\r
+        String name = ((EVar)expression).name;\r
+        if(TranslationContext.isConstructorName(name))\r
+            return true;\r
+        try {\r
+            return Environments.getRelation(context.getEnvironment(), name) != null;\r
+        } catch (AmbiguousNameException e) {\r
+            return true;\r
+        }\r
+    }\r
+\r
+    public static CHRRule convertCHRStatement(TranslationContext context, CHRStatement statement) {\r
+        ArrayList<CHRLiteral> head = new ArrayList<CHRLiteral>(statement.head.length);\r
+        for(ListQualifier qualifier : statement.head) {\r
+            CHRLiteral literal = convertListQualifier(context, true, qualifier);\r
+            if(literal != null)\r
+                head.add(literal);\r
+        }\r
+        ArrayList<CHRLiteral> body = new ArrayList<CHRLiteral>(statement.body.length);\r
+        for(ListQualifier qualifier : statement.body) {\r
+            CHRLiteral literal = convertListQualifier(context, false, qualifier);\r
+            if(literal != null)\r
+                body.add(literal);\r
+        }\r
+        return new CHRRule(statement.location,\r
+                new CHRQuery(head.toArray(new CHRLiteral[head.size()])),\r
+                new CHRQuery(body.toArray(new CHRLiteral[body.size()])),\r
+                null);\r
+    }\r
+\r
+    public static CHRConstraint convertConstraintStatement(TranslationContext context, ConstraintStatement statement) {\r
+        return new CHRConstraint(statement.location, statement.name.text, TypeAst.toTypes(context, statement.parameterTypes));\r
+    }\r
+    \r
+}\r