X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.scl.compiler%2Fsrc%2Forg%2Fsimantics%2Fscl%2Fcompiler%2Felaboration%2Fchr%2Ftranslation%2FCHRTranslation.java;h=260927b74c6c3659e12997035a80cfd5c5fb167a;hp=14106711d0640499c5e6eda34a1f57b262f1becd;hb=d9a283acefae11c2cc094ed1c7b74759f8166f17;hpb=4bf8562ab7cbb3747f9c5844a07469291d43e905 diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/translation/CHRTranslation.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/translation/CHRTranslation.java index 14106711d..260927b74 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/translation/CHRTranslation.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/translation/CHRTranslation.java @@ -1,142 +1,160 @@ -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 parameters = new ArrayList(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 head = new ArrayList(statement.head.length); - for(ListQualifier qualifier : statement.head) { - CHRLiteral literal = convertListQualifier(context, true, qualifier); - if(literal != null) - head.add(literal); - } - ArrayList body = new ArrayList(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)); - } - -} +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.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.ERecord; +import org.simantics.scl.compiler.elaboration.expressions.EVar; +import org.simantics.scl.compiler.elaboration.expressions.Expression; +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.elaboration.expressions.records.FieldAssignment; +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.declarations.DAnnotationAst; +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) { + long location = expression.location; + Expression[] parameters; + FieldAssignment[] fields = null; + if(expression instanceof EApply) { + EApply apply = (EApply)expression; + parameters = apply.parameters; + expression = apply.function; + } + else if(expression instanceof ERecord) { + ERecord record = (ERecord)expression; + parameters = null; + fields = record.fields; + expression = record.constructor; + } + else // if(expression instanceof EVar) + parameters = Expression.EMPTY_ARRAY; + EVar var = (EVar)expression; // this should succeed because of isConstraint test + CHRLiteral literal = new CHRLiteral(location, new UnresolvedCHRRelation(var.location, var.name), + parameters, remove, negated); + literal.fields = fields; + return literal; + } + + 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) { + if(expression instanceof EApply) + expression = ((EApply)expression).function; + else if(expression instanceof ERecord) + expression = ((ERecord)expression).constructor; + 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 CHRQuery convertCHRQuery(TranslationContext context, boolean isHead, ListQualifier[] lqs) { + ArrayList query = new ArrayList(lqs.length); + for(ListQualifier qualifier : lqs) { + CHRLiteral literal = convertListQualifier(context, isHead, qualifier); + if(literal != null) + query.add(literal); + } + return new CHRQuery(query.toArray(new CHRLiteral[query.size()])); + } + + /*public static CHRRule convertCHRStatement(TranslationContext context, CHRStatement statement) { + return new CHRRule(statement.location, + convertCHRQuery(context, true, statement.head), + convertCHRQuery(context, false, statement.body), + null); + }*/ + + public static CHRConstraint convertConstraintStatement(TranslationContext context, ConstraintStatement statement) { + CHRConstraint constraint = new CHRConstraint(statement.location, statement.name.text, TypeAst.toTypes(context, statement.parameterTypes)); + for(DAnnotationAst annotation : statement.annotations) + applyConstraintAnnotation(context, constraint, annotation); + constraint.fieldNames = statement.fieldNames; + return constraint; + } + + private static void applyConstraintAnnotation(TranslationContext context, CHRConstraint constraint, DAnnotationAst annotation) { + context.getErrorLog().log(annotation.location, "Invalid constraint annotation"); + } + +}