From 07a3f4624c79435bb3070f66844bdb28f7f5007b Mon Sep 17 00:00:00 2001 From: OmarTawfik <15987992+OmarTawfik@users.noreply.github.com> Date: Thu, 8 Feb 2024 10:35:46 -0800 Subject: [PATCH] support Yul label statements before `0.5.0` --- .changeset/tall-impalas-look.md | 5 + .../inputs/language/src/definition.rs | 32 +++-- .../cargo/crate/src/generated/kinds.rs | 1 + .../cargo/crate/src/generated/language.rs | 44 +++++- .../generated/napi_interface/ast_selectors.rs | 65 +++++---- .../src/cst_output/generated/YulLabel.rs | 10 ++ .../tests/src/cst_output/generated/mod.rs | 2 + .../package/src/ast/generated/ast_types.ts | 135 +++++++++++------- .../npm/package/src/generated/index.d.ts | 1 + .../outputs/spec/generated/grammar.ebnf | 19 ++- .../public/06-yul/01-yul-statements.md | 44 +++--- .../single_label/generated/0.4.11-success.yml | 12 ++ .../single_label/generated/0.5.0-failure.yml | 17 +++ .../YulLabel/single_label/input.sol | 1 + 14 files changed, 262 insertions(+), 126 deletions(-) create mode 100644 .changeset/tall-impalas-look.md create mode 100644 crates/solidity/outputs/cargo/tests/src/cst_output/generated/YulLabel.rs create mode 100644 crates/solidity/testing/snapshots/cst_output/YulLabel/single_label/generated/0.4.11-success.yml create mode 100644 crates/solidity/testing/snapshots/cst_output/YulLabel/single_label/generated/0.5.0-failure.yml create mode 100644 crates/solidity/testing/snapshots/cst_output/YulLabel/single_label/input.sol diff --git a/.changeset/tall-impalas-look.md b/.changeset/tall-impalas-look.md new file mode 100644 index 0000000000..e8d6b1d97b --- /dev/null +++ b/.changeset/tall-impalas-look.md @@ -0,0 +1,5 @@ +--- +"@nomicfoundation/slang": patch +--- + +support Yul label statements before `0.5.0` diff --git a/crates/solidity/inputs/language/src/definition.rs b/crates/solidity/inputs/language/src/definition.rs index 19a855a9be..200e60f54f 100644 --- a/crates/solidity/inputs/language/src/definition.rs +++ b/crates/solidity/inputs/language/src/definition.rs @@ -3932,6 +3932,7 @@ codegen_language_macros::compile!(Language( EnumVariant(reference = YulLeaveStatement, enabled = From("0.6.0")), EnumVariant(reference = YulBreakStatement), EnumVariant(reference = YulContinueStatement), + EnumVariant(reference = YulLabel, enabled = Till("0.5.0")), EnumVariant(reference = YulExpression) ] ), @@ -4005,19 +4006,6 @@ codegen_language_macros::compile!(Language( body = Required(YulBlock) ) ), - Struct( - name = YulLeaveStatement, - enabled = From("0.6.0"), - fields = (leave_keyword = Required(YulLeaveKeyword)) - ), - Struct( - name = YulBreakStatement, - fields = (break_keyword = Required(YulBreakKeyword)) - ), - Struct( - name = YulContinueStatement, - fields = (continue_keyword = Required(YulContinueKeyword)) - ), Struct( name = YulForStatement, fields = ( @@ -4058,6 +4046,24 @@ codegen_language_macros::compile!(Language( value = Required(YulLiteral), body = Required(YulBlock) ) + ), + Struct( + name = YulLeaveStatement, + enabled = From("0.6.0"), + fields = (leave_keyword = Required(YulLeaveKeyword)) + ), + Struct( + name = YulBreakStatement, + fields = (break_keyword = Required(YulBreakKeyword)) + ), + Struct( + name = YulContinueStatement, + fields = (continue_keyword = Required(YulContinueKeyword)) + ), + Struct( + name = YulLabel, + enabled = Till("0.5.0"), + fields = (label = Required(YulIdentifier), colon = Required(Colon)) ) ] ), diff --git a/crates/solidity/outputs/cargo/crate/src/generated/kinds.rs b/crates/solidity/outputs/cargo/crate/src/generated/kinds.rs index 41570f2fc0..08f4b46d1e 100644 --- a/crates/solidity/outputs/cargo/crate/src/generated/kinds.rs +++ b/crates/solidity/outputs/cargo/crate/src/generated/kinds.rs @@ -214,6 +214,7 @@ pub enum RuleKind { YulIdentifierPath, YulIdentifierPaths, YulIfStatement, + YulLabel, YulLeaveStatement, YulLiteral, YulParameters, diff --git a/crates/solidity/outputs/cargo/crate/src/generated/language.rs b/crates/solidity/outputs/cargo/crate/src/generated/language.rs index eabd94d193..9c75e0222b 100644 --- a/crates/solidity/outputs/cargo/crate/src/generated/language.rs +++ b/crates/solidity/outputs/cargo/crate/src/generated/language.rs @@ -6431,6 +6431,32 @@ impl Language { .with_kind(RuleKind::YulIfStatement) } + #[allow(unused_assignments, unused_parens)] + fn yul_label(&self, input: &mut ParserContext<'_>) -> ParserResult { + if !self.version_is_at_least_0_5_0 { + SequenceHelper::run(|mut seq| { + seq.elem_named( + FieldName::Label, + self.parse_token_with_trivia::( + input, + TokenKind::YulIdentifier, + ), + )?; + seq.elem_named( + FieldName::Colon, + self.parse_token_with_trivia::( + input, + TokenKind::Colon, + ), + )?; + seq.finish() + }) + } else { + ParserResult::disabled() + } + .with_kind(RuleKind::YulLabel) + } + #[allow(unused_assignments, unused_parens)] fn yul_leave_statement(&self, input: &mut ParserContext<'_>) -> ParserResult { if self.version_is_at_least_0_6_0 { @@ -6595,6 +6621,10 @@ impl Language { choice.consider(input, result)?; let result = self.yul_continue_statement(input); choice.consider(input, result)?; + if !self.version_is_at_least_0_5_0 { + let result = self.yul_label(input); + choice.consider(input, result)?; + } let result = self.yul_expression(input); choice.consider(input, result)?; choice.finish(input) @@ -9036,6 +9066,7 @@ impl Language { RuleKind::YulIdentifierPath => Self::yul_identifier_path.parse(self, input, true), RuleKind::YulIdentifierPaths => Self::yul_identifier_paths.parse(self, input, true), RuleKind::YulIfStatement => Self::yul_if_statement.parse(self, input, true), + RuleKind::YulLabel => Self::yul_label.parse(self, input, true), RuleKind::YulLeaveStatement => Self::yul_leave_statement.parse(self, input, true), RuleKind::YulLiteral => Self::yul_literal.parse(self, input, true), RuleKind::YulParameters => Self::yul_parameters.parse(self, input, true), @@ -10619,13 +10650,14 @@ impl Lexer for Language { } } Some('.') => Some(TokenKind::Period), - Some(':') => { - if scan_chars!(input, '=') { - Some(TokenKind::ColonEqual) - } else { - None + Some(':') => match input.next() { + Some('=') => Some(TokenKind::ColonEqual), + Some(_) => { + input.undo(); + Some(TokenKind::Colon) } - } + None => Some(TokenKind::Colon), + }, Some('{') => Some(TokenKind::OpenBrace), Some('}') => Some(TokenKind::CloseBrace), Some(_) => { diff --git a/crates/solidity/outputs/cargo/crate/src/generated/napi_interface/ast_selectors.rs b/crates/solidity/outputs/cargo/crate/src/generated/napi_interface/ast_selectors.rs index 050e7aca5d..6303ea18c2 100644 --- a/crates/solidity/outputs/cargo/crate/src/generated/napi_interface/ast_selectors.rs +++ b/crates/solidity/outputs/cargo/crate/src/generated/napi_interface/ast_selectors.rs @@ -148,13 +148,14 @@ pub fn select_sequence( RuleKind::YulVariableDeclarationValue => selector.yul_variable_declaration_value()?, RuleKind::YulAssignmentStatement => selector.yul_assignment_statement()?, RuleKind::YulIfStatement => selector.yul_if_statement()?, - RuleKind::YulLeaveStatement => selector.yul_leave_statement()?, - RuleKind::YulBreakStatement => selector.yul_break_statement()?, - RuleKind::YulContinueStatement => selector.yul_continue_statement()?, RuleKind::YulForStatement => selector.yul_for_statement()?, RuleKind::YulSwitchStatement => selector.yul_switch_statement()?, RuleKind::YulDefaultCase => selector.yul_default_case()?, RuleKind::YulValueCase => selector.yul_value_case()?, + RuleKind::YulLeaveStatement => selector.yul_leave_statement()?, + RuleKind::YulBreakStatement => selector.yul_break_statement()?, + RuleKind::YulContinueStatement => selector.yul_continue_statement()?, + RuleKind::YulLabel => selector.yul_label()?, RuleKind::YulFunctionCallExpression => selector.yul_function_call_expression()?, _ => { return Error::UnexpectedParent(node.kind()).into(); @@ -1381,30 +1382,6 @@ impl Selector { } } -impl Selector { - fn yul_leave_statement(&mut self) -> Result>> { - Ok(vec![Some(self.select(|node| { - node.is_token_with_kind(TokenKind::YulLeaveKeyword) - })?)]) - } -} - -impl Selector { - fn yul_break_statement(&mut self) -> Result>> { - Ok(vec![Some(self.select(|node| { - node.is_token_with_kind(TokenKind::YulBreakKeyword) - })?)]) - } -} - -impl Selector { - fn yul_continue_statement(&mut self) -> Result>> { - Ok(vec![Some(self.select(|node| { - node.is_token_with_kind(TokenKind::YulContinueKeyword) - })?)]) - } -} - impl Selector { fn yul_for_statement(&mut self) -> Result>> { Ok(vec![ @@ -1446,6 +1423,39 @@ impl Selector { } } +impl Selector { + fn yul_leave_statement(&mut self) -> Result>> { + Ok(vec![Some(self.select(|node| { + node.is_token_with_kind(TokenKind::YulLeaveKeyword) + })?)]) + } +} + +impl Selector { + fn yul_break_statement(&mut self) -> Result>> { + Ok(vec![Some(self.select(|node| { + node.is_token_with_kind(TokenKind::YulBreakKeyword) + })?)]) + } +} + +impl Selector { + fn yul_continue_statement(&mut self) -> Result>> { + Ok(vec![Some(self.select(|node| { + node.is_token_with_kind(TokenKind::YulContinueKeyword) + })?)]) + } +} + +impl Selector { + fn yul_label(&mut self) -> Result>> { + Ok(vec![ + Some(self.select(|node| node.is_token_with_kind(TokenKind::YulIdentifier))?), + Some(self.select(|node| node.is_token_with_kind(TokenKind::Colon))?), + ]) + } +} + impl Selector { fn yul_function_call_expression(&mut self) -> Result>> { Ok(vec![ @@ -2011,6 +2021,7 @@ impl Selector { RuleKind::YulLeaveStatement, RuleKind::YulBreakStatement, RuleKind::YulContinueStatement, + RuleKind::YulLabel, RuleKind::YulExpression, ]) }) diff --git a/crates/solidity/outputs/cargo/tests/src/cst_output/generated/YulLabel.rs b/crates/solidity/outputs/cargo/tests/src/cst_output/generated/YulLabel.rs new file mode 100644 index 0000000000..61c1295325 --- /dev/null +++ b/crates/solidity/outputs/cargo/tests/src/cst_output/generated/YulLabel.rs @@ -0,0 +1,10 @@ +// This file is generated automatically by infrastructure scripts. Please don't edit by hand. + +use anyhow::Result; + +use crate::cst_output::runner::run; + +#[test] +fn single_label() -> Result<()> { + run("YulLabel", "single_label") +} diff --git a/crates/solidity/outputs/cargo/tests/src/cst_output/generated/mod.rs b/crates/solidity/outputs/cargo/tests/src/cst_output/generated/mod.rs index de80ddf8d9..b1fda13211 100644 --- a/crates/solidity/outputs/cargo/tests/src/cst_output/generated/mod.rs +++ b/crates/solidity/outputs/cargo/tests/src/cst_output/generated/mod.rs @@ -98,6 +98,8 @@ mod YulExpression; #[allow(non_snake_case)] mod YulFunctionCallExpression; #[allow(non_snake_case)] +mod YulLabel; +#[allow(non_snake_case)] mod YulLeaveStatement; #[allow(non_snake_case)] mod YulVariableDeclarationStatement; diff --git a/crates/solidity/outputs/npm/package/src/ast/generated/ast_types.ts b/crates/solidity/outputs/npm/package/src/ast/generated/ast_types.ts index 30ac702318..38b39e8ce7 100644 --- a/crates/solidity/outputs/npm/package/src/ast/generated/ast_types.ts +++ b/crates/solidity/outputs/npm/package/src/ast/generated/ast_types.ts @@ -3481,60 +3481,6 @@ export class YulIfStatement { } } -export class YulLeaveStatement { - private readonly fetch = once(() => { - const [$leaveKeyword] = ast_internal.selectSequence(this.cst); - - return { - leaveKeyword: $leaveKeyword as TokenNode, - }; - }); - - public constructor(public readonly cst: RuleNode) { - assertKind(this.cst.kind, RuleKind.YulLeaveStatement); - } - - public get leaveKeyword(): TokenNode { - return this.fetch().leaveKeyword; - } -} - -export class YulBreakStatement { - private readonly fetch = once(() => { - const [$breakKeyword] = ast_internal.selectSequence(this.cst); - - return { - breakKeyword: $breakKeyword as TokenNode, - }; - }); - - public constructor(public readonly cst: RuleNode) { - assertKind(this.cst.kind, RuleKind.YulBreakStatement); - } - - public get breakKeyword(): TokenNode { - return this.fetch().breakKeyword; - } -} - -export class YulContinueStatement { - private readonly fetch = once(() => { - const [$continueKeyword] = ast_internal.selectSequence(this.cst); - - return { - continueKeyword: $continueKeyword as TokenNode, - }; - }); - - public constructor(public readonly cst: RuleNode) { - assertKind(this.cst.kind, RuleKind.YulContinueStatement); - } - - public get continueKeyword(): TokenNode { - return this.fetch().continueKeyword; - } -} - export class YulForStatement { private readonly fetch = once(() => { const [$forKeyword, $initialization, $condition, $iterator, $body] = ast_internal.selectSequence(this.cst); @@ -3652,6 +3598,83 @@ export class YulValueCase { } } +export class YulLeaveStatement { + private readonly fetch = once(() => { + const [$leaveKeyword] = ast_internal.selectSequence(this.cst); + + return { + leaveKeyword: $leaveKeyword as TokenNode, + }; + }); + + public constructor(public readonly cst: RuleNode) { + assertKind(this.cst.kind, RuleKind.YulLeaveStatement); + } + + public get leaveKeyword(): TokenNode { + return this.fetch().leaveKeyword; + } +} + +export class YulBreakStatement { + private readonly fetch = once(() => { + const [$breakKeyword] = ast_internal.selectSequence(this.cst); + + return { + breakKeyword: $breakKeyword as TokenNode, + }; + }); + + public constructor(public readonly cst: RuleNode) { + assertKind(this.cst.kind, RuleKind.YulBreakStatement); + } + + public get breakKeyword(): TokenNode { + return this.fetch().breakKeyword; + } +} + +export class YulContinueStatement { + private readonly fetch = once(() => { + const [$continueKeyword] = ast_internal.selectSequence(this.cst); + + return { + continueKeyword: $continueKeyword as TokenNode, + }; + }); + + public constructor(public readonly cst: RuleNode) { + assertKind(this.cst.kind, RuleKind.YulContinueStatement); + } + + public get continueKeyword(): TokenNode { + return this.fetch().continueKeyword; + } +} + +export class YulLabel { + private readonly fetch = once(() => { + const [$label, $colon] = ast_internal.selectSequence(this.cst); + + return { + label: $label as TokenNode, + colon: $colon as TokenNode, + }; + }); + + public constructor(public readonly cst: RuleNode) { + assertKind(this.cst.kind, RuleKind.YulLabel); + } + + public get label(): TokenNode { + return this.fetch().label; + } + + public get colon(): TokenNode { + return this.fetch().colon; + } +} + export class YulFunctionCallExpression { private readonly fetch = once(() => { const [$openParen, $arguments, $closeParen, $operand] = ast_internal.selectSequence(this.cst); @@ -4896,6 +4919,7 @@ export class YulStatement { | YulLeaveStatement | YulBreakStatement | YulContinueStatement + | YulLabel | YulExpression = once(() => { const variant = ast_internal.selectChoice(this.cst); @@ -4920,6 +4944,8 @@ export class YulStatement { return new YulBreakStatement(variant as RuleNode); case RuleKind.YulContinueStatement: return new YulContinueStatement(variant as RuleNode); + case RuleKind.YulLabel: + return new YulLabel(variant as RuleNode); case RuleKind.YulExpression: return new YulExpression(variant as RuleNode); @@ -4943,6 +4969,7 @@ export class YulStatement { | YulLeaveStatement | YulBreakStatement | YulContinueStatement + | YulLabel | YulExpression { return this.fetch(); } diff --git a/crates/solidity/outputs/npm/package/src/generated/index.d.ts b/crates/solidity/outputs/npm/package/src/generated/index.d.ts index 4630878758..1d84d7a375 100644 --- a/crates/solidity/outputs/npm/package/src/generated/index.d.ts +++ b/crates/solidity/outputs/npm/package/src/generated/index.d.ts @@ -206,6 +206,7 @@ export namespace kinds { YulIdentifierPath = "YulIdentifierPath", YulIdentifierPaths = "YulIdentifierPaths", YulIfStatement = "YulIfStatement", + YulLabel = "YulLabel", YulLeaveStatement = "YulLeaveStatement", YulLiteral = "YulLiteral", YulParameters = "YulParameters", diff --git a/crates/solidity/outputs/spec/generated/grammar.ebnf b/crates/solidity/outputs/spec/generated/grammar.ebnf index 92d4dd40ed..82730ca40a 100644 --- a/crates/solidity/outputs/spec/generated/grammar.ebnf +++ b/crates/solidity/outputs/spec/generated/grammar.ebnf @@ -1317,6 +1317,7 @@ YulStatement = YulBlock | YulLeaveStatement (* Introduced in 0.6.0 *) | YulBreakStatement | YulContinueStatement + | YulLabel (* Deprecated in 0.5.0 *) | YulExpression; YulFunctionDefinition = YUL_FUNCTION_KEYWORD @@ -1351,13 +1352,6 @@ YulIfStatement = YUL_IF_KEYWORD YulExpression YulBlock; -(* Introduced in 0.6.0 *) -YulLeaveStatement = YUL_LEAVE_KEYWORD; - -YulBreakStatement = YUL_BREAK_KEYWORD; - -YulContinueStatement = YUL_CONTINUE_KEYWORD; - YulForStatement = YUL_FOR_KEYWORD YulBlock YulExpression @@ -1380,6 +1374,17 @@ YulValueCase = YUL_CASE_KEYWORD YulLiteral YulBlock; +(* Introduced in 0.6.0 *) +YulLeaveStatement = YUL_LEAVE_KEYWORD; + +YulBreakStatement = YUL_BREAK_KEYWORD; + +YulContinueStatement = YUL_CONTINUE_KEYWORD; + +(* Deprecated in 0.5.0 *) +YulLabel = YUL_IDENTIFIER + COLON; + (* 6.2. Yul Expressions: *) YulExpression = YulFunctionCallExpression diff --git a/crates/solidity/outputs/spec/generated/public/06-yul/01-yul-statements.md b/crates/solidity/outputs/spec/generated/public/06-yul/01-yul-statements.md index 10e9e1a047..b98fa521e5 100644 --- a/crates/solidity/outputs/spec/generated/public/06-yul/01-yul-statements.md +++ b/crates/solidity/outputs/spec/generated/public/06-yul/01-yul-statements.md @@ -20,7 +20,7 @@ ``` -
YulStatement = YulBlock
| YulFunctionDefinition
| YulVariableDeclarationStatement
| YulAssignmentStatement
| YulIfStatement
| YulForStatement
| YulSwitchStatement
| YulLeaveStatement (* Introduced in 0.6.0 *)
| YulBreakStatement
| YulContinueStatement
| YulExpression;
+
YulStatement = YulBlock
| YulFunctionDefinition
| YulVariableDeclarationStatement
| YulAssignmentStatement
| YulIfStatement
| YulForStatement
| YulSwitchStatement
| YulLeaveStatement (* Introduced in 0.6.0 *)
| YulBreakStatement
| YulContinueStatement
| YulLabel (* Deprecated in 0.5.0 *)
| YulExpression;
```{ .ebnf #YulFunctionDefinition } @@ -76,24 +76,6 @@
YulIfStatement = YUL_IF_KEYWORD
YulExpression
YulBlock;
-```{ .ebnf #YulLeaveStatement } - -``` - -
(* Introduced in 0.6.0 *)
YulLeaveStatement = YUL_LEAVE_KEYWORD;
- -```{ .ebnf #YulBreakStatement } - -``` - -
YulBreakStatement = YUL_BREAK_KEYWORD;
- -```{ .ebnf #YulContinueStatement } - -``` - -
YulContinueStatement = YUL_CONTINUE_KEYWORD;
- ```{ .ebnf #YulForStatement } ``` @@ -130,4 +112,28 @@
YulValueCase = YUL_CASE_KEYWORD
YulLiteral
YulBlock;
+```{ .ebnf #YulLeaveStatement } + +``` + +
(* Introduced in 0.6.0 *)
YulLeaveStatement = YUL_LEAVE_KEYWORD;
+ +```{ .ebnf #YulBreakStatement } + +``` + +
YulBreakStatement = YUL_BREAK_KEYWORD;
+ +```{ .ebnf #YulContinueStatement } + +``` + +
YulContinueStatement = YUL_CONTINUE_KEYWORD;
+ +```{ .ebnf #YulLabel } + +``` + +
(* Deprecated in 0.5.0 *)
YulLabel = YUL_IDENTIFIER
COLON;
+ --8<-- "crates/solidity/inputs/language/docs/06-yul/01-yul-statements.md" diff --git a/crates/solidity/testing/snapshots/cst_output/YulLabel/single_label/generated/0.4.11-success.yml b/crates/solidity/testing/snapshots/cst_output/YulLabel/single_label/generated/0.4.11-success.yml new file mode 100644 index 0000000000..85d84ea03a --- /dev/null +++ b/crates/solidity/testing/snapshots/cst_output/YulLabel/single_label/generated/0.4.11-success.yml @@ -0,0 +1,12 @@ +# This file is generated automatically by infrastructure scripts. Please don't edit by hand. + +Source: > + 1 │ foo: │ 0..4 + +Errors: [] + +Tree: + - (YulLabel): # "foo:\n" (0..5) + - (label꞉ YulIdentifier): "foo" # (0..3) + - (colon꞉ Colon): ":" # (3..4) + - (TrailingTrivia) ► (EndOfLine): "\n" # (4..5) diff --git a/crates/solidity/testing/snapshots/cst_output/YulLabel/single_label/generated/0.5.0-failure.yml b/crates/solidity/testing/snapshots/cst_output/YulLabel/single_label/generated/0.5.0-failure.yml new file mode 100644 index 0000000000..bba0a780fd --- /dev/null +++ b/crates/solidity/testing/snapshots/cst_output/YulLabel/single_label/generated/0.5.0-failure.yml @@ -0,0 +1,17 @@ +# This file is generated automatically by infrastructure scripts. Please don't edit by hand. + +Source: > + 1 │ foo: │ 0..4 + +Errors: # 1 total + - > + Error: Expected end of file. + ╭─[crates/solidity/testing/snapshots/cst_output/YulLabel/single_label/input.sol:1:1] + │ + 1 │ foo: + │ ──┬── + │ ╰──── Error occurred here. + ───╯ + +Tree: + - (SKIPPED): "foo:\n" # (0..5) diff --git a/crates/solidity/testing/snapshots/cst_output/YulLabel/single_label/input.sol b/crates/solidity/testing/snapshots/cst_output/YulLabel/single_label/input.sol new file mode 100644 index 0000000000..0152a79652 --- /dev/null +++ b/crates/solidity/testing/snapshots/cst_output/YulLabel/single_label/input.sol @@ -0,0 +1 @@ +foo: