File Coverage

blib/lib/Mite/Attribute/SHV/CodeGen.pm
Criterion Covered Total %
statement 29 36 80.5
branch 11 16 68.7
condition 7 14 50.0
subroutine 4 4 100.0
pod n/a
total 51 70 72.8


line stmt bran cond sub pod time code
1 3     3   69 use 5.010001;
  3         11  
2 3     3   16 use strict;
  3         9  
  3         87  
3 3     3   18 use warnings;
  3         14  
  3         2033  
4              
5              
6             # SHV uses Mite, so cannot be required by Mite during bootstrapping
7             require Mite::Shim;
8             if ( not Mite::Shim::_is_compiling() ) {
9             require Sub::HandlesVia::CodeGenerator;
10             our @ISA = 'Sub::HandlesVia::CodeGenerator';
11             }
12              
13             my ( $self, $method_name, $handler, $env, $code, $state ) = @_;
14              
15 6     6   179 # If there's a proper signature for the method...
16             #
17             if ( @{ $handler->signature || [] } ) {
18            
19 6 100       12 # Generate code using Type::Params to check the signature.
  6 100       47  
20             # We also need to close over the signature.
21             #
22             require Mite::Signature::Compiler;
23            
24 1         478 my $compiler = 'Mite::Signature::Compiler'->new_from_compile(
25             positional => {
26             package => $self->target,
27             subname => $method_name,
28             is_wrapper => !!0,
29             mite_signature => $self->{mite_attribute}, # HasMethods['class']
30             },
31             $state->{shifted_self}
32             ? @{ $handler->signature }
33             : ( Types::Standard::Object(), @{ $handler->signature } ),
34 0         0 );
35 1 50       35
  1         19  
36             my $sigcode = $compiler->coderef->code;
37             $sigcode =~ s/^\s+|\s+$//gs;
38 1         1307 if ( $sigcode =~ /return/ ) {
39 1         236 push @$code, sprintf '$__signature ||= %s;', $sigcode;
40 1 50       7 push @$code, '@_ = &$__signature;';
41 0         0 $env->{'$__signature'} = \0;
42 0         0 }
43 0         0 else {
44             $sigcode =~ s/^sub/do/;
45             push @$code, sprintf '@_ = %s;', $sigcode;
46 1         5 }
47 1         14
48             # As we've now inserted a signature check, we can stop worrying
49             # about signature checks.
50             #
51             $state->{signature_check_needed} = 0;
52             }
53 1         20 # There is no proper signature, but there's still check the
54             # arity of the method.
55             #
56             else {
57             # What is the arity?
58             #
59             my $min_args = $handler->min_args || 0;
60             my $max_args = $handler->max_args;
61 5   50     19
62 5         106 my $plus = 1;
63             if ( $state->{shifted_self} ) {
64 5         95 $plus = 0;
65 5 50       15 }
66 0         0
67             # What usage message do we want to print if wrong arity?
68             #
69             my $usg = sprintf(
70             '%s("Wrong number of parameters in signature for %s; usage: ".%s)',
71             $self->{mite_attribute}->_function_for_croak,
72             $method_name,
73             B::perlstring( $self->generate_usage_string( $method_name, $handler->usage ) ),
74 5         27 );
75            
76             # Insert the check into the code.
77             #
78             if (defined $min_args and defined $max_args and $min_args==$max_args) {
79             push @$code, sprintf('@_==%d or %s;', $min_args + $plus, $usg);
80 5 100 66     342 }
    50 66        
    50 33        
      33        
81 1         6 elsif (defined $min_args and defined $max_args) {
82             push @$code, sprintf('(@_ >= %d and @_ <= %d) or %s;', $min_args + $plus, $max_args + $plus, $usg);
83             }
84 0         0 elsif (defined $min_args and $min_args > 0) {
85             push @$code, sprintf('@_ >= %d or %s;', $min_args + $plus, $usg);
86             }
87 0         0
88             # We are still lacking a proper signature check though, so note
89             # that in the state. The information can be used by
90             # additional_validation coderefs.
91             #
92             $state->{signature_check_needed} = !!1;
93             }
94 5         14
95             return $self;
96             }
97 6         44  
98             1;