]> gerrit.simantics Code Review - simantics/platform.git/blob
260927b74c6c3659e12997035a80cfd5c5fb167a
[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.relations.CHRConstraint;
9 import org.simantics.scl.compiler.elaboration.chr.relations.SpecialCHRRelation;
10 import org.simantics.scl.compiler.elaboration.chr.relations.UnresolvedCHRRelation;
11 import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
12 import org.simantics.scl.compiler.elaboration.expressions.EApply;
13 import org.simantics.scl.compiler.elaboration.expressions.EBinary;
14 import org.simantics.scl.compiler.elaboration.expressions.ERecord;
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.ConstraintStatement;
18 import org.simantics.scl.compiler.elaboration.expressions.list.ListAssignment;
19 import org.simantics.scl.compiler.elaboration.expressions.list.ListGenerator;
20 import org.simantics.scl.compiler.elaboration.expressions.list.ListGuard;
21 import org.simantics.scl.compiler.elaboration.expressions.list.ListQualifier;
22 import org.simantics.scl.compiler.elaboration.expressions.records.FieldAssignment;
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.declarations.DAnnotationAst;
27 import org.simantics.scl.compiler.internal.parsing.types.TypeAst;
28
29 public class CHRTranslation {
30
31     private static CHRLiteral convertExpression(boolean isHead, Expression expression) {
32         if(isHead)
33             return new CHRLiteral(expression.location, SpecialCHRRelation.CHECK, new Expression[] {expression}, false, false);
34         else
35             return new CHRLiteral(expression.location, SpecialCHRRelation.EXECUTE, new Expression[] {expression}, false, false);
36     }
37
38     private static CHRLiteral convertConstraint(boolean remove, boolean negated, Expression expression) {
39         long location = expression.location;
40         Expression[] parameters;
41         FieldAssignment[] fields = null;
42         if(expression instanceof EApply) {
43             EApply apply = (EApply)expression;
44             parameters = apply.parameters;
45             expression = apply.function;
46         }
47         else if(expression instanceof ERecord) {
48             ERecord record = (ERecord)expression;
49             parameters = null;
50             fields = record.fields;
51             expression = record.constructor;
52         }
53         else // if(expression instanceof EVar)
54             parameters = Expression.EMPTY_ARRAY;
55         EVar var = (EVar)expression; // this should succeed because of isConstraint test
56         CHRLiteral literal = new CHRLiteral(location, new UnresolvedCHRRelation(var.location, var.name),
57                 parameters, remove, negated);
58         literal.fields = fields;
59         return literal;
60     }
61     
62     private static CHRLiteral convertListQualifier(TranslationContext context, boolean isHead, ListQualifier qualifier) {
63         if(qualifier instanceof ListGuard) {
64             Expression originalExpression = ((ListGuard)qualifier).condition;
65             if(originalExpression instanceof EVar && ((EVar)originalExpression).name.equals("True"))
66                 return null;
67             Expression currentExpression = originalExpression;
68             boolean remove = false;
69             boolean negated = false;
70             if(currentExpression instanceof EBinary) {
71                 EBinary binary = (EBinary)currentExpression;
72                 if(binary.negation==null || !binary.rights.isEmpty())
73                     return convertExpression(isHead, originalExpression);
74                 currentExpression = binary.left;
75                 remove = true;
76             }
77             else if(currentExpression instanceof EApply) {
78                 EApply apply = (EApply)currentExpression;
79                 if(apply.function instanceof EVar && ((EVar)apply.function).name.equals("not")) {
80                     negated = true;
81                     if(apply.parameters.length == 1)
82                         currentExpression = apply.parameters[0];
83                     else {
84                         currentExpression = new EApply(
85                                 Locations.combine(apply.parameters[0].location, apply.parameters[apply.parameters.length-1].location),
86                                 apply.parameters[0],
87                                 Arrays.copyOfRange(apply.parameters, 1, apply.parameters.length));
88                     }
89                 }
90             }
91             if(isConstraint(context, currentExpression))
92                 return convertConstraint(remove, negated, currentExpression);
93             else
94                 return convertExpression(isHead, originalExpression);
95         }
96         else if(qualifier instanceof ListAssignment) {
97             ListAssignment assignment = (ListAssignment)qualifier;
98             return new CHRLiteral(assignment.location, SpecialCHRRelation.EQUALS, new Expression[] {
99                     assignment.pattern, assignment.value 
100             }, false, false);
101         }
102         else if(qualifier instanceof ListGenerator) {
103             ListGenerator generator = (ListGenerator)qualifier;
104             return new CHRLiteral(generator.location, SpecialCHRRelation.MEMBER, new Expression[] {
105                     generator.pattern, generator.value
106             }, false, false);
107         }
108         else {
109             context.getErrorLog().log(qualifier.location, "Invalid CHR literal.");
110             return null;
111         }
112     }
113     
114     private static boolean isConstraint(TranslationContext context, Expression expression) {
115         if(expression instanceof EApply)
116             expression = ((EApply)expression).function;
117         else if(expression instanceof ERecord)
118             expression = ((ERecord)expression).constructor;
119         if(!(expression instanceof EVar))
120             return false;
121         String name = ((EVar)expression).name;
122         if(TranslationContext.isConstructorName(name))
123             return true;
124         try {
125             return Environments.getRelation(context.getEnvironment(), name) != null;
126         } catch (AmbiguousNameException e) {
127             return true;
128         }
129     }
130
131     public static CHRQuery convertCHRQuery(TranslationContext context, boolean isHead, ListQualifier[] lqs) {
132         ArrayList<CHRLiteral> query = new ArrayList<CHRLiteral>(lqs.length);
133         for(ListQualifier qualifier : lqs) {
134             CHRLiteral literal = convertListQualifier(context, isHead, qualifier);
135             if(literal != null)
136                 query.add(literal);
137         }
138         return new CHRQuery(query.toArray(new CHRLiteral[query.size()]));
139     }
140     
141     /*public static CHRRule convertCHRStatement(TranslationContext context, CHRStatement statement) {
142         return new CHRRule(statement.location,
143                 convertCHRQuery(context, true, statement.head),
144                 convertCHRQuery(context, false, statement.body),
145                 null);
146     }*/
147
148     public static CHRConstraint convertConstraintStatement(TranslationContext context, ConstraintStatement statement) {
149         CHRConstraint constraint = new CHRConstraint(statement.location, statement.name.text, TypeAst.toTypes(context, statement.parameterTypes));
150         for(DAnnotationAst annotation : statement.annotations)
151             applyConstraintAnnotation(context, constraint, annotation);
152         constraint.fieldNames = statement.fieldNames;
153         return constraint;
154     }
155
156     private static void applyConstraintAnnotation(TranslationContext context, CHRConstraint constraint, DAnnotationAst annotation) {
157         context.getErrorLog().log(annotation.location, "Invalid constraint annotation");
158     }
159     
160 }