perl sucks - and what to do about it

Post on 10-May-2015

22.704 Views

Category:

Technology

4 Downloads

Preview:

Click to see full reader

DESCRIPTION

(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...

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 "Hello World\n";

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 "Hello World\n";

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.8whatever

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

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

BETA

Tell it where to go

• mkdir -p /User/mark/bin/perl5.9.5

• ./Configure -Dusedevel -Dprefix=/User/mark/bin/perl5.9.5 -Duserelocatableinc -d

BETA

Tell it where to go

• mkdir -p /User/mark/bin/perl5.9.5

• ./Configure -Dusedevel -Dprefix=/User/mark/bin/perl5.9.5 -Duserelocatableinc -d

BETA

Install it

• make

• make test

• make install

BETA

mv ~/bin/perl5.9.5whatever

BETA

whatever/bin/perl5.9.5 -e ‘use Storable’

BETA

Exception Handling

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

Java

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

Perl

Perl has SUCKY SYNTAX

Sins include:

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

Perl

die “stop my program”;

die “some catchable exception”;

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

Perl

eval “some code to be compiled”;

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

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 $@ }

Perl

We can fix it!

try { throw NoCheeseException “redo”;}catch NoCheeseException with { print STDERR $@;};

(still) Perl

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

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

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

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

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

sub with (&;@) { return @_}

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

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

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 “oops\n”;})));

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

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

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

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

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

try { throw NoCheeseException “redo”;}catch NoCheeseException with { print STDERR $@;};

(still) Perl

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

NoCheeseException

NoDairyException

NoMilkException

NoSpreadException

NoEdamException NoStiltonException NoBrieException

NoButterException

NoMargException

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 %]^D12345bash$

#!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

#!tpage

[% whereami = “Vienna” -%]Hello [% whereami %]!

where bash finds theExecutable code to

load into memory

bash$ cat tpage#!/usr/bin/perl -wuse 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 outprint "hi\n";

#!/usr/bin/perl

use strict;use warnings;

use EnableDebugging;

;print STDERR “DEBUG: printing stuff out\n”;print "hi\n";

package EnableDebugging;use Filter::Simple;

FILTER { s{#\s*DEBUG\s+(.*)} {;print STDERR q<DEBUG: $1>, "\n";};};

1;

package EnableDebugging;use Filter::Simple;

FILTER { s{#\s*DEBUG\s+(.*)} {;print STDERR q<DEBUG: $1>, "\n";};};

1;

package tpage;use Filter::Simple;

FILTER { s{#\s*DEBUG\s+(.*)} {;print STDERR q<DEBUG: $1>, "\n";};};

1;

package tpage;use Filter::Simple;

FILTER { s{#\s*DEBUG\s+(.*)} {;print STDERR q<DEBUG: $1>, "\n";};};

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/perluse 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[] = { "", "-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();}

stolen from “perldoc perlembed”)(

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

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

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

bash$ ./hellowo hai

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

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

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

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

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

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

#!mytt

[% whereami = “Vienna” -%]Hello [% whereami %]!

now Executable code toload into memory

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

“hellov.tp”

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

“hellov.tp”

We’ve already seen source filters

ALPHA

• 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

PPIBETA

MAD

ALPHA

./configure.gnu --prefix=~/bin/perl595 -Dusedevel -Dmad=y

make && make test && make install

ALPHA

my $a = 1;my $b = 2;

print $a + $b;

ALPHA

PERL_XMLDUMP="foo.xml" ./perl foo.pl

ALPHA

<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> </op_null> <op_nextstate seq="2 -> 3" flags="VOID" line="1" package="main"> <madprops> <mad_sv key=";" val=";"/> <mad_sv key="#;" val="&#xA;"/> </madprops> </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"> <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> <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" 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> <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> </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"/> </madprops> </op_padsv> </op_sassign> <op_nextstate seq="10 -> 11" flags="VOID" line="3" package="main"> <madprops> <mad_sv key=";" 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> <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> <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> </op_add> </op_print> <op_null seq="0 -> (16)" flags="VOID" /></op_leave>

<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> </op_null>

<op_nextstate seq="2 -> 3" flags="VOID" line="1"

package="main"> <madprops>

<mad_sv key=";" val=";"/> <mad_sv key="#;" val="&#xA;"/>

</madprops> </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"> <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>

<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"

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> <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> </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"/> </madprops>

</op_padsv> </op_sassign>

<op_nextstate seq="10 -> 11" flags="VOID" line="3"

package="main"> <madprops>

<mad_sv key=";" 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>

<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>

<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>

</op_add> </op_print>

<op_null seq="0 -> (16)" flags="VOID" /></op_leave>

ALPHA

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("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); }

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

package main;use typesafety; # 'summary', 'debug';

my FooBar $foo; # establish type-checked variablesmy FooBar $bar; # FooBar is the base class of references $bar will holdmy 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

ALPHA

package main;use typesafety; # 'summary', 'debug';

my FooBar $foo; # establish type-checked variablesmy FooBar $bar; # FooBar is the base class of references $bar will holdmy 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

ALPHA

package main;use typesafety; # 'summary', 'debug';

my FooBar $foo; # establish type-checked variablesmy FooBar $bar; # FooBar is the base class of references $bar will holdmy 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

ALPHA

package main;use typesafety; # 'summary', 'debug';

my FooBar $foo; # establish type-checked variablesmy FooBar $bar; # FooBar is the base class of references $bar will holdmy 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

ALPHA

top related