python-on-a-chip online compiler

Dependencies:   mbed TSI

/media/uploads/va009039/p14p-f446re.png

more info: python-on-a-chip

Revision:
0:65f1469d6bfb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm/seq.c	Sat Mar 02 11:54:20 2013 +0000
@@ -0,0 +1,275 @@
+/*
+# This file is Copyright 2006 Dean Hall.
+# This file is part of the PyMite VM.
+# This file is licensed under the MIT License.
+# See the LICENSE file for details.
+*/
+
+
+#undef __FILE_ID__
+#define __FILE_ID__ 0x14
+
+
+/**
+ * \file
+ * \brief Sequence
+ *
+ * Functions that operate on sequences
+ */
+
+
+#include "pm.h"
+
+
+/*
+ * Compares two sequence objects
+ * Assumes both objects are of same type (guaranteed by obj_compare)
+ */
+int8_t
+seq_compare(pPmObj_t pobj1, pPmObj_t pobj2)
+{
+    int16_t l1;
+    int16_t l2;
+    pPmObj_t pa;
+    pPmObj_t pb;
+    PmReturn_t retval;
+    int8_t retcompare;
+
+    /* Get the lengths of supported types or return differ */
+    if (OBJ_GET_TYPE(pobj1) == OBJ_TYPE_TUP)
+    {
+        l1 = ((pPmTuple_t)pobj1)->length;
+        l2 = ((pPmTuple_t)pobj2)->length;
+    }
+    else if (OBJ_GET_TYPE(pobj1) == OBJ_TYPE_LST)
+    {
+        l1 = ((pPmList_t)pobj1)->length;
+        l2 = ((pPmList_t)pobj2)->length;
+    }
+
+#ifdef HAVE_BYTEARRAY
+    else if (OBJ_GET_TYPE(pobj1) == OBJ_TYPE_BYA)
+    {
+        /* Return if the lengths differ */
+        l1 = ((pPmBytearray_t)pobj1)->length;
+        l2 = ((pPmBytearray_t)pobj2)->length;
+        if (l1 != l2)
+        {
+            return C_DIFFER;
+        }
+
+        return sli_strncmp((char const *)&(((pPmBytes_t)((pPmBytearray_t)pobj1)->val)->val),
+                           (char const *)&(((pPmBytes_t)((pPmBytearray_t)pobj2)->val)->val),
+                           l1)
+               ? C_DIFFER : C_SAME;
+    }
+#endif /* HAVE_BYTEARRAY */
+
+    else
+    {
+        return C_DIFFER;
+    }
+
+    /* Return if the lengths differ */
+    if (l1 != l2)
+    {
+        return C_DIFFER;
+    }
+
+    /* Compare all items in the sequences */
+    while (--l1 >= 0)
+    {
+        retval = seq_getSubscript(pobj1, l1, &pa);
+        if (retval != PM_RET_OK)
+        {
+            return C_DIFFER;
+        }
+        retval = seq_getSubscript(pobj2, l1, &pb);
+        if (retval != PM_RET_OK)
+        {
+            return C_DIFFER;
+        }
+        retcompare = obj_compare(pa, pb);
+        if (retcompare != C_SAME)
+        {
+            return retcompare;
+        }
+    }
+
+    return C_SAME;
+}
+
+
+/* Returns the length of the sequence */
+PmReturn_t
+seq_getLength(pPmObj_t pobj, uint16_t *r_index)
+{
+    PmReturn_t retval = PM_RET_OK;
+
+    switch (OBJ_GET_TYPE(pobj))
+    {
+        case OBJ_TYPE_STR:
+            *r_index = ((pPmString_t)pobj)->length;
+            break;
+
+        case OBJ_TYPE_TUP:
+            *r_index = ((pPmTuple_t)pobj)->length;
+            break;
+
+        case OBJ_TYPE_LST:
+            *r_index = ((pPmList_t)pobj)->length;
+            break;
+
+#ifdef HAVE_BYTEARRAY
+        case OBJ_TYPE_BYA:
+            *r_index = ((pPmBytearray_t)pobj)->length;
+            break;
+#endif /* HAVE_BYTEARRAY */
+
+        case OBJ_TYPE_DIC:
+            *r_index = ((pPmDict_t)pobj)->length;
+            break;
+
+        default:
+            /* Raise TypeError, non-sequence object */
+            PM_RAISE(retval, PM_RET_EX_TYPE);
+            break;
+    }
+
+    return retval;
+}
+
+
+/* Returns the object sequence[index] */
+PmReturn_t
+seq_getSubscript(pPmObj_t pobj, int16_t index, pPmObj_t *r_pobj)
+{
+    PmReturn_t retval;
+    pSeglist_t pkeys;
+    uint8_t c;
+
+    switch (OBJ_GET_TYPE(pobj))
+    {
+        case OBJ_TYPE_STR:
+            /* Adjust for negative index */
+            if (index < 0)
+            {
+                index += ((pPmString_t)pobj)->length;
+            }
+
+            /* Raise IndexError if index is out of bounds */
+            if ((index < 0) || (index > ((pPmString_t)pobj)->length))
+            {
+                PM_RAISE(retval, PM_RET_EX_INDX);
+                break;
+            }
+
+            /* Get the character from the string */
+            c = ((pPmString_t)pobj)->val[index];
+
+            /* Create a new string from the character */
+            retval = string_newFromChar(c, r_pobj);
+            break;
+
+        case OBJ_TYPE_TUP:
+            /* Get the tuple item */
+            retval = tuple_getItem(pobj, index, r_pobj);
+            break;
+
+        case OBJ_TYPE_LST:
+            /* Get the list item */
+            retval = list_getItem(pobj, index, r_pobj);
+            break;
+
+#ifdef HAVE_BYTEARRAY
+        case OBJ_TYPE_BYA:
+            retval = bytearray_getItem(pobj, index, r_pobj);
+            break;
+#endif /* HAVE_BYTEARRAY */
+
+        /* Issue #176 Add support to iterate over keys in a dict */
+        case OBJ_TYPE_DIC:
+            pkeys = ((pPmDict_t)pobj)->d_keys;
+            retval = seglist_getItem(pkeys, index, r_pobj);
+            break;
+
+        default:
+            /* Raise TypeError, unsubscriptable object */
+            PM_RAISE(retval, PM_RET_EX_TYPE);
+            break;
+    }
+
+    return retval;
+}
+
+
+PmReturn_t
+seqiter_getNext(pPmObj_t pobj, pPmObj_t *r_pitem)
+{
+    PmReturn_t retval;
+    uint16_t length;
+
+    C_ASSERT(pobj != C_NULL);
+    C_ASSERT(*r_pitem != C_NULL);
+    C_ASSERT(OBJ_GET_TYPE(pobj) == OBJ_TYPE_SQI);
+
+    /*
+     * Raise TypeError if sequence iterator's object is not a sequence
+     * otherwise, the get sequence's length
+     */
+    retval = seq_getLength(((pPmSeqIter_t)pobj)->si_sequence, &length);
+    PM_RETURN_IF_ERROR(retval);
+
+    /* Raise StopIteration if at the end of the sequence */
+    if (((pPmSeqIter_t)pobj)->si_index == length)
+    {
+        /* Make null the pointer to the sequence */
+        ((pPmSeqIter_t)pobj)->si_sequence = C_NULL;
+        PM_RAISE(retval, PM_RET_EX_STOP);
+        return retval;
+    }
+
+    /* Get the item at the current index */
+    retval = seq_getSubscript(((pPmSeqIter_t)pobj)->si_sequence,
+                              ((pPmSeqIter_t)pobj)->si_index, r_pitem);
+
+    /* Increment the index */
+    ((pPmSeqIter_t)pobj)->si_index++;
+
+    return retval;
+}
+
+
+PmReturn_t
+seqiter_new(pPmObj_t pobj, pPmObj_t *r_pobj)
+{
+    PmReturn_t retval;
+    uint8_t *pchunk;
+    pPmSeqIter_t psi;
+
+    C_ASSERT(pobj != C_NULL);
+    C_ASSERT(*r_pobj != C_NULL);
+
+    /* Raise a TypeError if pobj is not a sequence */
+    if ((OBJ_GET_TYPE(pobj) != OBJ_TYPE_STR)
+        && (OBJ_GET_TYPE(pobj) != OBJ_TYPE_TUP)
+        && (OBJ_GET_TYPE(pobj) != OBJ_TYPE_LST)
+        && (OBJ_GET_TYPE(pobj) != OBJ_TYPE_DIC))
+    {
+        PM_RAISE(retval, PM_RET_EX_TYPE);
+        return retval;
+    }
+
+    /* Alloc a chunk for the sequence iterator obj */
+    retval = heap_getChunk(sizeof(PmSeqIter_t), &pchunk);
+    PM_RETURN_IF_ERROR(retval);
+
+    /* Set the sequence iterator's fields */
+    psi = (pPmSeqIter_t)pchunk;
+    OBJ_SET_TYPE(psi, OBJ_TYPE_SQI);
+    psi->si_sequence = pobj;
+    psi->si_index = 0;
+
+    *r_pobj = (pPmObj_t)psi;
+    return retval;
+}