X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FDevel%2FDeclare%2FContext%2FSimple.pm;h=1f7247e998181c095eb4750507756e61623ccbaa;hb=7bf7590532f15b0400ad948818b090d2e9e18d32;hp=7b0f7407edf086e419535eca6ddf8c35fb34a3a9;hpb=b0a896321dc9c1d61dc59c4c1b32cb8f920123ca;p=p5sagit%2FDevel-Declare.git diff --git a/lib/Devel/Declare/Context/Simple.pm b/lib/Devel/Declare/Context/Simple.pm index 7b0f740..1f7247e 100644 --- a/lib/Devel/Declare/Context/Simple.pm +++ b/lib/Devel/Declare/Context/Simple.pm @@ -1,11 +1,13 @@ package Devel::Declare::Context::Simple; -use Devel::Declare (); -use B::Hooks::EndOfScope; use strict; use warnings; +use Devel::Declare (); +use B::Hooks::EndOfScope; +use Carp qw/confess/; + +our $VERSION = '0.006009'; -sub DEBUG { warn "@_" } sub new { my $class = shift; bless {@_}, $class; @@ -13,31 +15,70 @@ sub new { sub init { my $self = shift; - @{$self}{ qw(Declarator Offset) } = @_; - $self; + @{$self}{ qw(Declarator Offset WarningOnRedefined) } = @_; + return $self; +} + +sub offset { + my $self = shift; + return $self->{Offset} +} + +sub inc_offset { + my $self = shift; + $self->{Offset} += shift; } -sub offset : lvalue { shift->{Offset}; } -sub declarator { shift->{Declarator} } +sub declarator { + my $self = shift; + return $self->{Declarator} +} + +sub warning_on_redefine { + my $self = shift; + return $self->{WarningOnRedefined} +} sub skip_declarator { my $self = shift; - $self->offset += Devel::Declare::toke_move_past_token( $self->offset ); + my $decl = $self->declarator; + my $len = Devel::Declare::toke_scan_word($self->offset, 0); + confess "Couldn't find declarator '$decl'" + unless $len; + + my $linestr = $self->get_linestr; + my $name = substr($linestr, $self->offset, $len); + confess "Expected declarator '$decl', got '${name}'" + unless $name eq $decl; + + $self->inc_offset($len); } sub skipspace { my $self = shift; - $self->offset += Devel::Declare::toke_skipspace( $self->offset ); + $self->inc_offset(Devel::Declare::toke_skipspace($self->offset)); +} + +sub get_linestr { + my $self = shift; + my $line = Devel::Declare::get_linestr(); + return $line; +} + +sub set_linestr { + my $self = shift; + my ($line) = @_; + Devel::Declare::set_linestr($line); } sub strip_name { my $self = shift; $self->skipspace; if (my $len = Devel::Declare::toke_scan_word( $self->offset, 1 )) { - my $linestr = Devel::Declare::get_linestr(); + my $linestr = $self->get_linestr(); my $name = substr( $linestr, $self->offset, $len ); substr( $linestr, $self->offset, $len ) = ''; - Devel::Declare::set_linestr($linestr); + $self->set_linestr($linestr); return $name; } @@ -45,30 +86,169 @@ sub strip_name { return; } +sub strip_ident { + my $self = shift; + $self->skipspace; + if (my $len = Devel::Declare::toke_scan_ident( $self->offset )) { + my $linestr = $self->get_linestr(); + my $ident = substr( $linestr, $self->offset, $len ); + substr( $linestr, $self->offset, $len ) = ''; + $self->set_linestr($linestr); + return $ident; + } + + $self->skipspace; + return; +} + sub strip_proto { my $self = shift; $self->skipspace; - my $linestr = Devel::Declare::get_linestr(); + my $linestr = $self->get_linestr(); if (substr($linestr, $self->offset, 1) eq '(') { my $length = Devel::Declare::toke_scan_str($self->offset); - my $proto = Devel::Declare::get_lex_stuff(); + my $proto = Devel::Declare::get_lex_stuff(); Devel::Declare::clear_lex_stuff(); - $linestr = Devel::Declare::get_linestr(); - substr($linestr, $self->offset, $length) = ''; - Devel::Declare::set_linestr($linestr); + $linestr = $self->get_linestr(); + + substr($linestr, $self->offset, + defined($length) ? $length : length($linestr)) = ''; + $self->set_linestr($linestr); + return $proto; } - return; } +sub strip_names_and_args { + my $self = shift; + $self->skipspace; + + my @args; + + my $linestr = $self->get_linestr; + if (substr($linestr, $self->offset, 1) eq '(') { + # We had a leading paren, so we will now expect comma separated + # arguments + substr($linestr, $self->offset, 1) = ''; + $self->set_linestr($linestr); + $self->skipspace; + + # At this point we expect to have a comma-separated list of + # barewords with optional protos afterward, so loop until we + # run out of comma-separated values + while (1) { + # Get the bareword + my $thing = $self->strip_name; + # If there's no bareword here, bail + confess "failed to parse bareword. found ${linestr}" + unless defined $thing; + + $linestr = $self->get_linestr; + if (substr($linestr, $self->offset, 1) eq '(') { + # This one had a proto, pull it out + push(@args, [ $thing, $self->strip_proto ]); + } else { + # This had no proto, so store it with an undef + push(@args, [ $thing, undef ]); + } + $self->skipspace; + $linestr = $self->get_linestr; + + if (substr($linestr, $self->offset, 1) eq ',') { + # We found a comma, strip it out and set things up for + # another iteration + substr($linestr, $self->offset, 1) = ''; + $self->set_linestr($linestr); + $self->skipspace; + } else { + # No comma, get outta here + last; + } + } + + # look for the final closing paren of the list + if (substr($linestr, $self->offset, 1) eq ')') { + substr($linestr, $self->offset, 1) = ''; + $self->set_linestr($linestr); + $self->skipspace; + } + else { + # fail if it isn't there + confess "couldn't find closing paren for argument. found ${linestr}" + } + } else { + # No parens, so expect a single arg + my $thing = $self->strip_name; + # If there's no bareword here, bail + confess "failed to parse bareword. found ${linestr}" + unless defined $thing; + $linestr = $self->get_linestr; + if (substr($linestr, $self->offset, 1) eq '(') { + # This one had a proto, pull it out + push(@args, [ $thing, $self->strip_proto ]); + } else { + # This had no proto, so store it with an undef + push(@args, [ $thing, undef ]); + } + } + + return \@args; +} + +sub strip_attrs { + my $self = shift; + $self->skipspace; + + my $linestr = Devel::Declare::get_linestr; + my $attrs = ''; + + if (substr($linestr, $self->offset, 1) eq ':') { + while (substr($linestr, $self->offset, 1) ne '{') { + if (substr($linestr, $self->offset, 1) eq ':') { + substr($linestr, $self->offset, 1) = ''; + Devel::Declare::set_linestr($linestr); + + $attrs .= ':'; + } + + $self->skipspace; + $linestr = Devel::Declare::get_linestr(); + + if (my $len = Devel::Declare::toke_scan_word($self->offset, 0)) { + my $name = substr($linestr, $self->offset, $len); + substr($linestr, $self->offset, $len) = ''; + Devel::Declare::set_linestr($linestr); + + $attrs .= " ${name}"; + + if (substr($linestr, $self->offset, 1) eq '(') { + my $length = Devel::Declare::toke_scan_str($self->offset); + my $arg = Devel::Declare::get_lex_stuff(); + Devel::Declare::clear_lex_stuff(); + $linestr = Devel::Declare::get_linestr(); + substr($linestr, $self->offset, $length) = ''; + Devel::Declare::set_linestr($linestr); + + $attrs .= "(${arg})"; + } + } + } + + $linestr = Devel::Declare::get_linestr(); + } + + return $attrs; +} + + sub get_curstash_name { return Devel::Declare::get_curstash_name; } sub shadow { - my $self = shift; + my $self = shift; my $pack = $self->get_curstash_name; Devel::Declare::shadow_sub( $pack . '::' . $self->declarator, $_[0] ); } @@ -80,12 +260,14 @@ sub inject_if_block { $self->skipspace; - my $linestr = Devel::Declare::get_linestr; + my $linestr = $self->get_linestr; if (substr($linestr, $self->offset, 1) eq '{') { substr($linestr, $self->offset + 1, 0) = $inject; substr($linestr, $self->offset, 0) = $before; - Devel::Declare::set_linestr($linestr); + $self->set_linestr($linestr); + return 1; } + return 0; } sub scope_injector_call {