PageRenderTime 87ms CodeModel.GetById 72ms app.highlight 12ms RepoModel.GetById 0ms app.codeStats 1ms

/Tools/framer/framer/bases.py

http://unladen-swallow.googlecode.com/
Python | 220 lines | 168 code | 42 blank | 10 comment | 55 complexity | c7e40254f507ae39b4fd60f266dbcbfd MD5 | raw file
  1"""Provides the Module and Type base classes that user code inherits from."""
  2
  3__all__ = ["Module", "Type", "member"]
  4
  5from framer import struct, template
  6from framer.function import Function, Method
  7from framer.member import member
  8from framer.slots import *
  9from framer.util import cstring, unindent
 10
 11from types import FunctionType
 12
 13def sortitems(dict):
 14    L = dict.items()
 15    L.sort()
 16    return L
 17
 18# The Module and Type classes are implemented using metaclasses,
 19# because most of the methods are class methods.  It is easier to use
 20# metaclasses than the cumbersome classmethod() builtin.  They have
 21# class methods because they are exposed to user code as base classes.
 22
 23class BaseMetaclass(type):
 24    """Shared infrastructure for generating modules and types."""
 25
 26    # just methoddef so far
 27
 28    def dump_methoddef(self, f, functions, vars):
 29        def p(templ, vars=vars): # helper function to generate output
 30            print >> f, templ % vars
 31
 32        if not functions:
 33            return
 34        p(template.methoddef_start)
 35        for name, func in sortitems(functions):
 36            if func.__doc__:
 37                p(template.methoddef_def_doc, func.vars)
 38            else:
 39                p(template.methoddef_def, func.vars)
 40        p(template.methoddef_end)
 41
 42class ModuleMetaclass(BaseMetaclass):
 43    """Provides methods for Module class."""
 44
 45    def gen(self):
 46        self.analyze()
 47        self.initvars()
 48        f = open(self.__filename, "w")
 49        self.dump(f)
 50        f.close()
 51
 52    def analyze(self):
 53        self.name = getattr(self, "abbrev", self.__name__)
 54        self.__functions = {}
 55        self.__types = {}
 56        self.__members = False
 57
 58        for name, obj in self.__dict__.iteritems():
 59            if isinstance(obj, FunctionType):
 60                self.__functions[name] = Function(obj, self)
 61            elif isinstance(obj, TypeMetaclass):
 62                obj._TypeMetaclass__module = self.name
 63                obj.analyze()
 64                self.__types[name] = obj
 65                if obj.has_members():
 66                    self.__members = True
 67
 68    def initvars(self):
 69        v = self.__vars = {}
 70        filename = getattr(self, "__file__", None)
 71        if filename is None:
 72            filename = self.__name__ + "module.c"
 73        self.__filename = v["FileName"] = filename
 74        name = v["ModuleName"] = self.__name__
 75        v["MethodDefName"] = "%s_methods" % name
 76        v["ModuleDocstring"] = cstring(unindent(self.__doc__))
 77
 78    def dump(self, f):
 79        def p(templ, vars=self.__vars): # helper function to generate output
 80            print >> f, templ % vars
 81
 82        p(template.module_start)
 83        if self.__members:
 84            p(template.member_include)
 85        print >> f
 86
 87        if self.__doc__:
 88            p(template.module_doc)
 89
 90        for name, type in sortitems(self.__types):
 91            type.dump(f)
 92
 93        for name, func  in sortitems(self.__functions):
 94            func.dump(f)
 95
 96        self.dump_methoddef(f, self.__functions, self.__vars)
 97
 98        p(template.module_init_start)
 99        for name, type in sortitems(self.__types):
100            type.dump_init(f)
101
102        p("}")
103
104class Module:
105    __metaclass__ = ModuleMetaclass
106
107class TypeMetaclass(BaseMetaclass):
108
109    def dump(self, f):
110        self.initvars()
111
112        # defined after initvars() so that __vars is defined
113        def p(templ, vars=self.__vars):
114            print >> f, templ % vars
115
116        if self.struct is not None:
117            print >> f, unindent(self.struct, False)
118
119        if self.__doc__:
120            p(template.docstring)
121
122        for name, func in sortitems(self.__methods):
123            func.dump(f)
124
125        self.dump_methoddef(f, self.__methods, self.__vars)
126        self.dump_memberdef(f)
127        self.dump_slots(f)
128
129    def has_members(self):
130        if self.__members:
131            return True
132        else:
133            return False
134
135    def analyze(self):
136        # called by ModuleMetaclass analyze()
137        self.name = getattr(self, "abbrev", self.__name__)
138        src = getattr(self, "struct", None)
139        if src is not None:
140            self.__struct = struct.parse(src)
141        else:
142            self.__struct = None
143        self.__methods = {}
144        self.__members = {}
145        for cls in self.__mro__:
146            for k, v in cls.__dict__.iteritems():
147                if isinstance(v, FunctionType):
148                    self.__methods[k] = Method(v, self)
149                if isinstance(v, member):
150                    self.__members[k] = v
151                    assert self.__struct is not None
152                    v.register(k, self.__struct)
153        self.analyze_slots()
154
155    def analyze_slots(self):
156        self.__slots = {}
157        for s in Slots:
158            if s.special is not None:
159                meth = self.__methods.get(s.special)
160                if meth is not None:
161                    self.__slots[s] = meth
162        self.__slots[TP_NAME] = '"%s.%s"' % (self.__module, self.__name__)
163        if self.__doc__:
164            self.__slots[TP_DOC] = "%s_doc" % self.name
165        if self.__struct is not None:
166            self.__slots[TP_BASICSIZE] = "sizeof(%s)" % self.__struct.name
167            self.__slots[TP_DEALLOC] = "%s_dealloc" % self.name
168        if self.__methods:
169            self.__slots[TP_METHODS] = "%s_methods" % self.name
170        if self.__members:
171            self.__slots[TP_MEMBERS] = "%s_members" % self.name
172
173    def initvars(self):
174        v = self.__vars = {}
175        v["TypeName"] = self.__name__
176        v["CTypeName"] = "Py%s_Type" % self.__name__
177        v["MethodDefName"] = self.__slots[TP_METHODS]
178        if self.__doc__:
179            v["DocstringVar"] = self.__slots[TP_DOC]
180            v["Docstring"] = cstring(unindent(self.__doc__))
181        if self.__struct is not None:
182            v["StructName"] = self.__struct.name
183        if self.__members:
184            v["MemberDefName"] = self.__slots[TP_MEMBERS]
185
186    def dump_memberdef(self, f):
187        def p(templ, vars=self.__vars):
188            print >> f, templ % vars
189
190        if not self.__members:
191            return
192        p(template.memberdef_start)
193        for name, slot in sortitems(self.__members):
194            slot.dump(f)
195        p(template.memberdef_end)
196
197    def dump_slots(self, f):
198        def p(templ, vars=self.__vars):
199            print >> f, templ % vars
200
201        if self.struct:
202            p(template.dealloc_func, {"name" : self.__slots[TP_DEALLOC]})
203
204        p(template.type_struct_start)
205        for s in Slots[:-5]: # XXX
206            val = self.__slots.get(s, s.default)
207            ntabs = 4 - (4 + len(val)) / 8
208            line = "        %s,%s/* %s */" % (val, "\t" * ntabs, s.name)
209            print >> f, line
210        p(template.type_struct_end)
211
212    def dump_init(self, f):
213        def p(templ):
214            print >> f, templ % self.__vars
215
216        p(template.type_init_type)
217        p(template.module_add_type)
218
219class Type:
220    __metaclass__ = TypeMetaclass