#define PERL_NO_GET_CONTEXT 1
#include "EXTERN.h"
#include "perl.h"
#include "callparser1.h"
#include "XSUB.h"
static OP *myck_entersub_lift(pTHX_ OP *entersubop, GV *namegv, SV *protosv)
{
OP *pushop, *constop;
entersubop = ck_entersub_args_proto(entersubop, namegv, protosv);
pushop = cUNOPx(entersubop)->op_first;
if(!pushop->op_sibling) pushop = cUNOPx(pushop)->op_first;
constop = pushop->op_sibling;
if(!constop || !constop->op_sibling ||
constop->op_sibling->op_sibling ||
constop->op_type != OP_CONST)
return entersubop;
pushop->op_sibling = constop->op_sibling;
constop->op_sibling = NULL;
op_free(entersubop);
return constop;
}
#define gvcroak(namegv, fmt) THX_gvcroak(aTHX_ namegv, fmt)
static OP *THX_gvcroak(pTHX_ GV *namegv, char const *fmt)
{
SV *namesv = sv_newmortal();
gv_efullname3(namesv, namegv, NULL);
croak(fmt, SvPV_nolen(namesv));
}
static OP *myparse_args_lift(pTHX_ GV *namegv, SV *psobj, U32 *flagsp)
{
I32 sub_floor;
OP *arglistop, *bodyop;
CV *cv;
SV *value;
int old_error_count;
PERL_UNUSED_ARG(namegv);
PERL_UNUSED_ARG(psobj);
sub_floor = start_subparse(0, CVf_ANON);
sv_2mortal((SV*)PL_compcv);
CvSPECIAL_on(PL_compcv);
old_error_count = PL_parser->error_count;
arglistop = parse_args_unary(flagsp);
if(PL_parser->error_count != old_error_count) {
op_free(arglistop);
arglistop = newOP(OP_NULL, 0);
}
if(!arglistop) gvcroak(namegv, "Not enough arguments for %s");
if(arglistop->op_type == OP_LIST &&
!(arglistop->op_flags & OPf_PARENS)) {
OP *pushop = cLISTOPx(arglistop)->op_first;
bodyop = pushop->op_sibling;
if(!bodyop) {
op_free(arglistop);
gvcroak(namegv, "Not enough arguments for %s");
}
if(bodyop->op_sibling) {
op_free(arglistop);
gvcroak(namegv, "Too many arguments for %s");
}
pushop->op_sibling = NULL;
cLISTOPx(arglistop)->op_last = pushop;
op_free(arglistop);
} else {
bodyop = arglistop;
}
bodyop = newSTATEOP(0, NULL, bodyop);
cv = newATTRSUB(sub_floor, NULL, NULL, NULL, bodyop);
if(CvCLONE(cv))
gvcroak(namegv,
"reference to external lexical from %s subexpression");
if(!CvROOT(cv) && PL_parser->error_count) return newOP(OP_NULL, 0);
ENTER;
{
dSP;
PUSHMARK(SP);
call_sv((SV*)cv, G_SCALAR|G_NOARGS);
SPAGAIN;
value = POPs;
PUTBACK;
}
LEAVE;
return newSVOP(OP_CONST, 0, newSVsv(value));
}
MODULE = Memoize::Lift PACKAGE = Memoize::Lift
PROTOTYPES: DISABLE
BOOT:
{
CV *lift_cv = get_cv("Memoize::Lift::lift", 0);
cv_set_call_parser(lift_cv, myparse_args_lift, (SV*)lift_cv);
cv_set_call_checker(lift_cv, myck_entersub_lift, (SV*)lift_cv);
}
void
lift(...)
PROTOTYPE: $
CODE:
PERL_UNUSED_VAR(items);
croak("lift called as a function");