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: vm/obj.c
- 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 */