"Monadish" refactoring of interpreter #721
Closed
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Towards #720
This PR does not introduce new functionality to the interpreter, it only refactors the interpreter to be able to change the semantics or add additional functionality to it.
At first, I was trying to do a monad-style interpreter, but TypeScript does not have do-notation, which can quickly produce unreadable code because of the bind functions. Although, there are some suggestions over the internet on how to emulate do-notation using generators, it looks ad-hoc, hacky, and unnatural. So, I decided to take the idea of monad and adapt it into an imperative flavor. The idea is to define the semantics of an interpreter as an abstract class parametric over two generic types: "V" (the type of expressions' results) and "S" (the type of statements' results).
At the moment, module level declarations do not have an associated generic type, but it will probably be added.
Specific semantics can be represented by implementing the abstract class. For example, to create an interpreter with the standard semantics, just write:
If we want to change the behavior, for example, by collecting special values when statements execute, just pass another semantics:
This is a first version of the "monadish" interpreter. As such, it probably will suffer changes as more semantics are added since they will probably force changes to the interface in the abstract class.
You can see the abstract class interface in the file
src/interpreterSemantics/types.ts
.I have documented my contribution in Tact Docs: https://github.com/tact-lang/tact-docs/pull/PR-NUMBERI have added tests to demonstrate the contribution is correctly implemented: this usually includes both positive and negative tests, showing the happy path(s) and featuring intentionally broken cases