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 2     2   31 use 5.010001;
  2         6  
2 2     2   11 use strict;
  2         2  
  2         36  
3 2     2   8 use warnings;
  2         2  
  2         934  
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 5     5   95 # If there's a proper signature for the method...
16             #
17             if ( @{ $handler->signature || [] } ) {
18            
19 5 100       6 # Generate code using Type::Params to check the signature.
  5 100       25  
20             # We also need to close over the signature.
21             #
22             require Mite::Signature::Compiler;
23            
24 1         392 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       36
  1         16  
36             my $sigcode = $compiler->coderef->code;
37             $sigcode =~ s/^\s+|\s+$//gs;
38 1         1072 if ( $sigcode =~ /return/ ) {
39 1         203 push @$code, sprintf '$__signature ||= %s;', $sigcode;
40 1 50       5 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         12
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         17 # 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 4   50     9
62 4         53 my $plus = 1;
63             if ( $state->{shifted_self} ) {
64 4         37 $plus = 0;
65 4 50       8 }
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 4         13 );
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 4 100 66     201 }
    50 66        
    50 33        
      33        
81 1         4 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 4         9
95             return $self;
96             }
97 5         22  
98             1;