diff options
author | James Henstridge <james@daa.com.au> | 2000-11-09 11:46:09 +0000 |
---|---|---|
committer | James Henstridge <jamesh@src.gnome.org> | 2000-11-09 11:46:09 +0000 |
commit | 8657fdbf2d9d55cbda8424155ffaef50e31dbc39 (patch) | |
tree | 5789cc4776dda8ceda06467b815df7a2ec5e37bb | |
parent | c0f0b3ae57342d1f11a98cdbda10e2d879212a22 (diff) | |
download | pygtk-8657fdbf2d9d55cbda8424155ffaef50e31dbc39.tar.gz |
register interfaces into the argument type matcher. (write_source): write
2000-11-09 James Henstridge <james@daa.com.au>
* codegen/codegen.py (register_types): register interfaces into
the argument type matcher.
(write_source): write out interface source. Register interface
class types before object types, as they may be used by objects.
(write_source): set multiple base classes if an object implements
an interface.
(write_interface): function to write out the code for an
interface. It is really a simplified version of write_class.
* codegen/parser.py (DefsParser.interface): handle interface
clauses.
* codegen/definitions.py (InterfaceDef): add a class for interface
definitions.
(ObjectDef): add support for an implements keyword.
* codegen/codegen.py (write_source): change code generator to pass
bases in as a tuple rather than a single PyExtensionClass
structure.
-rw-r--r-- | ChangeLog | 16 | ||||
-rw-r--r-- | codegen/codegen.py | 101 | ||||
-rw-r--r-- | codegen/definitions.py | 38 | ||||
-rw-r--r-- | codegen/parser.py | 5 |
4 files changed, 158 insertions, 2 deletions
@@ -1,5 +1,21 @@ 2000-11-09 James Henstridge <james@daa.com.au> + * codegen/codegen.py (register_types): register interfaces into + the argument type matcher. + (write_source): write out interface source. Register interface + class types before object types, as they may be used by objects. + (write_source): set multiple base classes if an object implements + an interface. + (write_interface): function to write out the code for an + interface. It is really a simplified version of write_class. + + * codegen/parser.py (DefsParser.interface): handle interface + clauses. + + * codegen/definitions.py (InterfaceDef): add a class for interface + definitions. + (ObjectDef): add support for an implements keyword. + * codegen/codegen.py (write_source): change code generator to pass bases in as a tuple rather than a single PyExtensionClass structure. diff --git a/codegen/codegen.py b/codegen/codegen.py index adf1ee62..8ffc6b19 100644 --- a/codegen/codegen.py +++ b/codegen/codegen.py @@ -105,6 +105,33 @@ typetmpl = 'PyExtensionClass Py%(class)s_Type = {\n' + \ ' %(methods)s,\n' + \ ' EXTENSIONCLASS_INSTDICT_FLAG,\n' + \ '};\n\n' +interfacetypetmpl = 'PyExtensionClass Py%(class)s_Type = {\n' + \ + ' PyObject_HEAD_INIT(NULL)\n' + \ + ' 0, /* ob_size */\n' + \ + ' "%(class)s", /* tp_name */\n' + \ + ' sizeof(PyPureMixinObject), /* tp_basicsize */\n' + \ + ' 0, /* tp_itemsize */\n' + \ + ' /* methods */\n' + \ + ' (destructor)0, /* tp_dealloc */\n' + \ + ' (printfunc)0, /* tp_print */\n' + \ + ' (getattrfunc)0, /* tp_getattr */\n' + \ + ' (setattrfunc)0, /* tp_setattr */\n' + \ + ' (cmpfunc)0, /* tp_compare */\n' + \ + ' (reprfunc)0, /* tp_repr */\n' + \ + ' 0, /* tp_as_number */\n' + \ + ' 0, /* tp_as_sequence */\n' + \ + ' 0, /* tp_as_mapping */\n' + \ + ' (hashfunc)0, /* tp_hash */\n' + \ + ' (ternaryfunc)0, /* tp_call */\n' + \ + ' (reprfunc)0, /* tp_str */\n' + \ + ' (getattrofunc)0, /* tp_getattro */\n' + \ + ' (setattrofunc)0, /* tp_setattro */\n' + \ + ' /* Space for future expansion */\n' + \ + ' 0L, 0L,\n' + \ + ' NULL, /* Documentation string */\n' + \ + ' %(methods)s,\n' + \ + ' EXTENSIONCLASS_BASICNEW_FLAG,\n' + \ + '};\n\n' def fixname(name): if keyword.iskeyword(name): @@ -342,6 +369,50 @@ def write_class(parser, objobj, overrides, fp=sys.stdout): dict['methods'] = 'METHOD_CHAIN(_Py' + dict['class'] + '_methods)' fp.write(typetmpl % dict) +def write_interface(parser, interface, overrides, fp=sys.stdout): + fp.write('\n/* ----------- ' + interface.c_name + ' ----------- */\n\n') + methods = [] + if not hasattr(overrides, 'no_constructor_written'): + fp.write(noconstructor) + overrides.no_constructor_written = 1 + methods.append(methdeftmpl % + { 'name': '__init__', + 'cname': 'pygobject_no_constructor', + 'flags': 'METH_VARARGS'}) + # do the get_type routine as class method ... + uclass = string.lower(argtypes._to_upper_str(interface.c_name)[1:]) + for meth in parser.find_methods(interface): + if overrides.is_ignored(meth.c_name): + continue + try: + methtype = 'METH_VARARGS' + if overrides.is_overriden(meth.c_name): + fp.write(overrides.override(meth.c_name)) + fp.write('\n\n') + if overrides.wants_kwargs(meth.c_name): + methtype = methtype + '|METH_KEYWORDS' + else: + write_method(interface.c_name, meth, fp) + methtype = methtype + '|METH_KEYWORDS' + methods.append(methdeftmpl % { 'name': fixname(meth.name), + 'cname': '_wrap_' + meth.c_name, + 'flags': methtype}) + except: + sys.stderr.write('Could not write method ' + interface.c_name + + '.' + meth.name + '\n') + #traceback.print_exc() + + # write the PyMethodDef structure + methods.append(' { NULL, NULL, 0 }\n') + fp.write('static PyMethodDef _Py' + interface.c_name + '_methods[] = {\n') + fp.write(string.join(methods, '')) + fp.write('};\n\n') + + # write the type template + dict = { 'class': interface.c_name, 'getattr': '0' } + dict['methods'] = 'METHOD_CHAIN(_Py' + dict['class'] + '_methods)' + fp.write(typetmpl % dict) + def write_functions(parser, overrides, prefix, fp=sys.stdout): fp.write('\n/* ----------- functions ----------- */\n\n') functions = [] @@ -379,10 +450,15 @@ def write_source(parser, overrides, prefix, fp=sys.stdout): fp.write('/* ---------- forward type declarations ---------- */\n') for obj in parser.objects: fp.write('PyExtensionClass Py' + obj.c_name + '_Type;\n') + for interface in parser.interfaces: + fp.write('PyExtensionClass Py' + interface.c_name + '_Type;\n') fp.write('\n') for obj in parser.objects: write_class(parser, obj, overrides, fp) fp.write('\n') + for interface in parser.interfaces: + write_interface(parser, interface, overrides, fp) + fp.write('\n') write_functions(parser, overrides, prefix, fp) @@ -390,12 +466,27 @@ def write_source(parser, overrides, prefix, fp=sys.stdout): fp.write('void\n' + prefix + '_register_classes(PyObject *d)\n{\n') fp.write(' ExtensionClassImported;\n') fp.write(overrides.get_init() + '\n') + for interface in parser.interfaces: + if interface.parent != (None, None): + fp.write(' PyExtensionClass_ExportSubclassSingle(d, "' + + interface.c_name + '", Py' + interface.c_name + + '_Type, Py' + interface.parent[1] + interface.parent[0] + + '_Type);\n') + else: + fp.write(' PyExtensionClass_Export(d, "' + + interface.c_name + '", Py' + interface.c_name + + '_Type);\n') for obj in parser.objects: + bases = [] if obj.parent != (None, None): + bases.append(obj.parent[1] + obj.parent[0]) + bases = bases + obj.implements + if bases: fp.write(' pygobject_register_class(d, "' + obj.c_name + '", &Py' + obj.c_name + - '_Type, Py_BuildValue("(O)", (PyObject *)&Py' + - obj.parent[1] + obj.parent[0] + '_Type));\n') + '_Type, Py_BuildValue("(' + 'O' * len(bases) + ')", ' + + string.join(map(lambda s: '&Py'+s+'_Type', bases), ', ') + + '));\n') else: fp.write(' pygobject_register_class(d, "' + obj.c_name + '", &Py' + obj.c_name + '_Type, NULL);\n') @@ -408,6 +499,12 @@ def register_types(parser): obj.parent[1] + obj.parent[0]) else: argtypes.matcher.register_object(obj.c_name, None) + for obj in parser.interfaces: + if obj.parent != (None, None): + argtypes.matcher.register_object(obj.c_name, + obj.parent[1] + obj.parent[0]) + else: + argtypes.matcher.register_object(obj.c_name, None) for enum in parser.enums: if enum.deftype == 'flags': argtypes.matcher.register_flag(enum.c_name) diff --git a/codegen/definitions.py b/codegen/definitions.py index 88b2cefc..3fc471cc 100644 --- a/codegen/definitions.py +++ b/codegen/definitions.py @@ -20,6 +20,7 @@ class ObjectDef(Definition): self.c_name = None self.parent = (None, None) self.fields = [] + self.implements = [] for arg in args: if type(arg) != type(()) or len(arg) < 2: continue @@ -36,11 +37,14 @@ class ObjectDef(Definition): for parg in arg[1:]: if parg[0] == 'type-and-name': self.fields.append((parg[1], parg[2])) + elif arg[0] == 'implements': + self.implements.append(arg[1]) def merge(self, old): # currently the .h parser doesn't try to work out what fields of # an object structure should be public, so we just copy the list # from the old version ... self.fields = old.fields + self.implements = old.implements def write_defs(self, fp=sys.stdout): fp.write('(object ' + self.name + '\n') if self.module: @@ -54,6 +58,40 @@ class ObjectDef(Definition): fp.write(' (c-name ' + self.c_name + ')\n') for (ftype, fname) in self.fields: fp.write(' (field (type-and-name ' + ftype + ' ' + fname + '))\n') + for interface in self.implements: + fp.write(' (implements ' + interface + ')\n') + fp.write(')\n\n') + +class InterfaceDef(Definition): + def __init__(self, name, *args): + self.name = name + self.module = None + self.c_name = None + self.parent = (None, None) + self.fields = [] + for arg in args: + if type(arg) != type(()) or len(arg) < 2: + continue + if arg[0] == 'in-module': + self.module = arg[1] + elif arg[0] == 'parent': + if len(arg) > 2: + self.parent = (arg[1], arg[2][0]) + else: + self.parent = (arg[1], None) + elif arg[0] == 'c-name': + self.c_name = arg[1] + def write_defs(self, fp=sys.stdout): + fp.write('(interface ' + self.name + '\n') + if self.module: + fp.write(' (in-module ' + self.module + ')\n') + if self.parent != (None, None): + fp.write(' (parent ' + self.parent[0]) + if self.parent[1]: + fp.write(' (' + self.parent[1] + ')') + fp.write(')\n') + if self.c_name: + fp.write(' (c-name ' + self.c_name + ')\n') fp.write(')\n\n') class EnumDef(Definition): diff --git a/codegen/parser.py b/codegen/parser.py index 4cf3c2c4..13b016d7 100644 --- a/codegen/parser.py +++ b/codegen/parser.py @@ -19,6 +19,7 @@ class DefsParser(IncludeParser): def __init__(self, arg): IncludeParser.__init__(self, arg) self.objects = [] + self.interfaces = [] self.enums = [] # enums and flags self.functions = [] # functions and methods self.c_name = {} # hash of c names of functions @@ -28,6 +29,10 @@ class DefsParser(IncludeParser): odef = apply(ObjectDef, args) self.objects.append(odef) self.c_name[odef.c_name] = odef + def interface(self, *args): + idef = apply(InterfaceDef, args) + self.interfaces.append(idef) + self.c_name[idef.c_name] = idef def enum(self, *args): edef = apply(EnumDef, args) self.enums.append(edef) |