Remove weird nesting of effect blocks in hir

This commit is contained in:
Lukas Wirth 2023-03-04 14:45:57 +01:00
parent 24ba1bed04
commit 1b5bc83118
9 changed files with 285 additions and 247 deletions

View file

@ -37,7 +37,7 @@ use crate::{
item_scope::BuiltinShadowMode,
path::{GenericArgs, Path},
type_ref::{Mutability, Rawness, TypeRef},
AdtId, BlockLoc, ModuleDefId, UnresolvedMacro,
AdtId, BlockId, BlockLoc, ModuleDefId, UnresolvedMacro,
};
pub struct LowerCtx<'a> {
@ -238,33 +238,32 @@ impl ExprCollector<'_> {
}
ast::Expr::BlockExpr(e) => match e.modifier() {
Some(ast::BlockModifier::Try(_)) => {
let body = self.collect_block(e);
self.alloc_expr(Expr::TryBlock { body }, syntax_ptr)
self.collect_block_(e, |id, statements, tail| Expr::TryBlock {
id,
statements,
tail,
})
}
Some(ast::BlockModifier::Unsafe(_)) => {
let body = self.collect_block(e);
self.alloc_expr(Expr::Unsafe { body }, syntax_ptr)
self.collect_block_(e, |id, statements, tail| Expr::Unsafe {
id,
statements,
tail,
})
}
// FIXME: we need to record these effects somewhere...
Some(ast::BlockModifier::Label(label)) => {
let label = self.collect_label(label);
let res = self.collect_block(e);
match &mut self.body.exprs[res] {
Expr::Block { label: block_label, .. } => {
*block_label = Some(label);
}
_ => unreachable!(),
}
res
}
Some(ast::BlockModifier::Async(_)) => {
let body = self.collect_block(e);
self.alloc_expr(Expr::Async { body }, syntax_ptr)
}
Some(ast::BlockModifier::Const(_)) => {
let body = self.collect_block(e);
self.alloc_expr(Expr::Const { body }, syntax_ptr)
self.collect_block_(e, |id, statements, tail| Expr::Block {
id,
statements,
tail,
label: Some(label),
})
}
Some(ast::BlockModifier::Async(_)) => self
.collect_block_(e, |id, statements, tail| Expr::Async { id, statements, tail }),
Some(ast::BlockModifier::Const(_)) => self
.collect_block_(e, |id, statements, tail| Expr::Const { id, statements, tail }),
None => self.collect_block(e),
},
ast::Expr::LoopExpr(e) => {
@ -737,6 +736,19 @@ impl ExprCollector<'_> {
}
fn collect_block(&mut self, block: ast::BlockExpr) -> ExprId {
self.collect_block_(block, |id, statements, tail| Expr::Block {
id,
statements,
tail,
label: None,
})
}
fn collect_block_(
&mut self,
block: ast::BlockExpr,
mk_block: impl FnOnce(BlockId, Box<[Statement]>, Option<ExprId>) -> Expr,
) -> ExprId {
let file_local_id = self.ast_id_map.ast_id(&block);
let ast_id = AstId::new(self.expander.current_file_id, file_local_id);
let block_loc =
@ -769,15 +781,8 @@ impl ExprCollector<'_> {
});
let syntax_node_ptr = AstPtr::new(&block.into());
let expr_id = self.alloc_expr(
Expr::Block {
id: block_id,
statements: statements.into_boxed_slice(),
tail,
label: None,
},
syntax_node_ptr,
);
let expr_id = self
.alloc_expr(mk_block(block_id, statements.into_boxed_slice(), tail), syntax_node_ptr);
self.expander.def_map = prev_def_map;
self.expander.module = prev_local_module;

View file

