]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/translation/CHRTranslation.java
Merge "Remove unused import in DeleteHandler"
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / elaboration / chr / translation / CHRTranslation.java
1 package org.simantics.scl.compiler.elaboration.chr.translation;\r
2 \r
3 import java.util.ArrayList;\r
4 import java.util.Arrays;\r
5 \r
6 import org.simantics.scl.compiler.elaboration.chr.CHRLiteral;\r
7 import org.simantics.scl.compiler.elaboration.chr.CHRQuery;\r
8 import org.simantics.scl.compiler.elaboration.chr.CHRRule;\r
9 import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint;\r
10 import org.simantics.scl.compiler.elaboration.chr.relations.SpecialCHRRelation;\r
11 import org.simantics.scl.compiler.elaboration.chr.relations.UnresolvedCHRRelation;\r
12 import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;\r
13 import org.simantics.scl.compiler.elaboration.expressions.EApply;\r
14 import org.simantics.scl.compiler.elaboration.expressions.EBinary;\r
15 import org.simantics.scl.compiler.elaboration.expressions.EVar;\r
16 import org.simantics.scl.compiler.elaboration.expressions.Expression;\r
17 import org.simantics.scl.compiler.elaboration.expressions.block.CHRStatement;\r
18 import org.simantics.scl.compiler.elaboration.expressions.block.ConstraintStatement;\r
19 import org.simantics.scl.compiler.elaboration.expressions.list.ListAssignment;\r
20 import org.simantics.scl.compiler.elaboration.expressions.list.ListGenerator;\r
21 import org.simantics.scl.compiler.elaboration.expressions.list.ListGuard;\r
22 import org.simantics.scl.compiler.elaboration.expressions.list.ListQualifier;\r
23 import org.simantics.scl.compiler.environment.AmbiguousNameException;\r
24 import org.simantics.scl.compiler.environment.Environments;\r
25 import org.simantics.scl.compiler.errors.Locations;\r
26 import org.simantics.scl.compiler.internal.parsing.types.TypeAst;\r
27 \r
28 public class CHRTranslation {\r
29 \r
30     private static CHRLiteral convertExpression(boolean isHead, Expression expression) {\r
31         if(isHead)\r
32             return new CHRLiteral(expression.location, SpecialCHRRelation.CHECK, new Expression[] {expression}, false, false);\r
33         else\r
34             return new CHRLiteral(expression.location, SpecialCHRRelation.EXECUTE, new Expression[] {expression}, false, false);\r
35     }\r
36 \r
37     private static CHRLiteral convertConstraint(boolean remove, boolean negated, Expression expression) {\r
38         ArrayList<Expression> parameters = new ArrayList<Expression>(4);\r
39         while(expression instanceof EApply) {\r
40             EApply apply = (EApply)expression;\r
41             for(int i=apply.parameters.length-1;i>=0;--i)\r
42                 parameters.add(apply.parameters[i]);\r
43             expression = apply.function;\r
44         }\r
45         EVar var = (EVar)expression;\r
46         Expression[] parametersArray = new Expression[parameters.size()];\r
47         for(int i=0,j=parametersArray.length-1;i<parametersArray.length;++i,--j)\r
48             parametersArray[i] = parameters.get(j);\r
49         return new CHRLiteral(expression.location, new UnresolvedCHRRelation(var.location, var.name), parametersArray, remove, negated);\r
50     }\r
51     \r
52     private static CHRLiteral convertListQualifier(TranslationContext context, boolean isHead, ListQualifier qualifier) {\r
53         if(qualifier instanceof ListGuard) {\r
54             Expression originalExpression = ((ListGuard)qualifier).condition;\r
55             if(originalExpression instanceof EVar && ((EVar)originalExpression).name.equals("True"))\r
56                 return null;\r
57             Expression currentExpression = originalExpression;\r
58             boolean remove = false;\r
59             boolean negated = false;\r
60             if(currentExpression instanceof EBinary) {\r
61                 EBinary binary = (EBinary)currentExpression;\r
62                 if(binary.negation==null || !binary.rights.isEmpty())\r
63                     return convertExpression(isHead, originalExpression);\r
64                 currentExpression = binary.left;\r
65                 remove = true;\r
66             }\r
67             else if(currentExpression instanceof EApply) {\r
68                 EApply apply = (EApply)currentExpression;\r
69                 if(apply.function instanceof EVar && ((EVar)apply.function).name.equals("not")) {\r
70                     negated = true;\r
71                     if(apply.parameters.length == 1)\r
72                         currentExpression = apply.parameters[0];\r
73                     else {\r
74                         currentExpression = new EApply(\r
75                                 Locations.combine(apply.parameters[0].location, apply.parameters[apply.parameters.length-1].location),\r
76                                 apply.parameters[0],\r
77                                 Arrays.copyOfRange(apply.parameters, 1, apply.parameters.length));\r
78                     }\r
79                 }\r
80             }\r
81             if(isConstraint(context, currentExpression))\r
82                 return convertConstraint(remove, negated, currentExpression);\r
83             else\r
84                 return convertExpression(isHead, originalExpression);\r
85         }\r
86         else if(qualifier instanceof ListAssignment) {\r
87             ListAssignment assignment = (ListAssignment)qualifier;\r
88             return new CHRLiteral(assignment.location, SpecialCHRRelation.EQUALS, new Expression[] {\r
89                     assignment.pattern, assignment.value \r
90             }, false, false);\r
91         }\r
92         else if(qualifier instanceof ListGenerator) {\r
93             ListGenerator generator = (ListGenerator)qualifier;\r
94             return new CHRLiteral(generator.location, SpecialCHRRelation.MEMBER, new Expression[] {\r
95                     generator.pattern, generator.value\r
96             }, false, false);\r
97         }\r
98         else {\r
99             context.getErrorLog().log(qualifier.location, "Invalid CHR literal.");\r
100             return null;\r
101         }\r
102     }\r
103     \r
104     private static boolean isConstraint(TranslationContext context, Expression expression) {\r
105         while(expression instanceof EApply)\r
106             expression = ((EApply)expression).function;\r
107         if(!(expression instanceof EVar))\r
108             return false;\r
109         String name = ((EVar)expression).name;\r
110         if(TranslationContext.isConstructorName(name))\r
111             return true;\r
112         try {\r
113             return Environments.getRelation(context.getEnvironment(), name) != null;\r
114         } catch (AmbiguousNameException e) {\r
115             return true;\r
116         }\r
117     }\r
118 \r
119     public static CHRRule convertCHRStatement(TranslationContext context, CHRStatement statement) {\r
120         ArrayList<CHRLiteral> head = new ArrayList<CHRLiteral>(statement.head.length);\r
121         for(ListQualifier qualifier : statement.head) {\r
122             CHRLiteral literal = convertListQualifier(context, true, qualifier);\r
123             if(literal != null)\r
124                 head.add(literal);\r
125         }\r
126         ArrayList<CHRLiteral> body = new ArrayList<CHRLiteral>(statement.body.length);\r
127         for(ListQualifier qualifier : statement.body) {\r
128             CHRLiteral literal = convertListQualifier(context, false, qualifier);\r
129             if(literal != null)\r
130                 body.add(literal);\r
131         }\r
132         return new CHRRule(statement.location,\r
133                 new CHRQuery(head.toArray(new CHRLiteral[head.size()])),\r
134                 new CHRQuery(body.toArray(new CHRLiteral[body.size()])),\r
135                 null);\r
136     }\r
137 \r
138     public static CHRConstraint convertConstraintStatement(TranslationContext context, ConstraintStatement statement) {\r
139         return new CHRConstraint(statement.location, statement.name.text, TypeAst.toTypes(context, statement.parameterTypes));\r
140     }\r
141     \r
142 }\r