+class Collector(Traverser):
+ '''Visitor which collects all unique types as it traverses them.'''
+
+ def __init__(self):
+ self.__visited = set()
+ self.types = []
+
+ def visit(self, type):
+ if type in self.__visited:
+ return
+ self.__visited.add(type)
+ Visitor.visit(self, type)
+ self.types.append(type)
+
+
+class ExpanderMixin:
+ '''Mixin class that provides a bunch of methods to expand C expressions
+ from the specifications.'''
+
+ __structs = None
+ __indices = None
+
+ def expand(self, expr):
+ # Expand a C expression, replacing certain variables
+ if not isinstance(expr, basestring):
+ return expr
+ variables = {}
+
+ if self.__structs is not None:
+ variables['self'] = '(%s)' % self.__structs[0]
+ if self.__indices is not None:
+ variables['i'] = self.__indices[0]
+
+ expandedExpr = expr.format(**variables)
+ if expandedExpr != expr and 0:
+ sys.stderr.write(" %r -> %r\n" % (expr, expandedExpr))
+ return expandedExpr
+
+ def visitMember(self, member, structInstance, *args, **kwargs):
+ memberType, memberName = member
+ if memberName is None:
+ # Anonymous structure/union member
+ memberInstance = structInstance
+ else:
+ memberInstance = '(%s).%s' % (structInstance, memberName)
+ self.__structs = (structInstance, self.__structs)
+ try:
+ return self.visit(memberType, memberInstance, *args, **kwargs)
+ finally:
+ _, self.__structs = self.__structs
+
+ def visitElement(self, elementIndex, elementType, *args, **kwargs):
+ self.__indices = (elementIndex, self.__indices)
+ try:
+ return self.visit(elementType, *args, **kwargs)
+ finally:
+ _, self.__indices = self.__indices
+
+
+class Module:
+ '''A collection of functions.'''