Perl Sucks - and what to do about it
Upcoming SlideShare
Loading in...5
×
 

Perl Sucks - and what to do about it

on

  • 31,411 views

(originally presented at YAPC::Europe::2007) ...

(originally presented at YAPC::Europe::2007)

No-one is as critical about something as those that love it dearly. Mark Fowler has been collecting complaints from professional Perl developers for years about what warts still remain with the language when strict and warnings are turned on.

Are these problems unsolvable? A veteran Perl programmer himself Mark attempted to try and solve these issues - and then turned to the experts, the people who write books on Perl, the people who maintain the perl interpreter itself, for help.

This is what he learned...

Statistics

Views

Total Views
31,411
Views on SlideShare
31,211
Embed Views
200

Actions

Likes
15
Downloads
547
Comments
7

17 Embeds 200

http://copypast.ru 82
http://blog.xwolf.de 43
http://www.slideshare.net 29
http://www.kt.rim.or.jp 15
http://thomas-fahle.blogspot.com 9
http://wp.monotechnology.com:8088 7
http://pda.copypast.ru 3
http://www.filescon.com 2
http://test.takeoverapp.com 2
http://s.deeeki.com 1
http://www.takeoverapp.com 1
http://www.allslides.com 1
http://www.ig.gmodules.com 1
http://www.fachak.com 1
http://ig.gmodules.com 1
http://www.easyrapidshare.com 1
http://lambda.sgr 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

CC Attribution-NoDerivs LicenseCC Attribution-NoDerivs License

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel

