diff options
Diffstat (limited to 'crates/ra_hir/src/expr.rs')
-rw-r--r-- | crates/ra_hir/src/expr.rs | 363 |
1 files changed, 298 insertions, 65 deletions
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs index 5cdcca082..5cf0f5e3f 100644 --- a/crates/ra_hir/src/expr.rs +++ b/crates/ra_hir/src/expr.rs | |||
@@ -4,7 +4,7 @@ use rustc_hash::FxHashMap; | |||
4 | 4 | ||
5 | use ra_arena::{Arena, RawId, impl_arena_id}; | 5 | use ra_arena::{Arena, RawId, impl_arena_id}; |
6 | use ra_db::{LocalSyntaxPtr, Cancelable}; | 6 | use ra_db::{LocalSyntaxPtr, Cancelable}; |
7 | use ra_syntax::ast::{self, AstNode, LoopBodyOwner, ArgListOwner}; | 7 | use ra_syntax::ast::{self, AstNode, LoopBodyOwner, ArgListOwner, NameOwner}; |
8 | 8 | ||
9 | use crate::{Path, type_ref::{Mutability, TypeRef}, Name, HirDatabase, DefId, Def, name::AsName}; | 9 | use crate::{Path, type_ref::{Mutability, TypeRef}, Name, HirDatabase, DefId, Def, name::AsName}; |
10 | 10 | ||
@@ -21,7 +21,7 @@ pub struct Body { | |||
21 | /// part of the function signature, the patterns are not (they don't change | 21 | /// part of the function signature, the patterns are not (they don't change |
22 | /// the external type of the function). | 22 | /// the external type of the function). |
23 | /// | 23 | /// |
24 | /// If this `ExprTable` is for the body of a constant, this will just be | 24 | /// If this `Body` is for the body of a constant, this will just be |
25 | /// empty. | 25 | /// empty. |
26 | args: Vec<PatId>, | 26 | args: Vec<PatId>, |
27 | /// The `ExprId` of the actual body expression. | 27 | /// The `ExprId` of the actual body expression. |
@@ -43,6 +43,43 @@ pub struct BodySyntaxMapping { | |||
43 | pat_syntax_mapping_back: FxHashMap<PatId, LocalSyntaxPtr>, | 43 | pat_syntax_mapping_back: FxHashMap<PatId, LocalSyntaxPtr>, |
44 | } | 44 | } |
45 | 45 | ||
46 | impl Body { | ||
47 | pub fn expr(&self, expr: ExprId) -> &Expr { | ||
48 | &self.exprs[expr] | ||
49 | } | ||
50 | |||
51 | pub fn pat(&self, pat: PatId) -> &Pat { | ||
52 | &self.pats[pat] | ||
53 | } | ||
54 | |||
55 | pub fn args(&self) -> &[PatId] { | ||
56 | &self.args | ||
57 | } | ||
58 | |||
59 | pub fn body_expr(&self) -> ExprId { | ||
60 | self.body_expr | ||
61 | } | ||
62 | } | ||
63 | |||
64 | impl BodySyntaxMapping { | ||
65 | pub fn expr_syntax(&self, expr: ExprId) -> Option<LocalSyntaxPtr> { | ||
66 | self.expr_syntax_mapping_back.get(&expr).cloned() | ||
67 | } | ||
68 | pub fn syntax_expr(&self, ptr: LocalSyntaxPtr) -> Option<ExprId> { | ||
69 | self.expr_syntax_mapping.get(&ptr).cloned() | ||
70 | } | ||
71 | pub fn pat_syntax(&self, pat: PatId) -> Option<LocalSyntaxPtr> { | ||
72 | self.pat_syntax_mapping_back.get(&pat).cloned() | ||
73 | } | ||
74 | pub fn syntax_pat(&self, ptr: LocalSyntaxPtr) -> Option<PatId> { | ||
75 | self.pat_syntax_mapping.get(&ptr).cloned() | ||
76 | } | ||
77 | |||
78 | pub fn body(&self) -> &Arc<Body> { | ||
79 | &self.body | ||
80 | } | ||
81 | } | ||
82 | |||
46 | #[derive(Debug, Clone, Eq, PartialEq)] | 83 | #[derive(Debug, Clone, Eq, PartialEq)] |
47 | pub enum Expr { | 84 | pub enum Expr { |
48 | /// This is produced if syntax tree does not have a required expression piece. | 85 | /// This is produced if syntax tree does not have a required expression piece. |
@@ -113,21 +150,26 @@ pub enum Expr { | |||
113 | expr: ExprId, | 150 | expr: ExprId, |
114 | op: Option<UnaryOp>, | 151 | op: Option<UnaryOp>, |
115 | }, | 152 | }, |
153 | Lambda { | ||
154 | args: Vec<PatId>, | ||
155 | arg_types: Vec<Option<TypeRef>>, | ||
156 | body: ExprId, | ||
157 | }, | ||
116 | } | 158 | } |
117 | 159 | ||
118 | pub type UnaryOp = ast::PrefixOp; | 160 | pub type UnaryOp = ast::PrefixOp; |
119 | 161 | ||
120 | #[derive(Debug, Clone, Eq, PartialEq)] | 162 | #[derive(Debug, Clone, Eq, PartialEq)] |
121 | pub struct MatchArm { | 163 | pub struct MatchArm { |
122 | pats: Vec<PatId>, | 164 | pub pats: Vec<PatId>, |
123 | // guard: Option<ExprId>, // TODO | 165 | // guard: Option<ExprId>, // TODO |
124 | expr: ExprId, | 166 | pub expr: ExprId, |
125 | } | 167 | } |
126 | 168 | ||
127 | #[derive(Debug, Clone, Eq, PartialEq)] | 169 | #[derive(Debug, Clone, Eq, PartialEq)] |
128 | pub struct StructLitField { | 170 | pub struct StructLitField { |
129 | name: Name, | 171 | pub name: Name, |
130 | expr: ExprId, | 172 | pub expr: ExprId, |
131 | } | 173 | } |
132 | 174 | ||
133 | #[derive(Debug, Clone, Eq, PartialEq)] | 175 | #[derive(Debug, Clone, Eq, PartialEq)] |
@@ -140,12 +182,118 @@ pub enum Statement { | |||
140 | Expr(ExprId), | 182 | Expr(ExprId), |
141 | } | 183 | } |
142 | 184 | ||
185 | impl Expr { | ||
186 | pub fn walk_child_exprs(&self, mut f: impl FnMut(ExprId)) { | ||
187 | match self { | ||
188 | Expr::Missing => {} | ||
189 | Expr::Path(_) => {} | ||
190 | Expr::If { | ||
191 | condition, | ||
192 | then_branch, | ||
193 | else_branch, | ||
194 | } => { | ||
195 | f(*condition); | ||
196 | f(*then_branch); | ||
197 | if let Some(else_branch) = else_branch { | ||
198 | f(*else_branch); | ||
199 | } | ||
200 | } | ||
201 | Expr::Block { statements, tail } => { | ||
202 | for stmt in statements { | ||
203 | match stmt { | ||
204 | Statement::Let { initializer, .. } => { | ||
205 | if let Some(expr) = initializer { | ||
206 | f(*expr); | ||
207 | } | ||
208 | } | ||
209 | Statement::Expr(e) => f(*e), | ||
210 | } | ||
211 | } | ||
212 | if let Some(expr) = tail { | ||
213 | f(*expr); | ||
214 | } | ||
215 | } | ||
216 | Expr::Loop { body } => f(*body), | ||
217 | Expr::While { condition, body } => { | ||
218 | f(*condition); | ||
219 | f(*body); | ||
220 | } | ||
221 | Expr::For { iterable, body, .. } => { | ||
222 | f(*iterable); | ||
223 | f(*body); | ||
224 | } | ||
225 | Expr::Call { callee, args } => { | ||
226 | f(*callee); | ||
227 | for arg in args { | ||
228 | f(*arg); | ||
229 | } | ||
230 | } | ||
231 | Expr::MethodCall { receiver, args, .. } => { | ||
232 | f(*receiver); | ||
233 | for arg in args { | ||
234 | f(*arg); | ||
235 | } | ||
236 | } | ||
237 | Expr::Match { expr, arms } => { | ||
238 | f(*expr); | ||
239 | for arm in arms { | ||
240 | f(arm.expr); | ||
241 | } | ||
242 | } | ||
243 | Expr::Continue => {} | ||
244 | Expr::Break { expr } | Expr::Return { expr } => { | ||
245 | if let Some(expr) = expr { | ||
246 | f(*expr); | ||
247 | } | ||
248 | } | ||
249 | Expr::StructLit { fields, spread, .. } => { | ||
250 | for field in fields { | ||
251 | f(field.expr); | ||
252 | } | ||
253 | if let Some(expr) = spread { | ||
254 | f(*expr); | ||
255 | } | ||
256 | } | ||
257 | Expr::Lambda { body, .. } => { | ||
258 | f(*body); | ||
259 | } | ||
260 | Expr::Field { expr, .. } | ||
261 | | Expr::Try { expr } | ||
262 | | Expr::Cast { expr, .. } | ||
263 | | Expr::Ref { expr, .. } | ||
264 | | Expr::UnaryOp { expr, .. } => { | ||
265 | f(*expr); | ||
266 | } | ||
267 | } | ||
268 | } | ||
269 | } | ||
270 | |||
143 | #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] | 271 | #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] |
144 | pub struct PatId(RawId); | 272 | pub struct PatId(RawId); |
145 | impl_arena_id!(PatId); | 273 | impl_arena_id!(PatId); |
146 | 274 | ||
147 | #[derive(Debug, Clone, Eq, PartialEq)] | 275 | #[derive(Debug, Clone, Eq, PartialEq)] |
148 | pub struct Pat; | 276 | pub enum Pat { |
277 | Missing, | ||
278 | Bind { | ||
279 | name: Name, | ||
280 | }, | ||
281 | TupleStruct { | ||
282 | path: Option<Path>, | ||
283 | args: Vec<PatId>, | ||
284 | }, | ||
285 | } | ||
286 | |||
287 | impl Pat { | ||
288 | pub fn walk_child_pats(&self, f: impl FnMut(PatId)) { | ||
289 | match self { | ||
290 | Pat::Missing | Pat::Bind { .. } => {} | ||
291 | Pat::TupleStruct { args, .. } => { | ||
292 | args.iter().map(|pat| *pat).for_each(f); | ||
293 | } | ||
294 | } | ||
295 | } | ||
296 | } | ||
149 | 297 | ||
150 | // Queries | 298 | // Queries |
151 | 299 | ||
@@ -163,6 +311,17 @@ struct ExprCollector { | |||
163 | } | 311 | } |
164 | 312 | ||
165 | impl ExprCollector { | 313 | impl ExprCollector { |
314 | fn new() -> Self { | ||
315 | ExprCollector { | ||
316 | exprs: Arena::default(), | ||
317 | pats: Arena::default(), | ||
318 | expr_syntax_mapping: FxHashMap::default(), | ||
319 | expr_syntax_mapping_back: FxHashMap::default(), | ||
320 | pat_syntax_mapping: FxHashMap::default(), | ||
321 | pat_syntax_mapping_back: FxHashMap::default(), | ||
322 | } | ||
323 | } | ||
324 | |||
166 | fn alloc_expr(&mut self, expr: Expr, syntax_ptr: LocalSyntaxPtr) -> ExprId { | 325 | fn alloc_expr(&mut self, expr: Expr, syntax_ptr: LocalSyntaxPtr) -> ExprId { |
167 | let id = self.exprs.alloc(expr); | 326 | let id = self.exprs.alloc(expr); |
168 | self.expr_syntax_mapping.insert(syntax_ptr, id); | 327 | self.expr_syntax_mapping.insert(syntax_ptr, id); |
@@ -177,30 +336,63 @@ impl ExprCollector { | |||
177 | id | 336 | id |
178 | } | 337 | } |
179 | 338 | ||
339 | fn empty_block(&mut self) -> ExprId { | ||
340 | let block = Expr::Block { | ||
341 | statements: Vec::new(), | ||
342 | tail: None, | ||
343 | }; | ||
344 | self.exprs.alloc(block) | ||
345 | } | ||
346 | |||
180 | fn collect_expr(&mut self, expr: ast::Expr) -> ExprId { | 347 | fn collect_expr(&mut self, expr: ast::Expr) -> ExprId { |
181 | let syntax_ptr = LocalSyntaxPtr::new(expr.syntax()); | 348 | let syntax_ptr = LocalSyntaxPtr::new(expr.syntax()); |
182 | match expr { | 349 | match expr { |
183 | ast::Expr::IfExpr(e) => { | 350 | ast::Expr::IfExpr(e) => { |
184 | let condition = if let Some(condition) = e.condition() { | 351 | if let Some(pat) = e.condition().and_then(|c| c.pat()) { |
185 | if condition.pat().is_none() { | 352 | // if let -- desugar to match |
353 | let pat = self.collect_pat(pat); | ||
354 | let match_expr = | ||
355 | self.collect_expr_opt(e.condition().expect("checked above").expr()); | ||
356 | let then_branch = self.collect_block_opt(e.then_branch()); | ||
357 | let else_branch = e | ||
358 | .else_branch() | ||
359 | .map(|e| self.collect_block(e)) | ||
360 | .unwrap_or_else(|| self.empty_block()); | ||
361 | let placeholder_pat = self.pats.alloc(Pat::Missing); | ||
362 | let arms = vec![ | ||
363 | MatchArm { | ||
364 | pats: vec![pat], | ||
365 | expr: then_branch, | ||
366 | }, | ||
367 | MatchArm { | ||
368 | pats: vec![placeholder_pat], | ||
369 | expr: else_branch, | ||
370 | }, | ||
371 | ]; | ||
372 | self.alloc_expr( | ||
373 | Expr::Match { | ||
374 | expr: match_expr, | ||
375 | arms, | ||
376 | }, | ||
377 | syntax_ptr, | ||
378 | ) | ||
379 | } else { | ||
380 | let condition = if let Some(condition) = e.condition() { | ||
186 | self.collect_expr_opt(condition.expr()) | 381 | self.collect_expr_opt(condition.expr()) |
187 | } else { | 382 | } else { |
188 | // TODO handle if let | 383 | self.exprs.alloc(Expr::Missing) |
189 | return self.alloc_expr(Expr::Missing, syntax_ptr); | 384 | }; |
190 | } | 385 | let then_branch = self.collect_block_opt(e.then_branch()); |
191 | } else { | 386 | let else_branch = e.else_branch().map(|e| self.collect_block(e)); |
192 | self.exprs.alloc(Expr::Missing) | 387 | self.alloc_expr( |
193 | }; | 388 | Expr::If { |
194 | let then_branch = self.collect_block_opt(e.then_branch()); | 389 | condition, |
195 | let else_branch = e.else_branch().map(|e| self.collect_block(e)); | 390 | then_branch, |
196 | self.alloc_expr( | 391 | else_branch, |
197 | Expr::If { | 392 | }, |
198 | condition, | 393 | syntax_ptr, |
199 | then_branch, | 394 | ) |
200 | else_branch, | 395 | } |
201 | }, | ||
202 | syntax_ptr, | ||
203 | ) | ||
204 | } | 396 | } |
205 | ast::Expr::BlockExpr(e) => self.collect_block_opt(e.block()), | 397 | ast::Expr::BlockExpr(e) => self.collect_block_opt(e.block()), |
206 | ast::Expr::LoopExpr(e) => { | 398 | ast::Expr::LoopExpr(e) => { |
@@ -368,18 +560,30 @@ impl ExprCollector { | |||
368 | let op = e.op(); | 560 | let op = e.op(); |
369 | self.alloc_expr(Expr::UnaryOp { expr, op }, syntax_ptr) | 561 | self.alloc_expr(Expr::UnaryOp { expr, op }, syntax_ptr) |
370 | } | 562 | } |
371 | 563 | ast::Expr::LambdaExpr(e) => { | |
372 | // We should never get to these because they're handled in MatchExpr resp. StructLit: | 564 | let mut args = Vec::new(); |
373 | ast::Expr::MatchArmList(_) | ast::Expr::MatchArm(_) | ast::Expr::MatchGuard(_) => { | 565 | let mut arg_types = Vec::new(); |
374 | panic!("collect_expr called on {:?}", expr) | 566 | if let Some(pl) = e.param_list() { |
375 | } | 567 | for param in pl.params() { |
376 | ast::Expr::NamedFieldList(_) | ast::Expr::NamedField(_) => { | 568 | let pat = self.collect_pat_opt(param.pat()); |
377 | panic!("collect_expr called on {:?}", expr) | 569 | let type_ref = param.type_ref().map(TypeRef::from_ast); |
570 | args.push(pat); | ||
571 | arg_types.push(type_ref); | ||
572 | } | ||
573 | } | ||
574 | let body = self.collect_expr_opt(e.body()); | ||
575 | self.alloc_expr( | ||
576 | Expr::Lambda { | ||
577 | args, | ||
578 | arg_types, | ||
579 | body, | ||
580 | }, | ||
581 | syntax_ptr, | ||
582 | ) | ||
378 | } | 583 | } |
379 | 584 | ||
380 | // TODO implement HIR for these: | 585 | // TODO implement HIR for these: |
381 | ast::Expr::Label(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), | 586 | ast::Expr::Label(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), |
382 | ast::Expr::LambdaExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), | ||
383 | ast::Expr::IndexExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), | 587 | ast::Expr::IndexExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), |
384 | ast::Expr::TupleExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), | 588 | ast::Expr::TupleExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), |
385 | ast::Expr::ArrayExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), | 589 | ast::Expr::ArrayExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), |
@@ -431,16 +635,31 @@ impl ExprCollector { | |||
431 | 635 | ||
432 | fn collect_pat(&mut self, pat: ast::Pat) -> PatId { | 636 | fn collect_pat(&mut self, pat: ast::Pat) -> PatId { |
433 | let syntax_ptr = LocalSyntaxPtr::new(pat.syntax()); | 637 | let syntax_ptr = LocalSyntaxPtr::new(pat.syntax()); |
434 | // TODO | 638 | match pat { |
435 | self.alloc_pat(Pat, syntax_ptr) | 639 | ast::Pat::BindPat(bp) => { |
640 | let name = bp | ||
641 | .name() | ||
642 | .map(|nr| nr.as_name()) | ||
643 | .unwrap_or_else(Name::missing); | ||
644 | self.alloc_pat(Pat::Bind { name }, syntax_ptr) | ||
645 | } | ||
646 | ast::Pat::TupleStructPat(p) => { | ||
647 | let path = p.path().and_then(Path::from_ast); | ||
648 | let args = p.args().map(|p| self.collect_pat(p)).collect(); | ||
649 | self.alloc_pat(Pat::TupleStruct { path, args }, syntax_ptr) | ||
650 | } | ||
651 | _ => { | ||
652 | // TODO | ||
653 | self.alloc_pat(Pat::Missing, syntax_ptr) | ||
654 | } | ||
655 | } | ||
436 | } | 656 | } |
437 | 657 | ||
438 | fn collect_pat_opt(&mut self, pat: Option<ast::Pat>) -> PatId { | 658 | fn collect_pat_opt(&mut self, pat: Option<ast::Pat>) -> PatId { |
439 | if let Some(pat) = pat { | 659 | if let Some(pat) = pat { |
440 | self.collect_pat(pat) | 660 | self.collect_pat(pat) |
441 | } else { | 661 | } else { |
442 | // TODO | 662 | self.pats.alloc(Pat::Missing) |
443 | self.pats.alloc(Pat) | ||
444 | } | 663 | } |
445 | } | 664 | } |
446 | 665 | ||
@@ -461,47 +680,61 @@ impl ExprCollector { | |||
461 | } | 680 | } |
462 | } | 681 | } |
463 | 682 | ||
683 | pub(crate) fn collect_fn_body_syntax(node: ast::FnDef) -> BodySyntaxMapping { | ||
684 | let mut collector = ExprCollector::new(); | ||
685 | |||
686 | let args = if let Some(param_list) = node.param_list() { | ||
687 | let mut args = Vec::new(); | ||
688 | |||
689 | if let Some(self_param) = param_list.self_param() { | ||
690 | let self_param = LocalSyntaxPtr::new( | ||
691 | self_param | ||
692 | .self_kw() | ||
693 | .expect("self param without self keyword") | ||
694 | .syntax(), | ||
695 | ); | ||
696 | let arg = collector.alloc_pat( | ||
697 | Pat::Bind { | ||
698 | name: Name::self_param(), | ||
699 | }, | ||
700 | self_param, | ||
701 | ); | ||
702 | args.push(arg); | ||
703 | } | ||
704 | |||
705 | for param in param_list.params() { | ||
706 | let pat = if let Some(pat) = param.pat() { | ||
707 | pat | ||
708 | } else { | ||
709 | continue; | ||
710 | }; | ||
711 | args.push(collector.collect_pat(pat)); | ||
712 | } | ||
713 | args | ||
714 | } else { | ||
715 | Vec::new() | ||
716 | }; | ||
717 | |||
718 | let body = collector.collect_block_opt(node.body()); | ||
719 | collector.into_body_syntax_mapping(args, body) | ||
720 | } | ||
721 | |||
464 | pub(crate) fn body_syntax_mapping( | 722 | pub(crate) fn body_syntax_mapping( |
465 | db: &impl HirDatabase, | 723 | db: &impl HirDatabase, |
466 | def_id: DefId, | 724 | def_id: DefId, |
467 | ) -> Cancelable<Arc<BodySyntaxMapping>> { | 725 | ) -> Cancelable<Arc<BodySyntaxMapping>> { |
468 | let def = def_id.resolve(db)?; | 726 | let def = def_id.resolve(db)?; |
469 | let mut collector = ExprCollector { | ||
470 | exprs: Arena::default(), | ||
471 | pats: Arena::default(), | ||
472 | expr_syntax_mapping: FxHashMap::default(), | ||
473 | expr_syntax_mapping_back: FxHashMap::default(), | ||
474 | pat_syntax_mapping: FxHashMap::default(), | ||
475 | pat_syntax_mapping_back: FxHashMap::default(), | ||
476 | }; | ||
477 | 727 | ||
478 | let (body, args) = match def { | 728 | let body_syntax_mapping = match def { |
479 | Def::Function(f) => { | 729 | Def::Function(f) => { |
480 | let node = f.syntax(db); | 730 | let node = f.syntax(db); |
481 | let node = node.borrowed(); | 731 | let node = node.borrowed(); |
482 | 732 | ||
483 | let args = if let Some(param_list) = node.param_list() { | 733 | collect_fn_body_syntax(node) |
484 | let mut args = Vec::new(); | ||
485 | // TODO self param | ||
486 | for param in param_list.params() { | ||
487 | let pat = if let Some(pat) = param.pat() { | ||
488 | pat | ||
489 | } else { | ||
490 | continue; | ||
491 | }; | ||
492 | args.push(collector.collect_pat(pat)); | ||
493 | } | ||
494 | args | ||
495 | } else { | ||
496 | Vec::new() | ||
497 | }; | ||
498 | |||
499 | let body = collector.collect_block_opt(node.body()); | ||
500 | (body, args) | ||
501 | } | 734 | } |
502 | // TODO: consts, etc. | 735 | // TODO: consts, etc. |
503 | _ => panic!("Trying to get body for item type without body"), | 736 | _ => panic!("Trying to get body for item type without body"), |
504 | }; | 737 | }; |
505 | 738 | ||
506 | Ok(Arc::new(collector.into_body_syntax_mapping(args, body))) | 739 | Ok(Arc::new(body_syntax_mapping)) |
507 | } | 740 | } |