File Coverage

blib/lib/Language/Befunge/Storage/Generic/AoA.pm
Criterion Covered Total %
statement 96 96 100.0
branch 32 32 100.0
condition 5 6 83.3
subroutine 13 13 100.0
pod 5 5 100.0
total 151 152 99.3


line stmt bran cond sub pod time code
1             #
2             # This file is part of Language-Befunge
3             #
4             # This software is copyright (c) 2003 by Jerome Quelin.
5             #
6             # This is free software; you can redistribute it and/or modify it under
7             # the same terms as the Perl 5 programming language system itself.
8             #
9 8     8   18388 use 5.010;
  8         25  
10 8     8   30 use strict;
  8         11  
  8         140  
11 8     8   25 use warnings;
  8         58  
  8         409  
12              
13             package Language::Befunge::Storage::Generic::AoA;
14             # ABSTRACT: a generic N-dimensional LaheySpace
15             $Language::Befunge::Storage::Generic::AoA::VERSION = '5.000';
16 8     8   30 use Carp;
  8         9  
  8         491  
17 8     8   354 use Language::Befunge::Vector;
  8         10  
  8         70  
18 8     8   531 use Language::Befunge::IP;
  8         11  
  8         72  
19 8     8   130 use base 'Language::Befunge::Storage';
  8         103  
  8         4028  
