Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
tree: f35b03c947
Fetching contributors…

Cannot retrieve contributors at this time

917 lines (692 sloc) 24.624 kb
/*
Copyright: 2001-2003 The Perl Foundation. All Rights Reserved.
$Id$
=head1 NAME
classes/pybuiltin.pmc - Python "builtin" Functions
=head1 DESCRIPTION
This class implements the Python "builtin" Functions.
=head2 Methods
=over 4
=cut
*/
#include "parrot/parrot.h"
/* cache of classes referenced */
static INTVAL dynclass_PyObject;
static INTVAL dynclass_PyBoolean;
static INTVAL dynclass_PyComplex;
static INTVAL dynclass_PyDict;
static INTVAL dynclass_PyException;
static INTVAL dynclass_PyInt;
static INTVAL dynclass_PyFloat;
static INTVAL dynclass_PyList;
static INTVAL dynclass_PyLong;
static INTVAL dynclass_PyNone;
static INTVAL dynclass_PyProxyType;
static INTVAL dynclass_PyString;
static INTVAL dynclass_PyTuple;
static STRING *BASES;
static STRING *HEX;
static STRING *NAME;
static STRING *OCT;
static STRING *PYOBJECT;
extern PMC* Parrot_Hash_get_iter(Interp* interpreter, PMC* pmc);
#define VTABLE_cmp(i,l,r) mmd_dispatch_i_pp(i,l,r,MMD_CMP)
PMC* Parrot_lib_python_group_init(Interp* interpreter, PMC *lib_pmc);
void Parrot_PyBuiltin___load__(Interp* interpreter, PMC* pmc);
PMC* Parrot_lib_python_group_init(Interp* interpreter, PMC *lib_pmc) {
Parrot_PyBuiltin___load__(interpreter, NULL);
return lib_pmc;
}
static PMC* make_type(Interp* interpreter, INTVAL class, STRING* name) {
STRING *pmcname = Parrot_base_vtables[class]->whoami;
PMC *type = pmc_new(interpreter, dynclass_PyProxyType);
PMC *nameprop = pmc_new(interpreter, dynclass_PyString);
PMC *stash, *iter, *item;
STRING *key;
INTVAL n, j;
stash = Parrot_find_global(interpreter, pmcname, NULL);
if (!stash) internal_exception(1, "Can't find methods");
/* For each, extract the key and item, and store in the scratchpad */
iter = Parrot_Hash_get_iter(interpreter, stash);
n = VTABLE_elements(interpreter, stash);
for (j = 0; j < n; ++j) {
key = VTABLE_shift_string(interpreter, iter);
item = VTABLE_get_pmc_keyed_str(interpreter, stash, key);
VTABLE_add_method(interpreter, type, key, item);
}
VTABLE_set_string_native(interpreter, nameprop, name);
VTABLE_setprop(interpreter, type, NAME, nameprop);
return type;
}
pmclass PyBuiltin 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_PyObject = Parrot_PMC_typenum(INTERP, "PyObject");
dynclass_PyBoolean = Parrot_PMC_typenum(INTERP, "PyBoolean");
dynclass_PyComplex = Parrot_PMC_typenum(INTERP, "PyComplex");
dynclass_PyDict = Parrot_PMC_typenum(INTERP, "PyDict");
dynclass_PyException = Parrot_PMC_typenum(INTERP, "PyException");
dynclass_PyInt = Parrot_PMC_typenum(INTERP, "PyInt");
dynclass_PyFloat = Parrot_PMC_typenum(INTERP, "PyFloat");
dynclass_PyList = Parrot_PMC_typenum(INTERP, "PyList");
dynclass_PyLong = Parrot_PMC_typenum(INTERP, "PyLong");
dynclass_PyNone = Parrot_PMC_typenum(INTERP, "PyNone");
dynclass_PyProxyType = Parrot_PMC_typenum(INTERP, "PyProxyType");
dynclass_PyString = Parrot_PMC_typenum(INTERP, "PyString");
dynclass_PyTuple = Parrot_PMC_typenum(INTERP, "PyTuple");
BASES = const_string(INTERP, "__bases__");
HEX = const_string(INTERP, "__hex__");
NAME = const_string(INTERP, "__name__");
OCT = const_string(INTERP, "__oct__");
PYOBJECT = const_string(INTERP, "PyObject");
}
}
/*
=item C<PMC* "__load__"()>
This is unabashed hackery scaffolding. It copies all the builtins
functions from globals to lexicaly scoped variables.
=cut
The implementation is highly dependent on the internals of globals and
ordered hashes, and will break should either of them change - of course,
any such breakage should show up quickly in the unit tests.
Longer term, either globals should expose an iterator by which one
can discover keys (needed to support a Python "dir" like function), or
enter_nci_method should create these as locals to begin with.
*/
METHOD void __load__() {
STRING *name, *key;
PMC *stash, *iter, *item, *pad, *temp, *parent;
INTVAL j, n;
/* Already init'ed? */
pad = scratchpad_get_current(INTERP);
if (!pad) {
pad = scratchpad_new(interpreter, NULL, 0);
stack_push(interpreter, &interpreter->ctx.pad_stack, pad,
STACK_ENTRY_PMC, STACK_CLEANUP_NULL);
}
name = const_string(INTERP, "__name__");
temp = scratchpad_find(INTERP, pad, name);
if (temp && VTABLE_defined(INTERP, temp)) return;
/* Find all PyBuiltin "nci" methods */
stash = Parrot_find_global(INTERP,
const_string(INTERP, "PyBuiltin"), NULL);
if (!stash)
internal_exception(1, "Can't find PyBuiltins");
/* For each, extract the key and item, and store in the scratchpad */
iter = Parrot_Hash_get_iter(INTERP, stash);
n = VTABLE_elements(INTERP, stash);
for (j = 0; j < n; ++j) {
PMC *nameprop = pmc_new(interpreter, dynclass_PyString);
key = VTABLE_shift_string(INTERP, iter);
item = VTABLE_get_pmc_keyed_str(INTERP, stash, key);
VTABLE_set_string_native(interpreter, nameprop, key);
VTABLE_setprop(interpreter, item, NAME, nameprop);
scratchpad_store_by_name(INTERP, pad, 0, key, item);
}
/* constants */
key = const_string(INTERP, "__debug__");
item = pmc_new(INTERP, dynclass_PyBoolean);
VTABLE_set_integer_native(INTERP, item, 1);
scratchpad_store_by_name(INTERP, pad, 0, key, item);
key = const_string(INTERP, "False");
item = pmc_new(INTERP, dynclass_PyBoolean);
VTABLE_set_integer_native(INTERP, item, 0);
scratchpad_store_by_name(INTERP, pad, 0, key, item);
key = const_string(INTERP, "True");
item = pmc_new(INTERP, dynclass_PyBoolean);
VTABLE_set_integer_native(INTERP, item, 1);
scratchpad_store_by_name(INTERP, pad, 0, key, item);
key = const_string(INTERP, "None");
item = pmc_new(INTERP, dynclass_PyNone);
scratchpad_store_by_name(INTERP, pad, 0, key, item);
/* exceptions */
key = const_string(INTERP, "RuntimeError");
item = pmc_new(INTERP, dynclass_PyException);
VTABLE_set_integer_native(INTERP, item, E_RuntimeError);
scratchpad_store_by_name(INTERP, pad, 0, key, item);
key = const_string(INTERP, "StopIteration");
item = pmc_new(INTERP, dynclass_PyException);
VTABLE_set_integer_native(INTERP, item, E_StopIteration);
scratchpad_store_by_name(INTERP, pad, 0, key, item);
key = const_string(INTERP, "ValueError");
item = pmc_new(INTERP, dynclass_PyException);
VTABLE_set_integer_native(INTERP, item, E_ValueError);
scratchpad_store_by_name(INTERP, pad, 0, key, item);
/* Class objects */
key = const_string(INTERP, "object");
parent = make_type(INTERP, dynclass_PyObject, key);
key = const_string(INTERP, "dict");
item = make_type(INTERP, dynclass_PyDict, key);
VTABLE_setprop(INTERP, item, BASES, parent);
scratchpad_store_by_name(INTERP, pad, 0, key, item);
key = const_string(INTERP, "int");
item = make_type(INTERP, dynclass_PyInt, key);
VTABLE_setprop(INTERP, item, BASES, parent);
scratchpad_store_by_name(INTERP, pad, 0, key, item);
/* TODO: convert this to instances of <type> */
key = const_string(INTERP, "xrange");
item = pmc_new(INTERP, enum_class_Slice);
scratchpad_store_by_name(INTERP, pad, 0, key, item);
key = const_string(INTERP, "object");
item = Parrot_class_lookup(interpreter, const_string(INTERP, "PyType"));
scratchpad_store_by_name(INTERP, pad, 0, key, item);
/* Begin main! */
item = pmc_new(INTERP, dynclass_PyString);
VTABLE_set_string_native(INTERP, item,
const_string(INTERP, "__main__"));
scratchpad_store_by_name(INTERP, pad, 0, name, item);
}
/*
=item C<PMC* "abs"()>
Returns the absolute value of an object
=cut
*/
METHOD PMC* abs(PMC *object) {
PMC * ret = pmc_new(INTERP, dynclass_PyObject);
VTABLE_absolute(INTERP, object, ret);
return ret;
}
/*
=item C<PMC* "callable"(PMC *object)>
Returns the absolute value of an object
=cut
*/
METHOD PMC* callable(PMC *object) {
PMC * ret = pmc_new(INTERP, dynclass_PyBoolean);
STRING *sub = Parrot_base_vtables[enum_class_Sub]->whoami;
STRING *nci = Parrot_base_vtables[enum_class_NCI]->whoami;
INTVAL isa = VTABLE_isa(INTERP, object, sub) ||
VTABLE_isa(INTERP, object, nci);
VTABLE_set_integer_native(INTERP, ret, isa);
return ret;
}
/*
=item C<PMC* "chr"(PMC *value)>
Return a string of one character with ordinal C<*value>.
=cut
*/
METHOD PMC* chr(PMC *value) {
PMC *s = pmc_new_noinit(INTERP, dynclass_PyString);
INTVAL i = VTABLE_get_integer(INTERP, value);
/*
* TODO if i < 0 || > 255 throgh ValueError
*/
PMC_str_val(s) = string_chr(INTERP, (UINTVAL)i);
PObj_custom_mark_SET(s);
return s;
}
/*
=item C<PMC* "cmp"(PMC *value1, PMC *value2)>
Returns the result of comparing C<*value1> with C<*value2).
=cut
*/
METHOD PMC* cmp(PMC *value1, PMC *value2) {
PMC * ret = pmc_new(INTERP, dynclass_PyInt);
VTABLE_set_integer_native(INTERP, ret,
mmd_dispatch_i_pp(INTERP, value1, value2, MMD_CMP));
return ret;
}
/*
=item C<PMC* "complex"()>
Combines a real and imaginary number and returns the result.
=cut
*/
METHOD PMC* complex(PMC *real, PMC *imag) {
FLOATVAL fvalue;
PMC * ret = pmc_new(INTERP, dynclass_PyComplex);
fvalue = VTABLE_get_number(INTERP, real);
VTABLE_set_number_keyed_int(INTERP, ret, 0, fvalue);
fvalue = VTABLE_get_number(INTERP, imag);
VTABLE_set_number_keyed_int(INTERP, ret, 1, fvalue);
return ret;
}
/*
=item C<PMC* "enumerate"(PMC *list)>
Iterator for index, value of iterable.
=cut
*/
METHOD PMC* enumerate(PMC *list) {
PMC *res = pmc_new_init(INTERP, enum_class_Enumerate, list);
return res;
}
/*
=item C<PMC* "filter"(PMC *func, PMC *list)>
Combines a real and imaginary number and returns the result.
Return those it ems of sequence for which function(item) is true.
If function is None, return the items that are true. If sequence
is a tuple or string, return the same type, else return a list.
=cut
*/
METHOD PMC* filter(PMC *func, PMC *list) {
PMC *res, *iter;
INTVAL i, n;
STRING *s;
INTVAL type;
int none_func;
type = list->vtable->base_type;
iter = NULL;
if (type == dynclass_PyString) {
res = pmc_new(INTERP, type);
}
else {
if (type == enum_class_Iterator) iter = list;
res = pmc_new(INTERP, dynclass_PyList);
}
if (!iter)
iter = pmc_new_init(INTERP, enum_class_Iterator, list);
VTABLE_set_integer_native(INTERP, iter, 0);
i = 0;
none_func = PMC_IS_NULL(func) ||
func->vtable->base_type == dynclass_PyNone;
while (VTABLE_get_bool(INTERP, iter)) {
PMC *item = VTABLE_shift_pmc(INTERP, iter);
if (none_func) {
if (!VTABLE_get_bool(INTERP, item))
continue;
}
else {
/* run filter func -
* TODO save registers once around loop
*/
PMC *t;
struct parrot_regs_t *bp;
REG_PMC(5) = item;
REG_INT(0) = REG_INT(3) = 1;
REG_INT(1) = REG_INT(2) = REG_INT(4) = 0;
bp = Parrot_runops_fromc(INTERP, func);
t = BP_REG_PMC(bp,5);
if (!VTABLE_get_bool(INTERP, t))
continue;
}
VTABLE_set_pmc_keyed_int(INTERP, res, i++, item);
}
return res;
}
/*
=item C<PMC* "float"()>
Returns the float value of C<value>.
=cut
*/
METHOD PMC* float(PMC *value) {
PMC * ret;
if (value->vtable->base_type == dynclass_PyFloat)
return value;
ret = pmc_new(INTERP, dynclass_PyFloat);
if (value->vtable->base_type == dynclass_PyInt) {
FLOATVAL fvalue = VTABLE_get_number(INTERP, value);
VTABLE_set_number_native(INTERP, ret, fvalue);
}
else {
STRING *svalue = VTABLE_get_string(INTERP, value);
VTABLE_set_string_native(INTERP, ret, svalue);
}
return ret;
}
/*
=item C<PMC* "hash"(PMC *value)>
Returns the hash of C<value>.
=cut
*/
METHOD PMC* hash(PMC *value) {
PMC *ret = pmc_new_noinit(INTERP, dynclass_PyInt);
VTABLE_set_integer_native(INTERP, ret, VTABLE_hash(INTERP, value));
return ret;
}
/*
=item C<PMC* "hex"(PMC *value)>
Returns the hex representation of C<value>.
=cut
*/
METHOD PMC* hex(PMC *value) {
PMC * meth = VTABLE_find_method(INTERP, value, HEX);
REG_INT(3) = 0;
REG_PMC(2) = value;
VTABLE_invoke(INTERP, meth, REG_PMC(1));
return REG_PMC(5);
}
/*
=item C<PMC* "id"(PMC *value)>
Returns the "identity" of C<value>.
=cut
*/
METHOD PMC* id(PMC *value) {
PMC * ret = pmc_new(INTERP, dynclass_PyInt);
VTABLE_set_integer_native(INTERP, ret, (INTVAL)value);
return ret;
}
/*
=item C<PMC* "isinstance"(PMC *object, PMC* class)>
Returns the "identity" of C<value>.
=cut
TODO: for this to be interoperable across languages, we will need
a C<isinstance> VTABLE entry.
TODO: bases should be a tuple
*/
METHOD PMC* isinstance(PMC *object, PMC* class) {
PMC *ret = pmc_new(INTERP, dynclass_PyBoolean);
PMC * test = VTABLE_get_class(INTERP, object);
VTABLE_set_integer_native(INTERP, ret, 0);
while (test && VTABLE_defined(INTERP, test)) {
if (test == class) {
VTABLE_set_integer_native(INTERP, ret, 1);
break;
}
test = VTABLE_getprop(INTERP, test, BASES);
}
return ret;
}
/*
=item C<PMC* "iter"(PMC *obj)>
Returns an iterator over a sequence.
=cut
*/
METHOD PMC* iter(PMC *obj) {
/*
* need an iterator - that's the original construction code
*/
return VTABLE_get_iter(INTERP, obj);
}
/*
=item C<PMC* "list"(PMC *value)>
Returns the list value of C<value>.
=cut
*/
METHOD PMC* list(PMC *value) {
PMC *ret = pmc_new(INTERP, dynclass_PyList);
INTVAL n = VTABLE_elements(INTERP, value);
INTVAL j;
for (j=0; j<n; j++) {
PMC *item = VTABLE_get_pmc_keyed_int(INTERP, value, j);
VTABLE_set_pmc_keyed_int(INTERP, ret, j, item);
}
VTABLE_set_integer_native(INTERP, ret, n);
return ret;
}
/*
=item C<PMC* "long"(PMC *value)>
Returns the long value of C<value>.
=cut
*/
METHOD PMC* long(PMC *value, PMC *base) {
PMC *ret;
if (value->vtable->base_type == dynclass_PyLong)
return value;
ret = pmc_new(INTERP, dynclass_PyLong);
if (value->vtable->base_type == dynclass_PyInt) {
INTVAL ivalue = VTABLE_get_integer(INTERP, value);
VTABLE_set_integer_native(INTERP, ret, ivalue);
}
else {
INTVAL argcP = REG_INT(3);
STRING *svalue = VTABLE_get_string(INTERP, value);
if (argcP == 1)
VTABLE_set_string_native(INTERP, ret, svalue);
else {
INTVAL key = VTABLE_get_integer(INTERP, base);
VTABLE_set_string_keyed_int(INTERP, ret, key, svalue);
}
}
return ret;
}
/*
=item C<PMC* "max"(PMC *value)>
Returns the maximum of a set of values.
=cut
*/
METHOD PMC* max(PMC *argv) {
PMC *arg, *max, *iter;
INTVAL i, n;
/*
* no arguments: bail out
*/
if ((n = REG_INT(3)) == 0)
real_exception(INTERP, NULL, E_TypeError,
"TypeError: max expected 1 arguments, got 0");
if (n == 1) {
/* argument must be iterable */
arg = REG_PMC(5);
iter = pmc_new_init(INTERP, enum_class_Iterator, arg);
VTABLE_set_integer_native(INTERP, iter, 0);
max = VTABLE_shift_pmc(INTERP, iter);
while (VTABLE_get_bool(INTERP, iter)) {
PMC *item = VTABLE_shift_pmc(INTERP, iter);
if (VTABLE_cmp(INTERP, max, item) < 0)
max = item;
}
return max;
}
/* got n items */
max = REG_PMC(5);
for (i = 1; i < n && i<11; ++i) {
PMC *item = REG_PMC(5+i);
if (VTABLE_cmp(INTERP, max, item) < 0)
max = item;
}
return max;
}
/*
=item C<PMC* "map"(PMC *value)>
Return a list of the result s of applying the function to the items of
the argument sequence(s).
=cut
*/
METHOD PMC* map(PMC *func, PMC *list) {
PMC *res, *iter;
INTVAL i, n;
STRING *s;
INTVAL type;
int none_func;
type = list->vtable->base_type;
iter = NULL;
if (type == dynclass_PyString) {
res = pmc_new(INTERP, type);
}
else {
if (type == enum_class_Iterator) iter = list;
res = pmc_new(INTERP, dynclass_PyList);
}
if (!iter)
iter = pmc_new_init(INTERP, enum_class_Iterator, list);
VTABLE_set_integer_native(INTERP, iter, 0);
i = 0;
none_func = PMC_IS_NULL(func) ||
func->vtable->base_type == dynclass_PyNone;
while (VTABLE_get_bool(INTERP, iter)) {
PMC *item = VTABLE_shift_pmc(INTERP, iter);
if (!none_func) {
struct parrot_regs_t *bp;
REG_PMC(5) = item;
REG_INT(0) = REG_INT(3) = 1;
REG_INT(1) = REG_INT(2) = REG_INT(4) = 0;
bp = Parrot_runops_fromc(INTERP, func);
item = BP_REG_PMC(bp,5);
}
VTABLE_set_pmc_keyed_int(INTERP, res, i++, item);
}
return res;
}
/*
=item C<PMC* "min"(PMC *value)>
Returns the minimum of a set of values.
=cut
*/
METHOD PMC* min(PMC *argv) {
PMC *arg, *min, *iter;
INTVAL i, n;
/*
* no arguments: bail out
*/
if ((n = REG_INT(3)) == 0)
real_exception(INTERP, NULL, E_TypeError,
"TypeError: min expected 1 arguments, got 0");
if (n == 1) {
/* argument must be iterable */
arg = REG_PMC(5);
iter = pmc_new_init(INTERP, enum_class_Iterator, arg);
VTABLE_set_integer_native(INTERP, iter, 0);
min = VTABLE_shift_pmc(INTERP, iter);
while (VTABLE_get_bool(INTERP, iter)) {
PMC *item = VTABLE_shift_pmc(INTERP, iter);
if (VTABLE_cmp(INTERP, min, item) > 0)
min = item;
}
return min;
}
/* got n items */
min = REG_PMC(5);
for (i = 1; i < n && i<11; ++i) {
PMC *item = REG_PMC(5+i);
if (VTABLE_cmp(INTERP, min, item) > 0)
min = item;
}
return min;
}
/*
=item C<PMC* "oct"(PMC *value)>
Returns the octal representation of C<value>.
=cut
*/
METHOD PMC* oct(PMC *value) {
PMC * meth = VTABLE_find_method(INTERP, value, OCT);
REG_INT(3) = 0;
REG_PMC(2) = value;
VTABLE_invoke(INTERP, meth, REG_PMC(1));
return REG_PMC(5);
}
/*
=item C<PMC* "ord"(PMC *value)>
Return the integer ordinal of a one-character string.
=cut
*/
METHOD PMC* ord(PMC *value) {
PMC * ret = pmc_new(INTERP, dynclass_PyInt);
STRING *svalue = VTABLE_get_string(INTERP, value);
INTVAL ivalue = string_ord(INTERP, svalue, 0);
VTABLE_set_integer_native(INTERP, ret, ivalue);
return ret;
}
/*
=item C<PMC* "range"(PMC *pstart, PMC *pend, PMC *pstep)>
Returns a list of integers ranging from C<pstart> to C<pend> with
an increment of C<pstep>
=cut
*/
METHOD PMC* range(PMC *pstart, PMC *pend, PMC *pstep) {
PMC *ar = pmc_new(INTERP, dynclass_PyList);
INTVAL start = 0, end = 0, step = 1;
int i, k, argcP;
argcP = REG_INT(3);
if (argcP == 1) {
end = VTABLE_get_integer(INTERP, pstart);
}
else if (argcP == 2) {
start = VTABLE_get_integer(INTERP, pstart);
end = VTABLE_get_integer(INTERP, pend);
}
else if (argcP == 3) {
start = VTABLE_get_integer(INTERP, pstart);
end = VTABLE_get_integer(INTERP, pend);
step = VTABLE_get_integer(INTERP, pstep);
if (step == 0)
real_exception(INTERP, NULL, E_ValueError,
"range() step argument must not be zero");
}
else {
/* TODO err */
}
if (step < 0) {
for (i = start, k = 0; i > end; i += step, ++k)
VTABLE_set_integer_keyed_int(INTERP, ar, k, i);
}
else {
for (i = start, k = 0; i < end; i += step, ++k)
VTABLE_set_integer_keyed_int(INTERP, ar, k, i);
}
return ar;
}
/*
=item C<PMC* "reduce"(PMC *func, PMC *list, PMC *init)>
Apply a function of two arguments cumulatively to the items of a sequence,
from left to right, so as to reduce the sequence to a single value.
If initial is present, it is placed before the items of the sequence in the
calculation, and serves as a default whe n the sequence is empty.
=cut
*/
METHOD PMC* reduce(PMC *func, PMC *list, PMC *init) {
PMC *res, *iter;
INTVAL i, n;
STRING *s;
INTVAL type;
int none_func;
type = list->vtable->base_type;
iter = NULL;
if (type == dynclass_PyString) {
res = pmc_new(INTERP, type);
}
else {
if (type == enum_class_Iterator) iter = list;
res = pmc_new(INTERP, dynclass_PyList);
}
if (!iter)
iter = pmc_new_init(INTERP, enum_class_Iterator, list);
VTABLE_set_integer_native(INTERP, iter, 0);
i = 0;
none_func = PMC_IS_NULL(func) ||
func->vtable->base_type == dynclass_PyNone;
if (none_func) {
/* TODO TypeError: 'NoneType' object is not callable */
}
while (VTABLE_get_bool(INTERP, iter)) {
PMC *item = VTABLE_shift_pmc(INTERP, iter);
/* run filter func -
* TODO save registers once around loop
*/
struct parrot_regs_t *bp;
REG_PMC(5) = res;
REG_PMC(6) = item;
REG_INT(3) = 2;
REG_INT(0) = 1;
REG_INT(1) = REG_INT(2) = REG_INT(4) = 0;
bp = Parrot_runops_fromc(INTERP, func);
res = BP_REG_PMC(bp,5);
}
if ((REG_INT(3)>2) && 0==VTABLE_elements(INTERP, res))
res = init;
return res;
}
/*
=item C<PMC* "tuple"(PMC *value)>
Returns the tuple value of C<value>.
=cut
*/
METHOD PMC* tuple(PMC *value) {
PMC *ret = pmc_new(INTERP, dynclass_PyTuple);
INTVAL n = VTABLE_elements(INTERP, value);
INTVAL j;
VTABLE_set_integer_native(INTERP, ret, n);
for (j=0; j<n; j++) {
PMC *item = VTABLE_get_pmc_keyed_int(INTERP, value, j);
VTABLE_set_pmc_keyed_int(INTERP, ret, j, item);
}
return ret;
}
/*
=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.