Slideshare.net (beta)

 

All comments

Add a comment on Slide 1

If you have a SlideShare account, login to comment; else you can comment as a guest


Showing 1-50 of 10 (more)

Perl Sucks - and what to do about it

From 2shortplanks, 11 months ago

(originally presented at YAPC::Europe::2007)<br /><br />No-one is as criti more

12898 views  |  7 comments  |  7 favorites  |  405 downloads  |  1 embed (Stats)
Embed
options

More Info

CC Attribution-NoDerivs LicenseCC Attribution-NoDerivs License
This slideshow is Public
Total Views: 12898
on Slideshare: 12889
from embeds: 9

Slideshow transcript

Slide 1: Perl Sucks! (and what to do about it)

Slide 2: What this talk is not • “Wah, no one uses ‘use strict’” • “People’s perception of Perl is wrong” • “The CPAN/mailing list/a other website isn’t exactly how I like it” • “The garbage collection de-allocation routine isn’t very efficent”

Slide 3: What this talk is • What’s a few major annoyances with Perl • What we the humble programmer can do to work around them

Slide 5: ~/bin

Slide 6: scp ~/bin nethost:

Slide 7: ssh newhost

Slide 8: jabme -m ‘compile done’

Slide 9: Module “Jabber::Lite” not found

Slide 10: -bash: jabme: /usr/local/bin/ perl: bad interpreter: No such file or directory

Slide 11: My Scripts Need • A particular version of Perl • A set of Perl modules

Slide 12: PAR

Slide 13: #!/usr/bin/perl use strict; use warnings; use XML::LibXML; use Template; use DBD::SQLite; use CGI; use Parse::RecDescent; use List::MoreUtils; use Moose; print \"Hello World\\n\";

Slide 14: Make an executable • perl -MCPAN -e ‘install PAR::Packer’ • pp -o hellow hellow.pl • ...copy “hellow” to new computer • ./hellow Hello World

Slide 16: #!/usr/bin/perl use strict; use warnings; print \"Hello World\\n\";

Slide 18: Build our own Perl and ship the whole thing

Slide 19: Get Stable Perl • lwp-request $CPAN_URL > perl-5.8.8.tar.gz • gunzip -c perl-5.8.8.tar.gz | tar -xvf - • cd perl-5.8.8

Slide 20: Tell it where to go • mkdir -p /User/mark/bin/perl5.8.8 • ./configure.gnu --prefix=/User/mark/bin/ perl5.8.8

Slide 21: Install it • make • make test • make install

Slide 22: We now have our own perl in ~/bin

Slide 23: We can install it’s own modules

Slide 24: ~/bin/perl5.8.8/bin/perl -MCPAN -e ‘install Template’

Slide 25: Problem: different paths • /home/mark/bin/myperl • /home/mfowler/bin/myperl • /home/nisuser/bin/myperl

Slide 26: mv ~/bin/perl5.8.8 whatever

Slide 27: whatever/bin/perl -e ‘use Storable’

Slide 28: Can't locate Storable.pm in @INC (@INC contains: /User/mark/bin/perl5.8.8/lib/5.8.8/ darwin-2level /User/mark/bin/perl5.8.8/lib/ 5.8.8 /User/mark/bin/perl5.8.8/lib/site_perl/ 5.8.8/darwin-2level /User/mark/bin/perl5.8.8/lib/ site_perl/5.8.8 /User/mark/bin/perl5.8.8/lib/ site_perl .) at -e line 1.

Slide 29: Can't locate Storable.pm in @INC (@INC contains: /User/mark/bin/perl5.8.8/lib/5.8.8/ darwin-2level /User/mark/bin/perl5.8.8/lib/ 5.8.8 /User/mark/bin/perl5.8.8/lib/site_perl/ 5.8.8/darwin-2level /User/mark/bin/perl5.8.8/lib/ site_perl/5.8.8 /User/mark/bin/perl5.8.8/lib/ site_perl .) at -e line 1.

Slide 30: Can't locate Storable.pm in @INC (@INC contains: ../lib/5.8.8/darwin-2level ../lib/5.8.8 ../lib/site_perl/5.8.8/darwin-2level ../lib/site_perl/5.8.8 ../lib/site_perl .) at -e line 1.

Slide 31: bleed to the rescue

