python-on-a-chip online compiler

Dependencies:   mbed TSI

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers seq.c Source File

seq.c

Go to the documentation of this file.
00001 /*
00002 # This file is Copyright 2006 Dean Hall.
00003 # This file is part of the PyMite VM.
00004 # This file is licensed under the MIT License.
00005 # See the LICENSE file for details.
00006 */
00007 
00008 
00009 #undef __FILE_ID__
00010 #define __FILE_ID__ 0x14
00011 
00012 
00013 /**
00014  * \file
00015  * \brief Sequence
00016  *
00017  * Functions that operate on sequences
00018  */
00019 
00020 
00021 #include "pm.h"
00022 
00023 
00024 /*
00025  * Compares two sequence objects
00026  * Assumes both objects are of same type (guaranteed by obj_compare)
00027  */
00028 int8_t
00029 seq_compare(pPmObj_t pobj1, pPmObj_t pobj2)
00030 {
00031     int16_t l1;
00032     int16_t l2;
00033     pPmObj_t pa;
00034     pPmObj_t pb;
00035     PmReturn_t retval;
00036     int8_t retcompare;
00037 
00038     /* Get the lengths of supported types or return differ */
00039     if (OBJ_GET_TYPE(pobj1) == OBJ_TYPE_TUP)
00040     {
00041         l1 = ((pPmTuple_t)pobj1)->length;
00042         l2 = ((pPmTuple_t)pobj2)->length;
00043     }
00044     else if (OBJ_GET_TYPE(pobj1) == OBJ_TYPE_LST)
00045     {
00046         l1 = ((pPmList_t)pobj1)->length;
00047         l2 = ((pPmList_t)pobj2)->length;
00048     }
00049 
00050 #ifdef HAVE_BYTEARRAY
00051     else if (OBJ_GET_TYPE(pobj1) == OBJ_TYPE_BYA)
00052     {
00053         /* Return if the lengths differ */
00054         l1 = ((pPmBytearray_t)pobj1)->length;
00055         l2 = ((pPmBytearray_t)pobj2)->length;
00056         if (l1 != l2)
00057         {
00058             return C_DIFFER;
00059         }
00060 
00061         return sli_strncmp((char const *)&(((pPmBytes_t)((pPmBytearray_t)pobj1)->val)->val),
00062                            (char const *)&(((pPmBytes_t)((pPmBytearray_t)pobj2)->val)->val),
00063                            l1)
00064                ? C_DIFFER : C_SAME;
00065     }
00066 #endif /* HAVE_BYTEARRAY */
00067 
00068     else
00069     {
00070         return C_DIFFER;
00071     }
00072 
00073     /* Return if the lengths differ */
00074     if (l1 != l2)
00075     {
00076         return C_DIFFER;
00077     }
00078 
00079     /* Compare all items in the sequences */
00080     while (--l1 >= 0)
00081     {
00082         retval = seq_getSubscript(pobj1, l1, &pa);
00083         if (retval != PM_RET_OK)
00084         {
00085             return C_DIFFER;
00086         }
00087         retval = seq_getSubscript(pobj2, l1, &pb);
00088         if (retval != PM_RET_OK)
00089         {
00090             return C_DIFFER;
00091         }
00092         retcompare = obj_compare(pa, pb);
00093         if (retcompare != C_SAME)
00094         {
00095             return retcompare;
00096         }
00097     }
00098 
00099     return C_SAME;
00100 }
00101 
00102 
00103 /* Returns the length of the sequence */
00104 PmReturn_t
00105 seq_getLength(pPmObj_t pobj, uint16_t *r_index)
00106 {
00107     PmReturn_t retval = PM_RET_OK;
00108 
00109     switch (OBJ_GET_TYPE(pobj))
00110     {
00111         case OBJ_TYPE_STR:
00112             *r_index = ((pPmString_t)pobj)->length;
00113             break;
00114 
00115         case OBJ_TYPE_TUP:
00116             *r_index = ((pPmTuple_t)pobj)->length;
00117             break;
00118 
00119         case OBJ_TYPE_LST:
00120             *r_index = ((pPmList_t)pobj)->length;
00121             break;
00122 
00123 #ifdef HAVE_BYTEARRAY
00124         case OBJ_TYPE_BYA:
00125             *r_index = ((pPmBytearray_t)pobj)->length;
00126             break;
00127 #endif /* HAVE_BYTEARRAY */
00128 
00129         case OBJ_TYPE_DIC:
00130             *r_index = ((pPmDict_t)pobj)->length;
00131             break;
00132 
00133         default:
00134             /* Raise TypeError, non-sequence object */
00135             PM_RAISE(retval, PM_RET_EX_TYPE);
00136             break;
00137     }
00138 
00139     return retval;
00140 }
00141 
00142 
00143 /* Returns the object sequence[index] */
00144 PmReturn_t
00145 seq_getSubscript(pPmObj_t pobj, int16_t index, pPmObj_t *r_pobj)
00146 {
00147     PmReturn_t retval;
00148     pSeglist_t pkeys;
00149     uint8_t c;
00150 
00151     switch (OBJ_GET_TYPE(pobj))
00152     {
00153         case OBJ_TYPE_STR:
00154             /* Adjust for negative index */
00155             if (index < 0)
00156             {
00157                 index += ((pPmString_t)pobj)->length;
00158             }
00159 
00160             /* Raise IndexError if index is out of bounds */
00161             if ((index < 0) || (index > ((pPmString_t)pobj)->length))
00162             {
00163                 PM_RAISE(retval, PM_RET_EX_INDX);
00164                 break;
00165             }
00166 
00167             /* Get the character from the string */
00168             c = ((pPmString_t)pobj)->val[index];
00169 
00170             /* Create a new string from the character */
00171             retval = string_newFromChar(c, r_pobj);
00172             break;
00173 
00174         case OBJ_TYPE_TUP:
00175             /* Get the tuple item */
00176             retval = tuple_getItem(pobj, index, r_pobj);
00177             break;
00178 
00179         case OBJ_TYPE_LST:
00180             /* Get the list item */
00181             retval = list_getItem(pobj, index, r_pobj);
00182             break;
00183 
00184 #ifdef HAVE_BYTEARRAY
00185         case OBJ_TYPE_BYA:
00186             retval = bytearray_getItem(pobj, index, r_pobj);
00187             break;
00188 #endif /* HAVE_BYTEARRAY */
00189 
00190         /* Issue #176 Add support to iterate over keys in a dict */
00191         case OBJ_TYPE_DIC:
00192             pkeys = ((pPmDict_t)pobj)->d_keys;
00193             retval = seglist_getItem(pkeys, index, r_pobj);
00194             break;
00195 
00196         default:
00197             /* Raise TypeError, unsubscriptable object */
00198             PM_RAISE(retval, PM_RET_EX_TYPE);
00199             break;
00200     }
00201 
00202     return retval;
00203 }
00204 
00205 
00206 PmReturn_t
00207 seqiter_getNext(pPmObj_t pobj, pPmObj_t *r_pitem)
00208 {
00209     PmReturn_t retval;
00210     uint16_t length;
00211 
00212     C_ASSERT(pobj != C_NULL);
00213     C_ASSERT(*r_pitem != C_NULL);
00214     C_ASSERT(OBJ_GET_TYPE(pobj) == OBJ_TYPE_SQI);
00215 
00216     /*
00217      * Raise TypeError if sequence iterator's object is not a sequence
00218      * otherwise, the get sequence's length
00219      */
00220     retval = seq_getLength(((pPmSeqIter_t)pobj)->si_sequence, &length);
00221     PM_RETURN_IF_ERROR(retval);
00222 
00223     /* Raise StopIteration if at the end of the sequence */
00224     if (((pPmSeqIter_t)pobj)->si_index == length)
00225     {
00226         /* Make null the pointer to the sequence */
00227         ((pPmSeqIter_t)pobj)->si_sequence = C_NULL;
00228         PM_RAISE(retval, PM_RET_EX_STOP);
00229         return retval;
00230     }
00231 
00232     /* Get the item at the current index */
00233     retval = seq_getSubscript(((pPmSeqIter_t)pobj)->si_sequence,
00234                               ((pPmSeqIter_t)pobj)->si_index, r_pitem);
00235 
00236     /* Increment the index */
00237     ((pPmSeqIter_t)pobj)->si_index++;
00238 
00239     return retval;
00240 }
00241 
00242 
00243 PmReturn_t
00244 seqiter_new(pPmObj_t pobj, pPmObj_t *r_pobj)
00245 {
00246     PmReturn_t retval;
00247     uint8_t *pchunk;
00248     pPmSeqIter_t psi;
00249 
00250     C_ASSERT(pobj != C_NULL);
00251     C_ASSERT(*r_pobj != C_NULL);
00252 
00253     /* Raise a TypeError if pobj is not a sequence */
00254     if ((OBJ_GET_TYPE(pobj) != OBJ_TYPE_STR)
00255         && (OBJ_GET_TYPE(pobj) != OBJ_TYPE_TUP)
00256         && (OBJ_GET_TYPE(pobj) != OBJ_TYPE_LST)
00257         && (OBJ_GET_TYPE(pobj) != OBJ_TYPE_DIC))
00258     {
00259         PM_RAISE(retval, PM_RET_EX_TYPE);
00260         return retval;
00261     }
00262 
00263     /* Alloc a chunk for the sequence iterator obj */
00264     retval = heap_getChunk(sizeof(PmSeqIter_t), &pchunk);
00265     PM_RETURN_IF_ERROR(retval);
00266 
00267     /* Set the sequence iterator's fields */
00268     psi = (pPmSeqIter_t)pchunk;
00269     OBJ_SET_TYPE(psi, OBJ_TYPE_SQI);
00270     psi->si_sequence = pobj;
00271     psi->si_index = 0;
00272 
00273     *r_pobj = (pPmObj_t)psi;
00274     return retval;
00275 }