20              
21             # -- CONSTRUCTOR
22              
23              
24             #
25             # new( dimensions )
26             #
27             # Creates a new Lahey Space.
28             #
29             sub new {
30 31     31 1 504 my $package = shift;
31 31         33 my $dimensions = shift;
32 31         54 my %args = @_;
33 31         88 my $usage = "Usage: $package->new(\$dimensions, Wrapping => \$wrapping)";
34 31 100       72 croak $usage unless defined $dimensions;
35 30 100       59 croak $usage unless $dimensions > 0;
36 29 100       72 croak $usage unless exists $args{Wrapping};
37             my $self = {
38             nd => $dimensions,
39             wrapping => $args{Wrapping},
40 28         64 };
41 28         37 bless $self, $package;
42 28         92 $self->clear();
43 28         102 return $self;
44             }
45              
46              
47             # -- PUBLIC METHODS
48              
49             #
50             # clear( )
51             #
52             # Clear the torus.
53             #
54             sub clear {
55 46     46 1 594 my $self = shift;
56 46         160 $$self{min} = Language::Befunge::Vector->new_zeroes($$self{nd});
57 46         101 $$self{max} = Language::Befunge::Vector->new_zeroes($$self{nd});
58 46         67 $$self{torus} = [32];
59 46         218 $$self{torus} = [$$self{torus}] for(1..$$self{nd});
60             }
61              
62              
63             #
64             # expand( vector )
65             #
66             # Expand the torus to include the provided point.
67             #
68             sub expand {
69 557     557 1 362 my ($self, $v) = @_;
70 557         405 my $nd = $$self{nd};
71 557         452 my ($min, $max) = ($$self{min}, $$self{max});
72              
73             # if we have nothing to do, skip out early.
74 557 100       779 return 0 if $v->bounds_check($min,$max);
75              
76             sub _expand_helper {
77 191     191   157 my ($d, $v, $torus, $min, $max) = @_;
78 191         245 my $oldmin = $min->get_component($d); # left end of old array
79 191         259 my $oldmax = $max->get_component($d); # right end of old array
80 191         127 my $doff = 0; # prepend this many elements
81 191 100       247 $doff = $oldmin - $v->get_component($d) if $v->get_component($d) < $oldmin;
82 191         132 my $newmin = $oldmin; # left end of new array
83 191         113 my $newmax = $oldmax; # right end of new array
84 191 100       254 $newmin = $v->get_component($d) if $v->get_component($d) < $newmin;
85 191 100       258 $newmax = $v->get_component($d) if $v->get_component($d) > $newmax;
86 191         244 my $append = $v->get_component($d) - $max->get_component($d);
87 191 100       255 $append = 0 if $append < 0; # append this many elements
88 191         122 my $wholerow = 0;
89             # if a higher-level dimension has been expanded where we are, we
90             # have to create a new row out of whole cloth.
91 191         225 for(my $i = $v->get_dims()-1; $i > $d; $i--) {
92 158 100       198 $wholerow = 1 if $v->get_component($i) < $min->get_component($i);
93 158 100       216 $wholerow = 1 if $v->get_component($i) > $max->get_component($i);
94             }
95 191         125 my @newrow;
96 191         244 my $o = $v->get_component($d);
97 191 100       207 if($d > 0) {
98             # handle the nodes we have to create from whole cloth
99 42         68 for(my $i = 0; $i < $doff; $i++) {
100 13         27 $v->set_component($d,$i+$newmin);
101 13         28 push(@newrow,_expand_helper($d-1,$v,undef,$min,$max));
102             }
103             # handle the nodes we're expanding from existing data
104 42         74 for(my $i = 0; $i <= ($oldmax-$oldmin); $i++) {
105 93         147 $v->set_component($d,$i+$oldmin);
106 93         139 push(@newrow,_expand_helper($d-1,$v,$$torus[$i],$min,$max));
107             }
108             # handle more nodes we're creating from whole cloth
109 42         83 for(my $i = $oldmax + 1; $i < $newmax + 1; $i++) {
110 44         65 $v->set_component($d,$i);
111 44         56 push(@newrow,_expand_helper($d-1,$v,undef,$min,$max));
112             }
113             } else {
114 149         212 for(my $i = $newmin; $i <= $newmax; $i++) {
115 1883 100 100     4287 if(!$wholerow && ($i >= ($newmin+$doff) && (($i-($newmin+$doff)) <= ($oldmax-$oldmin)))) {
      66        
116             # newmin = -3
117             # oldmin = -1
118             # doff = 2
119             # lhs offset -3-2-1 0 1 2 3 4 5 6 7 8
120             # data . . a b c d e f g h i j
121             # array index . . 0 1 2 3 4 5 6 7 8 9
122 836         595 my $newdata = $$torus[$i-$oldmin];
123 836         1083 push(@newrow,$newdata);
124             } else {
125 1047         1368 push(@newrow,32);
126             }
127             }
128             }
129 191         292 $v->set_component($d,$o);
130 191         396 return \@newrow;
131             }
132 41         77 $$self{torus} = _expand_helper($nd - 1, $v, $$self{torus}, $min, $max);
133 41         124 for(my $d = $$self{nd} - 1; $d > -1; $d--) {
134 82         120 my $n = $v->get_component($d);
135 82         123 my $min = $$self{min}->get_component($d);
136 82         118 my $max = $$self{max}->get_component($d);
137 82 100       124 $$self{min}->set_component($d,$n) if $n < $min;
138 82 100       188 $$self{max}->set_component($d,$n) if $n > $max;
139             }
140             }
141              
142              
143             #
144             # my $val = get_value( vector )
145             #
146             # Return the number stored in the torus at the specified location. If
147             # the value hasn't yet been set, it defaults to the ordinal value of a
148             # space (ie, #32).
149             #
150             # B As in Funge, code and data share the same playfield, the
151             # number returned can be either an instruction B a data (or even
152             # both... Eh, that's Funge! :o) ).
153             #
154             sub get_value {
155 1716     1716 1 1190 my ($self, $v) = @_;
156 1716         1004 my $val;
157              
158 1716 100       2640 if ($v->bounds_check($$self{min}, $$self{max})) {
159             # for each dimension, go one level deeper into the array.
160 1701         1244 $val = $$self{torus};
161 1701         2437 for(my $d = $$self{nd} - 1; $d > -1; $d--) {
162 3494         4558 $val = $$val[$v->get_component($d) - $$self{min}->get_component($d)];
163             }
164             }
165 1716 100       3224 return $val if defined $val;
166 15         41 return 32; # Default to space.
167             }
168              
169              
170             #
171             # set_value( vector, value )
172             #
173             # Write the supplied value in the torus at the specified location.
174             #
175             # B As in Funge, code and data share the same playfield, the
176             # number stored can be either an instruction B a data (or even
177             # both... Eh, that's Funge! :o) ).
178             #
179             sub set_value {
180 479     479 1 351 my ($self, $v, $val) = @_;
181              
182             # Ensure we can set the value.
183 479         450 $self->expand($v);
184             # for each dimension, go one level deeper into the array.
185 479         352 my $line = $$self{torus};
186 479         678 for(my $d = $$self{nd} - 1; ($d > 0); $d--) {
187 492         613 my $i = $v->get_component($d) - $$self{min}->get_component($d);
188 492         689 $line = $$line[$i];
189             }
190 479         655 $$line[$v->get_component(0) - $$self{min}->get_component(0)] = $val;
191             }
192              
193              
194             1;
195              
196             __END__