Catching up after the holidays.
[kakapo:kakapo.git] / src / Matchers / EqualsFloat.nqp
1 # Copyright (C) 2009, Austin Hastings. See accompanying LICENSE file, or 
2 # http://www.opensource.org/licenses/artistic-license-2.0.php for license.
3
4 module Matcher::EqualsFloat;
5 # TypeSafe matcher that matches if the target is the same as a preset value. This version compares floats with an approximation range.
6
7 use('Dumper');
8 Program::initload(:after('Matcher::TypeSafe'));
9
10 sub _initload() {
11         if our $_Initload_done { return 0; }
12         $_Initload_done := 1;
13         
14         my $class_name := 'Matcher::EqualsFloat';
15         
16         NOTE("Creating class ", $class_name);
17         Class::SUBCLASS($class_name,
18                 'Matcher::TypeSafe'
19         );
20         
21         Class::multi_method($class_name, 'matches_typesafe', :starting_with('_match_'));
22 }
23
24 method describe_failure($item, $description) {
25         return $description
26                 ~ $item
27                 ~ " differed by "
28                 ~ self.difference($item);
29 }
30
31 method describe_self($description) {
32         return $description 
33                 ~ "a Number equal to " ~ self.value;
34 }
35
36 method difference($item) {
37         my $difference := $item - self.value;
38         my $abs := Q:PIR {
39                 $P0 = find_lex '$difference'
40                 %r = abs $P0
41         };
42         return $abs;
43 }
44
45 method init(@children, %attributes) {
46         unless +@children {
47                 DIE("You must provide at least a target value for is-close-to matcher");
48         }
49         
50         self.value(@children.shift);
51         
52         if +@children {
53                 self.within(@children.shift);
54         }
55         else {
56                 if self.value != 0 {
57                         self.within(self.value * '0.00001');
58                 }
59                 else {
60                         self.within('0.00001');
61                 }
62         }
63 }
64
65 method _match_Float($item)              { self.match_scalar($item); }
66 method _match_Integer($item)            { self.match_scalar($item); }
67 method _match_String($item)             { self.match_scalar($item); }
68
69 # NB: cannot use _match_scalar because of mmd bug (TT#1133)
70 method match_scalar($item) {
71         if self.difference($item) <= self.within {
72                 return 1;
73         }
74         
75         return 0;
76 }
77
78 method value(*@value)                   { self._ATTR('value', @value); }
79 method within(*@value)                  { self._ATTR('within', @value); }