--- /dev/null
+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