/Tools/framer/framer/bases.py

http://unladen-swallow.googlecode.com/ · Python · 220 lines · 168 code · 42 blank · 10 comment · 39 complexity · c7e40254f507ae39b4fd60f266dbcbfd MD5 · raw file

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