Skip to content

Commit

Permalink
Handle macro-call statements
Browse files Browse the repository at this point in the history
Some macros, such as `calc!{}` can sit in statement position and need
not have a terminating semicolon. This would previously be rejected by
the parser, requiring the extra semicolon to not misparse whatever came
_after_ such a statement-position macro-call.

By convention, such macro calls use curly braces (while expr ones tend
to use square or parens), so we can use this as a disambiguating factor.
More details in parser comment.
  • Loading branch information
jaybosamiya committed Feb 2, 2024
1 parent 066eaae commit ff17d23
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -727,6 +727,7 @@ fn to_doc<'a>(
Rule::lifetime_arg => map_to_doc(ctx, arena, pair),
Rule::const_arg => unsupported(pair),
Rule::macro_call => s,
Rule::macro_call_stmt => s,
Rule::punctuation => map_to_doc(ctx, arena, pair),
Rule::token => map_to_doc(ctx, arena, pair),
Rule::delim_token_tree => map_to_doc(ctx, arena, pair),
Expand Down
15 changes: 15 additions & 0 deletions src/verus.pest
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,20 @@ macro_call = {
attr* ~ path ~ bang_str ~ !"=" ~ token_tree
}

// NOTE: By convention, stmt-like or item-like macros (e.g., calc!{}) tend to
// use curly braces; this is only a convention though, and _technically_ one
// could use parens or square brackets for the same. However, we use this to
// disambiguate unknown macros when used in statement lists _without_
// semi-colons; if it is intended as an expr, the user better be using parens.
//
// Another alternative is to use `!(expr ~ "}") ~ macro_call` rather than
// `macro_call_stmt`, but as of now, I believe this to be a better choice; we
// can switch to the alternative if we find situations where it might be better
// suited.
macro_call_stmt = {
attr* ~ path ~ bang_str ~ !"=" ~ lbrace_str ~ token_tree* ~ rbrace_str
}

// See https://doc.rust-lang.org/beta/reference/tokens.html#punctuation
punctuation = {
bin_expr_ops
Expand Down Expand Up @@ -869,6 +883,7 @@ stmt = {
| expr_with_block ~ semi_str?
| expr ~ semi_str
| item_no_macro_call
| macro_call_stmt
}

let_stmt = {
Expand Down
53 changes: 53 additions & 0 deletions tests/verus-consistency.rs
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,59 @@ verus!{
"###);
}

#[test]
fn verus_macro_statements() {
let file = r#"
verus! {
// Notice that the semicolon is optional
proof fn foo() {
calc! {
(==)
1int; {}
(0int + 1int); {}
};
calc! {
(==)
1int; {}
(0int + 1int); {}
}
calc! {
(==)
1int; {}
(0int + 1int); {}
}
}
}
"#;

assert_snapshot!(parse_and_format(file).unwrap(), @r###"
verus! {
// Notice that the semicolon is optional
proof fn foo() {
calc! {
(==)
1int; {}
(0int + 1int); {}
};
calc! {
(==)
1int; {}
(0int + 1int); {}
}
calc! {
(==)
1int; {}
(0int + 1int); {}
}
}
} // verus!
"###);
}

#[test]
fn verus_impl() {
let file = r#"
Expand Down

0 comments on commit ff17d23

Please sign in to comment.