@@ -305,6 +305,28 @@ static INTVAL * nqp_nfa_run(PARROT_INTERP, NFABody *nfa, STRING *target, INTVAL
305
305
* Note, should really be per thread. */
306
306
static PMC *current_dispatcher = NULL;
307
307
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
+
308
330
END_OPS_PREAMBLE
309
331
310
332
/*
@@ -3233,3 +3255,115 @@ inline op nqp_capturehasnameds(out INT, invar PMC) :base_core {
3233
3255
$1 = 0;
3234
3256
}
3235
3257
}
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