summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Henstridge <james@daa.com.au>2000-11-09 11:46:09 +0000
committerJames Henstridge <jamesh@src.gnome.org>2000-11-09 11:46:09 +0000
commit8657fdbf2d9d55cbda8424155ffaef50e31dbc39 (patch)
tree5789cc4776dda8ceda06467b815df7a2ec5e37bb
parentc0f0b3ae57342d1f11a98cdbda10e2d879212a22 (diff)
downloadpygtk-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--ChangeLog16
-rw-r--r--codegen/codegen.py101
-rw-r--r--codegen/definitions.py38
-rw-r--r--codegen/parser.py5
4 files changed, 158 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog
index 9ce9736c..78344cb4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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)