Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Diff: src/vm/obj.c
- Revision:
- 0:14e5e829dffe
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/vm/obj.c Wed Jul 21 12:50:41 2010 +0000 @@ -0,0 +1,505 @@ +/* +# This file is Copyright 2003, 2006, 2007, 2009 Dean Hall. +# +# This file is part of the PyMite VM. +# The PyMite VM is free software: you can redistribute it and/or modify +# it under the terms of the GNU GENERAL PUBLIC LICENSE Version 2. +# +# The PyMite VM is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# A copy of the GNU GENERAL PUBLIC LICENSE Version 2 +# is seen in the file COPYING in this directory. +*/ + + +#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); + + /* The CO must reference the top of the code img obj */ + ((pPmCo_t)*r_pobj)->co_codeimgaddr = (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: + /* #17: PyMite does not support Dict comparisons (yet) */ + 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 marshallString) +{ + PmReturn_t retval = PM_RET_OK; + + C_ASSERT(pobj != C_NULL); + + switch (OBJ_GET_TYPE(pobj)) + { + case OBJ_TYPE_NON: + if (marshallString) + { + plat_putByte('N'); + plat_putByte('o'); + plat_putByte('n'); + retval = plat_putByte('e'); + } + 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, marshallString); + 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: + if (((pPmBoolean_t) pobj)->val == C_TRUE) + { + plat_putByte('T'); + plat_putByte('r'); + plat_putByte('u'); + } + else + { + plat_putByte('F'); + plat_putByte('a'); + plat_putByte('l'); + plat_putByte('s'); + } + retval = plat_putByte('e'); + 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: + if (marshallString) + { + retval = plat_putByte('\''); + PM_RETURN_IF_ERROR(retval); + } + plat_putByte('<'); + plat_putByte('o'); + plat_putByte('b'); + plat_putByte('j'); + plat_putByte(' '); + plat_putByte('t'); + plat_putByte('y'); + plat_putByte('p'); + plat_putByte('e'); + plat_putByte(' '); + plat_putByte('0'); + plat_putByte('x'); + int_printHexByte(OBJ_GET_TYPE(pobj)); + plat_putByte(' '); + plat_putByte('@'); + plat_putByte(' '); + plat_putByte('0'); + plat_putByte('x'); + _int_printHex((intptr_t)pobj); + retval = plat_putByte('>'); + if (marshallString) + { + 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]; + uint8_t bytesWritten = 0; + 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: + bytesWritten = snprintf((char *)&tBuffer, sizeof(tBuffer), "%li", + (long)((pPmInt_t)pobj)->val); + retval = string_new(&pcstr, r_pstr); + break; + +#ifdef HAVE_FLOAT + case OBJ_TYPE_FLT: + bytesWritten = snprintf((char *)&tBuffer, sizeof(tBuffer), "%f", + ((pPmFloat_t)pobj)->val); + retval = string_new(&pcstr, r_pstr); + break; +#endif /* HAVE_FLOAT */ + + default: + /* Otherwise raise a TypeError */ + PM_RAISE(retval, PM_RET_EX_TYPE); + break; + } + + /* Sanity check */ + C_ASSERT(bytesWritten < sizeof(tBuffer)); + + return retval; +} +#endif /* HAVE_BACKTICK */