# 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()