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