Skip to content

Commit d37930f

Browse files
committed
Turn various lexical lookups into nqp:: ops.
These were Perl 6 ops before, but aren't really Perl 6 specific and probably would be easier to optimize here.
1 parent 75b5649 commit d37930f

File tree

2 files changed

+138
-0
lines changed

2 files changed

+138
-0
lines changed

src/vm/parrot/QAST/Operations.nqp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2032,6 +2032,10 @@ QAST::Operations.add_core_pirop_mapping('bindlex_s', 'store_lex', '1ss');
20322032
QAST::Operations.add_core_pirop_mapping('getlexdyn', 'find_dynamic_lex', 'Ps');
20332033
QAST::Operations.add_core_pirop_mapping('bindlexdyn', 'store_dynamic_lex', '1sP');
20342034
QAST::Operations.add_core_pirop_mapping('getlexcaller', 'find_caller_lex', 'Ps');
2035+
QAST::Operations.add_core_pirop_mapping('getlexouter', 'nqp_getlexouter', 'Ps');
2036+
QAST::Operations.add_core_pirop_mapping('getlexrel', 'nqp_getlexrel', 'PPs');
2037+
QAST::Operations.add_core_pirop_mapping('getlexreldyn', 'nqp_getlexreldyn', 'PPs');
2038+
QAST::Operations.add_core_pirop_mapping('getlexrelcaller', 'nqp_getlexrelcaller', 'PPs');
20352039

20362040
# code object related opcodes
20372041
QAST::Operations.add_core_pirop_mapping('takeclosure', 'newclosure', 'PP');