@ -292,18 +292,6 @@ impl<'a> Printer<'a> {
self.print_expr(*expr);
w!(self, "?");
}
Expr::TryBlock { body } => {
w!(self, "try ");
self.print_expr(*body);
}
Expr::Async { body } => {
w!(self, "async ");
self.print_expr(*body);
}
Expr::Const { body } => {
w!(self, "const ");
self.print_expr(*body);
}
Expr::Cast { expr, type_ref } => {
self.print_expr(*expr);
w!(self, " as ");
@ -402,10 +390,6 @@ impl<'a> Printer<'a> {
}
w!(self, ")");
}
Expr::Unsafe { body } => {
w!(self, "unsafe ");
self.print_expr(*body);
}
Expr::Array(arr) => {
w!(self, "[");
if !matches!(arr, Array::ElementList { elements, .. } if elements.is_empty()) {
@ -428,27 +412,49 @@ impl<'a> Printer<'a> {
}
Expr::Literal(lit) => self.print_literal(lit),
Expr::Block { id: _, statements, tail, label } => {
self.whitespace();
if let Some(lbl) = label {
w!(self, "{}: ", self.body[*lbl].name);
}
w!(self, "{{");
if !statements.is_empty() || tail.is_some() {
self.indented(|p| {
for stmt in &**statements {
p.print_stmt(stmt);
}
if let Some(tail) = tail {
p.print_expr(*tail);
}
p.newline();
});
}
w!(self, "}}");
let label = label.map(|lbl| format!("{}: ", self.body[lbl].name));
self.print_block(label.as_deref(), statements, tail);
}
Expr::Unsafe { id: _, statements, tail } => {
self.print_block(Some("unsafe "), statements, tail);
}
Expr::TryBlock { id: _, statements, tail } => {
self.print_block(Some("try "), statements, tail);
}
Expr::Async { id: _, statements, tail } => {
self.print_block(Some("async "), statements, tail);
}
Expr::Const { id: _, statements, tail } => {
self.print_block(Some("const "), statements, tail);
}
}
}
fn print_block(
&mut self,
label: Option<&str>,
statements: &Box<[Statement]>,
tail: &Option<la_arena::Idx<Expr>>,
) {
self.whitespace();
if let Some(lbl) = label {
w!(self, "{}", lbl);
}
w!(self, "{{");
if !statements.is_empty() || tail.is_some() {
self.indented(|p| {
for stmt in &**statements {
p.print_stmt(stmt);
}
if let Some(tail) = tail {
p.print_expr(*tail);
}
p.newline();
});
}
w!(self, "}}");
}
fn print_pat(&mut self, pat: PatId) {
let pat = &self.body[pat];

View file

@ -109,6 +109,26 @@ pub enum Expr {
tail: Option<ExprId>,
label: Option<LabelId>,
},
TryBlock {
id: BlockId,
statements: Box<[Statement]>,
tail: Option<ExprId>,
},
Async {
id: BlockId,
statements: Box<[Statement]>,
tail: Option<ExprId>,
},
Const {
id: BlockId,
statements: Box<[Statement]>,
tail: Option<ExprId>,
},
Unsafe {
id: BlockId,
statements: Box<[Statement]>,
tail: Option<ExprId>,
},
Loop {
body: ExprId,
label: Option<LabelId>,
@ -172,15 +192,6 @@ pub enum Expr {
Try {
expr: ExprId,
},
TryBlock {
body: ExprId,
},
Async {
body: ExprId,
},
Const {
body: ExprId,
},
Cast {
expr: ExprId,
type_ref: Interned<TypeRef>,
@ -222,9 +233,6 @@ pub enum Expr {
exprs: Box<[ExprId]>,
is_assignee_expr: bool,
},
Unsafe {
body: ExprId,
},
Array(Array),
Literal(Literal),
Underscore,
@ -290,13 +298,20 @@ impl Expr {
Expr::Let { expr, .. } => {
f(*expr);
}
Expr::Block { statements, tail, .. } => {
Expr::Block { statements, tail, .. }
| Expr::TryBlock { statements, tail, .. }
| Expr::Unsafe { statements, tail, .. }
| Expr::Async { statements, tail, .. }
| Expr::Const { statements, tail, .. } => {
for stmt in statements.iter() {
match stmt {
Statement::Let { initializer, .. } => {
Statement::Let { initializer, else_branch, .. } => {
if let &Some(expr) = initializer {
f(expr);
}
if let &Some(expr) = else_branch {
f(expr);
}
}
Statement::Expr { expr: expression, .. } => f(*expression),
}
@ -305,10 +320,6 @@ impl Expr {
f(expr);
}
}
Expr::TryBlock { body }
| Expr::Unsafe { body }
| Expr::Async { body }
| Expr::Const { body } => f(*body),
Expr::Loop { body, .. } => f(*body),
Expr::While { condition, body, .. } => {
f(*condition);