File Coverage

blib/lib/Language/Befunge/Storage/Generic/AoA.pm
Criterion Covered Total %
statement 94 94 100.0
branch 32 32 100.0
condition 5 6 83.3
subroutine 12 12 100.0
pod 5 5 100.0
total 148 149 99.3


line stmt bran cond sub pod time code
1             #
2             # This file is part of Language::Befunge.
3             # Copyright (c) 2001-2009 Jerome Quelin, all rights reserved.
4             #
5             # This program is free software; you can redistribute it and/or modify
6             # it under the same terms as Perl itself.
7             #
8             #
9              
10             package Language::Befunge::Storage::Generic::AoA;
11             require 5.010;
12 9     9   39285 use strict;
  9         106  
  9         388  
13 9     9   53 use warnings;
  9         21  
  9         276  
14 9     9   45407 use Carp;
  9         36  
  9         1073  
15 9     9   654 use Language::Befunge::Vector;
  9         27  
  9         131  
16 9     9   823 use Language::Befunge::IP;
  9         20  
  9         100  
17 9     9   341 use base 'Language::Befunge::Storage';
  9         72  
  9         8939  
18              
19             # -- CONSTRUCTOR
20              
21              
22             #
23             # new( dimensions )
24             #
25             # Creates a new Lahey Space.
26             #
27             sub new {
28 31     31 1 4187 my $package = shift;
29 31         63 my $dimensions = shift;
30 31         91 my %args = @_;
31 31         81 my $usage = "Usage: $package->new(\$dimensions, Wrapping => \$wrapping)";
32 31 100       110 croak $usage unless defined $dimensions;
33 30 100       108 croak $usage unless $dimensions > 0;
34 29 100       99 croak $usage unless exists $args{Wrapping};
35 28         107 my $self = {
36             nd => $dimensions,
37             wrapping => $args{Wrapping},
38             };
39 28         94 bless $self, $package;
40 28         81 $self->clear();
41 28         202 return $self;
42             }
43              
44              
45             # -- PUBLIC METHODS
46              
47             #
48             # clear( )
49             #
50             # Clear the torus.
51             #
52             sub clear {
53 46     46 1 1545 my $self = shift;
54 46         397 $$self{min} = Language::Befunge::Vector->new_zeroes($$self{nd});
55 46         274 $$self{max} = Language::Befunge::Vector->new_zeroes($$self{nd});
56 46         128 $$self{torus} = [32];
57 46         371 $$self{torus} = [$$self{torus}] for(1..$$self{nd});
58             }
59              
60              
61             #
62             # expand( vector )
63             #
64             # Expand the torus to include the provided point.
65             #
66             sub expand {
67 557     557 1 656 my ($self, $v) = @_;
68 557         770 my $nd = $$self{nd};
69 557         796 my ($min, $max) = ($$self{min}, $$self{max});
70              
71             # if we have nothing to do, skip out early.
72 557 100       2019 return 0 if $v->bounds_check($min,$max);
73              
74             sub _expand_helper {
75 191     191   273 my ($d, $v, $torus, $min, $max) = @_;
76 191         427 my $oldmin = $min->get_component($d); # left end of old array
77 191         296 my $oldmax = $max->get_component($d); # right end of old array
78 191         271 my $doff = 0; # prepend this many elements
79 191 100       513 $doff = $oldmin - $v->get_component($d) if $v->get_component($d) < $oldmin;
80 191         197 my $newmin = $oldmin; # left end of new array
81 191         176 my $newmax = $oldmax; # right end of new array
82 191 100       510 $newmin = $v->get_component($d) if $v->get_component($d) < $newmin;
83 191 100       577 $newmax = $v->get_component($d) if $v->get_component($d) > $newmax;
84 191         511 my $append = $v->get_component($d) - $max->get_component($d);
85 191 100       343 $append = 0 if $append < 0; # append this many elements
86 191         208 my $wholerow = 0;
87             # if a higher-level dimension has been expanded where we are, we
88             # have to create a new row out of whole cloth.
89 191         524 for(my $i = $v->get_dims()-1; $i > $d; $i--) {
90 158 100       493 $wholerow = 1 if $v->get_component($i) < $min->get_component($i);
91 158 100       661 $wholerow = 1 if $v->get_component($i) > $max->get_component($i);
92             }
93 191         227 my @newrow;
94 191         318 my $o = $v->get_component($d);
95 191 100       320 if($d > 0) {
96             # handle the nodes we have to create from whole cloth
97 42         91 for(my $i = 0; $i < $doff; $i++) {
98 13         36 $v->set_component($d,$i+$newmin);
99 13         37 push(@newrow,_expand_helper($d-1,$v,undef,$min,$max));
100             }
101             # handle the nodes we're expanding from existing data
102 42         96 for(my $i = 0; $i <= ($oldmax-$oldmin); $i++) {
103 93         376 $v->set_component($d,$i+$oldmin);
104 93         234 push(@newrow,_expand_helper($d-1,$v,$$torus[$i],$min,$max));
105             }
106             # handle more nodes we're creating from whole cloth
107 42         113 for(my $i = $oldmax + 1; $i < $newmax + 1; $i++) {
108 44         113 $v->set_component($d,$i);
109 44         92 push(@newrow,_expand_helper($d-1,$v,undef,$min,$max));
110             }
111             } else {
112 149         295 for(my $i = $newmin; $i <= $newmax; $i++) {
113 1883 100 100     7357 if(!$wholerow && ($i >= ($newmin+$doff) && (($i-($newmin+$doff)) <= ($oldmax-$oldmin)))) {
      66        
114             # newmin = -3
115             # oldmin = -1
116             # doff = 2
117             # lhs offset -3-2-1 0 1 2 3 4 5 6 7 8
118             # data . . a b c d e f g h i j
119             # array index . . 0 1 2 3 4 5 6 7 8 9
120 836         979 my $newdata = $$torus[$i-$oldmin];
121 836         1871 push(@newrow,$newdata);
122             } else {
123 1047         2666 push(@newrow,32);
124             }
125             }
126             }
127 191         399 $v->set_component($d,$o);
128 191         772 return \@newrow;
129             }
130 41         143 $$self{torus} = _expand_helper($nd - 1, $v, $$self{torus}, $min, $max);
131 41         191 for(my $d = $$self{nd} - 1; $d > -1; $d--) {
132 82         154 my $n = $v->get_component($d);
133 82         181 my $min = $$self{min}->get_component($d);
134 82         186 my $max = $$self{max}->get_component($d);
135 82 100       170 $$self{min}->set_component($d,$n) if $n < $min;
136 82 100       545 $$self{max}->set_component($d,$n) if $n > $max;
137             }
138             }
139              
140              
141             #
142             # my $val = get_value( vector )
143             #
144             # Return the number stored in the torus at the specified location. If
145             # the value hasn't yet been set, it defaults to the ordinal value of a
146             # space (ie, #32).
147             #
148             # B As in Funge, code and data share the same playfield, the
149             # number returned can be either an instruction B a data (or even
150             # both... Eh, that's Funge! :o) ).
151             #
152             sub get_value {
153 1716     1716 1 2343 my ($self, $v) = @_;
154 1716         2232 my $val;
155              
156 1716 100       6433 if ($v->bounds_check($$self{min}, $$self{max})) {
157             # for each dimension, go one level deeper into the array.
158 1701         2675 $val = $$self{torus};
159 1701         3968 for(my $d = $$self{nd} - 1; $d > -1; $d--) {
160 3494         15060 $val = $$val[$v->get_component($d) - $$self{min}->get_component($d)];
161             }
162             }
163 1716 100       5607 return $val if defined $val;
164 15         51 return 32; # Default to space.
165             }
166              
167              
168             #
169             # set_value( vector, value )
170             #
171             # Write the supplied value in the torus at the specified location.
172             #
173             # B As in Funge, code and data share the same playfield, the
174             # number stored can be either an instruction B a data (or even
175             # both... Eh, that's Funge! :o) ).
176             #
177             sub set_value {
178 479     479 1 699 my ($self, $v, $val) = @_;
179              
180             # Ensure we can set the value.
181 479         863 $self->expand($v);
182             # for each dimension, go one level deeper into the array.
183 479         639 my $line = $$self{torus};
184 479         1077 for(my $d = $$self{nd} - 1; ($d > 0); $d--) {
185 492         1378 my $i = $v->get_component($d) - $$self{min}->get_component($d);
186 492         1131 $line = $$line[$i];
187             }
188 479         2594 $$line[$v->get_component(0) - $$self{min}->get_component(0)] = $val;
189             }
190              
191              
192             1;
193             __END__