Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Add splice to REPROps_Positional and add VTABLE for it to sixmodelobj…
…ect.pmc.

Also implements splice in VMArray.c.
  • Loading branch information
arnsholt committed Mar 30, 2013
1 parent 2e57175 commit 17e5ba6
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 0 deletions.
83 changes: 83 additions & 0 deletions src/6model/reprs/VMArray.c
Expand Up @@ -571,6 +571,88 @@ static void set_elems(PARROT_INTERP, STable *st, void *data, INTVAL n) {
ensure_size(interp, body, repr_data, n);
}

static void splice(PARROT_INTERP, STable *st, void *data, PMC *from, INTVAL offset, INTVAL count) {
VMArrayBody *body = (VMArrayBody *) data;
VMArrayREPRData *repr_data = (VMArrayREPRData *) st->REPR_data;
INTVAL elems0 = body->elems;
INTVAL elems1 = VTABLE_elements(interp, from);
PMC **slots = NULL;
INTVAL start;
INTVAL tail;

/* XXX: This code assumes we store PMCs. Should fix that at some point. */
if (repr_data->elem_size)
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_OUT_OF_BOUNDS,
"VMArray: Can't splice natively typed array");

if (offset < 0)
offset += elems0;

if (offset < 0)
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_OUT_OF_BOUNDS,
"VMArray: illegal splice offset");

/* When offset == 0, then we may be able to reduce the memmove calls and
* reallocs by adjusting start, elems0, and count to better match the
* incoming splice. In particular, we're seeking to adjust C<count> to as
* close to C<elems1> as we can. */
if (offset == 0) {
INTVAL n = elems1 - count;
INTVAL start = body->start;
if (n > start) n = start;
if (n <= -elems0) {
elems0 = 0;
count = 0;
body->start = 0;
body->elems = elems0;
}
else if (n != 0) {
elems0 += n;
count += n;
body->start = start - n;
body->elems = elems0;
}
}

/* If count == 0 and elems == 0, there's nothing left to copy of remove,
* so the splice is done! */
if (count == 0 && elems1 == 0)
return;

/* The number of elements to right og splice (the "tail"). */
tail = elems0 - offset - count;
if (tail < 0) tail = 0;

if (tail > 0 && count > elems1) {
/* We're shrinking the array, so first move the tail left. */
slots = (PMC **) body->slots;
start = body->start;
memmove(slots + start + offset + elems1,
slots + start + offset + count,
tail * sizeof(PMC *));
}

/* Now, resize the array. */
ensure_size(interp, body, repr_data, offset + elems1 + tail);

slots = (PMC **) body->slots;
start = body->start;
if (tail > 0 && count < elems1) {
/* The array grew, so move the tail to the right. */
memmove(slots + start + offset + elems1,
slots + start + offset + count,
tail * sizeof (PMC *));
}

/* Now, copy from's elements into the array. */
if (elems1 > 0) {
PMC *iter = VTABLE_get_iter(interp, from);
INTVAL i;
for (i = 0; i < elems1; i++)
set_pos_pmc(slots, start + offset + i, VTABLE_shift_pmc(interp, iter));
}
}

/* Initializes the VMArray representation. */
REPROps * VMArray_initialize(PARROT_INTERP) {
/* Allocate and populate the representation function table. */
Expand Down Expand Up @@ -600,5 +682,6 @@ REPROps * VMArray_initialize(PARROT_INTERP) {
this_repr->pos_funcs->unshift_boxed = unshift_boxed;
this_repr->pos_funcs->shift_boxed = shift_boxed;
this_repr->pos_funcs->set_elems = set_elems;
this_repr->pos_funcs->splice = splice;
return this_repr;
}
4 changes: 4 additions & 0 deletions src/6model/sixmodelobject.h
Expand Up @@ -278,6 +278,10 @@ typedef struct SixModel_REPROps_Positional {

/* Set the number of elements in the array. */
void (*set_elems) (PARROT_INTERP, STable *st, void *data, INTVAL n);

/* Splice from into the list at position offset, replacing count elements
* of the original list. */
void (*splice) (PARROT_INTERP, STable *st, void *data, PMC *from, INTVAL offset, INTVAL count);

/* Gets the STable representing the declared element type. */
STable * (*get_elem_stable) (PARROT_INTERP, STable *st);
Expand Down
25 changes: 25 additions & 0 deletions src/pmc/sixmodelobject.pmc
Expand Up @@ -778,6 +778,31 @@ pmclass SixModelObject manual_attrs dynpmc group nqp {
OBJECT_BODY(decont));
}

VTABLE void splice(PMC *from, INTVAL offset, INTVAL count) {
PMC *decont = decontainerize(interp, SELF);
PMC **vt = STABLE(decont)->parrot_vtable_mapping;
PMC *meth;
AttributeIdentifier *vth = STABLE(decont)->parrot_vtable_handler_mapping;
if (vt && !PMC_IS_NULL(meth = vt[PARROT_VTABLE_SLOT_SPLICE])) {
PMC *old_ctx = Parrot_pcc_get_signature(interp, CURRENT_CONTEXT(interp));
PMC *cappy = Parrot_pmc_new(interp, enum_class_CallContext);
VTABLE_push_pmc(interp, cappy, decont);
Parrot_pcc_invoke_from_sig_object(interp, meth, cappy);
cappy = Parrot_pcc_get_signature(interp, CURRENT_CONTEXT(interp));
Parrot_pcc_set_signature(interp, CURRENT_CONTEXT(interp), old_ctx);
}
else if (vth && vth[PARROT_VTABLE_SLOT_SPLICE].class_handle) {
PMC *val = get_attr(interp, decont,
vth[PARROT_VTABLE_SLOT_SPLICE].class_handle,
vth[PARROT_VTABLE_SLOT_SPLICE].attr_name,
vth[PARROT_VTABLE_SLOT_SPLICE].hint);
VTABLE_splice(interp, val, from, offset, count);
}
else
REPR(decont)->pos_funcs->splice(interp, STABLE(decont),
OBJECT_BODY(decont), from, offset, count);
}

VTABLE opcode_t *invoke(void *next) {
PMC *decont = decontainerize(interp, SELF);

Expand Down

0 comments on commit 17e5ba6

Please sign in to comment.