Skip to content

Commit 47650ac

Browse files
author
Bogdan Damian
committed
Fixed conflicts
2 parents bc2b5ce + 0e9ecc9 commit 47650ac

File tree

44 files changed

+2018
-299
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+2018
-299
lines changed

README.md

Lines changed: 64 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,45 +2,92 @@
22

33
An interpreter for a subset of the Rune DSl.
44

5-
For most practical information, refer to the [original readme file](README_project.md)
5+
For more information, refer to the [original Rosetta readme file](README_project.md)
66

7-
## Authors
8-
- Jacek Kulik
9-
- Antonio Lupu
10-
- Maria Cristescu
11-
- Bogdan Damian
12-
- Diana Şutac
7+
## How to build
8+
9+
Refer to the main building instructions in the original readme.
10+
11+
Additionally, open the `interpreternew` module.
12+
13+
If the project still doesn't build try the following steps:
14+
- Mark [xsemantics gen](rosetta-lang/target/xsemantics-gen/main/java/) as a source folder
15+
- Close the projects: `com.regnosys.rosetta.ide`, `com.regnosys.rosetta.profiling`, `com.regnosys.rosetta.tools`, `rosetta-maven-plugin`
16+
- Update the Maven project
1317

1418
## Project Structure
1519

16-
FIGURE HERE
20+
![Class structure Diagram](img/Project_Structure.png)
1721

18-
Rune operations are defined in [xcore files](rosetta-lang/model/RosettaInterpreter.xcore)
22+
Rune operations are defined in [xcore files in the model folder](rosetta-lang/model/). The constructs defined there get auto generated into the generated source folders. They correspond to the objects that the parser can return, and thus are essential for ensuring compatibility with it. It does have some limitations, such as the lack of the notion of many data types, like streams, so some general operations are defined outside those files if they concern more complicated Java constructs. All objects generated via xcore have som associated EObject methods required for them, that are used to get back the original semantics of how they were generated. Thus to implement those methods, the generated objects we make use of also implement `MinimalEObject` to get a base implementation of those methods, if nothing custom is required.
1923

20-
All interpretable operations implement an interp method which takes in an expression and an environment.
24+
All interpretable operations implement an interp method which takes in a visitor and an environment.
2125

2226
There is a visitor which accepts the expressions and passes them along to the correct concrete interpreter to perform their operations.
2327

28+
Each concrete interpreter in the [interpreters module](rosetta-interpreter/src/main/java/com/regnosys/rosetta/interpreternew/visitors/) concerns the interpretation of a certain thematically linked part of Rune operations. For example the List Operators interpreter interprets list `exists`, `absent`, `first`, `only`, `last`, `distinct`, `reverse`, `sum` as they all apply an operation to a list of values and they are somewhat similar in their implementation pattern.
29+
30+
The program flow starts in the [main interpreter file](rosetta-interpreter/src/main/java/com/regnosys/rosetta/interpreternew/RosettaInterpreterNew.java). It contains fields for the visitor and the environment and keeps track of them. When interrpetation is started, this class is used by calling its `interp` method. This starts the interpretation flow and keeps track of the environment
31+
32+
## Error handling and preservation of semantics
33+
34+
All the operations are implementations of `EObject` so they retain information about the original text they were generated from and all other metadata about the parsing process. Thus it is important to preserve that information through the interpretation process.
35+
36+
When an error is encountered, it gets associated with an EObject, such that more diagnostic information can be retaing from it. Currently, the information that is given to the user is the position in the source code of the text that generated the error constructs, though in the future this functionality could be extended.
37+
38+
Errors are stored as `RosettaInterpreterErrorValue`. When an interpretation function encounteres an error value, it should try to propagate that error further up in the computation. This can be achieved by scanning through all the inputs received, and if any errors are found, returning them. The `RosettaInterpreterErrorValue.errorsExist()` and `RosettaInterpreterErrorValue.merge()` methods can be used for those purposes.
39+
40+
## Testing
41+
42+
The benchmark for good testing coverage for this project is 100% branch coverage, and should be achieved wherever possible.
43+
44+
Tests are created in the [interpreter test folder](rosetta-interpreter/src/test/java/com/regnosys/rosetta/interpreternew/)
45+
46+
Useful tools for the testing process:
47+
- Expressionparser: allows for parsing a string representation of a Rune expression into a `RosettaExpression`
48+
- ExpressionFactory: allows for directly instantiating an expression object
49+
- ExpressionValidationHelper: allows for validating that a parsed expression is actually a valid Rune expression
50+
51+
## Checkstyle
52+
53+
The [checkstyle file](checkstyle-SP.xml) is enforced for the project. It is not a very strict checkstyle, but ensures some style guidelines and helps with readability of the codebase.
54+
55+
## CI/CD Pipeline
56+
57+
The [pipeline](.gitlab-ci.yml) runs on the repository after each pushed commit.
58+
59+
It consists of three stages:
60+
1. Build - ensure the codebase compiles and builds successfully
61+
2. Test - run all the tests and ensure they all pass
62+
3. Checkstyle - check all Interpreter source files and ensure they adhere to the checkstyle
63+
2464
## How to extend
2565

