Embed:
(wiki syntax)
Show/hide line numbers
obj.c
Go to the documentation of this file.
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