1 use rustc_index::vec::IndexVec;
2 use rustc_middle::{mir::*, thir::*, ty::Ty};
5 use super::{PResult, ParseCtxt, ParseError};
9 /// Helper macro for parsing custom MIR.
11 /// Example usage looks something like:
12 /// ```rust,ignore (incomplete example)
14 /// self, // : &ParseCtxt
15 /// expr_id, // what you're matching against
16 /// "assignment", // the thing you're trying to parse
17 /// @call("mir_assign", args) => { args[0] }, // match invocations of the `mir_assign` special function
18 /// ExprKind::Assign { lhs, .. } => { lhs }, // match thir assignment expressions
19 /// // no need for fallthrough case - reasonable error is automatically generated
22 macro_rules! parse_by_kind {
29 @call($name:literal, $args:ident) => $call_expr:expr,
32 $pat:pat => $expr:expr,
35 let expr_id = $self.preparse($expr_id);
36 let expr = &$self.thir[expr_id];
37 debug!("Trying to parse {:?} as {}", expr.kind, $expected);
38 let $expr_name = expr;
41 ExprKind::Call { ty, fun: _, args: $args, .. } if {
43 ty::FnDef(did, _) => {
44 $self.tcx.is_diagnostic_item(rustc_span::Symbol::intern($name), *did)
53 #[allow(unreachable_patterns)]
54 _ => return Err($self.expr_error(expr_id, $expected))
58 pub(crate) use parse_by_kind;
60 impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
61 /// Expressions should only ever be matched on after preparsing them. This removes extra scopes
62 /// we don't care about.
63 fn preparse(&self, expr_id: ExprId) -> ExprId {
64 let expr = &self.thir[expr_id];
66 ExprKind::Scope { value, .. } => self.preparse(value),
71 fn statement_as_expr(&self, stmt_id: StmtId) -> PResult<ExprId> {
72 match &self.thir[stmt_id].kind {
73 StmtKind::Expr { expr, .. } => Ok(*expr),
74 kind @ StmtKind::Let { pattern, .. } => {
75 return Err(ParseError {
77 item_description: format!("{:?}", kind),
78 expected: "expression".to_string(),
84 pub fn parse_args(&mut self, params: &IndexVec<ParamId, Param<'tcx>>) -> PResult<()> {
85 for param in params.iter() {
87 let pat = param.pat.as_ref().unwrap();
89 PatKind::Binding { var, .. } => (*var, pat.span),
91 return Err(ParseError {
93 item_description: format!("{:?}", pat.kind),
94 expected: "local".to_string(),
99 let decl = LocalDecl::new(param.ty, span);
100 let local = self.body.local_decls.push(decl);
101 self.local_map.insert(var, local);
107 /// Bodies are of the form:
111 /// let bb1: BasicBlock;
112 /// let bb2: BasicBlock;
140 /// This allows us to easily parse the basic blocks declarations, local declarations, and
141 /// basic block definitions in order.
142 pub fn parse_body(&mut self, expr_id: ExprId) -> PResult<()> {
143 let body = parse_by_kind!(self, expr_id, _, "whole body",
144 ExprKind::Block { block } => self.thir[*block].expr.unwrap(),
146 let (block_decls, rest) = parse_by_kind!(self, body, _, "body with block decls",
147 ExprKind::Block { block } => {
148 let block = &self.thir[*block];
149 (&block.stmts, block.expr.unwrap())
152 self.parse_block_decls(block_decls.iter().copied())?;
154 let (local_decls, rest) = parse_by_kind!(self, rest, _, "body with local decls",
155 ExprKind::Block { block } => {
156 let block = &self.thir[*block];
157 (&block.stmts, block.expr.unwrap())
160 self.parse_local_decls(local_decls.iter().copied())?;
162 let block_defs = parse_by_kind!(self, rest, _, "body with block defs",
163 ExprKind::Block { block } => &self.thir[*block].stmts,
165 for (i, block_def) in block_defs.iter().enumerate() {
166 let block = self.parse_block_def(self.statement_as_expr(*block_def)?)?;
167 self.body.basic_blocks_mut()[BasicBlock::from_usize(i)] = block;
173 fn parse_block_decls(&mut self, stmts: impl Iterator<Item = StmtId>) -> PResult<()> {
175 let (var, _, _) = self.parse_let_statement(stmt)?;
176 let data = BasicBlockData::new(None);
177 let block = self.body.basic_blocks_mut().push(data);
178 self.block_map.insert(var, block);
184 fn parse_local_decls(&mut self, mut stmts: impl Iterator<Item = StmtId>) -> PResult<()> {
185 let (ret_var, ..) = self.parse_let_statement(stmts.next().unwrap())?;
186 self.local_map.insert(ret_var, Local::from_u32(0));
189 let (var, ty, span) = self.parse_let_statement(stmt)?;
190 let decl = LocalDecl::new(ty, span);
191 let local = self.body.local_decls.push(decl);
192 self.local_map.insert(var, local);
198 fn parse_let_statement(&mut self, stmt_id: StmtId) -> PResult<(LocalVarId, Ty<'tcx>, Span)> {
199 let pattern = match &self.thir[stmt_id].kind {
200 StmtKind::Let { pattern, .. } => pattern,
201 StmtKind::Expr { expr, .. } => {
202 return Err(self.expr_error(*expr, "let statement"));
206 self.parse_var(pattern)
209 fn parse_var(&mut self, mut pat: &Pat<'tcx>) -> PResult<(LocalVarId, Ty<'tcx>, Span)> {
210 // Make sure we throw out any `AscribeUserType` we find
213 PatKind::Binding { var, ty, .. } => break Ok((*var, *ty, pat.span)),
214 PatKind::AscribeUserType { subpattern, .. } => {
218 break Err(ParseError {
220 item_description: format!("{:?}", pat.kind),
221 expected: "local".to_string(),
228 fn parse_block_def(&self, expr_id: ExprId) -> PResult<BasicBlockData<'tcx>> {
229 let block = parse_by_kind!(self, expr_id, _, "basic block",
230 ExprKind::Block { block } => &self.thir[*block],
233 let mut data = BasicBlockData::new(None);
234 for stmt_id in &*block.stmts {
235 let stmt = self.statement_as_expr(*stmt_id)?;
236 let span = self.thir[stmt].span;
237 let statement = self.parse_statement(stmt)?;
238 data.statements.push(Statement {
239 source_info: SourceInfo { span, scope: self.source_scope },
244 let Some(trailing) = block.expr else {
245 return Err(self.expr_error(expr_id, "terminator"))
247 let span = self.thir[trailing].span;
248 let terminator = self.parse_terminator(trailing)?;
249 data.terminator = Some(Terminator {
250 source_info: SourceInfo { span, scope: self.source_scope },