File Coverage

blib/lib/VM/Dreamer/Instructions.pm
Criterion Covered Total %
statement 12 60 20.0
branch 0 8 0.0
condition 0 3 0.0
subroutine 4 15 26.6
pod 11 11 100.0
total 27 97 27.8


line stmt bran cond sub pod time code
1             package VM::Dreamer::Instructions;
2              
3 1     1   2979 use strict;
  1         2  
  1         32  
4 1     1   4 use warnings;
  1         1  
  1         44  
5              
6             our $VERSION = '0.851';
7              
8 1     1   533 use VM::Dreamer::IO qw( get_valid_input_from_user add_input_to_inbox shift_inbox_to_memory add_to_outbox shift_outbox_to_user );
  1         3  
  1         91  
9 1     1   6 use VM::Dreamer::Util qw( arrayify_string stringify_array add_two_arrays subtract_two_arrays );
  1         2  
  1         827  
10              
11             require Exporter;
12              
13             our @ISA = qw(Exporter);
14             our @EXPORT_OK = qw( input_to_mb output_from_mb store load add subtract branch_always branch_if_zero branch_if_positive halt );
15              
16             sub input_to_mb {
17 0     0 1   my ( $machine, $operand ) = @_;
18              
19 0           my $input = get_valid_input_from_user($machine);
20              
21 0           add_input_to_inbox( $machine, $input );
22              
23 0           shift_inbox_to_memory( $machine, $operand );
24              
25 0           return 0;
26             }
27              
28             sub output_from_mb {
29 0     0 1   my ( $machine, $operand ) = @_;
30              
31 0           add_to_outbox( $machine, $operand );
32              
33 0           shift_outbox_to_user($machine);
34              
35 0           return 0;
36             }
37              
38             sub store {
39 0     0 1   my ( $machine, $operand ) = @_;
40              
41 0           $machine->{memory}->{$operand} = stringify_array( $machine->{accumulator} );
42              
43 0           return 0;
44              
45             # Assuming that operand is a valid mailbox value
46             }
47              
48             sub load {
49 0     0 1   my ( $machine, $operand ) = @_;
50              
51 0 0         if ( $machine->{memory}->{$operand} ) {
52 0           $machine->{accumulator} = arrayify_string( $machine->{memory}->{$operand} );
53 0           $machine->{n_flag} = 0;
54             }
55             else {
56 0           die "No value stored at address $operand to load onto the accumulator\n";
57             }
58              
59 0           return 0;
60             }
61              
62             sub add {
63 0     0 1   my ( $machine, $operand ) = @_;
64              
65 0           my $augend = $machine->{accumulator};
66 0           my $addend = arrayify_string( $machine->{memory}->{$operand} );
67              
68 0           $machine->{accumulator} = add_two_arrays( $augend, $addend, $machine->{meta}->{greatest}->{digit} );
69              
70 0           return 0;
71             }
72              
73             sub subtract {
74 0     0 1   my ( $machine, $operand ) = @_;
75              
76 0           my $minuend = $machine->{accumulator};
77 0           my $subtrahend = arrayify_string( $machine->{memory}->{$operand} );
78              
79 0           ( $machine->{accumulator}, $machine->{n_flag} ) = subtract_two_arrays( $minuend, $subtrahend, $machine->{meta}->{greatest}->{digit} );
80              
81 0           return 0;
82             }
83              
84             sub branch_always {
85 0     0 1   my ( $machine, $operand ) = @_;
86              
87 0           $machine->{counter} = arrayify_string($operand);
88              
89 0           return 0;
90             }
91              
92             sub branch_if_zero {
93 0     0 1   my ( $machine, $operand ) = @_;
94              
95 0           my $accumulator = stringify_array( $machine->{accumulator} );
96              
97 0 0         if ( $accumulator == 0 ) {
98 0           $machine->{counter} = arrayify_string($operand);
99             }
100              
101             # in Perl, a string of zeros is treated as the number 0 when used
102             # in numeric context, e.g. '000' == 0 would be true
103              
104 0           return 0;
105             }
106              
107             sub branch_if_negative {
108 0     0 1   my ( $machine, $operand ) = @_;
109              
110 0 0         if ( $machine->{n_flag} == 1 ) {
111 0           $machine->{counter} = arrayify_string($operand);
112             }
113              
114 0           return 0;
115             }
116              
117             sub branch_if_positive {
118 0     0 1   my ( $machine, $operand ) = @_;
119              
120 0           my $accumulator = stringify_array( $machine->{counter} );
121              
122 0 0 0       if ( $accumulator > 0 && $machine->{n_flag} == 0 ) {
123 0           $machine->{counter} = arrayify_string($operand);
124             }
125              
126             # just like above, in Perl, a sting of numbers is treated like
127             # the number itself and padded zeros are ignored when used
128             # in numeric context
129              
130             # e.g. '0050' > 0 would be true, so there is no need, in this
131             # language, to strip them
132              
133 0           return 0;
134             }
135              
136             sub halt {
137 0     0 1   my $machine = shift;
138              
139 0           $machine->{halt} = 1;
140              
141 0           return 0;
142             }
143              
144             1;
145              
146             =pod
147              
148             =head1 NAME
149              
150             VM::Dreamer::Instructions - The heavy lifting
151              
152             =head1 SYNOPSIS
153              
154             input_to_mb( $machine, '72' );
155             output_from_my( $machine, $operand );
156             store( $machine, $operand );
157             load( $machine, $operand );
158             add( $machine, $operand );
159             subtract( $machine, $operand );
160             branch_always( $machine, $operand );
161             branch_if_zero( $machine, $operand );
162             branch_if_negative( $machine, $operand );
163             branch_if_positive( $machine, $operand );
164             halt($machine);
165              
166             =head1 DESCRIPTION
167              
168             These functions will be used in a dispatch table in VM::Dreamer::Languages::YourMachine where you map your operation codes to these functions.
169              
170             A base 10 machine with an op code width of 1 might map op code 7 to branch_always. A base 2 machine with an opcode width of 4 might map 0101 to subtract.
171              
172             For an example, see VM::Dreamer::Languages::Grasshopper
173              
174             If you'd like to add more instructions, you can do so here in VM::Dreamer::Instructions and send me a pull request. You can also use VM::Dreamer::Local for your own code.
175              
176             =head2 input_to_mb
177              
178             input_to_mb( $machine, '72' );
179              
180             Prompts the user for input and, if valid, stores their input in memory at address '72'.
181              
182             =head2 output_from_mb
183              
184             output_from_mb( $machine, '72' );
185              
186             Outputs the value stored in memory at address '72' to the user.
187              
188             =head2 store
189              
190             store( $machine, '1011101' );
191              
192             Stores the value on the accumulator at address '1011101' in memory.
193              
194             =head2 load
195              
196             load( $machine, '271104523210' );
197              
198             Loads the value stored in memory at address '271104523210' onto the accumulator.
199              
200             =head2 add
201              
202             add( $machine, '10011100101001' );
203              
204             Adds the value stored in memory at address '10011100101001' to the current value on the accumulator.
205              
206             =head2 subtract( $machine, '9744321229' );
207              
208             Subtracts the value stored in memory at address '9744321229' from the current value on the accumulator.
209              
210             If the resulting value is negative, the negative flag is set and the remaining value on the accumulator is undefined.
211              
212             =head2 branch_always
213              
214             branch_always( $machine, '432' );
215              
216             Sets the value of the counter to 432, always.
217              
218             This means that the next instruction executed will be fetched from address 432 in memory.
219              
220             =head2 branch_if_zero
221              
222             branch_if_zero( $machine, '34221023' );
223              
224             Sets the value of the counter to 34221023 if the value on the accumulator is zero.
225              
226             In other words, if the accumulator is zero, fetch the next instruction from address 34221023 in memory.
227              
228             =head2 branch_if_negative
229              
230             branch_if_negative( $machine, '1521532' );
231              
232             Sets the value of the counter to 1521532 if the negative flag is set.
233              
234             In other words, if the negative flag is set, fetch the next instruction from address 1521532 in memory.
235              
236             =head2 branch_if_positive
237              
238             branch_if_positive( $machine, '92345' );
239              
240             Sets the value of the counter to 92345 if the value on the accumulator is greater than zero and the negative flag is not set.
241              
242             In other words, if the negative flag is unset and the accumulator is greater than 0, fetch the next instruction from address 92345 in memory.
243              
244             =head2 halt
245              
246             halt($machine);
247              
248             Sets the halt flag to 1. This means that the machine should cease operation.
249              
250             =head1 SEE ALSO
251              
252             VM::Dreamer::execute_next_instruction
253             VM::Dreamer::Languages::Grasshopper
254              
255             =head1 AUTHOR
256              
257             William Stevenson
258              
259             =head1 COPYRIGHT AND LICENSE
260              
261             This software is Copyright (c) 2013 by William Stevenson.
262              
263             This is free software, licensed under:
264              
265             The Artistic License 2.0 (GPL Compatible)
266            
267             =cut