1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
|
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use syntax::ast;
use syntax::codemap::{Span};
use syntax::visit;
use syntax::visit::Visitor;
use std::local_data;
use extra;
pub fn time<T, U>(do_it: bool, what: &str, u: U, f: |U| -> T) -> T {
local_data_key!(depth: uint);
if !do_it { return f(u); }
let old = local_data::get(depth, |d| d.map(|a| *a).unwrap_or(0));
local_data::set(depth, old + 1);
let start = extra::time::precise_time_s();
let rv = f(u);
let end = extra::time::precise_time_s();
println!("{}time: {:3.3f} s\t{}", " ".repeat(old), end - start, what);
local_data::set(depth, old);
rv
}
pub fn indent<R>(op: || -> R) -> R {
// Use in conjunction with the log post-processor like `src/etc/indenter`
// to make debug output more readable.
debug!(">>");
let r = op();
debug!("<< (Result = {:?})", r);
r
}
pub struct _indenter {
_i: (),
}
impl Drop for _indenter {
fn drop(&mut self) { debug!("<<"); }
}
pub fn _indenter(_i: ()) -> _indenter {
_indenter {
_i: ()
}
}
pub fn indenter() -> _indenter {
debug!(">>");
_indenter(())
}
pub fn field_expr(f: ast::Field) -> @ast::Expr { return f.expr; }
pub fn field_exprs(fields: ~[ast::Field]) -> ~[@ast::Expr] {
fields.map(|f| f.expr)
}
struct LoopQueryVisitor<'a> {
p: 'a |&ast::Expr_| -> bool,
flag: bool,
}
impl<'a> Visitor<()> for LoopQueryVisitor<'a> {
fn visit_expr(&mut self, e: &ast::Expr, _: ()) {
self.flag |= (self.p)(&e.node);
match e.node {
// Skip inner loops, since a break in the inner loop isn't a
// break inside the outer loop
ast::ExprLoop(..) | ast::ExprWhile(..) => {}
_ => visit::walk_expr(self, e, ())
}
}
}
// Takes a predicate p, returns true iff p is true for any subexpressions
// of b -- skipping any inner loops (loop, while, loop_body)
pub fn loop_query(b: &ast::Block, p: |&ast::Expr_| -> bool) -> bool {
let mut v = LoopQueryVisitor {
p: p,
flag: false,
};
visit::walk_block(&mut v, b, ());
return v.flag;
}
struct BlockQueryVisitor<'a> {
p: 'a |&ast::Expr| -> bool,
flag: bool,
}
impl<'a> Visitor<()> for BlockQueryVisitor<'a> {
fn visit_expr(&mut self, e: &ast::Expr, _: ()) {
self.flag |= (self.p)(e);
visit::walk_expr(self, e, ())
}
}
// Takes a predicate p, returns true iff p is true for any subexpressions
// of b -- skipping any inner loops (loop, while, loop_body)
pub fn block_query(b: ast::P<ast::Block>, p: |&ast::Expr| -> bool) -> bool {
let mut v = BlockQueryVisitor {
p: p,
flag: false,
};
visit::walk_block(&mut v, b, ());
return v.flag;
}
pub fn local_rhs_span(l: &ast::Local, def: Span) -> Span {
match l.init {
Some(i) => return i.span,
_ => return def
}
}
pub fn pluralize(n: uint, s: ~str) -> ~str {
if n == 1 { s }
else { format!("{}s", s) }
}
|