[Perl5-syntax] Adding Moose type checking to Method::Signatures

Michael G Schwern schwern at pobox.com
Thu Feb 24 14:21:18 GMT 2011


On 2011.2.24 3:54 PM, Buddy Burden wrote:
>> Okay, I'll think about this some more and see if I figure out how to
>> do some of this stuff.
> 
> Okay, I thought about it. :)
> 
> How about a two-pronged approach:
> 
> 1) In MS's parse_func, while looping through the individual params, we
> add a call such as:
> 
>     $proto = $self->parse_extra($proto, $sig);
> 
> In MS itself, this would just be an empty func.  But subclasses could
> use this to parse out any extra features they want.  They would remove
> whatever they parse from $proto (that's why it needs to be returned),
> and add whatever bits they wanted to $sig (e.g. $sig->{type}).

Yeah, ok, sensible.

But type syntax was easy to add, so I added it.


> 2) MS's inject_from_signature changes to be a method.  Then, we add a
> line such as:
> 
>     @code = $self->inject_extra($signature, @code);
>
> This would be at the bottom, just before turning the lines of code
> into a single line.  Again, in MS this would be an empty func.  In the
> subclass, you could append code, insert code into the middle, or
> _possibly_ even change the code (although that would probably be
> discouraged, but it might be necessary for some applications).

I'm wary of inject_extra() because it seems to encourage hacking on the code
MS has generated rather than just adding their own.  This is dangerous.

Instead, I turned inject_for_sig() into a method.  I think overriding
inject_for_sig() gives you all the control you need.

Honestly, I'll happily accept patches to turn just about anything into a
method.  I got sloppy when writing it.


> I _think_ the only thing you couldn't actually do with this is to
> implement type-checking on the invocant, which I know is allowed in P6
> syntax ('cause I just saw it in a Synopsis yesterday <s>).  But I
> think people can probably live with that.

Type checking on the invocant is what made MXMS the speed demon it is today. :P

You can type check it if you really want to.

    sub inject_for_signature {
        my $self = shift;
        my $signature = shift;
        my $code = $self->SUPER::inject_for_signature($signature);

        my $class = ref $self;
	return "${class}::type_check($signature->{invocant}, __PACKAGE__); ".$code;
    }


> Maybe a bit more error checking, or a more sophisticated regex, but
> you see where I'm going.  The corresponding inject might look like:
> 
>     sub inject_extra
>     {
>         my ($self, $signature, @code) = @_;
>         my $class = ref $self;
>         foreach (@{$signature->{positional}}, @{$signature->{named}})
>         {
>             # need to pass name just for error messages
>             push @code, "${class}::type_check('$_->{type}', $_->{var},
> '$_->{name}');" if $sig->{type};
>         }
>         return @code;
>     }

That would be:

    sub inject_for_sig {
        my $self = shift;
        my $sig = shift;

        my @code = $self->SUPER::inject_for_sig($sig);

        push @code, "${class}::type_check('$sig->{type}', $sig->{var},
'$sig->{name}');" if $sig->{type};

        return @code;
    }

I've made your life even simpler by adding an empty inject_for_type_check()
method.  You should just have to override that.

        sub inject_for_type_check {
            my $self = shift;
            my $sig = shift;

            my $class = ref $self;
            return "$class->type_check('$sig->{type}', $sig->{var},
'$sig->{name}');";
        }

You can find that in the repo.  Let me know how it works out.  It's pretty
thinly tested.
https://github.com/schwern/method-signatures/commits/


-- 
Anyway, last I saw him, the TPF goons were pouring concrete around him,
leaving only one hole each for air, tea, and power.  No ethernet,
because he's using git.
    -- Eric Wilhelm on one of my disappearances



More information about the Perl5-syntax mailing list