diff options
author | 2021-11-06 16:56:11 +0100 | |
---|---|---|
committer | 2021-11-06 16:56:11 +0100 | |
commit | bf479290c950c004d8f99eda967e3a6c76e0e64b (patch) | |
tree | 2d805f058ab6b4289d4338b8f6beb12c51c31d09 | |
parent | Merge pull request #11 from kris7t/unique-to-individual (diff) | |
parent | chore(lang): seralize assertions in short form (diff) | |
download | refinery-bf479290c950c004d8f99eda967e3a6c76e0e64b.tar.gz refinery-bf479290c950c004d8f99eda967e3a6c76e0e64b.tar.zst refinery-bf479290c950c004d8f99eda967e3a6c76e0e64b.zip |
Merge pull request #12 from kris7t/xtext-serialization
Make sure Xtext serialization works
15 files changed, 242 insertions, 26 deletions
diff --git a/language-model/META-INF/MANIFEST.MF b/language-model/META-INF/MANIFEST.MF index 88725730..96617f85 100644 --- a/language-model/META-INF/MANIFEST.MF +++ b/language-model/META-INF/MANIFEST.MF | |||
@@ -12,5 +12,6 @@ Export-Package: tools.refinery.language.model.problem, | |||
12 | tools.refinery.language.model.problem.impl, | 12 | tools.refinery.language.model.problem.impl, |
13 | tools.refinery.language.model.problem.util | 13 | tools.refinery.language.model.problem.util |
14 | Require-Bundle: org.eclipse.emf.ecore;visibility:=reexport, | 14 | Require-Bundle: org.eclipse.emf.ecore;visibility:=reexport, |
15 | org.eclipse.emf.ecore.xmi;visibility:=reexport, | ||
15 | org.eclipse.core.runtime | 16 | org.eclipse.core.runtime |
16 | Bundle-ActivationPolicy: lazy | 17 | Bundle-ActivationPolicy: lazy |
diff --git a/language-model/src/main/java/tools/refinery/language/model/GenerateProblemModel.mwe2 b/language-model/src/main/java/tools/refinery/language/model/GenerateProblemModel.mwe2 index 7f998448..c1518b4d 100644 --- a/language-model/src/main/java/tools/refinery/language/model/GenerateProblemModel.mwe2 +++ b/language-model/src/main/java/tools/refinery/language/model/GenerateProblemModel.mwe2 | |||
@@ -3,7 +3,7 @@ module tools.refinery.language.model.GenerateProblemModel | |||
3 | Workflow { | 3 | Workflow { |
4 | bean = org.eclipse.emf.mwe.utils.StandaloneSetup { | 4 | bean = org.eclipse.emf.mwe.utils.StandaloneSetup { |
5 | projectMapping = { | 5 | projectMapping = { |
6 | projectName = "language-model" | 6 | projectName = "refinery-language-model" |
7 | path = "." | 7 | path = "." |
8 | } | 8 | } |
9 | } | 9 | } |
@@ -14,7 +14,7 @@ Workflow { | |||
14 | 14 | ||
15 | component = org.eclipse.emf.mwe2.ecore.EcoreGenerator { | 15 | component = org.eclipse.emf.mwe2.ecore.EcoreGenerator { |
16 | generateCustomClasses = false | 16 | generateCustomClasses = false |
17 | genModel = "platform:/resource/language-model/src/main/resources/model/problem.genmodel" | 17 | genModel = "platform:/resource/refinery-language-model/src/main/resources/model/problem.genmodel" |
18 | srcPath = "platform:/resource/language-model/src/main/emf-gen" | 18 | srcPath = "platform:/resource/refinery-language-model/src/main/emf-gen" |
19 | } | 19 | } |
20 | } | 20 | } |
diff --git a/language-model/src/main/resources/model/problem.ecore b/language-model/src/main/resources/model/problem.ecore index 77211b66..582f67c8 100644 --- a/language-model/src/main/resources/model/problem.ecore +++ b/language-model/src/main/resources/model/problem.ecore | |||
@@ -3,7 +3,7 @@ | |||
3 | xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" name="problem" nsURI="https://refinery.tools/emf/2021/Problem" nsPrefix="problem"> | 3 | xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" name="problem" nsURI="https://refinery.tools/emf/2021/Problem" nsPrefix="problem"> |
4 | <eClassifiers xsi:type="ecore:EClass" name="Problem" eSuperTypes="#//NamedElement"> | 4 | <eClassifiers xsi:type="ecore:EClass" name="Problem" eSuperTypes="#//NamedElement"> |
5 | <eStructuralFeatures xsi:type="ecore:EReference" name="nodes" upperBound="-1" | 5 | <eStructuralFeatures xsi:type="ecore:EReference" name="nodes" upperBound="-1" |
6 | eType="#//Node" containment="true"/> | 6 | eType="#//Node" transient="true" containment="true"/> |
7 | <eStructuralFeatures xsi:type="ecore:EReference" name="statements" upperBound="-1" | 7 | <eStructuralFeatures xsi:type="ecore:EReference" name="statements" upperBound="-1" |
8 | eType="#//Statement" containment="true"/> | 8 | eType="#//Statement" containment="true"/> |
9 | </eClassifiers> | 9 | </eClassifiers> |
@@ -15,7 +15,7 @@ | |||
15 | <eStructuralFeatures xsi:type="ecore:EReference" name="referenceDeclarations" | 15 | <eStructuralFeatures xsi:type="ecore:EReference" name="referenceDeclarations" |
16 | upperBound="-1" eType="#//ReferenceDeclaration" containment="true"/> | 16 | upperBound="-1" eType="#//ReferenceDeclaration" containment="true"/> |
17 | <eStructuralFeatures xsi:type="ecore:EReference" name="newNode" eType="#//Node" | 17 | <eStructuralFeatures xsi:type="ecore:EReference" name="newNode" eType="#//Node" |
18 | containment="true"/> | 18 | transient="true" containment="true"/> |
19 | </eClassifiers> | 19 | </eClassifiers> |
20 | <eClassifiers xsi:type="ecore:EClass" name="ReferenceDeclaration" eSuperTypes="#//Relation"> | 20 | <eClassifiers xsi:type="ecore:EClass" name="ReferenceDeclaration" eSuperTypes="#//Relation"> |
21 | <eStructuralFeatures xsi:type="ecore:EReference" name="referenceType" eType="#//Relation"/> | 21 | <eStructuralFeatures xsi:type="ecore:EReference" name="referenceType" eType="#//Relation"/> |
@@ -52,7 +52,7 @@ | |||
52 | <eClassifiers xsi:type="ecore:EClass" name="ExistentialQuantifier" abstract="true" | 52 | <eClassifiers xsi:type="ecore:EClass" name="ExistentialQuantifier" abstract="true" |
53 | interface="true"> | 53 | interface="true"> |
54 | <eStructuralFeatures xsi:type="ecore:EReference" name="implicitVariables" upperBound="-1" | 54 | <eStructuralFeatures xsi:type="ecore:EReference" name="implicitVariables" upperBound="-1" |
55 | eType="#//ImplicitVariable" containment="true"/> | 55 | eType="#//ImplicitVariable" transient="true" containment="true"/> |
56 | </eClassifiers> | 56 | </eClassifiers> |
57 | <eClassifiers xsi:type="ecore:EClass" name="Assertion" eSuperTypes="#//Statement"> | 57 | <eClassifiers xsi:type="ecore:EClass" name="Assertion" eSuperTypes="#//Statement"> |
58 | <eStructuralFeatures xsi:type="ecore:EReference" name="relation" eType="#//Relation"/> | 58 | <eStructuralFeatures xsi:type="ecore:EReference" name="relation" eType="#//Relation"/> |
@@ -95,7 +95,7 @@ | |||
95 | <eClassifiers xsi:type="ecore:EClass" name="VariableOrNodeArgument" eSuperTypes="#//Argument"> | 95 | <eClassifiers xsi:type="ecore:EClass" name="VariableOrNodeArgument" eSuperTypes="#//Argument"> |
96 | <eStructuralFeatures xsi:type="ecore:EReference" name="variableOrNode" eType="#//VariableOrNode"/> | 96 | <eStructuralFeatures xsi:type="ecore:EReference" name="variableOrNode" eType="#//VariableOrNode"/> |
97 | <eStructuralFeatures xsi:type="ecore:EReference" name="singletonVariable" eType="#//ImplicitVariable" | 97 | <eStructuralFeatures xsi:type="ecore:EReference" name="singletonVariable" eType="#//ImplicitVariable" |
98 | containment="true"/> | 98 | transient="true" containment="true"/> |
99 | </eClassifiers> | 99 | </eClassifiers> |
100 | <eClassifiers xsi:type="ecore:EClass" name="EnumDeclaration" eSuperTypes="#//Relation #//Statement"> | 100 | <eClassifiers xsi:type="ecore:EClass" name="EnumDeclaration" eSuperTypes="#//Relation #//Statement"> |
101 | <eStructuralFeatures xsi:type="ecore:EReference" name="literals" upperBound="-1" | 101 | <eStructuralFeatures xsi:type="ecore:EReference" name="literals" upperBound="-1" |
diff --git a/language-model/src/main/resources/model/problem.genmodel b/language-model/src/main/resources/model/problem.genmodel index 094533e7..3e0ee35e 100644 --- a/language-model/src/main/resources/model/problem.genmodel +++ b/language-model/src/main/resources/model/problem.genmodel | |||
@@ -1,7 +1,7 @@ | |||
1 | <?xml version="1.0" encoding="UTF-8"?> | 1 | <?xml version="1.0" encoding="UTF-8"?> |
2 | <genmodel:GenModel xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | 2 | <genmodel:GenModel xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
3 | xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" xmlns:genmodel="http://www.eclipse.org/emf/2002/GenModel" | 3 | xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" xmlns:genmodel="http://www.eclipse.org/emf/2002/GenModel" |
4 | modelDirectory="/language-model/src/main/emf-gen" creationIcons="false" | 4 | modelDirectory="/refinery-language-model/src/main/emf-gen" creationIcons="false" |
5 | editDirectory="/language-edit/src/main/emf-gen" editorDirectory="/org.eclipse.viatra.solver.language.model.editor/src-gen" | 5 | editDirectory="/language-edit/src/main/emf-gen" editorDirectory="/org.eclipse.viatra.solver.language.model.editor/src-gen" |
6 | modelPluginID="language-model" modelName="Problem" rootExtendsClass="org.eclipse.emf.ecore.impl.MinimalEObjectImpl$Container" | 6 | modelPluginID="language-model" modelName="Problem" rootExtendsClass="org.eclipse.emf.ecore.impl.MinimalEObjectImpl$Container" |
7 | codeFormatting="true" importerID="org.eclipse.emf.importer.ecore" complianceLevel="5.0" | 7 | codeFormatting="true" importerID="org.eclipse.emf.importer.ecore" complianceLevel="5.0" |
diff --git a/language-to-store/src/test/java/tools/refinery/language/mapping/tests/PartialModelMapperTest.xtend b/language-to-store/src/test/java/tools/refinery/language/mapping/tests/PartialModelMapperTest.xtend index add73c87..b2fcbaa9 100644 --- a/language-to-store/src/test/java/tools/refinery/language/mapping/tests/PartialModelMapperTest.xtend +++ b/language-to-store/src/test/java/tools/refinery/language/mapping/tests/PartialModelMapperTest.xtend | |||
@@ -290,7 +290,7 @@ class PartialModelMapperTest { | |||
290 | error invalidTaxStatus(Person p) <-> | 290 | error invalidTaxStatus(Person p) <-> |
291 | taxStatus(p, child), children(p, _q). | 291 | taxStatus(p, child), children(p, _q). |
292 | 292 | ||
293 | individual family. | 293 | indiv family. |
294 | Family(family). | 294 | Family(family). |
295 | members(family, anne): true. | 295 | members(family, anne): true. |
296 | members(family, bob). | 296 | members(family, bob). |
diff --git a/language-web/src/main/js/index.tsx b/language-web/src/main/js/index.tsx index 3e077ba8..d368c9ba 100644 --- a/language-web/src/main/js/index.tsx +++ b/language-web/src/main/js/index.tsx | |||
@@ -38,7 +38,7 @@ direct rule createChild(p): | |||
38 | children(p, q) = true, | 38 | children(p, q) = true, |
39 | taxStatus(q, child) = true. | 39 | taxStatus(q, child) = true. |
40 | 40 | ||
41 | individual family. | 41 | indiv family. |
42 | Family(family). | 42 | Family(family). |
43 | members(family, anne). | 43 | members(family, anne). |
44 | members(family, bob). | 44 | members(family, bob). |
diff --git a/language-web/src/main/js/language/problem.grammar b/language-web/src/main/js/language/problem.grammar index 0cbfa831..bccc2e31 100644 --- a/language-web/src/main/js/language/problem.grammar +++ b/language-web/src/main/js/language/problem.grammar | |||
@@ -35,7 +35,7 @@ statement { | |||
35 | IndividualNodeName ":" Constant "." | 35 | IndividualNodeName ":" Constant "." |
36 | } | | 36 | } | |
37 | IndividualDeclaration { | 37 | IndividualDeclaration { |
38 | ckw<"individual"> sep<",", IndividualNodeName> "." | 38 | ckw<"indiv"> sep<",", IndividualNodeName> "." |
39 | } | | 39 | } | |
40 | ScopeDeclaration { | 40 | ScopeDeclaration { |
41 | kw<"scope"> sep<",", ScopeElement> "." | 41 | kw<"scope"> sep<",", ScopeElement> "." |
diff --git a/language-web/src/main/js/language/problemLanguageSupport.ts b/language-web/src/main/js/language/problemLanguageSupport.ts index 1dba3447..6508a2c0 100644 --- a/language-web/src/main/js/language/problemLanguageSupport.ts +++ b/language-web/src/main/js/language/problemLanguageSupport.ts | |||
@@ -27,7 +27,7 @@ const parserWithMetadata = (parser as LRParser).configure({ | |||
27 | styleTags({ | 27 | styleTags({ |
28 | LineComment: t.lineComment, | 28 | LineComment: t.lineComment, |
29 | BlockComment: t.blockComment, | 29 | BlockComment: t.blockComment, |
30 | 'problem class enum pred rule individual scope': t.definitionKeyword, | 30 | 'problem class enum pred rule indiv scope': t.definitionKeyword, |
31 | 'abstract extends refers contains opposite error direct default': t.modifier, | 31 | 'abstract extends refers contains opposite error direct default': t.modifier, |
32 | 'true false unknown error': t.keyword, | 32 | 'true false unknown error': t.keyword, |
33 | 'new delete': t.operatorKeyword, | 33 | 'new delete': t.operatorKeyword, |
diff --git a/language-web/src/test/java/tools/refinery/language/web/ProblemWebSocketServletIntegrationTest.java b/language-web/src/test/java/tools/refinery/language/web/ProblemWebSocketServletIntegrationTest.java index d34a1610..a26ce040 100644 --- a/language-web/src/test/java/tools/refinery/language/web/ProblemWebSocketServletIntegrationTest.java +++ b/language-web/src/test/java/tools/refinery/language/web/ProblemWebSocketServletIntegrationTest.java | |||
@@ -96,7 +96,7 @@ class ProblemWebSocketServletIntegrationTest { | |||
96 | case 0 -> session.getRemote().sendString( | 96 | case 0 -> session.getRemote().sendString( |
97 | "{\"id\":\"foo\",\"request\":{\"resource\":\"test.problem\",\"serviceType\":\"update\",\"fullText\":\"class Person.\n\"}}"); | 97 | "{\"id\":\"foo\",\"request\":{\"resource\":\"test.problem\",\"serviceType\":\"update\",\"fullText\":\"class Person.\n\"}}"); |
98 | case 3 -> session.getRemote().sendString( | 98 | case 3 -> session.getRemote().sendString( |
99 | "{\"id\":\"bar\",\"request\":{\"resource\":\"test.problem\",\"serviceType\":\"update\",\"requiredStateId\":\"-80000000\",\"deltaText\":\"individual q.\nnode(q).\n\",\"deltaOffset\":\"0\",\"deltaReplaceLength\":\"0\"}}"); | 99 | "{\"id\":\"bar\",\"request\":{\"resource\":\"test.problem\",\"serviceType\":\"update\",\"requiredStateId\":\"-80000000\",\"deltaText\":\"indiv q.\nnode(q).\n\",\"deltaOffset\":\"0\",\"deltaReplaceLength\":\"0\"}}"); |
100 | case 5 -> session.close(); | 100 | case 5 -> session.close(); |
101 | } | 101 | } |
102 | } | 102 | } |
diff --git a/language-web/src/test/java/tools/refinery/language/web/xtext/servlet/TransactionExecutorTest.java b/language-web/src/test/java/tools/refinery/language/web/xtext/servlet/TransactionExecutorTest.java index 3229597e..5b8fedba 100644 --- a/language-web/src/test/java/tools/refinery/language/web/xtext/servlet/TransactionExecutorTest.java +++ b/language-web/src/test/java/tools/refinery/language/web/xtext/servlet/TransactionExecutorTest.java | |||
@@ -92,7 +92,7 @@ class TransactionExecutorTest { | |||
92 | var stateId = updateFullText(); | 92 | var stateId = updateFullText(); |
93 | var responseHandler = sendRequestAndWaitForAllResponses( | 93 | var responseHandler = sendRequestAndWaitForAllResponses( |
94 | new XtextWebRequest("bar", Map.of("resource", RESOURCE_NAME, "serviceType", "update", "requiredStateId", | 94 | new XtextWebRequest("bar", Map.of("resource", RESOURCE_NAME, "serviceType", "update", "requiredStateId", |
95 | stateId, "deltaText", "individual q.\nnode(q).\n", "deltaOffset", "0", "deltaReplaceLength", "0"))); | 95 | stateId, "deltaText", "indiv q.\nnode(q).\n", "deltaOffset", "0", "deltaReplaceLength", "0"))); |
96 | 96 | ||
97 | var captor = newCaptor(); | 97 | var captor = newCaptor(); |
98 | verify(responseHandler, times(2)).onResponse(captor.capture()); | 98 | verify(responseHandler, times(2)).onResponse(captor.capture()); |
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 | ||
110 | Assertion: | 110 | Assertion: |
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 | ||
120 | AssertionArgument: | 120 | AssertionArgument: |
@@ -174,7 +174,7 @@ ExactMultiplicity: | |||
174 | exactValue=INT; | 174 | exactValue=INT; |
175 | 175 | ||
176 | IndividualDeclaration: | 176 | IndividualDeclaration: |
177 | "individual" nodes+=EnumLiteral ("," nodes+=EnumLiteral)* "."; | 177 | "indiv" nodes+=EnumLiteral ("," nodes+=EnumLiteral)* "."; |
178 | 178 | ||
179 | UpperBound returns ecore::EInt: | 179 | UpperBound returns ecore::EInt: |
180 | INT | "*"; | 180 | INT | "*"; |
@@ -184,7 +184,7 @@ QualifiedName hidden(): | |||
184 | 184 | ||
185 | Identifier: | 185 | Identifier: |
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 | ||
189 | Integer returns ecore::EInt hidden(): | 189 | Integer 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 @@ | |||
1 | package tools.refinery.language.tests.serializer; | ||
2 | |||
3 | import static org.hamcrest.MatcherAssert.assertThat; | ||
4 | import static org.hamcrest.Matchers.equalTo; | ||
5 | |||
6 | import java.io.ByteArrayOutputStream; | ||
7 | import java.io.IOException; | ||
8 | import java.util.Map; | ||
9 | import java.util.stream.Stream; | ||
10 | |||
11 | import org.eclipse.emf.common.util.URI; | ||
12 | import org.eclipse.emf.ecore.resource.Resource; | ||
13 | import org.eclipse.emf.ecore.resource.ResourceSet; | ||
14 | import org.eclipse.xtext.testing.InjectWith; | ||
15 | import org.eclipse.xtext.testing.extensions.InjectionExtension; | ||
16 | import org.junit.jupiter.api.BeforeEach; | ||
17 | import org.junit.jupiter.api.Test; | ||
18 | import org.junit.jupiter.api.extension.ExtendWith; | ||
19 | import org.junit.jupiter.params.ParameterizedTest; | ||
20 | import org.junit.jupiter.params.provider.Arguments; | ||
21 | import org.junit.jupiter.params.provider.MethodSource; | ||
22 | |||
23 | import com.google.inject.Inject; | ||
24 | |||
25 | import tools.refinery.language.model.ProblemUtil; | ||
26 | import tools.refinery.language.model.problem.Atom; | ||
27 | import tools.refinery.language.model.problem.LogicValue; | ||
28 | import tools.refinery.language.model.problem.Node; | ||
29 | import tools.refinery.language.model.problem.PredicateDefinition; | ||
30 | import tools.refinery.language.model.problem.Problem; | ||
31 | import tools.refinery.language.model.problem.ProblemFactory; | ||
32 | import tools.refinery.language.model.problem.Relation; | ||
33 | import tools.refinery.language.model.problem.VariableOrNode; | ||
34 | import tools.refinery.language.model.tests.ProblemTestUtil; | ||
35 | import tools.refinery.language.tests.ProblemInjectorProvider; | ||
36 | |||
37 | @ExtendWith(InjectionExtension.class) | ||
38 | @InjectWith(ProblemInjectorProvider.class) | ||
39 | public 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 | } | ||