Skip to content

Commit

Permalink
Parse builtin# syntax
Browse files Browse the repository at this point in the history
  • Loading branch information
Veykril committed Sep 5, 2023
1 parent db4684e commit 9b8eb80
Show file tree
Hide file tree
Showing 17 changed files with 257 additions and 81 deletions.
9 changes: 4 additions & 5 deletions crates/hir-def/src/body/lower.rs
Original file line number Diff line number Diff line change
Expand Up @@ -579,11 +579,6 @@ impl ExprCollector<'_> {
syntax_ptr,
)
}
ast::Expr::BoxExpr(e) => {
let expr = self.collect_expr_opt(e.expr());
self.alloc_expr(Expr::Box { expr }, syntax_ptr)
}

ast::Expr::ArrayExpr(e) => {
let kind = e.kind();

Expand Down Expand Up @@ -653,6 +648,9 @@ impl ExprCollector<'_> {
}
}
ast::Expr::UnderscoreExpr(_) => self.alloc_expr(Expr::Underscore, syntax_ptr),
ast::Expr::AsmExpr(_) => self.missing_expr(),
ast::Expr::OffsetOfExpr(_) => self.missing_expr(),
ast::Expr::FormatArgsExpr(_) => self.missing_expr(),
})
}

Expand All @@ -663,6 +661,7 @@ impl ExprCollector<'_> {
let result_expr_id = self.alloc_expr(Expr::Missing, syntax_ptr);
let prev_binding_owner = self.current_binding_owner.take();
self.current_binding_owner = Some(result_expr_id);

(result_expr_id, prev_binding_owner)
}

Expand Down
29 changes: 29 additions & 0 deletions crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,35 @@ fn main() { 0 as u32; }
);
}

