Top Banner
prototype::signatures xxx HERE BE DRAGONS xxx YAPC::EU 2008 Chia-liang Kao
49

prototype::signatures

May 06, 2015

Download

Business

clkao

Declare subroutine signatures without using a source filter! add type-contraint, name-based calling convention, without a source filter, benchmarked faster than traditional hash passing!

This is a Perl 5 talk. come learn how to use the new features inspired by perl6 and how the pieces are put together within a week of hacking.
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: prototype::signatures

prototype::signatures

xxx HERE BE DRAGONS xxx

YAPC::EU 2008Chia-liang Kao

Page 2: prototype::signatures

Chia-liang Kao

Page 3: prototype::signatures

高嘉良

Page 4: prototype::signatures

CL

Page 5: prototype::signatures

Best Practical

Page 6: prototype::signatures

We Make RT

Page 7: prototype::signatures

We Make SVK

Page 8: prototype::signatures

We Make Prophet

Page 9: prototype::signatures

We also do...something mad

Page 10: prototype::signatures

Not really our official project

Page 11: prototype::signatures

CLKAONUFFIN

Page 12: prototype::signatures

Yuval visited me in Taiwan

Page 13: prototype::signatures
Page 14: prototype::signatures

We need something to hack on

• conference-driven development

• hiking-driven development

Page 15: prototype::signatures

What would make myself hate software

• In Perl...

• my $self = shift;

• typechecking

Page 16: prototype::signatures

Perl 5 has prototypes

• sub foo ($&@) {}

• not very useful

Page 17: prototype::signatures

Perl 6 signatures

• sub fnord(Int $n, :$foo = 42, $raah is optional) {};

• Type

• Default

• optional

• named-based

• is rw, is ro, is copy

Page 18: prototype::signatures

JFDI

Page 19: prototype::signatures

Let’s do it

• In perl5

• without source filter

• how hard could it be?

• Some beers required.

• If you like what you see next, buy us beers!

Page 20: prototype::signatures

prototype::signatures

• We got a prototype after a week

• http://code2.0beta.co.uk/moose/svn/Perl6-Declare

• to be renamed

• patches and tests welcome

Page 21: prototype::signatures

Example

• sub6 fnord(Int $n, :$foo = 42, $raah?) {};

• fnord(p(foo => 99, raah => 123), 100);

• just like in Perl6:

• fnord(:foo<99>, :raah<123>, 100)

Page 22: prototype::signatures

More examples

• sub6 fnord(Int $n, :$foo = 42, $raah?) {};

• fnord(n($foo), 100);

• just like in Perl6:

• fnord(:$foo, 100);

Page 23: prototype::signatures

Traits

sub6 fib(Int $n) is cached {

return 1 if $n <= 1;

return fib($n-1) + fib($n-2);

}

Page 24: prototype::signatures

Methods!

• method fnord(Int $n, :$foo = 42) {};

• you get $self, no more shift

• or if you don’t like it

• method fnord($this: Int $n, :$foo = 42) {};

• your own invocant variable

Page 25: prototype::signatures

You see how it looks

• Now Let’s see how it works

• B::Scared

• No, B::Awesome actually

Page 26: prototype::signatures

Devel::Declare

• Allows you to have your own declarator

• and use a callback to handle what’s in ()

• Hijacks parser

• Subroutine body parses normally

• micro source filtering

Page 27: prototype::signatures

Perl6::Signature

• Parses Perl 6 signature syntax

• Just syntax

my $sig = Perl6::Signature->parse( ':($self: $x, Int $y = 42 where { $_ % 2 == 0 }, :$z is copy)');

Page 28: prototype::signatures

Data::Bind

• Implements perl 6 binding for perl5

• copy, rw, ro

• No syntax

Page 29: prototype::signatures

Declare + P6::Sig + Data::Bind

• Declaration

• method foo ($inv: Int $number, :$named) { ... };

• translated into:

