aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/language/src/main/java/tools
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <kristof@marussy.com>2022-11-19 21:39:00 +0100
committerLibravatar Kristóf Marussy <kristof@marussy.com>2022-11-22 16:40:03 +0100
commit3aa4a2b58221a3e83b17d0c04c9a6e9c41e5500c (patch)
tree1e25f513e3b34b2ea29dbcc6cc3795e5927a1362 /subprojects/language/src/main/java/tools
parentfeat(language): numeric expressions (diff)
downloadrefinery-3aa4a2b58221a3e83b17d0c04c9a6e9c41e5500c.tar.gz
refinery-3aa4a2b58221a3e83b17d0c04c9a6e9c41e5500c.tar.zst
refinery-3aa4a2b58221a3e83b17d0c04c9a6e9c41e5500c.zip
refactor: separate primitive types from nodes
Diffstat (limited to 'subprojects/language/src/main/java/tools')
-rw-r--r--subprojects/language/src/main/java/tools/refinery/language/Problem.xtext102
-rw-r--r--subprojects/language/src/main/java/tools/refinery/language/ProblemRuntimeModule.java21
-rw-r--r--subprojects/language/src/main/java/tools/refinery/language/formatting2/ProblemFormatter.java32
-rw-r--r--subprojects/language/src/main/java/tools/refinery/language/resource/NodeNameCollector.java38
-rw-r--r--subprojects/language/src/main/java/tools/refinery/language/resource/ProblemDerivedStateComputer.java67
-rw-r--r--subprojects/language/src/main/java/tools/refinery/language/scoping/ProblemScopeProvider.java3
-rw-r--r--subprojects/language/src/main/java/tools/refinery/language/serializer/PreferShortAssertionsProblemSemanticSequencer.java52
-rw-r--r--subprojects/language/src/main/java/tools/refinery/language/utils/BuiltinSymbols.java12
-rw-r--r--subprojects/language/src/main/java/tools/refinery/language/utils/NodeInfo.java10
-rw-r--r--subprojects/language/src/main/java/tools/refinery/language/utils/ProblemDesugarer.java50
-rw-r--r--subprojects/language/src/main/java/tools/refinery/language/utils/SymbolCollector.java134
11 files changed, 237 insertions, 284 deletions
diff --git a/subprojects/language/src/main/java/tools/refinery/language/Problem.xtext b/subprojects/language/src/main/java/tools/refinery/language/Problem.xtext
index bc1ee465..8b13a693 100644
--- a/subprojects/language/src/main/java/tools/refinery/language/Problem.xtext
+++ b/subprojects/language/src/main/java/tools/refinery/language/Problem.xtext
@@ -10,14 +10,13 @@ Problem:
10Statement: 10Statement:
11 ClassDeclaration | EnumDeclaration | 11 ClassDeclaration | EnumDeclaration |
12 PredicateDefinition | FunctionDefinition | /* RuleDefinition | */ 12 PredicateDefinition | FunctionDefinition | /* RuleDefinition | */
13 Assertion | NodeValueAssertion | 13 Assertion | ScopeDeclaration | IndividualDeclaration;
14 ScopeDeclaration | IndividualDeclaration;
15 14
16ClassDeclaration: 15ClassDeclaration:
17 abstract?="abstract"? "class" 16 abstract?="abstract"? "class"
18 name=Identifier 17 name=Identifier
19 ("extends" superTypes+=[Relation|QualifiedName] ("," superTypes+=[Relation|QualifiedName])*)? 18 ("extends" superTypes+=[Relation|QualifiedName] ("," superTypes+=[Relation|QualifiedName])*)?
20 ("{" (referenceDeclarations+=ReferenceDeclaration ";"?)* "}" | "."); 19 ("{" (featureDeclarations+=FeatureDeclaration ";"?)* "}" | ".");
21 20
22EnumDeclaration: 21EnumDeclaration:
23 "enum" 22 "enum"
@@ -27,16 +26,27 @@ EnumDeclaration:
27EnumLiteral returns Node: 26EnumLiteral returns Node:
28 name=Identifier; 27 name=Identifier;
29 28
29FeatureDeclaration:
30 ReferenceDeclaration | AttributeDeclaration | FlagDeclaration;
31
30enum ReferenceKind: 32enum ReferenceKind:
31 REFERENCE="refers" | CONTAINMENT="contains" | CONTAINER="container"; 33 REFERENCE="refers" | CONTAINMENT="contains" | CONTAINER="container";
32 34
33ReferenceDeclaration: 35ReferenceDeclaration:
34 (kind=ReferenceKind referenceType=[Relation|QualifiedName] | 36 kind=ReferenceKind referenceType=[Relation|QualifiedName]
35 referenceType=[Relation|NonRelationKindQualifiedName])
36 ("[" multiplicity=Multiplicity "]")? 37 ("[" multiplicity=Multiplicity "]")?
37 name=Identifier 38 name=Identifier
38 ("opposite" opposite=[ReferenceDeclaration|QualifiedName])?; 39 ("opposite" opposite=[ReferenceDeclaration|QualifiedName])?;
39 40
41enum PrimitiveType:
42 INT="int" | REAL="real" | STRING="string";
43
44AttributeDeclaration:
45 attributeType=PrimitiveType name=Identifier;
46
47FlagDeclaration:
48 "bool" name=Identifier;
49
40enum ErrorKind returns PredicateKind: 50enum ErrorKind returns PredicateKind:
41 ERROR="error"; 51 ERROR="error";
42 52
@@ -54,7 +64,7 @@ Conjunction:
54 literals+=Expr ("," literals+=Expr)*; 64 literals+=Expr ("," literals+=Expr)*;
55 65
56FunctionDefinition: 66FunctionDefinition:
57 functionType=[Relation|QualifiedName] name=Identifier 67 functionType=PrimitiveType name=Identifier
58 "(" (parameters+=Parameter ("," parameters+=Parameter)*)? ")" 68 "(" (parameters+=Parameter ("," parameters+=Parameter)*)? ")"
59 ("=" cases+=Case (";" cases+=Case)*)? 69 ("=" cases+=Case (";" cases+=Case)*)?
60 "."; 70 ".";
@@ -96,11 +106,21 @@ Expr:
96 ComparisonExpr; 106 ComparisonExpr;
97 107
98enum ComparisonOp: 108enum ComparisonOp:
99 LESS="<" | LESS_EQ="<=" | GREATER=">" | GREATER_EQ=">=" | EQ="==" | NOT_EQ="!="; 109 LESS="<" | LESS_EQ="<=" | GREATER=">" | GREATER_EQ=">=" | EQ="==" | NOT_EQ="!=" | IN="in";
100 110
101ComparisonExpr returns Expr: 111ComparisonExpr returns Expr:
102 AdditiveExpr ({ComparisonExpr.left=current} 112 LatticeExpr ({ComparisonExpr.left=current}
103 op=ComparisonOp right=AdditiveExpr)*; 113 op=ComparisonOp right=LatticeExpr)*;
114
115enum LatticeOp returns BinaryOp:
116 MEET="/\\" | JOIN="\\/";
117
118LatticeExpr returns Expr:
119 RangeExpr ({ArithmeticBinaryExpr.left=current}
120 op=LatticeOp right=RangeExpr)*;
121
122RangeExpr returns Expr:
123 AdditiveExpr ({RangeExpr.left=current} ".." right=AdditiveExpr)*;
104 124
105enum AdditiveOp returns BinaryOp: 125enum AdditiveOp returns BinaryOp:
106 ADD="+" | SUB="-"; 126 ADD="+" | SUB="-";
@@ -125,7 +145,7 @@ ExponentialExpr returns Expr:
125 145
126UnaryExpr returns Expr: 146UnaryExpr returns Expr:
127 ArithmeticUnaryExpr | ModalExpr | NegationExpr | CountExpr | AggregationExpr | 147 ArithmeticUnaryExpr | ModalExpr | NegationExpr | CountExpr | AggregationExpr |
128 Atom | VariableOrNodeExpr | ConstantExpr | "(" Expr ")"; 148 Atom | VariableOrNodeExpr | Constant | "(" Expr ")";
129 149
130enum UnaryOp: 150enum UnaryOp:
131 PLUS="+" | MINUS="-"; 151 PLUS="+" | MINUS="-";
@@ -159,21 +179,33 @@ Atom:
159VariableOrNodeExpr: 179VariableOrNodeExpr:
160 variableOrNode=[VariableOrNode|QualifiedName]; 180 variableOrNode=[VariableOrNode|QualifiedName];
161 181
162ConstantExpr: 182Constant:
163 constant=Constant; 183 RealConstant | IntConstant | InfConstant | StringConstant;
184
185IntConstant:
186 intValue=INT;
187
188RealConstant:
189 realValue=Real;
190
191InfConstant:
192 {InfConstant} "*";
193
194StringConstant:
195 stringValue=STRING;
164 196
165Assertion: 197Assertion:
166 default?="default"? 198 default?="default"?
167 (value=ShortLogicValue? 199 (relation=[Relation|QualifiedName]
168 relation=[Relation|QualifiedName]
169 "(" (arguments+=AssertionArgument ("," arguments+=AssertionArgument)*)? ")"
170 | relation=[Relation|QualifiedName]
171 "(" (arguments+=AssertionArgument ("," arguments+=AssertionArgument)*)? ")" 200 "(" (arguments+=AssertionArgument ("," arguments+=AssertionArgument)*)? ")"
172 ":" value=LogicValue) 201 value=AssertionValue |
202 value=ShortLogicAssertionValue
203 relation=[Relation|QualifiedName]
204 "(" (arguments+=AssertionArgument ("," arguments+=AssertionArgument)*)? ")")
173 "."; 205 ".";
174 206
175AssertionArgument: 207AssertionArgument:
176 NodeAssertionArgument | WildcardAssertionArgument | ConstantAssertionArgument; 208 NodeAssertionArgument | WildcardAssertionArgument;
177 209
178NodeAssertionArgument: 210NodeAssertionArgument:
179 node=[Node|QualifiedName]; 211 node=[Node|QualifiedName];
@@ -181,29 +213,23 @@ NodeAssertionArgument:
181WildcardAssertionArgument: 213WildcardAssertionArgument:
182 {WildcardAssertionArgument} "*"; 214 {WildcardAssertionArgument} "*";
183 215
184ConstantAssertionArgument: 216AssertionValue:
185 negative?="-"? constant=Constant; 217 LogicAssertionValue | ExprAssertionValue;
186 218
187enum LogicValue: 219enum LogicValue:
188 TRUE="true" | FALSE="false" | UNKNOWN="unknown" | ERROR="error"; 220 TRUE="true" | FALSE="false" | UNKNOWN="unknown" | ERROR="error";
189 221
190enum ShortLogicValue returns LogicValue: 222LogicAssertionValue:
191 FALSE="!" | UNKNOWN="?"; 223 ":" logicValue=LogicValue;
192 224
193NodeValueAssertion: 225ExprAssertionValue:
194 node=[Node|QualifiedName] ":" value=Constant "."; 226 (range?="in" | "=") body=Expr;
195
196Constant:
197 RealConstant | IntConstant | StringConstant;
198
199IntConstant:
200 intValue=INT;
201 227
202RealConstant: 228enum ShortLogicValue returns LogicValue:
203 realValue=Real; 229 FALSE="!" | UNKNOWN="?";
204 230
205StringConstant: 231ShortLogicAssertionValue returns LogicAssertionValue:
206 stringValue=STRING; 232 {LogicAssertionValue} logicValue=ShortLogicValue?;
207 233
208ScopeDeclaration: 234ScopeDeclaration:
209 "scope" typeScopes+=TypeScope ("," typeScopes+=TypeScope)* "."; 235 "scope" typeScopes+=TypeScope ("," typeScopes+=TypeScope)* ".";
@@ -234,17 +260,11 @@ IndividualDeclaration:
234UpperBound returns ecore::EInt: 260UpperBound returns ecore::EInt:
235 INT | "*"; 261 INT | "*";
236 262
237NonRelationKindQualifiedName hidden():
238 NonRelationKindIdentifier ("::" Identifier)*;
239
240QualifiedName hidden(): 263QualifiedName hidden():
241 Identifier ("::" Identifier)*; 264 Identifier ("::" Identifier)*;
242 265
243NonRelationKindIdentifier:
244 ID | "true" | "false" | "contained" | "sum" | "prod" | "min" | "max";
245
246Identifier: 266Identifier:
247 NonRelationKindIdentifier | "contains"; 267 ID | "contains" | "contained" | "sum" | "prod" | "min" | "max";
248 268
249Real returns ecore::EDouble: 269Real returns ecore::EDouble:
250 EXPONENTIAL | INT "." (INT | EXPONENTIAL); 270 EXPONENTIAL | INT "." (INT | EXPONENTIAL);
diff --git a/subprojects/language/src/main/java/tools/refinery/language/ProblemRuntimeModule.java b/subprojects/language/src/main/java/tools/refinery/language/ProblemRuntimeModule.java
index c0777038..5efcdc81 100644
--- a/subprojects/language/src/main/java/tools/refinery/language/ProblemRuntimeModule.java
+++ b/subprojects/language/src/main/java/tools/refinery/language/ProblemRuntimeModule.java
@@ -3,25 +3,18 @@
3 */ 3 */
4package tools.refinery.language; 4package tools.refinery.language;
5 5
6import com.google.inject.Binder;
7import com.google.inject.name.Names;
6import org.eclipse.xtext.conversion.IValueConverterService; 8import org.eclipse.xtext.conversion.IValueConverterService;
7import org.eclipse.xtext.naming.IQualifiedNameConverter; 9import org.eclipse.xtext.naming.IQualifiedNameConverter;
8import org.eclipse.xtext.parser.IParser; 10import org.eclipse.xtext.parser.IParser;
9import org.eclipse.xtext.resource.DerivedStateAwareResource; 11import org.eclipse.xtext.resource.*;
10import org.eclipse.xtext.resource.DerivedStateAwareResourceDescriptionManager;
11import org.eclipse.xtext.resource.IDefaultResourceDescriptionStrategy;
12import org.eclipse.xtext.resource.IDerivedStateComputer;
13import org.eclipse.xtext.resource.ILocationInFileProvider;
14import org.eclipse.xtext.resource.IResourceDescription;
15import org.eclipse.xtext.resource.XtextResource;
16import org.eclipse.xtext.scoping.IGlobalScopeProvider; 12import org.eclipse.xtext.scoping.IGlobalScopeProvider;
17import org.eclipse.xtext.scoping.IScopeProvider; 13import org.eclipse.xtext.scoping.IScopeProvider;
18import org.eclipse.xtext.scoping.impl.AbstractDeclarativeScopeProvider; 14import org.eclipse.xtext.scoping.impl.AbstractDeclarativeScopeProvider;
15import org.eclipse.xtext.serializer.sequencer.ISemanticSequencer;
19import org.eclipse.xtext.validation.IResourceValidator; 16import org.eclipse.xtext.validation.IResourceValidator;
20import org.eclipse.xtext.xbase.annotations.validation.DerivedStateAwareResourceValidator; 17import org.eclipse.xtext.xbase.annotations.validation.DerivedStateAwareResourceValidator;
21
22import com.google.inject.Binder;
23import com.google.inject.name.Names;
24
25import tools.refinery.language.conversion.ProblemValueConverterService; 18import tools.refinery.language.conversion.ProblemValueConverterService;
26import tools.refinery.language.naming.ProblemQualifiedNameConverter; 19import tools.refinery.language.naming.ProblemQualifiedNameConverter;
27import tools.refinery.language.parser.antlr.TokenSourceInjectingProblemParser; 20import tools.refinery.language.parser.antlr.TokenSourceInjectingProblemParser;
@@ -30,6 +23,7 @@ import tools.refinery.language.resource.ProblemLocationInFileProvider;
30import tools.refinery.language.resource.ProblemResourceDescriptionStrategy; 23import tools.refinery.language.resource.ProblemResourceDescriptionStrategy;
31import tools.refinery.language.scoping.ProblemGlobalScopeProvider; 24import tools.refinery.language.scoping.ProblemGlobalScopeProvider;
32import tools.refinery.language.scoping.ProblemLocalScopeProvider; 25import tools.refinery.language.scoping.ProblemLocalScopeProvider;
26import tools.refinery.language.serializer.PreferShortAssertionsProblemSemanticSequencer;
33 27
34/** 28/**
35 * Use this class to register components to be used at runtime / without the 29 * Use this class to register components to be used at runtime / without the
@@ -88,4 +82,9 @@ public class ProblemRuntimeModule extends AbstractProblemRuntimeModule {
88 public Class<? extends ILocationInFileProvider> bindILocationInFileProvider() { 82 public Class<? extends ILocationInFileProvider> bindILocationInFileProvider() {
89 return ProblemLocationInFileProvider.class; 83 return ProblemLocationInFileProvider.class;
90 } 84 }
85
86 @Override
87 public Class<? extends ISemanticSequencer> bindISemanticSequencer() {
88 return PreferShortAssertionsProblemSemanticSequencer.class;
89 }
91} 90}
diff --git a/subprojects/language/src/main/java/tools/refinery/language/formatting2/ProblemFormatter.java b/subprojects/language/src/main/java/tools/refinery/language/formatting2/ProblemFormatter.java
index a65e0750..46870edb 100644
--- a/subprojects/language/src/main/java/tools/refinery/language/formatting2/ProblemFormatter.java
+++ b/subprojects/language/src/main/java/tools/refinery/language/formatting2/ProblemFormatter.java
@@ -3,6 +3,7 @@
3 */ 3 */
4package tools.refinery.language.formatting2; 4package tools.refinery.language.formatting2;
5 5
6import com.google.inject.Inject;
6import org.eclipse.emf.ecore.EObject; 7import org.eclipse.emf.ecore.EObject;
7import org.eclipse.xtext.formatting2.AbstractJavaFormatter; 8import org.eclipse.xtext.formatting2.AbstractJavaFormatter;
8import org.eclipse.xtext.formatting2.IFormattableDocument; 9import org.eclipse.xtext.formatting2.IFormattableDocument;
@@ -12,9 +13,12 @@ import org.eclipse.xtext.formatting2.regionaccess.ISequentialRegion;
12import org.eclipse.xtext.xbase.lib.Procedures.Procedure1; 13import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
13 14
14import tools.refinery.language.model.problem.*; 15import tools.refinery.language.model.problem.*;
16import tools.refinery.language.services.ProblemGrammarAccess;
15 17
16@SuppressWarnings("UnstableApiUsage") 18@SuppressWarnings("UnstableApiUsage")
17public class ProblemFormatter extends AbstractJavaFormatter { 19public class ProblemFormatter extends AbstractJavaFormatter {
20 @Inject
21 private ProblemGrammarAccess problemGrammarAccess;
18 22
19 protected void format(Problem problem, IFormattableDocument doc) { 23 protected void format(Problem problem, IFormattableDocument doc) {
20 doc.prepend(problem, this::noSpace); 24 doc.prepend(problem, this::noSpace);
@@ -31,17 +35,35 @@ public class ProblemFormatter extends AbstractJavaFormatter {
31 surroundNewLines(doc, assertion, this::singleNewLine); 35 surroundNewLines(doc, assertion, this::singleNewLine);
32 var region = regionFor(assertion); 36 var region = regionFor(assertion);
33 doc.append(region.feature(ProblemPackage.Literals.ASSERTION__DEFAULT), this::oneSpace); 37 doc.append(region.feature(ProblemPackage.Literals.ASSERTION__DEFAULT), this::oneSpace);
34 doc.append(region.feature(ProblemPackage.Literals.ASSERTION__VALUE), this::noSpace);
35 doc.append(region.feature(ProblemPackage.Literals.ASSERTION__RELATION), this::noSpace); 38 doc.append(region.feature(ProblemPackage.Literals.ASSERTION__RELATION), this::noSpace);
36 formatParenthesizedList(region, doc); 39 formatParenthesizedList(region, doc);
37 doc.prepend(region.keyword(":"), this::noSpace); 40 var value = assertion.getValue();
38 doc.append(region.keyword(":"), this::oneSpace); 41 if (value != null) {
42 doc.append(value, this::noSpace);
43 doc.format(value);
44 }
39 doc.prepend(region.keyword("."), this::noSpace); 45 doc.prepend(region.keyword("."), this::noSpace);
40 for (var argument : assertion.getArguments()) { 46 for (var argument : assertion.getArguments()) {
41 doc.format(argument); 47 doc.format(argument);
42 } 48 }
43 } 49 }
44 50
51 protected void format(LogicAssertionValue assertionValue, IFormattableDocument doc) {
52 var region = regionFor(assertionValue);
53 doc.prepend(region.keyword(":"), this::noSpace);
54 doc.append(region.keyword(":"), this::oneSpace);
55 }
56
57 protected void format(ExprAssertionValue assertionValue, IFormattableDocument doc) {
58 var region = regionFor(assertionValue);
59 doc.surround(region.keyword("="), this::oneSpace);
60 doc.surround(region.keyword("in"), this::oneSpace);
61 var body = assertionValue.getBody();
62 if (body != null) {
63 doc.format(body);
64 }
65 }
66
45 protected void format(ClassDeclaration classDeclaration, IFormattableDocument doc) { 67 protected void format(ClassDeclaration classDeclaration, IFormattableDocument doc) {
46 surroundNewLines(doc, classDeclaration, this::twoNewLines); 68 surroundNewLines(doc, classDeclaration, this::twoNewLines);
47 var region = regionFor(classDeclaration); 69 var region = regionFor(classDeclaration);
@@ -53,8 +75,8 @@ public class ProblemFormatter extends AbstractJavaFormatter {
53 doc.append(region.keyword("{"), it -> it.setNewLines(1, 1, 2)); 75 doc.append(region.keyword("{"), it -> it.setNewLines(1, 1, 2));
54 doc.prepend(region.keyword("}"), it -> it.setNewLines(1, 1, 2)); 76 doc.prepend(region.keyword("}"), it -> it.setNewLines(1, 1, 2));
55 doc.prepend(region.keyword("."), this::noSpace); 77 doc.prepend(region.keyword("."), this::noSpace);
56 for (var referenceDeclaration : classDeclaration.getReferenceDeclarations()) { 78 for (var featureDeclaration : classDeclaration.getFeatureDeclarations()) {
57 doc.format(referenceDeclaration); 79 doc.format(featureDeclaration);
58 } 80 }
59 } 81 }
60 82
diff --git a/subprojects/language/src/main/java/tools/refinery/language/resource/NodeNameCollector.java b/subprojects/language/src/main/java/tools/refinery/language/resource/NodeNameCollector.java
index 99bf9b64..419be0d3 100644
--- a/subprojects/language/src/main/java/tools/refinery/language/resource/NodeNameCollector.java
+++ b/subprojects/language/src/main/java/tools/refinery/language/resource/NodeNameCollector.java
@@ -1,10 +1,9 @@
1package tools.refinery.language.resource; 1package tools.refinery.language.resource;
2 2
3import java.util.List; 3import com.google.common.collect.ImmutableSet;
4import java.util.Set; 4import com.google.inject.Inject;
5 5import com.google.inject.name.Named;
6import org.eclipse.emf.ecore.EObject; 6import org.eclipse.emf.ecore.EObject;
7import org.eclipse.emf.ecore.EStructuralFeature;
8import org.eclipse.xtext.linking.impl.LinkingHelper; 7import org.eclipse.xtext.linking.impl.LinkingHelper;
9import org.eclipse.xtext.naming.IQualifiedNameConverter; 8import org.eclipse.xtext.naming.IQualifiedNameConverter;
10import org.eclipse.xtext.nodemodel.INode; 9import org.eclipse.xtext.nodemodel.INode;
@@ -12,20 +11,12 @@ import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
12import org.eclipse.xtext.scoping.IScope; 11import org.eclipse.xtext.scoping.IScope;
13import org.eclipse.xtext.scoping.IScopeProvider; 12import org.eclipse.xtext.scoping.IScopeProvider;
14import org.eclipse.xtext.scoping.impl.AbstractDeclarativeScopeProvider; 13import org.eclipse.xtext.scoping.impl.AbstractDeclarativeScopeProvider;
15 14import tools.refinery.language.model.problem.*;
16import com.google.common.collect.ImmutableSet;
17import com.google.inject.Inject;
18import com.google.inject.name.Named;
19
20import tools.refinery.language.model.problem.Assertion;
21import tools.refinery.language.model.problem.AssertionArgument;
22import tools.refinery.language.model.problem.NodeAssertionArgument;
23import tools.refinery.language.model.problem.NodeValueAssertion;
24import tools.refinery.language.model.problem.Problem;
25import tools.refinery.language.model.problem.ProblemPackage;
26import tools.refinery.language.model.problem.Statement;
27import tools.refinery.language.naming.NamingUtil; 15import tools.refinery.language.naming.NamingUtil;
28 16
17import java.util.List;
18import java.util.Set;
19
29public class NodeNameCollector { 20public class NodeNameCollector {
30 @Inject 21 @Inject
31 private LinkingHelper linkingHelper; 22 private LinkingHelper linkingHelper;
@@ -55,25 +46,20 @@ public class NodeNameCollector {
55 protected void collectStatementNodeNames(Statement statement) { 46 protected void collectStatementNodeNames(Statement statement) {
56 if (statement instanceof Assertion assertion) { 47 if (statement instanceof Assertion assertion) {
57 collectAssertionNodeNames(assertion); 48 collectAssertionNodeNames(assertion);
58 } else if (statement instanceof NodeValueAssertion nodeValueAssertion) {
59 collectNodeValueAssertionNodeNames(nodeValueAssertion);
60 } 49 }
61 } 50 }
62 51
63 protected void collectAssertionNodeNames(Assertion assertion) { 52 protected void collectAssertionNodeNames(Assertion assertion) {
64 for (AssertionArgument argument : assertion.getArguments()) { 53 for (AssertionArgument argument : assertion.getArguments()) {
65 if (argument instanceof NodeAssertionArgument) { 54 if (argument instanceof NodeAssertionArgument) {
66 collectNodeNames(argument, ProblemPackage.Literals.NODE_ASSERTION_ARGUMENT__NODE); 55 collectNodeNames(argument);
67 } 56 }
68 } 57 }
69 } 58 }
70 59
71 protected void collectNodeValueAssertionNodeNames(NodeValueAssertion nodeValueAssertion) { 60 private void collectNodeNames(EObject eObject) {
72 collectNodeNames(nodeValueAssertion, ProblemPackage.Literals.NODE_VALUE_ASSERTION__NODE); 61 List<INode> nodes = NodeModelUtils.findNodesForFeature(eObject,
73 } 62 ProblemPackage.Literals.NODE_ASSERTION_ARGUMENT__NODE);
74
75 private void collectNodeNames(EObject eObject, EStructuralFeature feature) {
76 List<INode> nodes = NodeModelUtils.findNodesForFeature(eObject, feature);
77 for (INode node : nodes) { 63 for (INode node : nodes) {
78 var nodeName = linkingHelper.getCrossRefNodeAsString(node, true); 64 var nodeName = linkingHelper.getCrossRefNodeAsString(node, true);
79 if (!NamingUtil.isValidId(nodeName)) { 65 if (!NamingUtil.isValidId(nodeName)) {
@@ -85,4 +71,4 @@ public class NodeNameCollector {
85 } 71 }
86 } 72 }
87 } 73 }
88} \ No newline at end of file 74}
diff --git a/subprojects/language/src/main/java/tools/refinery/language/resource/ProblemDerivedStateComputer.java b/subprojects/language/src/main/java/tools/refinery/language/resource/ProblemDerivedStateComputer.java
index f28e1791..8d3a552a 100644
--- a/subprojects/language/src/main/java/tools/refinery/language/resource/ProblemDerivedStateComputer.java
+++ b/subprojects/language/src/main/java/tools/refinery/language/resource/ProblemDerivedStateComputer.java
@@ -1,13 +1,9 @@
1package tools.refinery.language.resource; 1package tools.refinery.language.resource;
2 2
3import java.util.Collection; 3import com.google.inject.Inject;
4import java.util.HashMap; 4import com.google.inject.Provider;
5import java.util.HashSet; 5import com.google.inject.Singleton;
6import java.util.List; 6import com.google.inject.name.Named;
7import java.util.Map;
8import java.util.Set;
9import java.util.function.Function;
10
11import org.eclipse.emf.common.notify.impl.AdapterImpl; 7import org.eclipse.emf.common.notify.impl.AdapterImpl;
12import org.eclipse.emf.ecore.EObject; 8import org.eclipse.emf.ecore.EObject;
13import org.eclipse.emf.ecore.resource.Resource; 9import org.eclipse.emf.ecore.resource.Resource;
@@ -16,37 +12,20 @@ import org.eclipse.xtext.Constants;
16import org.eclipse.xtext.resource.DerivedStateAwareResource; 12import org.eclipse.xtext.resource.DerivedStateAwareResource;
17import org.eclipse.xtext.resource.IDerivedStateComputer; 13import org.eclipse.xtext.resource.IDerivedStateComputer;
18import org.eclipse.xtext.resource.XtextResource; 14import org.eclipse.xtext.resource.XtextResource;
19import org.eclipse.xtext.scoping.IScopeProvider; 15import tools.refinery.language.model.problem.*;
20import org.eclipse.xtext.scoping.impl.AbstractDeclarativeScopeProvider;
21
22import com.google.inject.Inject;
23import com.google.inject.Provider;
24import com.google.inject.Singleton;
25import com.google.inject.name.Named;
26 16
27import tools.refinery.language.model.problem.Assertion; 17import java.util.*;
28import tools.refinery.language.model.problem.ClassDeclaration; 18import java.util.function.Function;
29import tools.refinery.language.model.problem.ConstantAssertionArgument;
30import tools.refinery.language.model.problem.Node;
31import tools.refinery.language.model.problem.Problem;
32import tools.refinery.language.model.problem.ProblemFactory;
33import tools.refinery.language.model.problem.Statement;
34 19
35@Singleton 20@Singleton
36public class ProblemDerivedStateComputer implements IDerivedStateComputer { 21public class ProblemDerivedStateComputer implements IDerivedStateComputer {
37 public static final String NEW_NODE = "new"; 22 public static final String NEW_NODE = "new";
38 23
39 public static final String CONSTANT_NODE = "constant";
40
41 @Inject 24 @Inject
42 @Named(Constants.LANGUAGE_NAME) 25 @Named(Constants.LANGUAGE_NAME)
43 private String languageName; 26 private String languageName;
44 27
45 @Inject 28 @Inject
46 @Named(AbstractDeclarativeScopeProvider.NAMED_DELEGATE)
47 private IScopeProvider scopeProvider;
48
49 @Inject
50 private Provider<NodeNameCollector> nodeNameCollectorProvider; 29 private Provider<NodeNameCollector> nodeNameCollectorProvider;
51 30
52 @Inject 31 @Inject
@@ -88,15 +67,6 @@ public class ProblemDerivedStateComputer implements IDerivedStateComputer {
88 && declaration.getNewNode() == null) { 67 && declaration.getNewNode() == null) {
89 var newNode = adapter.createNewNodeIfAbsent(declaration, key -> createNode(NEW_NODE)); 68 var newNode = adapter.createNewNodeIfAbsent(declaration, key -> createNode(NEW_NODE));
90 declaration.setNewNode(newNode); 69 declaration.setNewNode(newNode);
91 } else if (statement instanceof Assertion assertion) {
92 for (var argument : assertion.getArguments()) {
93 if (argument instanceof ConstantAssertionArgument constantAssertionArgument
94 && constantAssertionArgument.getNode() == null) {
95 var constantNode = adapter.createConstantNodeIfAbsent(constantAssertionArgument,
96 key -> createNode(CONSTANT_NODE));
97 constantAssertionArgument.setNode(constantNode);
98 }
99 }
100 } 70 }
101 } 71 }
102 } 72 }
@@ -130,22 +100,14 @@ public class ProblemDerivedStateComputer implements IDerivedStateComputer {
130 100
131 protected void discardDerivedProblemState(Problem problem, Adapter adapter) { 101 protected void discardDerivedProblemState(Problem problem, Adapter adapter) {
132 Set<ClassDeclaration> classDeclarations = new HashSet<>(); 102 Set<ClassDeclaration> classDeclarations = new HashSet<>();
133 Set<ConstantAssertionArgument> constantAssertionArguments = new HashSet<>();
134 problem.getNodes().clear(); 103 problem.getNodes().clear();
135 for (var statement : problem.getStatements()) { 104 for (var statement : problem.getStatements()) {
136 if (statement instanceof ClassDeclaration classDeclaration) { 105 if (statement instanceof ClassDeclaration classDeclaration) {
137 classDeclaration.setNewNode(null); 106 classDeclaration.setNewNode(null);
138 classDeclarations.add(classDeclaration); 107 classDeclarations.add(classDeclaration);
139 } else if (statement instanceof Assertion assertion) {
140 for (var argument : assertion.getArguments()) {
141 if (argument instanceof ConstantAssertionArgument constantAssertionArgument) {
142 constantAssertionArgument.setNode(null);
143 constantAssertionArguments.add(constantAssertionArgument);
144 }
145 }
146 } 108 }
147 } 109 }
148 adapter.retainAll(classDeclarations, constantAssertionArguments); 110 adapter.retainAll(classDeclarations);
149 derivedVariableComputer.discardDerivedVariables(problem); 111 derivedVariableComputer.discardDerivedVariables(problem);
150 } 112 }
151 113
@@ -166,24 +128,15 @@ public class ProblemDerivedStateComputer implements IDerivedStateComputer {
166 } 128 }
167 129
168 protected static class Adapter extends AdapterImpl { 130 protected static class Adapter extends AdapterImpl {
169 private Map<ClassDeclaration, Node> newNodes = new HashMap<>(); 131 private final Map<ClassDeclaration, Node> newNodes = new HashMap<>();
170
171 private Map<ConstantAssertionArgument, Node> constantNodes = new HashMap<>();
172 132
173 public Node createNewNodeIfAbsent(ClassDeclaration classDeclaration, 133 public Node createNewNodeIfAbsent(ClassDeclaration classDeclaration,
174 Function<ClassDeclaration, Node> createNode) { 134 Function<ClassDeclaration, Node> createNode) {
175 return newNodes.computeIfAbsent(classDeclaration, createNode); 135 return newNodes.computeIfAbsent(classDeclaration, createNode);
176 } 136 }
177 137
178 public Node createConstantNodeIfAbsent(ConstantAssertionArgument constantAssertionArgument, 138 public void retainAll(Collection<ClassDeclaration> classDeclarations) {
179 Function<ConstantAssertionArgument, Node> createNode) {
180 return constantNodes.computeIfAbsent(constantAssertionArgument, createNode);
181 }
182
183 public void retainAll(Collection<ClassDeclaration> classDeclarations,
184 Collection<ConstantAssertionArgument> constantAssertionArguments) {
185 newNodes.keySet().retainAll(classDeclarations); 139 newNodes.keySet().retainAll(classDeclarations);
186 constantNodes.keySet().retainAll(constantAssertionArguments);
187 } 140 }
188 141
189 @Override 142 @Override
diff --git a/subprojects/language/src/main/java/tools/refinery/language/scoping/ProblemScopeProvider.java b/subprojects/language/src/main/java/tools/refinery/language/scoping/ProblemScopeProvider.java
index c2045aea..3ab07496 100644
--- a/subprojects/language/src/main/java/tools/refinery/language/scoping/ProblemScopeProvider.java
+++ b/subprojects/language/src/main/java/tools/refinery/language/scoping/ProblemScopeProvider.java
@@ -29,8 +29,7 @@ public class ProblemScopeProvider extends AbstractProblemScopeProvider {
29 @Override 29 @Override
30 public IScope getScope(EObject context, EReference reference) { 30 public IScope getScope(EObject context, EReference reference) {
31 var scope = super.getScope(context, reference); 31 var scope = super.getScope(context, reference);
32 if (reference == ProblemPackage.Literals.NODE_ASSERTION_ARGUMENT__NODE 32 if (reference == ProblemPackage.Literals.NODE_ASSERTION_ARGUMENT__NODE) {
33 || reference == ProblemPackage.Literals.NODE_VALUE_ASSERTION__NODE) {
34 return getNodesScope(context, scope); 33 return getNodesScope(context, scope);
35 } 34 }
36 if (reference == ProblemPackage.Literals.VARIABLE_OR_NODE_EXPR__VARIABLE_OR_NODE 35 if (reference == ProblemPackage.Literals.VARIABLE_OR_NODE_EXPR__VARIABLE_OR_NODE
diff --git a/subprojects/language/src/main/java/tools/refinery/language/serializer/PreferShortAssertionsProblemSemanticSequencer.java b/subprojects/language/src/main/java/tools/refinery/language/serializer/PreferShortAssertionsProblemSemanticSequencer.java
new file mode 100644
index 00000000..c51a5e28
--- /dev/null
+++ b/subprojects/language/src/main/java/tools/refinery/language/serializer/PreferShortAssertionsProblemSemanticSequencer.java
@@ -0,0 +1,52 @@
1package tools.refinery.language.serializer;
2
3import com.google.inject.Inject;
4import org.eclipse.xtext.serializer.ISerializationContext;
5import org.eclipse.xtext.serializer.sequencer.ITransientValueService.ListTransient;
6import org.eclipse.xtext.serializer.sequencer.ITransientValueService.ValueTransient;
7import tools.refinery.language.model.problem.Assertion;
8import tools.refinery.language.model.problem.LogicAssertionValue;
9import tools.refinery.language.model.problem.LogicValue;
10import tools.refinery.language.model.problem.ProblemPackage;
11import tools.refinery.language.services.ProblemGrammarAccess;
12
13public class PreferShortAssertionsProblemSemanticSequencer extends ProblemSemanticSequencer {
14 @Inject
15 private ProblemGrammarAccess grammarAccess;
16
17 @Override
18 protected void sequence_Assertion(ISerializationContext context, Assertion semanticObject) {
19 if (semanticObject.isDefault() ||
20 !(semanticObject.getValue() instanceof LogicAssertionValue logicAssertionValue) ||
21 logicAssertionValue.getLogicValue() == LogicValue.ERROR) {
22 super.sequence_Assertion(context, semanticObject);
23 return;
24 }
25 if (errorAcceptor != null) {
26 if (transientValues.isValueTransient(semanticObject, ProblemPackage.Literals.ASSERTION__RELATION) == ValueTransient.YES) {
27 errorAcceptor.accept(diagnosticProvider.createFeatureValueMissing(semanticObject,
28 ProblemPackage.Literals.ASSERTION__RELATION));
29 }
30 if (transientValues.isListTransient(semanticObject, ProblemPackage.Literals.ASSERTION__ARGUMENTS) == ListTransient.YES) {
31 errorAcceptor.accept(diagnosticProvider.createFeatureValueMissing(semanticObject,
32 ProblemPackage.Literals.ASSERTION__ARGUMENTS));
33 }
34 }
35 var feeder = createSequencerFeeder(context, semanticObject);
36 var access = grammarAccess.getAssertionAccess();
37 feeder.accept(access.getValueShortLogicAssertionValueParserRuleCall_1_1_0_0(), logicAssertionValue);
38 feeder.accept(access.getRelationRelationQualifiedNameParserRuleCall_1_1_1_0_1(), semanticObject.getRelation());
39 var iterator = semanticObject.getArguments().iterator();
40 if (iterator.hasNext()) {
41 var firstArgument = iterator.next();
42 feeder.accept(access.getArgumentsAssertionArgumentParserRuleCall_1_1_3_0_0(), firstArgument, 0);
43 int index = 1;
44 while (iterator.hasNext()) {
45 var argument = iterator.next();
46 feeder.accept(access.getArgumentsAssertionArgumentParserRuleCall_1_1_3_1_1_0(), argument, index);
47 index++;
48 }
49 }
50 feeder.finish();
51 }
52}
diff --git a/subprojects/language/src/main/java/tools/refinery/language/utils/BuiltinSymbols.java b/subprojects/language/src/main/java/tools/refinery/language/utils/BuiltinSymbols.java
index 7e43cecf..d3777cd3 100644
--- a/subprojects/language/src/main/java/tools/refinery/language/utils/BuiltinSymbols.java
+++ b/subprojects/language/src/main/java/tools/refinery/language/utils/BuiltinSymbols.java
@@ -1,14 +1,8 @@
1package tools.refinery.language.utils; 1package tools.refinery.language.utils;
2 2
3import tools.refinery.language.model.problem.ClassDeclaration; 3import tools.refinery.language.model.problem.*;
4import tools.refinery.language.model.problem.EnumDeclaration;
5import tools.refinery.language.model.problem.Node;
6import tools.refinery.language.model.problem.PredicateDefinition;
7import tools.refinery.language.model.problem.Problem;
8import tools.refinery.language.model.problem.ReferenceDeclaration;
9 4
10public record BuiltinSymbols(Problem problem, ClassDeclaration node, ReferenceDeclaration equals, 5public record BuiltinSymbols(Problem problem, ClassDeclaration node, ReferenceDeclaration equals,
11 PredicateDefinition exists, ClassDeclaration domain, ClassDeclaration data, EnumDeclaration bool, Node boolTrue, 6 PredicateDefinition exists, PredicateDefinition contained, PredicateDefinition contains,
12 Node boolFalse, ClassDeclaration intClass, ClassDeclaration real, ClassDeclaration string, 7 PredicateDefinition root) {
13 PredicateDefinition contained, PredicateDefinition contains, PredicateDefinition root) {
14} 8}
diff --git a/subprojects/language/src/main/java/tools/refinery/language/utils/NodeInfo.java b/subprojects/language/src/main/java/tools/refinery/language/utils/NodeInfo.java
index 38db0e29..c8f47653 100644
--- a/subprojects/language/src/main/java/tools/refinery/language/utils/NodeInfo.java
+++ b/subprojects/language/src/main/java/tools/refinery/language/utils/NodeInfo.java
@@ -1,12 +1,4 @@
1package tools.refinery.language.utils; 1package tools.refinery.language.utils;
2 2
3import java.util.ArrayList; 3public record NodeInfo(String name, boolean individual) {
4import java.util.Collection;
5
6import tools.refinery.language.model.problem.NodeValueAssertion;
7
8public record NodeInfo(String name, boolean individual, Collection<NodeValueAssertion> valueAssertions) {
9 public NodeInfo(String name, boolean individual) {
10 this(name, individual, new ArrayList<>());
11 }
12} 4}
diff --git a/subprojects/language/src/main/java/tools/refinery/language/utils/ProblemDesugarer.java b/subprojects/language/src/main/java/tools/refinery/language/utils/ProblemDesugarer.java
index 23fd8982..b8200919 100644
--- a/subprojects/language/src/main/java/tools/refinery/language/utils/ProblemDesugarer.java
+++ b/subprojects/language/src/main/java/tools/refinery/language/utils/ProblemDesugarer.java
@@ -40,19 +40,10 @@ public class ProblemDesugarer {
40 var node = doGetDeclaration(builtin, ClassDeclaration.class, "node"); 40 var node = doGetDeclaration(builtin, ClassDeclaration.class, "node");
41 var equals = doGetEqualsReference(node); 41 var equals = doGetEqualsReference(node);
42 var exists = doGetDeclaration(builtin, PredicateDefinition.class, "exists"); 42 var exists = doGetDeclaration(builtin, PredicateDefinition.class, "exists");
43 var domain = doGetDeclaration(builtin, ClassDeclaration.class, "domain");
44 var data = doGetDeclaration(builtin, ClassDeclaration.class, "data");
45 var bool = doGetDeclaration(builtin, EnumDeclaration.class, "bool");
46 var boolTrue = doGetLiteral(bool, "true");
47 var boolFalse = doGetLiteral(bool, "false");
48 var intClass = doGetDeclaration(builtin, ClassDeclaration.class, "int");
49 var real = doGetDeclaration(builtin, ClassDeclaration.class, "real");
50 var string = doGetDeclaration(builtin, ClassDeclaration.class, "string");
51 var contained = doGetDeclaration(builtin, PredicateDefinition.class, "contained"); 43 var contained = doGetDeclaration(builtin, PredicateDefinition.class, "contained");
52 var contains = doGetDeclaration(builtin, PredicateDefinition.class, "contains"); 44 var contains = doGetDeclaration(builtin, PredicateDefinition.class, "contains");
53 var root = doGetDeclaration(builtin, PredicateDefinition.class, "root"); 45 var root = doGetDeclaration(builtin, PredicateDefinition.class, "root");
54 return new BuiltinSymbols(builtin, node, equals, exists, domain, data, bool, boolTrue, boolFalse, intClass, 46 return new BuiltinSymbols(builtin, node, equals, exists, contained, contains, root);
55 real, string, contained, contains, root);
56 } 47 }
57 48
58 private <T extends Statement & NamedElement> T doGetDeclaration(Problem builtin, Class<T> type, String name) { 49 private <T extends Statement & NamedElement> T doGetDeclaration(Problem builtin, Class<T> type, String name) {
@@ -62,16 +53,12 @@ public class ProblemDesugarer {
62 } 53 }
63 54
64 private ReferenceDeclaration doGetEqualsReference(ClassDeclaration nodeClassDeclaration) { 55 private ReferenceDeclaration doGetEqualsReference(ClassDeclaration nodeClassDeclaration) {
65 return nodeClassDeclaration.getReferenceDeclarations().stream() 56 return (ReferenceDeclaration) nodeClassDeclaration.getFeatureDeclarations().stream()
66 .filter(reference -> "equals".equals(reference.getName())).findFirst() 57 .filter(reference -> reference instanceof ReferenceDeclaration &&
58 "equals".equals(reference.getName())).findFirst()
67 .orElseThrow(() -> new IllegalArgumentException("Reference " + "equals" + " not found")); 59 .orElseThrow(() -> new IllegalArgumentException("Reference " + "equals" + " not found"));
68 } 60 }
69 61
70 private Node doGetLiteral(EnumDeclaration enumDeclaration, String name) {
71 return enumDeclaration.getLiterals().stream().filter(literal -> name.equals(literal.getName())).findFirst()
72 .orElseThrow(() -> new IllegalArgumentException("Enum literal " + name + " not found"));
73 }
74
75 public Collection<ClassDeclaration> getSuperclassesAndSelf(ClassDeclaration classDeclaration) { 62 public Collection<ClassDeclaration> getSuperclassesAndSelf(ClassDeclaration classDeclaration) {
76 return cache.get(Tuples.create(classDeclaration, "superclassesAndSelf"), classDeclaration.eResource(), 63 return cache.get(Tuples.create(classDeclaration, "superclassesAndSelf"), classDeclaration.eResource(),
77 () -> doGetSuperclassesAndSelf(classDeclaration)); 64 () -> doGetSuperclassesAndSelf(classDeclaration));
@@ -94,9 +81,6 @@ public class ProblemDesugarer {
94 } 81 }
95 } 82 }
96 } 83 }
97 if (builtinSymbols.isPresent() && !found.contains(builtinSymbols.get().data())) {
98 found.add(builtinSymbols.get().domain());
99 }
100 return found; 84 return found;
101 } 85 }
102 86
@@ -108,31 +92,17 @@ public class ProblemDesugarer {
108 private Collection<ReferenceDeclaration> doGetAllReferenceDeclarations(ClassDeclaration classDeclaration) { 92 private Collection<ReferenceDeclaration> doGetAllReferenceDeclarations(ClassDeclaration classDeclaration) {
109 Set<ReferenceDeclaration> referenceDeclarations = new HashSet<>(); 93 Set<ReferenceDeclaration> referenceDeclarations = new HashSet<>();
110 for (ClassDeclaration superclass : getSuperclassesAndSelf(classDeclaration)) { 94 for (ClassDeclaration superclass : getSuperclassesAndSelf(classDeclaration)) {
111 referenceDeclarations.addAll(superclass.getReferenceDeclarations()); 95 for (FeatureDeclaration featureDeclaration : superclass.getFeatureDeclarations()) {
96 if (featureDeclaration instanceof ReferenceDeclaration referenceDeclaration) {
97 referenceDeclarations.add(referenceDeclaration);
98 }
99 }
112 } 100 }
113 return referenceDeclarations; 101 return referenceDeclarations;
114 } 102 }
115 103
116 public boolean isContainmentReference(ReferenceDeclaration referenceDeclaration) { 104 public boolean isContainmentReference(ReferenceDeclaration referenceDeclaration) {
117 switch (referenceDeclaration.getKind()) { 105 return referenceDeclaration.getKind() == ReferenceKind.CONTAINMENT;
118 case REFERENCE, CONTAINER:
119 return false;
120 case CONTAINMENT:
121 return true;
122 case DEFAULT:
123 return isDataClass(referenceDeclaration.getReferenceType());
124 default:
125 throw new IllegalArgumentException("Unknown reference kind " + referenceDeclaration.getKind());
126 }
127 }
128
129 public boolean isDataClass(Relation relation) {
130 if (relation instanceof ClassDeclaration classDeclaration) {
131 var supertypes = getSuperclassesAndSelf(classDeclaration);
132 var builtinSymbols = getBuiltinSymbols(relation);
133 return builtinSymbols.isPresent() && supertypes.contains(builtinSymbols.get().data());
134 }
135 return false;
136 } 106 }
137 107
138 public CollectedSymbols collectSymbols(Problem problem) { 108 public CollectedSymbols collectSymbols(Problem problem) {
diff --git a/subprojects/language/src/main/java/tools/refinery/language/utils/SymbolCollector.java b/subprojects/language/src/main/java/tools/refinery/language/utils/SymbolCollector.java
index 210e96ab..5412f620 100644
--- a/subprojects/language/src/main/java/tools/refinery/language/utils/SymbolCollector.java
+++ b/subprojects/language/src/main/java/tools/refinery/language/utils/SymbolCollector.java
@@ -2,7 +2,6 @@ package tools.refinery.language.utils;
2 2
3import com.google.inject.Inject; 3import com.google.inject.Inject;
4import org.eclipse.emf.ecore.EObject; 4import org.eclipse.emf.ecore.EObject;
5import org.eclipse.emf.ecore.util.EcoreUtil;
6import org.eclipse.xtext.naming.IQualifiedNameConverter; 5import org.eclipse.xtext.naming.IQualifiedNameConverter;
7import org.eclipse.xtext.naming.IQualifiedNameProvider; 6import org.eclipse.xtext.naming.IQualifiedNameProvider;
8import tools.refinery.language.model.problem.*; 7import tools.refinery.language.model.problem.*;
@@ -64,43 +63,65 @@ class SymbolCollector {
64 } 63 }
65 64
66 private void collectClass(ClassDeclaration classDeclaration) { 65 private void collectClass(ClassDeclaration classDeclaration) {
67 // node and domain classes are not contained by default, but every other type is 66 var contained = classDeclaration != builtinSymbols.node();
68 // contained, including data types.
69 var contained =
70 classDeclaration != builtinSymbols.node() && classDeclaration != builtinSymbols.domain();
71 var containmentRole = contained ? ContainmentRole.CONTAINED : ContainmentRole.NONE; 67 var containmentRole = contained ? ContainmentRole.CONTAINED : ContainmentRole.NONE;
72 var instanceParameter = ProblemFactory.eINSTANCE.createParameter(); 68 var instanceParameter = ProblemFactory.eINSTANCE.createParameter();
73 instanceParameter.setName("instance"); 69 instanceParameter.setName("instance");
74 var classInfo = new RelationInfo(getQualifiedNameString(classDeclaration), containmentRole, 70 var classInfo = new RelationInfo(getQualifiedNameString(classDeclaration), containmentRole,
75 List.of(instanceParameter), null, null, List.of()); 71 List.of(instanceParameter), null, null, List.of());
76 relations.put(classDeclaration, classInfo); 72 relations.put(classDeclaration, classInfo);
77 collectReferences(classDeclaration); 73 collectFeatures(classDeclaration);
78 } 74 }
79 75
80 private void collectReferences(ClassDeclaration classDeclaration) { 76 private void collectFeatures(ClassDeclaration classDeclaration) {
81 for (var referenceDeclaration : classDeclaration.getReferenceDeclarations()) { 77 for (var featureDeclaration : classDeclaration.getFeatureDeclarations()) {
82 var referenceRole = desugarer.isContainmentReference(referenceDeclaration) ? 78 if (featureDeclaration instanceof ReferenceDeclaration referenceDeclaration) {
83 ContainmentRole.CONTAINMENT : 79 collectReference(classDeclaration, referenceDeclaration);
84 ContainmentRole.NONE; 80 } else if (featureDeclaration instanceof AttributeDeclaration attributeDeclaration) {
85 var sourceParameter = ProblemFactory.eINSTANCE.createParameter(); 81 collectAttribute(classDeclaration, attributeDeclaration);
86 sourceParameter.setName("source"); 82 } else if (featureDeclaration instanceof FlagDeclaration flagDeclaration) {
87 sourceParameter.setParameterType(classDeclaration); 83 collectFlag(classDeclaration, flagDeclaration);
88 var targetParameter = ProblemFactory.eINSTANCE.createParameter(); 84 } else {
89 targetParameter.setName("target"); 85 throw new IllegalArgumentException("Unknown FeatureDeclaration: " + featureDeclaration);
90 var multiplicity = referenceDeclaration.getMultiplicity();
91 if (multiplicity == null) {
92 var exactMultiplicity = ProblemFactory.eINSTANCE.createExactMultiplicity();
93 exactMultiplicity.setExactValue(1);
94 multiplicity = exactMultiplicity;
95 } 86 }
96 targetParameter.setParameterType(referenceDeclaration.getReferenceType());
97 var referenceInfo = new RelationInfo(getQualifiedNameString(referenceDeclaration), referenceRole,
98 List.of(sourceParameter, targetParameter), multiplicity, referenceDeclaration.getOpposite(),
99 List.of());
100 this.relations.put(referenceDeclaration, referenceInfo);
101 } 87 }
102 } 88 }
103 89
90 private void collectReference(ClassDeclaration classDeclaration, ReferenceDeclaration referenceDeclaration) {
91 var referenceRole = desugarer.isContainmentReference(referenceDeclaration) ?
92 ContainmentRole.CONTAINMENT :
93 ContainmentRole.NONE;
94 var sourceParameter = ProblemFactory.eINSTANCE.createParameter();
95 sourceParameter.setName("source");
96 sourceParameter.setParameterType(classDeclaration);
97 var targetParameter = ProblemFactory.eINSTANCE.createParameter();
98 targetParameter.setName("target");
99 var multiplicity = referenceDeclaration.getMultiplicity();
100 if (multiplicity == null) {
101 var exactMultiplicity = ProblemFactory.eINSTANCE.createExactMultiplicity();
102 exactMultiplicity.setExactValue(1);
103 multiplicity = exactMultiplicity;
104 }
105 targetParameter.setParameterType(referenceDeclaration.getReferenceType());
106 var referenceInfo = new RelationInfo(getQualifiedNameString(referenceDeclaration), referenceRole,
107 List.of(sourceParameter, targetParameter), multiplicity, referenceDeclaration.getOpposite(),
108 List.of());
109 this.relations.put(referenceDeclaration, referenceInfo);
110 }
111
112 private void collectAttribute(ClassDeclaration classDeclaration, AttributeDeclaration attributeDeclaration) {
113 // TODO Implement attribute handling.
114 }
115
116 private void collectFlag(ClassDeclaration classDeclaration, FlagDeclaration flagDeclaration) {
117 var parameter = ProblemFactory.eINSTANCE.createParameter();
118 parameter.setName("object");
119 parameter.setParameterType(classDeclaration);
120 var referenceInfo = new RelationInfo(getQualifiedNameString(flagDeclaration), ContainmentRole.NONE,
121 List.of(parameter), null, null, List.of());
122 this.relations.put(flagDeclaration, referenceInfo);
123 }
124
104 private void collectEnum(EnumDeclaration enumDeclaration) { 125 private void collectEnum(EnumDeclaration enumDeclaration) {
105 var instanceParameter = ProblemFactory.eINSTANCE.createParameter(); 126 var instanceParameter = ProblemFactory.eINSTANCE.createParameter();
106 instanceParameter.setName("instance"); 127 instanceParameter.setName("instance");
@@ -117,8 +138,6 @@ class SymbolCollector {
117 collectNewNode(classDeclaration); 138 collectNewNode(classDeclaration);
118 } else if (statement instanceof EnumDeclaration enumDeclaration) { 139 } else if (statement instanceof EnumDeclaration enumDeclaration) {
119 collectEnumLiterals(enumDeclaration); 140 collectEnumLiterals(enumDeclaration);
120 } else if (statement instanceof Assertion assertion) {
121 collectConstantNodes(assertion);
122 } 141 }
123 } 142 }
124 for (var node : problem.getNodes()) { 143 for (var node : problem.getNodes()) {
@@ -145,17 +164,6 @@ class SymbolCollector {
145 } 164 }
146 } 165 }
147 166
148 private void collectConstantNodes(Assertion assertion) {
149 for (var argument : assertion.getArguments()) {
150 if (argument instanceof ConstantAssertionArgument constantAssertionArgument) {
151 var constantNode = constantAssertionArgument.getNode();
152 if (constantNode != null) {
153 addNode(constantNode, false);
154 }
155 }
156 }
157 }
158
159 private void addNode(Node node, boolean individual) { 167 private void addNode(Node node, boolean individual) {
160 var info = new NodeInfo(getQualifiedNameString(node), individual); 168 var info = new NodeInfo(getQualifiedNameString(node), individual);
161 this.nodes.put(node, info); 169 this.nodes.put(node, info);
@@ -173,8 +181,6 @@ class SymbolCollector {
173 for (var statement : problem.getStatements()) { 181 for (var statement : problem.getStatements()) {
174 if (statement instanceof Assertion assertion) { 182 if (statement instanceof Assertion assertion) {
175 collectAssertion(assertion); 183 collectAssertion(assertion);
176 } else if (statement instanceof NodeValueAssertion nodeValueAssertion) {
177 collectNodeValueAssertion(nodeValueAssertion);
178 } else if (statement instanceof PredicateDefinition predicateDefinition) { 184 } else if (statement instanceof PredicateDefinition predicateDefinition) {
179 collectPredicateAssertion(predicateDefinition); 185 collectPredicateAssertion(predicateDefinition);
180 } else if (statement instanceof ClassDeclaration classDeclaration) { 186 } else if (statement instanceof ClassDeclaration classDeclaration) {
@@ -196,48 +202,6 @@ class SymbolCollector {
196 return; 202 return;
197 } 203 }
198 relationInfo.assertions().add(assertion); 204 relationInfo.assertions().add(assertion);
199 for (var argument : assertion.getArguments()) {
200 if (argument instanceof ConstantAssertionArgument constantAssertionArgument) {
201 var constantNode = constantAssertionArgument.getNode();
202 if (constantNode != null) {
203 var valueAssertion = ProblemFactory.eINSTANCE.createNodeValueAssertion();
204 valueAssertion.setNode(constantNode);
205 valueAssertion.setValue(EcoreUtil.copy(constantAssertionArgument.getConstant()));
206 collectNodeValueAssertion(valueAssertion);
207 var logicValue = assertion.getValue();
208 if (logicValue != LogicValue.TRUE) {
209 addAssertion(builtinSymbols.exists(), logicValue, constantNode);
210 }
211 }
212 }
213 }
214 }
215
216 private void collectNodeValueAssertion(NodeValueAssertion nodeValueAssertion) {
217 var node = nodeValueAssertion.getNode();
218 if (node == null) {
219 return;
220 }
221 var nodeInfo = this.nodes.get(node);
222 if (nodeInfo == null) {
223 throw new IllegalStateException("Node value assertion refers to unknown node");
224 }
225 nodeInfo.valueAssertions().add(nodeValueAssertion);
226 var constant = nodeValueAssertion.getValue();
227 if (constant == null) {
228 return;
229 }
230 Relation dataType;
231 if (constant instanceof IntConstant) {
232 dataType = builtinSymbols.intClass();
233 } else if (constant instanceof RealConstant) {
234 dataType = builtinSymbols.real();
235 } else if (constant instanceof StringConstant) {
236 dataType = builtinSymbols.string();
237 } else {
238 throw new IllegalArgumentException("Unknown constant type");
239 }
240 addAssertion(dataType, LogicValue.TRUE, node);
241 } 205 }
242 206
243 private void collectPredicateAssertion(PredicateDefinition predicateDefinition) { 207 private void collectPredicateAssertion(PredicateDefinition predicateDefinition) {
@@ -278,7 +242,9 @@ class SymbolCollector {
278 } 242 }
279 assertion.getArguments().add(argument); 243 assertion.getArguments().add(argument);
280 } 244 }
281 assertion.setValue(logicValue); 245 var value = ProblemFactory.eINSTANCE.createLogicAssertionValue();
246 value.setLogicValue(logicValue);
247 assertion.setValue(value);
282 collectAssertion(assertion); 248 collectAssertion(assertion);
283 } 249 }
284} 250}