(index<- )        ./librustc/middle/check_loop.rs

    git branch:    * master           5200215 auto merge of #14035 : alexcrichton/rust/experimental, r=huonw
    modified:    Wed Apr  9 17:27:02 2014
  1  // Copyright 2012 The Rust Project Developers. See the COPYRIGHT
  2  // file at the top-level directory of this distribution and at
  3  // http://rust-lang.org/COPYRIGHT.
  4  //
  5  // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
  6  // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
  7  // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
  8  // option. This file may not be copied, modified, or distributed
  9  // except according to those terms.
 10  
 11  use driver::session::Session;
 12  
 13  use syntax::ast;
 14  use syntax::codemap::Span;
 15  use syntax::visit::Visitor;
 16  use syntax::visit;
 17  
 18  #[deriving(Clone, Eq)]
 19  enum Context {
 20      Normal, Loop, Closure
 21  }
 22  
 23  struct CheckLoopVisitor<'a> {
 24      sess: &'a Session,
 25  }
 26  
 27  pub fn check_crate(sess: &Session, krate: &ast::Crate) {
 28      visit::walk_crate(&mut CheckLoopVisitor { sess: sess }, krate, Normal)
 29  }
 30  
 31  impl<'a> Visitor<Context> for CheckLoopVisitor<'a> {
 32      fn visit_item(&mut self, i&ast::Item, _cxContext) {
 33          visit::walk_item(self, i, Normal);
 34      }
 35  
 36      fn visit_expr(&mut self, e&ast::Expr, cx:Context) {
 37          match e.node {
 38              ast::ExprWhile(e, b) => {
 39                  self.visit_expr(e, cx);
 40                  self.visit_block(b, Loop);
 41              }
 42              ast::ExprLoop(b, _) => {
 43                  self.visit_block(b, Loop);
 44              }
 45              ast::ExprFnBlock(_, b) | ast::ExprProc(_, b) => {
 46                  self.visit_block(b, Closure);
 47              }
 48              ast::ExprBreak(_) => self.require_loop("break", cx, e.span),
 49              ast::ExprAgain(_) => self.require_loop("continue", cx, e.span),
 50              _ => visit::walk_expr(self, e, cx)
 51          }
 52      }
 53  }
 54  
 55  impl<'a> CheckLoopVisitor<'a> {
 56      fn require_loop(&self, name&str, cxContext, spanSpan) {
 57          match cx {
 58              Loop => {}
 59              Closure => {
 60                  self.sess.span_err(span, format!("`{}` inside of a closure", name));
 61              }
 62              Normal => {
 63                  self.sess.span_err(span, format!("`{}` outside of loop", name));
 64              }
 65          }
 66      }
 67  }