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.
17 #define __FILE_ID__ 0x18
22 * \brief Class Object Type
24 * Class object type operations.
32 class_new(pPmObj_t pattrs
, pPmObj_t pbases
, pPmObj_t pname
, pPmObj_t
*r_pclass
)
34 PmReturn_t retval
= PM_RET_OK
;
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
);
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
;
63 /* Returns an instance of the class by reference */
65 class_instantiate(pPmObj_t pclass
, pPmObj_t
*r_pobj
)
67 PmReturn_t retval
= PM_RET_OK
;
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 */
96 class_method(pPmObj_t pinstance
, pPmObj_t pfunc
, pPmObj_t
*r_pmeth
)
98 PmReturn_t retval
= PM_RET_OK
;
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
;
126 class_getAttr(pPmObj_t pobj
, pPmObj_t pname
, pPmObj_t
*r_pobj
)
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
,
137 if (retval
== PM_RET_OK
)
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
,
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
)
169 uint8_t /* boolean */
170 class_isSubclass(pPmObj_t ptest_class
, pPmObj_t pbase_class
)
177 if (ptest_class
== pbase_class
)
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
],