Slide 32: B E TA Get Bleed Perl • lwp-request $CPAN_URL > perl-5.9.5.tar.gz • gunzip -c perl-5.9.5.tar.gz | tar -xvf - • cd perl-5.9.5

Slide 33: B E TA Tell it where to go • mkdir -p /User/mark/bin/perl5.9.5 • ./Configure -Dusedevel -Dprefix=/User/ mark/bin/perl5.9.5 -Duserelocatableinc -d

Slide 34: B E TA Tell it where to go • mkdir -p /User/mark/bin/perl5.9.5 • ./Configure -Dusedevel -Dprefix=/User/ mark/bin/perl5.9.5 -Duserelocatableinc -d

Slide 35: B E TA Install it • make • make test • make install

Slide 36: B E TA mv ~/bin/perl5.9.5 whatever

Slide 37: B E TA whatever/bin/perl5.9.5 -e ‘use Storable’

Slide 38: Exception Handling

Slide 39: Java try { throw new NoCheeseException(“redo”); } catch (NoCheeseException e) { system.err.println(e.toString()); }

Slide 40: Perl eval { die new NoCheeseError->new(“redo”); }; if (blessed($@) && $@->isa(“NoCheeseException”)) { print STDERR $@; } elsif ($@) { die $@ }

Slide 41: Perl has SUCKY SYNTAX

Slide 42: Sins include:

Slide 43: Perl eval { die new NoCheeseError->new(“redo”); }; if (blessed($@) && $@->isa(“NoCheeseException”)) { print STDERR $@; } elsif ($@) { die $@ }

Slide 44: die “stop my program”;

Slide 45: die “some catchable exception”;

Slide 46: Perl eval { die new NoCheeseError->new(“redo”); }; if (blessed($@) && $@->isa(“NoCheeseException”)) { print STDERR $@; } elsif ($@) { die $@ }

Slide 47: eval “some code to be compiled”;

