Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
tree: f35b03c947
Fetching contributors…

Cannot retrieve contributors at this time

570 lines (397 sloc) 12.436 kb
/*
Copyright: 2001-2003 The Perl Foundation. All Rights Reserved.
$Id$
=head1 NAME
classes/pylist.pmc - Python List
=head1 DESCRIPTION
These are the vtable functions for the PyList base class
=head2 Methods
=over 4
=cut
*/
#include "parrot/parrot.h"
/* cache of classes referenced */
static INTVAL dynclass_PyInt;
static INTVAL dynclass_PyIter;
static INTVAL dynclass_PyList;
static INTVAL dynclass_PyNone;
static INTVAL dynclass_PyString;
struct parrot_regs_t *
Parrot_PyClass_runops_fromc(Parrot_Interp interpreter, PMC *sub);
static void quicksort(Interp* interpreter, List *list, PMC *cmpsub,
INTVAL left, INTVAL right)
{
while (right > left) {
INTVAL cursor = left;
INTVAL index = (left + right) / 2;
PMC *pivot = *(PMC**)list_get(interpreter, list, index, enum_type_PMC);
PMC *temp = *(PMC**)list_get(interpreter, list, right, enum_type_PMC);
list_assign(interpreter, list, index, temp, enum_type_PMC);
index = right;
while (cursor != index) {
INTVAL cmp;
temp = *(PMC**)list_get(interpreter, list, cursor, enum_type_PMC);
if (!cmpsub)
cmp = mmd_dispatch_i_pp(interpreter, temp, pivot, MMD_CMP);
else {
struct parrot_regs_t *bp;
REG_INT(0) = 1;
REG_INT(1) = REG_INT(2) = 0;
REG_INT(3) = 2;
REG_PMC(5) = temp;
REG_PMC(6) = pivot;
bp = Parrot_PyClass_runops_fromc(interpreter, cmpsub);
cmp = VTABLE_get_integer(interpreter, BP_REG_PMC(bp,5));
}
if (cmp <= 0) {
if (cursor > index) {
INTVAL swap = index;
index = cursor;
cursor = swap;
list_assign(interpreter, list, cursor, temp, enum_type_PMC);
}
cursor++;
}
else {
if (cursor < index) {
INTVAL swap = index;
index = cursor;
cursor = swap;
list_assign(interpreter, list, cursor, temp, enum_type_PMC);
}
cursor--;
}
}
list_assign(interpreter, list, index, pivot, enum_type_PMC);
if (index*2 < left + right) {
quicksort(interpreter, list, cmpsub, left, index-1);
left = index+1;
}
else {
quicksort(interpreter, list, cmpsub, index+1, right);
right = index-1;
}
}
}
pmclass PyList extends PyObject need_ext does array dynpmc group python_group {
/*
=item C<void class_init()>
Class initialization. Caches the type id of various PMCs because
they will be used frequently here.
=cut
*/
void class_init() {
if (pass) {
dynclass_PyInt = Parrot_PMC_typenum(INTERP, "PyInt");
dynclass_PyIter = Parrot_PMC_typenum(INTERP, "PyIter");
dynclass_PyList = Parrot_PMC_typenum(INTERP, "PyList");
dynclass_PyNone = Parrot_PMC_typenum(INTERP, "PyNone");
dynclass_PyString = Parrot_PMC_typenum(INTERP, "PyString");
}
}
/*
=item C<void init()>
Initializes the PMC by calling the underlying C<list_new()> function.
=cut
*/
void init () {
list_pmc_new(INTERP, SELF);
PObj_custom_mark_SET(SELF);
}
/*
=item C<void "append" (PMC* self, PMC* value)>
Extends the array by adding an element of value C<*value> to the end of
the array.
=cut
*/
METHOD void append (PMC* self, PMC* value) {
VTABLE_push_pmc(INTERP, self, value);
}
/*
=item C<void mark()>
Mark the array and its contents as live.
=cut
*/
void mark () {
list_mark(INTERP, (List *) PMC_data(SELF));
}
/*
=item C<void delete_keyed(PMC *key)>
Delete a (range of) elements from the list
=cut
*/
void delete_keyed (PMC* key) {
if (key->vtable->base_type == enum_class_Slice) {
List *list = (List *)PMC_data(SELF);
PMC *slice = Parrot_py_make_slice(INTERP, SELF, key);
parrot_range_t *range = PMC_struct_val(slice);
INTVAL start = RVal_int(range->start);
INTVAL end = RVal_int(range->end);
list_delete(INTERP, list, start, end-start);
}
else
internal_exception(OUT_OF_BOUNDS,
"PyList: unimplemented delete!");
}
/*
=item C<INTVAL elements()>
Returns the number of elements in the array.
=cut
*/
INTVAL elements () {
return ((List *) PMC_data(SELF))->length;
}
/*
=item C<INTVAL get_bool()>
Returns true iff there are elements in the list.
=cut
*/
INTVAL get_bool () {
return DYNSELF.elements() != 0;
}
/*
=item C<INTVAL get_integer()>
Returns the number of elements in the array.
=cut
*/
INTVAL get_integer () {
return DYNSELF.elements();
}
/*
=item C<PMC* get_iter ()>
Return a new iterator for SELF.
=cut
*/
PMC* get_iter () {
PMC *iter = pmc_new_init(interpreter, dynclass_PyIter, SELF);
PMC *key = pmc_new(interpreter, enum_class_Key);
PMC_struct_val(iter) = key;
PObj_get_FLAGS(key) |= KEY_integer_FLAG;
PMC_int_val(key) = 0;
if (!((List *) PMC_data(SELF))->length)
PMC_int_val(key) = -1;
return iter;
}
/*
=item C<PMC* get_pmc_keyed(PMC* key)>
Returns the PMC value of the element at index C<key>.
=cut
*/
PMC* get_pmc_keyed (PMC* key) {
if (key->vtable->base_type == enum_class_Slice) {
PMC *slice = Parrot_py_make_slice(INTERP, SELF, key);
parrot_range_t *range = PMC_struct_val(slice);
INTVAL start = RVal_int(range->start);
INTVAL end = RVal_int(range->end);
PMC * ret = pmc_new(INTERP, dynclass_PyList);
INTVAL n = end-start;
INTVAL j;
for (j=0; j<n; j++) {
PMC *item = VTABLE_get_pmc_keyed_int(INTERP, SELF, start+j);
VTABLE_set_pmc_keyed_int(INTERP, ret, j, item);
}
VTABLE_set_integer_native(INTERP, ret, n);
return ret;
}
else {
INTVAL ix = key_integer(INTERP, key);
return SELF.get_pmc_keyed_int(ix);
}
}
/*
=item C<PMC* get_pmc_keyed_int(INTVAL key)>
Returns the PMC value of the element at index C<key>.
=cut
*/
PMC* get_pmc_keyed_int (INTVAL key) {
List *list = (List *)PMC_data(SELF);
PMC *ret = list_get(INTERP, list, key, enum_type_PMC);
if (ret == (void*) -1)
/* XXX throw IndexError: list index out of range */ ;
else {
ret = *(PMC**) ret;
if (ret == NULL)
ret = pmc_new(interpreter, dynclass_PyNone);
}
return ret;
}
/*
=item C<STRING *get_string()>
Returns the list as a string
=cut
*/
STRING* get_string () {
STRING *res, *s;
INTVAL j, n;
PMC *val;
res = string_from_cstring(INTERP, "[", 0);
n = VTABLE_elements(INTERP, SELF);
for (j = 0; j < n; ++j) {
STRING *vals;
val = SELF.get_pmc_keyed_int(j);
REG_INT(3) = 0;
vals = VTABLE_get_repr(INTERP, val);
res = string_append(INTERP, res, vals, 0);
if (j < n - 1)
res = string_append(INTERP, res,
const_string(INTERP, ", "), 0);
}
res = string_append(INTERP, res,
const_string(INTERP, "]"), 0);
return res;
}
/*
=item C<INTVAL is_equal (PMC* value)>
The C<==> operation. Compares two array to hold equal elements.
=cut
*/
INTVAL is_equal (PMC* value) {
INTVAL j, n;
if (value->vtable->base_type != dynclass_PyList)
return 0;
n = SELF.elements();
if (VTABLE_elements(INTERP, value) != n)
return 0;
for (j = 0; j < n; ++j) {
PMC *item1, *item2;
item1 = SELF.get_pmc_keyed_int(j);
item2 = VTABLE_get_pmc_keyed_int(INTERP, value, j);
if (item1 == item2)
continue;
if (!mmd_dispatch_i_pp(INTERP, item1, item2, MMD_EQ))
return 0;
}
return 1;
}
/*
=item C<void multiply_int(INTVAL value, PMC *dest)>
Build a list by duplicating the passed list N times.
=cut
*/
void multiply_int (INTVAL value, PMC* dest) {
INTVAL k = DYNSELF.elements();
INTVAL i;
PMC *elem;
List *list;
if (k == 1) {
elem = VTABLE_get_pmc_keyed_int(INTERP, SELF, 0);
VTABLE_morph(INTERP, dest, dynclass_PyList);
list = PMC_data(dest);
list_set_length(INTERP, list, value);
for (i = 0; i < value; ++i)
list_assign(INTERP, list, i, elem, enum_type_PMC);
}
else {
internal_exception(1, "multiply_int: unimplemented list size");
}
}
/*
=item C<void push_integer (INTVAL value)>
Extends the array by adding an element of value C<value> to the end of
the array.
=cut
*/
void push_integer (INTVAL value) {
INTVAL nextix = DYNSELF.elements();
DYNSELF.set_integer_keyed_int(nextix, value);
}
/*
=item C<void push_pmc (PMC* value)>
Extends the array by adding an element of value C<*value> to the end of
the array.
=cut
*/
void push_pmc (PMC* value) {
INTVAL nextix = DYNSELF.elements();
DYNSELF.set_pmc_keyed_int(nextix, value);
}
/*
=item C<void push_string (STRING* value)>
Extends the array by adding an element of value C<*value> to the end of
the array.
=cut
*/
void push_string (STRING* value) {
INTVAL nextix = DYNSELF.elements();
DYNSELF.set_string_keyed_int(nextix, value);
}
/*
=item C<void set_integer_keyed_int (INTVAL key, INTVAL value)>
Sets the integer value of the PMC at element C<key> to C<value>.
=cut
*/
void set_integer_keyed_int (INTVAL key, INTVAL value) {
PMC *src = pmc_new_noinit(INTERP, dynclass_PyInt);
PMC_int_val(src) = value;
list_assign(INTERP, (List *) PMC_data(SELF), key, src, enum_type_PMC);
}
/*
=item C<void set_integer_native(INTVAL size)>
Sets the length of the array to C<size>.
=cut
*/
void set_integer_native (INTVAL size) {
list_set_length(INTERP, (List *) PMC_data(SELF) ,size);
}
/*
=item C<void set_pmc_keyed(PMC* key)>
Sets the PMC at element C<key> to C<*value>.
=cut
*/
void set_pmc_keyed (PMC* key, PMC* value) {
if (key->vtable->base_type == enum_class_Slice) {
List *list = (List *)PMC_data(SELF);
PMC *slice = Parrot_py_make_slice(INTERP, SELF, key);
parrot_range_t *range = PMC_struct_val(slice);
INTVAL start = RVal_int(range->start);
INTVAL end = RVal_int(range->end);
list_splice(INTERP, list, value, start, end-start);
}
else {
INTVAL ix = key_integer(INTERP, key);
SELF.set_pmc_keyed_int(ix, value);
}
}
/*
=item C<void set_pmc_keyed_int(INTVAL key, PMC *src)>
Assigns C<*src> to the array at index C<key>.
=cut
*/
void set_pmc_keyed_int (INTVAL key, PMC* src) {
list_assign(INTERP, (List *) PMC_data(SELF), key, src, enum_type_PMC);
}
/*
=item C<void set_string_keyed_int(INTVAL key, STRING* value)>
Sets the string value of the PMC at element C<key> to C<value>.
=cut
*/
void set_string_keyed_int (INTVAL key, STRING* value) {
PMC *src = pmc_new_noinit(INTERP, dynclass_PyString);
VTABLE_set_string_native(INTERP, src, value);
list_assign(INTERP, (List *) PMC_data(SELF), key, src, enum_type_PMC);
}
/*
=item C<void* "sort"(PMC* cmp_func)>
Sort this array, optionally using the provided cmp_func
=cut
*/
METHOD void sort(PMC *self, PMC *cmp_func) {
if (REG_INT(3) < 2 || !VTABLE_get_bool(INTERP, cmp_func))
cmp_func = NULL;
INTVAL n = VTABLE_elements(INTERP, self);
quicksort(INTERP, (List *) PMC_data(self), cmp_func, 0, n-1);
}
/*
=back
=cut
*/
}
/*
* Local variables:
* c-indentation-style: bsd
* c-basic-offset: 4
* indent-tabs-mode: nil
* End:
*
* vim: expandtab shiftwidth=4:
*/
Jump to Line
Something went wrong with that request. Please try again.