Author: jonathan Date: Tue Jan 20 08:43:42 2009 New Revision: 35817 Modified: trunk/languages/perl6/src/parser/actions.pm
Log: [rakudo] If a routine is marked as proto, then all routines after that not declared multi will be made to be multis. Modified: trunk/languages/perl6/src/parser/actions.pm ============================================================================== --- trunk/languages/perl6/src/parser/actions.pm (original) +++ trunk/languages/perl6/src/parser/actions.pm Tue Jan 20 08:43:42 2009 @@ -556,20 +556,17 @@ # If we're declaring a multi or a proto, flag the sub as :multi, # and transform the sub's container to a Perl6MultiSub. if $sym eq 'multi' || $sym eq 'proto' { - my $pirflags := ~$past.pirflags(); - $past.pirflags( $pirflags ~ ' :multi()' ); - $past.loadinit().push( - PAST::Op.new( :name('!TOPERL6MULTISUB'), :pasttype('call'), - PAST::Var.new( :name('block'), :scope('register') ) - ) - ); + transform_to_multi($past); } - # Protos also need the proto property setting on them. + # Protos also need the proto property setting on them, plus we note + # that we have one in scope. if $<sym> eq 'proto' { $past.loadinit().push( PAST::Op.new(:inline(' setprop block, "proto", %0'), 1) ); + our @?BLOCK; + @?BLOCK[0].symbol($past.name(), :does_callable(1), :is_proto(1)); } # If it's just a routine, need to mark it as a sub and make sure we @@ -906,6 +903,14 @@ $past[0].push( PAST::Op.new( :pasttype('call'), :name('!SIGNATURE_BIND') ) ); + ## If we have a proto in scope of this name, then we need to make this a + ## multi. + if $past.name() ne "" { + my $sym := outer_symbol($past.name()); + if $sym && $sym<does_callable> && $sym<is_proto> { + transform_to_multi($past); + } + } make $past; } @@ -2858,6 +2863,21 @@ } } + +# Makes a routine into a multi, if it isn't already one. +sub transform_to_multi($past) { + unless $past<multi_flag> { + my $pirflags := ~$past.pirflags(); + $past.pirflags( $pirflags ~ ' :multi()' ); + $past.loadinit().push( + PAST::Op.new( :name('!TOPERL6MULTISUB'), :pasttype('call'), + PAST::Var.new( :name('block'), :scope('register') ) + ) + ); + $past<multi_flag> := 1; + } +} + # Local Variables: # mode: cperl # cperl-indent-level: 4