obj.c

Go to the documentation of this file.
00001 /*
00002 # This file is Copyright 2003, 2006, 2007, 2009, 2010 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 
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     /* All COs must reference the top of the code img obj 
00102      * so the image is marked and prevented from being reclaimed */
00103     co_rSetCodeImgAddr((pPmCo_t)*r_pobj, (uint8_t const *)pimg);
00104 
00105     return retval;
00106 }
00107 
00108 
00109 /* Returns true if the obj is false */
00110 int8_t
00111 obj_isFalse(pPmObj_t pobj)
00112 {
00113     C_ASSERT(pobj != C_NULL);
00114 
00115     switch (OBJ_GET_TYPE(pobj))
00116     {
00117         case OBJ_TYPE_NON:
00118             /* None evaluates to false, so return true */
00119             return C_TRUE;
00120 
00121         case OBJ_TYPE_INT:
00122             /* Only the integer zero is false */
00123             return ((pPmInt_t)pobj)->val == 0;
00124 
00125 #ifdef HAVE_FLOAT
00126         case OBJ_TYPE_FLT:
00127             /* The floats 0.0 and -0.0 are false */
00128             return (((pPmFloat_t) pobj)->val == 0.0)
00129                 || (((pPmFloat_t) pobj)->val == -0.0);
00130 #endif /* HAVE_FLOAT */
00131 
00132         case OBJ_TYPE_STR:
00133             /* An empty string is false */
00134             return ((pPmString_t)pobj)->length == 0;
00135 
00136         case OBJ_TYPE_TUP:
00137             /* An empty tuple is false */
00138             return ((pPmTuple_t)pobj)->length == 0;
00139 
00140         case OBJ_TYPE_LST:
00141             /* An empty list is false */
00142             return ((pPmList_t)pobj)->length == 0;
00143 
00144         case OBJ_TYPE_DIC:
00145             /* An empty dict is false */
00146             return ((pPmDict_t)pobj)->length == 0;
00147 
00148         case OBJ_TYPE_BOOL:
00149             /* C int zero means false */
00150             return ((pPmBoolean_t) pobj)->val == 0;
00151 
00152         default:
00153             /*
00154              * The following types are always not false:
00155              * CodeObj, Function, Module, Class, ClassInstance.
00156              */
00157             return C_FALSE;
00158     }
00159 }
00160 
00161 
00162 /* Returns true if the item is in the container object */
00163 PmReturn_t
00164 obj_isIn(pPmObj_t pobj, pPmObj_t pitem)
00165 {
00166     PmReturn_t retval = PM_RET_NO;
00167     pPmObj_t ptestItem;
00168     int16_t i;
00169     uint8_t c;
00170 
00171     switch (OBJ_GET_TYPE(pobj))
00172     {
00173         case OBJ_TYPE_TUP:
00174             /* Iterate over tuple to find item */
00175             for (i = 0; i < ((pPmTuple_t)pobj)->length; i++)
00176             {
00177                 PM_RETURN_IF_ERROR(tuple_getItem(pobj, i, &ptestItem));
00178 
00179                 if (obj_compare(pitem, ptestItem) == C_SAME)
00180                 {
00181                     retval = PM_RET_OK;
00182                     break;
00183                 }
00184             }
00185             break;
00186 
00187         case OBJ_TYPE_STR:
00188             /* Raise a TypeError if item is not a string */
00189             if ((OBJ_GET_TYPE(pitem) != OBJ_TYPE_STR))
00190             {
00191                 retval = PM_RET_EX_TYPE;
00192                 break;
00193             }
00194 
00195             /* Empty string is alway present */
00196             if (((pPmString_t)pitem)->length == 0)
00197             {
00198                 retval = PM_RET_OK;
00199                 break;
00200             }
00201 
00202             /* Raise a ValueError if the string is more than 1 char */
00203             else if (((pPmString_t)pitem)->length != 1)
00204             {
00205                 retval = PM_RET_EX_VAL;
00206                 break;
00207             }
00208 
00209             /* Iterate over string to find char */
00210             c = ((pPmString_t)pitem)->val[0];
00211             for (i = 0; i < ((pPmString_t)pobj)->length; i++)
00212             {
00213                 if (c == ((pPmString_t)pobj)->val[i])
00214                 {
00215                     retval = PM_RET_OK;
00216                     break;
00217                 }
00218             }
00219             break;
00220 
00221         case OBJ_TYPE_LST:
00222             /* Iterate over list to find item */
00223             for (i = 0; i < ((pPmList_t)pobj)->length; i++)
00224             {
00225                 PM_RETURN_IF_ERROR(list_getItem(pobj, i, &ptestItem));
00226 
00227                 if (obj_compare(pitem, ptestItem) == C_SAME)
00228                 {
00229                     retval = PM_RET_OK;
00230                     break;
00231                 }
00232             }
00233             break;
00234 
00235         case OBJ_TYPE_DIC:
00236             /* Check if the item is one of the keys of the dict */
00237             retval = dict_getItem(pobj, pitem, &ptestItem);
00238             if (retval == PM_RET_EX_KEY)
00239             {
00240                 retval = PM_RET_NO;
00241             }
00242             break;
00243 
00244         default:
00245             retval = PM_RET_EX_TYPE;
00246             break;
00247     }
00248 
00249     return retval;
00250 }
00251 
00252 
00253 int8_t
00254 obj_compare(pPmObj_t pobj1, pPmObj_t pobj2)
00255 {
00256 #ifdef HAVE_BYTEARRAY
00257     PmReturn_t retval;
00258     pPmObj_t pobj;
00259 #endif /* HAVE_BYTEARRAY */
00260 
00261     C_ASSERT(pobj1 != C_NULL);
00262     C_ASSERT(pobj2 != C_NULL);
00263 
00264     /* Check if pointers are same */
00265     if (pobj1 == pobj2)
00266     {
00267         return C_SAME;
00268     }
00269 
00270     /* If types are different, objs must differ */
00271     if (OBJ_GET_TYPE(pobj1) != OBJ_GET_TYPE(pobj2))
00272     {
00273         return C_DIFFER;
00274     }
00275 
00276 #ifdef HAVE_BYTEARRAY
00277     /* If object is an instance, get the thing it contains */
00278     if (OBJ_GET_TYPE(pobj1) == OBJ_TYPE_CLI)
00279     {
00280         retval = dict_getItem((pPmObj_t)((pPmInstance_t)pobj1)->cli_attrs,
00281                               PM_NONE,
00282                               &pobj);
00283         PM_RETURN_IF_ERROR(retval);
00284         pobj1 = pobj;
00285     }
00286     if (OBJ_GET_TYPE(pobj2) == OBJ_TYPE_CLI)
00287     {
00288         retval = dict_getItem((pPmObj_t)((pPmInstance_t)pobj2)->cli_attrs,
00289                               PM_NONE,
00290                               &pobj);
00291         PM_RETURN_IF_ERROR(retval);
00292         pobj2 = pobj;
00293     }
00294 
00295     /* If types are different, objs must differ */
00296     if (OBJ_GET_TYPE(pobj1) != OBJ_GET_TYPE(pobj2))
00297     {
00298         return C_DIFFER;
00299     }
00300 #endif /* HAVE_BYTEARRAY */
00301 
00302     /* Otherwise handle types individually */
00303     switch (OBJ_GET_TYPE(pobj1))
00304     {
00305         case OBJ_TYPE_NON:
00306             return C_SAME;
00307 
00308         case OBJ_TYPE_INT:
00309             return ((pPmInt_t)pobj1)->val ==
00310                 ((pPmInt_t)pobj2)->val ? C_SAME : C_DIFFER;
00311 
00312 #ifdef HAVE_FLOAT
00313         case OBJ_TYPE_FLT:
00314         {
00315             pPmObj_t r_pobj;
00316 
00317             float_compare(pobj1, pobj2, &r_pobj, COMP_EQ);
00318             return (r_pobj == PM_TRUE) ? C_SAME : C_DIFFER;
00319         }
00320 #endif /* HAVE_FLOAT */
00321 
00322         case OBJ_TYPE_STR:
00323             return string_compare((pPmString_t)pobj1, (pPmString_t)pobj2);
00324 
00325         case OBJ_TYPE_TUP:
00326         case OBJ_TYPE_LST:
00327 #ifdef HAVE_BYTEARRAY
00328         case OBJ_TYPE_BYA:
00329 #endif /* HAVE_BYTEARRAY */
00330             return seq_compare(pobj1, pobj2);
00331 
00332         case OBJ_TYPE_DIC:
00333             /* #17: PyMite does not support Dict comparisons (yet) */
00334         default:
00335             break;
00336     }
00337 
00338     /* All other types would need same pointer to be true */
00339     return C_DIFFER;
00340 }
00341 
00342 
00343 #ifdef HAVE_PRINT
00344 PmReturn_t
00345 obj_print(pPmObj_t pobj, uint8_t is_expr_repr, uint8_t is_nested)
00346 {
00347     PmReturn_t retval = PM_RET_OK;
00348 
00349     C_ASSERT(pobj != C_NULL);
00350 
00351     /* Something gets printed unless it's None in an unnested expression */
00352     if (!((OBJ_GET_TYPE(pobj) == OBJ_TYPE_NON) && is_expr_repr && !is_nested))
00353     {
00354         gVmGlobal.somethingPrinted = C_TRUE;
00355     }
00356 
00357     switch (OBJ_GET_TYPE(pobj))
00358     {
00359         case OBJ_TYPE_NON:
00360             if (!is_expr_repr || is_nested)
00361             {
00362                 plat_putByte('N');
00363                 plat_putByte('o');
00364                 plat_putByte('n');
00365                 retval = plat_putByte('e');
00366             }
00367             break;
00368         case OBJ_TYPE_INT:
00369             retval = int_print(pobj);
00370             break;
00371 #ifdef HAVE_FLOAT
00372         case OBJ_TYPE_FLT:
00373             retval = float_print(pobj);
00374             break;
00375 #endif /* HAVE_FLOAT */
00376         case OBJ_TYPE_STR:
00377             retval = string_print(pobj, (is_expr_repr || is_nested));
00378             break;
00379         case OBJ_TYPE_TUP:
00380             retval = tuple_print(pobj);
00381             break;
00382         case OBJ_TYPE_LST:
00383             retval = list_print(pobj);
00384             break;
00385         case OBJ_TYPE_DIC:
00386             retval = dict_print(pobj);
00387             break;
00388         case OBJ_TYPE_BOOL:
00389             if (((pPmBoolean_t) pobj)->val == C_TRUE)
00390             {
00391                 plat_putByte('T');
00392                 plat_putByte('r');
00393                 plat_putByte('u');
00394             }
00395             else
00396             {
00397                 plat_putByte('F');
00398                 plat_putByte('a');
00399                 plat_putByte('l');
00400                 plat_putByte('s');
00401             }
00402             retval = plat_putByte('e');
00403             break;
00404 
00405         case OBJ_TYPE_CLI:
00406 #ifdef HAVE_BYTEARRAY
00407             {
00408                 pPmObj_t pobj2;
00409 
00410                 retval = dict_getItem((pPmObj_t)((pPmInstance_t)pobj)->cli_attrs,
00411                                       PM_NONE,
00412                                       (pPmObj_t *)&pobj2);
00413                 if ((retval == PM_RET_OK)
00414                     && (OBJ_GET_TYPE(pobj2) == OBJ_TYPE_BYA))
00415                 {
00416                     retval = bytearray_print(pobj2);
00417                     break;
00418                 }
00419             }
00420 #endif /* HAVE_BYTEARRAY */
00421 
00422         case OBJ_TYPE_COB:
00423         case OBJ_TYPE_MOD:
00424         case OBJ_TYPE_CLO:
00425         case OBJ_TYPE_FXN:
00426         case OBJ_TYPE_CIM:
00427         case OBJ_TYPE_NIM:
00428         case OBJ_TYPE_NOB:
00429         case OBJ_TYPE_THR:
00430         case OBJ_TYPE_CIO:
00431         case OBJ_TYPE_MTH:
00432         case OBJ_TYPE_SQI:
00433             plat_putByte('<');
00434             plat_putByte('o');
00435             plat_putByte('b');
00436             plat_putByte('j');
00437             plat_putByte(' ');
00438             plat_putByte('t');
00439             plat_putByte('y');
00440             plat_putByte('p');
00441             plat_putByte('e');
00442             plat_putByte(' ');
00443             plat_putByte('0');
00444             plat_putByte('x');
00445             int_printHexByte(OBJ_GET_TYPE(pobj));
00446             plat_putByte(' ');
00447             plat_putByte('@');
00448             plat_putByte(' ');
00449             plat_putByte('0');
00450             plat_putByte('x');
00451             _int_printHex((intptr_t)pobj);
00452             retval = plat_putByte('>');
00453             break;
00454 
00455         default:
00456             /* Otherwise raise a TypeError */
00457             PM_RAISE(retval, PM_RET_EX_TYPE);
00458             break;
00459     }
00460     return retval;
00461 }
00462 #endif /* HAVE_PRINT */
00463 
00464 
00465 #ifdef HAVE_BACKTICK
00466 PmReturn_t
00467 obj_repr(pPmObj_t pobj, pPmObj_t *r_pstr)
00468 {
00469     uint8_t tBuffer[32];
00470     uint8_t bytesWritten = 0;
00471     PmReturn_t retval = PM_RET_OK;
00472     uint8_t const *pcstr = (uint8_t *)tBuffer;;
00473 
00474     C_ASSERT(pobj != C_NULL);
00475 
00476     switch (OBJ_GET_TYPE(pobj))
00477     {
00478         case OBJ_TYPE_INT:
00479             bytesWritten = snprintf((char *)&tBuffer, sizeof(tBuffer), "%li",
00480                                     (long)((pPmInt_t)pobj)->val);
00481             retval = string_new(&pcstr, r_pstr);
00482             break;
00483 
00484 #ifdef HAVE_FLOAT
00485         case OBJ_TYPE_FLT:
00486             bytesWritten = snprintf((char *)&tBuffer, sizeof(tBuffer), "%f",
00487                                     ((pPmFloat_t)pobj)->val);
00488             retval = string_new(&pcstr, r_pstr);
00489             break;
00490 #endif /* HAVE_FLOAT */
00491 
00492         default:
00493             /* Otherwise raise a TypeError */
00494             PM_RAISE(retval, PM_RET_EX_TYPE);
00495             break;
00496     }
00497 
00498     /* Sanity check */
00499     C_ASSERT(bytesWritten < sizeof(tBuffer));
00500 
00501     return retval;
00502 }
00503 #endif /* HAVE_BACKTICK */

Generated on Mon Oct 18 07:40:48 2010 for Python-on-a-chip by  doxygen 1.5.9