2 # This file is Copyright 2003, 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__ 0x0B
22 * \brief List Object Type
24 * List object type operations.
32 list_append(pPmObj_t plist
, pPmObj_t pobj
)
37 C_ASSERT(plist
!= C_NULL
);
38 C_ASSERT(pobj
!= C_NULL
);
40 /* If plist is not a list, raise a TypeError exception */
41 if (OBJ_GET_TYPE(plist
) != OBJ_TYPE_LST
)
43 PM_RAISE(retval
, PM_RET_EX_TYPE
);
47 /* Create new seglist if needed */
48 if (((pPmList_t
)plist
)->length
== 0)
50 retval
= seglist_new(&((pPmList_t
)plist
)->val
);
51 PM_RETURN_IF_ERROR(retval
);
54 /* Append object to list */
55 heap_gcPushTempRoot((pPmObj_t
)((pPmList_t
)plist
)->val
, &objid
);
56 retval
= seglist_appendItem(((pPmList_t
)plist
)->val
, pobj
);
57 heap_gcPopTempRoot(objid
);
58 PM_RETURN_IF_ERROR(retval
);
60 /* Increment list length */
61 ((pPmList_t
)plist
)->length
++;
68 list_getItem(pPmObj_t plist
, int16_t index
, pPmObj_t
*r_pobj
)
72 /* If it's not a list, raise TypeError */
73 if (OBJ_GET_TYPE(plist
) != OBJ_TYPE_LST
)
75 PM_RAISE(retval
, PM_RET_EX_TYPE
);
79 /* Adjust the index */
82 index
+= ((pPmList_t
)plist
)->length
;
85 /* Check the bounds of the index */
86 if ((index
< 0) || (index
>= ((pPmList_t
)plist
)->length
))
88 PM_RAISE(retval
, PM_RET_EX_INDX
);
92 /* Get item from seglist */
93 retval
= seglist_getItem(((pPmList_t
)plist
)->val
, index
, r_pobj
);
99 list_insert(pPmObj_t plist
, int16_t index
, pPmObj_t pobj
)
105 C_ASSERT(plist
!= C_NULL
);
106 C_ASSERT(pobj
!= C_NULL
);
108 /* Raise a TypeError if plist is not a List */
109 if (OBJ_GET_TYPE(plist
) != OBJ_TYPE_LST
)
111 retval
= PM_RET_EX_TYPE
;
112 PM_RETURN_IF_ERROR(retval
);
115 /* Adjust an out-of-bounds index value */
116 len
= ((pPmList_t
)plist
)->length
;
130 /* Create new seglist if needed */
131 if (((pPmList_t
)plist
)->length
== 0)
133 retval
= seglist_new(&((pPmList_t
)plist
)->val
);
134 PM_RETURN_IF_ERROR(retval
);
137 /* Insert the item in the container */
138 heap_gcPushTempRoot((pPmObj_t
)((pPmList_t
)plist
)->val
, &objid
);
139 retval
= seglist_insertItem(((pPmList_t
)plist
)->val
, pobj
, index
);
140 heap_gcPopTempRoot(objid
);
141 PM_RETURN_IF_ERROR(retval
);
143 /* Increment list length */
144 ((pPmList_t
)plist
)->length
++;
150 list_new(pPmObj_t
*r_pobj
)
152 PmReturn_t retval
= PM_RET_OK
;
153 pPmList_t plist
= C_NULL
;
155 /* Allocate a list */
156 retval
= heap_getChunk(sizeof(PmList_t
), (uint8_t **)r_pobj
);
157 PM_RETURN_IF_ERROR(retval
);
159 /* Set list type, empty the contents */
160 plist
= (pPmList_t
)*r_pobj
;
161 OBJ_SET_TYPE(plist
, OBJ_TYPE_LST
);
170 list_copy(pPmObj_t pobj
, pPmObj_t
*r_pobj
)
172 return list_replicate(pobj
, 1, r_pobj
);
177 list_replicate(pPmObj_t psrclist
, int16_t n
, pPmObj_t
*r_pnewlist
)
179 PmReturn_t retval
= PM_RET_OK
;
183 pPmObj_t pitem
= C_NULL
;
186 C_ASSERT(psrclist
!= C_NULL
);
187 C_ASSERT(r_pnewlist
!= C_NULL
);
189 /* If first arg is not a list, raise TypeError */
190 if (OBJ_GET_TYPE(psrclist
) != OBJ_TYPE_LST
)
192 PM_RAISE(retval
, PM_RET_EX_TYPE
);
195 length
= ((pPmList_t
)psrclist
)->length
;
197 /* Allocate new list */
198 retval
= list_new(r_pnewlist
);
199 PM_RETURN_IF_ERROR(retval
);
201 /* Copy srclist the designated number of times */
202 for (i
= n
; i
> 0; i
--)
204 /* Iterate over the length of srclist */
205 for (j
= 0; j
< length
; j
++)
207 retval
= list_getItem(psrclist
, j
, &pitem
);
208 PM_RETURN_IF_ERROR(retval
);
209 heap_gcPushTempRoot(*r_pnewlist
, &objid
);
210 retval
= list_append(*r_pnewlist
, pitem
);
211 heap_gcPopTempRoot(objid
);
212 PM_RETURN_IF_ERROR(retval
);
220 list_setItem(pPmObj_t plist
, int16_t index
, pPmObj_t pobj
)
224 /* If it's not a list, raise TypeError */
225 if (OBJ_GET_TYPE(plist
) != OBJ_TYPE_LST
)
227 PM_RAISE(retval
, PM_RET_EX_TYPE
);
231 /* Adjust the index */
234 index
+= ((pPmList_t
)plist
)->length
;
237 /* Check the bounds of the index */
238 if ((index
< 0) || (index
>= ((pPmList_t
)plist
)->length
))
240 PM_RAISE(retval
, PM_RET_EX_INDX
);
245 retval
= seglist_setItem(((pPmList_t
)plist
)->val
, pobj
, index
);
251 list_remove(pPmObj_t plist
, pPmObj_t item
)
253 PmReturn_t retval
= PM_RET_OK
;
256 /* If it's not a list, raise TypeError */
257 if (OBJ_GET_TYPE(plist
) != OBJ_TYPE_LST
)
259 PM_RAISE(retval
, PM_RET_EX_TYPE
);
263 /* Locate the item to remove */
264 retval
= list_index(plist
, item
, &index
);
265 PM_RETURN_IF_ERROR(retval
);
267 /* Remove the item and decrement the list length */
268 retval
= seglist_removeItem(((pPmList_t
)plist
)->val
, index
);
269 ((pPmList_t
)plist
)->length
--;
271 /* Unlink seglist if there are no contents */
272 if (((pPmList_t
)plist
)->length
== 0)
274 ((pPmList_t
)plist
)->val
= C_NULL
;
282 list_index(pPmObj_t plist
, pPmObj_t pitem
, uint16_t *r_index
)
284 PmReturn_t retval
= PM_RET_OK
;
289 /* If it's not a list, raise TypeError */
290 if (OBJ_GET_TYPE(plist
) != OBJ_TYPE_LST
)
292 PM_RAISE(retval
, PM_RET_EX_TYPE
);
296 /* Raise a ValueError if the list is empty */
297 if (((pPmList_t
)plist
)->length
== 0)
299 PM_RAISE(retval
, PM_RET_EX_VAL
);
303 pseglist
= ((pPmList_t
)plist
)->val
;
305 /* Iterate over the list's contents */
306 for (index
= 0; index
< pseglist
->sl_length
; index
++)
308 retval
= seglist_getItem(pseglist
, index
, &pobj
);
309 PM_RETURN_IF_ERROR(retval
);
311 /* If the list item matches the given item, return the index */
312 if (obj_compare(pobj
, pitem
) == C_SAME
)
319 return PM_RET_EX_VAL
;
324 list_delItem(pPmObj_t plist
, int16_t index
)
326 PmReturn_t retval
= PM_RET_OK
;
328 /* If it's not a list, raise TypeError */
329 if (OBJ_GET_TYPE(plist
) != OBJ_TYPE_LST
)
331 PM_RAISE(retval
, PM_RET_EX_TYPE
);
335 /* Adjust the index */
338 index
+= ((pPmList_t
)plist
)->length
;
341 /* Check the bounds of the index */
342 if ((index
< 0) || (index
>= ((pPmList_t
)plist
)->length
))
344 PM_RAISE(retval
, PM_RET_EX_INDX
);
348 /* Remove the item and decrement the list length */
349 retval
= seglist_removeItem(((pPmList_t
)plist
)->val
, index
);
350 ((pPmList_t
)plist
)->length
--;
352 /* Unlink seglist if there are no contents */
353 if (((pPmList_t
)plist
)->length
== 0)
355 ((pPmList_t
)plist
)->val
= C_NULL
;
364 list_print(pPmObj_t plist
)
366 PmReturn_t retval
= PM_RET_OK
;
371 C_ASSERT(plist
!= C_NULL
);
373 /* If it's not a list, raise TypeError */
374 if (OBJ_GET_TYPE(plist
) != OBJ_TYPE_LST
)
376 PM_RAISE(retval
, PM_RET_EX_TYPE
);
382 vals
= ((pPmList_t
)plist
)->val
;
384 /* Iterate over the list's contents */
385 for (index
= 0; index
< ((pPmList_t
)plist
)->length
; index
++)
393 /* Print each item */
394 retval
= seglist_getItem(vals
, index
, &pobj1
);
395 PM_RETURN_IF_ERROR(retval
);
396 retval
= obj_print(pobj1
, C_FALSE
, C_TRUE
);
397 PM_RETURN_IF_ERROR(retval
);
400 return plat_putByte(']');
402 #endif /* HAVE_PRINT */
406 list_clear(pPmObj_t plist
)
408 PmReturn_t retval
= PM_RET_OK
;
410 C_ASSERT(plist
!= C_NULL
);
412 /* Raise TypeError if arg is not a dict */
413 if (OBJ_GET_TYPE(plist
) != OBJ_TYPE_LST
)
415 PM_RAISE(retval
, PM_RET_EX_TYPE
);
419 /* Clear length and unlink seglist */
420 ((pPmList_t
)plist
)->length
= 0;
421 ((pPmList_t
)plist
)->val
= C_NULL
;