Guido van Rossum | 8cfc4bf | 1995-01-18 23:45:01 +0000 | [diff] [blame] | 1 | from bgenOutput import * |
| 2 | from bgenGeneratorGroup import GeneratorGroup |
| 3 | |
| 4 | class ObjectDefinition(GeneratorGroup): |
Guido van Rossum | 01f5a81 | 1995-01-25 22:59:21 +0000 | [diff] [blame] | 5 | "Spit out code that together defines a new Python object type" |
Jack Jansen | 1319abf | 2001-06-28 22:07:30 +0000 | [diff] [blame] | 6 | basechain = "NULL" |
Guido van Rossum | 8cfc4bf | 1995-01-18 23:45:01 +0000 | [diff] [blame] | 7 | |
| 8 | def __init__(self, name, prefix, itselftype): |
Guido van Rossum | 01f5a81 | 1995-01-25 22:59:21 +0000 | [diff] [blame] | 9 | """ObjectDefinition constructor. May be extended, but do not override. |
| 10 | |
| 11 | - name: the object's official name, e.g. 'SndChannel'. |
| 12 | - prefix: the prefix used for the object's functions and data, e.g. 'SndCh'. |
| 13 | - itselftype: the C type actually contained in the object, e.g. 'SndChannelPtr'. |
| 14 | |
| 15 | XXX For official Python data types, rules for the 'Py' prefix are a problem. |
| 16 | """ |
| 17 | |
Guido van Rossum | 8cfc4bf | 1995-01-18 23:45:01 +0000 | [diff] [blame] | 18 | GeneratorGroup.__init__(self, prefix or name) |
| 19 | self.name = name |
| 20 | self.itselftype = itselftype |
| 21 | self.objecttype = name + 'Object' |
Guido van Rossum | 8d6c180 | 1995-01-18 23:46:59 +0000 | [diff] [blame] | 22 | self.typename = name + '_Type' |
| 23 | self.argref = "" # set to "*" if arg to <type>_New should be pointer |
Guido van Rossum | 01f5a81 | 1995-01-25 22:59:21 +0000 | [diff] [blame] | 24 | self.static = "static " # set to "" to make <type>_New and <type>_Convert public |
Jack Jansen | 5801a2d | 2001-12-09 23:25:00 +0000 | [diff] [blame] | 25 | self.modulename = None |
Guido van Rossum | 8cfc4bf | 1995-01-18 23:45:01 +0000 | [diff] [blame] | 26 | |
Jack Jansen | 27489d4 | 2000-12-12 22:24:35 +0000 | [diff] [blame] | 27 | def add(self, g, dupcheck=0): |
Guido van Rossum | 8cfc4bf | 1995-01-18 23:45:01 +0000 | [diff] [blame] | 28 | g.setselftype(self.objecttype, self.itselftype) |
Jack Jansen | 27489d4 | 2000-12-12 22:24:35 +0000 | [diff] [blame] | 29 | GeneratorGroup.add(self, g, dupcheck) |
Guido van Rossum | 8cfc4bf | 1995-01-18 23:45:01 +0000 | [diff] [blame] | 30 | |
| 31 | def reference(self): |
| 32 | # In case we are referenced from a module |
| 33 | pass |
Jack Jansen | 5801a2d | 2001-12-09 23:25:00 +0000 | [diff] [blame] | 34 | |
| 35 | def setmodulename(self, name): |
| 36 | self.modulename = name |
Guido van Rossum | 8cfc4bf | 1995-01-18 23:45:01 +0000 | [diff] [blame] | 37 | |
| 38 | def generate(self): |
| 39 | # XXX This should use long strings and %(varname)s substitution! |
| 40 | |
| 41 | OutHeader2("Object type " + self.name) |
| 42 | |
Guido van Rossum | 01f5a81 | 1995-01-25 22:59:21 +0000 | [diff] [blame] | 43 | sf = self.static and "staticforward " |
| 44 | Output("%sPyTypeObject %s;", sf, self.typename) |
Guido van Rossum | 8cfc4bf | 1995-01-18 23:45:01 +0000 | [diff] [blame] | 45 | Output() |
Guido van Rossum | 8d6c180 | 1995-01-18 23:46:59 +0000 | [diff] [blame] | 46 | Output("#define %s_Check(x) ((x)->ob_type == &%s)", |
| 47 | self.prefix, self.typename) |
Guido van Rossum | 8cfc4bf | 1995-01-18 23:45:01 +0000 | [diff] [blame] | 48 | Output() |
Guido van Rossum | 01f5a81 | 1995-01-25 22:59:21 +0000 | [diff] [blame] | 49 | Output("typedef struct %s {", self.objecttype) |
Guido van Rossum | 8cfc4bf | 1995-01-18 23:45:01 +0000 | [diff] [blame] | 50 | IndentLevel() |
Guido van Rossum | 8d6c180 | 1995-01-18 23:46:59 +0000 | [diff] [blame] | 51 | Output("PyObject_HEAD") |
Guido van Rossum | 01f5a81 | 1995-01-25 22:59:21 +0000 | [diff] [blame] | 52 | self.outputStructMembers() |
Guido van Rossum | 8cfc4bf | 1995-01-18 23:45:01 +0000 | [diff] [blame] | 53 | DedentLevel() |
| 54 | Output("} %s;", self.objecttype) |
Guido van Rossum | 8cfc4bf | 1995-01-18 23:45:01 +0000 | [diff] [blame] | 55 | |
Guido van Rossum | 8d6c180 | 1995-01-18 23:46:59 +0000 | [diff] [blame] | 56 | self.outputNew() |
| 57 | |
| 58 | self.outputConvert() |
Guido van Rossum | 8cfc4bf | 1995-01-18 23:45:01 +0000 | [diff] [blame] | 59 | |
Guido van Rossum | 8d6c180 | 1995-01-18 23:46:59 +0000 | [diff] [blame] | 60 | self.outputDealloc() |
Guido van Rossum | 8cfc4bf | 1995-01-18 23:45:01 +0000 | [diff] [blame] | 61 | |
| 62 | GeneratorGroup.generate(self) |
| 63 | |
Guido van Rossum | 80ffd66 | 1995-01-30 11:44:02 +0000 | [diff] [blame] | 64 | Output() |
| 65 | Output("%sPyMethodChain %s_chain = { %s_methods, %s };", |
| 66 | self.static, self.prefix, self.prefix, self.basechain) |
| 67 | |
Guido van Rossum | 8cfc4bf | 1995-01-18 23:45:01 +0000 | [diff] [blame] | 68 | self.outputGetattr() |
| 69 | |
| 70 | self.outputSetattr() |
Guido van Rossum | 8d6c180 | 1995-01-18 23:46:59 +0000 | [diff] [blame] | 71 | |
Guido van Rossum | c7e7c60 | 1999-03-15 16:37:54 +0000 | [diff] [blame] | 72 | self.outputCompare() |
| 73 | |
| 74 | self.outputRepr() |
| 75 | |
| 76 | self.outputHash() |
| 77 | |
Guido van Rossum | 8d6c180 | 1995-01-18 23:46:59 +0000 | [diff] [blame] | 78 | self.outputTypeObject() |
Guido van Rossum | 8cfc4bf | 1995-01-18 23:45:01 +0000 | [diff] [blame] | 79 | |
Guido van Rossum | 8d6c180 | 1995-01-18 23:46:59 +0000 | [diff] [blame] | 80 | OutHeader2("End object type " + self.name) |
| 81 | |
Guido van Rossum | 01f5a81 | 1995-01-25 22:59:21 +0000 | [diff] [blame] | 82 | def outputStructMembers(self): |
| 83 | Output("%s ob_itself;", self.itselftype) |
| 84 | |
Guido van Rossum | 8d6c180 | 1995-01-18 23:46:59 +0000 | [diff] [blame] | 85 | def outputNew(self): |
Guido van Rossum | 80ffd66 | 1995-01-30 11:44:02 +0000 | [diff] [blame] | 86 | Output() |
Jack Jansen | 656fe69 | 2001-05-19 13:59:18 +0000 | [diff] [blame] | 87 | Output("%sPyObject *%s_New(%s %sitself)", self.static, self.prefix, |
| 88 | self.itselftype, self.argref) |
Guido van Rossum | 8d6c180 | 1995-01-18 23:46:59 +0000 | [diff] [blame] | 89 | OutLbrace() |
| 90 | Output("%s *it;", self.objecttype) |
Guido van Rossum | f8de068 | 1995-01-22 18:35:09 +0000 | [diff] [blame] | 91 | self.outputCheckNewArg() |
Guido van Rossum | 8d6c180 | 1995-01-18 23:46:59 +0000 | [diff] [blame] | 92 | Output("it = PyObject_NEW(%s, &%s);", self.objecttype, self.typename) |
| 93 | Output("if (it == NULL) return NULL;") |
Guido van Rossum | 01f5a81 | 1995-01-25 22:59:21 +0000 | [diff] [blame] | 94 | self.outputInitStructMembers() |
Guido van Rossum | f8de068 | 1995-01-22 18:35:09 +0000 | [diff] [blame] | 95 | Output("return (PyObject *)it;") |
Guido van Rossum | 8d6c180 | 1995-01-18 23:46:59 +0000 | [diff] [blame] | 96 | OutRbrace() |
Guido van Rossum | 01f5a81 | 1995-01-25 22:59:21 +0000 | [diff] [blame] | 97 | |
| 98 | def outputInitStructMembers(self): |
| 99 | Output("it->ob_itself = %sitself;", self.argref) |
Guido van Rossum | f8de068 | 1995-01-22 18:35:09 +0000 | [diff] [blame] | 100 | |
| 101 | def outputCheckNewArg(self): |
Guido van Rossum | 01f5a81 | 1995-01-25 22:59:21 +0000 | [diff] [blame] | 102 | "Override this method to apply additional checks/conversions" |
| 103 | |
Guido van Rossum | 8d6c180 | 1995-01-18 23:46:59 +0000 | [diff] [blame] | 104 | def outputConvert(self): |
Jack Jansen | d157b37 | 2001-09-04 22:16:33 +0000 | [diff] [blame] | 105 | Output("%sint %s_Convert(PyObject *v, %s *p_itself)", self.static, self.prefix, |
Jack Jansen | 656fe69 | 2001-05-19 13:59:18 +0000 | [diff] [blame] | 106 | self.itselftype) |
Guido van Rossum | 01f5a81 | 1995-01-25 22:59:21 +0000 | [diff] [blame] | 107 | OutLbrace() |
| 108 | self.outputCheckConvertArg() |
| 109 | Output("if (!%s_Check(v))", self.prefix) |
| 110 | OutLbrace() |
| 111 | Output('PyErr_SetString(PyExc_TypeError, "%s required");', self.name) |
| 112 | Output("return 0;") |
| 113 | OutRbrace() |
| 114 | Output("*p_itself = ((%s *)v)->ob_itself;", self.objecttype) |
| 115 | Output("return 1;") |
| 116 | OutRbrace() |
| 117 | |
| 118 | def outputCheckConvertArg(self): |
| 119 | "Override this method to apply additional conversions" |
Guido van Rossum | 8d6c180 | 1995-01-18 23:46:59 +0000 | [diff] [blame] | 120 | |
| 121 | def outputDealloc(self): |
Guido van Rossum | 80ffd66 | 1995-01-30 11:44:02 +0000 | [diff] [blame] | 122 | Output() |
Jack Jansen | 656fe69 | 2001-05-19 13:59:18 +0000 | [diff] [blame] | 123 | Output("static void %s_dealloc(%s *self)", self.prefix, self.objecttype) |
Guido van Rossum | 8d6c180 | 1995-01-18 23:46:59 +0000 | [diff] [blame] | 124 | OutLbrace() |
Guido van Rossum | 01f5a81 | 1995-01-25 22:59:21 +0000 | [diff] [blame] | 125 | self.outputCleanupStructMembers() |
Jack Jansen | a6aa71d | 2002-04-19 14:29:47 +0000 | [diff] [blame] | 126 | Output("PyObject_Del(self);") |
Guido van Rossum | 8d6c180 | 1995-01-18 23:46:59 +0000 | [diff] [blame] | 127 | OutRbrace() |
Guido van Rossum | 8d6c180 | 1995-01-18 23:46:59 +0000 | [diff] [blame] | 128 | |
Guido van Rossum | 01f5a81 | 1995-01-25 22:59:21 +0000 | [diff] [blame] | 129 | def outputCleanupStructMembers(self): |
| 130 | self.outputFreeIt("self->ob_itself") |
| 131 | |
Guido van Rossum | 8d6c180 | 1995-01-18 23:46:59 +0000 | [diff] [blame] | 132 | def outputFreeIt(self, name): |
| 133 | Output("/* Cleanup of %s goes here */", name) |
| 134 | |
| 135 | def outputGetattr(self): |
Guido van Rossum | 80ffd66 | 1995-01-30 11:44:02 +0000 | [diff] [blame] | 136 | Output() |
Jack Jansen | 656fe69 | 2001-05-19 13:59:18 +0000 | [diff] [blame] | 137 | Output("static PyObject *%s_getattr(%s *self, char *name)", self.prefix, self.objecttype) |
Guido van Rossum | 8d6c180 | 1995-01-18 23:46:59 +0000 | [diff] [blame] | 138 | OutLbrace() |
| 139 | self.outputGetattrBody() |
| 140 | OutRbrace() |
Guido van Rossum | 8d6c180 | 1995-01-18 23:46:59 +0000 | [diff] [blame] | 141 | |
| 142 | def outputGetattrBody(self): |
| 143 | self.outputGetattrHook() |
Guido van Rossum | 80ffd66 | 1995-01-30 11:44:02 +0000 | [diff] [blame] | 144 | Output("return Py_FindMethodInChain(&%s_chain, (PyObject *)self, name);", |
| 145 | self.prefix) |
Guido van Rossum | 8d6c180 | 1995-01-18 23:46:59 +0000 | [diff] [blame] | 146 | |
| 147 | def outputGetattrHook(self): |
| 148 | pass |
| 149 | |
| 150 | def outputSetattr(self): |
Guido van Rossum | 8d6c180 | 1995-01-18 23:46:59 +0000 | [diff] [blame] | 151 | Output() |
Guido van Rossum | 80ffd66 | 1995-01-30 11:44:02 +0000 | [diff] [blame] | 152 | Output("#define %s_setattr NULL", self.prefix) |
Guido van Rossum | 8d6c180 | 1995-01-18 23:46:59 +0000 | [diff] [blame] | 153 | |
Guido van Rossum | c7e7c60 | 1999-03-15 16:37:54 +0000 | [diff] [blame] | 154 | def outputCompare(self): |
| 155 | Output() |
| 156 | Output("#define %s_compare NULL", self.prefix) |
| 157 | |
| 158 | def outputRepr(self): |
| 159 | Output() |
| 160 | Output("#define %s_repr NULL", self.prefix) |
| 161 | |
| 162 | def outputHash(self): |
| 163 | Output() |
| 164 | Output("#define %s_hash NULL", self.prefix) |
| 165 | |
Guido van Rossum | 8d6c180 | 1995-01-18 23:46:59 +0000 | [diff] [blame] | 166 | def outputTypeObject(self): |
Guido van Rossum | 9784295 | 1995-02-19 15:59:49 +0000 | [diff] [blame] | 167 | sf = self.static and "staticforward " |
Guido van Rossum | 80ffd66 | 1995-01-30 11:44:02 +0000 | [diff] [blame] | 168 | Output() |
Guido van Rossum | 9784295 | 1995-02-19 15:59:49 +0000 | [diff] [blame] | 169 | Output("%sPyTypeObject %s = {", sf, self.typename) |
Guido van Rossum | 8cfc4bf | 1995-01-18 23:45:01 +0000 | [diff] [blame] | 170 | IndentLevel() |
Jack Jansen | 1062e70 | 2001-11-14 15:48:13 +0000 | [diff] [blame] | 171 | Output("PyObject_HEAD_INIT(NULL)") |
Guido van Rossum | 8cfc4bf | 1995-01-18 23:45:01 +0000 | [diff] [blame] | 172 | Output("0, /*ob_size*/") |
Jack Jansen | 5801a2d | 2001-12-09 23:25:00 +0000 | [diff] [blame] | 173 | if self.modulename: |
| 174 | Output("\"%s.%s\", /*tp_name*/", self.modulename, self.name) |
| 175 | else: |
| 176 | Output("\"%s\", /*tp_name*/", self.name) |
Guido van Rossum | 8cfc4bf | 1995-01-18 23:45:01 +0000 | [diff] [blame] | 177 | Output("sizeof(%s), /*tp_basicsize*/", self.objecttype) |
| 178 | Output("0, /*tp_itemsize*/") |
| 179 | Output("/* methods */") |
| 180 | Output("(destructor) %s_dealloc, /*tp_dealloc*/", self.prefix) |
| 181 | Output("0, /*tp_print*/") |
| 182 | Output("(getattrfunc) %s_getattr, /*tp_getattr*/", self.prefix) |
| 183 | Output("(setattrfunc) %s_setattr, /*tp_setattr*/", self.prefix) |
Guido van Rossum | c7e7c60 | 1999-03-15 16:37:54 +0000 | [diff] [blame] | 184 | Output("(cmpfunc) %s_compare, /*tp_compare*/", self.prefix) |
| 185 | Output("(reprfunc) %s_repr, /*tp_repr*/", self.prefix) |
| 186 | Output("(PyNumberMethods *)0, /* tp_as_number */") |
| 187 | Output("(PySequenceMethods *)0, /* tp_as_sequence */") |
| 188 | Output("(PyMappingMethods *)0, /* tp_as_mapping */") |
| 189 | Output("(hashfunc) %s_hash, /*tp_hash*/", self.prefix) |
Guido van Rossum | 8cfc4bf | 1995-01-18 23:45:01 +0000 | [diff] [blame] | 190 | DedentLevel() |
| 191 | Output("};") |
Guido van Rossum | 03be7f5 | 1997-09-22 16:13:19 +0000 | [diff] [blame] | 192 | |
| 193 | def outputTypeObjectInitializer(self): |
| 194 | Output("""%s.ob_type = &PyType_Type;""", self.typename); |
| 195 | Output("""Py_INCREF(&%s);""", self.typename); |
| 196 | Output("""if (PyDict_SetItemString(d, "%sType", (PyObject *)&%s) != 0)""", |
| 197 | self.name, self.typename); |
| 198 | IndentLevel() |
Jack Jansen | 9403591 | 2001-08-27 14:30:55 +0000 | [diff] [blame] | 199 | Output("""Py_FatalError("can\'t initialize %sType");""", |
Guido van Rossum | 03be7f5 | 1997-09-22 16:13:19 +0000 | [diff] [blame] | 200 | self.name) |
| 201 | DedentLevel() |
| 202 | |
Guido van Rossum | 01f5a81 | 1995-01-25 22:59:21 +0000 | [diff] [blame] | 203 | |
| 204 | |
| 205 | class GlobalObjectDefinition(ObjectDefinition): |
Guido van Rossum | 80ffd66 | 1995-01-30 11:44:02 +0000 | [diff] [blame] | 206 | """Like ObjectDefinition but exports some parts. |
| 207 | |
| 208 | XXX Should also somehow generate a .h file for them. |
| 209 | """ |
Guido van Rossum | 01f5a81 | 1995-01-25 22:59:21 +0000 | [diff] [blame] | 210 | |
| 211 | def __init__(self, name, prefix = None, itselftype = None): |
| 212 | ObjectDefinition.__init__(self, name, prefix or name, itselftype or name) |
| 213 | self.static = "" |
Guido van Rossum | c7e7c60 | 1999-03-15 16:37:54 +0000 | [diff] [blame] | 214 | |
| 215 | class ObjectIdentityMixin: |
| 216 | """A mixin class for objects that makes the identity of ob_itself |
| 217 | govern comparisons and dictionary lookups. Useful if the C object can |
| 218 | be returned by library calls and it is difficult (or impossible) to find |
| 219 | the corresponding Python objects. With this you can create Python object |
| 220 | wrappers on the fly""" |
| 221 | |
| 222 | def outputCompare(self): |
| 223 | Output() |
Jack Jansen | 656fe69 | 2001-05-19 13:59:18 +0000 | [diff] [blame] | 224 | Output("static int %s_compare(%s *self, %s *other)", self.prefix, self.objecttype, |
| 225 | self.objecttype) |
Guido van Rossum | c7e7c60 | 1999-03-15 16:37:54 +0000 | [diff] [blame] | 226 | OutLbrace() |
| 227 | Output("unsigned long v, w;") |
| 228 | Output() |
| 229 | Output("if (!%s_Check((PyObject *)other))", self.prefix) |
| 230 | OutLbrace() |
| 231 | Output("v=(unsigned long)self;") |
| 232 | Output("w=(unsigned long)other;") |
| 233 | OutRbrace() |
| 234 | Output("else") |
| 235 | OutLbrace() |
| 236 | Output("v=(unsigned long)self->ob_itself;") |
| 237 | Output("w=(unsigned long)other->ob_itself;") |
| 238 | OutRbrace() |
| 239 | Output("if( v < w ) return -1;") |
| 240 | Output("if( v > w ) return 1;") |
| 241 | Output("return 0;") |
| 242 | OutRbrace() |
| 243 | |
| 244 | def outputHash(self): |
| 245 | Output() |
Jack Jansen | 656fe69 | 2001-05-19 13:59:18 +0000 | [diff] [blame] | 246 | Output("static long %s_hash(%s *self)", self.prefix, self.objecttype) |
Guido van Rossum | c7e7c60 | 1999-03-15 16:37:54 +0000 | [diff] [blame] | 247 | OutLbrace() |
| 248 | Output("return (long)self->ob_itself;") |
| 249 | OutRbrace() |
| 250 | |
| 251 | |