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 # 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 00020 /** 00021 * \file 00022 * \brief Class Object Type 00023 * 00024 * Class object type operations. 00025 */ 00026 00027 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 00072 /* Allocate a class instance */ 00073 retval = heap_getChunk(sizeof(PmInstance_t), &pchunk); 00074 PM_RETURN_IF_ERROR(retval); 00075 pobj = (pPmObj_t)pchunk; 00076 OBJ_SET_TYPE(pobj, OBJ_TYPE_CLI); 00077 00078 /* Set the instance's class */ 00079 ((pPmInstance_t)pobj)->cli_class = (pPmClass_t)pclass; 00080 00081 /* Create the attributes dict */ 00082 retval = dict_new(&pattrs); 00083 ((pPmInstance_t)pobj)->cli_attrs = (pPmDict_t)pattrs; 00084 00085 /* TODO: Store pclass in __class__ attr */ 00086 00087 *r_pobj = pobj; 00088 return retval; 00089 } 00090 00091 00092 PmReturn_t 00093 class_method(pPmObj_t pinstance, pPmObj_t pfunc, pPmObj_t *r_pmeth) 00094 { 00095 PmReturn_t retval = PM_RET_OK; 00096 uint8_t *pchunk; 00097 pPmMethod_t pmeth; 00098 pPmObj_t pattrs; 00099 00100 /* Allocate a method */ 00101 retval = heap_getChunk(sizeof(PmMethod_t), &pchunk); 00102 PM_RETURN_IF_ERROR(retval); 00103 OBJ_SET_TYPE(pchunk, OBJ_TYPE_MTH); 00104 00105 /* Set method fields */ 00106 pmeth = (pPmMethod_t)pchunk; 00107 pmeth->m_instance = (pPmInstance_t)pinstance; 00108 pmeth->m_func = (pPmFunc_t)pfunc; 00109 00110 /* Create the attributes dict */ 00111 retval = dict_new(&pattrs); 00112 pmeth->m_attrs = (pPmDict_t)pattrs; 00113 00114 *r_pmeth = (pPmObj_t)pmeth; 00115 return retval; 00116 } 00117 00118 00119 PmReturn_t 00120 class_getAttr(pPmObj_t pobj, pPmObj_t pname, pPmObj_t *r_pobj) 00121 { 00122 PmReturn_t retval; 00123 uint16_t i; 00124 pPmObj_t pparent; 00125 00126 /* If the given obj is an instance, check its attrs */ 00127 if (OBJ_GET_TYPE(pobj) == OBJ_TYPE_CLI) 00128 { 00129 retval = dict_getItem((pPmObj_t)((pPmInstance_t)pobj)->cli_attrs, pname, 00130 r_pobj); 00131 if (retval == PM_RET_OK) 00132 { 00133 return retval; 00134 } 00135 00136 /* Otherwise, check the instance's class */ 00137 pobj = (pPmObj_t)((pPmInstance_t)pobj)->cli_class; 00138 } 00139 00140 C_ASSERT(OBJ_GET_TYPE(pobj) == OBJ_TYPE_CLO); 00141 00142 retval = dict_getItem((pPmObj_t)((pPmClass_t)pobj)->cl_attrs, pname, 00143 r_pobj); 00144 00145 /* If attr is not found, search parent(s) */ 00146 if ((retval == PM_RET_EX_KEY) && (((pPmClass_t)pobj)->cl_bases != C_NULL)) 00147 { 00148 for (i = 0; i < ((pPmClass_t)pobj)->cl_bases->length; i++) 00149 { 00150 pparent = ((pPmClass_t)pobj)->cl_bases->val[i]; 00151 retval = class_getAttr(pparent, pname, r_pobj); 00152 if (retval == PM_RET_OK) 00153 { 00154 break; 00155 } 00156 } 00157 } 00158 00159 return retval; 00160 } 00161 00162 00163 uint8_t /* boolean */ 00164 class_isSubclass(pPmObj_t ptest_class, pPmObj_t pbase_class) 00165 { 00166 uint8_t i; 00167 uint8_t retval; 00168 00169 retval = C_FALSE; 00170 00171 if (ptest_class == pbase_class) 00172 { 00173 return C_TRUE; 00174 } 00175 00176 /* Recursively check if test class has a matching base class */ 00177 if (((pPmClass_t)ptest_class)->cl_bases != C_NULL) 00178 { 00179 for (i = 0; i < ((pPmClass_t)ptest_class)->cl_bases->length; i++) 00180 { 00181 retval = class_isSubclass(((pPmClass_t)ptest_class)->cl_bases->val[i], 00182 pbase_class); 00183 if (retval) 00184 { 00185 break; 00186 } 00187 } 00188 } 00189 return retval; 00190 }
Generated on Tue Jul 12 2022 17:07:01 by
1.7.2