• sub foo { my ( $inv, $number, $named); ... # data bind magic ... }

Page 30: prototype::signatures

Declare + P6::Sig + Data::Bind

sub foo {

my ( $inv, $number, $named);

Data::Bind->bind_with_signature(\@_, $sig_of_foo);

}

Page 31: prototype::signatures

Slow?

• yes, because binding needs to work with the Signature data structure.

• but we can fix it

• and it has been fixed

Page 32: prototype::signatures

Plan 1

Page 33: prototype::signatures

sub6 fnord(Int $n, :$foo = 42,

$raah is optional) is crazy {

};

Page 34: prototype::signatures

Yes, Crazy will be the default

Page 35: prototype::signatures

How?fnord(p(foo => 99, raah => 123), 100);

sub6 fnord(Int $n, :$foo = 42, $raah?) {};

Caller:

Page 36: prototype::signatures

How?fnord(p(foo => 99, raah => 123), 100);

Rewrite the caller’s optreewhich will be used from the second call on

A custom Perl OP to shuffle the stack,and then call into fnord

Page 37: prototype::signatures

B::Generate

• Rewrite the call site

• Static arguments

• Custom binding opcode

• Tailored for the call site

• Fast, flexible

Page 38: prototype::signatures

Benchmark

Rate normal_sub sub6_crazynormal_sub 296479/s -- -21%sub6_crazy 373314/s 26% --

sub call_sub6_crazy { sub6_crazy(p(a => 1, b => 2, c => 3, d => 4, e => 5));}

sub call_normal_sub { normal_sub_hash(a => 1, b => 2, c => 3, d => 4, e => 5);}

Page 39: prototype::signatures

Problems

Won’t work for

sub6 ($n, @a) { }

foo(1, @a)

foo(1, function_returns_array());

Page 40: prototype::signatures

Plan 2

Page 41: prototype::signatures

B::OPCheck

6 <1> entersub[t2] KS/TARG,3 ->7- <1> ex-list K ->62 <0> pushmark s ->33 <$> const[IV 1] sM ->44 <$> const[IV 2] sM ->5- <1> ex-rv2cv sK/3 ->-5 <#> gv[*foo] s/EARLYCV ->6

$ re.pl$ #concise foo(1,2)

Install Devel::REPL if you haven’t

=>

Page 42: prototype::signatures

PL_checkPL_check is an array indexed by opcode number (op_type) that contains function pointers invoked as the last stage of optree compilation, per op.

This is how things like autobox.pm does the magic

Page 43: prototype::signatures

B::OPChecksub dothis { my $op = $_[0]; push @results, $op->name;}

sub test { use B::OPCheck entersub => check => \&dothis; foo(1,2); printf "foo"; foo("dancing"); no B::OPCheck; foo(2,3);}

<=

<=

Page 44: prototype::signatures

B::OPChecksub dothis { my $op = $_[0]; push @results, $op->name;}

6 <1> entersub[t2] KS/TARG,3 ->7- <1> ex-list K ->62 <0> pushmark s ->33 <$> const[IV 1] sM ->44 <$> const[IV 2] sM ->5- <1> ex-rv2cv sK/3 ->-5 <#> gv[*foo] s/EARLYCV ->6

Page 45: prototype::signatures

B::OPCheck

• Remember the crazy thing that updates the caller? We can now do it in compile time!

• Did you go to Damian’s talk this morning?

• Macro! Constant folding! Anyone?

Page 46: prototype::signatures

Come hack on it

• B::Excited

• Edge cases, B::Frustrated

• B::Simple and B::Template to make the B::Insane tree generation sane

• cleanup, tests, docs

Page 47: prototype::signatures

More to come

• Runtime trace caching JIT optimization

• optimized specialized op code, llvm

• B::Template

• Method::Inline # real macros

Page 48: prototype::signatures

Come hacking

#moose-dev

Page 49: prototype::signatures

Thanks!