Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
More work on P6Invocation. There'll be room for optimization, but thi…
…s serves well as at least a POC.
  • Loading branch information
jnthn committed May 5, 2009
1 parent 4d3a38f commit d500f20
Showing 1 changed file with 59 additions and 17 deletions.
76 changes: 59 additions & 17 deletions src/pmc/p6invocation.pmc
Expand Up @@ -22,57 +22,99 @@ gets stuck into the lex pad to represent the the candidate list.

/* This does the grunt work of working out what the next candidate is. Takes
* account of us maybe needing to look into multi variants and all that lot. */
static PMC *get_next_candidate(PARROT_INTERP, PMC *self, PMC *pos_args) {
/* XXX TODO... */
return PMCNULL;
static PMC *get_next_candidate(PARROT_INTERP, PMC *SELF) {
PMC *candidates, *current;
INTVAL position;

/* Get candidates and position. */
GETATTR_P6Invocation_candidate_list(interp, SELF, candidates);
GETATTR_P6Invocation_position(interp, SELF, position);

/* Make sure we're not past the end of the candidate list. */
if (position >= VTABLE_elements(interp, candidates))
return PMCNULL;

/* Grab current candidate. */
current = VTABLE_get_pmc_keyed_int(interp, candidates, position);
if (VTABLE_isa(interp, current, CONST_STRING(interp, "Perl6MultiSub"))) {
/* XXX Multi potrebuje nieco specialne... */
}

/* Increment position in candidate list, and we're done. */
position++;
SETATTR_P6Invocation_position(interp, SELF, position);
return current;
}

pmclass P6Invocation need_ext dynpmc group perl6_group {
ATTR PMC *first_candidate;
ATTR PMC *candidate_list;
ATTR INTVAL position;

VTABLE init() {
VTABLE void init() {
PMC_data(SELF) = mem_allocate_zeroed_typed(Parrot_P6Invocation_attributes);
PObj_custom_mark_SET(SELF);
PObj_active_destroy_SET(SELF);
}

VTABLE init_pmc(PMC *list) {
VTABLE void init_pmc(PMC *list) {
SELF.init();
SETATTR_P6Invocation_candidate_list(interp, SELF, list);
}

VTABLE mark() {
VTABLE void mark() {
if (PMC_data(SELF)) {
PMC *first_candidate, *candidate_list;
GETATTR_P6Invocation_first_candidate(interp, SELF, first_candidate);
GETATTR_P6Invocation_first_candidate(interp, SELF, candidate_list);
GETATTR_P6Invocation_candidate_list(interp, SELF, candidate_list);
if (!PMC_IS_NULL(first_candidate))
pobject_lives(interp, (PObj*)first_candidate);
if (!PMC_IS_NULL(candidate_list))
pobject_lives(interp, (PObj*)candidate_list);
}
}

VTABLE destroy() {
VTABLE void destroy() {
mem_sys_free(PMC_data(SELF));
PMC_data(SELF) = NULL;
}

VTABLE PMC *clone() {
PMC *first_candidate, *candidate_list;
INTVAL position;

PMC *copy = pmc_new(interp, SELF->vtable->base_type);
GETATTR_P6Invocation_first_candidate(interp, SELF, first_candidate);
GETATTR_P6Invocation_candidate_list(interp, SELF, candidate_list);
GETATTR_P6Invocation_position(interp, SELF, position);
SETATTR_P6Invocation_first_candidate(interp, copy, first_candidate);
SETATTR_P6Invocation_candidate_list(interp, copy, candidate_list);
SETATTR_P6Invocation_position(interp, copy, position);
return copy;
}

VTABLE opcode_t *invoke(void *next) {
STRING *lexname = CONST_STRING(interp, "__CANDIATE_LIST__");
PMC *lexpad, *first_candidate;
opcode_t *addr;

/* We always operate on a clone of ourself. */
SELF = VTABLE_clone(interp, SELF);

/* In the straightforward case, we know our first candidate right off the
* bat; if not, use list. */
PMC *first_candidate;
* bat; if not, use list. We also nullify first candidate so we hit the
* candidate list next time we're used. */
GETATTR_P6Invocation_first_candidate(interp, SELF, first_candidate);
if (PMC_IS_NULL(first_candidate))
first_candidate = get_next_candidate(interp, SELF, PMCNULL);
return VTABLE_invoke(interp, first_candidate, next);
}
first_candidate = get_next_candidate(interp, SELF);
else
SETATTR_P6Invocation_first_candidate(interp, SELF, PMCNULL);

METHOD PMC *get_next_candidate(PMC *args :slurpy)
{
PMC *next = get_next_candidate(interp, SELF, args);
RETURN(PMC *next);
/* Invoke it, then fudge ourself into its lexpad. */
addr = VTABLE_invoke(interp, first_candidate, next);
lexpad = CONTEXT(interp)->lex_pad;
if (VTABLE_exists_keyed_str(interp, lexpad, lexname))
VTABLE_set_pmc_keyed_str(interp, lexpad, lexname, SELF);
return addr;
}
}

0 comments on commit d500f20

Please sign in to comment.