File Coverage

blib/lib/Repl/Cmd/MathCmd.pm
Criterion Covered Total %
statement 58 89 65.1
branch 6 28 21.4
condition 1 3 33.3
subroutine 7 7 100.0
pod 0 3 0.0
total 72 130 55.3


line stmt bran cond sub pod time code
1             package Repl::Cmd::MathCmd;
2            
3 1     1   1440 use strict;
  1         2  
  1         41  
4 1     1   5 use warnings;
  1         2  
  1         32  
5            
6 1     1   526 use Repl::Spec::Types;
  1         3  
  1         118  
7 1     1   6 use Carp;
  1         2  
  1         1300  
8            
9             require Exporter;
10             our @ISA = qw(Exporter);
11             our @EXPORT_OK = qw();
12            
13             # Ordinary function, not a method.
14             sub registerCommands
15             {
16 1     1 0 8 my $repl = shift;
17 1         7 $repl->registerCommand("+", new Repl::Cmd::MathCmd("add"));
18 1         5 $repl->registerCommand("-", new Repl::Cmd::MathCmd("sub"));
19 1         3 $repl->registerCommand("*", new Repl::Cmd::MathCmd("mult"));
20 1         4 $repl->registerCommand("/", new Repl::Cmd::MathCmd("div"));
21 1         3 $repl->registerCommand("^", new Repl::Cmd::MathCmd("pow"));
22 1         4 $repl->registerCommand("fin", new Repl::Cmd::MathCmd("fin"));
23 1         2 $repl->registerCommand("float->int", new Repl::Cmd::MathCmd("toInt"));
24 1         4 $repl->registerCommand("zero?", new Repl::Cmd::MathCmd("isZero"));
25 1         10 $repl->registerCommand("<", new Repl::Cmd::MathCmd("lt"));
26 1         3 $repl->registerCommand("<~", new Repl::Cmd::MathCmd("le"));
27 1         2 $repl->registerCommand(">", new Repl::Cmd::MathCmd("gt"));
28 1         9 $repl->registerCommand(">~", new Repl::Cmd::MathCmd("ge"));
29            
30 1         6 my $parser = new Repl::Core::Parser();
31 1         6 $repl->evalExpr($parser->parseString("(defun fac (n) (if \$n (* \$n (fac (- \$n 1))) 1))"));
32             }
33            
34             sub new
35             {
36 12     12 0 15 my $invocant = shift;
37 12   33     35 my $class = ref($invocant) || $invocant;
38 12         12 my $type = shift;
39            
40 12         23 my $self= {};
41 12         23 $self->{TYPE} = $type;
42 12         49 return bless $self, $class;
43             }
44            
45             sub execute
46             {
47 51     51 0 54 my $self = shift;
48 51         45 my $ctx = shift;
49 51         48 my $args = shift;
50 51         78 my $type = $self->{TYPE};
51            
52             # Remove the command name.
53 51         117 my $command = shift @$args;
54            
55 51 100       140 if($type eq 'add')
    100          
    50          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
56             {
57             # Argument testing.
58 1         5 my $checked = ARRAY_NUMBER_TYPE->guard($args);
59            
60 1         2 my $total = 0;
61 1         3 foreach my $num (@$checked)
62             {
63 2         3 $total += $num;
64             }
65 1         4 return $total;
66             }
67             elsif($type eq 'sub')
68             {
69 30         83 my $checked = ARRAY_NUMBER_TYPE->guard($args);
70 30         38 my $checkedsize = scalar(@$checked);
71 30 50       55 croak sprintf("ERROR: Command '%s' expected at least one argument.", $command) if $checkedsize < 1;
72            
73 30         37 my $total = $checked->[0];
74 30         28 my $i = 1;
75 30         57 while ($i < $checkedsize)
76             {
77 30         41 $ total -= $checked->[$i];
78 30         75 $i = $i + 1;
79             }
80 30         102 return $total;
81             }
82             elsif($type eq 'mult')
83             {
84 20         59 my $checked = ARRAY_NUMBER_TYPE->guard($args);
85            
86 20         24 my $total = 1;
87 20         35 foreach my $num (@$checked)
88             {
89 40         60 $total *= $num;
90             }
91 20         71 return $total;
92             }
93             elsif($type eq 'div')
94             {
95 0           my $checked = ARRAY_NUMBER_TYPE->guard($args);
96 0           my $checkedsize = scalar(@$checked);
97 0 0         croak sprintf("ERROR: Command '%s' expected at least one argument.", $command) if $checkedsize < 1;
98            
99 0           my $total = $checked->[0];
100 0           my $i = 1;
101 0           while ($i < $checkedsize)
102             {
103 0           $total /= $checked->[$i];
104 0           $i = $i + 1;
105             }
106 0           return $total;
107             }
108             elsif($type eq 'pow')
109             {
110 0           my $arg1 = NUMBER_TYPE->guard($args->[0]);
111 0           my $arg2 = NUMBER_TYPE->guard($args->[1]);
112 0           return $arg1 ** $arg2;
113             }
114             elsif($type eq 'fin')
115             {
116 0           my $checked = NUMBER_TYPE->guard($args->[0]);
117 0           return sprintf ("%.2f", $checked);
118             }
119             elsif($type eq 'toInt')
120             {
121 0           my $checked = NUMBER_TYPE->guard($args->[0]);
122 0           return sprintf ("%.d", $checked);
123             }
124             elsif($type eq 'isZero')
125             {
126 0           my $checked = NUMBER_TYPE->guard($args->[0]);
127 0           return $checked == 0;
128             }
129             elsif($type eq 'lt')
130             {
131 0           my $arg1 = NUMBER_TYPE->guard($args->[0]);
132 0           my $arg2 = NUMBER_TYPE->guard($args->[1]);
133 0           return $arg1 < $arg2;
134             }
135             elsif($type eq 'le')
136             {
137 0           my $arg1 = NUMBER_TYPE->guard($args->[0]);
138 0           my $arg2 = NUMBER_TYPE->guard($args->[1]);
139 0           return $arg1 <= $arg2;
140             }
141             elsif($type eq 'gt')
142             {
143 0           my $arg1 = NUMBER_TYPE->guard($args->[0]);
144 0           my $arg2 = NUMBER_TYPE->guard($args->[1]);
145 0           return $arg1 > $arg2;
146             }
147             elsif($type eq 'ge')
148             {
149 0           my $arg1 = NUMBER_TYPE->guard($args->[0]);
150 0           my $arg2 = NUMBER_TYPE->guard($args->[1]);
151 0           return $arg1 >= $arg2;
152             }
153             else
154             {
155 0           croak sprintf("ERROR: Command '%s' internal error.", $command);
156             }
157             }
158            
159             1;