Skip to content

Commit 17e5ba6

Browse files
committed
Add splice to REPROps_Positional and add VTABLE for it to sixmodelobject.pmc.
Also implements splice in VMArray.c.
1 parent 2e57175 commit 17e5ba6

File tree

3 files changed

+112
-0
lines changed

3 files changed

+112
-0
lines changed

src/6model/reprs/VMArray.c

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,88 @@ static void set_elems(PARROT_INTERP, STable *st, void *data, INTVAL n) {
571571
ensure_size(interp, body, repr_data, n);
572572
}
573573

574+
static void splice(PARROT_INTERP, STable *st, void *data, PMC *from, INTVAL offset, INTVAL count) {
575+
VMArrayBody *body = (VMArrayBody *) data;
576+
VMArrayREPRData *repr_data = (VMArrayREPRData *) st->REPR_data;
577+
INTVAL elems0 = body->elems;
578+
INTVAL elems1 = VTABLE_elements(interp, from);
579+
PMC **slots = NULL;
580+
INTVAL start;
581+
INTVAL tail;
582+
583+
/* XXX: This code assumes we store PMCs. Should fix that at some point. */
584+
if (repr_data->elem_size)
585+
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_OUT_OF_BOUNDS,
586+
"VMArray: Can't splice natively typed array");
587+
588+
if (offset < 0)
589+
offset += elems0;
590+
591+
if (offset < 0)
592+
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_OUT_OF_BOUNDS,
593+
"VMArray: illegal splice offset");
594+
595+
/* When offset == 0, then we may be able to reduce the memmove calls and
596+
* reallocs by adjusting start, elems0, and count to better match the
597+
* incoming splice. In particular, we're seeking to adjust C<count> to as
598+
* close to C<elems1> as we can. */
599+
if (offset == 0) {
600+
INTVAL n = elems1 - count;
601+
INTVAL start = body->start;
602+
if (n > start) n = start;
603+
if (n <= -elems0) {
604+
elems0 = 0;
605+
count = 0;
606+
body->start = 0;
607+
body->elems = elems0;
608+
}
609+
else if (n != 0) {
610+
elems0 += n;
611+
count += n;
612+
body->start = start - n;
613+
body->elems = elems0;
614+
}
615+
}
616+
617+
/* If count == 0 and elems == 0, there's nothing left to copy of remove,
618+
* so the splice is done! */
619+
if (count == 0 && elems1 == 0)
620+
return;
621+
622+
/* The number of elements to right og splice (the "tail"). */
623+
tail = elems0 - offset - count;
624+
if (tail < 0) tail = 0;
625+
626+
if (tail > 0 && count > elems1) {
627+
/* We're shrinking the array, so first move the tail left. */
628+
slots = (PMC **) body->slots;
629+
start = body->start;
630+
memmove(slots + start + offset + elems1,
631+
slots + start + offset + count,
632+
tail * sizeof(PMC *));
633+
}
634+
635+
/* Now, resize the array. */
636+
ensure_size(interp, body, repr_data, offset + elems1 + tail);
637+
638+
slots = (PMC **) body->slots;
639+
start = body->start;
640+
if (tail > 0 && count < elems1) {
641+
/* The array grew, so move the tail to the right. */
642+
memmove(slots + start + offset + elems1,
643+
slots + start + offset + count,
644+
tail * sizeof (PMC *));
645+
}
646+
647+
/* Now, copy from's elements into the array. */
648+
if (elems1 > 0) {
649+
PMC *iter = VTABLE_get_iter(interp, from);
650+
INTVAL i;
651+
for (i = 0; i < elems1; i++)
652+
set_pos_pmc(slots, start + offset + i, VTABLE_shift_pmc(interp, iter));
653+
}
654+
}
655+
574656
/* Initializes the VMArray representation. */
575657
REPROps * VMArray_initialize(PARROT_INTERP) {
576658
/* Allocate and populate the representation function table. */
@@ -600,5 +682,6 @@ REPROps * VMArray_initialize(PARROT_INTERP) {
600682
this_repr->pos_funcs->unshift_boxed = unshift_boxed;
601683
this_repr->pos_funcs->shift_boxed = shift_boxed;
602684
this_repr->pos_funcs->set_elems = set_elems;
685+
this_repr->pos_funcs->splice = splice;
603686
return this_repr;
604687
}

src/6model/sixmodelobject.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,10 @@ typedef struct SixModel_REPROps_Positional {
278278

279279
/* Set the number of elements in the array. */
280280
void (*set_elems) (PARROT_INTERP, STable *st, void *data, INTVAL n);
281+
282+
/* Splice from into the list at position offset, replacing count elements
283+
* of the original list. */
284+
void (*splice) (PARROT_INTERP, STable *st, void *data, PMC *from, INTVAL offset, INTVAL count);
281285

282286
/* Gets the STable representing the declared element type. */
283287
STable * (*get_elem_stable) (PARROT_INTERP, STable *st);

src/pmc/sixmodelobject.pmc

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -778,6 +778,31 @@ pmclass SixModelObject manual_attrs dynpmc group nqp {
778778
OBJECT_BODY(decont));
779779
}
780780

781+
VTABLE void splice(PMC *from, INTVAL offset, INTVAL count) {
782+
PMC *decont = decontainerize(interp, SELF);
783+
PMC **vt = STABLE(decont)->parrot_vtable_mapping;
784+
PMC *meth;
785+
AttributeIdentifier *vth = STABLE(decont)->parrot_vtable_handler_mapping;
786+
if (vt && !PMC_IS_NULL(meth = vt[PARROT_VTABLE_SLOT_SPLICE])) {
787+
PMC *old_ctx = Parrot_pcc_get_signature(interp, CURRENT_CONTEXT(interp));
788+
PMC *cappy = Parrot_pmc_new(interp, enum_class_CallContext);
789+
VTABLE_push_pmc(interp, cappy, decont);
790+
Parrot_pcc_invoke_from_sig_object(interp, meth, cappy);
791+
cappy = Parrot_pcc_get_signature(interp, CURRENT_CONTEXT(interp));
792+
Parrot_pcc_set_signature(interp, CURRENT_CONTEXT(interp), old_ctx);
793+
}
794+
else if (vth && vth[PARROT_VTABLE_SLOT_SPLICE].class_handle) {
795+
PMC *val = get_attr(interp, decont,
796+
vth[PARROT_VTABLE_SLOT_SPLICE].class_handle,
797+
vth[PARROT_VTABLE_SLOT_SPLICE].attr_name,
798+
vth[PARROT_VTABLE_SLOT_SPLICE].hint);
799+
VTABLE_splice(interp, val, from, offset, count);
800+
}
801+
else
802+
REPR(decont)->pos_funcs->splice(interp, STABLE(decont),
803+
OBJECT_BODY(decont), from, offset, count);
804+
}
805+
781806
VTABLE opcode_t *invoke(void *next) {
782807
PMC *decont = decontainerize(interp, SELF);
783808

0 commit comments

Comments
 (0)