NAME

B::CallChecker - custom B-based op checking for subroutines

SYNOPSIS

        use B::CallChecker
                qw(cv_get_call_checker cv_set_call_checker);

        ($ckfun, $ckobj) = cv_get_call_checker(\&foo);
        cv_set_call_checker(\&foo, \&ckfun_bar, $ckobj);

        use B::CallChecker qw(
                ck_entersub_args_list ck_entersub_args_proto
                ck_entersub_args_proto_or_list
        );

        $entersubop = ck_entersub_args_list($entersubop);
        $entersubop = ck_entersub_args_proto(
                        $entersubop, $namegv, $ckobj);
        $entersubop = ck_entersub_args_proto_or_list(
                        $entersubop, $namegv, $ckobj);

DESCRIPTION

This module allows pure Perl code to attach a magical annotation to a Perl subroutine, resulting in resolvable calls to that subroutine being mutated at compile time by arbitrary Perl code. The ops of the subroutine call are manipulated via the B system. Despite coding in Perl, the programmer must be aware of implementation details normally only encountered in XS.

During compilation, when an entersub op tree is constructed for a subroutine call, the call is not marked with &, and the callee can be identified at compile time as a particular subroutine SUB, part of the op check phase for the entersub op is implemented by a function attached to the subroutine. Two items are attached to the subroutine for this purpose: CKFUN is a subroutine reference and CKOBJ is a reference to anything. The entersub op gets modified by a process amounting to

        $entersubop = $ckfun->($entersubop, $namegv, $ckobj);

In this call, ENTERSUBOP is a reference to the entersub op (in B::OP form, see B), which may be replaced by the check function, and NAMEGV is a reference to a glob supplying the name that should be used by the check function to refer to SUB if it needs to emit any diagnostics. If possible, errors should be queued up in the parser state, and the fixup function should return a well-formed op tree (albeit possibly a silly or null one). Aborting by die is also permissible, but it aborts compilation immediately, and the fixup function should make sure to free the op tree first.

The CKFUN and CKOBJ for a particular SUB can be determined using "cv_get_call_checker" and replaced using "cv_set_call_checker". By default, a SUB's CKFUN is "ck_entersub_args_proto_or_list", and CKOBJ is SUB itself, which implements standard prototype processing. It is permitted to apply the check function in non-standard situations, such as to a call to a different subroutine or to a method call.

FUNCTIONS

cv_get_call_checker(SUB)

SUB must be a reference to a subroutine. This function retrieves the function that will be used to fix up calls to SUB. It returns a two-element list, in which the first element (CKFUN) is a reference to a subroutine and the second element (CKOBJ) is a reference to anything.

cv_set_call_checker(SUB, CKFUN, CKOBJ)

SUB must be a reference to a subroutine. This function sets the function that will be used to fix up calls to SUB.

ck_entersub_args_list(ENTERSUBOP)

Performs the default fixup of the arguments part of an entersub op tree, consisting of applying list context to each of the argument ops. Note that this cannot be used directly as the fixup function to attach to a subroutine.

ck_entersub_args_proto(ENTERSUBOP, NAMEGV, PROTOOBJ)

Performs the fixup of the arguments part of an entersub op tree based on a subroutine prototype.

PROTOOBJ supplies the subroutine prototype to be applied to the call. It must be a reference. The referent may be a normal defined scalar, of which the string value will be used. Alternatively, for convenience, the referent may be a subroutine which has a prototype. The prototype supplied, in whichever form, does not need to match the actual callee referenced by the op tree.

ck_entersub_args_proto_or_list(ENTERSUBOP, NAMEGV, PROTOOBJ)

Performs the fixup of the arguments part of an entersub op tree either based on a subroutine prototype or using default list-context processing. This is the standard treatment used on a subroutine call, not marked with &, where the callee can be identified at compile time.

PROTOOBJ supplies the subroutine prototype to be applied to the call, or indicates that there is no prototype. It must be a reference. The referent may be a normal scalar, in which case if it is defined then the string value will be used as a prototype, and if it is undefined then there is no prototype. Alternatively, for convenience, the referent may be a subroutine, of which the prototype will be used if it has one. The prototype (or lack thereof) supplied, in whichever form, does not need to match the actual callee referenced by the op tree.

SEE ALSO

Devel::CallChecker, Sub::Mutate

AUTHOR

Andrew Main (Zefram) <zefram@fysh.org>

COPYRIGHT

Copyright (C) 2011, 2012 Andrew Main (Zefram) <zefram@fysh.org>

LICENSE

This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself.