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

Implement constant string receivers #401

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- CLI flag `--with-decompilation` to turn on decompilation of BoC files at the end of the compilation pipeline: PR [#417](https://github.com/tact-lang/tact/pull/417)
- Support more Tact expressions in the constant evaluator: condition expressions, struct instances, struct field access, `emptyMap()`: PR [#432](https://github.com/tact-lang/tact/pull/432)
- The `fromCell` and `fromSlice` methods for struct parsing: PR [#418](https://github.com/tact-lang/tact/pull/418)
- Constants can now be used in receivers: PR [#401](https://github.com/tact-lang/tact/pull/401)

### Changed

Expand Down
1 change: 1 addition & 0 deletions cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@
"src/test/e2e-emulated/__snapshots__/masterchain.spec.ts.snap",
"src/test/e2e-emulated/__snapshots__/sample-jetton.spec.ts.snap",
"src/test/e2e-emulated/__snapshots__/try-catch.spec.ts.snap",
"src/test/e2e-emulated/__snapshots__/const-string-receiver.spec.ts.snap",
"src/test/e2e-emulated/address.spec.ts",
"src/test/e2e-emulated/intrinsics.spec.ts",
"src/test/e2e-emulated/optionals.spec.ts",
Expand Down
8 changes: 8 additions & 0 deletions src/grammar/ast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,10 @@ export type ASTReceiveType =
kind: "internal-comment";
comment: ASTString;
}
| {
kind: "internal-const-comment";
comment: ASTLvalueRef[];
}
| {
kind: "bounce";
arg: ASTArgument;
Expand All @@ -379,6 +383,10 @@ export type ASTReceiveType =
| {
kind: "external-comment";
comment: ASTString;
}
| {
kind: "external-const-comment";
comment: ASTLvalueRef[];
};

export type ASTReceive = {
Expand Down
2 changes: 2 additions & 0 deletions src/grammar/grammar.ohm
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,11 @@ Tact {

Receiver = receive "(" Parameter? ")" "{" Statement* "}" --regular
| receive "(" stringLiteral ")" "{" Statement* "}" --comment
| receive "(" LValue ")" "{" Statement* "}" --constComment
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's actually change stringLiteral to Expression here (and for externals) to support arbitrary expressions: it should work as long as it's a string-valued constant expression. In the future we might have some compile-time string builtins or even allow integers, so instead of doing this:

message(1) OpCodeOneNoData {}

contract Contract {
  // would be nice to support underscores here too, since OpCodeOneNoData does not carry any further info
  receive(f: OpCodeOneNoData) {
      self.reply("OpCodeOneNoData".asComment())
  }
}

one could do

contract Contract {
  receive(1) {
      self.reply("OpCodeOneNoData".asComment())
  }
}

Copy link
Member

@novusnota novusnota Jun 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, interestingly enough it would somewhat change receivers towards #433. I'd propose having arbitrary string-valued expressions specified in constant declarations somewhere on top, or generally just prior to receivers and not embedded in. Motivation here reflects what you've said there: #433 (comment)

That said, @Gusarich would have the last word here :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, it's a bit too late to have a consistent design for Tact v1.x :) given that we already have messages and strings

| "bounced" "(" Parameter ")" "{" Statement* "}" --bounced // cannot be a reserved word because there a 'bounced' field in stdlib's 'Context' structure
| external "(" Parameter? ")" "{" Statement* "}" --externalRegular
| external "(" stringLiteral ")" "{" Statement* "}" --externalComment
| external "(" LValue ")" "{" Statement* "}" --constExternalComment

Statement = StatementLet
| StatementBlock
Expand Down
38 changes: 38 additions & 0 deletions src/grammar/grammar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,25 @@ semantics.addOperation<ASTNode>("astOfItem", {
ref: createRef(this),
});
},
Receiver_constComment(
_receiveKwd,
_lparen,
comment,
_rparen,
_lbrace,
receiverBody,
_rbrace,
) {
return createNode({
kind: "def_receive",
selector: {
kind: "internal-const-comment",
comment: comment.astOfLValue(),
},
statements: receiverBody.children.map((s) => s.astOfStatement()),
ref: createRef(this),
});
},
Receiver_bounced(
_bouncedKwd,
_lparen,
Expand Down Expand Up @@ -398,6 +417,25 @@ semantics.addOperation<ASTNode>("astOfItem", {
ref: createRef(this),
});
},
Receiver_constExternalComment(
_externalKwd,
_lparen,
comment,
_rparen,
_lbrace,
receiverBody,
_rbrace,
) {
return createNode({
kind: "def_receive",
selector: {
kind: "external-const-comment",
comment: comment.astOfLValue(),
},
statements: receiverBody.children.map((s) => s.astOfStatement()),
ref: createRef(this),
});
},
});

semantics.addOperation<ASTFunctionAttribute>("astOfFunctionAttributes", {
Expand Down
Loading
Loading