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.
obj.c
00001 /* 00002 # This file is Copyright 2003, 2006, 2007, 2009 Dean Hall. 00003 # 00004 # This file is part of the PyMite VM. 00005 # The PyMite VM is free software: you can redistribute it and/or modify 00006 # it under the terms of the GNU GENERAL PUBLIC LICENSE Version 2. 00007 # 00008 # The PyMite VM is distributed in the hope that it will be useful, 00009 # but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00011 # A copy of the GNU GENERAL PUBLIC LICENSE Version 2 00012 # is seen in the file COPYING in this directory. 00013 */ 00014 00015 00016 #undef __FILE_ID__ 00017 #define __FILE_ID__ 0x0F 00018 00019 00020 /** 00021 * \file 00022 * \brief Object Type 00023 * 00024 * Object type operations. 00025 */ 00026 00027 00028 #include "pm.h" 00029 00030 00031 PmReturn_t 00032 obj_loadFromImg(PmMemSpace_t memspace, 00033 uint8_t const **paddr, pPmObj_t *r_pobj) 00034 { 00035 PmReturn_t retval = PM_RET_OK; 00036 PmObj_t obj; 00037 00038 00039 /* Get the object descriptor */ 00040 obj.od = (PmObjDesc_t)0x0000; 00041 OBJ_SET_TYPE(&obj, mem_getByte(memspace, paddr)); 00042 00043 switch (OBJ_GET_TYPE(&obj)) 00044 { 00045 case OBJ_TYPE_NON: 00046 /* If it's the None object, return global None */ 00047 *r_pobj = PM_NONE; 00048 break; 00049 00050 case OBJ_TYPE_INT: 00051 /* Read an integer and create an integer object with the value */ 00052 retval = int_new(mem_getInt(memspace, paddr), r_pobj); 00053 break; 00054 00055 #ifdef HAVE_FLOAT 00056 case OBJ_TYPE_FLT: 00057 /* Read a float and create an float object with the value */ 00058 retval = float_new(mem_getFloat(memspace, paddr), r_pobj); 00059 break; 00060 #endif /* HAVE_FLOAT */ 00061 00062 case OBJ_TYPE_STR: 00063 retval = string_loadFromImg(memspace, paddr, r_pobj); 00064 break; 00065 00066 case OBJ_TYPE_TUP: 00067 retval = tuple_loadFromImg(memspace, paddr, r_pobj); 00068 break; 00069 00070 case OBJ_TYPE_NIM: 00071 /* If it's a native code img, load into a code obj */ 00072 retval = no_loadFromImg(memspace, paddr, r_pobj); 00073 break; 00074 00075 case OBJ_TYPE_CIM: 00076 /* If it's a code img, load into a code obj */ 00077 retval = co_loadFromImg(memspace, paddr, r_pobj); 00078 break; 00079 00080 default: 00081 /* All other types should not be in an img obj */ 00082 PM_RAISE(retval, PM_RET_EX_SYS); 00083 break; 00084 } 00085 return retval; 00086 } 00087 00088 00089 PmReturn_t 00090 obj_loadFromImgObj(pPmObj_t pimg, pPmObj_t *r_pobj) 00091 { 00092 uint8_t const *imgaddr; 00093 PmReturn_t retval; 00094 00095 C_ASSERT(OBJ_GET_TYPE(pimg) == OBJ_TYPE_CIO); 00096 imgaddr = (uint8_t const *)&(((pPmCodeImgObj_t)pimg)->val); 00097 00098 retval = obj_loadFromImg(MEMSPACE_RAM, &imgaddr, r_pobj); 00099 C_ASSERT(OBJ_GET_TYPE(*r_pobj) == OBJ_TYPE_COB); 00100 00101 /* The CO must reference the top of the code img obj */ 00102 ((pPmCo_t)*r_pobj)->co_codeimgaddr = (uint8_t const *)pimg; 00103 00104 return retval; 00105 } 00106 00107 00108 /* Returns true if the obj is false */ 00109 int8_t 00110 obj_isFalse(pPmObj_t pobj) 00111 { 00112 C_ASSERT(pobj != C_NULL); 00113 00114 switch (OBJ_GET_TYPE(pobj)) 00115 { 00116 case OBJ_TYPE_NON: 00117 /* None evaluates to false, so return true */ 00118 return C_TRUE; 00119 00120 case OBJ_TYPE_INT: 00121 /* Only the integer zero is false */ 00122 return ((pPmInt_t)pobj)->val == 0; 00123 00124 #ifdef HAVE_FLOAT 00125 case OBJ_TYPE_FLT: 00126 /* The floats 0.0 and -0.0 are false */ 00127 return (((pPmFloat_t) pobj)->val == 0.0) 00128 || (((pPmFloat_t) pobj)->val == -0.0); 00129 #endif /* HAVE_FLOAT */ 00130 00131 case OBJ_TYPE_STR: 00132 /* An empty string is false */ 00133 return ((pPmString_t)pobj)->length == 0; 00134 00135 case OBJ_TYPE_TUP: 00136 /* An empty tuple is false */ 00137 return ((pPmTuple_t)pobj)->length == 0; 00138 00139 case OBJ_TYPE_LST: 00140 /* An empty list is false */ 00141 return ((pPmList_t)pobj)->length == 0; 00142 00143 case OBJ_TYPE_DIC: 00144 /* An empty dict is false */ 00145 return ((pPmDict_t)pobj)->length == 0; 00146 00147 case OBJ_TYPE_BOOL: 00148 /* C int zero means false */ 00149 return ((pPmBoolean_t) pobj)->val == 0; 00150 00151 default: 00152 /* 00153 * The following types are always not false: 00154 * CodeObj, Function, Module, Class, ClassInstance. 00155 */ 00156 return C_FALSE; 00157 } 00158 } 00159 00160 00161 /* Returns true if the item is in the container object */ 00162 PmReturn_t 00163 obj_isIn(pPmObj_t pobj, pPmObj_t pitem) 00164 { 00165 PmReturn_t retval = PM_RET_NO; 00166 pPmObj_t ptestItem; 00167 int16_t i; 00168 uint8_t c; 00169 00170 switch (OBJ_GET_TYPE(pobj)) 00171 { 00172 case OBJ_TYPE_TUP: 00173 /* Iterate over tuple to find item */ 00174 for (i = 0; i < ((pPmTuple_t)pobj)->length; i++) 00175 { 00176 PM_RETURN_IF_ERROR(tuple_getItem(pobj, i, &ptestItem)); 00177 00178 if (obj_compare(pitem, ptestItem) == C_SAME) 00179 { 00180 retval = PM_RET_OK; 00181 break; 00182 } 00183 } 00184 break; 00185 00186 case OBJ_TYPE_STR: 00187 /* Raise a TypeError if item is not a string */ 00188 if ((OBJ_GET_TYPE(pitem) != OBJ_TYPE_STR)) 00189 { 00190 retval = PM_RET_EX_TYPE; 00191 break; 00192 } 00193 00194 /* Empty string is alway present */ 00195 if (((pPmString_t)pitem)->length == 0) 00196 { 00197 retval = PM_RET_OK; 00198 break; 00199 } 00200 00201 /* Raise a ValueError if the string is more than 1 char */ 00202 else if (((pPmString_t)pitem)->length != 1) 00203 { 00204 retval = PM_RET_EX_VAL; 00205 break; 00206 } 00207 00208 /* Iterate over string to find char */ 00209 c = ((pPmString_t)pitem)->val[0]; 00210 for (i = 0; i < ((pPmString_t)pobj)->length; i++) 00211 { 00212 if (c == ((pPmString_t)pobj)->val[i]) 00213 { 00214 retval = PM_RET_OK; 00215 break; 00216 } 00217 } 00218 break; 00219 00220 case OBJ_TYPE_LST: 00221 /* Iterate over list to find item */ 00222 for (i = 0; i < ((pPmList_t)pobj)->length; i++) 00223 { 00224 PM_RETURN_IF_ERROR(list_getItem(pobj, i, &ptestItem)); 00225 00226 if (obj_compare(pitem, ptestItem) == C_SAME) 00227 { 00228 retval = PM_RET_OK; 00229 break; 00230 } 00231 } 00232 break; 00233 00234 case OBJ_TYPE_DIC: 00235 /* Check if the item is one of the keys of the dict */ 00236 retval = dict_getItem(pobj, pitem, &ptestItem); 00237 if (retval == PM_RET_EX_KEY) 00238 { 00239 retval = PM_RET_NO; 00240 } 00241 break; 00242 00243 default: 00244 retval = PM_RET_EX_TYPE; 00245 break; 00246 } 00247 00248 return retval; 00249 } 00250 00251 00252 int8_t 00253 obj_compare(pPmObj_t pobj1, pPmObj_t pobj2) 00254 { 00255 #ifdef HAVE_BYTEARRAY 00256 PmReturn_t retval; 00257 pPmObj_t pobj; 00258 #endif /* HAVE_BYTEARRAY */ 00259 00260 C_ASSERT(pobj1 != C_NULL); 00261 C_ASSERT(pobj2 != C_NULL); 00262 00263 /* Check if pointers are same */ 00264 if (pobj1 == pobj2) 00265 { 00266 return C_SAME; 00267 } 00268 00269 /* If types are different, objs must differ */ 00270 if (OBJ_GET_TYPE(pobj1) != OBJ_GET_TYPE(pobj2)) 00271 { 00272 return C_DIFFER; 00273 } 00274 00275 #ifdef HAVE_BYTEARRAY 00276 /* If object is an instance, get the thing it contains */ 00277 if (OBJ_GET_TYPE(pobj1) == OBJ_TYPE_CLI) 00278 { 00279 retval = dict_getItem((pPmObj_t)((pPmInstance_t)pobj1)->cli_attrs, 00280 PM_NONE, 00281 &pobj); 00282 PM_RETURN_IF_ERROR(retval); 00283 pobj1 = pobj; 00284 } 00285 if (OBJ_GET_TYPE(pobj2) == OBJ_TYPE_CLI) 00286 { 00287 retval = dict_getItem((pPmObj_t)((pPmInstance_t)pobj2)->cli_attrs, 00288 PM_NONE, 00289 &pobj); 00290 PM_RETURN_IF_ERROR(retval); 00291 pobj2 = pobj; 00292 } 00293 00294 /* If types are different, objs must differ */ 00295 if (OBJ_GET_TYPE(pobj1) != OBJ_GET_TYPE(pobj2)) 00296 { 00297 return C_DIFFER; 00298 } 00299 #endif /* HAVE_BYTEARRAY */ 00300 00301 /* Otherwise handle types individually */ 00302 switch (OBJ_GET_TYPE(pobj1)) 00303 { 00304 case OBJ_TYPE_NON: 00305 return C_SAME; 00306 00307 case OBJ_TYPE_INT: 00308 return ((pPmInt_t)pobj1)->val == 00309 ((pPmInt_t)pobj2)->val ? C_SAME : C_DIFFER; 00310 00311 #ifdef HAVE_FLOAT 00312 case OBJ_TYPE_FLT: 00313 { 00314 pPmObj_t r_pobj; 00315 00316 float_compare(pobj1, pobj2, &r_pobj, COMP_EQ); 00317 return (r_pobj == PM_TRUE) ? C_SAME : C_DIFFER; 00318 } 00319 #endif /* HAVE_FLOAT */ 00320 00321 case OBJ_TYPE_STR: 00322 return string_compare((pPmString_t)pobj1, (pPmString_t)pobj2); 00323 00324 case OBJ_TYPE_TUP: 00325 case OBJ_TYPE_LST: 00326 #ifdef HAVE_BYTEARRAY 00327 case OBJ_TYPE_BYA: 00328 #endif /* HAVE_BYTEARRAY */ 00329 return seq_compare(pobj1, pobj2); 00330 00331 case OBJ_TYPE_DIC: 00332 /* #17: PyMite does not support Dict comparisons (yet) */ 00333 default: 00334 break; 00335 } 00336 00337 /* All other types would need same pointer to be true */ 00338 return C_DIFFER; 00339 } 00340 00341 00342 #ifdef HAVE_PRINT 00343 PmReturn_t 00344 obj_print(pPmObj_t pobj, uint8_t marshallString) 00345 { 00346 PmReturn_t retval = PM_RET_OK; 00347 00348 C_ASSERT(pobj != C_NULL); 00349 00350 switch (OBJ_GET_TYPE(pobj)) 00351 { 00352 case OBJ_TYPE_NON: 00353 if (marshallString) 00354 { 00355 plat_putByte('N'); 00356 plat_putByte('o'); 00357 plat_putByte('n'); 00358 retval = plat_putByte('e'); 00359 } 00360 break; 00361 case OBJ_TYPE_INT: 00362 retval = int_print(pobj); 00363 break; 00364 #ifdef HAVE_FLOAT 00365 case OBJ_TYPE_FLT: 00366 retval = float_print(pobj); 00367 break; 00368 #endif /* HAVE_FLOAT */ 00369 case OBJ_TYPE_STR: 00370 retval = string_print(pobj, marshallString); 00371 break; 00372 case OBJ_TYPE_TUP: 00373 retval = tuple_print(pobj); 00374 break; 00375 case OBJ_TYPE_LST: 00376 retval = list_print(pobj); 00377 break; 00378 case OBJ_TYPE_DIC: 00379 retval = dict_print(pobj); 00380 break; 00381 case OBJ_TYPE_BOOL: 00382 if (((pPmBoolean_t) pobj)->val == C_TRUE) 00383 { 00384 plat_putByte('T'); 00385 plat_putByte('r'); 00386 plat_putByte('u'); 00387 } 00388 else 00389 { 00390 plat_putByte('F'); 00391 plat_putByte('a'); 00392 plat_putByte('l'); 00393 plat_putByte('s'); 00394 } 00395 retval = plat_putByte('e'); 00396 break; 00397 00398 case OBJ_TYPE_CLI: 00399 #ifdef HAVE_BYTEARRAY 00400 { 00401 pPmObj_t pobj2; 00402 00403 retval = dict_getItem((pPmObj_t)((pPmInstance_t)pobj)->cli_attrs, 00404 PM_NONE, 00405 (pPmObj_t *)&pobj2); 00406 if ((retval == PM_RET_OK) 00407 && (OBJ_GET_TYPE(pobj2) == OBJ_TYPE_BYA)) 00408 { 00409 retval = bytearray_print(pobj2); 00410 break; 00411 } 00412 } 00413 #endif /* HAVE_BYTEARRAY */ 00414 00415 case OBJ_TYPE_COB: 00416 case OBJ_TYPE_MOD: 00417 case OBJ_TYPE_CLO: 00418 case OBJ_TYPE_FXN: 00419 case OBJ_TYPE_CIM: 00420 case OBJ_TYPE_NIM: 00421 case OBJ_TYPE_NOB: 00422 case OBJ_TYPE_THR: 00423 case OBJ_TYPE_CIO: 00424 case OBJ_TYPE_MTH: 00425 case OBJ_TYPE_SQI: 00426 if (marshallString) 00427 { 00428 retval = plat_putByte('\''); 00429 PM_RETURN_IF_ERROR(retval); 00430 } 00431 plat_putByte('<'); 00432 plat_putByte('o'); 00433 plat_putByte('b'); 00434 plat_putByte('j'); 00435 plat_putByte(' '); 00436 plat_putByte('t'); 00437 plat_putByte('y'); 00438 plat_putByte('p'); 00439 plat_putByte('e'); 00440 plat_putByte(' '); 00441 plat_putByte('0'); 00442 plat_putByte('x'); 00443 int_printHexByte(OBJ_GET_TYPE(pobj)); 00444 plat_putByte(' '); 00445 plat_putByte('@'); 00446 plat_putByte(' '); 00447 plat_putByte('0'); 00448 plat_putByte('x'); 00449 _int_printHex((intptr_t)pobj); 00450 retval = plat_putByte('>'); 00451 if (marshallString) 00452 { 00453 retval = plat_putByte('\''); 00454 } 00455 break; 00456 00457 default: 00458 /* Otherwise raise a TypeError */ 00459 PM_RAISE(retval, PM_RET_EX_TYPE); 00460 break; 00461 } 00462 return retval; 00463 } 00464 #endif /* HAVE_PRINT */ 00465 00466 00467 #ifdef HAVE_BACKTICK 00468 PmReturn_t 00469 obj_repr(pPmObj_t pobj, pPmObj_t *r_pstr) 00470 { 00471 uint8_t tBuffer[32]; 00472 uint8_t bytesWritten = 0; 00473 PmReturn_t retval = PM_RET_OK; 00474 uint8_t const *pcstr = (uint8_t *)tBuffer;; 00475 00476 C_ASSERT(pobj != C_NULL); 00477 00478 switch (OBJ_GET_TYPE(pobj)) 00479 { 00480 case OBJ_TYPE_INT: 00481 bytesWritten = snprintf((char *)&tBuffer, sizeof(tBuffer), "%li", 00482 (long)((pPmInt_t)pobj)->val); 00483 retval = string_new(&pcstr, r_pstr); 00484 break; 00485 00486 #ifdef HAVE_FLOAT 00487 case OBJ_TYPE_FLT: 00488 bytesWritten = snprintf((char *)&tBuffer, sizeof(tBuffer), "%f", 00489 ((pPmFloat_t)pobj)->val); 00490 retval = string_new(&pcstr, r_pstr); 00491 break; 00492 #endif /* HAVE_FLOAT */ 00493 00494 default: 00495 /* Otherwise raise a TypeError */ 00496 PM_RAISE(retval, PM_RET_EX_TYPE); 00497 break; 00498 } 00499 00500 /* Sanity check */ 00501 C_ASSERT(bytesWritten < sizeof(tBuffer)); 00502 00503 return retval; 00504 } 00505 #endif /* HAVE_BACKTICK */
Generated on Tue Jul 12 2022 17:07:01 by
1.7.2