LP-89 - Port OP_15.05.01 fixes. Release notes:
[librepilot.git] / flight / libraries / PyMite / vm / class.c
blobeb526778ba61cd40a29b4a7158e0d34ecfe27379
1 /*
2 # This file is Copyright 2009, 2010 Dean Hall.
4 # This file is part of the PyMite VM.
5 # The PyMite VM is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU GENERAL PUBLIC LICENSE Version 2.
8 # The PyMite VM is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 # A copy of the GNU GENERAL PUBLIC LICENSE Version 2
12 # is seen in the file COPYING in this directory.
16 #undef __FILE_ID__
17 #define __FILE_ID__ 0x18
20 /**
21 * \file
22 * \brief Class Object Type
24 * Class object type operations.
28 #include "pm.h"
31 PmReturn_t
32 class_new(pPmObj_t pattrs, pPmObj_t pbases, pPmObj_t pname, pPmObj_t *r_pclass)
34 PmReturn_t retval = PM_RET_OK;
35 uint8_t *pchunk;
36 pPmObj_t pobj;
38 /* Ensure types */
39 if ((OBJ_GET_TYPE(pattrs) != OBJ_TYPE_DIC)
40 || (OBJ_GET_TYPE(pbases) != OBJ_TYPE_TUP)
41 || (OBJ_GET_TYPE(pname) != OBJ_TYPE_STR))
43 PM_RAISE(retval, PM_RET_EX_TYPE);
44 return retval;
47 /* Allocate a class obj */
48 retval = heap_getChunk(sizeof(PmClass_t), &pchunk);
49 PM_RETURN_IF_ERROR(retval);
50 pobj = (pPmObj_t)pchunk;
51 OBJ_SET_TYPE(pobj, OBJ_TYPE_CLO);
53 /* Class has no access to its CO */
54 ((pPmClass_t)pobj)->cl_attrs = (pPmDict_t)pattrs;
55 ((pPmClass_t)pobj)->cl_bases = (pPmTuple_t)pbases;
57 *r_pclass = pobj;
59 return retval;
63 /* Returns an instance of the class by reference */
64 PmReturn_t
65 class_instantiate(pPmObj_t pclass, pPmObj_t *r_pobj)
67 PmReturn_t retval = PM_RET_OK;
68 uint8_t *pchunk;
69 pPmObj_t pobj;
70 pPmObj_t pattrs;
71 uint8_t objid;
73 /* Allocate a class instance */
74 retval = heap_getChunk(sizeof(PmInstance_t), &pchunk);
75 PM_RETURN_IF_ERROR(retval);
76 pobj = (pPmObj_t)pchunk;
77 OBJ_SET_TYPE(pobj, OBJ_TYPE_CLI);
79 /* Set the instance's class */
80 ((pPmInstance_t)pobj)->cli_class = (pPmClass_t)pclass;
82 /* Create the attributes dict */
83 heap_gcPushTempRoot(pobj, &objid);
84 retval = dict_new(&pattrs);
85 heap_gcPopTempRoot(objid);
86 ((pPmInstance_t)pobj)->cli_attrs = (pPmDict_t)pattrs;
88 /* TODO: Store pclass in __class__ attr */
90 *r_pobj = pobj;
91 return retval;
95 PmReturn_t
96 class_method(pPmObj_t pinstance, pPmObj_t pfunc, pPmObj_t *r_pmeth)
98 PmReturn_t retval = PM_RET_OK;
99 uint8_t *pchunk;
100 pPmMethod_t pmeth;
101 pPmObj_t pattrs;
102 uint8_t objid;
104 /* Allocate a method */
105 retval = heap_getChunk(sizeof(PmMethod_t), &pchunk);
106 PM_RETURN_IF_ERROR(retval);
107 OBJ_SET_TYPE(pchunk, OBJ_TYPE_MTH);
109 /* Set method fields */
110 pmeth = (pPmMethod_t)pchunk;
111 pmeth->m_instance = (pPmInstance_t)pinstance;
112 pmeth->m_func = (pPmFunc_t)pfunc;
114 /* Create the attributes dict */
115 heap_gcPushTempRoot((pPmObj_t)pmeth, &objid);
116 retval = dict_new(&pattrs);
117 heap_gcPopTempRoot(objid);
118 pmeth->m_attrs = (pPmDict_t)pattrs;
120 *r_pmeth = (pPmObj_t)pmeth;
121 return retval;
125 PmReturn_t
126 class_getAttr(pPmObj_t pobj, pPmObj_t pname, pPmObj_t *r_pobj)
128 PmReturn_t retval;
129 uint16_t i;
130 pPmObj_t pparent;
132 /* If the given obj is an instance, check its attrs */
133 if (OBJ_GET_TYPE(pobj) == OBJ_TYPE_CLI)
135 retval = dict_getItem((pPmObj_t)((pPmInstance_t)pobj)->cli_attrs, pname,
136 r_pobj);
137 if (retval == PM_RET_OK)
139 return retval;
142 /* Otherwise, check the instance's class */
143 pobj = (pPmObj_t)((pPmInstance_t)pobj)->cli_class;
146 C_ASSERT(OBJ_GET_TYPE(pobj) == OBJ_TYPE_CLO);
148 retval = dict_getItem((pPmObj_t)((pPmClass_t)pobj)->cl_attrs, pname,
149 r_pobj);
151 /* If attr is not found, search parent(s) */
152 if ((retval == PM_RET_EX_KEY) && (((pPmClass_t)pobj)->cl_bases != C_NULL))
154 for (i = 0; i < ((pPmClass_t)pobj)->cl_bases->length; i++)
156 pparent = ((pPmClass_t)pobj)->cl_bases->val[i];
157 retval = class_getAttr(pparent, pname, r_pobj);
158 if (retval == PM_RET_OK)
160 break;
165 return retval;
169 uint8_t /* boolean */
170 class_isSubclass(pPmObj_t ptest_class, pPmObj_t pbase_class)
172 uint8_t i;
173 uint8_t retval;
175 retval = C_FALSE;
177 if (ptest_class == pbase_class)
179 return C_TRUE;
182 /* Recursively check if test class has a matching base class */
183 if (((pPmClass_t)ptest_class)->cl_bases != C_NULL)
185 for (i = 0; i < ((pPmClass_t)ptest_class)->cl_bases->length; i++)
187 retval = class_isSubclass(((pPmClass_t)ptest_class)->cl_bases->val[i],
188 pbase_class);
189 if (retval)
191 break;
195 return retval;