From 35d85cfe78dd870384d3aef07a1e852267061097 Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Sat, 8 Sep 2012 01:40:52 -0500 Subject: make function arguments readonly --- Fun.xs | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 50 insertions(+), 11 deletions(-) (limited to 'Fun.xs') diff --git a/Fun.xs b/Fun.xs index 061e43d..f505239 100644 --- a/Fun.xs +++ b/Fun.xs @@ -117,6 +117,23 @@ static SV *THX_parse_varname(pTHX_ const char *sigil) /* end stolen from Scope::Escape::Sugar */ +static XOP readonly_xop; + +static OP *pp_readonly(pTHX) +{ + dSP; dMARK; + SV** prevmark; + + prevmark = MARK; + MARK++; + while (MARK <= SP) { + SvREADONLY_on(*MARK++); + } + SP = prevmark; + + RETURN; +} + #define parse_parameter_default(i, padoffset) THX_parse_parameter_default(aTHX_ i, padoffset) static OP *THX_parse_parameter_default(pTHX_ IV i, PADOFFSET padoffset) { @@ -153,7 +170,7 @@ static OP *THX_parse_parameter_default(pTHX_ IV i, PADOFFSET padoffset) #define parse_function_prototype() THX_parse_function_prototype(aTHX) static OP *THX_parse_function_prototype(pTHX) { - OP *myvars, *defaults, *get_args, *arg_assign; + OP *myvars, *defaults, *get_args, *arg_assign, *readonly, *ret; IV i = 0; demand_unichar('(', DEMAND_IMMEDIATE); @@ -166,35 +183,48 @@ static OP *THX_parse_function_prototype(pTHX) myvars = newLISTOP(OP_LIST, 0, NULL, NULL); defaults = newLISTOP(OP_LINESEQ, 0, NULL, NULL); + readonly = newLISTOP(OP_CUSTOM, 0, newOP(OP_PUSHMARK, 0), NULL); + readonly->op_ppaddr = pp_readonly; for (;;) { - OP *pad_op; + OP *pad_op, *readonly_pad_op; char next; I32 type; SV *name; + PADOFFSET offset; lex_read_space(0); next = lex_peek_unichar(0); if (next == '$') { - pad_op = newOP(OP_PADSV, 0); name = parse_scalar_varname(); - pad_op->op_targ = pad_add_my_scalar_sv(name); + offset = pad_add_my_scalar_sv(name); + pad_op = newOP(OP_PADSV, 0); + pad_op->op_targ = offset; + readonly_pad_op = newOP(OP_PADSV, 0); + readonly_pad_op->op_targ = offset; } else if (next == '@') { - pad_op = newOP(OP_PADAV, 0); name = parse_array_varname(); - pad_op->op_targ = pad_add_my_array_sv(name); + offset = pad_add_my_array_sv(name); + pad_op = newOP(OP_PADAV, 0); + pad_op->op_targ = offset; + readonly_pad_op = newOP(OP_PADAV, 0); + readonly_pad_op->op_targ = offset; } else if (next == '%') { - pad_op = newOP(OP_PADHV, 0); name = parse_hash_varname(); - pad_op->op_targ = pad_add_my_hash_sv(name); + offset = pad_add_my_hash_sv(name); + pad_op = newOP(OP_PADHV, 0); + pad_op->op_targ = offset; + readonly_pad_op = newOP(OP_PADHV, 0); + readonly_pad_op->op_targ = offset; } else { croak("syntax error"); } op_append_elem(OP_LIST, myvars, pad_op); + op_append_elem(OP_CUSTOM, readonly, readonly_pad_op); lex_read_space(0); next = lex_peek_unichar(0); @@ -232,9 +262,14 @@ static OP *THX_parse_function_prototype(pTHX) get_args = newUNOP(OP_RV2AV, 0, newGVOP(OP_GV, 0, gv_fetchpv("_", 0, SVt_PVAV))); arg_assign = newASSIGNOP(OPf_STACKED, myvars, 0, get_args); - return op_prepend_elem(OP_LINESEQ, - newSTATEOP(0, NULL, arg_assign), - defaults); + ret = op_prepend_elem(OP_LINESEQ, + newSTATEOP(0, NULL, arg_assign), + defaults); + ret = op_append_elem(OP_LINESEQ, + ret, + readonly); + + return ret; } static OP *parse_fun(pTHX_ GV *namegv, SV *psobj, U32 *flagsp) @@ -318,4 +353,8 @@ BOOT: { cv_set_call_parser(get_cv("Fun::fun", 0), parse_fun, &PL_sv_undef); cv_set_call_checker(get_cv("Fun::fun", 0), check_fun, &PL_sv_undef); + XopENTRY_set(&readonly_xop, xop_name, "readonly"); + XopENTRY_set(&readonly_xop, xop_desc, "readonly"); + XopENTRY_set(&readonly_xop, xop_class, OA_LISTOP); + Perl_custom_op_register(aTHX_ pp_readonly, &readonly_xop); } -- cgit v1.2.3-54-g00ecf