2666
### New Expression
2767
The simplest extension is by adding new Rune constructs to interpret. The process for this is:
2868
1. Define the interp method for this expression in [RosettaExpression.xcore](rosetta-lang/model/RosettaExpression.xcore)
29-
2. Create a new class inside [interpreternew.visitors](rosetta-lang/src/main/java/com/regnosys/rosetta/interpreternew/visitors/) OR use one of the already existing ones if it fits thematically
30-
3. Implement a new interp method in [RosettaInterpreterVisitor.java](rosetta-lang/src/main/java/com/regnosys/rosetta/interpreternew/RosettaInterpreterVisitor.java) to accept the new expression
69+
2. Create a new class inside [interpreternew.visitors](rosetta-interpreter/src/main/java/com/regnosys/rosetta/interpreternew/visitors/) OR use one of the already existing ones if it fits thematically
70+
3. Implement a new interp method in [RosettaInterpreterVisitor.java](rosetta-interpreter/src/main/java/com/regnosys/rosetta/interpreternew/RosettaInterpreterVisitor.java) to accept the new expression
3171
4. Implement the interpretation of the expression
32-
5. Test the expression in [the testing module](rosetta-testing/src/test/java/com/regnosys/rosetta/interpreternew/visitors/)
72+
5. Test the expression in [the testing module](rosetta-interpreter/src/test/java/com/regnosys/rosetta/interpreternew/visitors/)
3373

3474
### New Value Domain Type
3575
Right now this process doesn't have any additional steps, but this may change in the future.
3676

37-
1. Create a new class in [the value domain folder](rosetta-lang/src/main/java/com/regnosys/rosetta/interpreternew/values/)
38-
2. Optionally also test the class if it requires it
77+
1. Create a new class in [the value domain folder](rosetta-interpreter/src/main/java/com/regnosys/rosetta/interpreternew/values/)
78+
2. Test the class if it requires it
3979

4080
### New Expression Function
4181

42-
Currently there is only the interpretation function defined for the expressions, but the visitor pattern allows for easily adding a new one.
82+
Currently there is only the interpretation function defined for the expressions, but the visitor pattern allows for adding a new one.
4383

4484
1. Create a new main visitor (like RosettaTypeCheckVisitor)
4585
2. Define accept methods for this visitor for all the expressions
46-
3. Implement concrete acceptors in the new visitor or in new files stemming from it
86+
3. Implement concrete acceptors in the new visitor or in new files stemming from it
87+
88+
## Authors
89+
- Jacek Kulik
90+
- Antonio Lupu
91+
- Maria Cristescu
92+
- Bogdan Damian
93+
- Diana Şutac

img/Project_Structure.png

326 KB
Loading

