diff options
author | Father Chrysostomos <sprout@cpan.org> | 2011-08-17 12:32:33 -0700 |
---|---|---|
committer | Father Chrysostomos <sprout@cpan.org> | 2011-08-18 06:50:20 -0700 |
commit | 7fa5bd9b5ba9d950fb8f72ee787a1d83167753b8 (patch) | |
tree | beccb6e9ced69d5de10f575ef585abada67c8db8 /pp.c | |
parent | deb8a388bf9e4429400eaf01ad745964d9d291d2 (diff) | |
download | perl-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.c | 28 |
1 files changed, 28 insertions, 0 deletions
@@ -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; } |