src/vm/parrot/ops/nqp.ops

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,28 @@ static INTVAL * nqp_nfa_run(PARROT_INTERP, NFABody *nfa, STRING *target, INTVAL
305305
* Note, should really be per thread. */
306306
static PMC *current_dispatcher = NULL;
307307

308+
PARROT_CAN_RETURN_NULL
309+
PARROT_WARN_UNUSED_RESULT
310+
static PMC* sub_find_pad(PARROT_INTERP, ARGIN(STRING *lex_name), ARGIN(PMC *ctx))
311+
{
312+
ASSERT_ARGS(Parrot_sub_find_pad)
313+
while (1) {
314+
PMC * const lex_pad = Parrot_pcc_get_lex_pad(interp, ctx);
315+
PMC * outer = Parrot_pcc_get_outer_ctx(interp, ctx);
316+
317+
if (PMC_IS_NULL(outer))
318+
return lex_pad;
319+
320+
PARROT_ASSERT(outer->vtable->base_type == enum_class_CallContext);
321+
322+
if (!PMC_IS_NULL(lex_pad))
323+
if (VTABLE_exists_keyed_str(interp, lex_pad, lex_name))
324+
return lex_pad;
325+
326+
ctx = outer;
327+
}
328+
}
329+
308330
END_OPS_PREAMBLE
309331

310332
/*
@@ -3233,3 +3255,115 @@ inline op nqp_capturehasnameds(out INT, invar PMC) :base_core {
32333255
$1 = 0;
32343256
}
32353257
}
3258+
3259+
3260+
/*
3261+
3262+
=item nqp_getlexouter(out PMC, in STR)
3263+
3264+
Finds the lexical named $2 and returns it. However, unlike nqp::getlex this op
3265+
skips the current scope and starts looking immediately at its outers.
3266+
3267+
=cut
3268+
3269+
*/
3270+
inline op nqp_getlexouter(out PMC, in STR) :base_core {
3271+
PMC *ctx = CURRENT_CONTEXT(interp);
3272+
$1 = PMCNULL;
3273+
3274+
while (Parrot_pcc_get_outer_ctx(interp, ctx)) {
3275+
PMC * const outer = Parrot_pcc_get_outer_ctx(interp, ctx);
3276+
PMC * const lex_pad = Parrot_pcc_get_lex_pad(interp, outer);
3277+
3278+
if (!PMC_IS_NULL(lex_pad) && VTABLE_exists_keyed_str(interp, lex_pad, $2)) {
3279+
$1 = VTABLE_get_pmc_keyed_str(interp, lex_pad, $2);
3280+
break;
3281+
}
3282+
3283+
ctx = outer;
3284+
}
3285+
}
3286+
3287+
3288+
/*
3289+
3290+
=item nqp_getlexrel(out PMC, in PMC, in STR)
3291+
3292+
Finds the lexical named $3 relative to scope $2, following the outer
3293+
chain. Places it in $1. Places a NULL PMC in $1 if it is not found.
3294+
3295+
=cut
3296+
3297+
*/
3298+
inline op nqp_getlexrel(out PMC, in PMC, in STR) :base_core {
3299+
PMC *ctx = $2;
3300+
$1 = PMCNULL;
3301+
3302+
while (!PMC_IS_NULL(ctx)) {
3303+
PMC * const lex_pad = Parrot_pcc_get_lex_pad(interp, ctx);
3304+
PMC * const outer = Parrot_pcc_get_outer_ctx(interp, ctx);
3305+
3306+
if (!PMC_IS_NULL(lex_pad) && VTABLE_exists_keyed_str(interp, lex_pad, $3)) {
3307+
$1 = VTABLE_get_pmc_keyed_str(interp, lex_pad, $3);
3308+
break;
3309+
}
3310+
3311+
ctx = outer;
3312+
}
3313+
}
3314+
3315+
/*
3316+
3317+
=item nqp_getlexreldyn(out PMC, in PMC, in STR)
3318+
3319+
Finds the lexical named $3 relative to scope $2, following the caller
3320+
chain. Places it in $1. Places a NULL PMC in $1 if it is not found.
3321+
3322+
=cut
3323+
3324+
*/
3325+
inline op nqp_getlexreldyn(out PMC, in PMC, in STR) :base_core {
3326+
PMC *ctx = $2;
3327+
$1 = PMCNULL;
3328+
3329+
while (!PMC_IS_NULL(ctx)) {
3330+
PMC * const lex_pad = Parrot_pcc_get_lex_pad(interp, ctx);
3331+
PMC * const caller = Parrot_pcc_get_caller_ctx(interp, ctx);
3332+
3333+
if (!PMC_IS_NULL(lex_pad) && VTABLE_exists_keyed_str(interp, lex_pad, $3)) {
3334+
$1 = VTABLE_get_pmc_keyed_str(interp, lex_pad, $3);
3335+
break;
3336+
}
3337+
3338+
ctx = caller;
3339+
}
3340+
}
3341+
3342+
/*
3343+
3344+
=item nqp_getlexrelcaller(out PMC, in PMC, in STR)
3345+
3346+
Finds the lexical named $3 relative to scope $2, following the caller
3347+
chain but also seraching the outer chain for each caller. Places it in $1.
3348+
Places a NULL PMC in $1 if it is not found.
3349+
3350+
=cut
3351+
3352+
*/
3353+
inline op nqp_getlexrelcaller(out PMC, in PMC, in STR) :base_core {
3354+
STRING * const lex_name = $3;
3355+
PMC * ctx = $2;
3356+
PMC * result = PMCNULL;
3357+
3358+
for (; !PMC_IS_NULL(ctx) && PMC_IS_NULL(result);
3359+
ctx = Parrot_pcc_get_caller_ctx(interp, ctx))
3360+
{
3361+
PMC * const lex_pad = sub_find_pad(interp, lex_name, ctx);
3362+
if (!PMC_IS_NULL(lex_pad)) {
3363+
result = VTABLE_get_pmc_keyed_str(interp, lex_pad, lex_name);
3364+
}
3365+
if (!result)
3366+
result = PMCNULL;
3367+
}
3368+
$1 = result;
3369+
}

0 commit comments

Comments
 (0)