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