Norimasa Okamoto
/
pymite
python-on-a-chip online compiler
Embed:
(wiki syntax)
Show/hide line numbers
class.c
Go to the documentation of this file.
00001 /* 00002 # This file is Copyright 2009 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__ 0x18 00011 00012 00013 /** 00014 * \file 00015 * \brief Class Object Type 00016 * 00017 * Class object type operations. 00018 */ 00019 00020 00021 #include "pm.h" 00022 00023 00024 #ifdef HAVE_AUTOBOX 00025 static uint8_t const *liststr = (uint8_t const *)"list"; 00026 static uint8_t const *dictstr = (uint8_t const *)"dict"; 00027 static uint8_t const *stringstr = (uint8_t const *)"string"; 00028 static uint8_t const *autoboxstr = (uint8_t const *)"_Autobox"; 00029 static uint8_t const *objstr = (uint8_t const *)"obj"; 00030 #endif 00031 00032 00033 PmReturn_t 00034 class_new(pPmObj_t pattrs, pPmObj_t pbases, pPmObj_t pname, pPmObj_t *r_pclass) 00035 { 00036 PmReturn_t retval = PM_RET_OK; 00037 uint8_t *pchunk; 00038 pPmObj_t pobj; 00039 00040 /* Ensure types */ 00041 if ((OBJ_GET_TYPE(pattrs) != OBJ_TYPE_DIC) 00042 || (OBJ_GET_TYPE(pbases) != OBJ_TYPE_TUP) 00043 || (OBJ_GET_TYPE(pname) != OBJ_TYPE_STR)) 00044 { 00045 PM_RAISE(retval, PM_RET_EX_TYPE); 00046 return retval; 00047 } 00048 00049 /* Allocate a class obj */ 00050 retval = heap_getChunk(sizeof(PmClass_t), &pchunk); 00051 PM_RETURN_IF_ERROR(retval); 00052 pobj = (pPmObj_t)pchunk; 00053 OBJ_SET_TYPE(pobj, OBJ_TYPE_CLO); 00054 00055 /* Class has no access to its CO */ 00056 ((pPmClass_t)pobj)->cl_attrs = (pPmDict_t)pattrs; 00057 ((pPmClass_t)pobj)->cl_bases = (pPmTuple_t)pbases; 00058 00059 *r_pclass = pobj; 00060 00061 return retval; 00062 } 00063 00064 00065 /* Returns an instance of the class by reference */ 00066 PmReturn_t 00067 class_instantiate(pPmObj_t pclass, pPmObj_t *r_pobj) 00068 { 00069 PmReturn_t retval = PM_RET_OK; 00070 uint8_t *pchunk; 00071 pPmObj_t pobj; 00072 pPmObj_t pattrs; 00073 uint8_t objid; 00074 00075 /* Allocate a class instance */ 00076 retval = heap_getChunk(sizeof(PmInstance_t), &pchunk); 00077 PM_RETURN_IF_ERROR(retval); 00078 pobj = (pPmObj_t)pchunk; 00079 OBJ_SET_TYPE(pobj, OBJ_TYPE_CLI); 00080 00081 /* Set the instance's fields */ 00082 ((pPmInstance_t)pobj)->cli_class = (pPmClass_t)pclass; 00083 ((pPmInstance_t)pobj)->cli_attrs = C_NULL; 00084 00085 /* Create the attributes dict */ 00086 heap_gcPushTempRoot(pobj, &objid); 00087 retval = dict_new(&pattrs); 00088 heap_gcPopTempRoot(objid); 00089 ((pPmInstance_t)pobj)->cli_attrs = (pPmDict_t)pattrs; 00090 00091 /* TODO: Store pclass in __class__ attr */ 00092 00093 *r_pobj = pobj; 00094 return retval; 00095 } 00096 00097 00098 #ifdef HAVE_AUTOBOX 00099 PmReturn_t 00100 class_autobox(pPmObj_t *pobj) 00101 { 00102 PmReturn_t retval = PM_RET_OK; 00103 pPmObj_t pmodule, pstr, pclass, pwrapped, pmodcache; 00104 00105 uint8_t const *pliststr = liststr; 00106 uint8_t const *pdictstr = dictstr; 00107 uint8_t const *pstringstr = stringstr; 00108 00109 uint8_t const *pAutoboxstr = autoboxstr; 00110 uint8_t const *pobjstr = objstr; 00111 00112 /* Load the appropriate module name, 00113 * or do nothing if we have a non-boxable type 00114 */ 00115 if (OBJ_GET_TYPE(*pobj) == OBJ_TYPE_LST) { 00116 retval = string_new(&pliststr, &pstr); 00117 PM_RETURN_IF_ERROR(retval); 00118 } else if (OBJ_GET_TYPE(*pobj) == OBJ_TYPE_DIC) { 00119 retval = string_new(&pdictstr, &pstr); 00120 PM_RETURN_IF_ERROR(retval); 00121 } else if (OBJ_GET_TYPE(*pobj) == OBJ_TYPE_STR) { 00122 retval = string_new(&pstringstr, &pstr); 00123 PM_RETURN_IF_ERROR(retval); 00124 } else { 00125 return retval; 00126 } 00127 00128 /** first, try to get the module from the cache */ 00129 retval = dict_getItem(PM_PBUILTINS, PM_MD_STR, &pmodcache); 00130 PM_RETURN_IF_ERROR(retval); 00131 00132 retval = dict_getItem(pmodcache, pstr, &pmodule); 00133 PM_RETURN_IF_ERROR(retval); 00134 00135 if (!((retval == PM_RET_OK) && (OBJ_GET_TYPE(pmodule) == OBJ_TYPE_MOD))) 00136 { 00137 PM_RAISE(retval, PM_RET_EX_SYS); 00138 return retval; 00139 } 00140 00141 /* grab the class from within the loaded module */ 00142 retval = string_new(&pAutoboxstr, &pstr); 00143 PM_RETURN_IF_ERROR(retval); 00144 retval = dict_getItem((pPmObj_t) ((pPmFunc_t)pmodule)->f_attrs, pstr, &pclass); 00145 PM_RETURN_IF_ERROR(retval); 00146 00147 /* instantiate instance of (type)._Autobox */ 00148 retval = class_instantiate(pclass, &pwrapped); 00149 PM_RETURN_IF_ERROR(retval); 00150 00151 /* store object as _Autobox().obj */ 00152 retval = string_new(&pobjstr, &pstr); 00153 PM_RETURN_IF_ERROR(retval); 00154 retval = dict_setItem((pPmObj_t)((pPmInstance_t)pwrapped)->cli_attrs, 00155 pstr, *pobj); 00156 PM_RETURN_IF_ERROR(retval); 00157 00158 /** replace old object with new instance in place */ 00159 *pobj = pwrapped; 00160 00161 return retval; 00162 } 00163 #endif 00164 00165 00166 PmReturn_t 00167 class_method(pPmObj_t pinstance, pPmObj_t pfunc, pPmObj_t *r_pmeth) 00168 { 00169 PmReturn_t retval = PM_RET_OK; 00170 uint8_t *pchunk; 00171 pPmMethod_t pmeth; 00172 pPmObj_t pattrs; 00173 uint8_t objid; 00174 00175 /* Allocate a method */ 00176 retval = heap_getChunk(sizeof(PmMethod_t), &pchunk); 00177 PM_RETURN_IF_ERROR(retval); 00178 OBJ_SET_TYPE(pchunk, OBJ_TYPE_MTH); 00179 00180 /* Set method fields */ 00181 pmeth = (pPmMethod_t)pchunk; 00182 pmeth->m_instance = (pPmInstance_t)pinstance; 00183 pmeth->m_func = (pPmFunc_t)pfunc; 00184 pmeth->m_attrs = C_NULL; 00185 00186 /* Create the attributes dict */ 00187 heap_gcPushTempRoot((pPmObj_t)pmeth, &objid); 00188 retval = dict_new(&pattrs); 00189 heap_gcPopTempRoot(objid); 00190 pmeth->m_attrs = (pPmDict_t)pattrs; 00191 00192 *r_pmeth = (pPmObj_t)pmeth; 00193 return retval; 00194 } 00195 00196 00197 PmReturn_t 00198 class_getAttr(pPmObj_t pobj, pPmObj_t pname, pPmObj_t *r_pobj) 00199 { 00200 PmReturn_t retval; 00201 uint16_t i; 00202 pPmObj_t pparent; 00203 00204 /* If the given obj is an instance, check its attrs */ 00205 if (OBJ_GET_TYPE(pobj) == OBJ_TYPE_CLI) 00206 { 00207 retval = dict_getItem((pPmObj_t)((pPmInstance_t)pobj)->cli_attrs, pname, 00208 r_pobj); 00209 if (retval == PM_RET_OK) 00210 { 00211 return retval; 00212 } 00213 00214 /* Otherwise, check the instance's class */ 00215 pobj = (pPmObj_t)((pPmInstance_t)pobj)->cli_class; 00216 } 00217 00218 C_ASSERT(OBJ_GET_TYPE(pobj) == OBJ_TYPE_CLO); 00219 00220 retval = dict_getItem((pPmObj_t)((pPmClass_t)pobj)->cl_attrs, pname, 00221 r_pobj); 00222 00223 /* If attr is not found, search parent(s) */ 00224 if ((retval == PM_RET_EX_KEY) && (((pPmClass_t)pobj)->cl_bases != C_NULL)) 00225 { 00226 for (i = 0; i < ((pPmClass_t)pobj)->cl_bases->length; i++) 00227 { 00228 pparent = ((pPmClass_t)pobj)->cl_bases->val[i]; 00229 retval = class_getAttr(pparent, pname, r_pobj); 00230 if (retval == PM_RET_OK) 00231 { 00232 break; 00233 } 00234 } 00235 } 00236 00237 return retval; 00238 } 00239 00240 00241 uint8_t /* boolean */ 00242 class_isSubclass(pPmObj_t ptest_class, pPmObj_t pbase_class) 00243 { 00244 uint8_t i; 00245 uint8_t retval; 00246 00247 retval = C_FALSE; 00248 00249 if (ptest_class == pbase_class) 00250 { 00251 return C_TRUE; 00252 } 00253 00254 /* Recursively check if test class has a matching base class */ 00255 if (((pPmClass_t)ptest_class)->cl_bases != C_NULL) 00256 { 00257 for (i = 0; i < ((pPmClass_t)ptest_class)->cl_bases->length; i++) 00258 { 00259 retval = class_isSubclass(((pPmClass_t)ptest_class)->cl_bases->val[i], 00260 pbase_class); 00261 if (retval) 00262 { 00263 break; 00264 } 00265 } 00266 } 00267 return retval; 00268 }
Generated on Tue Jul 12 2022 23:13:47 by 1.7.2