diff options
author | Aleksey Kladov <[email protected]> | 2019-09-03 07:40:34 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2019-09-03 07:41:21 +0100 |
commit | 4b51c92feeda0078033508ceee7345c6ac1a97e6 (patch) | |
tree | 652969521ed93d8b30d80bfd47f35f60d0a3d2a8 | |
parent | da850361ba22c78ed3579c33d6748735dcd2885c (diff) |
slightly simplify expr lowering flow
-rw-r--r-- | crates/ra_hir/src/db.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir/src/expr.rs | 33 | ||||
-rw-r--r-- | crates/ra_hir/src/expr/lower.rs | 228 |
3 files changed, 136 insertions, 129 deletions
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index f669ab969..7b7974f5b 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs | |||
@@ -169,13 +169,13 @@ pub trait HirDatabase: DefDatabase + AstDatabase { | |||
169 | #[salsa::invoke(crate::ty::generic_defaults_query)] | 169 | #[salsa::invoke(crate::ty::generic_defaults_query)] |
170 | fn generic_defaults(&self, def: GenericDef) -> Substs; | 170 | fn generic_defaults(&self, def: GenericDef) -> Substs; |
171 | 171 | ||
172 | #[salsa::invoke(crate::expr::lower::body_with_source_map_query)] | 172 | #[salsa::invoke(crate::expr::body_with_source_map_query)] |
173 | fn body_with_source_map( | 173 | fn body_with_source_map( |
174 | &self, | 174 | &self, |
175 | def: DefWithBody, | 175 | def: DefWithBody, |
176 | ) -> (Arc<crate::expr::Body>, Arc<crate::expr::BodySourceMap>); | 176 | ) -> (Arc<crate::expr::Body>, Arc<crate::expr::BodySourceMap>); |
177 | 177 | ||
178 | #[salsa::invoke(crate::expr::lower::body_hir_query)] | 178 | #[salsa::invoke(crate::expr::body_hir_query)] |
179 | fn body_hir(&self, def: DefWithBody) -> Arc<crate::expr::Body>; | 179 | fn body_hir(&self, def: DefWithBody) -> Arc<crate::expr::Body>; |
180 | 180 | ||
181 | #[salsa::invoke(crate::ty::method_resolution::CrateImplBlocks::impls_in_crate_query)] | 181 | #[salsa::invoke(crate::ty::method_resolution::CrateImplBlocks::impls_in_crate_query)] |
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs index bfd250f38..5f6a4b320 100644 --- a/crates/ra_hir/src/expr.rs +++ b/crates/ra_hir/src/expr.rs | |||
@@ -12,7 +12,7 @@ use crate::{ | |||
12 | path::GenericArgs, | 12 | path::GenericArgs, |
13 | ty::primitive::{UncertainFloatTy, UncertainIntTy}, | 13 | ty::primitive::{UncertainFloatTy, UncertainIntTy}, |
14 | type_ref::{Mutability, TypeRef}, | 14 | type_ref::{Mutability, TypeRef}, |
15 | DefWithBody, Either, HirDatabase, Name, Path, Resolver, | 15 | DefWithBody, Either, HasSource, HirDatabase, Name, Path, Resolver, |
16 | }; | 16 | }; |
17 | 17 | ||
18 | pub use self::scope::ExprScopes; | 18 | pub use self::scope::ExprScopes; |
@@ -524,3 +524,34 @@ impl Pat { | |||
524 | } | 524 | } |
525 | } | 525 | } |
526 | } | 526 | } |
527 | |||
528 | // Queries | ||
529 | pub(crate) fn body_with_source_map_query( | ||
530 | db: &impl HirDatabase, | ||
531 | def: DefWithBody, | ||
532 | ) -> (Arc<Body>, Arc<BodySourceMap>) { | ||
533 | let mut params = None; | ||
534 | |||
535 | let (file_id, body) = match def { | ||
536 | DefWithBody::Function(f) => { | ||
537 | let src = f.source(db); | ||
538 | params = src.ast.param_list(); | ||
539 | (src.file_id, src.ast.body().map(ast::Expr::from)) | ||
540 | } | ||
541 | DefWithBody::Const(c) => { | ||
542 | let src = c.source(db); | ||
543 | (src.file_id, src.ast.body()) | ||
544 | } | ||
545 | DefWithBody::Static(s) => { | ||
546 | let src = s.source(db); | ||
547 | (src.file_id, src.ast.body()) | ||
548 | } | ||
549 | }; | ||
550 | |||
551 | let (body, source_map) = lower::lower(db, def.resolver(db), file_id, def, params, body); | ||
552 | (Arc::new(body), Arc::new(source_map)) | ||
553 | } | ||
554 | |||
555 | pub(crate) fn body_hir_query(db: &impl HirDatabase, def: DefWithBody) -> Arc<Body> { | ||
556 | db.body_with_source_map(def).0 | ||
557 | } | ||
diff --git a/crates/ra_hir/src/expr/lower.rs b/crates/ra_hir/src/expr/lower.rs index f6a75a379..7b3e55b7e 100644 --- a/crates/ra_hir/src/expr/lower.rs +++ b/crates/ra_hir/src/expr/lower.rs | |||
@@ -1,5 +1,3 @@ | |||
1 | use std::sync::Arc; | ||
2 | |||
3 | use ra_arena::Arena; | 1 | use ra_arena::Arena; |
4 | use ra_syntax::{ | 2 | use ra_syntax::{ |
5 | ast::{ | 3 | ast::{ |
@@ -15,8 +13,8 @@ use crate::{ | |||
15 | path::GenericArgs, | 13 | path::GenericArgs, |
16 | ty::primitive::{FloatTy, IntTy, UncertainFloatTy, UncertainIntTy}, | 14 | ty::primitive::{FloatTy, IntTy, UncertainFloatTy, UncertainIntTy}, |
17 | type_ref::TypeRef, | 15 | type_ref::TypeRef, |
18 | DefWithBody, Either, HasSource, HirDatabase, HirFileId, MacroCallLoc, MacroFileKind, | 16 | DefWithBody, Either, HirDatabase, HirFileId, MacroCallLoc, MacroFileKind, Mutability, Path, |
19 | Mutability, Path, Resolver, | 17 | Resolver, |
20 | }; | 18 | }; |
21 | 19 | ||
22 | use super::{ | 20 | use super::{ |
@@ -24,14 +22,33 @@ use super::{ | |||
24 | LogicOp, MatchArm, Ordering, Pat, PatId, PatPtr, RecordFieldPat, RecordLitField, Statement, | 22 | LogicOp, MatchArm, Ordering, Pat, PatId, PatPtr, RecordFieldPat, RecordLitField, Statement, |
25 | }; | 23 | }; |
26 | 24 | ||
27 | pub(crate) struct ExprCollector<DB> { | 25 | pub(super) fn lower( |
28 | db: DB, | 26 | db: &impl HirDatabase, |
27 | resolver: Resolver, | ||
28 | file_id: HirFileId, | ||
29 | owner: DefWithBody, | 29 | owner: DefWithBody, |
30 | exprs: Arena<ExprId, Expr>, | 30 | params: Option<ast::ParamList>, |
31 | pats: Arena<PatId, Pat>, | 31 | body: Option<ast::Expr>, |
32 | source_map: BodySourceMap, | 32 | ) -> (Body, BodySourceMap) { |
33 | params: Vec<PatId>, | 33 | ExprCollector { |
34 | body_expr: Option<ExprId>, | 34 | resolver, |
35 | db, | ||
36 | original_file_id: file_id, | ||
37 | current_file_id: file_id, | ||
38 | source_map: BodySourceMap::default(), | ||
39 | body: Body { | ||
40 | owner, | ||
41 | exprs: Arena::default(), | ||
42 | pats: Arena::default(), | ||
43 | params: Vec::new(), | ||
44 | body_expr: ExprId((!0).into()), | ||
45 | }, | ||
46 | } | ||
47 | .collect(params, body) | ||
48 | } | ||
49 | |||
50 | struct ExprCollector<DB> { | ||
51 | db: DB, | ||
35 | resolver: Resolver, | 52 | resolver: Resolver, |
36 | // Expr collector expands macros along the way. original points to the file | 53 | // Expr collector expands macros along the way. original points to the file |
37 | // we started with, current points to the current macro expansion. source | 54 | // we started with, current points to the current macro expansion. source |
@@ -39,38 +56,73 @@ pub(crate) struct ExprCollector<DB> { | |||
39 | // current == original (see #1196) | 56 | // current == original (see #1196) |
40 | original_file_id: HirFileId, | 57 | original_file_id: HirFileId, |
41 | current_file_id: HirFileId, | 58 | current_file_id: HirFileId, |
59 | |||
60 | body: Body, | ||
61 | source_map: BodySourceMap, | ||
42 | } | 62 | } |
43 | 63 | ||
44 | impl<'a, DB> ExprCollector<&'a DB> | 64 | impl<'a, DB> ExprCollector<&'a DB> |
45 | where | 65 | where |
46 | DB: HirDatabase, | 66 | DB: HirDatabase, |
47 | { | 67 | { |
48 | fn new(owner: DefWithBody, file_id: HirFileId, resolver: Resolver, db: &'a DB) -> Self { | 68 | fn collect( |
49 | ExprCollector { | 69 | mut self, |
50 | owner, | 70 | param_list: Option<ast::ParamList>, |
51 | resolver, | 71 | body: Option<ast::Expr>, |
52 | db, | 72 | ) -> (Body, BodySourceMap) { |
53 | exprs: Arena::default(), | 73 | if let Some(param_list) = param_list { |
54 | pats: Arena::default(), | 74 | if let Some(self_param) = param_list.self_param() { |
55 | source_map: BodySourceMap::default(), | 75 | let ptr = AstPtr::new(&self_param); |
56 | params: Vec::new(), | 76 | let param_pat = self.alloc_pat( |
57 | body_expr: None, | 77 | Pat::Bind { |
58 | original_file_id: file_id, | 78 | name: SELF_PARAM, |
59 | current_file_id: file_id, | 79 | mode: BindingAnnotation::Unannotated, |
60 | } | 80 | subpat: None, |
81 | }, | ||
82 | Either::B(ptr), | ||
83 | ); | ||
84 | self.body.params.push(param_pat); | ||
85 | } | ||
86 | |||
87 | for param in param_list.params() { | ||
88 | let pat = match param.pat() { | ||
89 | None => continue, | ||
90 | Some(pat) => pat, | ||
91 | }; | ||
92 | let param_pat = self.collect_pat(pat); | ||
93 | self.body.params.push(param_pat); | ||
94 | } | ||
95 | }; | ||
96 | |||
97 | self.body.body_expr = self.collect_expr_opt(body); | ||
98 | (self.body, self.source_map) | ||
61 | } | 99 | } |
100 | |||
62 | fn alloc_expr(&mut self, expr: Expr, ptr: AstPtr<ast::Expr>) -> ExprId { | 101 | fn alloc_expr(&mut self, expr: Expr, ptr: AstPtr<ast::Expr>) -> ExprId { |
63 | let ptr = Either::A(ptr); | 102 | let ptr = Either::A(ptr); |
64 | let id = self.exprs.alloc(expr); | 103 | let id = self.body.exprs.alloc(expr); |
104 | if self.current_file_id == self.original_file_id { | ||
105 | self.source_map.expr_map.insert(ptr, id); | ||
106 | self.source_map.expr_map_back.insert(id, ptr); | ||
107 | } | ||
108 | id | ||
109 | } | ||
110 | // deshugared exprs don't have ptr, that's wrong and should be fixed | ||
111 | // somehow. | ||
112 | fn alloc_expr_desugared(&mut self, expr: Expr) -> ExprId { | ||
113 | self.body.exprs.alloc(expr) | ||
114 | } | ||
115 | fn alloc_expr_field_shorthand(&mut self, expr: Expr, ptr: AstPtr<ast::RecordField>) -> ExprId { | ||
116 | let ptr = Either::B(ptr); | ||
117 | let id = self.body.exprs.alloc(expr); | ||
65 | if self.current_file_id == self.original_file_id { | 118 | if self.current_file_id == self.original_file_id { |
66 | self.source_map.expr_map.insert(ptr, id); | 119 | self.source_map.expr_map.insert(ptr, id); |
67 | self.source_map.expr_map_back.insert(id, ptr); | 120 | self.source_map.expr_map_back.insert(id, ptr); |
68 | } | 121 | } |
69 | id | 122 | id |
70 | } | 123 | } |
71 | |||
72 | fn alloc_pat(&mut self, pat: Pat, ptr: PatPtr) -> PatId { | 124 | fn alloc_pat(&mut self, pat: Pat, ptr: PatPtr) -> PatId { |
73 | let id = self.pats.alloc(pat); | 125 | let id = self.body.pats.alloc(pat); |
74 | 126 | ||
75 | if self.current_file_id == self.original_file_id { | 127 | if self.current_file_id == self.original_file_id { |
76 | self.source_map.pat_map.insert(ptr, id); | 128 | self.source_map.pat_map.insert(ptr, id); |
@@ -82,7 +134,15 @@ where | |||
82 | 134 | ||
83 | fn empty_block(&mut self) -> ExprId { | 135 | fn empty_block(&mut self) -> ExprId { |
84 | let block = Expr::Block { statements: Vec::new(), tail: None }; | 136 | let block = Expr::Block { statements: Vec::new(), tail: None }; |
85 | self.exprs.alloc(block) | 137 | self.body.exprs.alloc(block) |
138 | } | ||
139 | |||
140 | fn missing_expr(&mut self) -> ExprId { | ||
141 | self.body.exprs.alloc(Expr::Missing) | ||
142 | } | ||
143 | |||
144 | fn missing_pat(&mut self) -> PatId { | ||
145 | self.body.pats.alloc(Pat::Missing) | ||
86 | } | 146 | } |
87 | 147 | ||
88 | fn collect_expr(&mut self, expr: ast::Expr) -> ExprId { | 148 | fn collect_expr(&mut self, expr: ast::Expr) -> ExprId { |
@@ -100,14 +160,14 @@ where | |||
100 | }); | 160 | }); |
101 | 161 | ||
102 | let condition = match e.condition() { | 162 | let condition = match e.condition() { |
103 | None => self.exprs.alloc(Expr::Missing), | 163 | None => self.missing_expr(), |
104 | Some(condition) => match condition.pat() { | 164 | Some(condition) => match condition.pat() { |
105 | None => self.collect_expr_opt(condition.expr()), | 165 | None => self.collect_expr_opt(condition.expr()), |
106 | // if let -- desugar to match | 166 | // if let -- desugar to match |
107 | Some(pat) => { | 167 | Some(pat) => { |
108 | let pat = self.collect_pat(pat); | 168 | let pat = self.collect_pat(pat); |
109 | let match_expr = self.collect_expr_opt(condition.expr()); | 169 | let match_expr = self.collect_expr_opt(condition.expr()); |
110 | let placeholder_pat = self.pats.alloc(Pat::Missing); | 170 | let placeholder_pat = self.missing_pat(); |
111 | let arms = vec![ | 171 | let arms = vec![ |
112 | MatchArm { pats: vec![pat], expr: then_branch, guard: None }, | 172 | MatchArm { pats: vec![pat], expr: then_branch, guard: None }, |
113 | MatchArm { | 173 | MatchArm { |
@@ -137,7 +197,7 @@ where | |||
137 | let body = self.collect_block_opt(e.loop_body()); | 197 | let body = self.collect_block_opt(e.loop_body()); |
138 | 198 | ||
139 | let condition = match e.condition() { | 199 | let condition = match e.condition() { |
140 | None => self.exprs.alloc(Expr::Missing), | 200 | None => self.missing_expr(), |
141 | Some(condition) => match condition.pat() { | 201 | Some(condition) => match condition.pat() { |
142 | None => self.collect_expr_opt(condition.expr()), | 202 | None => self.collect_expr_opt(condition.expr()), |
143 | // if let -- desugar to match | 203 | // if let -- desugar to match |
@@ -145,14 +205,14 @@ where | |||
145 | tested_by!(infer_while_let); | 205 | tested_by!(infer_while_let); |
146 | let pat = self.collect_pat(pat); | 206 | let pat = self.collect_pat(pat); |
147 | let match_expr = self.collect_expr_opt(condition.expr()); | 207 | let match_expr = self.collect_expr_opt(condition.expr()); |
148 | let placeholder_pat = self.pats.alloc(Pat::Missing); | 208 | let placeholder_pat = self.missing_pat(); |
149 | let break_ = self.exprs.alloc(Expr::Break { expr: None }); | 209 | let break_ = self.alloc_expr_desugared(Expr::Break { expr: None }); |
150 | let arms = vec![ | 210 | let arms = vec![ |
151 | MatchArm { pats: vec![pat], expr: body, guard: None }, | 211 | MatchArm { pats: vec![pat], expr: body, guard: None }, |
152 | MatchArm { pats: vec![placeholder_pat], expr: break_, guard: None }, | 212 | MatchArm { pats: vec![placeholder_pat], expr: break_, guard: None }, |
153 | ]; | 213 | ]; |
154 | let match_expr = | 214 | let match_expr = |
155 | self.exprs.alloc(Expr::Match { expr: match_expr, arms }); | 215 | self.alloc_expr_desugared(Expr::Match { expr: match_expr, arms }); |
156 | return self.alloc_expr(Expr::Loop { body: match_expr }, syntax_ptr); | 216 | return self.alloc_expr(Expr::Loop { body: match_expr }, syntax_ptr); |
157 | } | 217 | } |
158 | }, | 218 | }, |
@@ -247,13 +307,12 @@ where | |||
247 | self.collect_expr(e) | 307 | self.collect_expr(e) |
248 | } else if let Some(nr) = field.name_ref() { | 308 | } else if let Some(nr) = field.name_ref() { |
249 | // field shorthand | 309 | // field shorthand |
250 | let id = self.exprs.alloc(Expr::Path(Path::from_name_ref(&nr))); | 310 | self.alloc_expr_field_shorthand( |
251 | let ptr = Either::B(AstPtr::new(&field)); | 311 | Expr::Path(Path::from_name_ref(&nr)), |
252 | self.source_map.expr_map.insert(ptr, id); | 312 | AstPtr::new(&field), |
253 | self.source_map.expr_map_back.insert(id, ptr); | 313 | ) |
254 | id | ||
255 | } else { | 314 | } else { |
256 | self.exprs.alloc(Expr::Missing) | 315 | self.missing_expr() |
257 | }, | 316 | }, |
258 | }) | 317 | }) |
259 | .collect(); | 318 | .collect(); |
@@ -420,7 +479,7 @@ where | |||
420 | if let Some(expr) = expr { | 479 | if let Some(expr) = expr { |
421 | self.collect_expr(expr) | 480 | self.collect_expr(expr) |
422 | } else { | 481 | } else { |
423 | self.exprs.alloc(Expr::Missing) | 482 | self.missing_expr() |
424 | } | 483 | } |
425 | } | 484 | } |
426 | 485 | ||
@@ -450,7 +509,7 @@ where | |||
450 | if let Some(block) = expr { | 509 | if let Some(block) = expr { |
451 | self.collect_block(block) | 510 | self.collect_block(block) |
452 | } else { | 511 | } else { |
453 | self.exprs.alloc(Expr::Missing) | 512 | self.missing_expr() |
454 | } | 513 | } |
455 | } | 514 | } |
456 | 515 | ||
@@ -519,60 +578,9 @@ where | |||
519 | if let Some(pat) = pat { | 578 | if let Some(pat) = pat { |
520 | self.collect_pat(pat) | 579 | self.collect_pat(pat) |
521 | } else { | 580 | } else { |
522 | self.pats.alloc(Pat::Missing) | 581 | self.missing_pat() |
523 | } | 582 | } |
524 | } | 583 | } |
525 | |||
526 | fn collect_const_body(&mut self, node: ast::ConstDef) { | ||
527 | let body = self.collect_expr_opt(node.body()); | ||
528 | self.body_expr = Some(body); | ||
529 | } | ||
530 | |||
531 | fn collect_static_body(&mut self, node: ast::StaticDef) { | ||
532 | let body = self.collect_expr_opt(node.body()); | ||
533 | self.body_expr = Some(body); | ||
534 | } | ||
535 | |||
536 | fn collect_fn_body(&mut self, node: ast::FnDef) { | ||
537 | if let Some(param_list) = node.param_list() { | ||
538 | if let Some(self_param) = param_list.self_param() { | ||
539 | let ptr = AstPtr::new(&self_param); | ||
540 | let param_pat = self.alloc_pat( | ||
541 | Pat::Bind { | ||
542 | name: SELF_PARAM, | ||
543 | mode: BindingAnnotation::Unannotated, | ||
544 | subpat: None, | ||
545 | }, | ||
546 | Either::B(ptr), | ||
547 | ); | ||
548 | self.params.push(param_pat); | ||
549 | } | ||
550 | |||
551 | for param in param_list.params() { | ||
552 | let pat = if let Some(pat) = param.pat() { | ||
553 | pat | ||
554 | } else { | ||
555 | continue; | ||
556 | }; | ||
557 | let param_pat = self.collect_pat(pat); | ||
558 | self.params.push(param_pat); | ||
559 | } | ||
560 | }; | ||
561 | |||
562 | let body = self.collect_block_opt(node.body()); | ||
563 | self.body_expr = Some(body); | ||
564 | } | ||
565 | |||
566 | fn finish(self) -> (Body, BodySourceMap) { | ||
567 | let body = Body { | ||
568 | owner: self.owner, | ||
569 | exprs: self.exprs, | ||
570 | pats: self.pats, | ||
571 | params: self.params, | ||
572 | body_expr: self.body_expr.expect("A body should have been collected"), | ||
573 | }; | ||
574 | (body, self.source_map) | ||
575 | } | ||
576 | } | 584 | } |
577 | 585 | ||
578 | impl From<ast::BinOp> for BinaryOp { | 586 | impl From<ast::BinOp> for BinaryOp { |
@@ -618,35 +626,3 @@ impl From<ast::BinOp> for BinaryOp { | |||
618 | } | 626 | } |
619 | } | 627 | } |
620 | } | 628 | } |
621 | |||
622 | pub(crate) fn body_with_source_map_query( | ||
623 | db: &impl HirDatabase, | ||
624 | def: DefWithBody, | ||
625 | ) -> (Arc<Body>, Arc<BodySourceMap>) { | ||
626 | let mut collector; | ||
627 | |||
628 | match def { | ||
629 | DefWithBody::Const(ref c) => { | ||
630 | let src = c.source(db); | ||
631 | collector = ExprCollector::new(def, src.file_id, def.resolver(db), db); | ||
632 | collector.collect_const_body(src.ast) | ||
633 | } | ||
634 | DefWithBody::Function(ref f) => { | ||
635 | let src = f.source(db); | ||
636 | collector = ExprCollector::new(def, src.file_id, def.resolver(db), db); | ||
637 | collector.collect_fn_body(src.ast) | ||
638 | } | ||
639 | DefWithBody::Static(ref s) => { | ||
640 | let src = s.source(db); | ||
641 | collector = ExprCollector::new(def, src.file_id, def.resolver(db), db); | ||
642 | collector.collect_static_body(src.ast) | ||
643 | } | ||
644 | } | ||
645 | |||
646 | let (body, source_map) = collector.finish(); | ||
647 | (Arc::new(body), Arc::new(source_map)) | ||
648 | } | ||
649 | |||
650 | pub(crate) fn body_hir_query(db: &impl HirDatabase, def: DefWithBody) -> Arc<Body> { | ||
651 | db.body_with_source_map(def).0 | ||
652 | } | ||