#[test]
fn test_asm_expand() {
check(
r#"
#[rustc_builtin_macro]
macro_rules! asm {() => {}}
fn main() {
let i: u64 = 3;
let o: u64;
unsafe {
asm!(
"mov {0}, {1}",
"add {0}, 5",
out(reg) o,
in(reg) i,
);
}
}
"#,
expect![[r#"
#[rustc_builtin_macro]
macro_rules! column {() => {}}
fn main() { 0 as u32; }
"#]],
);
}

#[test]
fn test_line_expand() {
check(
Expand Down
12 changes: 8 additions & 4 deletions crates/hir-expand/src/builtin_fn_macro.rs
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,8 @@ fn asm_expand(
_id: MacroCallId,
tt: &tt::Subtree,
) -> ExpandResult<tt::Subtree> {
// FIXME: parse asm here

// We expand all assembly snippets to `format_args!` invocations to get format syntax
// highlighting for them.

Expand All @@ -415,10 +417,12 @@ fn asm_expand(
}
}

let expanded = quote! {{
##literals
loop {}
}};
let pound = quote! {@PUNCT '#'};
let expanded = quote! {
builtin #pound asm {
##literals
}
};
ExpandResult::ok(expanded)
}

Expand Down
1 change: 1 addition & 0 deletions crates/hir-ty/src/infer/closure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -620,6 +620,7 @@ impl InferenceContext<'_> {
| Expr::Tuple { exprs, is_assignee_expr: _ } => {
self.consume_exprs(exprs.iter().copied())
}

Expr::Missing
| Expr::Continue { .. }
| Expr::Path(_)
Expand Down
1 change: 0 additions & 1 deletion crates/ide-assists/src/handlers/convert_bool_then.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,6 @@ pub(crate) fn convert_if_to_bool_then(acc: &mut Assists, ctx: &AssistContext<'_>
cond,
ast::Expr::BinExpr(_)
| ast::Expr::BlockExpr(_)
| ast::Expr::BoxExpr(_)
| ast::Expr::BreakExpr(_)
| ast::Expr::CastExpr(_)
| ast::Expr::ClosureExpr(_)
Expand Down
3 changes: 1 addition & 2 deletions crates/ide-assists/src/handlers/promote_local_to_const.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,7 @@ fn is_body_const(sema: &Semantics<'_, RootDatabase>, expr: &ast::Expr) -> bool {
is_const &=
sema.resolve_method_call(&call).map(|it| it.is_const(sema.db)).unwrap_or(true)
}
ast::Expr::BoxExpr(_)
| ast::Expr::ForExpr(_)
ast::Expr::ForExpr(_)
| ast::Expr::ReturnExpr(_)
| ast::Expr::TryExpr(_)
| ast::Expr::YieldExpr(_)
Expand Down
5 changes: 1 addition & 4 deletions crates/ide-assists/src/handlers/remove_dbg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,10 +113,7 @@ fn compute_dbg_replacement(macro_expr: ast::MacroExpr) -> Option<(TextRange, Opt
Some(parent) => match (expr, parent) {
(ast::Expr::CastExpr(_), ast::Expr::CastExpr(_)) => false,
(
ast::Expr::BoxExpr(_)
| ast::Expr::PrefixExpr(_)
| ast::Expr::RefExpr(_)
| ast::Expr::MacroExpr(_),
ast::Expr::PrefixExpr(_) | ast::Expr::RefExpr(_) | ast::Expr::MacroExpr(_),
ast::Expr::AwaitExpr(_)
| ast::Expr::CallExpr(_)
| ast::Expr::CastExpr(_)
Expand Down
1 change: 0 additions & 1 deletion crates/ide-assists/src/utils/suggest_name.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,6 @@ pub(crate) fn for_variable(expr: &ast::Expr, sema: &Semantics<'_, RootDatabase>)

match expr {
ast::Expr::RefExpr(inner) => next_expr = inner.expr(),
ast::Expr::BoxExpr(inner) => next_expr = inner.expr(),
ast::Expr::AwaitExpr(inner) => next_expr = inner.expr(),
// ast::Expr::BlockExpr(block) => expr = block.tail_expr(),
ast::Expr::CastExpr(inner) => next_expr = inner.expr(),
Expand Down
6 changes: 4 additions & 2 deletions crates/ide-db/src/syntax_helpers/node_ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,6 @@ pub fn for_each_tail_expr(expr: &ast::Expr, cb: &mut dyn FnMut(&ast::Expr)) {
ast::Expr::ArrayExpr(_)
| ast::Expr::AwaitExpr(_)
| ast::Expr::BinExpr(_)
| ast::Expr::BoxExpr(_)
| ast::Expr::BreakExpr(_)
| ast::Expr::CallExpr(_)
| ast::Expr::CastExpr(_)
Expand All @@ -335,7 +334,10 @@ pub fn for_each_tail_expr(expr: &ast::Expr, cb: &mut dyn FnMut(&ast::Expr)) {
| ast::Expr::LetExpr(_)
| ast::Expr::UnderscoreExpr(_)
| ast::Expr::YieldExpr(_)
| ast::Expr::YeetExpr(_) => cb(expr),
| ast::Expr::YeetExpr(_)
| ast::Expr::OffsetOfExpr(_)
| ast::Expr::FormatArgsExpr(_)
| ast::Expr::AsmExpr(_) => cb(expr),
}
}

Expand Down
10 changes: 9 additions & 1 deletion crates/ide/src/syntax_highlighting/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -534,7 +534,15 @@ fn main() {
assert!(true, "{}", 1);
assert!(true, "{} asdasd", 1);
toho!("{}fmt", 0);
asm!("mov eax, {0}");
let i: u64 = 3;
let o: u64;
asm!(
"mov {0}, {1}",
"add {0}, 5",
out(reg) o,
in(reg) i,
);
format_args!(concat!("{}"), "{}");
format_args!("{} {} {} {} {} {}", backslash, format_args!("{}", 0), foo, "bar", toho!(), backslash);
}"#,
Expand Down
54 changes: 37 additions & 17 deletions crates/parser/src/grammar/expressions/atom.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use crate::grammar::types::type_;

use super::*;

// test expr_literals
Expand Down Expand Up @@ -73,6 +75,9 @@ pub(super) fn atom_expr(
if let Some(m) = literal(p) {
return Some((m, BlockLike::NotBlock));
}
if p.at_contextual_kw(T![builtin]) && p.nth_at(1, T![#]) {
return Some((builtin_expr(p)?, BlockLike::NotBlock));
}
if paths::is_path_start(p) {
return Some(path_expr(p, r));
}
Expand All @@ -93,7 +98,6 @@ pub(super) fn atom_expr(
m.complete(p, UNDERSCORE_EXPR)
}
T![loop] => loop_expr(p, None),
T![box] => box_expr(p, None),
T![while] => while_expr(p, None),
T![try] => try_block_expr(p, None),
T![match] => match_expr(p),
Expand Down Expand Up @@ -212,6 +216,38 @@ fn tuple_expr(p: &mut Parser<'_>) -> CompletedMarker {
m.complete(p, if saw_expr && !saw_comma { PAREN_EXPR } else { TUPLE_EXPR })
}

// test builtin_expr
// fn foo() {
// builtin#asm(0);
// builtin#format_args(0);
// builtin#builtin(0);
// }
fn builtin_expr(p: &mut Parser<'_>) -> Option<CompletedMarker> {
let m = p.start();
p.bump_remap(T![builtin]);
p.bump(T![#]);
if p.at_contextual_kw(T![offset_of]) {
p.expect(T!['(']);
type_(p);
p.bump(T![,]);
p.expect(T![')']);
Some(m.complete(p, OFFSET_OF_EXPR))
} else if p.at_contextual_kw(T![format_args]) {
p.expect(T!['(']);
expr(p);
p.expect(T![')']);
Some(m.complete(p, FORMAT_ARGS_EXPR))
} else if p.at_contextual_kw(T![asm]) {
p.expect(T!['(']);
expr(p);
p.expect(T![')']);
Some(m.complete(p, ASM_EXPR))
} else {
m.abandon(p);
None
}
}

// test array_expr
// fn foo() {
// [];
Expand Down Expand Up @@ -662,19 +698,3 @@ fn try_block_expr(p: &mut Parser<'_>, m: Option<Marker>) -> CompletedMarker {
}
m.complete(p, BLOCK_EXPR)
}

// test box_expr
// fn foo() {
// let x = box 1i32;
// let y = (box 1i32, box 2i32);
// let z = Foo(box 1i32, box 2i32);
// }
fn box_expr(p: &mut Parser<'_>, m: Option<Marker>) -> CompletedMarker {
assert!(p.at(T![box]));
let m = m.unwrap_or_else(|| p.start());
p.bump(T![box]);
if p.at_ts(EXPR_FIRST) {
expr(p);
}
m.complete(p, BOX_EXPR)
}
1 change: 1 addition & 0 deletions crates/parser/src/lexed_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ impl<'a> Converter<'a> {
rustc_lexer::TokenKind::Caret => T![^],
rustc_lexer::TokenKind::Percent => T![%],
rustc_lexer::TokenKind::Unknown => ERROR,
rustc_lexer::TokenKind::UnknownPrefix if token_text == "builtin" => IDENT,
rustc_lexer::TokenKind::UnknownPrefix => {
err = "unknown literal prefix";
IDENT
Expand Down
Loading

0 comments on commit 9b8eb80

Please sign in to comment.