python-on-a-chip online compiler

Dependencies:   mbed TSI

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers obj.c Source File

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 */