|
5 | 5 |
|
6 | 6 | use rustc::lint::*;
|
7 | 7 | use rustc::hir;
|
8 |
| -use rustc::hir::{Expr, Expr_, QPath, Ty_}; |
| 8 | +use rustc::hir::{Expr, Expr_, QPath, Ty_, Pat, PatKind, BindingAnnotation, StmtSemi, StmtExpr, StmtDecl, Decl_, Stmt}; |
9 | 9 | use rustc::hir::intravisit::{NestedVisitorMap, Visitor};
|
10 | 10 | use syntax::ast::{self, Attribute, LitKind, DUMMY_NODE_ID};
|
11 | 11 | use std::collections::HashMap;
|
@@ -322,10 +322,29 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor {
|
322 | 322 | self.current = body_pat;
|
323 | 323 | self.visit_block(body);
|
324 | 324 | },
|
325 |
| - Expr_::ExprMatch(ref _expr, ref _arms, desugaring) => { |
| 325 | + Expr_::ExprMatch(ref expr, ref arms, desugaring) => { |
326 | 326 | let des = desugaring_name(desugaring);
|
327 |
| - println!("Match(ref expr, ref arms, {}) = {};", des, current); |
328 |
| - println!(" // unimplemented: `ExprMatch` is not further destructured at the moment"); |
| 327 | + let expr_pat = self.next("expr"); |
| 328 | + let arms_pat = self.next("arms"); |
| 329 | + println!("Match(ref {}, ref {}, {}) = {};", expr_pat, arms_pat, des, current); |
| 330 | + self.current = expr_pat; |
| 331 | + self.visit_expr(expr); |
| 332 | + println!(" if {}.len() == {};", arms_pat, arms.len()); |
| 333 | + for (i, arm) in arms.iter().enumerate() { |
| 334 | + self.current = format!("{}[{}].body", arms_pat, i); |
| 335 | + self.visit_expr(&arm.body); |
| 336 | + if let Some(ref guard) = arm.guard { |
| 337 | + let guard_pat = self.next("guard"); |
| 338 | + println!(" if let Some(ref {}) = {}[{}].guard", guard_pat, arms_pat, i); |
| 339 | + self.current = guard_pat; |
| 340 | + self.visit_expr(guard); |
| 341 | + } |
| 342 | + println!(" if {}[{}].pats.len() == {};", arms_pat, i, arm.pats.len()); |
| 343 | + for (j, pat) in arm.pats.iter().enumerate() { |
| 344 | + self.current = format!("{}[{}].pats[{}]", arms_pat, i, j); |
| 345 | + self.visit_pat(pat); |
| 346 | + } |
| 347 | + } |
329 | 348 | },
|
330 | 349 | Expr_::ExprClosure(ref _capture_clause, ref _func, _, _, _) => {
|
331 | 350 | println!("Closure(ref capture_clause, ref func, _, _, _) = {};", current);
|
@@ -454,6 +473,160 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor {
|
454 | 473 | }
|
455 | 474 | }
|
456 | 475 |
|
| 476 | + fn visit_pat(&mut self, pat: &Pat) { |
| 477 | + print!(" if let PatKind::"); |
| 478 | + let current = format!("{}.node", self.current); |
| 479 | + match pat.node { |
| 480 | + PatKind::Wild => println!("Wild = {};", current), |
| 481 | + PatKind::Binding(anno, _, name, ref sub) => { |
| 482 | + let anno_pat = match anno { |
| 483 | + BindingAnnotation::Unannotated => "BindingAnnotation::Unannotated", |
| 484 | + BindingAnnotation::Mutable => "BindingAnnotation::Mutable", |
| 485 | + BindingAnnotation::Ref => "BindingAnnotation::Ref", |
| 486 | + BindingAnnotation::RefMut => "BindingAnnotation::RefMut", |
| 487 | + }; |
| 488 | + let name_pat = self.next("name"); |
| 489 | + if let Some(ref sub) = *sub { |
| 490 | + let sub_pat = self.next("sub"); |
| 491 | + println!("Binding({}, _, {}, Some(ref {})) = {};", anno_pat, name_pat, sub_pat, current); |
| 492 | + self.current = sub_pat; |
| 493 | + self.visit_pat(sub); |
| 494 | + } else { |
| 495 | + println!("Binding({}, _, {}, None) = {};", anno_pat, name_pat, current); |
| 496 | + } |
| 497 | + println!(" if {}.node.as_str() == \"{}\";", name_pat, name.node.as_str()); |
| 498 | + } |
| 499 | + PatKind::Struct(ref path, ref fields, ignore) => { |
| 500 | + let path_pat = self.next("path"); |
| 501 | + let fields_pat = self.next("fields"); |
| 502 | + println!("Struct(ref {}, ref {}, {}) = {};", path_pat, fields_pat, ignore, current); |
| 503 | + self.current = path_pat; |
| 504 | + self.print_qpath(path); |
| 505 | + println!(" if {}.len() == {};", fields_pat, fields.len()); |
| 506 | + println!(" // unimplemented: field checks"); |
| 507 | + } |
| 508 | + PatKind::TupleStruct(ref path, ref fields, skip_pos) => { |
| 509 | + let path_pat = self.next("path"); |
| 510 | + let fields_pat = self.next("fields"); |
| 511 | + println!("TupleStruct(ref {}, ref {}, {:?}) = {};", path_pat, fields_pat, skip_pos, current); |
| 512 | + self.current = path_pat; |
| 513 | + self.print_qpath(path); |
| 514 | + println!(" if {}.len() == {};", fields_pat, fields.len()); |
| 515 | + println!(" // unimplemented: field checks"); |
| 516 | + }, |
| 517 | + PatKind::Path(ref path) => { |
| 518 | + let path_pat = self.next("path"); |
| 519 | + println!("Path(ref {}) = {};", path_pat, current); |
| 520 | + self.current = path_pat; |
| 521 | + self.print_qpath(path); |
| 522 | + } |
| 523 | + PatKind::Tuple(ref fields, skip_pos) => { |
| 524 | + let fields_pat = self.next("fields"); |
| 525 | + println!("Tuple(ref {}, {:?}) = {};", fields_pat, skip_pos, current); |
| 526 | + println!(" if {}.len() == {};", fields_pat, fields.len()); |
| 527 | + println!(" // unimplemented: field checks"); |
| 528 | + } |
| 529 | + PatKind::Box(ref pat) => { |
| 530 | + let pat_pat = self.next("pat"); |
| 531 | + println!("Box(ref {}) = {};", pat_pat, current); |
| 532 | + self.current = pat_pat; |
| 533 | + self.visit_pat(pat); |
| 534 | + }, |
| 535 | + PatKind::Ref(ref pat, muta) => { |
| 536 | + let pat_pat = self.next("pat"); |
| 537 | + println!("Ref(ref {}, Mutability::{:?}) = {};", pat_pat, muta, current); |
| 538 | + self.current = pat_pat; |
| 539 | + self.visit_pat(pat); |
| 540 | + }, |
| 541 | + PatKind::Lit(ref lit_expr) => { |
| 542 | + let lit_expr_pat = self.next("lit_expr"); |
| 543 | + println!("Lit(ref {}) = {}", lit_expr_pat, current); |
| 544 | + self.current = lit_expr_pat; |
| 545 | + self.visit_expr(lit_expr); |
| 546 | + } |
| 547 | + PatKind::Range(ref start, ref end, end_kind) => { |
| 548 | + let start_pat = self.next("start"); |
| 549 | + let end_pat = self.next("end"); |
| 550 | + println!("Range(ref {}, ref {}, RangeEnd::{:?}) = {};", start_pat, end_pat, end_kind, current); |
| 551 | + self.current = start_pat; |
| 552 | + self.visit_expr(start); |
| 553 | + self.current = end_pat; |
| 554 | + self.visit_expr(end); |
| 555 | + } |
| 556 | + PatKind::Slice(ref start, ref middle, ref end) => { |
| 557 | + let start_pat = self.next("start"); |
| 558 | + let end_pat = self.next("end"); |
| 559 | + if let Some(ref middle) = middle { |
| 560 | + let middle_pat = self.next("middle"); |
| 561 | + println!("Slice(ref {}, Some(ref {}), ref {}) = {};", start_pat, middle_pat, end_pat, current); |
| 562 | + self.current = middle_pat; |
| 563 | + self.visit_pat(middle); |
| 564 | + } else { |
| 565 | + println!("Slice(ref {}, None, ref {}) = {};", start_pat, end_pat, current); |
| 566 | + } |
| 567 | + println!(" if {}.len() == {};", start_pat, start.len()); |
| 568 | + for (i, pat) in start.iter().enumerate() { |
| 569 | + self.current = format!("{}[{}]", start_pat, i); |
| 570 | + self.visit_pat(pat); |
| 571 | + } |
| 572 | + println!(" if {}.len() == {};", end_pat, end.len()); |
| 573 | + for (i, pat) in end.iter().enumerate() { |
| 574 | + self.current = format!("{}[{}]", end_pat, i); |
| 575 | + self.visit_pat(pat); |
| 576 | + } |
| 577 | + } |
| 578 | + } |
| 579 | + } |
| 580 | + |
| 581 | + fn visit_stmt(&mut self, s: &Stmt) { |
| 582 | + print!(" if let Stmt_::"); |
| 583 | + let current = format!("{}.node", self.current); |
| 584 | + match s.node { |
| 585 | + // Could be an item or a local (let) binding: |
| 586 | + StmtDecl(ref decl, _) => { |
| 587 | + let decl_pat = self.next("decl"); |
| 588 | + println!("StmtDecl(ref {}, _) = {}", decl_pat, current); |
| 589 | + print!(" if let Decl_::"); |
| 590 | + let current = format!("{}.node", decl_pat); |
| 591 | + match decl.node { |
| 592 | + // A local (let) binding: |
| 593 | + Decl_::DeclLocal(ref local) => { |
| 594 | + let local_pat = self.next("local"); |
| 595 | + println!("DeclLocal(ref {}) = {};", local_pat, current); |
| 596 | + if let Some(ref init) = local.init { |
| 597 | + let init_pat = self.next("init"); |
| 598 | + println!(" if let Some(ref {}) = {}.init", init_pat, local_pat); |
| 599 | + self.current = init_pat; |
| 600 | + self.visit_expr(init); |
| 601 | + } |
| 602 | + self.current = format!("{}.pat", local_pat); |
| 603 | + self.visit_pat(&local.pat); |
| 604 | + }, |
| 605 | + // An item binding: |
| 606 | + Decl_::DeclItem(_) => { |
| 607 | + println!("DeclItem(item_id) = {};", current); |
| 608 | + }, |
| 609 | + } |
| 610 | + } |
| 611 | + |
| 612 | + // Expr without trailing semi-colon (must have unit type): |
| 613 | + StmtExpr(ref e, _) => { |
| 614 | + let e_pat = self.next("e"); |
| 615 | + println!("StmtExpr(ref {}, _) = {}", e_pat, current); |
| 616 | + self.current = e_pat; |
| 617 | + self.visit_expr(e); |
| 618 | + }, |
| 619 | + |
| 620 | + // Expr with trailing semi-colon (may have any type): |
| 621 | + StmtSemi(ref e, _) => { |
| 622 | + let e_pat = self.next("e"); |
| 623 | + println!("StmtSemi(ref {}, _) = {}", e_pat, current); |
| 624 | + self.current = e_pat; |
| 625 | + self.visit_expr(e); |
| 626 | + }, |
| 627 | + } |
| 628 | + } |
| 629 | + |
457 | 630 | fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
|
458 | 631 | NestedVisitorMap::None
|
459 | 632 | }
|
|
0 commit comments