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/platform/mbed/pmstdlib_nat.cpp	Sat Mar 02 11:54:20 2013 +0000
@@ -0,0 +1,1647 @@
+#undef __FILE_ID__
+#define __FILE_ID__ 0x0A
+/**
+ * PyMite std native function file
+ *
+ * automatically created by pmImgCreator.py
+ * on Sat Mar 02 20:27:03 2013
+ *
+ * DO NOT EDIT THIS FILE.
+ * ANY CHANGES WILL BE LOST.
+ *
+ * @file    pmstdlib_nat.cpp
+ */
+
+#define __IN_LIBNATIVE_C__
+#include "pm.h"
+
+/* From: ../../lib/string.py */
+#include <stdlib.h>
+#include <string.h>
+
+PmReturn_t
+nat_00___bi_chr(pPmFrame_t *ppframe)
+{
+
+    pPmObj_t ps;
+    pPmObj_t pn;
+    int32_t n;
+    PmReturn_t retval;
+
+    /* If wrong number of args, raise TypeError */
+    if (NATIVE_GET_NUM_ARGS() != 1)
+    {
+        PM_RAISE(retval, PM_RET_EX_TYPE);
+        return retval;
+    }
+
+    /* Raise TypeError if arg is not an int */
+    pn = NATIVE_GET_LOCAL(0);
+    if (OBJ_GET_TYPE(pn) != OBJ_TYPE_INT)
+    {
+        PM_RAISE(retval, PM_RET_EX_TYPE);
+        return retval;
+    }
+
+    /* Raise ValueError if arg is not int within range(256) */
+    n = ((pPmInt_t)pn)->val;
+    if ((n < 0) || (n > 255))
+    {
+        PM_RAISE(retval, PM_RET_EX_VAL);
+        return retval;
+    }
+
+    /* Create char string from  integer value */
+    retval = string_newFromChar((uint8_t)n, &ps);
+    NATIVE_SET_TOS(ps);
+    return retval;
+    
+}
+
+PmReturn_t
+nat_01___bi_dir(pPmFrame_t *ppframe)
+{
+
+    PmReturn_t retval = PM_RET_OK;
+    pPmObj_t po;
+    pPmObj_t pk;
+    pPmObj_t pl;
+    pSeglist_t psl;
+    int16_t i;
+    uint8_t objid;
+
+    /* Use globals if no arg given */
+    if (NATIVE_GET_NUM_ARGS() == 0)
+    {
+        /* Get the globals dict */
+        po = (pPmObj_t)NATIVE_GET_PFRAME()->fo_globals;
+    }
+
+    /* Otherwise use the given arg */
+    else if (NATIVE_GET_NUM_ARGS() == 1)
+    {
+        po = NATIVE_GET_LOCAL(0);
+
+        /* If object is a function or module, use its attrs dict */
+        if ((OBJ_GET_TYPE(po) == OBJ_TYPE_FXN)
+            || (OBJ_GET_TYPE(po) == OBJ_TYPE_MOD))
+        {
+            po = (pPmObj_t)((pPmFunc_t)po)->f_attrs;
+        }
+
+#ifdef HAVE_CLASSES
+        else if (OBJ_GET_TYPE(po) == OBJ_TYPE_CLO)
+        {
+            po = (pPmObj_t)((pPmClass_t)po)->cl_attrs;
+        }
+        else if (OBJ_GET_TYPE(po) == OBJ_TYPE_CLI)
+        {
+            po = (pPmObj_t)((pPmInstance_t)po)->cli_attrs;
+        }
+        else if (OBJ_GET_TYPE(po) == OBJ_TYPE_MTH)
+        {
+            po = (pPmObj_t)((pPmMethod_t)po)->m_attrs;
+        }
+#endif /* HAVE_CLASSES */
+
+        else
+        {
+            po = C_NULL;
+        }
+    }
+
+    /* Raise TypeError if wrong number of args */
+    else
+    {
+        PM_RAISE(retval, PM_RET_EX_TYPE);
+        return retval;
+    }
+
+    if (po == C_NULL)
+    {
+        pl = PM_NONE;
+    }
+    else
+    {
+        /* Create new list */
+        retval = list_new(&pl);
+        PM_RETURN_IF_ERROR(retval);
+
+        /* Copy dict's keys to the list */
+        psl = ((pPmDict_t)po)->d_keys;
+        for (i = 0; i < ((pPmDict_t)po)->length; i++)
+        {
+            retval = seglist_getItem(psl, i, &pk);
+            PM_RETURN_IF_ERROR(retval);
+            heap_gcPushTempRoot(pl, &objid);
+            retval = list_append(pl, pk);
+            heap_gcPopTempRoot(objid);
+            PM_RETURN_IF_ERROR(retval);
+        }
+    }
+
+    NATIVE_SET_TOS(pl);
+    return retval;
+    
+}
+
+PmReturn_t
+nat_02___bi_eval(pPmFrame_t *ppframe)
+{
+
+    PmReturn_t retval;
+    pPmObj_t pco;
+    pPmObj_t pfunc;
+    pPmObj_t pnewframe;
+    pPmObj_t pg = C_NULL;
+    pPmObj_t pl = C_NULL;
+    uint8_t objid;
+
+    /* If wrong number of args, raise TypeError */
+    if ((NATIVE_GET_NUM_ARGS() == 0) || (NATIVE_GET_NUM_ARGS() > 3))
+    {
+        PM_RAISE(retval, PM_RET_EX_TYPE);
+        return retval;
+    }
+
+    /* Raise ValueError if first arg is not a Code Object */
+    pco = NATIVE_GET_LOCAL(0);
+    if (OBJ_GET_TYPE(pco) != OBJ_TYPE_COB)
+    {
+        PM_RAISE(retval, PM_RET_EX_VAL);
+        return retval;
+    }
+
+    /* If 2nd arg exists, raise ValueError if it is not a Dict */
+    if (NATIVE_GET_NUM_ARGS() >= 2)
+    {
+        pg = NATIVE_GET_LOCAL(1);
+        if (OBJ_GET_TYPE(pg) != OBJ_TYPE_DIC)
+        {
+            PM_RAISE(retval, PM_RET_EX_VAL);
+            return retval;
+        }
+    }
+
+    /* If no args are given, use the caller's globals for the function's */
+    else
+    {
+        pg = (pPmObj_t)NATIVE_GET_PFRAME()->fo_globals;
+    }
+
+    /* If 3rd arg exists, raise ValueError if it is not a Dict */
+    if (NATIVE_GET_NUM_ARGS() >= 3)
+    {
+        pl = NATIVE_GET_LOCAL(2);
+        if (OBJ_GET_TYPE(pl) != OBJ_TYPE_DIC)
+        {
+            PM_RAISE(retval, PM_RET_EX_VAL);
+            return retval;
+        }
+    }
+
+    /* Create func from code object */
+    retval = func_new(pco, pg, &pfunc);
+    PM_RETURN_IF_ERROR(retval);
+
+    /* Create frame from module object; globals is set to null */
+    heap_gcPushTempRoot(pfunc, &objid);
+    retval = frame_new(pfunc, &pnewframe);
+    heap_gcPopTempRoot(objid);
+    PM_RETURN_IF_ERROR(retval);
+
+    /* TODO: Reclaim pnewframe's attrs dict created in frame_new */
+    /*
+     * By default use calling frame's attrs as local namespace.
+     * This works for ipm because the interactive mode
+     * needs a locals namespace that persists across calls to eval()
+     */
+    ((pPmFrame_t)pnewframe)->fo_attrs = NATIVE_GET_PFRAME()->fo_attrs;
+
+    /* If 2nd arg exists, use it as the global namespace for the new func */
+    if (NATIVE_GET_NUM_ARGS() >= 2)
+    {
+        ((pPmFrame_t)pnewframe)->fo_globals = (pPmDict_t)pg;
+
+        /* If only globals is given, locals defaults to it */
+        ((pPmFrame_t)pnewframe)->fo_attrs = (pPmDict_t)pg;
+    }
+
+    /* If 3rd arg exists, use it as the local namespace for the new func */
+    if (NATIVE_GET_NUM_ARGS() >= 3)
+    {
+        ((pPmFrame_t)pnewframe)->fo_attrs = (pPmDict_t)pl;
+    }
+
+    /*
+     * Set the fo_back frame so flow returns to eval()'s caller when completed.
+     * Set the frame pointer so the new frame is interpreted immediately
+     * after this function returns.
+     */
+    ((pPmFrame_t)pnewframe)->fo_back = NATIVE_GET_PFRAME();
+    NATIVE_GET_PFRAME() = (pPmFrame_t)pnewframe;
+    retval = PM_RET_FRAME_SWITCH;
+
+    return retval;
+    
+}
+
+PmReturn_t
+nat_03___bi_globals(pPmFrame_t *ppframe)
+{
+
+    pPmObj_t pr = C_NULL;
+    PmReturn_t retval;
+
+    /* If wrong number of args, raise TypeError */
+    if (NATIVE_GET_NUM_ARGS() != 0)
+    {
+        PM_RAISE(retval, PM_RET_EX_TYPE);
+        return retval;
+    }
+
+    /* Return calling frame's globals dict  on stack*/
+    pr = (pPmObj_t)NATIVE_GET_PFRAME()->fo_globals;
+    NATIVE_SET_TOS(pr);
+
+    return PM_RET_OK;
+    
+}
+
+PmReturn_t
+nat_04___bi_id(pPmFrame_t *ppframe)
+{
+
+    PmReturn_t retval;
+    pPmObj_t pr = C_NULL;
+
+    /* If wrong number of args, raise TypeError */
+    if (NATIVE_GET_NUM_ARGS() != 1)
+    {
+        PM_RAISE(retval, PM_RET_EX_TYPE);
+        return retval;
+    }
+
+    /* Return object's address as an int on the stack */
+    retval = int_new((intptr_t)NATIVE_GET_LOCAL(0), &pr);
+    NATIVE_SET_TOS(pr);
+
+    return retval;
+    
+}
+
+PmReturn_t
+nat_05___bi_len(pPmFrame_t *ppframe)
+{
+
+    PmReturn_t retval;
+    pPmObj_t ps = C_NULL;
+    pPmObj_t pr = C_NULL;
+
+    /* If wrong number of args, raise TypeError */
+    if (NATIVE_GET_NUM_ARGS() != 1)
+    {
+        PM_RAISE(retval, PM_RET_EX_TYPE);
+        return retval;
+    }
+
+    /* Get first arg */
+    ps = NATIVE_GET_LOCAL(0);
+
+#ifdef HAVE_BYTEARRAY
+    /* If object is an instance, get the thing it contains */
+    if (OBJ_GET_TYPE(ps) == OBJ_TYPE_CLI)
+    {
+        retval = dict_getItem((pPmObj_t)((pPmInstance_t)ps)->cli_attrs,
+                              PM_NONE,
+                              &pr);
+
+        /* If None wasn't in attributes, obj is wrong type for len() */
+        if (retval == PM_RET_EX_KEY) retval = PM_RET_EX_TYPE;
+        PM_RETURN_IF_ERROR(retval);
+        ps = pr;
+    }
+#endif /* HAVE_BYTEARRAY */
+
+    /* Get the length of the arg based on its type */
+    switch (OBJ_GET_TYPE(ps))
+    {
+        case OBJ_TYPE_STR:
+            retval = int_new(((pPmString_t)ps)->length, &pr);
+            break;
+
+        case OBJ_TYPE_TUP:
+            retval = int_new(((pPmTuple_t)ps)->length, &pr);
+            break;
+
+        case OBJ_TYPE_LST:
+            retval = int_new(((pPmList_t)ps)->length, &pr);
+            break;
+
+        case OBJ_TYPE_DIC:
+            retval = int_new(((pPmDict_t)ps)->length, &pr);
+            break;
+
+#ifdef HAVE_BYTEARRAY
+        case OBJ_TYPE_BYA:
+            retval = int_new(((pPmBytearray_t)ps)->length, &pr);
+            break;
+#endif /* HAVE_BYTEARRAY */
+
+        default:
+            /* If not a string or sequence type, raise TypeError */
+            PM_RAISE(retval, PM_RET_EX_TYPE);
+    }
+
+    NATIVE_SET_TOS(pr);
+    return retval;
+    
+}
+
+PmReturn_t
+nat_06___bi_locals(pPmFrame_t *ppframe)
+{
+
+    pPmObj_t pr = C_NULL;
+    PmReturn_t retval;
+
+    /* If wrong number of args, raise TypeError */
+    if (NATIVE_GET_NUM_ARGS() != 0)
+    {
+        PM_RAISE(retval, PM_RET_EX_TYPE);
+        return retval;
+    }
+
+    /* Return calling frame's local attrs dict on the stack */
+    pr = (pPmObj_t)NATIVE_GET_PFRAME()->fo_attrs;
+    NATIVE_SET_TOS(pr);
+
+    return PM_RET_OK;
+    
+}
+
+PmReturn_t
+nat_07___bi_ord(pPmFrame_t *ppframe)
+{
+
+    pPmObj_t ps;
+    pPmObj_t pn;
+    int32_t n;
+    PmReturn_t retval;
+
+    /* If wrong number of args, raise TypeError */
+    if (NATIVE_GET_NUM_ARGS() != 1)
+    {
+        PM_RAISE(retval, PM_RET_EX_TYPE);
+        return retval;
+    }
+
+    ps = NATIVE_GET_LOCAL(0);
+
+    /* Raise TypeError if arg is not string of length 1 */
+    if ((OBJ_GET_TYPE(ps) != OBJ_TYPE_STR)
+        || (((pPmString_t)ps)->length != 1))
+
+    {
+        PM_RAISE(retval, PM_RET_EX_TYPE);
+        return retval;
+    }
+
+    /* Get integer value of character */
+    n = ((pPmString_t)ps)->val[0];
+    retval = int_new(n, &pn);
+    NATIVE_SET_TOS(pn);
+    return retval;
+    
+}
+
+PmReturn_t
+nat_08___bi_range(pPmFrame_t *ppframe)
+{
+
+    PmReturn_t retval;
+    pPmObj_t pa = C_NULL;
+    pPmObj_t pb = C_NULL;
+    pPmObj_t pc = C_NULL;
+    pPmObj_t pi = C_NULL;
+    pPmObj_t pr = C_NULL;
+    int16_t i = 0;
+    uint8_t objid1, objid2;
+
+    switch (NATIVE_GET_NUM_ARGS())
+    {
+        case 1:
+            pa = PM_ZERO;
+            pb = NATIVE_GET_LOCAL(0);
+            pc = PM_ONE;
+            break;
+
+        case 2:
+            pa = NATIVE_GET_LOCAL(0);
+            pb = NATIVE_GET_LOCAL(1);
+            pc = PM_ONE;
+            break;
+
+        case 3:
+            pa = NATIVE_GET_LOCAL(0);
+            pb = NATIVE_GET_LOCAL(1);
+            pc = NATIVE_GET_LOCAL(2);
+
+            /* If 3rd arg is 0, ValueError */
+            if (((pPmInt_t)pc)->val == 0)
+            {
+                PM_RAISE(retval, PM_RET_EX_VAL);
+                return retval;
+            }
+            break;
+
+        default:
+            /* If wrong number of args, raise TypeError */
+            PM_RAISE(retval, PM_RET_EX_TYPE);
+            return retval;
+    }
+
+    /* Allocate list */
+    retval = list_new(&pr);
+    PM_RETURN_IF_ERROR(retval);
+
+    /* Iterate depending on counting direction */
+    if (((pPmInt_t)pc)->val > 0)
+    {
+        for (i = ((pPmInt_t)pa)->val;
+             i < ((pPmInt_t)pb)->val;
+             i += ((pPmInt_t)pc)->val)
+        {
+            heap_gcPushTempRoot(pr, &objid1);
+            retval = int_new(i, &pi);
+            if (retval != PM_RET_OK)
+            {
+                heap_gcPopTempRoot(objid1);
+                return retval;
+            }
+
+            heap_gcPushTempRoot(pi, &objid2);
+            retval = list_append(pr, pi);
+            heap_gcPopTempRoot(objid1);
+            PM_RETURN_IF_ERROR(retval);
+        }
+    }
+    else
+    {
+        for (i = ((pPmInt_t)pa)->val;
+             i > ((pPmInt_t)pb)->val;
+             i += ((pPmInt_t)pc)->val)
+        {
+            heap_gcPushTempRoot(pr, &objid1);
+            retval = int_new(i, &pi);
+            if (retval != PM_RET_OK)
+            {
+                heap_gcPopTempRoot(objid1);
+                return retval;
+            }
+
+            heap_gcPushTempRoot(pi, &objid2);
+            retval = list_append(pr, pi);
+            heap_gcPopTempRoot(objid1);
+            PM_RETURN_IF_ERROR(retval);
+        }
+    }
+
+    /* Return list */
+    NATIVE_SET_TOS(pr);
+    return retval;
+    
+}
+
+PmReturn_t
+nat_09___bi_sum(pPmFrame_t *ppframe)
+{
+
+    pPmObj_t ps;
+    pPmObj_t pn;
+    pPmObj_t po;
+    int32_t n;
+    uint16_t len;
+    uint16_t i;
+    PmReturn_t retval;
+#ifdef HAVE_FLOAT
+    float f;
+    uint8_t usefloat = C_FALSE;
+#endif /* HAVE_FLOAT */
+
+    /* If wrong number of args, raise TypeError */
+    if (NATIVE_GET_NUM_ARGS() != 1)
+    {
+        PM_RAISE(retval, PM_RET_EX_TYPE);
+        return retval;
+    }
+
+    ps = NATIVE_GET_LOCAL(0);
+
+#ifdef HAVE_BYTEARRAY
+    /* Bytearray is a special case to save RAM converting each byte to an Int */
+    if (OBJ_GET_TYPE(ps) == OBJ_TYPE_BYA)
+    {
+        n = 0;
+        len = ((pPmBytearray_t)ps)->length;
+        po = (pPmObj_t)((pPmBytearray_t)ps)->val;
+        for (i = 0; i < len; i++)
+        {
+            n += (uint8_t)((pPmBytes_t)po)->val[i];
+        }
+        retval = int_new(n, &pn);
+        NATIVE_SET_TOS(pn);
+        return retval;
+    }
+#endif /* HAVE_BYTEARRAY */
+
+    /* Raise TypeError if arg is not a sequence */
+    if ((OBJ_GET_TYPE(ps) != OBJ_TYPE_TUP)
+        && (OBJ_GET_TYPE(ps) != OBJ_TYPE_LST)
+        && (OBJ_GET_TYPE(ps) != OBJ_TYPE_DIC))
+    {
+        PM_RAISE(retval, PM_RET_EX_TYPE);
+        return retval;
+    }
+
+    /* Get the length of the sequence */
+    retval = seq_getLength(ps, &len);
+    PM_RETURN_IF_ERROR(retval);
+
+    /* Calculate the sum of the sequence */
+    n = 0;
+#ifdef HAVE_FLOAT
+    f = 0.0;
+#endif
+    for (i = 0; i < len; i++)
+    {
+        retval = seq_getSubscript(ps, i, &po);
+
+        if (OBJ_GET_TYPE(po) == OBJ_TYPE_INT)
+        {
+            /* Add value to sum */
+            n += ((pPmInt_t)po)->val;
+#ifdef HAVE_FLOAT
+            f += (float)((pPmInt_t)po)->val;
+#endif /* HAVE_FLOAT */
+        }
+
+#ifdef HAVE_FLOAT
+        else if (OBJ_GET_TYPE(po) == OBJ_TYPE_FLT)
+        {
+            /* Add value to sum */
+            f += ((pPmFloat_t)po)->val;
+            usefloat = C_TRUE;
+        }
+#endif /* HAVE_FLOAT */
+
+        /* Raise TypeError if item is not an integer */
+        else
+        {
+            PM_RAISE(retval, PM_RET_EX_TYPE);
+            return retval;
+        }
+    }
+
+#ifdef HAVE_FLOAT
+    if (usefloat)
+    {
+        retval = float_new(f, &pn);
+    }
+    else
+#endif /* HAVE_FLOAT */
+    {
+        retval = int_new(n, &pn);
+    }
+    NATIVE_SET_TOS(pn);
+    return retval;
+    
+}
+
+PmReturn_t
+nat_10___bi_type(pPmFrame_t *ppframe)
+{
+
+    PmReturn_t retval;
+    pPmObj_t po = C_NULL;
+    pPmObj_t pr = C_NULL;
+
+    /* If wrong number of args, raise TypeError */
+    if (NATIVE_GET_NUM_ARGS() != 1)
+    {
+        PM_RAISE(retval, PM_RET_EX_TYPE);
+        return retval;
+    }
+
+    /* Get arg */
+    po = NATIVE_GET_LOCAL(0);
+
+    /* Create int from type enum */
+    retval = int_new(OBJ_GET_TYPE(po), &pr);
+    NATIVE_SET_TOS(pr);
+    return retval;
+    
+}
+
+PmReturn_t
+nat_11___bi_Co(pPmFrame_t *ppframe)
+{
+
+    PmReturn_t retval;
+    pPmObj_t pimg;
+    pPmObj_t pco;
+
+    /* If wrong number of args, raise TypeError */
+    if (NATIVE_GET_NUM_ARGS() != 1)
+    {
+        PM_RAISE(retval, PM_RET_EX_TYPE);
+        return retval;
+    }
+
+    /* Raise ValueError if arg is not an Image Obj */
+    pimg = NATIVE_GET_LOCAL(0);
+    if (OBJ_GET_TYPE(pimg) != OBJ_TYPE_CIO)
+    {
+        PM_RAISE(retval, PM_RET_EX_VAL);
+        return retval;
+    }
+
+    /* Create a code object from the image */
+    retval = obj_loadFromImgObj(pimg, &pco);
+    PM_RETURN_IF_ERROR(retval);
+
+    /* Return the code object */
+    NATIVE_SET_TOS(pco);
+    return retval;
+    
+}
+
+PmReturn_t
+nat_12___bi___init__(pPmFrame_t *ppframe)
+{
+
+        PmReturn_t retval;
+        pPmObj_t pself;
+        pPmObj_t pfa;
+        pPmObj_t pfunc;
+        pPmObj_t pframe;
+        uint8_t i;
+        uint8_t objid;
+
+        /* Raise TypeError if wrong number of args */
+        if (NATIVE_GET_NUM_ARGS() != 2)
+        {
+            PM_RAISE(retval, PM_RET_EX_TYPE);
+            return retval;
+        }
+
+        /* Raise ValueError if first args are not: instance, tuple */
+        pself = NATIVE_GET_LOCAL(0);
+        pfa = NATIVE_GET_LOCAL(1);
+        if (OBJ_GET_TYPE(pself) != OBJ_TYPE_CLI)
+        {
+            PM_RAISE(retval, PM_RET_EX_VAL);
+            return retval;
+        }
+        if (OBJ_GET_TYPE(pfa) != OBJ_TYPE_TUP)
+        {
+            PM_RAISE(retval, PM_RET_EX_VAL);
+            return retval;
+        }
+
+        /* Create a new frame for the function */
+        pfunc = ((pPmTuple_t)pfa)->val[0];
+        retval = frame_new(pfunc, &pframe);
+        PM_RETURN_IF_ERROR(retval);
+
+        /* Copy args into frame's locals */
+        for (i = 0; i < ((pPmTuple_t)pfa)->length - 1; i++)
+        {
+            /* The pfa tuple is (func, [arg0, ... argN]) */
+            ((pPmFrame_t)pframe)->fo_locals[i] = ((pPmTuple_t)pfa)->val[i + 1];
+        }
+
+        /* Store frame in None attr of instance */
+        heap_gcPushTempRoot(pframe, &objid);
+        retval = dict_setItem((pPmObj_t)((pPmInstance_t)pself)->cli_attrs,
+                              PM_NONE, pframe);
+        heap_gcPopTempRoot(objid);
+
+        NATIVE_SET_TOS(PM_NONE);
+        return retval;
+        
+}
+
+PmReturn_t
+nat_13___bi_send(pPmFrame_t *ppframe)
+{
+
+        PmReturn_t retval;
+        pPmObj_t pself;
+        pPmObj_t parg;
+        pPmObj_t pgenframe;
+
+        /* Raise TypeError if wrong number of args */
+        if (NATIVE_GET_NUM_ARGS() != 2)
+        {
+            PM_RAISE(retval, PM_RET_EX_TYPE);
+            return retval;
+        }
+
+        /* Raise ValueError if first arg is not an instance */
+        pself = NATIVE_GET_LOCAL(0);
+        parg = NATIVE_GET_LOCAL(1);
+        if (OBJ_GET_TYPE(pself) != OBJ_TYPE_CLI)
+        {
+            PM_RAISE(retval, PM_RET_EX_VAL);
+            return retval;
+        }
+
+        /* Get the generator's frame */
+        retval = dict_getItem((pPmObj_t)((pPmInstance_t)pself)->cli_attrs,
+                              PM_NONE, &pgenframe);
+        PM_RETURN_IF_ERROR(retval);
+
+        /* Push argument onto generator's frame's stack */
+        *(((pPmFrame_t)pgenframe)->fo_sp) = parg;
+        ((pPmFrame_t)pgenframe)->fo_sp++;
+
+        /* Set generator's frame's fo_back so yielded value goes to caller */
+        ((pPmFrame_t)pgenframe)->fo_back = NATIVE_GET_PFRAME();
+
+        /* Set active frame to run generator */
+        NATIVE_GET_PFRAME() = (pPmFrame_t)pgenframe;
+
+        return PM_RET_FRAME_SWITCH;
+        
+}
+
+PmReturn_t
+nat_14___bi_ismain(pPmFrame_t *ppframe)
+{
+
+
+    NATIVE_SET_TOS((NATIVE_GET_PFRAME()->fo_isImport) ? PM_FALSE : PM_TRUE);
+
+    return PM_RET_OK;
+    
+}
+
+PmReturn_t
+nat_15_dict_clear(pPmFrame_t *ppframe)
+{
+
+    pPmObj_t pd;
+    PmReturn_t retval = PM_RET_OK;
+
+    /* Raise TypeError if it's not a dict or wrong number of args, */
+    pd = NATIVE_GET_LOCAL(0);
+    if ((OBJ_GET_TYPE(pd) != OBJ_TYPE_DIC) || (NATIVE_GET_NUM_ARGS() != 1))
+    {
+        PM_RAISE(retval, PM_RET_EX_TYPE);
+        return retval;
+    }
+
+    /* Clear the contents of the dict */
+    retval = dict_clear(pd);
+    PM_RETURN_IF_ERROR(retval);
+
+    NATIVE_SET_TOS(PM_NONE);
+
+    return retval;
+    
+}
+
+PmReturn_t
+nat_16_dict_keys(pPmFrame_t *ppframe)
+{
+
+    pPmObj_t pd;
+    pPmObj_t pl;
+    pPmObj_t pk;
+    pSeglist_t psl;
+    uint16_t i;
+    PmReturn_t retval = PM_RET_OK;
+    uint8_t objid;
+
+    /* Raise TypeError if it's not a dict or wrong number of args, */
+    pd = NATIVE_GET_LOCAL(0);
+    if ((OBJ_GET_TYPE(pd) != OBJ_TYPE_DIC) || (NATIVE_GET_NUM_ARGS() != 1))
+    {
+        PM_RAISE(retval, PM_RET_EX_TYPE);
+        return retval;
+    }
+
+    /* Create empty list */
+    retval = list_new(&pl);
+    PM_RETURN_IF_ERROR(retval);
+
+    /* Iterate through the keys seglist */
+    psl = ((pPmDict_t)pd)->d_keys;
+    for (i = 0; i < ((pPmDict_t)pd)->length; i++)
+    {
+        /* Get the key and append it to the list */
+        retval = seglist_getItem(psl, i, &pk);
+        PM_RETURN_IF_ERROR(retval);
+        heap_gcPushTempRoot(pl, &objid);
+        retval = list_append(pl, pk);
+        heap_gcPopTempRoot(objid);
+        PM_RETURN_IF_ERROR(retval);
+    }
+
+    /* Return the list of keys to the caller */
+    NATIVE_SET_TOS(pl);
+
+    return retval;
+    
+}
+
+PmReturn_t
+nat_17_dict_values(pPmFrame_t *ppframe)
+{
+
+    pPmObj_t pd;
+    pPmObj_t pl;
+    pPmObj_t pv;
+    pSeglist_t psl;
+    uint16_t i;
+    PmReturn_t retval = PM_RET_OK;
+    uint8_t objid;
+
+    /* Raise TypeError if it's not a dict or wrong number of args, */
+    pd = NATIVE_GET_LOCAL(0);
+    if ((OBJ_GET_TYPE(pd) != OBJ_TYPE_DIC) || (NATIVE_GET_NUM_ARGS() != 1))
+    {
+        PM_RAISE(retval, PM_RET_EX_TYPE);
+        return retval;
+    }
+
+    /* Create empty list */
+    retval = list_new(&pl);
+    PM_RETURN_IF_ERROR(retval);
+
+    /* Iterate through the values seglist */
+    psl = ((pPmDict_t)pd)->d_vals;
+    for (i = 0; i < ((pPmDict_t)pd)->length; i++)
+    {
+        /* Get the value and append it to the list */
+        retval = seglist_getItem(psl, i, &pv);
+        PM_RETURN_IF_ERROR(retval);
+        heap_gcPushTempRoot(pl, &objid);
+        retval = list_append(pl, pv);
+        heap_gcPopTempRoot(objid);
+        PM_RETURN_IF_ERROR(retval);
+    }
+
+    /* Return the list of values to the caller */
+    NATIVE_SET_TOS(pl);
+
+    return retval;
+    
+}
+
+PmReturn_t
+nat_18_dict_update(pPmFrame_t *ppframe)
+{
+
+    pPmObj_t pd1;
+    pPmObj_t pd2;
+    PmReturn_t retval;
+
+    /* Raise TypeError if wrong number of args, */
+    if (NATIVE_GET_NUM_ARGS() != 2)
+    {
+        PM_RAISE(retval, PM_RET_EX_TYPE);
+        return retval;
+    }
+
+    pd1 = NATIVE_GET_LOCAL(0);
+    pd2 = NATIVE_GET_LOCAL(1);
+    retval = dict_update(pd1, pd2, C_FALSE);
+
+    NATIVE_SET_TOS(PM_NONE);
+    return retval;
+    
+}
+
+PmReturn_t
+nat_19_list_append(pPmFrame_t *ppframe)
+{
+
+    pPmObj_t pl;
+    PmReturn_t retval = PM_RET_OK;
+
+    /* Raise TypeError if it's not a list or wrong number of args, */
+    pl = NATIVE_GET_LOCAL(0);
+    if ((OBJ_GET_TYPE(pl) != OBJ_TYPE_LST) || (NATIVE_GET_NUM_ARGS() != 2))
+    {
+        PM_RAISE(retval, PM_RET_EX_TYPE);
+        return retval;
+    }
+
+    /* Append the object to the list */
+    retval = list_append(pl, NATIVE_GET_LOCAL(1));
+
+    NATIVE_SET_TOS(PM_NONE);
+
+    return retval;
+    
+}
+
+PmReturn_t
+nat_20_list_index(pPmFrame_t *ppframe)
+{
+
+    pPmObj_t pl;
+    pPmObj_t po;
+    pPmObj_t pi;
+    PmReturn_t retval = PM_RET_OK;
+    uint16_t i;
+
+    /* Raise TypeError if it's not a list or wrong number of args, */
+    pl = NATIVE_GET_LOCAL(0);
+    if ((OBJ_GET_TYPE(pl) != OBJ_TYPE_LST) || (NATIVE_GET_NUM_ARGS() != 2))
+    {
+        PM_RAISE(retval, PM_RET_EX_TYPE);
+        return retval;
+    }
+
+    /* Get the index of the object in the list */
+    po = NATIVE_GET_LOCAL(1);
+    retval = list_index(pl, po, &i);
+
+    if (retval == PM_RET_EX_VAL)
+    {
+        PM_RAISE(retval, PM_RET_EX_VAL);
+        return retval;
+    }
+
+    int_new((int32_t)i, &pi);
+    NATIVE_SET_TOS(pi);
+
+    return retval;
+    
+}
+
+PmReturn_t
+nat_21_list_insert(pPmFrame_t *ppframe)
+{
+
+    pPmObj_t pl;
+    pPmObj_t pi;
+    pPmObj_t po;
+    PmReturn_t retval = PM_RET_OK;
+    uint16_t i;
+
+    /*
+     * Raise TypeError if wrong number of args, first arg is not a list, or
+     * second arg is not an int
+     */
+    pl = NATIVE_GET_LOCAL(0);
+    pi = NATIVE_GET_LOCAL(1);
+    po = NATIVE_GET_LOCAL(2);
+    if ((NATIVE_GET_NUM_ARGS() != 3)
+        || (OBJ_GET_TYPE(pl) != OBJ_TYPE_LST)
+        || (OBJ_GET_TYPE(pi) != OBJ_TYPE_INT) )
+    {
+        PM_RAISE(retval, PM_RET_EX_TYPE);
+        return retval;
+    }
+
+    /* Insert the object before the given index */
+    i = (uint16_t)((pPmInt_t)pi)->val;
+    retval = list_insert(pl, i, po);
+
+    if (retval != PM_RET_OK)
+    {
+        PM_RAISE(retval, PM_RET_EX_SYS);
+    }
+
+    NATIVE_SET_TOS(PM_NONE);
+
+    return retval;
+    
+}
+
+PmReturn_t
+nat_22_list_pop(pPmFrame_t *ppframe)
+{
+
+    pPmObj_t pl;
+    pPmObj_t pi;
+    pPmObj_t po;
+    PmReturn_t retval = PM_RET_OK;
+    int16_t i;
+
+    /*
+     * Raise TypeError if first arg is not a list o second arg is not an int
+     * or there are the wrong number of arguments
+     */
+    pl = NATIVE_GET_LOCAL(0);
+    if (OBJ_GET_TYPE(pl) != OBJ_TYPE_LST)
+    {
+        PM_RAISE(retval, PM_RET_EX_TYPE);
+        return retval;
+    }
+
+    pi = NATIVE_GET_LOCAL(1);
+    if (NATIVE_GET_NUM_ARGS() == 2)
+    {
+        if (OBJ_GET_TYPE(pi) != OBJ_TYPE_INT)
+        {
+            PM_RAISE(retval, PM_RET_EX_TYPE);
+            return retval;
+        }
+        i = (uint16_t)((pPmInt_t)pi)->val;
+    }
+    else
+    {
+        i = -1;
+    }
+    if ((NATIVE_GET_NUM_ARGS() < 1) || (NATIVE_GET_NUM_ARGS() > 2))
+    {
+        PM_RAISE(retval, PM_RET_EX_TYPE);
+        return retval;
+    }
+
+    /* Get the object at the given index */
+    retval = list_getItem(pl, i, &po);
+    PM_RETURN_IF_ERROR(retval);
+
+    /* Return the object to the caller */
+    NATIVE_SET_TOS(po);
+
+    /* Remove the object from the given index */
+    retval = list_delItem(pl, i);
+    PM_RETURN_IF_ERROR(retval);
+
+    return retval;
+    
+}
+
+PmReturn_t
+nat_23_list_remove(pPmFrame_t *ppframe)
+{
+
+    pPmObj_t pl;
+    pPmObj_t pv;
+    PmReturn_t retval = PM_RET_OK;
+
+    /* Raise TypeError if it's not a list or wrong number of args, */
+    pl = NATIVE_GET_LOCAL(0);
+    if ((OBJ_GET_TYPE(pl) != OBJ_TYPE_LST) || (NATIVE_GET_NUM_ARGS() != 2))
+    {
+        PM_RAISE(retval, PM_RET_EX_TYPE);
+        return retval;
+    }
+
+    /* Remove the value from the list */
+    pv = NATIVE_GET_LOCAL(1);
+    retval = list_remove(pl, pv);
+    if (retval != PM_RET_OK)
+    {
+        PM_RAISE(retval, retval);
+    }
+
+    NATIVE_SET_TOS(PM_NONE);
+
+    return retval;
+    
+}
+
+PmReturn_t
+nat_24_string_atoi(pPmFrame_t *ppframe)
+{
+
+    pPmObj_t pa;
+    pPmObj_t pb;
+    char const *pc;
+    char *pend;
+    long i;
+    int8_t base;
+    pPmObj_t pi;
+    PmReturn_t retval = PM_RET_OK;
+
+    /* Raise TypeError if it's not a string or wrong number of args, */
+    pa = NATIVE_GET_LOCAL(0);
+    if ((OBJ_GET_TYPE(pa) != OBJ_TYPE_STR) || (NATIVE_GET_NUM_ARGS() < 1)
+        || (NATIVE_GET_NUM_ARGS() > 2))
+    {
+        PM_RAISE(retval, PM_RET_EX_TYPE);
+        return retval;
+    }
+
+    /* Get the base, if it exists; otherwise assume 10 */
+    base = 10;
+    if (NATIVE_GET_NUM_ARGS() == 2)
+    {
+        pb = NATIVE_GET_LOCAL(1);
+
+        /* Raise a TypeError if 2nd arg is not an int */
+        if (OBJ_GET_TYPE(pb) != OBJ_TYPE_INT)
+        {
+            PM_RAISE(retval, PM_RET_EX_TYPE);
+            return retval;
+        }
+
+        base = ((pPmInt_t)pb)->val;
+
+        /* Raise ValueError if base is out of range */
+        if ((base < 0) || (base == 1) || (base > 36))
+        {
+            PM_RAISE(retval, PM_RET_EX_VAL);
+            return retval;
+        }
+    }
+
+    /* Perform conversion */
+    pend = C_NULL;
+    pc = (char const *)&(((pPmString_t)pa)->val);
+    i = strtol(pc, &pend, base);
+
+    /* Raise ValueError if there was a conversion error */
+    if (*pend != C_NULL)
+    {
+        PM_RAISE(retval, PM_RET_EX_VAL);
+        return retval;
+    }
+
+    /* Create an int object to hold the result of the conversion */
+    retval = int_new(i, &pi);
+
+    NATIVE_SET_TOS(pi);
+
+    return retval;
+    
+}
+
+PmReturn_t
+nat_25_string_count(pPmFrame_t *ppframe)
+{
+
+    pPmObj_t ps1;
+    pPmObj_t ps2;
+    uint8_t *pc1;
+    uint8_t *pc2;
+    uint8_t *pscan;
+    uint8_t *pmatch;
+    uint8_t pc2c0;
+    uint16_t pc1len;
+    uint16_t pc2len;
+    uint16_t n;
+    uint16_t remaining;
+    uint16_t cmp;
+    pPmObj_t pn;
+    PmReturn_t retval = PM_RET_OK;
+
+    /* Raise TypeError if it's not a string or wrong number of args, */
+    ps1 = NATIVE_GET_LOCAL(0);
+    ps2 = NATIVE_GET_LOCAL(1);
+    if ((OBJ_GET_TYPE(ps1) != OBJ_TYPE_STR) || (NATIVE_GET_NUM_ARGS() != 2)
+        || (OBJ_GET_TYPE(ps2) != OBJ_TYPE_STR))
+    {
+        PM_RAISE(retval, PM_RET_EX_TYPE);
+        return retval;
+    }
+
+    pc1 = ((pPmString_t)ps1)->val;
+    pc2 = ((pPmString_t)ps2)->val;
+    pc1len = ((pPmString_t)ps1)->length;
+    pc2len = ((pPmString_t)ps2)->length;
+    n = 0;
+
+    /* Handle some quick special cases (order of if-clauses is important) */
+    if (pc2len == 0)
+    {
+        n = pc1len + 1;
+    }
+    else if (pc1len == 0)
+    {
+        n = 0;
+    }
+
+    /* Count the number of matches */
+    else
+    {
+        n = 0;
+        remaining = pc1len;
+        pscan = pc1;
+        pc2c0 = pc2[0];
+        while (pscan <= (pc1 + (pc1len - pc2len)))
+        {
+            /* Find the next possible start */
+            pmatch = (uint8_t *)memchr(pscan, pc2c0, remaining);
+            if (pmatch == C_NULL) break;
+            remaining -= (pmatch - pscan);
+            pscan = pmatch;
+
+            /* If it matches, increase the count, else try the next char */
+            cmp = memcmp(pscan, pc2, pc2len);
+            if (cmp == 0)
+            {
+                n++;
+                pscan += pc2len;
+                remaining -= pc2len;
+            }
+            else
+            {
+                pscan++;
+                remaining--;
+            }
+        }
+    }
+
+    retval = int_new(n, &pn);
+
+    NATIVE_SET_TOS(pn);
+
+    return retval;
+    
+}
+
+PmReturn_t
+nat_26_string_find(pPmFrame_t *ppframe)
+{
+
+    pPmObj_t ps1;
+    pPmObj_t ps2;
+    uint8_t *pc1;
+    uint8_t *pc2;
+    uint8_t *pmatch;
+    uint16_t pc1len;
+    uint16_t pc2len;
+    int32_t n;
+    pPmObj_t pn;
+    PmReturn_t retval = PM_RET_OK;
+
+    /* Raise TypeError if it's not a string or wrong number of args, */
+    ps1 = NATIVE_GET_LOCAL(0);
+    ps2 = NATIVE_GET_LOCAL(1);
+    if ((OBJ_GET_TYPE(ps1) != OBJ_TYPE_STR) || (NATIVE_GET_NUM_ARGS() != 2)
+        || (OBJ_GET_TYPE(ps2) != OBJ_TYPE_STR))
+    {
+        PM_RAISE(retval, PM_RET_EX_TYPE);
+        return retval;
+    }
+
+    pc1 = ((pPmString_t)ps1)->val;
+    pc2 = ((pPmString_t)ps2)->val;
+    pc1len = ((pPmString_t)ps1)->length;
+    pc2len = ((pPmString_t)ps2)->length;
+    n = -1;
+
+    /* Handle a quick special case */
+    if (pc2len == 0)
+    {
+        n = 0;
+    }
+
+    /* Try to find the index of the substring */
+    else
+    {
+        /* Find the next possible start */
+        pmatch = (uint8_t *)memchr(pc1, pc2[0], pc1len);
+        if (pmatch != C_NULL)
+        {
+            /* If it matches, calculate the index */
+            if (memcmp(pmatch, pc2, pc2len) == 0)
+            {
+                n = pmatch - pc1;
+            }
+        }
+    }
+
+    retval = int_new(n, &pn);
+
+    NATIVE_SET_TOS(pn);
+
+    return retval;
+    
+}
+
+PmReturn_t
+nat_27_sys_exit(pPmFrame_t *ppframe)
+{
+
+    pPmObj_t pval = C_NULL;
+    PmReturn_t retval;
+
+    /* If no arg given, assume return 0 */
+    if (NATIVE_GET_NUM_ARGS() == 0)
+    {
+        NATIVE_SET_TOS(PM_ZERO);
+    }
+
+    /* If 1 arg given, put it on stack */
+    else if (NATIVE_GET_NUM_ARGS() == 1)
+    {
+        pval = NATIVE_GET_LOCAL(0);
+        NATIVE_SET_TOS(pval);
+    }
+
+    /* If wrong number of args, raise TypeError */
+    else
+    {
+        PM_RAISE(retval, PM_RET_EX_TYPE);
+        return retval;
+    }
+
+    /* Raise the SystemExit exception */
+    PM_RAISE(retval, PM_RET_EX_EXIT);
+    return retval;
+    
+}
+
+PmReturn_t
+nat_28_sys_gc(pPmFrame_t *ppframe)
+{
+
+    PmReturn_t retval = PM_RET_OK;
+#ifdef HAVE_GC
+    /* If wrong number of args, raise TypeError */
+    if (NATIVE_GET_NUM_ARGS() != 0)
+    {
+        PM_RAISE(retval, PM_RET_EX_TYPE);
+        return retval;
+    }
+
+    retval = heap_gcRun();
+#endif
+    NATIVE_SET_TOS(PM_NONE);
+
+    return retval;
+    
+}
+
+PmReturn_t
+nat_29_sys_getb(pPmFrame_t *ppframe)
+{
+
+    uint8_t b;
+    pPmObj_t pb;
+    PmReturn_t retval;
+
+    /* If wrong number of args, raise TypeError */
+    if (NATIVE_GET_NUM_ARGS() != 0)
+    {
+        PM_RAISE(retval, PM_RET_EX_TYPE);
+        return retval;
+    }
+
+    retval = plat_getByte(&b);
+    PM_RETURN_IF_ERROR(retval);
+
+    retval = int_new((int32_t)b, &pb);
+    NATIVE_SET_TOS(pb);
+    return retval;
+    
+}
+
+PmReturn_t
+nat_30_sys_heap(pPmFrame_t *ppframe)
+{
+
+    PmReturn_t retval;
+    pPmObj_t pavail;
+    pPmObj_t psize;
+    pPmObj_t ptup;
+    uint8_t objid;
+
+    /* If wrong number of args, raise TypeError */
+    if (NATIVE_GET_NUM_ARGS() != 0)
+    {
+        PM_RAISE(retval, PM_RET_EX_TYPE);
+        return retval;
+    }
+
+    /* Allocate a tuple to store the return values */
+    retval = tuple_new(2, &ptup);
+    PM_RETURN_IF_ERROR(retval);
+
+    /* Get the maximum heap size */
+    heap_gcPushTempRoot(ptup, &objid);
+    retval = int_new(heap_getSize(), &psize);
+    if (retval != PM_RET_OK)
+    {
+        heap_gcPopTempRoot(objid);
+        return retval;
+    }
+
+    /* Allocate an int to hold the amount of heap available */
+    retval = int_new(heap_getAvail() - sizeof(PmInt_t), &pavail);
+    heap_gcPopTempRoot(objid);
+    PM_RETURN_IF_ERROR(retval);
+
+    /* Put the two heap values in the tuple */
+    ((pPmTuple_t)ptup)->val[0] = pavail;
+    ((pPmTuple_t)ptup)->val[1] = psize;
+
+    /* Return the tuple on the stack */
+    NATIVE_SET_TOS(ptup);
+
+    return retval;
+    
+}
+
+PmReturn_t
+nat_31_sys_putb(pPmFrame_t *ppframe)
+{
+
+    uint8_t b;
+    pPmObj_t pb;
+    PmReturn_t retval;
+
+    pb = NATIVE_GET_LOCAL(0);
+
+    /* If wrong number of args, raise TypeError */
+    if (NATIVE_GET_NUM_ARGS() != 1)
+    {
+        PM_RAISE(retval, PM_RET_EX_TYPE);
+        return retval;
+    }
+
+    /* If arg is not an int, raise TypeError */
+    if (OBJ_GET_TYPE(pb) != OBJ_TYPE_INT)
+    {
+        PM_RAISE(retval, PM_RET_EX_TYPE);
+        return retval;
+    }
+
+    b = ((pPmInt_t)pb)->val & 0xFF;
+    retval = plat_putByte(b);
+    NATIVE_SET_TOS(PM_NONE);
+    return retval;
+    
+}
+
+PmReturn_t
+nat_32_sys_runInThread(pPmFrame_t *ppframe)
+{
+
+    PmReturn_t retval;
+    pPmObj_t pf;
+
+    /* If wrong number of args, raise TypeError */
+    if (NATIVE_GET_NUM_ARGS() != 1)
+    {
+        PM_RAISE(retval, PM_RET_EX_TYPE);
+        return retval;
+    }
+
+    /* If arg is not a function, raise TypeError */
+    pf = NATIVE_GET_LOCAL(0);
+    if (OBJ_GET_TYPE(pf) != OBJ_TYPE_FXN)
+    {
+        PM_RAISE(retval, PM_RET_EX_TYPE);
+        return retval;
+    }
+
+    retval = interp_addThread((pPmFunc_t)pf);
+    NATIVE_SET_TOS(PM_NONE);
+    return retval;
+    
+}
+
+PmReturn_t
+nat_33_sys_time(pPmFrame_t *ppframe)
+{
+
+    uint32_t t;
+    pPmObj_t pt;
+    PmReturn_t retval;
+
+    /* If wrong number of args, raise TypeError */
+    if (NATIVE_GET_NUM_ARGS() != 0)
+    {
+        PM_RAISE(retval, PM_RET_EX_TYPE);
+        return retval;
+    }
+
+    /* Get the system time (milliseconds since init) */
+    retval = plat_getMsTicks(&t);
+    PM_RETURN_IF_ERROR(retval);
+
+    /*
+     * Raise ValueError if there is an overflow
+     * (plat_getMsTicks is unsigned; int is signed)
+     */
+    if ((int32_t)t < 0)
+    {
+        PM_RAISE(retval, PM_RET_EX_VAL);
+        return retval;
+    }
+
+    /* Return an int object with the time value */
+    retval = int_new((int32_t)t, &pt);
+    NATIVE_SET_TOS(pt);
+    return retval;
+    
+}
+
+PmReturn_t
+nat_34_ipm__getImg(pPmFrame_t *ppframe)
+{
+
+    PmReturn_t retval;
+    uint8_t imgType;
+    uint16_t imgSize;
+    uint8_t *pchunk;
+    pPmCodeImgObj_t pimg;
+    uint16_t i;
+    uint8_t b;
+
+    /* Get the image type */
+    retval = plat_getByte(&imgType);
+    PM_RETURN_IF_ERROR(retval);
+
+    /* Quit if a code image type was not received */
+    if (imgType != OBJ_TYPE_CIM)
+    {
+        PM_RAISE(retval, PM_RET_EX_STOP);
+        return retval;
+    }
+
+    /* Get the image size (little endien) */
+    retval = plat_getByte(&b);
+    PM_RETURN_IF_ERROR(retval);
+    imgSize = b;
+    retval = plat_getByte(&b);
+    PM_RETURN_IF_ERROR(retval);
+    imgSize |= (b << 8);
+
+    /* Get space for CodeImgObj */
+    retval = heap_getChunk(sizeof(PmCodeImgObj_t) + imgSize, &pchunk);
+    PM_RETURN_IF_ERROR(retval);
+    pimg = (pPmCodeImgObj_t)pchunk;
+    OBJ_SET_TYPE(pimg, OBJ_TYPE_CIO);
+
+    /* Start the image with the bytes that have already been received */
+    i = 0;
+    pimg->val[i++] = imgType;
+    pimg->val[i++] = imgSize & 0xFF;
+    pimg->val[i++] = (imgSize >> 8) & 0xFF;
+
+    /* Get the remaining bytes in the image */
+    for(; i < imgSize; i++)
+    {
+        retval = plat_getByte(&b);
+        PM_RETURN_IF_ERROR(retval);
+
+        pimg->val[i] = b;
+    }
+
+    /* Return the image as a code image object on the stack */
+    NATIVE_SET_TOS((pPmObj_t)pimg);
+    return retval;
+    
+}
+
+PmReturn_t
+nat_35_ipm_x04(pPmFrame_t *ppframe)
+{
+
+    NATIVE_SET_TOS(PM_NONE);
+    return plat_putByte(0x04);
+    
+}
+
+/* Native function lookup table */
+pPmNativeFxn_t const std_nat_fxn_table[] =
+{
+    nat_00___bi_chr,
+    nat_01___bi_dir,
+    nat_02___bi_eval,
+    nat_03___bi_globals,
+    nat_04___bi_id,
+    nat_05___bi_len,
+    nat_06___bi_locals,
+    nat_07___bi_ord,
+    nat_08___bi_range,
+    nat_09___bi_sum,
+    nat_10___bi_type,
+    nat_11___bi_Co,
+    nat_12___bi___init__,
+    nat_13___bi_send,
+    nat_14___bi_ismain,
+    nat_15_dict_clear,
+    nat_16_dict_keys,
+    nat_17_dict_values,
+    nat_18_dict_update,
+    nat_19_list_append,
+    nat_20_list_index,
+    nat_21_list_insert,
+    nat_22_list_pop,
+    nat_23_list_remove,
+    nat_24_string_atoi,
+    nat_25_string_count,
+    nat_26_string_find,
+    nat_27_sys_exit,
+    nat_28_sys_gc,
+    nat_29_sys_getb,
+    nat_30_sys_heap,
+    nat_31_sys_putb,
+    nat_32_sys_runInThread,
+    nat_33_sys_time,
+    nat_34_ipm__getImg,
+    nat_35_ipm_x04,
+};