From: Hannu Niemistö Date: Fri, 21 Jul 2017 11:06:25 +0000 (+0300) Subject: (refs #7377) Refactoring CHR query parsing X-Git-Tag: v1.31.0~264^2~43 X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=commitdiff_plain;h=d9a283acefae11c2cc094ed1c7b74759f8166f17;hp=747231cca0974ca9ed5f78caa6517ee9dcb8e4fc (refs #7377) Refactoring CHR query parsing Change-Id: Ia0e2e4589180505c02fabeb5b1dd2267825e3255 --- diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/CHRRule.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/CHRRule.java index f714497c4..c668005d7 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/CHRRule.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/CHRRule.java @@ -45,6 +45,10 @@ public class CHRRule extends Symbol { this.body = body; this.existentialVariables = existentialVariables; } + + public CHRRule(long location, CHRQuery head, CHRQuery body) { + this(location, head, body, null); + } public void resolve(TranslationContext context) { context.pushExistentialFrame(); diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/ast/CHRAstAtom.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/ast/CHRAstAtom.java new file mode 100644 index 000000000..031d8edd8 --- /dev/null +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/ast/CHRAstAtom.java @@ -0,0 +1,143 @@ +package org.simantics.scl.compiler.elaboration.chr.ast; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; + +import org.simantics.scl.compiler.common.names.Name; +import org.simantics.scl.compiler.elaboration.chr.CHRLiteral; +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.EConstant; +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.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.types.Types; + +public class CHRAstAtom extends CHRAstQuery { + public Expression expression; + public boolean remove; + + public CHRAstAtom(Expression expression, boolean remove) { + this.expression = expression; + this.remove = remove; + } + + @Override + public void accept(CHRAstQueryVisitor visitor) { + visitor.visit(this); + } + + public static CHRAstQuery atom(Expression expression) { + boolean remove = false; + if(expression instanceof EVar) { + EVar var = (EVar)expression; + if(var.name.equals("True")) { + CHRAstConjunction query = new CHRAstConjunction(Collections.emptyList()); + query.location = expression.location; + return query; + } + } + else if(expression instanceof EBinary) { + EBinary binary = (EBinary)expression; + if(binary.negation != null && binary.rights.isEmpty()) { + remove = true; + expression = binary.left; + } + // If query is marked for removal, it must be an atom + } + else if(expression instanceof EApply) { + EApply apply = (EApply)expression; + if(apply.function instanceof EVar && ((EVar)apply.function).name.equals("not")) { + Expression subExpression; + if(apply.parameters.length == 1) + subExpression = apply.parameters[0]; + else + subExpression = 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)); + CHRAstNegation query = new CHRAstNegation(atom(subExpression)); + query.location = expression.location; + return query; + } + else if(apply.function instanceof EConstant) { + Name valueName = ((EConstant)apply.function).getValue().getName(); + if(valueName.module.equals(Types.BUILTIN) && valueName.name.startsWith("(")) { + CHRAstQuery[] conjuncts = new CHRAstQuery[apply.parameters.length]; + for(int i=0;i literals) { + literals.add( + isConstraint(context, expression) ? + convertConstraint(remove, expression) : + convertExpression(isHead, expression)); + } + + 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; + } + } + + 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, 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, false); + literal.fields = fields; + return literal; + } +} diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/ast/CHRAstBinds.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/ast/CHRAstBinds.java new file mode 100644 index 000000000..aa78f4e98 --- /dev/null +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/ast/CHRAstBinds.java @@ -0,0 +1,29 @@ +package org.simantics.scl.compiler.elaboration.chr.ast; + +import java.util.ArrayList; + +import org.simantics.scl.compiler.elaboration.chr.CHRLiteral; +import org.simantics.scl.compiler.elaboration.chr.relations.SpecialCHRRelation; +import org.simantics.scl.compiler.elaboration.contexts.TranslationContext; +import org.simantics.scl.compiler.elaboration.expressions.Expression; + +public class CHRAstBinds extends CHRAstQuery { + public Expression left; + public Expression right; + + public CHRAstBinds(Expression left, Expression right) { + this.left = left; + this.right = right; + } + + @Override + public void accept(CHRAstQueryVisitor visitor) { + visitor.visit(this); + } + + @Override + protected void translate(TranslationContext context, boolean isHead, ArrayList literals) { + literals.add(new CHRLiteral(location, SpecialCHRRelation.MEMBER, + new Expression[] { left, right }, false, false)); + } +} diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/ast/CHRAstConjunction.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/ast/CHRAstConjunction.java new file mode 100644 index 000000000..48f8ae71f --- /dev/null +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/ast/CHRAstConjunction.java @@ -0,0 +1,40 @@ +package org.simantics.scl.compiler.elaboration.chr.ast; + +import java.util.ArrayList; +import java.util.List; + +import org.simantics.scl.compiler.elaboration.chr.CHRLiteral; +import org.simantics.scl.compiler.elaboration.contexts.TranslationContext; + +public class CHRAstConjunction extends CHRAstQuery { + public List conjuncts; + + public CHRAstConjunction(List conjuncts) { + this.conjuncts = conjuncts; + } + + @Override + public void accept(CHRAstQueryVisitor visitor) { + visitor.visit(this); + } + + public static CHRAstQuery conjunction(CHRAstQuery[] conjuncts) { + ArrayList result = new ArrayList(conjuncts.length); + for(CHRAstQuery conjunct : conjuncts) { + if(conjunct instanceof CHRAstConjunction) + result.addAll(((CHRAstConjunction)conjunct).conjuncts); + else + result.add(conjunct); + } + if(result.size() == 1) + return result.get(0); + else + return new CHRAstConjunction(result); + } + + @Override + protected void translate(TranslationContext context, boolean isHead, ArrayList literals) { + for(CHRAstQuery conjunct : conjuncts) + conjunct.translate(context, isHead, literals); + } +} diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/ast/CHRAstEquals.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/ast/CHRAstEquals.java new file mode 100644 index 000000000..d2828934f --- /dev/null +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/ast/CHRAstEquals.java @@ -0,0 +1,29 @@ +package org.simantics.scl.compiler.elaboration.chr.ast; + +import java.util.ArrayList; + +import org.simantics.scl.compiler.elaboration.chr.CHRLiteral; +import org.simantics.scl.compiler.elaboration.chr.relations.SpecialCHRRelation; +import org.simantics.scl.compiler.elaboration.contexts.TranslationContext; +import org.simantics.scl.compiler.elaboration.expressions.Expression; + +public class CHRAstEquals extends CHRAstQuery { + public Expression left; + public Expression right; + + public CHRAstEquals(Expression left, Expression right) { + this.left = left; + this.right = right; + } + + @Override + public void accept(CHRAstQueryVisitor visitor) { + visitor.visit(this); + } + + @Override + protected void translate(TranslationContext context, boolean isHead, ArrayList literals) { + literals.add(new CHRLiteral(location, SpecialCHRRelation.EQUALS, + new Expression[] { left, right }, false, false)); + } +} diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/ast/CHRAstNegation.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/ast/CHRAstNegation.java new file mode 100644 index 000000000..b97f1e7f7 --- /dev/null +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/ast/CHRAstNegation.java @@ -0,0 +1,24 @@ +package org.simantics.scl.compiler.elaboration.chr.ast; + +import java.util.ArrayList; + +import org.simantics.scl.compiler.elaboration.chr.CHRLiteral; +import org.simantics.scl.compiler.elaboration.contexts.TranslationContext; + +public class CHRAstNegation extends CHRAstQuery { + public CHRAstQuery subquery; + + public CHRAstNegation(CHRAstQuery subquery) { + this.subquery = subquery; + } + + @Override + public void accept(CHRAstQueryVisitor visitor) { + visitor.visit(this); + } + + @Override + protected void translate(TranslationContext context, boolean isHead, ArrayList literals) { + context.getCompilationContext().errorLog.log(location, "CHR negation is not yet supported."); + } +} diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/ast/CHRAstQuery.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/ast/CHRAstQuery.java new file mode 100644 index 000000000..bd708e690 --- /dev/null +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/ast/CHRAstQuery.java @@ -0,0 +1,28 @@ +package org.simantics.scl.compiler.elaboration.chr.ast; + +import java.util.ArrayList; + +import org.simantics.scl.compiler.elaboration.chr.CHRLiteral; +import org.simantics.scl.compiler.elaboration.chr.CHRQuery; +import org.simantics.scl.compiler.elaboration.contexts.TranslationContext; +import org.simantics.scl.compiler.internal.parsing.Symbol; + +public abstract class CHRAstQuery extends Symbol { + public CHRQuery translateAsHead(TranslationContext context) { + return translate(context, true); + } + + public CHRQuery translateAsBody(TranslationContext context) { + return translate(context, false); + } + + private CHRQuery translate(TranslationContext context, boolean isHead) { + ArrayList literals = new ArrayList(); + translate(context, isHead, literals); + return new CHRQuery(literals.toArray(new CHRLiteral[literals.size()])); + } + + protected abstract void translate(TranslationContext context, boolean isHead, ArrayList literals); + + public abstract void accept(CHRAstQueryVisitor visitor); +} diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/ast/CHRAstQueryVisitor.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/ast/CHRAstQueryVisitor.java new file mode 100644 index 000000000..3c7b42525 --- /dev/null +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/ast/CHRAstQueryVisitor.java @@ -0,0 +1,9 @@ +package org.simantics.scl.compiler.elaboration.chr.ast; + +public interface CHRAstQueryVisitor { + void visit(CHRAstAtom query); + void visit(CHRAstBinds query); + void visit(CHRAstConjunction query); + void visit(CHRAstEquals query); + void visit(CHRAstNegation query); +} 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 d4f21a726..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 @@ -5,7 +5,6 @@ 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; @@ -15,7 +14,6 @@ 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.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; @@ -140,12 +138,12 @@ public class CHRTranslation { return new CHRQuery(query.toArray(new CHRLiteral[query.size()])); } - public static CHRRule convertCHRStatement(TranslationContext context, CHRStatement statement) { + /*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)); diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EBlock.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EBlock.java index 2c70bd907..e184b1397 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EBlock.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EBlock.java @@ -3,6 +3,7 @@ package org.simantics.scl.compiler.elaboration.expressions; import java.util.ArrayList; import java.util.List; +import org.simantics.scl.compiler.elaboration.chr.CHRRule; import org.simantics.scl.compiler.elaboration.chr.CHRRuleset; import org.simantics.scl.compiler.elaboration.chr.translation.CHRTranslation; import org.simantics.scl.compiler.elaboration.contexts.TranslationContext; @@ -92,8 +93,10 @@ public class EBlock extends ASTExpression { ruleset.location = Locations.combine(statements.get(begin).location, statements.get(end-1).location); for(int i=begin;i result = new THashSet(); collectFreeVariables(result); return result; - } + } public static Expression[] concat(Expression[] a, Expression[] b) { if(a.length == 0) diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/StandardExpressionTransformer.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/StandardExpressionTransformer.java index 948f7c645..c489422a5 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/StandardExpressionTransformer.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/StandardExpressionTransformer.java @@ -4,6 +4,13 @@ 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.CHRRuleset; +import org.simantics.scl.compiler.elaboration.chr.ast.CHRAstAtom; +import org.simantics.scl.compiler.elaboration.chr.ast.CHRAstBinds; +import org.simantics.scl.compiler.elaboration.chr.ast.CHRAstConjunction; +import org.simantics.scl.compiler.elaboration.chr.ast.CHRAstEquals; +import org.simantics.scl.compiler.elaboration.chr.ast.CHRAstNegation; +import org.simantics.scl.compiler.elaboration.chr.ast.CHRAstQuery; +import org.simantics.scl.compiler.elaboration.chr.ast.CHRAstQueryVisitor; import org.simantics.scl.compiler.elaboration.equation.EqBasic; import org.simantics.scl.compiler.elaboration.equation.EqGuard; import org.simantics.scl.compiler.elaboration.equation.Equation; @@ -41,7 +48,7 @@ import org.simantics.scl.compiler.elaboration.query.pre.QPreGuard; public class StandardExpressionTransformer implements ExpressionTransformer, QueryTransformer, ListQualifierTransformer, StatementVisitor, -EquationVisitor { +EquationVisitor, CHRAstQueryVisitor { @Override public Expression transform(EAmbiguous expression) { @@ -532,10 +539,36 @@ EquationVisitor { @Override public void visit(CHRStatement statement) { - for(int i=0;i A (?x-1) True => A 0 -- -0 -() \ No newline at end of file +6:11-6:23: CHR negation is not yet supported. \ No newline at end of file