class.c

Go to the documentation of this file.
00001 /*
00002 # This file is Copyright 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__ 0x18
00018 
00019 
00028 #include "pm.h"
00029 
00030 
00031 PmReturn_t
00032 class_new(pPmObj_t pattrs, pPmObj_t pbases, pPmObj_t pname, pPmObj_t *r_pclass)
00033 {
00034     PmReturn_t retval = PM_RET_OK;
00035     uint8_t *pchunk;
00036     pPmObj_t pobj;
00037 
00038     /* Ensure types */
00039     if ((OBJ_GET_TYPE(pattrs) != OBJ_TYPE_DIC)
00040         || (OBJ_GET_TYPE(pbases) != OBJ_TYPE_TUP)
00041         || (OBJ_GET_TYPE(pname) != OBJ_TYPE_STR))
00042     {
00043         PM_RAISE(retval, PM_RET_EX_TYPE);
00044         return retval;
00045     }
00046 
00047     /* Allocate a class obj */
00048     retval = heap_getChunk(sizeof(PmClass_t), &pchunk);
00049     PM_RETURN_IF_ERROR(retval);
00050     pobj = (pPmObj_t)pchunk;
00051     OBJ_SET_TYPE(pobj, OBJ_TYPE_CLO);
00052 
00053     /* Class has no access to its CO */
00054     ((pPmClass_t)pobj)->cl_attrs = (pPmDict_t)pattrs;
00055     ((pPmClass_t)pobj)->cl_bases = (pPmTuple_t)pbases;
00056 
00057     *r_pclass = pobj;
00058 
00059     return retval;
00060 }
00061 
00062 
00063 /* Returns an instance of the class by reference */
00064 PmReturn_t
00065 class_instantiate(pPmObj_t pclass, pPmObj_t *r_pobj)
00066 {
00067     PmReturn_t retval = PM_RET_OK;
00068     uint8_t *pchunk;
00069     pPmObj_t pobj;
00070     pPmObj_t pattrs;
00071     uint8_t objid;
00072 
00073     /* Allocate a class instance */
00074     retval = heap_getChunk(sizeof(PmInstance_t), &pchunk);
00075     PM_RETURN_IF_ERROR(retval);
00076     pobj = (pPmObj_t)pchunk;
00077     OBJ_SET_TYPE(pobj, OBJ_TYPE_CLI);
00078 
00079     /* Set the instance's class */
00080     ((pPmInstance_t)pobj)->cli_class = (pPmClass_t)pclass;
00081 
00082     /* Create the attributes dict */
00083     heap_gcPushTempRoot(pobj, &objid);
00084     retval = dict_new(&pattrs);
00085     heap_gcPopTempRoot(objid);
00086     ((pPmInstance_t)pobj)->cli_attrs = (pPmDict_t)pattrs;
00087 
00088     /* TODO: Store pclass in __class__ attr */
00089 
00090     *r_pobj = pobj;
00091     return retval;
00092 }
00093 
00094 
00095 PmReturn_t
00096 class_method(pPmObj_t pinstance, pPmObj_t pfunc, pPmObj_t *r_pmeth)
00097 {
00098     PmReturn_t retval = PM_RET_OK;
00099     uint8_t *pchunk;
00100     pPmMethod_t pmeth;
00101     pPmObj_t pattrs;
00102     uint8_t objid;
00103 
00104     /* Allocate a method */
00105     retval = heap_getChunk(sizeof(PmMethod_t), &pchunk);
00106     PM_RETURN_IF_ERROR(retval);
00107     OBJ_SET_TYPE(pchunk, OBJ_TYPE_MTH);
00108 
00109     /* Set method fields */
00110     pmeth = (pPmMethod_t)pchunk;
00111     pmeth->m_instance = (pPmInstance_t)pinstance;
00112     pmeth->m_func = (pPmFunc_t)pfunc;
00113 
00114     /* Create the attributes dict */
00115     heap_gcPushTempRoot((pPmObj_t)pmeth, &objid);
00116     retval = dict_new(&pattrs);
00117     heap_gcPopTempRoot(objid);
00118     pmeth->m_attrs = (pPmDict_t)pattrs;
00119 
00120     *r_pmeth = (pPmObj_t)pmeth;
00121     return retval;
00122 }
00123 
00124 
00125 PmReturn_t
00126 class_getAttr(pPmObj_t pobj, pPmObj_t pname, pPmObj_t *r_pobj)
00127 {
00128     PmReturn_t retval;
00129     uint16_t i;
00130     pPmObj_t pparent;
00131 
00132     /* If the given obj is an instance, check its attrs */
00133     if (OBJ_GET_TYPE(pobj) == OBJ_TYPE_CLI)
00134     {
00135         retval = dict_getItem((pPmObj_t)((pPmInstance_t)pobj)->cli_attrs, pname,
00136                               r_pobj);
00137         if (retval == PM_RET_OK)
00138         {
00139             return retval;
00140         }
00141 
00142         /* Otherwise, check the instance's class */
00143         pobj = (pPmObj_t)((pPmInstance_t)pobj)->cli_class;
00144     }
00145 
00146     C_ASSERT(OBJ_GET_TYPE(pobj) == OBJ_TYPE_CLO);
00147 
00148     retval = dict_getItem((pPmObj_t)((pPmClass_t)pobj)->cl_attrs, pname,
00149                           r_pobj);
00150 
00151     /* If attr is not found, search parent(s) */
00152     if ((retval == PM_RET_EX_KEY) && (((pPmClass_t)pobj)->cl_bases != C_NULL))
00153     {
00154         for (i = 0; i < ((pPmClass_t)pobj)->cl_bases->length; i++)
00155         {
00156             pparent = ((pPmClass_t)pobj)->cl_bases->val[i];
00157             retval = class_getAttr(pparent, pname, r_pobj);
00158             if (retval == PM_RET_OK)
00159             {
00160                 break;
00161             }
00162         }
00163     }
00164 
00165     return retval;
00166 }
00167 
00168 
00169 uint8_t /* boolean */
00170 class_isSubclass(pPmObj_t ptest_class, pPmObj_t pbase_class)
00171 {
00172     uint8_t i;
00173     uint8_t retval;
00174 
00175     retval = C_FALSE;
00176 
00177     if (ptest_class == pbase_class)
00178     {
00179         return C_TRUE;
00180     }
00181 
00182     /* Recursively check if test class has a matching base class */
00183     if (((pPmClass_t)ptest_class)->cl_bases != C_NULL)
00184     {
00185         for (i = 0; i < ((pPmClass_t)ptest_class)->cl_bases->length; i++)
00186         {
00187             retval = class_isSubclass(((pPmClass_t)ptest_class)->cl_bases->val[i],
00188                                         pbase_class);
00189             if (retval)
00190             {
00191                 break;
00192             }
00193         }
00194     }
00195     return retval;
00196 }

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