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/obj.c	Sat Mar 02 11:54:20 2013 +0000
@@ -0,0 +1,471 @@
+/*
+# This file is Copyright 2002 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__ 0x0F
+
+
+/**
+ * \file
+ * \brief Object Type
+ *
+ * Object type operations.
+ */
+
+
+#include "pm.h"
+
+
+PmReturn_t
+obj_loadFromImg(PmMemSpace_t memspace,
+                uint8_t const **paddr, pPmObj_t *r_pobj)
+{
+    PmReturn_t retval = PM_RET_OK;
+    PmObj_t obj;
+
+
+    /* Get the object descriptor */
+    obj.od = (PmObjDesc_t)0x0000;
+    OBJ_SET_TYPE(&obj, mem_getByte(memspace, paddr));
+
+    switch (OBJ_GET_TYPE(&obj))
+    {
+        case OBJ_TYPE_NON:
+            /* If it's the None object, return global None */
+            *r_pobj = PM_NONE;
+            break;
+
+        case OBJ_TYPE_INT:
+            /* Read an integer and create an integer object with the value */
+            retval = int_new(mem_getInt(memspace, paddr), r_pobj);
+            break;
+
+#ifdef HAVE_FLOAT
+        case OBJ_TYPE_FLT:
+            /* Read a float and create an float object with the value */
+            retval = float_new(mem_getFloat(memspace, paddr), r_pobj);
+            break;
+#endif /* HAVE_FLOAT */
+
+        case OBJ_TYPE_STR:
+            retval = string_loadFromImg(memspace, paddr, r_pobj);
+            break;
+
+        case OBJ_TYPE_TUP:
+            retval = tuple_loadFromImg(memspace, paddr, r_pobj);
+            break;
+
+        case OBJ_TYPE_NIM:
+            /* If it's a native code img, load into a code obj */
+            retval = no_loadFromImg(memspace, paddr, r_pobj);
+            break;
+
+        case OBJ_TYPE_CIM:
+            /* If it's a code img, load into a code obj */
+            retval = co_loadFromImg(memspace, paddr, r_pobj);
+            break;
+
+        default:
+            /* All other types should not be in an img obj */
+            PM_RAISE(retval, PM_RET_EX_SYS);
+            break;
+    }
+    return retval;
+}
+
+
+PmReturn_t
+obj_loadFromImgObj(pPmObj_t pimg, pPmObj_t *r_pobj)
+{
+    uint8_t const *imgaddr;
+    PmReturn_t retval;
+
+    C_ASSERT(OBJ_GET_TYPE(pimg) == OBJ_TYPE_CIO);
+    imgaddr = (uint8_t const *)&(((pPmCodeImgObj_t)pimg)->val);
+
+    retval = obj_loadFromImg(MEMSPACE_RAM, &imgaddr, r_pobj);
+    C_ASSERT(OBJ_GET_TYPE(*r_pobj) == OBJ_TYPE_COB);
+
+    /* All COs must reference the top of the code img obj
+     * so the image is marked and prevented from being reclaimed */
+    co_rSetCodeImgAddr((pPmCo_t)*r_pobj, (uint8_t const *)pimg);
+
+    return retval;
+}
+
+
+/* Returns true if the obj is false */
+int8_t
+obj_isFalse(pPmObj_t pobj)
+{
+    C_ASSERT(pobj != C_NULL);
+
+    switch (OBJ_GET_TYPE(pobj))
+    {
+        case OBJ_TYPE_NON:
+            /* None evaluates to false, so return true */
+            return C_TRUE;
+
+        case OBJ_TYPE_INT:
+            /* Only the integer zero is false */
+            return ((pPmInt_t)pobj)->val == 0;
+
+#ifdef HAVE_FLOAT
+        case OBJ_TYPE_FLT:
+            /* The floats 0.0 and -0.0 are false */
+            return (((pPmFloat_t) pobj)->val == 0.0)
+                || (((pPmFloat_t) pobj)->val == -0.0);
+#endif /* HAVE_FLOAT */
+
+        case OBJ_TYPE_STR:
+            /* An empty string is false */
+            return ((pPmString_t)pobj)->length == 0;
+
+        case OBJ_TYPE_TUP:
+            /* An empty tuple is false */
+            return ((pPmTuple_t)pobj)->length == 0;
+
+        case OBJ_TYPE_LST:
+            /* An empty list is false */
+            return ((pPmList_t)pobj)->length == 0;
+
+        case OBJ_TYPE_DIC:
+            /* An empty dict is false */
+            return ((pPmDict_t)pobj)->length == 0;
+
+        case OBJ_TYPE_BOOL:
+            /* C int zero means false */
+            return ((pPmBoolean_t) pobj)->val == 0;
+
+        default:
+            /*
+             * The following types are always not false:
+             * CodeObj, Function, Module, Class, ClassInstance.
+             */
+            return C_FALSE;
+    }
+}
+
+
+/* Returns true if the item is in the container object */
+PmReturn_t
+obj_isIn(pPmObj_t pobj, pPmObj_t pitem)
+{
+    PmReturn_t retval = PM_RET_NO;
+    pPmObj_t ptestItem;
+    int16_t i;
+    uint8_t c;
+
+    switch (OBJ_GET_TYPE(pobj))
+    {
+        case OBJ_TYPE_TUP:
+            /* Iterate over tuple to find item */
+            for (i = 0; i < ((pPmTuple_t)pobj)->length; i++)
+            {
+                PM_RETURN_IF_ERROR(tuple_getItem(pobj, i, &ptestItem));
+
+                if (obj_compare(pitem, ptestItem) == C_SAME)
+                {
+                    retval = PM_RET_OK;
+                    break;
+                }
+            }
+            break;
+
+        case OBJ_TYPE_STR:
+            /* Raise a TypeError if item is not a string */
+            if ((OBJ_GET_TYPE(pitem) != OBJ_TYPE_STR))
+            {
+                retval = PM_RET_EX_TYPE;
+                break;
+            }
+
+            /* Empty string is alway present */
+            if (((pPmString_t)pitem)->length == 0)
+            {
+                retval = PM_RET_OK;
+                break;
+            }
+
+            /* Raise a ValueError if the string is more than 1 char */
+            else if (((pPmString_t)pitem)->length != 1)
+            {
+                retval = PM_RET_EX_VAL;
+                break;
+            }
+
+            /* Iterate over string to find char */
+            c = ((pPmString_t)pitem)->val[0];
+            for (i = 0; i < ((pPmString_t)pobj)->length; i++)
+            {
+                if (c == ((pPmString_t)pobj)->val[i])
+                {
+                    retval = PM_RET_OK;
+                    break;
+                }
+            }
+            break;
+
+        case OBJ_TYPE_LST:
+            /* Iterate over list to find item */
+            for (i = 0; i < ((pPmList_t)pobj)->length; i++)
+            {
+                PM_RETURN_IF_ERROR(list_getItem(pobj, i, &ptestItem));
+
+                if (obj_compare(pitem, ptestItem) == C_SAME)
+                {
+                    retval = PM_RET_OK;
+                    break;
+                }
+            }
+            break;
+
+        case OBJ_TYPE_DIC:
+            /* Check if the item is one of the keys of the dict */
+            retval = dict_getItem(pobj, pitem, &ptestItem);
+            if (retval == PM_RET_EX_KEY)
+            {
+                retval = PM_RET_NO;
+            }
+            break;
+
+        default:
+            retval = PM_RET_EX_TYPE;
+            break;
+    }
+
+    return retval;
+}
+
+
+int8_t
+obj_compare(pPmObj_t pobj1, pPmObj_t pobj2)
+{
+#ifdef HAVE_BYTEARRAY
+    PmReturn_t retval;
+    pPmObj_t pobj;
+#endif /* HAVE_BYTEARRAY */
+
+    C_ASSERT(pobj1 != C_NULL);
+    C_ASSERT(pobj2 != C_NULL);
+
+    /* Check if pointers are same */
+    if (pobj1 == pobj2)
+    {
+        return C_SAME;
+    }
+
+    /* If types are different, objs must differ */
+    if (OBJ_GET_TYPE(pobj1) != OBJ_GET_TYPE(pobj2))
+    {
+        return C_DIFFER;
+    }
+
+#ifdef HAVE_BYTEARRAY
+    /* If object is an instance, get the thing it contains */
+    if (OBJ_GET_TYPE(pobj1) == OBJ_TYPE_CLI)
+    {
+        retval = dict_getItem((pPmObj_t)((pPmInstance_t)pobj1)->cli_attrs,
+                              PM_NONE,
+                              &pobj);
+        PM_RETURN_IF_ERROR(retval);
+        pobj1 = pobj;
+    }
+    if (OBJ_GET_TYPE(pobj2) == OBJ_TYPE_CLI)
+    {
+        retval = dict_getItem((pPmObj_t)((pPmInstance_t)pobj2)->cli_attrs,
+                              PM_NONE,
+                              &pobj);
+        PM_RETURN_IF_ERROR(retval);
+        pobj2 = pobj;
+    }
+
+    /* If types are different, objs must differ */
+    if (OBJ_GET_TYPE(pobj1) != OBJ_GET_TYPE(pobj2))
+    {
+        return C_DIFFER;
+    }
+#endif /* HAVE_BYTEARRAY */
+
+    /* Otherwise handle types individually */
+    switch (OBJ_GET_TYPE(pobj1))
+    {
+        case OBJ_TYPE_NON:
+            return C_SAME;
+
+        case OBJ_TYPE_INT:
+            return ((pPmInt_t)pobj1)->val ==
+                ((pPmInt_t)pobj2)->val ? C_SAME : C_DIFFER;
+
+#ifdef HAVE_FLOAT
+        case OBJ_TYPE_FLT:
+        {
+            pPmObj_t r_pobj;
+
+            float_compare(pobj1, pobj2, &r_pobj, COMP_EQ);
+            return (r_pobj == PM_TRUE) ? C_SAME : C_DIFFER;
+        }
+#endif /* HAVE_FLOAT */
+
+        case OBJ_TYPE_STR:
+            return string_compare((pPmString_t)pobj1, (pPmString_t)pobj2);
+
+        case OBJ_TYPE_TUP:
+        case OBJ_TYPE_LST:
+#ifdef HAVE_BYTEARRAY
+        case OBJ_TYPE_BYA:
+#endif /* HAVE_BYTEARRAY */
+            return seq_compare(pobj1, pobj2);
+
+        case OBJ_TYPE_DIC:
+            return dict_compare(pobj1, pobj2);
+
+        default:
+            break;
+    }
+
+    /* All other types would need same pointer to be true */
+    return C_DIFFER;
+}
+
+
+#ifdef HAVE_PRINT
+PmReturn_t
+obj_print(pPmObj_t pobj, uint8_t is_expr_repr, uint8_t is_nested)
+{
+    PmReturn_t retval = PM_RET_OK;
+
+    C_ASSERT(pobj != C_NULL);
+
+    /* Something gets printed unless it's None in an unnested expression */
+    if (!((OBJ_GET_TYPE(pobj) == OBJ_TYPE_NON) && is_expr_repr && !is_nested))
+    {
+        gVmGlobal.somethingPrinted = C_TRUE;
+    }
+
+    switch (OBJ_GET_TYPE(pobj))
+    {
+        case OBJ_TYPE_NON:
+            if (!is_expr_repr || is_nested)
+            {
+                sli_puts((uint8_t *)"None");
+            }
+            break;
+        case OBJ_TYPE_INT:
+            retval = int_print(pobj);
+            break;
+#ifdef HAVE_FLOAT
+        case OBJ_TYPE_FLT:
+            retval = float_print(pobj);
+            break;
+#endif /* HAVE_FLOAT */
+        case OBJ_TYPE_STR:
+            retval = string_print(pobj, (is_expr_repr || is_nested));
+            break;
+        case OBJ_TYPE_TUP:
+            retval = tuple_print(pobj);
+            break;
+        case OBJ_TYPE_LST:
+            retval = list_print(pobj);
+            break;
+        case OBJ_TYPE_DIC:
+            retval = dict_print(pobj);
+            break;
+        case OBJ_TYPE_BOOL:
+            sli_puts(
+                (((pPmBoolean_t) pobj)->val == C_TRUE)
+                ? (uint8_t *)"True"
+                : (uint8_t *)"False");
+            break;
+
+        case OBJ_TYPE_CLI:
+#ifdef HAVE_BYTEARRAY
+            {
+                pPmObj_t pobj2;
+
+                retval = dict_getItem((pPmObj_t)((pPmInstance_t)pobj)->cli_attrs,
+                                      PM_NONE,
+                                      (pPmObj_t *)&pobj2);
+                if ((retval == PM_RET_OK)
+                    && (OBJ_GET_TYPE(pobj2) == OBJ_TYPE_BYA))
+                {
+                    retval = bytearray_print(pobj2);
+                    break;
+                }
+            }
+#endif /* HAVE_BYTEARRAY */
+
+        case OBJ_TYPE_COB:
+        case OBJ_TYPE_MOD:
+        case OBJ_TYPE_CLO:
+        case OBJ_TYPE_FXN:
+        case OBJ_TYPE_CIM:
+        case OBJ_TYPE_NIM:
+        case OBJ_TYPE_NOB:
+        case OBJ_TYPE_THR:
+        case OBJ_TYPE_CIO:
+        case OBJ_TYPE_MTH:
+        case OBJ_TYPE_SQI:
+        {
+            uint8_t buf[17];
+            sli_puts((uint8_t *)"<obj type 0x");
+            sli_btoa16(OBJ_GET_TYPE(pobj), buf, sizeof(buf), C_TRUE);
+            sli_puts(buf);
+            sli_puts((uint8_t *)" @ 0x");
+            sli_ptoa16((intptr_t)pobj, buf, sizeof(buf), C_TRUE);
+            sli_puts(buf);
+            retval = plat_putByte('>');
+            break;
+        }
+
+        default:
+            /* Otherwise raise a TypeError */
+            PM_RAISE(retval, PM_RET_EX_TYPE);
+            break;
+    }
+    return retval;
+}
+#endif /* HAVE_PRINT */
+
+
+#ifdef HAVE_BACKTICK
+PmReturn_t
+obj_repr(pPmObj_t pobj, pPmObj_t *r_pstr)
+{
+    uint8_t tBuffer[32];
+    PmReturn_t retval = PM_RET_OK;
+    uint8_t const *pcstr = (uint8_t *)tBuffer;;
+
+    C_ASSERT(pobj != C_NULL);
+
+    switch (OBJ_GET_TYPE(pobj))
+    {
+        case OBJ_TYPE_INT:
+            retval = sli_ltoa10(((pPmInt_t)pobj)->val, tBuffer, sizeof(tBuffer));
+            PM_RETURN_IF_ERROR(retval);
+            retval = string_new(&pcstr, r_pstr);
+            break;
+
+#ifdef HAVE_FLOAT
+        case OBJ_TYPE_FLT:
+            /* #212: Use homebrew float formatter */
+            retval = sli_ftoa(((pPmFloat_t)pobj)->val, tBuffer, sizeof(tBuffer));
+            sli_strlen((char *)tBuffer);
+            retval = string_new(&pcstr, r_pstr);
+            break;
+#endif /* HAVE_FLOAT */
+
+        default:
+            /* Otherwise raise a TypeError */
+            PM_RAISE(retval, PM_RET_EX_TYPE);
+            break;
+    }
+
+    return retval;
+}
+#endif /* HAVE_BACKTICK */