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__ 0x02
22 * \brief Dict Object Type
24 * Dict object type operations.
32 dict_new(pPmObj_t
*r_pdict
)
34 PmReturn_t retval
= PM_RET_OK
;
35 pPmDict_t pdict
= C_NULL
;
39 retval
= heap_getChunk(sizeof(PmDict_t
), &pchunk
);
40 PM_RETURN_IF_ERROR(retval
);
42 /* Init dict fields */
43 pdict
= (pPmDict_t
)pchunk
;
44 OBJ_SET_TYPE(pdict
, OBJ_TYPE_DIC
);
46 pdict
->d_keys
= C_NULL
;
47 pdict
->d_vals
= C_NULL
;
49 *r_pdict
= (pPmObj_t
)pchunk
;
55 dict_clear(pPmObj_t pdict
)
57 PmReturn_t retval
= PM_RET_OK
;
59 C_ASSERT(pdict
!= C_NULL
);
61 /* Raise TypeError if arg is not a dict */
62 if (OBJ_GET_TYPE(pdict
) != OBJ_TYPE_DIC
)
64 PM_RAISE(retval
, PM_RET_EX_TYPE
);
69 ((pPmDict_t
)pdict
)->length
= 0;
71 /* Free the keys and values seglists if needed */
72 if (((pPmDict_t
)pdict
)->d_keys
!= C_NULL
)
74 PM_RETURN_IF_ERROR(seglist_clear(((pPmDict_t
)pdict
)->d_keys
));
75 PM_RETURN_IF_ERROR(heap_freeChunk((pPmObj_t
)
76 ((pPmDict_t
)pdict
)->d_keys
));
77 ((pPmDict_t
)pdict
)->d_keys
= C_NULL
;
79 if (((pPmDict_t
)pdict
)->d_vals
!= C_NULL
)
81 PM_RETURN_IF_ERROR(seglist_clear(((pPmDict_t
)pdict
)->d_vals
));
82 retval
= heap_freeChunk((pPmObj_t
)((pPmDict_t
)pdict
)->d_vals
);
83 ((pPmDict_t
)pdict
)->d_vals
= C_NULL
;
90 * Sets a value in the dict using the given key.
92 * Scans dict for the key. If key val found, replace old
93 * with new val. If no key found, add key/val pair to dict.
96 dict_setItem(pPmObj_t pdict
, pPmObj_t pkey
, pPmObj_t pval
)
98 PmReturn_t retval
= PM_RET_OK
;
101 C_ASSERT(pdict
!= C_NULL
);
102 C_ASSERT(pkey
!= C_NULL
);
103 C_ASSERT(pval
!= C_NULL
);
105 /* If it's not a dict, raise TypeError */
106 if (OBJ_GET_TYPE(pdict
) != OBJ_TYPE_DIC
)
108 PM_RAISE(retval
, PM_RET_EX_TYPE
);
112 /* #112: Force Dict keys to be of hashable type */
113 /* If key is not hashable, raise TypeError */
114 if (OBJ_GET_TYPE(pkey
) > OBJ_TYPE_HASHABLE_MAX
)
116 PM_RAISE(retval
, PM_RET_EX_TYPE
);
120 /* #147: Change boolean keys to integers */
125 else if (pkey
== PM_FALSE
)
131 * #115: If this is the first key/value pair to be added to the Dict,
132 * allocate the key and value seglists that hold those items
134 if (((pPmDict_t
)pdict
)->length
== 0)
136 retval
= seglist_new(&((pPmDict_t
)pdict
)->d_keys
);
137 PM_RETURN_IF_ERROR(retval
);
138 retval
= seglist_new(&((pPmDict_t
)pdict
)->d_vals
);
139 PM_RETURN_IF_ERROR(retval
);
143 /* Check for matching key */
145 retval
= seglist_findEqual(((pPmDict_t
)pdict
)->d_keys
, pkey
, &indx
);
147 /* If found a matching key, replace val obj */
148 if (retval
== PM_RET_OK
)
150 retval
= seglist_setItem(((pPmDict_t
)pdict
)->d_vals
, pval
, indx
);
155 /* Otherwise, insert the key,val pair */
156 retval
= seglist_insertItem(((pPmDict_t
)pdict
)->d_keys
, pkey
, 0);
157 PM_RETURN_IF_ERROR(retval
);
158 retval
= seglist_insertItem(((pPmDict_t
)pdict
)->d_vals
, pval
, 0);
159 ((pPmDict_t
)pdict
)->length
++;
166 dict_getItem(pPmObj_t pdict
, pPmObj_t pkey
, pPmObj_t
*r_pobj
)
168 PmReturn_t retval
= PM_RET_OK
;
171 /* C_ASSERT(pdict != C_NULL);*/
173 /* if it's not a dict, raise TypeError */
174 if (OBJ_GET_TYPE(pdict
) != OBJ_TYPE_DIC
)
176 PM_RAISE(retval
, PM_RET_EX_TYPE
);
180 /* if dict is empty, raise KeyError */
181 if (((pPmDict_t
)pdict
)->length
<= 0)
183 PM_RAISE(retval
, PM_RET_EX_KEY
);
187 /* #147: Change boolean keys to integers */
192 else if (pkey
== PM_FALSE
)
197 /* check for matching key */
198 retval
= seglist_findEqual(((pPmDict_t
)pdict
)->d_keys
, pkey
, &indx
);
199 /* if key not found, raise KeyError */
200 if (retval
== PM_RET_NO
)
202 PM_RAISE(retval
, PM_RET_EX_KEY
);
204 /* return any other error */
205 PM_RETURN_IF_ERROR(retval
);
207 /* key was found, get obj from vals */
208 retval
= seglist_getItem(((pPmDict_t
)pdict
)->d_vals
, indx
, r_pobj
);
215 dict_delItem(pPmObj_t pdict
, pPmObj_t pkey
)
217 PmReturn_t retval
= PM_RET_OK
;
220 C_ASSERT(pdict
!= C_NULL
);
222 /* Check for matching key */
223 retval
= seglist_findEqual(((pPmDict_t
)pdict
)->d_keys
, pkey
, &indx
);
225 /* Raise KeyError if key is not found */
226 if (retval
== PM_RET_NO
)
228 PM_RAISE(retval
, PM_RET_EX_KEY
);
231 /* Return any other error */
232 PM_RETURN_IF_ERROR(retval
);
234 /* Remove the key and value */
235 retval
= seglist_removeItem(((pPmDict_t
)pdict
)->d_keys
, indx
);
236 PM_RETURN_IF_ERROR(retval
);
237 retval
= seglist_removeItem(((pPmDict_t
)pdict
)->d_vals
, indx
);
239 /* Reduce the item count */
240 ((pPmDict_t
)pdict
)->length
--;
244 #endif /* HAVE_DEL */
249 dict_print(pPmObj_t pdict
)
251 PmReturn_t retval
= PM_RET_OK
;
257 C_ASSERT(pdict
!= C_NULL
);
259 /* if it's not a dict, raise TypeError */
260 if (OBJ_GET_TYPE(pdict
) != OBJ_TYPE_DIC
)
262 PM_RAISE(retval
, PM_RET_EX_TYPE
);
268 keys
= ((pPmDict_t
)pdict
)->d_keys
;
269 vals
= ((pPmDict_t
)pdict
)->d_vals
;
271 /* if dict is empty, raise KeyError */
272 for (index
= 0; index
< ((pPmDict_t
)pdict
)->length
; index
++)
279 retval
= seglist_getItem(keys
, index
, &pobj1
);
280 PM_RETURN_IF_ERROR(retval
);
281 retval
= obj_print(pobj1
, C_FALSE
, C_TRUE
);
282 PM_RETURN_IF_ERROR(retval
);
285 retval
= seglist_getItem(vals
, index
, &pobj1
);
286 PM_RETURN_IF_ERROR(retval
);
287 retval
= obj_print(pobj1
, C_FALSE
, C_TRUE
);
288 PM_RETURN_IF_ERROR(retval
);
291 return plat_putByte('}');
293 #endif /* HAVE_PRINT */
296 dict_update(pPmObj_t pdestdict
, pPmObj_t psourcedict
)
298 PmReturn_t retval
= PM_RET_OK
;
303 C_ASSERT(pdestdict
!= C_NULL
);
304 C_ASSERT(psourcedict
!= C_NULL
);
306 /* If it's not a dict, raise TypeError */
307 if (OBJ_GET_TYPE(pdestdict
) != OBJ_TYPE_DIC
)
309 PM_RAISE(retval
, PM_RET_EX_TYPE
);
313 /* If it's not a dict, raise TypeError */
314 if (OBJ_GET_TYPE(psourcedict
) != OBJ_TYPE_DIC
)
316 PM_RAISE(retval
, PM_RET_EX_TYPE
);
320 /* Iterate over the add-on dict */
321 for (i
= 0; i
< ((pPmDict_t
)psourcedict
)->length
; i
++)
323 /* Get the key,val from the add-on dict */
324 retval
= seglist_getItem(((pPmDict_t
)psourcedict
)->d_keys
, i
, &pkey
);
325 PM_RETURN_IF_ERROR(retval
);
326 retval
= seglist_getItem(((pPmDict_t
)psourcedict
)->d_vals
, i
, &pval
);
327 PM_RETURN_IF_ERROR(retval
);
329 /* Set the key,val to the destination dict */
330 retval
= dict_setItem(pdestdict
, pkey
, pval
);
331 PM_RETURN_IF_ERROR(retval
);