1 package org.simantics.scl.compiler.elaboration.chr.translation;
\r
3 import java.util.ArrayList;
\r
4 import java.util.Arrays;
\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
28 public class CHRTranslation {
\r
30 private static CHRLiteral convertExpression(boolean isHead, Expression expression) {
\r
32 return new CHRLiteral(expression.location, SpecialCHRRelation.CHECK, new Expression[] {expression}, false, false);
\r
34 return new CHRLiteral(expression.location, SpecialCHRRelation.EXECUTE, new Expression[] {expression}, false, false);
\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
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
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
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
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
71 if(apply.parameters.length == 1)
\r
72 currentExpression = apply.parameters[0];
\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
81 if(isConstraint(context, currentExpression))
\r
82 return convertConstraint(remove, negated, currentExpression);
\r
84 return convertExpression(isHead, originalExpression);
\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
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
99 context.getErrorLog().log(qualifier.location, "Invalid CHR literal.");
\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
109 String name = ((EVar)expression).name;
\r
110 if(TranslationContext.isConstructorName(name))
\r
113 return Environments.getRelation(context.getEnvironment(), name) != null;
\r
114 } catch (AmbiguousNameException e) {
\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
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
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
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