[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