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