Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
class.c
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