Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"Monadish" refactoring of interpreter #721

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open

"Monadish" refactoring of interpreter #721

wants to merge 1 commit into from

Conversation

jeshecdom
Copy link
Contributor

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:

const interpreter = new Interpreter(new StandardSemantics(ctx));

If we want to change the behavior, for example, by collecting special values when statements execute, just pass another semantics:

const interpreter = new Interpreter(new YourCustomSemantics(ctx));

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 updated CHANGELOG.md
  • I have documented my contribution in Tact Docs: https://github.com/tact-lang/tact-docs/pull/PR-NUMBER
  • I 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
  • I have run all the tests locally and no test failure was reported
  • I have run the linter, formatter and spellchecker
  • I did not do unrelated and/or undiscussed refactorings

…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:

const interpreter = new Interpreter(new StandardSemantics(ctx));

If we want to change the behavior, for example, by collecting special values when statements execute, just pass another semantics:

const interpreter = new Interpreter(new YourCustomSemantics(ctx));

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.
@anton-trunov anton-trunov added this to the v1.6.0 milestone Sep 15, 2024
@jeshecdom
Copy link
Contributor Author

This PR is obsolete. Its code has been merged into PR #852.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants