# New Ticket Created by  James Keenan 
# Please include the string:  [perl #44615]
# in the subject line of all future correspondence about this issue. 
# <URL: http://rt.perl.org/rt3/Ticket/Display.html?id=44615 >


This ticket is a cage-cleaning assignment that would be especially  
good for a newcomer to the Parrot project to take on.  It entails the  
creation of a module written in Perl 5 to be placed under lib/Parrot/  
which would serve as a repository for Perl 5 subroutines which can be  
imported on demand by any Perl 5 packages anywhere in the Parrot  
distribution at any point in the compile-build-test-install cycle.

More precisely, it involves the *completion* of such a module,  
because I've begun the module's specification below.  Your task will  
be to complete the documentation, write tests of the interface, then  
write the code to implement the interface -- and then repeat the  
cycle until you get a high-quality Perl 5 package.

The impetus for this module comes from an inline comment made by Andy  
Lester in r20618 of config/auto/attributes.pm:

20618   petdance # Stolen from Parrot::Test
20618   petdance # Should be put somewhere more central
20618   petdance sub _slurp_file {
20618   petdance     my ($file_name) = @_;
20618   petdance
20618   petdance     open( my $SLURP, '<', $file_name ) or die "open  
'$file_name': $!";
20618   petdance     local $/ = undef;
20618   petdance     my $file = <$SLURP> . '';
20618   petdance     $file =~ s/\cM\cJ/\n/g;
20618   petdance     close $SLURP;
20618   petdance
20618   petdance     return $file;
20618   petdance }

Code to slurp a file into a string can be found in many places,  
notably in the Perl Cookbook and in Uri's CPAN module File::Slurp.   
But File::Slurp is not part of the Perl 5 core distribution.  That  
means it is not automatically available to Parrot developers.  But  
it's certainly something that would be nice to have.  I wondered why  
no one had made it available already.

It turns out, someone *had* made it available already -- but *not*  
available throughout all parts of the Parrot installation cycle.  A  
subroutine called slurp_file() is automatically exported by  
Parrot::Test and is used *very* extensively throughout the build and  
test phases (see attached file 'slurp_file.usages.txt' -- but note  
that some instances of the string 'slurp_file' pertain to PIR code).

So I wondered:  Why didn't Andy simply call Parrot::Test::slurp_file 
() in config/auto/attributes.pm?  Why was he complaining that it  
wasn't "central" enough?

The answer is that Parrot::Test has a dependency on Parrot::Config:

     use Parrot::Config;

... and Parrot::Config doesn't come into existence until after the  
configuration phase has completed!  So Parrot::Test::slurp_file() can  
only be used in the build and later phases -- even though it itself  
has no dependency on Parrot::Config.  It was not available when/where  
Andy needed it, because config/auto/attributes.pm is part of the  
configuration phase.

In fact, slurp_file() doesn't have anything to do with testing per  
se.  There is no intrinsic reason why it should be housed in  
Parrot::Test.  (That's probably just where it first proved useful  
some 8000 commits ago.)

It therefore makes sense to:

