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
vm/obj.c
- Committer:
- va009039
- Date:
- 2016-04-14
- Revision:
- 15:94ca5c8003e5
- Parent:
- 0:65f1469d6bfb
File content as of revision 15:94ca5c8003e5:
/* # 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 */