2 # This file is Copyright 2006, 2007, 2009, 2010 Dean Hall.
4 # This file is part of the PyMite VM.
5 # The PyMite VM is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU GENERAL PUBLIC LICENSE Version 2.
8 # The PyMite VM is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 # A copy of the GNU GENERAL PUBLIC LICENSE Version 2
12 # is seen in the file COPYING in this directory.
17 #define __FILE_ID__ 0x14
24 * Functions that operate on sequences
32 * Compares two sequence objects
33 * Assumes both objects are of same type (guaranteed by obj_compare)
36 seq_compare(pPmObj_t pobj1
, pPmObj_t pobj2
)
45 /* Get the lengths of supported types or return differ */
46 if (OBJ_GET_TYPE(pobj1
) == OBJ_TYPE_TUP
)
48 l1
= ((pPmTuple_t
)pobj1
)->length
;
49 l2
= ((pPmTuple_t
)pobj2
)->length
;
51 else if (OBJ_GET_TYPE(pobj1
) == OBJ_TYPE_LST
)
53 l1
= ((pPmList_t
)pobj1
)->length
;
54 l2
= ((pPmList_t
)pobj2
)->length
;
58 else if (OBJ_GET_TYPE(pobj1
) == OBJ_TYPE_BYA
)
60 /* Return if the lengths differ */
61 l1
= ((pPmBytearray_t
)pobj1
)->length
;
62 l2
= ((pPmBytearray_t
)pobj2
)->length
;
68 return sli_strncmp((char const *)&(((pPmBytes_t
)((pPmBytearray_t
)pobj1
)->val
)->val
),
69 (char const *)&(((pPmBytes_t
)((pPmBytearray_t
)pobj2
)->val
)->val
),
73 #endif /* HAVE_BYTEARRAY */
80 /* Return if the lengths differ */
86 /* Compare all items in the sequences */
89 retval
= seq_getSubscript(pobj1
, l1
, &pa
);
90 if (retval
!= PM_RET_OK
)
94 retval
= seq_getSubscript(pobj2
, l1
, &pb
);
95 if (retval
!= PM_RET_OK
)
99 retcompare
= obj_compare(pa
, pb
);
100 if (retcompare
!= C_SAME
)
110 /* Returns the length of the sequence */
112 seq_getLength(pPmObj_t pobj
, int16_t *r_index
)
114 PmReturn_t retval
= PM_RET_OK
;
116 switch (OBJ_GET_TYPE(pobj
))
119 *r_index
= ((pPmString_t
)pobj
)->length
;
123 *r_index
= ((pPmTuple_t
)pobj
)->length
;
127 *r_index
= ((pPmList_t
)pobj
)->length
;
130 #ifdef HAVE_BYTEARRAY
132 *r_index
= ((pPmBytearray_t
)pobj
)->length
;
134 #endif /* HAVE_BYTEARRAY */
137 /* Raise TypeError, non-sequence object */
138 PM_RAISE(retval
, PM_RET_EX_TYPE
);
146 /* Returns the object sequence[index] */
148 seq_getSubscript(pPmObj_t pobj
, int16_t index
, pPmObj_t
*r_pobj
)
153 switch (OBJ_GET_TYPE(pobj
))
156 /* Adjust for negative index */
159 index
+= ((pPmString_t
)pobj
)->length
;
162 /* Raise IndexError if index is out of bounds */
163 if ((index
< 0) || (index
> ((pPmString_t
)pobj
)->length
))
165 PM_RAISE(retval
, PM_RET_EX_INDX
);
169 /* Get the character from the string */
170 c
= ((pPmString_t
)pobj
)->val
[index
];
172 /* Create a new string from the character */
173 retval
= string_newFromChar(c
, r_pobj
);
177 /* Get the tuple item */
178 retval
= tuple_getItem(pobj
, index
, r_pobj
);
182 /* Get the list item */
183 retval
= list_getItem(pobj
, index
, r_pobj
);
186 #ifdef HAVE_BYTEARRAY
188 retval
= bytearray_getItem(pobj
, index
, r_pobj
);
190 #endif /* HAVE_BYTEARRAY */
193 /* Raise TypeError, unsubscriptable object */
194 PM_RAISE(retval
, PM_RET_EX_TYPE
);
203 seqiter_getNext(pPmObj_t pobj
, pPmObj_t
*r_pitem
)
208 C_ASSERT(pobj
!= C_NULL
);
209 C_ASSERT(*r_pitem
!= C_NULL
);
210 C_ASSERT(OBJ_GET_TYPE(pobj
) == OBJ_TYPE_SQI
);
213 * Raise TypeError if sequence iterator's object is not a sequence
214 * otherwise, the get sequence's length
216 retval
= seq_getLength(((pPmSeqIter_t
)pobj
)->si_sequence
, &length
);
217 PM_RETURN_IF_ERROR(retval
);
219 /* Raise StopIteration if at the end of the sequence */
220 if (((pPmSeqIter_t
)pobj
)->si_index
== length
)
222 /* Make null the pointer to the sequence */
223 ((pPmSeqIter_t
)pobj
)->si_sequence
= C_NULL
;
224 PM_RAISE(retval
, PM_RET_EX_STOP
);
228 /* Get the item at the current index */
229 retval
= seq_getSubscript(((pPmSeqIter_t
)pobj
)->si_sequence
,
230 ((pPmSeqIter_t
)pobj
)->si_index
, r_pitem
);
232 /* Increment the index */
233 ((pPmSeqIter_t
)pobj
)->si_index
++;
240 seqiter_new(pPmObj_t pobj
, pPmObj_t
*r_pobj
)
246 C_ASSERT(pobj
!= C_NULL
);
247 C_ASSERT(*r_pobj
!= C_NULL
);
249 /* Raise a TypeError if pobj is not a sequence */
250 if ((OBJ_GET_TYPE(pobj
) != OBJ_TYPE_STR
)
251 && (OBJ_GET_TYPE(pobj
) != OBJ_TYPE_TUP
)
252 && (OBJ_GET_TYPE(pobj
) != OBJ_TYPE_LST
))
254 PM_RAISE(retval
, PM_RET_EX_TYPE
);
258 /* Alloc a chunk for the sequence iterator obj */
259 retval
= heap_getChunk(sizeof(PmSeqIter_t
), &pchunk
);
260 PM_RETURN_IF_ERROR(retval
);
262 /* Set the sequence iterator's fields */
263 psi
= (pPmSeqIter_t
)pchunk
;
264 OBJ_SET_TYPE(psi
, OBJ_TYPE_SQI
);
265 psi
->si_sequence
= pobj
;
268 *r_pobj
= (pPmObj_t
)psi
;