rosetta-interpreter/src/main/java/com/regnosys/rosetta/interpreternew/RosettaInterpreterVisitor.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,16 @@
2626
import com.regnosys.rosetta.rosetta.interpreter.RosettaInterpreterValue;
2727
import com.regnosys.rosetta.rosetta.expression.RosettaNumberLiteral;
2828
import com.regnosys.rosetta.rosetta.expression.RosettaOnlyElement;
29+
import com.regnosys.rosetta.rosetta.expression.RosettaOnlyExistsExpression;
2930
import com.regnosys.rosetta.rosetta.expression.RosettaPatternLiteral;
3031
import com.regnosys.rosetta.rosetta.expression.RosettaStringLiteral;
3132
import com.regnosys.rosetta.rosetta.expression.RosettaSymbolReference;
3233
import com.regnosys.rosetta.rosetta.expression.SumOperation;
33-
34+
import com.regnosys.rosetta.interpreternew.values.RosettaInterpreterEmptyError;
3435
import org.eclipse.emf.ecore.impl.MinimalEObjectImpl;
35-
3636
import com.regnosys.rosetta.interpreternew.values.RosettaInterpreterEnvironment;
3737
import com.regnosys.rosetta.interpreternew.visitors.RosettaInterpreterLogicalOperationInterpreter;
38-
import com.regnosys.rosetta.interpreternew.values.RosettaInterpreterError;
38+
import com.regnosys.rosetta.interpreternew.visitors.RosettaInterpreterOnlyExistsInterpreter;
3939
import com.regnosys.rosetta.interpreternew.values.RosettaInterpreterErrorValue;
4040
import com.regnosys.rosetta.interpreternew.visitors.RosettaInterpreterComparisonOperationInterpreter;
4141
import com.regnosys.rosetta.interpreternew.visitors.RosettaInterpreterEnumerationInterpreter;
@@ -87,7 +87,7 @@ public RosettaInterpreterValue interp(RosettaIntLiteral exp,
8787
public RosettaInterpreterValue interp(RosettaPatternLiteral exp,
8888
RosettaInterpreterBaseEnvironment env) {
8989
return new RosettaInterpreterErrorValue(
90-
new RosettaInterpreterError("Pattern literals are not supported"));
90+
new RosettaInterpreterEmptyError("Pattern literals are not supported"));
9191
}
9292

9393
@Override
@@ -241,5 +241,10 @@ public RosettaInterpreterValue interp(RosettaFeatureCall exp, RosettaInterpreter
241241
(RosettaInterpreterEnvironment) env);
242242

243243
}
244+
245+
@Override
246+
public RosettaInterpreterValue interp(RosettaOnlyExistsExpression exp, RosettaInterpreterBaseEnvironment env) {
247+
return new RosettaInterpreterOnlyExistsInterpreter().interp(exp, env);
248+
}
244249
}
245250

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package com.regnosys.rosetta.interpreternew.values;
2+
3+
import java.util.Objects;
4+
5+
import org.eclipse.emf.ecore.impl.MinimalEObjectImpl;
6+
7+
import com.regnosys.rosetta.rosetta.interpreter.RosettaInterpreterBaseError;
8+
9+
public class RosettaInterpreterEmptyError extends MinimalEObjectImpl implements RosettaInterpreterBaseError {
10+
11+
private String errorMessage;
12+
13+
public RosettaInterpreterEmptyError(String message) {
14+
this.errorMessage = message;
15+
}
16+
17+
public RosettaInterpreterEmptyError() {
18+
this.errorMessage = "";
19+
}
20+
21+
@Override
22+
public String getMessage() {
23+
return errorMessage;
24+
}
25+
26+
@Override
27+
public void setMessage(String value) {
28+
this.errorMessage = value;
29+
}
30+
31+
@Override
32+
public int hashCode() {
33+
return Objects.hash(errorMessage);
34+
}
35+
36+
@Override
37+
public boolean equals(Object obj) {
38+
if (this == obj) {
39+
return true;
40+
}
41+
if (obj == null) {
42+
return false;
43+
}
44+
if (getClass() != obj.getClass()) {
45+
return false;
46+
}
47+
RosettaInterpreterEmptyError other = (RosettaInterpreterEmptyError) obj;
48+
return Objects.equals(errorMessage, other.errorMessage);
49+
}
50+
51+
@Override
52+
public String toString() {
53+
return errorMessage;
54+
}
55+
}

rosetta-interpreter/src/main/java/com/regnosys/rosetta/interpreternew/values/RosettaInterpreterEnvironment.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public RosettaInterpreterValue findValue(String name) {
4141
}
4242
else {
4343
return new RosettaInterpreterErrorValue(
44-
new RosettaInterpreterError(
44+
new RosettaInterpreterEmptyError(
4545
name
4646
+ " does not exist in the environment"));
4747
}

rosetta-interpreter/src/main/java/com/regnosys/rosetta/interpreternew/values/RosettaInterpreterError.java

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,22 @@
22

33
import java.util.Objects;
44

5+
import org.eclipse.emf.ecore.EObject;
6+
import org.eclipse.xtext.nodemodel.INode;
7+
import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
58
import org.eclipse.emf.ecore.impl.MinimalEObjectImpl;
69

710
import com.regnosys.rosetta.rosetta.interpreter.RosettaInterpreterBaseError;
811

9-
public class RosettaInterpreterError extends MinimalEObjectImpl implements RosettaInterpreterBaseError {
10-
private String errorMessage;
11-
12+
public class RosettaInterpreterError extends MinimalEObjectImpl implements RosettaInterpreterBaseError {
13+
private String errorMessage;
14+
private EObject associatedObject;
15+
1216
public RosettaInterpreterError(String errorMessage) {
1317
super();
1418
this.errorMessage = errorMessage;
1519
}
1620

17-
public String getError() { return errorMessage; }
18-
19-
@Override
20-
public String toString() {
21-
return "RosettaInterpreterError [errorMessage=" + errorMessage + "]";
22-
}
23-
2421
@Override
2522
public int hashCode() {
2623
return Objects.hash(errorMessage);
@@ -40,6 +37,40 @@ public boolean equals(Object obj) {
4037
RosettaInterpreterError other = (RosettaInterpreterError) obj;
4138
return Objects.equals(errorMessage, other.errorMessage);
4239
}
40+
41+
public RosettaInterpreterError(String errorMessage, EObject obj) {
42+
this.associatedObject = obj;
43+
this.errorMessage = errorMessage;
44+
}
45+
46+
public String getError() { return errorMessage; }
47+
48+
public EObject getEobject() { return associatedObject; }
49+
50+
/**
51+
* Gives a parsed error message associated with this error.
52+
* Gets the INode associated in order to provide details of where the erorr ocurred.
53+
*
54+
* @return Error message with code information
55+
*/
56+
public String properErrorMessage() {
57+
if (associatedObject == null) {
58+
return errorMessage;
59+
}
60+
61+
INode node = NodeModelUtils.findActualNodeFor(associatedObject);
62+
int startLine = node.getStartLine();
63+
int offset = node.getOffset();
64+
String text = node.getText().trim();
65+
String message = "Error at line " + startLine + ", position " + offset + ": "
66+
+ "\"" + text + "\". " + errorMessage;
67+
return message;
68+
}
69+
70+
@Override
71+
public String toString() {
72+
return properErrorMessage();
73+
}
4374

4475
@Override
4576
public String getMessage() {

rosetta-interpreter/src/main/java/com/regnosys/rosetta/interpreternew/values/RosettaInterpreterErrorValue.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,8 @@ public boolean equals(Object obj) {
145145
return false;
146146
}
147147
RosettaInterpreterErrorValue other = (RosettaInterpreterErrorValue) obj;
148-
return Objects.equals(errors, other.errors);
148+
return ((List<RosettaInterpreterBaseError>)errors)
149+
.equals(((List<RosettaInterpreterBaseError>)other.errors));
149150
}
150151

151152
@Override

rosetta-interpreter/src/main/java/com/regnosys/rosetta/interpreternew/values/RosettaInterpreterIntegerValue.java

Lines changed: 0 additions & 60 deletions
This file was deleted.

0 commit comments

Comments
 (0)