|
2 | 2 |
|
3 | 3 | An interpreter for a subset of the Rune DSl.
|
4 | 4 |
|
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) |
6 | 6 |
|
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 |
13 | 17 |
|
14 | 18 | ## Project Structure
|
15 | 19 |
|
16 |
| -FIGURE HERE |
| 20 | + |
17 | 21 |
|
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. |
19 | 23 |
|
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. |
21 | 25 |
|
22 | 26 | There is a visitor which accepts the expressions and passes them along to the correct concrete interpreter to perform their operations.
|
23 | 27 |
|
| 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 | + |
24 | 64 | ## How to extend
|
25 | 65 |
|
26 | 66 | ### New Expression
|
27 | 67 | The simplest extension is by adding new Rune constructs to interpret. The process for this is:
|
28 | 68 | 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 |
31 | 71 | 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/) |
33 | 73 |
|
34 | 74 | ### New Value Domain Type
|
35 | 75 | Right now this process doesn't have any additional steps, but this may change in the future.
|
36 | 76 |
|
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 |
39 | 79 |
|
40 | 80 | ### New Expression Function
|
41 | 81 |
|
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. |
43 | 83 |
|
44 | 84 | 1. Create a new main visitor (like RosettaTypeCheckVisitor)
|
45 | 85 | 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 |
0 commit comments