From b98bb0df11fb8bc9748247da004321ab94e954c5 Mon Sep 17 00:00:00 2001 From: Garami Bence <85867500+garamibence@users.noreply.github.com> Date: Wed, 13 Oct 2021 20:59:35 +0200 Subject: Add scope for new and delete with tests --- language-model/problem.aird | 14 ++-- .../language/model/tests/ProblemTestUtil.java | 47 ++++++++++- .../language/resource/DerivedVariableComputer.java | 18 ++-- .../language/scoping/ProblemScopeProvider.java | 23 ++++-- .../tests/rules/DirectRuleParsingTest.xtend | 96 ++++++++++++++++++++++ 5 files changed, 176 insertions(+), 22 deletions(-) create mode 100644 language/src/test/java/tools/refinery/language/tests/rules/DirectRuleParsingTest.xtend diff --git a/language-model/problem.aird b/language-model/problem.aird index 52f96061..c5652fe4 100644 --- a/language-model/problem.aird +++ b/language-model/problem.aird @@ -7,7 +7,7 @@ build/resources/main/model/problem.genmodel - + @@ -765,8 +765,8 @@ - - + + @@ -1731,17 +1731,17 @@ - + - + - + - + diff --git a/language-model/src/testFixtures/java/tools/refinery/language/model/tests/ProblemTestUtil.java b/language-model/src/testFixtures/java/tools/refinery/language/model/tests/ProblemTestUtil.java index b412ed1f..dadc5330 100644 --- a/language-model/src/testFixtures/java/tools/refinery/language/model/tests/ProblemTestUtil.java +++ b/language-model/src/testFixtures/java/tools/refinery/language/model/tests/ProblemTestUtil.java @@ -7,26 +7,33 @@ import org.eclipse.emf.ecore.resource.Resource.Diagnostic; import org.eclipse.emf.ecore.util.EcoreUtil; import tools.refinery.language.model.ProblemUtil; +import tools.refinery.language.model.problem.ActionLiteral; import tools.refinery.language.model.problem.Argument; import tools.refinery.language.model.problem.Assertion; import tools.refinery.language.model.problem.AssertionArgument; import tools.refinery.language.model.problem.Atom; import tools.refinery.language.model.problem.ClassDeclaration; import tools.refinery.language.model.problem.Conjunction; +import tools.refinery.language.model.problem.DeleteActionLiteral; import tools.refinery.language.model.problem.EnumDeclaration; import tools.refinery.language.model.problem.Literal; import tools.refinery.language.model.problem.NamedElement; import tools.refinery.language.model.problem.NegativeLiteral; +import tools.refinery.language.model.problem.NewActionLiteral; import tools.refinery.language.model.problem.Node; import tools.refinery.language.model.problem.NodeAssertionArgument; import tools.refinery.language.model.problem.NodeValueAssertion; import tools.refinery.language.model.problem.Parameter; +import tools.refinery.language.model.problem.ParametricDefinition; import tools.refinery.language.model.problem.PredicateDefinition; import tools.refinery.language.model.problem.Problem; import tools.refinery.language.model.problem.ReferenceDeclaration; import tools.refinery.language.model.problem.Relation; +import tools.refinery.language.model.problem.RuleDefinition; import tools.refinery.language.model.problem.Statement; import tools.refinery.language.model.problem.UniqueDeclaration; +import tools.refinery.language.model.problem.ValueActionLiteral; +import tools.refinery.language.model.problem.ValueLiteral; import tools.refinery.language.model.problem.Variable; import tools.refinery.language.model.problem.VariableOrNode; import tools.refinery.language.model.problem.VariableOrNodeArgument; @@ -49,17 +56,29 @@ public class ProblemTestUtil { return namedStatementOfType(problem, PredicateDefinition.class, name); } - public Parameter param(PredicateDefinition definition, int i) { + public RuleDefinition rule(Problem problem, String name) { + return namedStatementOfType(problem, RuleDefinition.class, name); + } + + public Parameter param(ParametricDefinition definition, int i) { return definition.getParameters().get(i); } - public Conjunction conj(PredicateDefinition definition, int i) { + public Conjunction conj(ParametricDefinition definition, int i) { return definition.getBodies().get(i); } public Literal lit(Conjunction conjunction, int i) { return conjunction.getLiterals().get(i); } + + public ActionLiteral actionLit(RuleDefinition rule, int i) { + return rule.getAction().getActionLiterals().get(i); + } + + public Atom valueAtom(Literal literal) { + return ((ValueLiteral) literal).getAtom(); + } public Atom negated(Literal literal) { return ((NegativeLiteral) literal).getAtom(); @@ -85,6 +104,30 @@ public class ProblemTestUtil { return (Variable) variableOrNode(argument); } + public Variable variable(ValueActionLiteral valueActionLiteral, int i) { + return variable(arg(valueActionLiteral.getAtom(), i)); + } + + public Variable variable(NewActionLiteral newActionLiteral) { + return newActionLiteral.getVariable(); + } + + public VariableOrNode deleteVar(ActionLiteral actionLiteral) { + return ((DeleteActionLiteral) actionLiteral).getVariableOrNode(); + } + + public VariableOrNode newVar(ActionLiteral actionLiteral) { + return ((NewActionLiteral) actionLiteral).getVariable(); + } + + public Atom valueAtom(ActionLiteral actionLiteral) { + return ((ValueActionLiteral) actionLiteral).getAtom(); + } + + public Variable variable(DeleteActionLiteral deleteActionLiteral) { + return (Variable) deleteActionLiteral.getVariableOrNode(); + } + public Node node(Argument argument) { return (Node) variableOrNode(argument); } diff --git a/language/src/main/java/tools/refinery/language/resource/DerivedVariableComputer.java b/language/src/main/java/tools/refinery/language/resource/DerivedVariableComputer.java index 2061c30e..bb1226c4 100644 --- a/language/src/main/java/tools/refinery/language/resource/DerivedVariableComputer.java +++ b/language/src/main/java/tools/refinery/language/resource/DerivedVariableComputer.java @@ -24,11 +24,12 @@ import tools.refinery.language.model.problem.ImplicitVariable; import tools.refinery.language.model.problem.Literal; import tools.refinery.language.model.problem.NegativeLiteral; import tools.refinery.language.model.problem.Parameter; -import tools.refinery.language.model.problem.PredicateDefinition; +import tools.refinery.language.model.problem.ParametricDefinition; import tools.refinery.language.model.problem.Problem; import tools.refinery.language.model.problem.ProblemFactory; import tools.refinery.language.model.problem.ProblemPackage; import tools.refinery.language.model.problem.Statement; +import tools.refinery.language.model.problem.ValueLiteral; import tools.refinery.language.model.problem.VariableOrNodeArgument; import tools.refinery.language.naming.NamingUtil; @@ -46,13 +47,13 @@ public class DerivedVariableComputer { public void installDerivedVariables(Problem problem, Set nodeNames) { for (Statement statement : problem.getStatements()) { - if (statement instanceof PredicateDefinition definition) { - installDerivedPredicateDefinitionState(definition, nodeNames); + if (statement instanceof ParametricDefinition definition) { + installDerivedParametricDefinitionState(definition, nodeNames); } } } - protected void installDerivedPredicateDefinitionState(PredicateDefinition definition, Set nodeNames) { + protected void installDerivedParametricDefinitionState(ParametricDefinition definition, Set nodeNames) { Set knownVariables = new HashSet<>(); knownVariables.addAll(nodeNames); for (Parameter parameter : definition.getParameters()) { @@ -71,6 +72,9 @@ public class DerivedVariableComputer { for (Literal literal : conjunction.getLiterals()) { if (literal instanceof Atom atom) { createSigletonVariablesAndCollectVariables(atom, knownVariables, newVariables); + } else + if (literal instanceof ValueLiteral valueLiteral) { + createSigletonVariablesAndCollectVariables(valueLiteral.getAtom(), knownVariables, newVariables); } } createVariables(conjunction, newVariables); @@ -156,13 +160,13 @@ public class DerivedVariableComputer { public void discardDerivedVariables(Problem problem) { for (Statement statement : problem.getStatements()) { - if (statement instanceof PredicateDefinition predicateDefinition) { - discardPredicateDefinitionState(predicateDefinition); + if (statement instanceof ParametricDefinition parametricDefinition) { + discardParametricDefinitionState(parametricDefinition); } } } - protected void discardPredicateDefinitionState(PredicateDefinition definition) { + protected void discardParametricDefinitionState(ParametricDefinition definition) { for (Conjunction body : definition.getBodies()) { body.getImplicitVariables().clear(); for (Literal literal : body.getLiterals()) { diff --git a/language/src/main/java/tools/refinery/language/scoping/ProblemScopeProvider.java b/language/src/main/java/tools/refinery/language/scoping/ProblemScopeProvider.java index 86b39dbc..d31a5308 100644 --- a/language/src/main/java/tools/refinery/language/scoping/ProblemScopeProvider.java +++ b/language/src/main/java/tools/refinery/language/scoping/ProblemScopeProvider.java @@ -15,7 +15,9 @@ import org.eclipse.xtext.scoping.Scopes; import tools.refinery.language.model.ProblemUtil; import tools.refinery.language.model.problem.ClassDeclaration; import tools.refinery.language.model.problem.ExistentialQuantifier; -import tools.refinery.language.model.problem.PredicateDefinition; +import tools.refinery.language.model.problem.NewActionLiteral; +import tools.refinery.language.model.problem.ParametricDefinition; +import tools.refinery.language.model.problem.Action; import tools.refinery.language.model.problem.Problem; import tools.refinery.language.model.problem.ProblemPackage; import tools.refinery.language.model.problem.ReferenceDeclaration; @@ -38,7 +40,8 @@ public class ProblemScopeProvider extends AbstractProblemScopeProvider { || reference == ProblemPackage.Literals.NODE_VALUE_ASSERTION__NODE) { return getNodesScope(context, scope); } - if (reference == ProblemPackage.Literals.VARIABLE_OR_NODE_ARGUMENT__VARIABLE_OR_NODE) { + if (reference == ProblemPackage.Literals.VARIABLE_OR_NODE_ARGUMENT__VARIABLE_OR_NODE + || reference == ProblemPackage.Literals.DELETE_ACTION_LITERAL__VARIABLE_OR_NODE) { return getVariableScope(context, scope); } if (reference == ProblemPackage.Literals.REFERENCE_DECLARATION__OPPOSITE) { @@ -64,17 +67,25 @@ public class ProblemScopeProvider extends AbstractProblemScopeProvider { variables.add(singletonVariable); } } - while (currentContext != null && !(currentContext instanceof PredicateDefinition)) { + while (currentContext != null && !(currentContext instanceof ParametricDefinition)) { if (currentContext instanceof ExistentialQuantifier quantifier) { variables.addAll(quantifier.getImplicitVariables()); + } else + if(currentContext instanceof Action action) { + for (var literal : action.getActionLiterals()) { + if(literal instanceof NewActionLiteral newActionLiteral && newActionLiteral.getVariable() != null) { + variables.add(newActionLiteral.getVariable()); + } + } } currentContext = currentContext.eContainer(); } + IScope parentScope = getNodesScope(context, delegateScope); if (currentContext != null) { - PredicateDefinition definition = (PredicateDefinition) currentContext; - variables.addAll(definition.getParameters()); + ParametricDefinition definition = (ParametricDefinition) currentContext; + parentScope = Scopes.scopeFor(definition.getParameters(),parentScope); } - return Scopes.scopeFor(variables, getNodesScope(context, delegateScope)); + return Scopes.scopeFor(variables,parentScope); } protected IScope getOppositeScope(EObject context, IScope delegateScope) { diff --git a/language/src/test/java/tools/refinery/language/tests/rules/DirectRuleParsingTest.xtend b/language/src/test/java/tools/refinery/language/tests/rules/DirectRuleParsingTest.xtend new file mode 100644 index 00000000..d60651a0 --- /dev/null +++ b/language/src/test/java/tools/refinery/language/tests/rules/DirectRuleParsingTest.xtend @@ -0,0 +1,96 @@ +package tools.refinery.language.tests.rules + +import com.google.inject.Inject +import org.eclipse.xtext.testing.InjectWith +import org.eclipse.xtext.testing.extensions.InjectionExtension +import org.eclipse.xtext.testing.util.ParseHelper +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.^extension.ExtendWith +import tools.refinery.language.model.problem.Problem +import tools.refinery.language.tests.ProblemInjectorProvider +import tools.refinery.language.model.tests.ProblemTestUtil + +import static org.hamcrest.MatcherAssert.assertThat +import static org.hamcrest.Matchers.* + +@ExtendWith(InjectionExtension) +@InjectWith(ProblemInjectorProvider) +class DirectRuleParsingTest { + @Inject + ParseHelper parseHelper + + @Inject + extension ProblemTestUtil + + @Test + def void relationValueRewriteTest() { + val it = parseHelper.parse(''' + pred Person(p). + direct rule r(p1): Person(p1) = true ~> Person(p1) = false. + ''') + assertThat(errors, empty) + } + + @Test + def void relationValueMergeTest() { + val it = parseHelper.parse(''' + pred Person(p). + direct rule r(p1): Person(p1): true ~> Person(p1): false. + ''') + assertThat(errors, empty) + } + + @Test + def void newNodeTest() { + val it = parseHelper.parse(''' + pred Person(p). + direct rule r(p1): Person(p1) = true ~> new p2, Person(p2) = unknown. + ''') + assertThat(errors, empty) + assertThat(rule("r").param(0), equalTo(rule("r").conj(0).lit(0).valueAtom.arg(0).variable)) + assertThat(rule("r").actionLit(0).newVar, + equalTo(rule("r").actionLit(1).valueAtom.arg(0).variable) + ) + } + + @Test + def void differentScopeTest() { + val it = parseHelper.parse(''' + pred Friend(a, b). + direct rule r(p1): Friend(p1, p2) = false ~> new p2, Friend(p1, p2) = true. + ''') + assertThat(errors, empty) + assertThat(rule("r").conj(0).lit(0).valueAtom.arg(1).variable, + not(equalTo(rule("r").actionLit(1).valueAtom.arg(1).variable))) + } + + @Test + def void parameterShadowingTest() { + val it = parseHelper.parse(''' + pred Friend(a, b). + direct rule r(p1, p2): Friend(p1, p2) = false ~> new p2, Friend(p1, p2) = true. + ''') + assertThat(errors, empty) + assertThat(rule("r").param(1), + not(equalTo(rule("r").actionLit(1).valueAtom.arg(1).variable))) + } + + @Test + def void deleteParameterNodeTest() { + val it = parseHelper.parse(''' + pred Person(p). + direct rule r(p1): Person(p1): false ~> delete p1. + ''') + assertThat(errors, empty) + } + + @Test + def void deleteDifferentScopeNodeTest() { + val it = parseHelper.parse(''' + pred Friend(p). + direct rule r(p1): Friend(p1, p2) = true ~> delete p2. + ''') + assertThat(errors, not(empty)) + } + +} -- cgit v1.2.3-54-g00ecf