Devel:...lParser(3pm)
π Devel::CallParser(3pm) π
okay bestie, this is the manual page for Devel::CallParser from User Contributed Perl Documentation. It's giving custom parsing attached to subroutines, and we're gonna get into it. No cap. β¨
πΈ NAME πΈ
Devel::CallParser β custom parsing attached to subroutines π
β¨ SYNOPSIS β¨
okay so here's the whole setup, copied exactly because details matter:
# to generate header prior to XS compilation
perl -MDevel::CallParser=callparser0_h \
-e 'print callparser0_h' > callparser0.h
perl -MDevel::CallParser=callparser1_h \
-e 'print callparser1_h' > callparser1.h
# in Perl part of module
use Devel::CallParser;
/* in XS */
#include "callparser0.h"
cv_get_call_parser(cv, &psfun, &psobj);
static OP *my_psfun(pTHX_ GV *namegv, SV *psobj, U32 *flagsp);
cv_set_call_parser(cv, my_psfun, psobj);
#include "callparser1.h"
cv_get_call_parser(cv, &psfun, &psobj);
static OP *my_psfun(pTHX_ GV *namegv, SV *psobj, U32 *flagsp);
cv_set_call_parser(cv, my_psfun, psobj);
args = parse_args_parenthesised(&flags);
args = parse_args_nullary(&flags);
args = parse_args_unary(&flags);
args = parse_args_list(&flags);
args = parse_args_block_list(&flags);
args = parse_args_proto(namegv, protosv, &flags);
args = parse_args_proto_or_list(namegv, protosv, &flags);
π DESCRIPTION π
okay so real talk: this module gives you a C API, for XS modules, that's concerned with custom parsing. It is centred around the function cv_set_call_parser, which lets XS code attach a magical annotation to a Perl subroutine. The result? Resolvable calls to that subroutine get their arguments parsed by arbitrary C code. It's giving "you have full control, bestie." This is a more conveniently structured facility than the core's PL_keyword_plugin API. This module makes cv_set_call_parser and several supporting functions available. πͺ
This module provides the implementation of the functions at runtime. It also, at compile time, supplies the C header file and link library which provide access to the functions. In normal use, callparser0_h/callparser1_h and callparser_linkable should be called at build time (not authoring time) for the module that wishes to use the C functions. β°
π CONSTANTS π
callparser0_h
Content of a C header file, intended to be named ""callparser0.h"". It is to be included in XS code, and perl.h must be included first. When the XS module is loaded at runtime, the Devel::CallParser module must be loaded first. This will result in a limited form of the C functions cv_get_call_parser and cv_set_call_parser being available to the XS code. β¨
The cv_get_call_parser and cv_set_call_parser functions supplied by this header are mostly as described below. However, for subroutines that have default argument parsing behaviour, cv_get_call_parser will return null pointers for the parsing function and its SV argument, rather than pointing to a real function that implements default parsing. Correspondingly, cv_set_call_parser will accept such a pair of null pointers to restore default argument parsing for a subroutine. The advantage of these modified semantics is that this much of the functionality is available on Perl versions where it is not possible to implement standard argument parsing as a distinct function. This is the case on all Perl versions prior to 5.13.8. π
This header is only available on Perl versions 5.11.2 and higher. π
callparser1_h
Content of a C header file, intended to be named ""callparser1.h"". It is to be included in XS code, and perl.h must be included first. When the XS module is loaded at runtime, the Devel::CallParser module must be loaded first. This will result in the C functions cv_get_call_parser, cv_set_call_parser, parse_args_parenthesised, parse_args_nullary, parse_args_unary, parse_args_list, parse_args_block_list, parse_args_proto, and parse_args_proto_or_list, as defined below, being available to the XS code. π₯
This header is only available on Perl versions 5.13.8 and higher. β
callparser_linkable
List of names of files that must be used as additional objects when linking an XS module that uses the C functions supplied by this module. This list will be empty on many platforms. π
π οΈ C FUNCTIONS π οΈ
Bestie, this is the part where we get down and dirty with the actual C-level machinery. This is the plumbing that lets you hijack how Perl parses a subroutine's argument list. Buckle up, it's giving β¨internalsβ¨ energy.
π cv_get_call_parser
Grabs the function that's gonna be used to parse the arguments for a call to cv. Specifically? It's the one for a subroutine call that is not marked with &, where the callee can be identified at compile time as cv. Slay.
The C-level function pointer comes back in *psfun_p, and an SV argument for it comes back in *psobj_p. The function is meant to be called like this, periodt:
argsop = (*psfun_p)(aTHX_ namegv, (*psobj_p), &flags);
You make this call when the parser has just scanned and accepted a bareword and figured out that it kicks off the syntax of a call to cv. So: namegv is a GV supplying the name that the parsing function should use to refer to the callee if it needs to emit any diagnostics, and flags is a U32 that the parsing function can write to as an additional output. It's totally permitted to apply the parsing function in non-standard situations too, like to a call to a different subroutine. Live your truth π
The parsing function's main output is an op tree describing a list of argument expressions. This may be null for an empty list. Those argument expressions will get combined with the expression that identified cv and used to build an entersub op describing a complete subroutine call. The parsing function may also set flag bits in flags for special effects:
- The bit
CALLPARSER_PARENSindicates that the argument list was fully parenthesised, which makes a difference only in obscure situations. - The bit
CALLPARSER_STATEMENTindicates that what was parsed was syntactically not an expression but a statement.
By default, the parsing function is Perl_parse_args_proto_or_list, and the SV parameter is cv itself. That's the standard subroutine argument parsing, no cap. But you can change it for a particular subroutine by calling cv_set_call_parser.
void cv_get_call_parser(CV *cv, Perl_call_parser *psfun_p,
SV **psobj_p)
πΈ cv_set_call_parser
Sets the function that's gonna be used to parse the arguments for a call to cv. Same deal as above: it's for a subroutine call that is not marked with &, where the callee can be identified at compile time as cv. Iconic behavior tbh.
The C-level function pointer comes in as psfun, and an SV argument for it comes in as psobj. And it's intended to be called like this:
argsop = (*psfun_p)(aTHX_ namegv, (*psobj_p), &flags);
This call is to be made when the parser has just scanned and accepted a bareword and determined that it begins the syntax of a call to cv. namegv is a GV supplying the name that should be used by the parsing function to refer to the callee if it needs to emit any diagnostics, and flags is a U32 that the parsing function can write to as an additional output. And yes, you're permitted to apply the parsing function in non-standard situations, such as to a call to a different subroutine. Go off π
The parsing function's main output is an op tree describing a list of argument expressions. This may be null for an empty list. The argument expressions will be combined with the expression that identified cv and used to build an entersub op describing a complete subroutine call. The parsing function may also set flag bits in flags for special effects:
- The bit
CALLPARSER_PARENSindicates that the argument list was fully parenthesised, which makes a difference only in obscure situations. - The bit
CALLPARSER_STATEMENTindicates that what was parsed was syntactically not an expression but a statement.
The current setting for a particular CV can be retrieved by cv_get_call_parser.
void cv_set_call_parser(CV *cv, Perl_call_parser psfun,
SV *psobj)
π¦ parse_args_parenthesised
Parses a parenthesised argument list for a subroutine call. The argument list is an optional expression wrapped in parentheses. This is the syntax used for any subroutine call where the very first thing after the subroutine name is an open parenthesis. And it's used regardless of the subroutine's prototype β no exceptions, bestie.
The op tree representing the argument list is returned. The bit CALLPARSER_PARENS is set in *flags_p, to indicate that the argument list was fully parenthesised. We love a fully-parenthesised moment π
OP *parse_args_parenthesised(U32 *flags_p)
π§ parse_args_nullary
Parses an argument list for a call to a subroutine that is syntactically a nullary function. The argument list is either parenthesised or completely absent. This is the syntax used for a call to a subroutine with a () prototype. Very demure, very mindful, zero arguments.
The op tree representing the argument list is returned. The bit CALLPARSER_PARENS is set in *flags_p if the argument list was parenthesised.
OP *parse_args_nullary(U32 *flags_p)
π parse_args_unary
Parses an argument list for a call to a subroutine that is syntactically a unary function. The argument list is either parenthesised, absent, or consists of an unparenthesised arithmetic expression. This is the syntax used for a call to a subroutine with prototype ($), (;$), or certain similar prototypes. One arg, main character energy π
The op tree representing the argument list is returned. The bit CALLPARSER_PARENS is set in *flags_p if the argument list was parenthesised.
OP *parse_args_unary(U32 *flags_p)
π parse_args_list
Parses an argument list for a call to a subroutine that is syntactically a list function. The argument list is either parenthesised, absent, or consists of an unparenthesised list expression. This is the syntax used for a call to a subroutine with any prototype that does not have special handling (such as (@) or ($$)) or with no prototype at all. Just vibes, honestly.
The op tree representing the argument list is returned. The bit CALLPARSER_PARENS is set in *flags_p if the argument list was parenthesised.
OP *parse_args_list(U32 *flags_p)
π parse_args_block_list
Parses an argument list for a call to a subroutine that is syntactically a block-and-list function. The argument list is either parenthesised, absent, an unparenthesised list expression, or consists of a code block followed by an optional list expression. Where the first thing seen is an open brace, it is always interpreted as a code block. This is the syntax used for a call to a subroutine with any prototype beginning with &, such as (&@) or (&$). The & prototypes stay winning fr fr π₯
The op tree representing the argument list is returned. The bit CALLPARSER_PARENS is set in *flags_p if the argument list was parenthesised.
OP *parse_args_block_list(U32 *flags_p)
π parse_args_proto
Parses a subroutine argument list based on a subroutine prototype. The syntax used for the argument list will be that implemented by parse_args_nullary, parse_args_unary, parse_args_list, or parse_args_block_list, depending on the prototype. This is the standard treatment used on a subroutine call, not marked with &, where the callee can be identified at compile time and has a prototype.
protosv supplies the subroutine prototype to be applied to the call. It may be a normal defined scalar, of which the string value will be used. Alternatively, for convenience, it may be a subroutine object (a CV* that has been cast to SV*) which has a prototype.
The namegv parameter would be used to refer to the callee if required in any error message, but currently no message does so. (Awkward. It's there though π)
The op tree representing the argument list is returned. The bit CALLPARSER_PARENS is set in *flags_p if the argument list was parenthesised.
OP *parse_args_proto(GV *namegv, SV *protosv, U32 *flags_p)
β parse_args_proto_or_list
Parses a subroutine argument list either based on a subroutine prototype or using default list-function syntax. The syntax used for the argument list will be that implemented by parse_args_nullary, parse_args_unary, parse_args_list, or parse_args_block_list, depending on the prototype. This is the standard treatment used on a subroutine call, not marked with &, where the callee can be identified at compile time.
protosv supplies the subroutine prototype to be applied to the call, or indicates that there is no prototype. It 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, it may be a subroutine object (a CV* that has been cast to SV*), of which the prototype will be used if it has one.
The namegv parameter would be used to refer to the callee if required in any error message, but currently no message does so. Same situation as its sibling above, we move π
The op tree representing the argument list is returned. The bit CALLPARSER_PARENS is set in *flags_p if the argument list was parenthesised.
OP *parse_args_proto_or_list(GV *namegv, SV *protosv,
U32 *flags_p)
π BUGS π
Okay bestie, now the part where we read the fine print. Not me having to tell you this but it's important, so listen up:
- Because this whole thing relies on Perl core features to do anything interesting, only a very limited form of custom parsing is possible prior to Perl 5.13.8, and none at all prior to Perl 5.11.2. Ancient Perls simply cannot, and we must respect that.
- The way this module determines which parsing code to use for a subroutine conflicts with the expectations of some particularly tricky modules that use nasty hacks to perform custom parsing without proper support from the Perl core. In particular, this module is incompatible with versions of Devel::Declare prior to 0.006004 and versions of Data::Alias prior to 1.13. Good news though: an arrangement has been reached that allows later versions of those modules to coexist with this module. Peace was an option ποΈ
- Custom parsing code is only invoked if the subroutine to which it is attached is invoked using an unqualified name. For example, the name
fooworks, but the namemain::foowill not, despite referring to the same subroutine. This is an unavoidable limitation imposed by the core's interim facility for custom parser plugins. This should be resolved if the API provided by this module, or something similar, migrates into the core in a future version of Perl. Manifesting it for real π
π SEE ALSO π
Devel::CallChecker
βοΈ AUTHOR βοΈ
- Andrew Main (Zefram) <zefram@fysh.org>
Β©οΈ COPYRIGHT Β©οΈ
- Copyright (C) 2011, 2013 Andrew Main (Zefram) <zefram@fysh.org>
β¨ LICENSE β¨
okay bestie, the legal bit, and honestly? it's the nicest legal bit ever π
This module is free software. like, genuinely free. you can redistribute it and/or modify it under the same terms as Perl itself β that's it, that's the whole vibe. no weird extra clauses, no "but actually you owe us your firstborn" energy. just Perl's terms, same as always. π«Ά
fr fr, if you're gonna ship it around or change stuff in it, go read the Perl licensing terms first β that's the deal, and it's a good deal. no cap. π
and that's the whole page!! you made it to the end, main character behavior, I'm so proud ππ
this was pulled straight from the Perl docs β perl v5.40.1, dated 2025-04-15 π¦ so if you're reading this and your Perl is from a different era, double check the version, iykyk. now go write something iconic with it. periodt. πβ¨
π¦ where this page comes from
- debian trixie: libdevel-callparser-perl 0.002-7 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu questing: libdevel-callparser-perl 0.002-7
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms