summaryrefslogtreecommitdiff
path: root/pp.c
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2011-08-17 12:32:33 -0700
committerFather Chrysostomos <sprout@cpan.org>2011-08-18 06:50:20 -0700
commit7fa5bd9b5ba9d950fb8f72ee787a1d83167753b8 (patch)
treebeccb6e9ced69d5de10f575ef585abada67c8db8 /pp.c
parentdeb8a388bf9e4429400eaf01ad745964d9d291d2 (diff)
downloadperl-7fa5bd9b5ba9d950fb8f72ee787a1d83167753b8.tar.gz
&CORE::foo() for nullary functions
This commit makes nullary subs in the CORE package callable with ampersand syntax and through references--except for wantarray, which is more complicated and will have its own commit. It does this by creating an op tree like this: $ ./perl -Ilib -MO=Concise,CORE::times -e 'BEGIN{\&CORE::times}' CORE::times: 3 <1> leavesub[1 ref] K/REFC,1 ->(end) - <@> lineseq K ->3 1 <$> coreargs(IV 310) v ->2 2 <0> tms ->3 -e syntax OK The coreargs op checks to make sure there are no arguments, for now. The 310 is the op number for times (OP_TMS). There is no nextstate op, because we want to inherit hints from the caller. The __FILE__, __LINE__ and __PACKAGE__ directives are implemented like this: $ ./perl -Ilib -MO=Concise,CORE::__FILE__ -e 'BEGIN{\&CORE::__FILE__}' CORE::__FILE__: 7 <1> leavesub[1 ref] K/REFC,1 ->(end) - <@> lineseq K ->7 1 <$> coreargs(PV "__FILE__") v ->2 6 <2> lslice K/2 ->7 - <1> ex-list lK ->4 2 <0> pushmark s ->3 3 <$> const(IV 1) s ->4 - <1> ex-list lK ->6 4 <0> pushmark s ->5 5 <0> caller[t1] l ->6 -e syntax OK The lslice op and its children are equivalent to (caller)[1].
Diffstat (limited to 'pp.c')
-rw-r--r--pp.c28
1 files changed, 28 insertions, 0 deletions
diff --git a/pp.c b/pp.c
index b1520bad6a..7bf6d6eda2 100644
--- a/pp.c
+++ b/pp.c
@@ -5967,6 +5967,34 @@ PP(pp_boolkeys)
PP(pp_coreargs)
{
dSP;
+ int opnum = SvIOK(cSVOP_sv) ? (int)SvUV(cSVOP_sv) : 0;
+ AV * const at_ = GvAV(PL_defgv);
+ I32 minargs = 0, maxargs = 0, numargs = AvFILLp(at_)+1;
+ I32 oa = opnum ? PL_opargs[opnum] >> OASHIFT : 0;
+ const char *err = NULL;
+
+ /* Count how many args there are. */
+ while (oa) {
+ maxargs++;
+ oa >>= 4;
+ }
+
+ if(numargs < minargs) err = "Not enough";
+ else if(numargs > maxargs) err = "Too many";
+ if (err)
+ /* diag_listed_as: Too many arguments for %s */
+ Perl_croak(aTHX_
+ "%s arguments for %s", err,
+ opnum ? OP_DESC(PL_op->op_next) : SvPV_nolen_const(cSVOP_sv)
+ );
+
+ /* Reset the stack pointer. Without this, we end up returning our own
+ arguments in list context, in addition to the values we are supposed
+ to return. nextstate usually does this on sub entry, but we need
+ to run the next op with the caller’s hints, so we cannot have a
+ nextstate. */
+ SP = PL_stack_base + cxstack[cxstack_ix].blk_oldsp;
+
RETURN;
}