aboutsummaryrefslogtreecommitdiffstats
path: root/language
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <marussy@mit.bme.hu>2021-11-06 16:56:11 +0100
committerLibravatar GitHub <noreply@github.com>2021-11-06 16:56:11 +0100
commitbf479290c950c004d8f99eda967e3a6c76e0e64b (patch)
tree2d805f058ab6b4289d4338b8f6beb12c51c31d09 /language
parentMerge pull request #11 from kris7t/unique-to-individual (diff)
parentchore(lang): seralize assertions in short form (diff)
downloadrefinery-bf479290c950c004d8f99eda967e3a6c76e0e64b.tar.gz
refinery-bf479290c950c004d8f99eda967e3a6c76e0e64b.tar.zst
refinery-bf479290c950c004d8f99eda967e3a6c76e0e64b.zip
Merge pull request #12 from kris7t/xtext-serialization
Make sure Xtext serialization works
Diffstat (limited to 'language')
-rw-r--r--language/src/main/java/tools/refinery/language/Problem.xtext14
-rw-r--r--language/src/main/java/tools/refinery/language/validation/ProblemValidator.java2
-rw-r--r--language/src/test/java/tools/refinery/language/tests/ProblemParsingTest.xtend2
-rw-r--r--language/src/test/java/tools/refinery/language/tests/scoping/NodeScopingTest.xtend6
-rw-r--r--language/src/test/java/tools/refinery/language/tests/serializer/ProblemSerializerTest.java215
5 files changed, 227 insertions, 12 deletions
diff --git a/language/src/main/java/tools/refinery/language/Problem.xtext b/language/src/main/java/tools/refinery/language/Problem.xtext
index b7562759..26773047 100644
--- a/language/src/main/java/tools/refinery/language/Problem.xtext
+++ b/language/src/main/java/tools/refinery/language/Problem.xtext
@@ -109,12 +109,12 @@ ConstantArgument:
109 109
110Assertion: 110Assertion:
111 default?="default"? 111 default?="default"?
112 (relation=[Relation|QualifiedName] 112 (value=ShortLogicValue?
113 "(" (arguments+=AssertionArgument ("," arguments+=AssertionArgument)*)? ")"
114 ":" value=LogicValue |
115 value=ShortLogicValue?
116 relation=[Relation|QualifiedName] 113 relation=[Relation|QualifiedName]
117 "(" (arguments+=AssertionArgument ("," arguments+=AssertionArgument)*)? ")") 114 "(" (arguments+=AssertionArgument ("," arguments+=AssertionArgument)*)? ")"
115 | relation=[Relation|QualifiedName]
116 "(" (arguments+=AssertionArgument ("," arguments+=AssertionArgument)*)? ")"
117 ":" value=LogicValue)
118 "."; 118 ".";
119 119
120AssertionArgument: 120AssertionArgument:
@@ -174,7 +174,7 @@ ExactMultiplicity:
174 exactValue=INT; 174 exactValue=INT;
175 175
176IndividualDeclaration: 176IndividualDeclaration:
177 "individual" nodes+=EnumLiteral ("," nodes+=EnumLiteral)* "."; 177 "indiv" nodes+=EnumLiteral ("," nodes+=EnumLiteral)* ".";
178 178
179UpperBound returns ecore::EInt: 179UpperBound returns ecore::EInt:
180 INT | "*"; 180 INT | "*";
@@ -184,7 +184,7 @@ QualifiedName hidden():
184 184
185Identifier: 185Identifier:
186 ID | "true" | "false" | "unknown" | "error" | "class" | "abstract" | "extends" | "enum" | "pred" | 186 ID | "true" | "false" | "unknown" | "error" | "class" | "abstract" | "extends" | "enum" | "pred" |
187 "individual" | "problem" | "new" | "delete" | "direct" | "rule"; 187 "indiv" | "problem" | "new" | "delete" | "direct" | "rule";
188 188
189Integer returns ecore::EInt hidden(): 189Integer returns ecore::EInt hidden():
190 "-"? INT; 190 "-"? INT;
diff --git a/language/src/main/java/tools/refinery/language/validation/ProblemValidator.java b/language/src/main/java/tools/refinery/language/validation/ProblemValidator.java
index 3c10d39e..975fdca2 100644
--- a/language/src/main/java/tools/refinery/language/validation/ProblemValidator.java
+++ b/language/src/main/java/tools/refinery/language/validation/ProblemValidator.java
@@ -53,7 +53,7 @@ public class ProblemValidator extends AbstractProblemValidator {
53 var variableOrNode = argument.getVariableOrNode(); 53 var variableOrNode = argument.getVariableOrNode();
54 if (variableOrNode instanceof Node node && !ProblemUtil.isIndividualNode(node)) { 54 if (variableOrNode instanceof Node node && !ProblemUtil.isIndividualNode(node)) {
55 var name = node.getName(); 55 var name = node.getName();
56 var message = "Only individual nodes can be referenced in predicates. Mark '%s' as individual with the declaration 'individual %s.'" 56 var message = "Only individual nodes can be referenced in predicates. Mark '%s' as individual with the declaration 'indiv %s.'"
57 .formatted(name, name); 57 .formatted(name, name);
58 error(message, argument, ProblemPackage.Literals.VARIABLE_OR_NODE_ARGUMENT__VARIABLE_OR_NODE, 58 error(message, argument, ProblemPackage.Literals.VARIABLE_OR_NODE_ARGUMENT__VARIABLE_OR_NODE,
59 INSIGNIFICANT_INDEX, NON_INDIVIDUAL_NODE_ISSUE); 59 INSIGNIFICANT_INDEX, NON_INDIVIDUAL_NODE_ISSUE);
diff --git a/language/src/test/java/tools/refinery/language/tests/ProblemParsingTest.xtend b/language/src/test/java/tools/refinery/language/tests/ProblemParsingTest.xtend
index 9e357529..53d31a6c 100644
--- a/language/src/test/java/tools/refinery/language/tests/ProblemParsingTest.xtend
+++ b/language/src/test/java/tools/refinery/language/tests/ProblemParsingTest.xtend
@@ -46,7 +46,7 @@ class ProblemParsingTest {
46 error invalidTaxStatus(Person p) <-> 46 error invalidTaxStatus(Person p) <->
47 taxStatus(p, child), children(p, _q). 47 taxStatus(p, child), children(p, _q).
48 48
49 individual family. 49 indiv family.
50 Family(family). 50 Family(family).
51 members(family, anne): true. 51 members(family, anne): true.
52 members(family, bob). 52 members(family, bob).
diff --git a/language/src/test/java/tools/refinery/language/tests/scoping/NodeScopingTest.xtend b/language/src/test/java/tools/refinery/language/tests/scoping/NodeScopingTest.xtend
index 5f669847..3a046341 100644
--- a/language/src/test/java/tools/refinery/language/tests/scoping/NodeScopingTest.xtend
+++ b/language/src/test/java/tools/refinery/language/tests/scoping/NodeScopingTest.xtend
@@ -81,7 +81,7 @@ class NodeScopingTest {
81 def void individualNodeInAssertionTest(String qualifiedNamePrefix, boolean namedProblem) { 81 def void individualNodeInAssertionTest(String qualifiedNamePrefix, boolean namedProblem) {
82 val it = parseHelper.parse(''' 82 val it = parseHelper.parse('''
83 «IF namedProblem»problem test.«ENDIF» 83 «IF namedProblem»problem test.«ENDIF»
84 individual a, b. 84 indiv a, b.
85 pred predicate(node x, node y) <-> node(x). 85 pred predicate(node x, node y) <-> node(x).
86 predicate(«qualifiedNamePrefix»a, «qualifiedNamePrefix»a). 86 predicate(«qualifiedNamePrefix»a, «qualifiedNamePrefix»a).
87 ?predicate(«qualifiedNamePrefix»a, «qualifiedNamePrefix»b). 87 ?predicate(«qualifiedNamePrefix»a, «qualifiedNamePrefix»b).
@@ -99,7 +99,7 @@ class NodeScopingTest {
99 def void individualNodeInNodeValueAssertionTest(String qualifiedNamePrefix, boolean namedProblem) { 99 def void individualNodeInNodeValueAssertionTest(String qualifiedNamePrefix, boolean namedProblem) {
100 val it = parseHelper.parse(''' 100 val it = parseHelper.parse('''
101 «IF namedProblem»problem test.«ENDIF» 101 «IF namedProblem»problem test.«ENDIF»
102 individual a. 102 indiv a.
103 «qualifiedNamePrefix»a: 16. 103 «qualifiedNamePrefix»a: 16.
104 ''') 104 ''')
105 assertThat(errors, empty) 105 assertThat(errors, empty)
@@ -112,7 +112,7 @@ class NodeScopingTest {
112 def void individualNodeInPredicateTest(String qualifiedNamePrefix, boolean namedProblem) { 112 def void individualNodeInPredicateTest(String qualifiedNamePrefix, boolean namedProblem) {
113 val it = parseHelper.parse(''' 113 val it = parseHelper.parse('''
114 «IF namedProblem»problem test.«ENDIF» 114 «IF namedProblem»problem test.«ENDIF»
115 individual b. 115 indiv b.
116 pred predicate(node a) <-> node(«qualifiedNamePrefix»b). 116 pred predicate(node a) <-> node(«qualifiedNamePrefix»b).
117 ''') 117 ''')
118 assertThat(errors, empty) 118 assertThat(errors, empty)
diff --git a/language/src/test/java/tools/refinery/language/tests/serializer/ProblemSerializerTest.java b/language/src/test/java/tools/refinery/language/tests/serializer/ProblemSerializerTest.java
new file mode 100644
index 00000000..802457cb
--- /dev/null
+++ b/language/src/test/java/tools/refinery/language/tests/serializer/ProblemSerializerTest.java
@@ -0,0 +1,215 @@
1package tools.refinery.language.tests.serializer;
2
3import static org.hamcrest.MatcherAssert.assertThat;
4import static org.hamcrest.Matchers.equalTo;
5
6import java.io.ByteArrayOutputStream;
7import java.io.IOException;
8import java.util.Map;
9import java.util.stream.Stream;
10
11import org.eclipse.emf.common.util.URI;
12import org.eclipse.emf.ecore.resource.Resource;
13import org.eclipse.emf.ecore.resource.ResourceSet;
14import org.eclipse.xtext.testing.InjectWith;
15import org.eclipse.xtext.testing.extensions.InjectionExtension;
16import org.junit.jupiter.api.BeforeEach;
17import org.junit.jupiter.api.Test;
18import org.junit.jupiter.api.extension.ExtendWith;
19import org.junit.jupiter.params.ParameterizedTest;
20import org.junit.jupiter.params.provider.Arguments;
21import org.junit.jupiter.params.provider.MethodSource;
22
23import com.google.inject.Inject;
24
25import tools.refinery.language.model.ProblemUtil;
26import tools.refinery.language.model.problem.Atom;
27import tools.refinery.language.model.problem.LogicValue;
28import tools.refinery.language.model.problem.Node;
29import tools.refinery.language.model.problem.PredicateDefinition;
30import tools.refinery.language.model.problem.Problem;
31import tools.refinery.language.model.problem.ProblemFactory;
32import tools.refinery.language.model.problem.Relation;
33import tools.refinery.language.model.problem.VariableOrNode;
34import tools.refinery.language.model.tests.ProblemTestUtil;
35import tools.refinery.language.tests.ProblemInjectorProvider;
36
37@ExtendWith(InjectionExtension.class)
38@InjectWith(ProblemInjectorProvider.class)
39public class ProblemSerializerTest {
40 @Inject
41 ResourceSet resourceSet;
42
43 @Inject
44 ProblemTestUtil testUtil;
45
46 Resource resource;
47
48 Problem problem;
49
50 Problem builtin;
51
52 @BeforeEach
53 void beforeEach() {
54 problem = ProblemFactory.eINSTANCE.createProblem();
55 resource = resourceSet.createResource(URI.createFileURI("test.problem"));
56 resource.getContents().add(problem);
57 builtin = ProblemUtil.getBuiltInLibrary(problem).get();
58 }
59
60 @ParameterizedTest
61 @MethodSource
62 void assertionTest(LogicValue value, String serializedAssertion) {
63 var pred = createPred();
64 var node = ProblemFactory.eINSTANCE.createNode();
65 node.setName("a");
66 var individualDeclaration = ProblemFactory.eINSTANCE.createIndividualDeclaration();
67 individualDeclaration.getNodes().add(node);
68 problem.getStatements().add(individualDeclaration);
69 createAssertion(pred, node, value);
70
71 assertSerializedResult("pred foo ( node p ) . indiv a . " + serializedAssertion);
72 }
73
74 static Stream<Arguments> assertionTest() {
75 return Stream.of(Arguments.of(LogicValue.TRUE, "foo ( a ) ."),
76 Arguments.of(LogicValue.FALSE, "! foo ( a ) ."),
77 Arguments.of(LogicValue.UNKNOWN, "? foo ( a ) ."),
78 Arguments.of(LogicValue.ERROR, "foo ( a ) : error ."));
79 }
80
81 @Test
82 void implicitNodeTest() {
83 var pred = createPred();
84 var node = ProblemFactory.eINSTANCE.createNode();
85 node.setName("a");
86 problem.getNodes().add(node);
87 createAssertion(pred, node);
88
89 assertSerializedResult("pred foo ( node p ) . foo ( a ) .");
90 }
91
92 private PredicateDefinition createPred() {
93 var pred = ProblemFactory.eINSTANCE.createPredicateDefinition();
94 pred.setName("foo");
95 var parameter = ProblemFactory.eINSTANCE.createParameter();
96 var nodeType = testUtil.findClass(builtin, "node");
97 parameter.setParameterType(nodeType);
98 parameter.setName("p");
99 pred.getParameters().add(parameter);
100 problem.getStatements().add(pred);
101 return pred;
102 }
103
104 @Test
105 void newNodeTest() {
106 var classDeclaration = ProblemFactory.eINSTANCE.createClassDeclaration();
107 classDeclaration.setName("Foo");
108 var newNode = ProblemFactory.eINSTANCE.createNode();
109 newNode.setName("new");
110 classDeclaration.setNewNode(newNode);
111 problem.getStatements().add(classDeclaration);
112 createAssertion(classDeclaration, newNode);
113
114 assertSerializedResult("class Foo . Foo ( Foo::new ) .");
115 }
116
117 private void createAssertion(Relation relation, Node node) {
118 createAssertion(relation, node, LogicValue.TRUE);
119 }
120
121 private void createAssertion(Relation relation, Node node, LogicValue value) {
122 var assertion = ProblemFactory.eINSTANCE.createAssertion();
123 assertion.setRelation(relation);
124 var argument = ProblemFactory.eINSTANCE.createNodeAssertionArgument();
125 argument.setNode(node);
126 assertion.getArguments().add(argument);
127 assertion.setValue(value);
128 problem.getStatements().add(assertion);
129 }
130
131 @Test
132 void implicitVariableTest() {
133 var pred = ProblemFactory.eINSTANCE.createPredicateDefinition();
134 pred.setName("foo");
135 var nodeType = testUtil.findClass(builtin, "node");
136 var parameter1 = ProblemFactory.eINSTANCE.createParameter();
137 parameter1.setParameterType(nodeType);
138 parameter1.setName("p1");
139 pred.getParameters().add(parameter1);
140 var parameter2 = ProblemFactory.eINSTANCE.createParameter();
141 parameter2.setParameterType(nodeType);
142 parameter2.setName("p2");
143 pred.getParameters().add(parameter2);
144 var conjunction = ProblemFactory.eINSTANCE.createConjunction();
145 var variable = ProblemFactory.eINSTANCE.createImplicitVariable();
146 variable.setName("q");
147 conjunction.getImplicitVariables().add(variable);
148 var equals = testUtil.reference(nodeType, "equals");
149 conjunction.getLiterals().add(createAtom(equals, parameter1, variable));
150 conjunction.getLiterals().add(createAtom(equals, variable, parameter2));
151 pred.getBodies().add(conjunction);
152 problem.getStatements().add(pred);
153
154 assertSerializedResult("pred foo ( node p1 , node p2 ) <-> equals ( p1 , q ) , equals ( q , p2 ) .");
155 }
156
157 private Atom createAtom(Relation relation, VariableOrNode variable1, VariableOrNode variable2) {
158 var atom = ProblemFactory.eINSTANCE.createAtom();
159 atom.setRelation(relation);
160 var arg1 = ProblemFactory.eINSTANCE.createVariableOrNodeArgument();
161 arg1.setVariableOrNode(variable1);
162 atom.getArguments().add(arg1);
163 var arg2 = ProblemFactory.eINSTANCE.createVariableOrNodeArgument();
164 arg2.setVariableOrNode(variable2);
165 atom.getArguments().add(arg2);
166 return atom;
167 }
168
169 @Test
170 void singletonVariableTest() {
171 var pred = ProblemFactory.eINSTANCE.createPredicateDefinition();
172 pred.setName("foo");
173 var nodeType = testUtil.findClass(builtin, "node");
174 var parameter = ProblemFactory.eINSTANCE.createParameter();
175 parameter.setParameterType(nodeType);
176 parameter.setName("p");
177 pred.getParameters().add(parameter);
178 var conjunction = ProblemFactory.eINSTANCE.createConjunction();
179 var atom = ProblemFactory.eINSTANCE.createAtom();
180 var equals = testUtil.reference(nodeType, "equals");
181 atom.setRelation(equals);
182 var arg1 = ProblemFactory.eINSTANCE.createVariableOrNodeArgument();
183 arg1.setVariableOrNode(parameter);
184 atom.getArguments().add(arg1);
185 var arg2 = ProblemFactory.eINSTANCE.createVariableOrNodeArgument();
186 var variable = ProblemFactory.eINSTANCE.createImplicitVariable();
187 variable.setName("_q");
188 arg2.setSingletonVariable(variable);
189 arg2.setVariableOrNode(variable);
190 atom.getArguments().add(arg2);
191 conjunction.getLiterals().add(atom);
192 pred.getBodies().add(conjunction);
193 problem.getStatements().add(pred);
194
195 assertSerializedResult("pred foo ( node p ) <-> equals ( p , _q ) .");
196 }
197
198 private void assertSerializedResult(String expected) {
199 var outputStream = new ByteArrayOutputStream();
200 try {
201 resource.save(outputStream, Map.of());
202 } catch (IOException e) {
203 throw new AssertionError("Failed to serialize problem", e);
204 } finally {
205 try {
206 outputStream.close();
207 } catch (IOException e) {
208 // Nothing to handle in a test.
209 }
210 }
211 var problemString = outputStream.toString();
212
213 assertThat(problemString, equalTo(expected));
214 }
215}