about summary refs log tree commit diff
path: root/src/test/run-pass/class-implements-multiple-ifaces.rs
blob: 968dfb07bf9e3e0778bf4640c5751a146e316705 (plain)
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
// xfail-test

use std;
import std::map::*;
import vec::*;
import dvec::{dvec, extensions};

enum furniture { chair, couch, bed }
enum body_part { finger, toe, nose, ear }

trait noisy {
  fn speak() -> int;
}

trait scratchy {
  fn scratch() -> option<furniture>;
}

trait bitey {
  fn bite() -> body_part;
}

fn vec_includes<T>(xs: ~[T], x: T) -> bool {
  for each(xs) |y| { if y == x { ret true; }}
  ret false;
}

// vtables other than the 1st one don't seem to work
class cat : noisy, scratchy, bitey {
  priv {
    let meows : @mut uint;
    let scratched : dvec<furniture>;
    let bite_counts : hashmap<body_part, uint>;

    fn meow() -> uint {
      debug!{"Meow: %u", *self.meows};
      *self.meows += 1u;
      if *self.meows % 5u == 0u {
          *self.how_hungry += 1;
      }
      *self.meows
    }
  }

  let how_hungry : @mut int;
  let name : str;

  new(in_x : uint, in_y : int, in_name: str)
    { self.meows = @mut in_x; self.how_hungry = @mut in_y;
      self.name = in_name; self.scratched = dvec();
      let hsher: hashfn<body_part> =
        fn@(p: body_part) -> uint { int::hash(p as int) };
      let eqer : eqfn<body_part> =
        fn@(p: body_part, q: body_part)  -> bool { p == q };
      let t : hashmap<body_part, uint> =
        hashmap::<body_part, uint>(hsher, eqer);
      self.bite_counts = t;
     do iter(~[finger, toe, nose, ear]) |p| {
          self.bite_counts.insert(p, 0u);
      };
    }

  fn speak() -> int { self.meow() as int }
  fn meow_count() -> uint { *self.meows }
  fn scratch() -> option<furniture> {
    let all = ~[chair, couch, bed];
    log(error, self.scratched);
    let mut rslt = none;
    for each(all) |thing| { if !self.scratched.contains(thing) {
          self.scratched.push(thing);
          ret some(thing); }}
    rslt
  }
  fn bite() -> body_part {
    error!{"In bite()"};
    let all = ~[toe, nose, ear];
    let mut min = finger;
    do iter(all) |next| {
      debug!{"min = %?", min};
        if self.bite_counts.get(next) < self.bite_counts.get(min) {
            min = next;
          }};
    self.bite_counts.insert(min, self.bite_counts.get(min) + 1u);
    debug!{"Bit %?", min};
    min
  }
}

fn annoy_neighbors<T: noisy>(critter: T) {
  for uint::range(0u, 10u) |i| {
      let what = critter.speak();
      debug!{"%u %d", i, what};
  }
}

fn bite_everything<T: bitey>(critter: T) -> bool {
  let mut left : ~[body_part] = ~[finger, toe, nose, ear];
  while vec::len(left) > 0u {
    let part = critter.bite();
    debug!{"%? %?", left, part};
    if vec_includes(left, part) {
        left = vec::filter(left, |p| p != part );
    }
    else {
      ret false;
    }
  }
  true
}

fn scratched_something<T: scratchy>(critter: T) -> bool {
  option::is_some(critter.scratch())
}

fn main() {
  let nyan : cat  = cat(0u, 2, "nyan");
  annoy_neighbors(nyan as noisy);
  assert(nyan.meow_count() == 10u);
  assert(bite_everything(nyan as bitey));
  assert(scratched_something(nyan as scratchy));
}