1.  Extract slurp_file() from Parrot::Test.
2.  Place it in a new package under lib/Parrot/ from which it is  
exported on demand (*not* automatically, as is currently the case;  
that's < best practice).
3.  Make this a package that can hold other self-contained, non- 
object-oriented, utility subroutines written in Perl 5 that can be  
useful in all phases of the Parrot installation cycle.
4.  Replace all current calls to Parrot::Test::slurp_file() with  
calls to Parrot::YetToBeNamed::slurp_file().
5.  And, of course, to do it right:  write unit tests for the  
subroutines exported by Parrot::YetToBeNamed.

What do you need to accomplish these objectives?  You don't need C,  
PIR or PASM.  In fact, you don't need to know anything about Parrot  
at all!  You only need competence in Perl 5.  (Of course, it would  
help if you've drunk the koolaid Schwern first started brewing seven  
years ago.  See any YAPC talk on module development or testing given  
by him, chromatic, Ian Langworth, Paul Johnson, Andy or myself in  
recent years.)

In fact, this would be a great assignment for any/all of you who came  
to our Parrot BOF at YAPC, said you were interested in joining the  
project, but haven't yet started an assignment.  Or a good assignment  
for those of you in Phalanx Phoenix!

So don't be bashful.  Step up to the plate and hit this one out of  
the ballpark -- and stop me before I use another baseball metaphor!

kid51

./config/auto/attributes.pm:81:    my $output = _slurp_file( $output_file );
./config/auto/attributes.pm:93:sub _slurp_file {
./languages/befunge/t/basic.t:28:is( Parrot::Test::slurp_file($out_f), << 
'OUT', 'output from test.bef' );
./languages/c99/c99.pir:99:    source = slurp_file(filename)
./languages/c99/c99.pir:202:.sub slurp_file
./languages/c99/lib/Parrot/Test/C99.pm:43:#my $gcc_output = 
Parrot::Test::slurp_file($out_f);
./languages/c99/lib/Parrot/Test/C99.pm:52:    my $c99_output = 
Parrot::Test::slurp_file($c99_out_f);
./languages/c99/lib/Parrot/Test/C99.pm:69:        my $c99_debug_output = 
Parrot::Test::slurp_file($c99_out_debug_f);
./languages/cardinal/cardinal.pir:326:    $S1 = _slurp_file(filename)
./languages/cardinal/cardinal.pir:334:.sub _slurp_file
./languages/jako/lib/Jako/Lexer.pm:309:# slurp_file()
./languages/jako/lib/Jako/Lexer.pm:312:sub slurp_file {
./languages/jako/lib/Jako/Lexer.pm:338:    my @lines = $self->slurp_file($file);
./languages/jako/lib/Jako/Lexer.pm:358:            my @use_lines = 
$self->slurp_file($use_file);
./languages/lua/t/Parrot/Test/Lua.pm:99:            ->$builder_func( 
Parrot::Test::slurp_file($lua_out_fn), $output, $desc );
./languages/lua/t/Parrot/Test/Lua_lex.pm:76:            ->$builder_func( 
Parrot::Test::slurp_file($lua_out_fn), $output, $desc );
./languages/lua/t/shootout.t:41:$code = 
Parrot::Test::slurp_file(File::Spec->catfile( @dir, 'knucleotide.lua-2.lua' ));
./languages/lua/t/shootout.t:42:$out = 
Parrot::Test::slurp_file(File::Spec->catfile( @dir, 'knucleotide-output.txt' ));
./languages/lua/t/shootout.t:52:$code = 
Parrot::Test::slurp_file(File::Spec->catfile( @dir, 'partialsums.lua-3.lua' ));
./languages/lua/t/shootout.t:53:$out = 
Parrot::Test::slurp_file(File::Spec->catfile( @dir, 'partialsums-output.txt' ));
./languages/lua/t/shootout.t:65:$code = 
Parrot::Test::slurp_file(File::Spec->catfile( @dir, 'fasta.lua-2.lua' ));
./languages/lua/t/shootout.t:66:$out = 
Parrot::Test::slurp_file(File::Spec->catfile( @dir, 'fasta-output.txt' ));
./languages/lua/t/shootout.t:79:$code = 
Parrot::Test::slurp_file(File::Spec->catfile( @dir, 'pidigits.lua-2.lua' ));
./languages/lua/t/shootout.t:80:$out = 
Parrot::Test::slurp_file(File::Spec->catfile( @dir, 'pidigits-output.txt' ));
./languages/lua/t/shootout.t:89:$code = 
Parrot::Test::slurp_file(File::Spec->catfile( @dir, 'nsieve.lua-3.lua' ));
./languages/lua/t/shootout.t:90:$out = 
Parrot::Test::slurp_file(File::Spec->catfile( @dir, 'nsieve-output.txt' ));
./languages/lua/t/shootout.t:102:$code = 
Parrot::Test::slurp_file(File::Spec->catfile( @dir, 'regexdna.lua-3.lua' ));
./languages/lua/t/shootout.t:103:$out = 
Parrot::Test::slurp_file(File::Spec->catfile( @dir, 'regexdna-output.txt' ));
./languages/lua/t/shootout.t:113:$code = 
Parrot::Test::slurp_file(File::Spec->catfile( @dir, 'nsievebits.lua' ));
./languages/lua/t/shootout.t:114:$out = 
Parrot::Test::slurp_file(File::Spec->catfile( @dir, 'nsievebits-output.txt' ));
./languages/lua/t/shootout.t:126:$code = 
Parrot::Test::slurp_file(File::Spec->catfile( @dir, 'recursive.lua' ));
./languages/lua/t/shootout.t:127:$out = 
Parrot::Test::slurp_file(File::Spec->catfile( @dir, 'recursive-output.txt' ));
./languages/lua/t/shootout.t:136:$code = 
Parrot::Test::slurp_file(File::Spec->catfile( @dir, 'mandelbrot.lua-2.lua' ));
./languages/lua/t/shootout.t:137:$out = 
Parrot::Test::slurp_file(File::Spec->catfile( @dir, 'mandelbrot-output.txt' ));
./languages/lua/t/shootout.t:145:$code = 
Parrot::Test::slurp_file(File::Spec->catfile( @dir, 'nbody.lua-2.lua' ));
./languages/lua/t/shootout.t:146:$out = 
Parrot::Test::slurp_file(File::Spec->catfile( @dir, 'nbody-output.txt' ));
./languages/lua/t/shootout.t:158:$code = 
Parrot::Test::slurp_file(File::Spec->catfile( @dir, 'message.lua-2.lua' ));
./languages/lua/t/shootout.t:159:$out = 
Parrot::Test::slurp_file(File::Spec->catfile( @dir, 'message-output.txt' ));
./languages/lua/t/shootout.t:168:$code = 
Parrot::Test::slurp_file(File::Spec->catfile( @dir, 'spectralnorm.lua-3.lua' ));
./languages/lua/t/shootout.t:169:$out = 
Parrot::Test::slurp_file(File::Spec->catfile( @dir, 'spectralnorm-output.txt' 
));
./languages/lua/t/shootout.t:177:$code = 
Parrot::Test::slurp_file(File::Spec->catfile( @dir, 'chameneos.lua' ));
./languages/lua/t/shootout.t:178:$out = 
Parrot::Test::slurp_file(File::Spec->catfile( @dir, 'chameneos-output.txt' ));
./languages/lua/t/shootout.t:190:$code = 
Parrot::Test::slurp_file(File::Spec->catfile( @dir, 'revcomp.lua-3.lua' ));
./languages/lua/t/shootout.t:191:$out = 
Parrot::Test::slurp_file(File::Spec->catfile( @dir, 'revcomp-output.txt' ));
./languages/lua/t/shootout.t:205:$code = 
Parrot::Test::slurp_file(File::Spec->catfile( @dir, 'binarytrees.lua-3.lua' ));
./languages/lua/t/shootout.t:206:$out = 
Parrot::Test::slurp_file(File::Spec->catfile( @dir, 'binarytrees-output.txt' ));
./languages/lua/t/shootout.t:215:$code = 
Parrot::Test::slurp_file(File::Spec->catfile( @dir, 'fannkuch.lua-3.lua' ));
./languages/lua/t/shootout.t:216:$out = 
Parrot::Test::slurp_file(File::Spec->catfile( @dir, 'fannkuch-output.txt' ));
./languages/lua/t/shootout.t:224:$code = 
Parrot::Test::slurp_file(File::Spec->catfile( @dir, 'sumcol.lua' ));
./languages/lua/t/shootout.t:225:$out = 
Parrot::Test::slurp_file(File::Spec->catfile( @dir, 'sumcol-output.txt' ));
./languages/lua/t/shootout.t:234:$code = 
Parrot::Test::slurp_file(File::Spec->catfile( @dir, 'hello.lua' ));
./languages/lua/t/shootout.t:235:$out = 
Parrot::Test::slurp_file(File::Spec->catfile( @dir, 'hello-output.txt' ));
./languages/ook/t/basic.t:49:my $out = Parrot::Test::slurp_file($out_fn);
./languages/parrot_compiler/lib/Parrot/Test/ParrotCompiler.pm:63:    return 
Parrot::Test::slurp_file($out_f);
./languages/scheme/Scheme/Test.pm:58:        my $prog_output = 
Parrot::Test::slurp_file("$out_f");
./languages/tcl/lib/Parrot/Test/Tcl.pm:93:            my $file         = 
Parrot::Test::slurp_file($out_f);
./languages/tcl/lib/Parrot/Test/Tcl.pm:101:                    ->$builder_func( 
Parrot::Test::slurp_file($out_f), $output, $desc );
./languages/urm/lib/URM/Test.pm:58:        my $prog_output = 
Parrot::Test::slurp_file("$out_f");
./languages/WMLScript/t/Parrot/Test/WMLScript.pm:87:            
$self->{builder}->$builder_func( Parrot::Test::slurp_file($out_fn), $output, 
$desc );
./lib/Parrot/Test/APL.pm:51:        my $file = Parrot::Test::slurp_file($out_f);
./lib/Parrot/Test/APL.pm:52:        $pass = $self->{builder}->is_eq( 
Parrot::Test::slurp_file($out_f), $output, $desc );
./lib/Parrot/Test/Cardinal.pm:49:    my $ruby_output = 
Parrot::Test::slurp_file($out_f);
./lib/Parrot/Test/Cardinal.pm:58:    my $cardinal_output = 
Parrot::Test::slurp_file($cardinal_out_f);
./lib/Parrot/Test/Cardinal.pm:74:        my $cardinal_debug_output = 
Parrot::Test::slurp_file($cardinal_out_debug_f);
./lib/Parrot/Test/Perl6.pm:132:            my $actual_output = 
Parrot::Test::slurp_file($f_out);
./lib/Parrot/Test/PIR_PGE.pm:56:        my $file         = 
Parrot::Test::slurp_file($out_f);
./lib/Parrot/Test/PIR_PGE.pm:63:            $pass = 
$self->{builder}->$builder_func( Parrot::Test::slurp_file($out_f), $output, 
$desc );
./lib/Parrot/Test/Punie.pm:51:        my $file = 
Parrot::Test::slurp_file($out_f);
./lib/Parrot/Test/Punie.pm:52:        $pass = $self->{builder}->is_eq( 
Parrot::Test::slurp_file($out_f), $output, $desc );
./lib/Parrot/Test.pm:226:=item C<slurp_file($file_name)>
./lib/Parrot/Test.pm:276:our @EXPORT = qw( plan run_command skip slurp_file );
./lib/Parrot/Test.pm:405:sub slurp_file {
./lib/Parrot/Test.pm:484:                my $real_output = slurp_file($out_f);
./lib/Parrot/Test.pm:715:            my $real_output = slurp_file($out_f);
./lib/Parrot/Test.pm:799:            my $real_output = slurp_file($out_f);
./lib/Parrot/Test.pm:920:                my $code      = slurp_file($example_f);
./lib/Parrot/Test.pm:986:                    $builder->diag( "Failed to build 
'$obj_f': " . slurp_file($build_f) );
./lib/Parrot/Test.pm:1016:                    $builder->diag( "Failed to build 
'$exe_f': " . slurp_file($build_f) );
./lib/Parrot/Test.pm:1033:                my $output = slurp_file($out_f);
./runtime/parrot/library/Config/JSON.pir:26:    if pio goto slurp_file
./runtime/parrot/library/Config/JSON.pir:32:  slurp_file:
./t/benchmark/benchmarks.t:214:        my $bench = 
Parrot::Test::slurp_file("examples/benchmarks/$_");
Binary file ./t/examples/pir.t matches
./t/examples/shootout.t:76:    my $expected = slurp_file("$file$EXT");
./t/native_pbc/header.t:39:    my $pbc = slurp_file($tmppbc);
./t/perl/Parrot_Test.t:74:    slurp_file
./t/perl/Parrot_Test.t:87:# TODO test write_code_to_file(), plan(), skip(), 
slurp_file()

Reply via email to