Slide 48: eval { # run some code to catch errors in };

Slide 49: Perl eval { die new NoCheeseError->new(“redo”); }; if (blessed($@) && $@->isa(“NoCheeseException”)) { print STDERR $@; } elsif ($@) { die $@ }

Slide 50: Perl eval { die new NoCheeseError->new(“redo”); }; if (blessed($@) && $@->isa(“NoCheeseException”)) { print STDERR $@; } elsif ($@) { die $@ }

Slide 51: We can fix it!

Slide 52: (still) Perl try { throw NoCheeseException “redo”; } catch NoCheeseException with { print STDERR $@; };

Slide 53: try { throw NoCheeseException “redo”; } catch NoCheeseException with { print STDERR $@; } catch AnotherError with { print STDERR “oops\\n”; };

Slide 54: try { throw NoCheeseException “redo”; } catch NoCheeseException with { print STDERR $@; } catch AnotherError with { print STDERR “oops\\n”; };

Slide 55: try( sub { throw NoCheeseException “redo”; }, catch NoCheeseException with(sub { print STDERR $@; }, catch AnotherError with(sub { print STDERR “oops\\n”; })));

Slide 56: try( sub { throw NoCheeseException “redo”; }, catch NoCheeseException with(sub { print STDERR $@; }, catch AnotherError with(sub { print STDERR “oops\\n”; })));

Slide 57: try( sub { NoCheeseException->throw( “redo” ); }, NoCheeseException->catch( with(sub { print STDERR $@; }, AnotherError->catch( with(sub { print STDERR “oops\\n”; })))));

Slide 58: sub with (&;@) { return @_ }

Slide 59: try( sub { NoCheeseException->throw( “redo” ); }, NoCheeseException->catch( with(sub { print STDERR $@; }, AnotherError->catch( with(sub { print STDERR “oops\\n”; })))));

Slide 60: try( sub { NoCheeseException->throw( “redo” ); }, NoCheeseException->catch( sub { print STDERR $@; }, AnotherError->catch( sub { print STDERR “oops\\n”; })));

Slide 61: package OurErrorSuperclass; sub catch { my $class = shift; my $action = shift; return +{ class => $class, action => $action }, @_; }

Slide 62: try( sub { NoCheeseException->throw( “redo” ); }, NoCheeseException->catch( sub { print STDERR $@; }, AnotherError->catch( sub { print STDERR “oops\\n”; })));

Slide 63: try( sub { NoCheeseException->throw( “redo” ); }, NoCheeseException->catch( sub { print STDERR $@; }, +{ class => “AnotherError”, action => sub { print STDERR “oops\\n” } }));

Slide 64: try( sub { NoCheeseException->throw( “redo” ); }, +{ class => “NoCheeseException”, action => sub { print STDERR $@; } }, +{ class => “AnotherError”, action => sub { print STDERR “oops\\n” } });

Slide 65: try( sub { NoCheeseException->throw( “redo” ); }, +{ class => “NoCheeseException”, action => sub { print STDERR $@; } }, +{ class => “AnotherError”, action => sub { print STDERR “oops\\n” } });

Slide 66: try( sub { NoCheeseException->throw( “redo” ); }, +{ class => “NoCheeseException”, action => sub { print STDERR $@; } }, +{ class => “AnotherError”, action => sub { print STDERR “oops\\n” } });

Slide 67: try( sub { NoCheeseException->throw( “redo” ); }, +{ class => “NoCheeseException”, action => sub { print STDERR $@; } }, +{ class => “AnotherError”, action => sub { print STDERR “oops\\n” } });

Slide 68: (still) Perl try { throw NoCheeseException “redo”; } catch NoCheeseException with { print STDERR $@; };

Slide 69: sub foo { try { return “This doesn’t return from foo”; } catch NoCheeseException with { print STDERR $@; }; }

Slide 70: sub foo { eval { return “This doesn’t return from foo”; }; if ($@) { .... } }

Slide 71: sub foo { try { return “This doesn’t return from foo”; } catch NoCheeseException with { print STDERR $@; }; }

Slide 72: sub foo { try { rreturn “This doesn’t return from foo”; } catch NoCheeseException with { print STDERR $@; } and return allowed; }

Slide 73: sub foo { try { rreturn “This doesn’t return from foo”; } catch NoCheeseException with { print STDERR $@; } and return allowed; }

Slide 74: MyException NoDairyException NoSpreadException NoMilkException NoButterException NoMargException NoCheeseException NoEdamException NoStiltonException NoBrieException

Slide 75: package NoDairyException; our @ISA = qw(MyError); package NoMilkException; our @ISA = qw(NoDairyException); package NoSpreadException; our @ISA = qw(NoDairyException); package NoButterException; our @ISA = qw(NoSpreadException); package NoMargException; our @ISA = qw(NoMargeException); package NoCheeseException; our @ISA = qw(NoDairyException); package NoEdamException; our @ISA = qw(NoCheeseException); package NoStiltonException; our @ISA = qw(NoCheeseException); package NoBrieException; our@ISA = qw(NoCheeseException);

Slide 76: Exceptions::define { exception NoDairyException; exception NoSpreadException extends NoDairyException; exception NoButterException extends NoSpreadException; exception NoMargException extends NoSpreadException; exception NoMilkException extends NoDairyException; exception NoCheeseException extends NoDairyException; exception NoEdamException extends NoCheeseException; exception NoStiltonException extends NoCheeseException; exception NoBrieException extends NoCheeseException; };

Slide 77: But it’s a scripting language!

Slide 78: Don’t you just love the Template Toolkit?

Slide 79: bash$ tpage [% FOR a = [1..5]; a; END %] ^D 12345 bash$

Slide 80: #!perl $whereami = “Vienna”; print “Hello $whereami!\\n”;

Slide 81: #!tpage [% whereami = “Vienna” -%] Hello [% whereami %]!

Slide 82: bash$ ./hellov.tp

Slide 83: bash$ ./hellov.tp -bash: ./hellov.tp: tpage: bad interpreter: No such file or directory

Slide 84: where bash finds the Executable code to #!tpage load into memory [% whereami = “Vienna” -%] Hello [% whereami %]!

Slide 85: bash$ cat tpage #!/usr/bin/perl -w use strict; use Template; use AppConfig; …

Slide 86: Two possible solutions

Slide 87: Method one: Abuse source filters

Slide 88: • “Source filters are a way to change your source code before perl gets to see it”

Slide 89: #!/usr/bin/perl use strict; use warnings; use EnableDebugging; # DEBUG printing stuff out print \"hi\\n\";

Slide 90: #!/usr/bin/perl use strict; use warnings; use EnableDebugging; ;print STDERR “DEBUG: printing stuff out\\n”; print \"hi\\n\";

Slide 91: package EnableDebugging; use Filter::Simple; FILTER { s{#\\s*DEBUG\\s+(.*)} {;print STDERR q<DEBUG: $1>, \"\\n\";}; }; 1;

Slide 92: package EnableDebugging; use Filter::Simple; FILTER { s{#\\s*DEBUG\\s+(.*)} {;print STDERR q<DEBUG: $1>, \"\\n\";}; }; 1;

Slide 93: package tpage; use Filter::Simple; FILTER { s{#\\s*DEBUG\\s+(.*)} {;print STDERR q<DEBUG: $1>, \"\\n\";}; }; 1;

Slide 94: package tpage; use Filter::Simple; FILTER { s{#\\s*DEBUG\\s+(.*)} {;print STDERR q<DEBUG: $1>, \"\\n\";}; }; 1;

Slide 95: package tpage; use Filter::Simple; FILTER { $template .= $_; $_ = “”; }; 1;

Slide 96: package tpage; use Filter::Simple; FILTER { $template .= $_; $_ = “”; }; END { use Template; Template->new->process(\\$template); }

Slide 97: #!/usr/bin/perl use tpage; [%- whereami = “Vienna” -%] Hello [% whereami %]!

Slide 98: 2. Build our own executable

Slide 99: #include <EXTERN.h> #include <perl.h> static PerlInterpreter *my_perl; int main(int argc, char **argv, char **env) { char *embedding[] = { \"\", \"-e\", \"0\" }; PERL_SYS_INIT3(&argc,&argv,&env); my_perl = perl_alloc(); perl_construct(my_perl); perl_parse(my_perl, NULL, 3, embedding, NULL); PL_exit_flags |= PERL_EXIT_DESTRUCT_END; perl_run(my_perl); eval_pv(\"print qq'oh hai\\n’;\", TRUE); perl_destruct(my_perl); perl_free(my_perl); PERL_SYS_TERM(); }

Slide 100: ( stolen from “perldoc perlembed”)

Slide 101: #include <EXTERN.h> #include <perl.h> static PerlInterpreter *my_perl; int main(int argc, char **argv, char **env) { char *embedding[] = { \"\", \"-e\", \"0\" }; PERL_SYS_INIT3(&argc,&argv,&env); my_perl = perl_alloc(); perl_construct(my_perl); perl_parse(my_perl, NULL, 3, embedding, NULL); PL_exit_flags |= PERL_EXIT_DESTRUCT_END; perl_run(my_perl); eval_pv(\"print qq'o hai\\n';\", TRUE); perl_destruct(my_perl); perl_free(my_perl); PERL_SYS_TERM(); }

Slide 102: #include <EXTERN.h> #include <perl.h> static PerlInterpreter *my_perl; int main(int argc, char **argv, char **env) { char *embedding[] = { \"\", \"-e\", \"0\" }; PERL_SYS_INIT3(&argc,&argv,&env); my_perl = perl_alloc(); perl_construct(my_perl); perl_parse(my_perl, NULL, 3, embedding, NULL); PL_exit_flags |= PERL_EXIT_DESTRUCT_END; perl_run(my_perl); eval_pv(\"print qq’o hai\\n’;\", TRUE); perl_destruct(my_perl); perl_free(my_perl); PERL_SYS_TERM(); }

Slide 103: cc -o hellow hellow.c `perl -MExtUtils::Embed -e ccopts -e ldopts`

Slide 104: bash$ ./hellow o hai

Slide 105: #include <EXTERN.h> #include <perl.h> static PerlInterpreter *my_perl; int main(int argc, char **argv, char **env) { char *embedding[] = { \"\", \"-e\", \"0\" }; PERL_SYS_INIT3(&argc,&argv,&env); my_perl = perl_alloc(); perl_construct(my_perl); perl_parse(my_perl, NULL, 3, embedding, NULL); PL_exit_flags |= PERL_EXIT_DESTRUCT_END; perl_run(my_perl); eval_pv(\"print qq'o hai\\n';\", TRUE); perl_destruct(my_perl); perl_free(my_perl); PERL_SYS_TERM(); }

Slide 106: #include <EXTERN.h> #include <perl.h> static PerlInterpreter *my_perl; int main(int argc, char **argv, char **env) { char *embedding[] = { \"\", \"-e\", \"0\" }; PERL_SYS_INIT3(&argc,&argv,&env); my_perl = perl_alloc(); perl_construct(my_perl); perl_parse(my_perl, NULL, 3, embedding, NULL); PL_exit_flags |= PERL_EXIT_DESTRUCT_END; perl_run(my_perl); eval_pv(\"print qq’o hai\\n’;\", TRUE); perl_destruct(my_perl); perl_free(my_perl); PERL_SYS_TERM(); }

Slide 107: #include <EXTERN.h> #include <perl.h> static PerlInterpreter *my_perl; int main(int argc, char **argv, char **env) { char *embedding[] = { \"\", \"-e\", \"0\", argv[0]}; PERL_SYS_INIT3(&argc,&argv,&env); my_perl = perl_alloc(); perl_construct(my_perl); perl_parse(my_perl, NULL, 4, embedding, NULL); PL_exit_flags |= PERL_EXIT_DESTRUCT_END; perl_run(my_perl); eval_pv(\"print qq’o hai\\n’;\", TRUE); perl_destruct(my_perl); perl_free(my_perl); PERL_SYS_TERM(); }

Slide 108: #include <EXTERN.h> #include <perl.h> static PerlInterpreter *my_perl; int main(int argc, char **argv, char **env) { char *embedding[] = { \"\", \"-e\", \"0\", argv[0]}; PERL_SYS_INIT3(&argc,&argv,&env); my_perl = perl_alloc(); perl_construct(my_perl); perl_parse(my_perl, NULL, 4, embedding, NULL); PL_exit_flags |= PERL_EXIT_DESTRUCT_END; perl_run(my_perl); eval_pv(\"print qq’o hai\\n’;\", TRUE); perl_destruct(my_perl); perl_free(my_perl); PERL_SYS_TERM(); }

Slide 109: #include <EXTERN.h> #include <perl.h> static PerlInterpreter *my_perl; int main(int argc, char **argv, char **env) { char *embedding[] = { \"\", \"-e\", \"0\", argv[0]}; PERL_SYS_INIT3(&argc,&argv,&env); my_perl = perl_alloc(); perl_construct(my_perl); perl_parse(my_perl, NULL, 4, embedding, NULL); PL_exit_flags |= PERL_EXIT_DESTRUCT_END; perl_run(my_perl); eval_pv( “use Template \\ Template->new->process($ARGV[0])\", TRUE); perl_destruct(my_perl); perl_free(my_perl); PERL_SYS_TERM(); }

Slide 110: cc -o mytt mytt.c `perl -MExtUtils::Embed -e ccopts -e ldopts`

Slide 111: now Executable code to load into memory #!mytt [% whereami = “Vienna” -%] Hello [% whereami %]!

Slide 112: #include <EXTERN.h> #include <perl.h> static PerlInterpreter *my_perl; “hellov.tp” int main(int argc, char **argv, char **env) { char *embedding[] = { \"\", \"-e\", \"0\", argv[0]}; PERL_SYS_INIT3(&argc,&argv,&env); my_perl = perl_alloc(); perl_construct(my_perl); perl_parse(my_perl, NULL, 4, embedding, NULL); PL_exit_flags |= PERL_EXIT_DESTRUCT_END; perl_run(my_perl); eval_pv( “use Template \\ Template->new->process($ARGV[0])\", TRUE); perl_destruct(my_perl); perl_free(my_perl); PERL_SYS_TERM(); }

Slide 113: #include <EXTERN.h> #include <perl.h> static PerlInterpreter *my_perl; “hellov.tp” int main(int argc, char **argv, char **env) { char *embedding[] = { \"\", \"-e\", \"0\", argv[0]}; PERL_SYS_INIT3(&argc,&argv,&env); my_perl = perl_alloc(); perl_construct(my_perl); perl_parse(my_perl, NULL, 4, embedding, NULL); PL_exit_flags |= PERL_EXIT_DESTRUCT_END; perl_run(my_perl); eval_pv( “use Template \\ Template->new->process($ARGV[0])\", TRUE); perl_destruct(my_perl); perl_free(my_perl); PERL_SYS_TERM(); }

Slide 115: A LP H A We’ve already seen source filters

Slide 116: B E TA PPI • Pure Perl parser • Only parses a subset of Perl • Can’t tell the difference between certain Perl constructs • This said - very very good at what it does

Slide 117: A LP H A MAD

Slide 118: A LP H A ./configure.gnu --prefix=~/bin/perl595 -Dusedevel -Dmad=y make && make test && make install

Slide 119: A LP H A my $a = 1; my $b = 2; print $a + $b;

Slide 120: A LP H A PERL_XMLDUMP=\"foo.xml\" ./perl foo.pl

Slide 121: </op_nextstate> A LP <op_sassign seq=\"9 -> 10\" H flags=\"VOID,KIDS,STACKED\"> A <op_leave seq=\"0 -> DONE\" targ=\"1\" flags=\"VOID,KIDS,PARENS\" private=\"REFCOUNTED\" refcnt=\"1\"> <op_enter seq=\"1 -> 2\" /> <op_null seq=\"0 -> (2)\" flags=\"VOID\"> <madprops> <mad_sv key=\";\" val=\"\"/> </madprops> <madprops> </op_null> <op_nextstate seq=\"2 -> 3\" flags=\"VOID\" line=\"1\" package=\"main\"> <madprops> <mad_sv key=\";\" val=\";\"/> <mad_sv key=\"#;\" val=\"&#xA;\"/> </madprops> <mad_sv key=\"o\" val=\"=\"/> </op_nextstate> <op_sassign seq=\"5 -> 6\" flags=\"VOID,KIDS,STACKED\"> <madprops> <mad_sv key=\"o\" val=\"=\"/> <mad_sv key=\"_o\" val=\" \"/> </madprops> <op_const seq=\"3 -> 4\" flags=\"SCALAR\" IV=\"1\"> <mad_sv key=\"_o\" val=\" \"/> <madprops> <mad_sv key=\"X\" val=\"1\"/> <mad_sv key=\"_X\" val=\" \"/> </madprops> </op_const> <op_padsv seq=\"4 -> 5\" targ=\"1\" flags=\"SCALAR,REF,MOD,SPECIAL\" private=\"INTRO\"> <madprops> </madprops> <mad_sv key=\"$\" val=\"$a\"/> <mad_sv key=\"_$\" val=\" \"/> <mad_sv key=\"d\" val=\"my\"/> <mad_sv key=\"_d\" val=\"\"/> </madprops> </op_padsv> </op_sassign> <op_nextstate seq=\"6 -> 7\" flags=\"VOID\" <op_const seq=\"7 -> 8\" flags=\"SCALAR\" line=\"2\" package=\"main\"> <madprops> <mad_sv key=\";\" val=\";\"/> <mad_sv key=\"#;\" val=\"&#xA;\"/> </madprops> </op_nextstate> <op_sassign seq=\"9 -> 10\" flags=\"VOID,KIDS,STACKED\"> <madprops> IV=\"2\"> <mad_sv key=\"o\" val=\"=\"/> <mad_sv key=\"_o\" val=\" \"/> </madprops> <op_const seq=\"7 -> 8\" flags=\"SCALAR\" IV=\"2\"> <madprops> <mad_sv key=\"X\" val=\"2\"/> <mad_sv key=\"_X\" val=\" \"/> <madprops> </madprops> </op_const> <op_padsv seq=\"8 -> 9\" targ=\"2\" flags=\"SCALAR,REF,MOD,SPECIAL\" private=\"INTRO\"> <madprops> <mad_sv key=\"$\" val=\"$b\"/> <mad_sv key=\"_$\" val=\" \"/> <mad_sv key=\"d\" val=\"my\"/> <mad_sv key=\"X\" val=\"2\"/> </madprops> </op_padsv> </op_sassign> <op_nextstate seq=\"10 -> 11\" flags=\"VOID\" line=\"3\" package=\"main\"> <madprops> <mad_sv key=\";\" val=\";\"/> <mad_sv key=\"_X\" val=\" \"/> <mad_sv key=\"_;\" val=\"\"/> <mad_sv key=\"#;\" val=\"&#xA;\"/> </madprops> </op_nextstate> <op_print seq=\"15 -> 16\" flags=\"SCALAR,KIDS\"> <madprops> <mad_sv key=\"o\" val=\"print\"/> </madprops> </madprops> <op_pushmark seq=\"11 -> 12\" flags=\"SCALAR\" /> <op_add seq=\"14 -> 15\" targ=\"3\" flags=\"SCALAR,KIDS\"> <madprops> <mad_sv key=\"o\" val=\"+\"/> <mad_sv key=\"_o\" val=\" \"/> </madprops> <op_padsv seq=\"12 -> 13\" targ=\"1\" flags=\"SCALAR\"> <madprops> </op_const> <mad_sv key=\"$\" val=\"$a\"/> <mad_sv key=\"_$\" val=\" \"/> </madprops> </op_padsv> <op_padsv seq=\"13 -> 14\" targ=\"2\" flags=\"SCALAR\"> <madprops> <mad_sv key=\"$\" val=\"$b\"/> <mad_sv key=\"_$\" val=\" \"/> </madprops> <op_padsv seq=\"8 -> 9\" targ=\"2\" </op_padsv> </op_add> </op_print> <op_null seq=\"0 -> (16)\" flags=\"VOID\" /> </op_leave> flags=\"SCALAR,REF,MOD,SPECIAL\"

Slide 122: B::Generate • Can be used to create OP codes (i.e. compiled Perl code) directly from Perl

Slide 123: use B::Generate; # Do nothing, slowly. CHECK { my $null = new B::OP(\"null\",0); my $enter = new B::OP(\"enter\",0); my $cop = new B::COP(0, \"hiya\", 0); my $leave = new B::LISTOP(\"leave\", 0, $enter, $null); $leave->children(3); $enter->sibling($cop); $enter->next($cop); $cop->sibling($null); $null->next($leave); $cop->next($leave); # Tell Perl where to find our tree. B::main_root($leave); B::main_start($enter); }

Slide 124: optomize.pm • Can be used to manipulate the OP codes after they’ve loaded • Kinda like source filters for compiled bypecode

Slide 125: Use? • PPI is reliable, but limited in it’s ability • Easy to try to do too much with • Other techniques are very unstable / new • B::Generate • optomize • MAD

Slide 127: A LP H A package main; use typesafety; # 'summary', 'debug'; my FooBar $foo; # establish type-checked variables my FooBar $bar; # FooBar is the base class of references $bar will hold my BazQux $baz; $foo = new FooBar; # this is okay, because $foo holds FooBars $bar = $foo; # this is okay, because $bar also holds FooBars # $foo = 10; # this would throw an error - 10 is not a FooBar # $baz = $foo; # not allowed - FooBar isn't a BazQux $foo = $baz; # is allowed - BazQux is a FooBar because of inheritance $bar = $foo->foo($baz, 1); # this is okay, as FooBar::foo() returns FooBars also typesafety::check(); # perform type check static analysis

Slide 128: A LP H A package main; use typesafety; # 'summary', 'debug'; my FooBar $foo; # establish type-checked variables my FooBar $bar; # FooBar is the base class of references $bar will hold my BazQux $baz; $foo = new FooBar; # this is okay, because $foo holds FooBars $bar = $foo; # this is okay, because $bar also holds FooBars # $foo = 10; # this would throw an error - 10 is not a FooBar # $baz = $foo; # not allowed - FooBar isn't a BazQux $foo = $baz; # is allowed - BazQux is a FooBar because of inheritance $bar = $foo->foo($baz, 1); # this is okay, as FooBar::foo() returns FooBars also typesafety::check(); # perform type check static analysis

Slide 129: A LP H A package main; use typesafety; # 'summary', 'debug'; my FooBar $foo; # establish type-checked variables my FooBar $bar; # FooBar is the base class of references $bar will hold my BazQux $baz; $foo = new FooBar; # this is okay, because $foo holds FooBars $bar = $foo; # this is okay, because $bar also holds FooBars # $foo = 10; # this would throw an error - 10 is not a FooBar # $baz = $foo; # not allowed - FooBar isn't a BazQux $foo = $baz; # is allowed - BazQux is a FooBar because of inheritance $bar = $foo->foo($baz, 1); # this is okay, as FooBar::foo() returns FooBars also typesafety::check(); # perform type check static analysis

Slide 130: A LP H A package main; use typesafety; # 'summary', 'debug'; my FooBar $foo; # establish type-checked variables my FooBar $bar; # FooBar is the base class of references $bar will hold my BazQux $baz; $foo = new FooBar; # this is okay, because $foo holds FooBars $bar = $foo; # this is okay, because $bar also holds FooBars # $foo = 10; # this would throw an error - 10 is not a FooBar # $baz = $foo; # not allowed - FooBar isn't a BazQux $foo = $baz; # is allowed - BazQux is a FooBar because of inheritance $bar = $foo->foo($baz, 1); # this is okay, as FooBar::foo() returns FooBars also typesafety::check(); # perform type check static analysis