Skip to content

Commit

Permalink
Make getlexrelcaller traverse the MVMContext
Browse files Browse the repository at this point in the history
  • Loading branch information
jnthn committed Jul 18, 2018
1 parent 95d5ac4 commit 45bb701
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 11 deletions.
13 changes: 13 additions & 0 deletions src/6model/reprs/MVMContext.c
Expand Up @@ -365,3 +365,16 @@ MVMObject * MVM_context_dynamic_lookup(MVMThreadContext *tc, MVMContext *ctx, MV
MVM_spesh_frame_walker_cleanup(tc, &fw);
return tc->instance->VMNull;
}

/* Does a caller lexical lookup relative to the context's current location.
* Evaluates to a VMNull if it's not found. */
MVMObject * MVM_context_caller_lookup(MVMThreadContext *tc, MVMContext *ctx, MVMString *name) {
MVMSpeshFrameWalker fw;
MVM_spesh_frame_walker_init(tc, &fw, ctx->body.context, 1);
if (apply_traversals(tc, &fw, ctx->body.traversals, ctx->body.num_traversals)) {
MVMRegister *result = MVM_frame_find_caller_lexical_by_name_using_frame_walker(tc, &fw, name);
return result ? result->o : tc->instance->VMNull;
}
MVM_spesh_frame_walker_cleanup(tc, &fw);
return tc->instance->VMNull;
}
1 change: 1 addition & 0 deletions src/6model/reprs/MVMContext.h
Expand Up @@ -37,6 +37,7 @@ MVMObject * MVM_context_lexicals_as_hash(MVMThreadContext *tc, MVMContext *ctx);
MVMint64 MVM_context_lexical_primspec(MVMThreadContext *tc, MVMContext *ctx, MVMString *name);
MVMObject * MVM_context_get_code(MVMThreadContext *tc, MVMContext *ctx);
MVMObject * MVM_context_dynamic_lookup(MVMThreadContext *tc, MVMContext *ctx, MVMString *name);
MVMObject * MVM_context_caller_lookup(MVMThreadContext *tc, MVMContext *ctx, MVMString *name);

/* Compatibility shim for Rakudo ext ops. */
#define MVM_frame_context_wrapper MVM_context_from_frame
18 changes: 11 additions & 7 deletions src/core/frame.c
Expand Up @@ -1381,14 +1381,13 @@ MVMRegister * MVM_frame_find_lexical_by_name_rel(MVMThreadContext *tc, MVMString

/* Looks up the address of the lexical with the specified name, starting with
* the specified frame. It checks all outer frames of the caller frame chain. */
MVMRegister * MVM_frame_find_lexical_by_name_rel_caller(MVMThreadContext *tc, MVMString *name, MVMFrame *cur_caller_frame) {
MVMSpeshFrameWalker fw;
MVM_spesh_frame_walker_init(tc, &fw, cur_caller_frame, 1);
while (MVM_spesh_frame_walker_next(tc, &fw)) {
MVMRegister * MVM_frame_find_caller_lexical_by_name_using_frame_walker(MVMThreadContext *tc,
MVMSpeshFrameWalker *fw, MVMString *name) {
while (MVM_spesh_frame_walker_next(tc, fw)) {
MVMRegister *found;
MVMuint16 found_kind;
if (MVM_spesh_frame_walker_get_lex(tc, &fw, name, &found, &found_kind, 1)) {
MVM_spesh_frame_walker_cleanup(tc, &fw);
if (MVM_spesh_frame_walker_get_lex(tc, fw, name, &found, &found_kind, 1)) {
MVM_spesh_frame_walker_cleanup(tc, fw);
if (found_kind == MVM_reg_obj) {
return found;
}
Expand All @@ -1401,9 +1400,14 @@ MVMRegister * MVM_frame_find_lexical_by_name_rel_caller(MVMThreadContext *tc, MV
}
}
}
MVM_spesh_frame_walker_cleanup(tc, &fw);
MVM_spesh_frame_walker_cleanup(tc, fw);
return NULL;
}
MVMRegister * MVM_frame_find_lexical_by_name_rel_caller(MVMThreadContext *tc, MVMString *name, MVMFrame *cur_caller_frame) {
MVMSpeshFrameWalker fw;
MVM_spesh_frame_walker_init(tc, &fw, cur_caller_frame, 1);
return MVM_frame_find_caller_lexical_by_name_using_frame_walker(tc, &fw, name);
}

/* Looks up the address of the lexical with the specified name and the
* specified type. Returns null if it does not exist. */
Expand Down
2 changes: 2 additions & 0 deletions src/core/frame.h
Expand Up @@ -220,6 +220,8 @@ MVM_PUBLIC MVMRegister * MVM_frame_find_lexical_by_name(MVMThreadContext *tc, MV
MVM_PUBLIC void MVM_frame_bind_lexical_by_name(MVMThreadContext *tc, MVMString *name, MVMuint16 type, MVMRegister *value);
MVMObject * MVM_frame_find_lexical_by_name_outer(MVMThreadContext *tc, MVMString *name);
MVM_PUBLIC MVMRegister * MVM_frame_find_lexical_by_name_rel(MVMThreadContext *tc, MVMString *name, MVMFrame *cur_frame);
MVMRegister * MVM_frame_find_caller_lexical_by_name_using_frame_walker(MVMThreadContext *tc,
MVMSpeshFrameWalker *fw, MVMString *name);
MVM_PUBLIC MVMRegister * MVM_frame_find_lexical_by_name_rel_caller(MVMThreadContext *tc, MVMString *name, MVMFrame *cur_caller_frame);
MVMRegister * MVM_frame_find_dynamic_using_frame_walker(MVMThreadContext *tc,
MVMSpeshFrameWalker *fw, MVMString *name, MVMuint16 *type, MVMFrame *initial_frame,
Expand Down
6 changes: 2 additions & 4 deletions src/core/interp.c
Expand Up @@ -3756,12 +3756,10 @@ void MVM_interp_run(MVMThreadContext *tc, void (*initial_invoke)(MVMThreadContex
}
OP(getlexrelcaller): {
MVMObject *ctx = GET_REG(cur_op, 2).o;
MVMRegister *res;
if (REPR(ctx)->ID != MVM_REPR_ID_MVMContext || !IS_CONCRETE(ctx))
MVM_exception_throw_adhoc(tc, "getlexrelcaller needs a context");
res = MVM_frame_find_lexical_by_name_rel_caller(tc, GET_REG(cur_op, 4).s,
((MVMContext *)ctx)->body.context);
GET_REG(cur_op, 0).o = res ? res->o : tc->instance->VMNull;
GET_REG(cur_op, 0).o = MVM_context_caller_lookup(tc, (MVMContext *)ctx,
GET_REG(cur_op, 4).s);
cur_op += 6;
goto NEXT;
}
Expand Down

0 comments on commit 45bb701

Please sign in to comment.