# -*- Mode: Python -*- # GObject-Introspection - a framework for introspecting GObject libraries # Copyright (C) 2008 Johan Dahlin # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301, USA. # """AST nodes This file descbribes abstract data type nodes independent on the implementation language. These can later on be extended (eg subclassed) with additional information which is language/library/domain specific. """ ## ## Basic types, modeled on GITypeTag but not equivalent ## TYPE_NONE = 'none' # We differ from repository on these first two TYPE_ANY = 'any' TYPE_BOOLEAN = 'boolean' TYPE_INT8 = 'int8' TYPE_UINT8 = 'uint8' TYPE_INT16 = 'int16' TYPE_UINT16 = 'uint16' TYPE_INT = 'int' TYPE_UINT = 'uint' TYPE_INT32 = 'int32' TYPE_UINT32 = 'uint32' TYPE_INT64 = 'int64' TYPE_UINT64 = 'uint64' TYPE_LONG = 'long' TYPE_ULONG = 'ulong' TYPE_SSIZET = 'ssize_t' TYPE_SIZET = 'size_t' TYPE_TIMET = 'time_t' TYPE_GTYPE = 'GType' TYPE_FLOAT = 'float' TYPE_DOUBLE = 'double' TYPE_STRING = 'utf8' # requires zero-terminated TYPE_FILENAME = 'filename' BASIC_GIR_TYPES = [TYPE_BOOLEAN, TYPE_INT8, TYPE_UINT8, TYPE_INT16, TYPE_UINT16, TYPE_INT32, TYPE_UINT32, TYPE_INT64, TYPE_UINT64, TYPE_INT, TYPE_UINT, TYPE_LONG, TYPE_ULONG, TYPE_SSIZET, TYPE_SIZET, TYPE_FLOAT, TYPE_DOUBLE, TYPE_TIMET, TYPE_GTYPE] GIR_TYPES = [TYPE_NONE, TYPE_ANY] GIR_TYPES.extend(BASIC_GIR_TYPES) GIR_TYPES.extend([TYPE_STRING, TYPE_FILENAME]) # Higher-level data types TYPE_SEQUENCE = 'sequence' # Sequence of something # Wide/Unicode TYPE_UCHAR = 'uchar' TYPE_USTRING = 'ustring' ## ## Parameters ## PARAM_DIRECTION_IN = 'in' PARAM_DIRECTION_OUT = 'out' PARAM_DIRECTION_INOUT = 'inout' PARAM_TRANSFER_NONE = 'none' PARAM_TRANSFER_CONTAINER = 'container' PARAM_TRANSFER_FULL = 'full' type_names = {} for name in GIR_TYPES: type_names[name] = name # C type_names['char'] = TYPE_INT8 type_names['signed char'] = TYPE_INT8 type_names['unsigned char'] = TYPE_UINT8 type_names['short'] = TYPE_INT16 type_names['signed short'] = TYPE_INT16 type_names['unsigned short'] = TYPE_UINT16 type_names['int'] = TYPE_INT type_names['signed int'] = TYPE_INT type_names['signed'] = TYPE_INT type_names['unsigned int'] = TYPE_UINT type_names['unsigned'] = TYPE_UINT type_names['long'] = TYPE_LONG type_names['signed long'] = TYPE_LONG type_names['unsigned long'] = TYPE_ULONG type_names['float'] = TYPE_FLOAT type_names['double'] = TYPE_DOUBLE type_names['char*'] = TYPE_STRING type_names['void*'] = TYPE_ANY type_names['void'] = TYPE_NONE type_names['size_t'] = TYPE_SIZET type_names['ssize_t'] = TYPE_SSIZET type_names['off_t'] = TYPE_SIZET # FIXME - can we make libraries use GPid? type_names['pid_t'] = TYPE_INT # Suppress some GLib names type_names['uchar'] = TYPE_UINT8 type_names['ushort'] = TYPE_UINT16 type_names['size'] = TYPE_SIZET type_names['ssize'] = TYPE_SSIZET type_names['pointer'] = TYPE_ANY type_names['constpointer'] = TYPE_ANY # These types, when seen by reference, are converted into an Array() # by default # If you add/change these, be sure to update glibast.py too default_array_types = {} default_array_types['uint8*'] = TYPE_UINT8 default_array_types['char**'] = TYPE_STRING # These types, when seen by reference, are interpreted as out parameters default_out_types = (TYPE_INT, TYPE_UINT, TYPE_LONG, TYPE_ULONG, TYPE_FLOAT, TYPE_DOUBLE, TYPE_SIZET, TYPE_SSIZET) def type_name_from_ctype(ctype): return type_names.get(ctype, ctype) class Node(object): def __init__(self, name=None): self.name = name self.deprecated = None self.deprecated_version = None def __repr__(self): return '%s(%r)' % (self.__class__.__name__, self.name) class Namespace(Node): def __init__(self, name, version): Node.__init__(self, name) self.version = version self.nodes = [] def __repr__(self): return '%s(%r, %r, %r)' % (self.__class__.__name__, self.name, self.version, self.nodes) class Include(Node): def __init__(self, name, version): Node.__init__(self, 'include') self.name = name self.version = version @classmethod def from_string(self, string): return Include(*string.split('-', 1)) def __cmp__(self, other): if not isinstance(other, Include): return cmp(self, other) namecmp = cmp(self.name, other.name) if namecmp != 0: return namecmp return cmp(self.version, other.version) def __hash__(self): return hash((self.name, self.version)) def __str__(self): return '%s-%s' % (self.name, self.version) class Function(Node): def __init__(self, name, retval, parameters, symbol, throws=None): Node.__init__(self, name) self.retval = retval self.parameters = parameters self.symbol = symbol self.throws = not not throws def __repr__(self): return '%s(%r, %r, %r)' % (self.__class__.__name__, self.name, self.retval, self.parameters) class VFunction(Function): pass class Type(Node): def __init__(self, name, ctype=None): Node.__init__(self, name) self.ctype = ctype self.resolved = False class Varargs(Type): def __init__(self): Type.__init__(self, '') class Array(Type): def __init__(self, ctype, element_type): Type.__init__(self, '', ctype) self.element_type = element_type self.zeroterminated = True self.length_param_index = -1 self.length_param_name = None self.size = None def __repr__(self): return 'Array(%r of %r)' % (self.name, self.element_type, ) class List(Type): def __init__(self, name, ctype, element_type): Type.__init__(self, name, ctype) self.element_type = element_type def __repr__(self): return 'List(%r of %r)' % (self.name, self.element_type, ) class Map(Type): def __init__(self, name, ctype, key_type, value_type): Type.__init__(self, name, ctype) self.key_type = key_type self.value_type = value_type def __repr__(self): return 'Map(%r <%r,%r.)' % (self.name, self.key_type, self.value_type) class Alias(Node): def __init__(self, name, target, ctype=None): Node.__init__(self, name) self.target = target self.ctype = ctype def __repr__(self): return 'Alias(%r, %r)' % (self.name, self.target) class TypeContainer(Node): def __init__(self, name, typenode, transfer): Node.__init__(self, name) self.type = typenode if transfer in [PARAM_TRANSFER_NONE, PARAM_TRANSFER_CONTAINER, PARAM_TRANSFER_FULL]: self.transfer = transfer else: self.transfer = None # transformer.py overrides this as needed self.transfer_inferred = False class Parameter(TypeContainer): def __init__(self, name, typenode, direction=PARAM_DIRECTION_IN, transfer=None, allow_none=False): TypeContainer.__init__(self, name, typenode, transfer) if direction in [PARAM_DIRECTION_IN, PARAM_DIRECTION_OUT, PARAM_DIRECTION_INOUT]: self.direction = direction else: self.direction = PARAM_DIRECTION_IN self.allow_none = not not allow_none def __repr__(self): return 'Parameter(%r, %r)' % (self.name, self.type) class Enum(Node): def __init__(self, name, symbol, members): Node.__init__(self, name) self.symbol = symbol self.members = members def __repr__(self): return 'Enum(%r, %r)' % (self.name, self.members) class Member(Node): def __init__(self, name, value, symbol): Node.__init__(self, name) self.value = value self.symbol = symbol def __repr__(self): return 'Member(%r, %r)' % (self.name, self.value) class Struct(Node): def __init__(self, name, symbol): Node.__init__(self, name) self.fields = [] self.constructors = [] self.symbol = symbol class Field(Node): def __init__(self, name, typenode, symbol, readable, writable, bits=None): Node.__init__(self, name) self.type = typenode self.symbol = symbol self.readable = readable self.writable = writable self.bits = bits def __repr__(self): if self.bits: return 'Field(%r, %r, %r)' % (self.name, self.type, self.bits) else: return 'Field(%r, %r)' % (self.name, self.type) class Return(TypeContainer): def __init__(self, rtype, transfer=None): TypeContainer.__init__(self, None, rtype, transfer) def __repr__(self): return 'Return(%r)' % (self.type, ) class Class(Node): def __init__(self, name, parent, is_abstract): Node.__init__(self, name) self.ctype = name self.parent = parent self.is_abstract = is_abstract self.methods = [] self.interfaces = [] self.constructors = [] self.properties = [] self.fields = [] def __repr__(self): return '%s(%r, %r, %r)' % ( self.__class__.__name__, self.name, self.parent, self.methods) class Interface(Node): def __init__(self, name, parent): Node.__init__(self, name) self.parent = parent self.methods = [] self.properties = [] self.fields = [] def __repr__(self): return '%s(%r, %r)' % ( self.__class__.__name__, self.name, self.methods) class Constant(Node): def __init__(self, name, type_name, value): Node.__init__(self, name) self.type = Type(type_name) self.value = value def __repr__(self): return 'Constant(%r, %r, %r)' % ( self.name, self.type, self.value) class Property(Node): def __init__(self, name, type_name, readable, writable, construct, construct_only, ctype=None): Node.__init__(self, name) self.type = Type(type_name, ctype) self.readable = readable self.writable = writable self.construct = construct self.construct_only = construct_only def __repr__(self): return '%s(%r, %r)' % ( self.__class__.__name__, self.name, self.type) # FIXME: Inherit from Function class Callback(Node): def __init__(self, name, retval, parameters, ctype=None): Node.__init__(self, name) self.retval = retval self.parameters = parameters self.ctype = ctype def __repr__(self): return 'Callback(%r, %r, %r)' % ( self.name, self.retval, self.parameters) class Union(Node): def __init__(self, name, symbol): Node.__init__(self, name) self.fields = [] self.constructors = [] self.symbol = symbol def __repr__(self): return 'Union(%r, %r)' % (self.name, self.fields, )