17 of 7 Post a comment

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
  • It looks like trying to bend Perl into being Lisp.
    Are you sure you want to
    Your message goes here
    Processing…
  • Error.pm indeed can be used for exceptions, and I did mention it in the talk (just not on the written slides.) You'll note most of my syntax is the same as Error.pm's too.
    Are you sure you want to
    Your message goes here
    Processing…
  • Error.pm can be used for exceptions.
    Are you sure you want to
    Your message goes here
    Processing…
  • 'But when it comes time to run one of the commands...'
    Are you sure you want to
    Your message goes here
    Processing…
  • 'Normally I can just SCP the files from my home linux box to the new machine'
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Perl Sucks - and what to do about it Perl Sucks - and what to do about it Presentation Transcript

    • Perl Sucks! (and what to do about it)
    • 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”
    • What this talk is • What’s a few major annoyances with Perl • What we the humble programmer can do to work around them
    • ~/bin
    • scp ~/bin nethost:
    • ssh newhost
    • jabme -m ‘compile done’
    • Module “Jabber::Lite” not found
    • -bash: jabme: /usr/local/bin/ perl: bad interpreter: No such file or directory
    • My Scripts Need • A particular version of Perl • A set of Perl modules
    • PAR
    • #!/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 quot;Hello Worldnquot;;
    • Make an executable • perl -MCPAN -e ‘install PAR::Packer’ • pp -o hellow hellow.pl • ...copy “hellow” to new computer • ./hellow Hello World
    • #!/usr/bin/perl use strict; use warnings; print quot;Hello Worldnquot;;
    • Build our own Perl and ship the whole thing
    • 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
    • Tell it where to go • mkdir -p /User/mark/bin/perl5.8.8 • ./configure.gnu --prefix=/User/mark/bin/ perl5.8.8
    • Install it • make • make test • make install
    • We now have our own perl in ~/bin
    • We can install it’s own modules
    • ~/bin/perl5.8.8/bin/perl -MCPAN -e ‘install Template’
    • Problem: different paths • /home/mark/bin/myperl • /home/mfowler/bin/myperl • /home/nisuser/bin/myperl
    • mv ~/bin/perl5.8.8 whatever
    • whatever/bin/perl -e ‘use Storable’
    • 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.
    • 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.
    • 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.
    • bleed to the rescue
    • 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
    • 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
    • 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
    • B E TA Install it • make • make test • make install
    • B E TA mv ~/bin/perl5.9.5 whatever
    • B E TA whatever/bin/perl5.9.5 -e ‘use Storable’
    • Exception Handling
    • Java try { throw new NoCheeseException(“redo”); } catch (NoCheeseException e) { system.err.println(e.toString()); }
    • Perl eval { die new NoCheeseError->new(“redo”); }; if (blessed($@) && $@->isa(“NoCheeseException”)) { print STDERR $@; } elsif ($@) { die $@ }
    • Perl has SUCKY SYNTAX
    • Sins include:
    • Perl eval { die new NoCheeseError->new(“redo”); }; if (blessed($@) && $@->isa(“NoCheeseException”)) { print STDERR $@; } elsif ($@) { die $@ }
    • die “stop my program”;
    • die “some catchable exception”;
    • Perl eval { die new NoCheeseError->new(“redo”); }; if (blessed($@) && $@->isa(“NoCheeseException”)) { print STDERR $@; } elsif ($@) { die $@ }
    • eval “some code to be compiled”;
    • eval { # run some code to catch errors in };
    • Perl eval { die new NoCheeseError->new(“redo”); }; if (blessed($@) && $@->isa(“NoCheeseException”)) { print STDERR $@; } elsif ($@) { die $@ }
    • Perl eval { die new NoCheeseError->new(“redo”); }; if (blessed($@) && $@->isa(“NoCheeseException”)) { print STDERR $@; } elsif ($@) { die $@ }
    • We can fix it!
    • (still) Perl try { throw NoCheeseException “redo”; } catch NoCheeseException with { print STDERR $@; };
    • try { throw NoCheeseException “redo”; } catch NoCheeseException with { print STDERR $@; } catch AnotherError with { print STDERR “oopsn”; };
    • try { throw NoCheeseException “redo”; } catch NoCheeseException with { print STDERR $@; } catch AnotherError with { print STDERR “oopsn”; };
    • try( sub { throw NoCheeseException “redo”; }, catch NoCheeseException with(sub { print STDERR $@; }, catch AnotherError with(sub { print STDERR “oopsn”; })));
    • try( sub { throw NoCheeseException “redo”; }, catch NoCheeseException with(sub { print STDERR $@; }, catch AnotherError with(sub { print STDERR “oopsn”; })));
    • try( sub { NoCheeseException->throw( “redo” ); }, NoCheeseException->catch( with(sub { print STDERR $@; }, AnotherError->catch( with(sub { print STDERR “oopsn”; })))));
    • sub with (&;@) { return @_ }
    • try( sub { NoCheeseException->throw( “redo” ); }, NoCheeseException->catch( with(sub { print STDERR $@; }, AnotherError->catch( with(sub { print STDERR “oopsn”; })))));
    • try( sub { NoCheeseException->throw( “redo” ); }, NoCheeseException->catch( sub { print STDERR $@; }, AnotherError->catch( sub { print STDERR “oopsn”; })));
    • package OurErrorSuperclass; sub catch { my $class = shift; my $action = shift; return +{ class => $class, action => $action }, @_; }
    • try( sub { NoCheeseException->throw( “redo” ); }, NoCheeseException->catch( sub { print STDERR $@; }, AnotherError->catch( sub { print STDERR “oopsn”; })));
    • try( sub { NoCheeseException->throw( “redo” ); }, NoCheeseException->catch( sub { print STDERR $@; }, +{ class => “AnotherError”, action => sub { print STDERR “oopsn” } }));
    • try( sub { NoCheeseException->throw( “redo” ); }, +{ class => “NoCheeseException”, action => sub { print STDERR $@; } }, +{ class => “AnotherError”, action => sub { print STDERR “oopsn” } });
    • try( sub { NoCheeseException->throw( “redo” ); }, +{ class => “NoCheeseException”, action => sub { print STDERR $@; } }, +{ class => “AnotherError”, action => sub { print STDERR “oopsn” } });
    • try( sub { NoCheeseException->throw( “redo” ); }, +{ class => “NoCheeseException”, action => sub { print STDERR $@; } }, +{ class => “AnotherError”, action => sub { print STDERR “oopsn” } });
    • try( sub { NoCheeseException->throw( “redo” ); }, +{ class => “NoCheeseException”, action => sub { print STDERR $@; } }, +{ class => “AnotherError”, action => sub { print STDERR “oopsn” } });
    • (still) Perl try { throw NoCheeseException “redo”; } catch NoCheeseException with { print STDERR $@; };
    • sub foo { try { return “This doesn’t return from foo”; } catch NoCheeseException with { print STDERR $@; }; }
    • sub foo { eval { return “This doesn’t return from foo”; }; if ($@) { .... } }
    • sub foo { try { return “This doesn’t return from foo”; } catch NoCheeseException with { print STDERR $@; }; }
    • sub foo { try { rreturn “This doesn’t return from foo”; } catch NoCheeseException with { print STDERR $@; } and return allowed; }
    • sub foo { try { rreturn “This doesn’t return from foo”; } catch NoCheeseException with { print STDERR $@; } and return allowed; }
    • MyException NoDairyException NoSpreadException NoMilkException NoButterException NoMargException NoCheeseException NoEdamException NoStiltonException NoBrieException
    • 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);
    • 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; };
    • But it’s a scripting language!
    • Don’t you just love the Template Toolkit?
    • bash$ tpage [% FOR a = [1..5]; a; END %] ^D 12345 bash$
    • #!perl $whereami = “Vienna”; print “Hello $whereami!n”;
    • #!tpage [% whereami = “Vienna” -%] Hello [% whereami %]!
    • bash$ ./hellov.tp
    • bash$ ./hellov.tp -bash: ./hellov.tp: tpage: bad interpreter: No such file or directory
    • where bash finds the Executable code to #!tpage load into memory [% whereami = “Vienna” -%] Hello [% whereami %]!
    • bash$ cat tpage #!/usr/bin/perl -w use strict; use Template; use AppConfig; …
    • Two possible solutions
    • Method one: Abuse source filters
    • • “Source filters are a way to change your source code before perl gets to see it”
    • #!/usr/bin/perl use strict; use warnings; use EnableDebugging; # DEBUG printing stuff out print quot;hinquot;;
    • #!/usr/bin/perl use strict; use warnings; use EnableDebugging; ;print STDERR “DEBUG: printing stuff outn”; print quot;hinquot;;
    • package EnableDebugging; use Filter::Simple; FILTER { s{#s*DEBUGs+(.*)} {;print STDERR q<DEBUG: $1>, quot;nquot;;}; }; 1;
    • package EnableDebugging; use Filter::Simple; FILTER { s{#s*DEBUGs+(.*)} {;print STDERR q<DEBUG: $1>, quot;nquot;;}; }; 1;
    • package tpage; use Filter::Simple; FILTER { s{#s*DEBUGs+(.*)} {;print STDERR q<DEBUG: $1>, quot;nquot;;}; }; 1;
    • package tpage; use Filter::Simple; FILTER { s{#s*DEBUGs+(.*)} {;print STDERR q<DEBUG: $1>, quot;nquot;;}; }; 1;
    • package tpage; use Filter::Simple; FILTER { $template .= $_; $_ = “”; }; 1;
    • package tpage; use Filter::Simple; FILTER { $template .= $_; $_ = “”; }; END { use Template; Template->new->process($template); }
    • #!/usr/bin/perl use tpage; [%- whereami = “Vienna” -%] Hello [% whereami %]!
    • 2. Build our own executable
    • #include <EXTERN.h> #include <perl.h> static PerlInterpreter *my_perl; int main(int argc, char **argv, char **env) { char *embedding[] = { quot;quot;, quot;-equot;, quot;0quot; }; 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(quot;print qq'oh hain’;quot;, TRUE); perl_destruct(my_perl); perl_free(my_perl); PERL_SYS_TERM(); }
    • ( stolen from “perldoc perlembed”)
    • #include <EXTERN.h> #include <perl.h> static PerlInterpreter *my_perl; int main(int argc, char **argv, char **env) { char *embedding[] = { quot;quot;, quot;-equot;, quot;0quot; }; 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(quot;print qq'o hain';quot;, TRUE); perl_destruct(my_perl); perl_free(my_perl); PERL_SYS_TERM(); }
    • #include <EXTERN.h> #include <perl.h> static PerlInterpreter *my_perl; int main(int argc, char **argv, char **env) { char *embedding[] = { quot;quot;, quot;-equot;, quot;0quot; }; 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(quot;print qq’o hain’;quot;, TRUE); perl_destruct(my_perl); perl_free(my_perl); PERL_SYS_TERM(); }
    • cc -o hellow hellow.c `perl -MExtUtils::Embed -e ccopts -e ldopts`
    • bash$ ./hellow o hai
    • #include <EXTERN.h> #include <perl.h> static PerlInterpreter *my_perl; int main(int argc, char **argv, char **env) { char *embedding[] = { quot;quot;, quot;-equot;, quot;0quot; }; 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(quot;print qq'o hain';quot;, TRUE); perl_destruct(my_perl); perl_free(my_perl); PERL_SYS_TERM(); }
    • #include <EXTERN.h> #include <perl.h> static PerlInterpreter *my_perl; int main(int argc, char **argv, char **env) { char *embedding[] = { quot;quot;, quot;-equot;, quot;0quot; }; 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(quot;print qq’o hain’;quot;, TRUE); perl_destruct(my_perl); perl_free(my_perl); PERL_SYS_TERM(); }
    • #include <EXTERN.h> #include <perl.h> static PerlInterpreter *my_perl; int main(int argc, char **argv, char **env) { char *embedding[] = { quot;quot;, quot;-equot;, quot;0quot;, 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(quot;print qq’o hain’;quot;, TRUE); perl_destruct(my_perl); perl_free(my_perl); PERL_SYS_TERM(); }
    • #include <EXTERN.h> #include <perl.h> static PerlInterpreter *my_perl; int main(int argc, char **argv, char **env) { char *embedding[] = { quot;quot;, quot;-equot;, quot;0quot;, 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(quot;print qq’o hain’;quot;, TRUE); perl_destruct(my_perl); perl_free(my_perl); PERL_SYS_TERM(); }
    • #include <EXTERN.h> #include <perl.h> static PerlInterpreter *my_perl; int main(int argc, char **argv, char **env) { char *embedding[] = { quot;quot;, quot;-equot;, quot;0quot;, 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])quot;, TRUE); perl_destruct(my_perl); perl_free(my_perl); PERL_SYS_TERM(); }
    • cc -o mytt mytt.c `perl -MExtUtils::Embed -e ccopts -e ldopts`
    • now Executable code to load into memory #!mytt [% whereami = “Vienna” -%] Hello [% whereami %]!
    • #include <EXTERN.h> #include <perl.h> static PerlInterpreter *my_perl; “hellov.tp” int main(int argc, char **argv, char **env) { char *embedding[] = { quot;quot;, quot;-equot;, quot;0quot;, 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])quot;, TRUE); perl_destruct(my_perl); perl_free(my_perl); PERL_SYS_TERM(); }
    • #include <EXTERN.h> #include <perl.h> static PerlInterpreter *my_perl; “hellov.tp” int main(int argc, char **argv, char **env) { char *embedding[] = { quot;quot;, quot;-equot;, quot;0quot;, 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])quot;, TRUE); perl_destruct(my_perl); perl_free(my_perl); PERL_SYS_TERM(); }
    • A LP H A We’ve already seen source filters
    • 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
    • A LP H A MAD
    • A LP H A ./configure.gnu --prefix=~/bin/perl595 -Dusedevel -Dmad=y make && make test && make install
    • A LP H A my $a = 1; my $b = 2; print $a + $b;
    • A LP H A PERL_XMLDUMP=quot;foo.xmlquot; ./perl foo.pl
    • </op_nextstate> A LP <op_sassign seq=quot;9 -> 10quot; H flags=quot;VOID,KIDS,STACKEDquot;> A <op_leave seq=quot;0 -> DONEquot; targ=quot;1quot; flags=quot;VOID,KIDS,PARENSquot; private=quot;REFCOUNTEDquot; refcnt=quot;1quot;> <op_enter seq=quot;1 -> 2quot; /> <op_null seq=quot;0 -> (2)quot; flags=quot;VOIDquot;> <madprops> <mad_sv key=quot;;quot; val=quot;quot;/> </madprops> <madprops> </op_null> <op_nextstate seq=quot;2 -> 3quot; flags=quot;VOIDquot; line=quot;1quot; package=quot;mainquot;> <madprops> <mad_sv key=quot;;quot; val=quot;;quot;/> <mad_sv key=quot;#;quot; val=quot;&#xA;quot;/> </madprops> <mad_sv key=quot;oquot; val=quot;=quot;/> </op_nextstate> <op_sassign seq=quot;5 -> 6quot; flags=quot;VOID,KIDS,STACKEDquot;> <madprops> <mad_sv key=quot;oquot; val=quot;=quot;/> <mad_sv key=quot;_oquot; val=quot; quot;/> </madprops> <op_const seq=quot;3 -> 4quot; flags=quot;SCALARquot; IV=quot;1quot;> <mad_sv key=quot;_oquot; val=quot; quot;/> <madprops> <mad_sv key=quot;Xquot; val=quot;1quot;/> <mad_sv key=quot;_Xquot; val=quot; quot;/> </madprops> </op_const> <op_padsv seq=quot;4 -> 5quot; targ=quot;1quot; flags=quot;SCALAR,REF,MOD,SPECIALquot; private=quot;INTROquot;> <madprops> </madprops> <mad_sv key=quot;$quot; val=quot;$aquot;/> <mad_sv key=quot;_$quot; val=quot; quot;/> <mad_sv key=quot;dquot; val=quot;myquot;/> <mad_sv key=quot;_dquot; val=quot;quot;/> </madprops> </op_padsv> </op_sassign> <op_nextstate seq=quot;6 -> 7quot; flags=quot;VOIDquot; <op_const seq=quot;7 -> 8quot; flags=quot;SCALARquot; line=quot;2quot; package=quot;mainquot;> <madprops> <mad_sv key=quot;;quot; val=quot;;quot;/> <mad_sv key=quot;#;quot; val=quot;&#xA;quot;/> </madprops> </op_nextstate> <op_sassign seq=quot;9 -> 10quot; flags=quot;VOID,KIDS,STACKEDquot;> <madprops> IV=quot;2quot;> <mad_sv key=quot;oquot; val=quot;=quot;/> <mad_sv key=quot;_oquot; val=quot; quot;/> </madprops> <op_const seq=quot;7 -> 8quot; flags=quot;SCALARquot; IV=quot;2quot;> <madprops> <mad_sv key=quot;Xquot; val=quot;2quot;/> <mad_sv key=quot;_Xquot; val=quot; quot;/> <madprops> </madprops> </op_const> <op_padsv seq=quot;8 -> 9quot; targ=quot;2quot; flags=quot;SCALAR,REF,MOD,SPECIALquot; private=quot;INTROquot;> <madprops> <mad_sv key=quot;$quot; val=quot;$bquot;/> <mad_sv key=quot;_$quot; val=quot; quot;/> <mad_sv key=quot;dquot; val=quot;myquot;/> <mad_sv key=quot;Xquot; val=quot;2quot;/> </madprops> </op_padsv> </op_sassign> <op_nextstate seq=quot;10 -> 11quot; flags=quot;VOIDquot; line=quot;3quot; package=quot;mainquot;> <madprops> <mad_sv key=quot;;quot; val=quot;;quot;/> <mad_sv key=quot;_Xquot; val=quot; quot;/> <mad_sv key=quot;_;quot; val=quot;quot;/> <mad_sv key=quot;#;quot; val=quot;&#xA;quot;/> </madprops> </op_nextstate> <op_print seq=quot;15 -> 16quot; flags=quot;SCALAR,KIDSquot;> <madprops> <mad_sv key=quot;oquot; val=quot;printquot;/> </madprops> </madprops> <op_pushmark seq=quot;11 -> 12quot; flags=quot;SCALARquot; /> <op_add seq=quot;14 -> 15quot; targ=quot;3quot; flags=quot;SCALAR,KIDSquot;> <madprops> <mad_sv key=quot;oquot; val=quot;+quot;/> <mad_sv key=quot;_oquot; val=quot; quot;/> </madprops> <op_padsv seq=quot;12 -> 13quot; targ=quot;1quot; flags=quot;SCALARquot;> <madprops> </op_const> <mad_sv key=quot;$quot; val=quot;$aquot;/> <mad_sv key=quot;_$quot; val=quot; quot;/> </madprops> </op_padsv> <op_padsv seq=quot;13 -> 14quot; targ=quot;2quot; flags=quot;SCALARquot;> <madprops> <mad_sv key=quot;$quot; val=quot;$bquot;/> <mad_sv key=quot;_$quot; val=quot; quot;/> </madprops> <op_padsv seq=quot;8 -> 9quot; targ=quot;2quot; </op_padsv> </op_add> </op_print> <op_null seq=quot;0 -> (16)quot; flags=quot;VOIDquot; /> </op_leave> flags=quot;SCALAR,REF,MOD,SPECIALquot;
    • B::Generate • Can be used to create OP codes (i.e. compiled Perl code) directly from Perl
    • use B::Generate; # Do nothing, slowly. CHECK { my $null = new B::OP(quot;nullquot;,0); my $enter = new B::OP(quot;enterquot;,0); my $cop = new B::COP(0, quot;hiyaquot;, 0); my $leave = new B::LISTOP(quot;leavequot;, 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); }
    • optomize.pm • Can be used to manipulate the OP codes after they’ve loaded • Kinda like source filters for compiled bypecode
    • 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
    • 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
    • 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
    • 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
    • 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