Norimasa Okamoto
/
pymite
python-on-a-chip online compiler
- http://pymbed.appspot.com/
- https://code.google.com/p/python-on-a-chip/
- http://www.youtube.com/watch?v=Oyqc2bFRW9I
- https://bitbucket.org/va009039/pymbed/
more info: python-on-a-chip
Diff: platform/mbed/pmstdlib_nat.cpp
- 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, +};