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