trAvis - MANAGER
Edit File: ir.py
#!/usr/bin/env python """ ir.py - parse c declarations (c) 2002, 2003, 2004, 2005 Simon Burton <simon@arrowtheory.com> Released under GNU LGPL license. version 0.xx """ import sys #import cPickle as pickle import pickle #from lexer import Lexer from parse_core import Symbols #, Parser import node as node_module import cparse import genpyx class Node(genpyx.Node, node_module.Node): """ tree structure """ def __init__( self, *args, **kw ): node_module.Node.__init__( self, *args, **kw ) self._marked = False def get_marked( self ): return self._marked def set_marked( self, marked ): # if marked: # print "MARK", self self._marked = marked marked = property( get_marked, set_marked ) # def __getstate__( self ): # return self.__class__, tuple( [ item.__getstate__() for item in self ] ) # def __setstate__( self, state ): # cls, states = state # states = list(states) # for idx, state in enumerate(states): # items[idx] = items[idx].__setstate__( def __getstate__(self): return str(self) def __setstate__(self, state): Node.__init__(self) self[:] = eval(state) # _unique_id = 0 # def get_unique_id(cls): # Node._unique_id += 1 # return Node._unique_id # get_unique_id = classmethod(get_unique_id) def __hash__( self ): return hash( tuple([hash(type(self))]+[hash(item) for item in self]) ) def clone(self): l = [] for item in self: if isinstance(item,Node): item = item.clone() l.append(item) return self.__class__(*l, **self.__dict__) def init_from( self, other ): # class method ? # Warning: shallow init self[:] = other self.__dict__.update( other.__dict__ ) return self # def is_struct(self): # for x in self: # if isinstance(x,Node): # if x.is_struct(): # return 1 # return 0 #def explain(self): #l = [] #for x in self: #if isinstance(x,Node): #l.append(x.explain()) #else: #l.append(str(x)) #return string.join(l," ") ##(self.__class__.__name__,string.join(l) ) def psource(self): if hasattr(self,'lines'): # print "# "+string.join(self.lines,"\n# ")+"\n" print "# "+"\n# ".join(self.lines)+"\n" def cstr(self,l=None): """ Build a list of tokens; return the joined tokens string """ if l is None: l = [] for x in self: if isinstance(x,Node): x.cstr(l) else: l.insert(0,str(x)+' ') s = ''.join(l) return s def ctype(self): # anon_clone " return clone of self without identifiers " #print "%s.ctype()"%self l=[] for x in self: if isinstance(x,Node): l.append(x.ctype()) else: l.append(x) #print "%s.__class__(*%s)"%(self,l) return self.__class__(*l, **self.__dict__) # XX **self.__dict__ ? def cbasetype(self): " return ctype with all TypeAlias's replaced " # WARNING: we cache results (so do not mutate self!!) l=[] for x in self: if isinstance(x,Node): l.append(x.cbasetype()) else: l.append(x) #print "%s.__class__(*%s)"%(self,l) return self.__class__(*l, **self.__dict__) # XX **self.__dict__ ? def signature( self, tank=None ): if tank is None: tank = {} for node in self.nodes(): if not tank.has_key( type(node) ): tank[ type(node) ] = {} type(node).tank = tank[type(node)] shape = tuple( [ type(_node).__name__ for _node in node ] ) if not tank[type(node)].has_key(shape): tank[type(node)][shape] = [] tank[type(node)][shape].append( node ) return tank def psig( self, tank=None ): if tank is None: tank = {} tank = self.signature(tank) for key in tank.keys(): print key.__name__ for shape in tank[key].keys(): print " ", shape # ################################################# class Named(genpyx.Named, Node): " has a .name property " def get_name(self): if self: assert type(self[0])==str return self[0] return None def set_name(self, name): if self: self[0] = name else: self.append(name) name = property(get_name,set_name) class BasicType(genpyx.BasicType, Named): "float double void char int" pass class Qualifier(genpyx.Qualifier, Named): "register signed unsigned short long const volatile inline" pass class StorageClass(genpyx.StorageClass, Named): "extern static auto" pass class Ellipses(genpyx.Ellipses, Named): "..." pass class GCCBuiltin(genpyx.GCCBuiltin, BasicType): "things with __builtin prefix" pass class Identifier(genpyx.Identifier, Named): """ shape = +( str, +ConstExpr ) """ #def explain(self): #if len(self)==1: #return "%s"%self.name #else: #return "%s initialized to %s"%(self.name, #Node(self[1]).explain()) # will handle Initializer # def ctype(self): # return self.__class__(*self[1:]) #.clone() ? # def get_name(self): # if self: # return self[0] # def set_name(self, name): # if self: # self[0] = name # else: # self.append(name) # name = property(get_name,set_name) def cstr(self,l=None): if l is None: l=[] if len(self)>1: assert len(self)==2 l.append( '%s = %s'%(self[0],self[1]) ) elif len(self)==1: l.append( str(self[0]) ) return " ".join(l) class TypeAlias(genpyx.TypeAlias, Named): """ typedefed things, eg. size_t """ def cbasetype( self ): node = self.typedef.cbasetype().get_rest() return node class Function(genpyx.Function, Node): """ """ #def explain(self): #if len(self): #return "function (%s), returning"%\ #", ".join( map(lambda x:x.explain(),self) ) #else: #return "function returning" def cstr(self,l): #print '%s.cstr(%s)'%(self,l) _l=[] assert len(self) i=0 while isinstance(self[i],Declarator): _l.append( self[i].cstr() ) i=i+1 l.append( '(%s)'% ', '.join(_l) ) while i<len(self): self[i].cstr(l) i=i+1 return " ".join(l) def return_type(self): node = self[-1] #assert isinstance(node,DeclarationSpecifiers) return Declarator( Identifier(), node ) ret = property(return_type) def get_args(self): args = [ arg for arg in self[:-1] if not arg.is_void() ] return args args = property(get_args) def arg_types(self): return [ AbstractDeclarator().init_from( arg.ctype() ) for arg in self[:-1]] def is_varargs(self): for node in self.nodes(): if isinstance(node,Ellipses) or 'va_list' in node: # print self, 'is_varargs' return True # print self, 'is_varargs' return False # return fn.deepfind(Ellipses) or fn.deepfind('va_list') def ctype(self): return Function(*self.arg_types()+[self[-1]]) # XX self[-1].ctype class Pointer(genpyx.Pointer, Node): """ """ def get_spec(self): if type(self[0])==TypeSpecifiers: # isinstance ?? return self[0] spec = property(get_spec) #def explain(self): #return "pointer to" def cstr(self,l): assert len(self) node=self[0] l.insert(0,'*') if isinstance(node,Function): l.insert(0,'(') l.append(')') elif isinstance(node,Array): l.insert(0,'(') l.append(')') return Node.cstr(self,l) class Array(genpyx.Array, Node): """ """ #def explain(self): #s='' #if len(self): #if type(self[0])==int: #s='0 to %s '%(self[0]-1) #return "array %sof"%s def has_size(self): try: int(self.size) return True except: return False def get_size(self): if type(self[-1])==str: try: return int(self[-1]) except: return self[-1] return self[-1] # None size = property(get_size) def get_spec(self): if type(self[0])==TypeSpecifiers: # isinstance ?? return self[0] spec = property(get_spec) def to_pointer(self): node = Pointer() node.init_from( self.clone() ) node.pop() # pop the size element return node def cstr(self,l): if self.size is None: l.append('[]') else: l.append('[%s]'%self.size) return Node( *self[:-1] ).cstr( l ) class Tag(genpyx.Tag, Named): " the tag of a Struct, Union or Enum " pass class Taged(genpyx.Taged, Node): "Struct, Union or Enum " def get_tag(self): if len(self): tag = self[0] assert type(tag)==Tag # isinstance ?? else: tag = None return tag def set_tag(self,tag): if len(self): self[0] = tag else: self.append(tag) tag = property( get_tag, set_tag ) def has_members(self): return len(self)>1 # more than just a tag def get_members(self): return self[1:] members = property(get_members) # fields ? def ctype(self): if not self.tag.name: #print "# WARNING : anonymous struct " # OK i think return self.clone() # self = self.clone() # return self[:1] # just the tag return self.__class__( self.tag, **self.__dict__ ) # just the Tag # return self.__class__( *self, **self.__dict__ ) def cbasetype(self): return self.ctype() # is this enough ??? # return Node.cbasetype(self) # XX lookup my tag if i am empty ..? class Compound(genpyx.Compound, Taged): "Struct or Union" def cstr(self,_l=None): assert isinstance( self[0], Tag ) tag='' if len(self[0]): tag=' '+self[0][0] if isinstance(self,Struct): l=[ 'struct%s '%tag ] elif isinstance(self,Union): l=[ 'union%s '%tag ] if len(self)>1: l.append(' { ') for decl in self[1:]: l.append( decl.cstr()+"; " ) l.append('} ') if _l is None: _l=[] while l: _l.insert( 0, l.pop() ) # XX empty struct with no tag -> "struct" XX return "".join( _l ) def ctype(self): tp = Taged.ctype(self) for i in range(1,len(tp)): tp[i] = StructDeclarator().init_from( tp[i] ) return tp class Struct(genpyx.Struct, Compound): """ """ pass class Union(genpyx.Union, Compound): """ """ pass class Enum(genpyx.Enum, Taged): """ """ def cstr(self,_l=None): assert isinstance( self[0], Tag ) tag='' if len(self[0]): tag=' '+self[0][0] l=[ 'enum%s '%tag ] if len(self)>1: l.append(' { ') for node in self[1:]: l.append( node.cstr()+', ' ) l.append('} ') if _l is None: _l=[] while l: _l.insert( 0, l.pop() ) return ''.join( _l ) class Declarator(genpyx.Declarator, Node): """ """ def __eq__(self,other): " unordered equality " # ordering sometimes gets lost when we do a cbasetype if not isinstance(other,Node): return False a, b = self[:], other[:] a.sort() b.sort() return a == b def __hash__( self ): hs = [hash(item) for item in self] hs.sort() return hash( tuple([hash(type(self))]+hs) ) def transform(self): return def get_identifier(self): if len(self)>1: return self[0] def set_identifier(self, identifier): if len(self)>1: self[0] = identifier else: self.insert(0,identifier) identifier = property(get_identifier,set_identifier) def get_spec(self): spec = self[-1] if type(spec)==TypeSpecifiers: # isinstance ?? return spec spec = property(get_spec) def get_type_alias(self): if self.spec: if isinstance(self.spec[0], TypeAlias): return self.spec[0] type_alias = property(get_type_alias) def get_tagged(self): if self.spec: return self.spec.tagged # i am a tagged tagged = property(get_tagged) def get_compound(self): if self.spec: return self.spec.compound # i am a compound compound = property(get_compound) def get_struct(self): if self.spec: return self.spec.struct # i am a struct struct = property(get_struct) def get_union(self): if self.spec: return self.spec.union # i am a union union = property(get_union) def get_enum(self): if self.spec: return self.spec.enum # i am an enum enum = property(get_enum) def get_function(self): if len(self)>1 and type(self[1])==Function: # isinstance ?? return self[1] function = property(get_function) def get_pointer(self): if len(self)>1 and type(self[1])==Pointer: # isinstance ?? return self[1] pointer = property(get_pointer) def get_array(self): if len(self)>1 and type(self[1])==Array: # isinstance ?? return self[1] array = property(get_array) def get_name(self): if self.identifier: return self.identifier.name def set_name(self, name): assert self.identifier is not None self.identifier.name = name name = property(get_name, set_name) def get_rest(self): # XX needs a better name if len(self)>1: return self[1] return self[0] def pointer_to( self ): " return Declarator pointing to self's type " decl = Declarator(Identifier(), Pointer(self.get_rest().clone())) return decl def deref( self ): " return (clone of) Declarator that self is pointing to " node = self.ctype() # clone pointer = node.pointer or node.array assert pointer, "cannot dereference non-pointer" node[1:2] = pointer return node def is_void(self): return self.spec and BasicType('void') in self.spec def is_pointer_to_fn(self): return self.pointer and self.deref().function def is_pointer_to_char(self): # return self.ctype() == TransUnit("char *a;").transform()[0].ctype() node = self.pointer or self.array if node: spec = node.spec if spec and BasicType('char') in spec and not BasicType('unsigned') in spec: return True return False def is_callback(self): " i am a pointer to a function whose last arg is void* " if self.is_pointer_to_fn(): fn = self.deref().function if fn.args: arg = fn.args[-1] if arg.pointer and arg.deref().is_void(): return True def is_complete( self, tag_lookup ): if self.tagged and self.tagged.tag.name in tag_lookup and not tag_lookup[self.tagged.tag.name].has_members(): return False return True def is_primative( self ): "i am a char,short,int,float,double... " spec = self.cbasetype().spec return spec and spec.find(BasicType) def is_pyxnative( self ): # pyrex handles char* too # but i don't know if we should make this the default # sometimes we want to send a NULL, so ... XXX self = self.cbasetype() if self.is_void(): return False if self.is_primative(): return True if self.enum: return True # pointer = None # if self.pointer: # pointer = self.pointer # elif self.array: # pointer = self.array # if pointer and pointer.spec: # spec = pointer.spec # if BasicType("char") in spec and not Qualifier("unsigned") in spec: # # char*, const char* ## print self.deepstr() # return True return False def cstr(self,l=None): return Node.cstr(self,l).strip() def ctype(self): decl=Declarator() decl.init_from( self.clone() ) decl.identifier = Identifier() for i in range(1,len(decl)): decl[i]=decl[i].ctype() return decl def cbasetype(self): # WARNING: we cache results (so do not mutate self!!) try: # this cache improves performance by 50% return self.__cbasetype.clone() except AttributeError: pass decl = self.ctype() # gets rid of Identifier names for i, node in enumerate(decl): decl[i] = decl[i].cbasetype() # return decl.get_rest() done = False while not done: done = True nodes = decl.deepfilter( TypeSpecifiers ) for node in nodes: if node.deepfind( TypeSpecifiers ) != node: # this node has another TypeSpecifier; decl.expose_node( node ) done = False break # start again... # each TypeSpecifier needs to absorb primitive siblings (StorageClass, BasicType etc.) nodes = decl.deepfilter( TypeSpecifiers ) for node in nodes: parent = decl.get_parent(node) i = 0 while i < len(parent): assert not type(parent[i]) in (TypeAlias, Enum, Struct, Union) if type(parent[i]) in (StorageClass, BasicType, Qualifier): node.append( parent.pop(i) ) else: i = i + 1 self.__cbasetype = decl.clone() return decl def invalidate(self): # flush cache, etc. try: del self.__cbasetype except AttributeError: pass def declare_str(self,name): " return c string declaring name with same type as self " tp = self.ctype() tp.name = name return tp.cstr()+";" class Typedef(genpyx.Typedef, Declarator): def cstr(self,l=None): return 'typedef ' + Declarator.cstr(self,l) #.strip() class AbstractDeclarator(genpyx.AbstractDeclarator, Declarator): """ used in Function; may lack an identifier """ #def cstr(self,l=None): #return Node.cstr(self,l) # def ctype(self): # # _type_ ignores the name of our identifier # return Node.ctype(self) class FieldLength(genpyx.FieldLength, Node): """ """ #def explain(self): #return "" def cstr(self,l): l.append(':%s'%self[0]) class StructDeclarator(genpyx.StructDeclarator, Declarator): # also used in Union """ """ #def explain(self): #flen = self.find(FieldLength) #if flen is not None: #i = self.index(flen) #self.pop(i) #s = Declarator.explain(self) #self.insert(i,flen) #width = flen[0] #if width > 0: #return s+" bitfield %s wide"%width #else: #return s+" alignment bitfield" #else: #return Declarator.explain(self) # def ctype(self): # return self def get_field_length(self): if len(self)>1 and isinstance( self[1], FieldLength ): return self[1] field_length = property(get_field_length) class DeclarationSpecifiers(genpyx.DeclarationSpecifiers, Node): #class TypeSpecifiers(Node): """ """ def __eq__(self,other): " unordered equality " if not isinstance(other,Node): return False a, b = self[:], other[:] a.sort() b.sort() return a == b def __hash__( self ): hs = [hash(item) for item in self] hs.sort() return hash( tuple([hash(type(self))]+hs) ) # def is_struct(self): # return self.find(Struct) is not None class TypeSpecifiers(genpyx.TypeSpecifiers, DeclarationSpecifiers): """ """ def get_tagged(self): if self and isinstance(self[0],Taged): return self[0] tagged = property(get_tagged) def get_compound(self): if self and isinstance(self[0],Compound): return self[0] compound = property(get_compound) def get_struct(self): if self and isinstance(self[0],Struct): return self[0] struct = property(get_struct) def get_union(self): if self and isinstance(self[0],Union): return self[0] union = property(get_union) def get_enum(self): if self and isinstance(self[0],Enum): return self[0] enum = property(get_enum) def cbasetype(self): node = Node.cbasetype(self) # node.expose( TypeSpecifiers ) # if node.deepfind(TypeSpecifiers) != node: return node class Initializer(genpyx.Initializer, Node): """ """ pass class Declaration(genpyx.Declaration, Node): """ """ def do_spec(self): " distribute DeclarationSpecifiers over each Declarator " spec=self[0] assert isinstance(spec,DeclarationSpecifiers), spec.deepstr() self.pop(0) for declarator in self: assert isinstance(declarator,Declarator) #if isinstance(declarator,DeclarationSpecifiers #huh? ##for node in spec: ##declarator.append(node.clone()) declarator.append(spec) def transform(self): # children go first for node in self.nodes(): if isinstance(node,Declaration): node.do_spec() node.file = self.file # overkill ? self.expose(Declaration) #def explain(self): #return string.join([x.explain() for x in self],", ") #return string.join(map(lambda x:x.explain(),self),", ") class ParameterDeclaration(genpyx.ParameterDeclaration, Declaration): """ """ pass class StructDeclaration(genpyx.StructDeclaration, Declaration): """ """ pass class TransUnit(genpyx.TransUnit, Node): """ Top level node. """ def __init__( self, item ): # XX __init__ uses different signature ! XX if type(item)==str: node = cparse.TransUnit() node.parse(item) else: node = item assert isinstance( node, cparse.TransUnit ), str(node) Node.__init__(self) self[:] = [ self.convert(child) for child in node ] self.__dict__.update( node.__dict__ ) assert "name" not in node.__dict__ self.syms = {} # map identifier names to their Declarator's self.typedefs = {} # map names to Typedef's self.tag_lookup = {} # map struct, union, enum tags to Taged's # XX should call transform here XX # print self.deepstr() def __getstate__( self ): nodes = tuple( [ repr(node) for node in self ] ) typedefs = tuple( [ (key,repr(val)) for key,val in self.typedefs.items() ] ) return nodes, typedefs def __setstate__( self, state ): Node.__init__(self) nodes, typedefs = state nodes = [ eval(node) for node in nodes ] self[:] = nodes typedefs = [ (key,eval(val)) for key,val in typedefs ] self.typedefs = dict(typedefs) def convert( self, node ): # name = node.__class__.__name__ # cls = globals()[ name ] cls = cls_lookup[ type(node) ] _node = cls() for child in node: if isinstance(child, node_module.Node): child = self.convert( child ) else: assert child is None or type(child) in (str, int), type(child) _node.append( child ) _node.__dict__.update( node.__dict__ ) return _node def strip(self,files): " leave only the declarations from <files> " i=0 while i<len(self): if self[i].file in files: i=i+1 else: self.pop(i) def mark(self,cb,verbose=False): " mark our child nodes such that cb(node).. mark dependants too. prune unmarked objects. " # mark the nodes: for node in self: node.marked = cb(self, node) if verbose and node.marked: print '1:', node.cstr() # propagate dependancy: i=len(self) while i: i-=1 # we go backwards for node in self[i].nodes(): # bottom-up search if verbose and self[i].marked and not node.marked: print '2:', str(node), '<--', self[i].cstr() node.marked = self[i].marked or node.marked if type(node)==TypeAlias: if verbose and node.marked and not node.typedef.marked: print '3:', node.typedef.cstr(), '<--', node.cstr() node.typedef.marked = node.typedef.marked or node.marked if isinstance(node, Taged): if node.tag.name in self.tag_lookup: _node = self.tag_lookup[ node.tag.name ] # look-up the def'n if verbose and node.marked and not _node.marked: print '4:', _node.cstr(), '<--', self[i].cstr() # _node.marked = _node.marked or self[i].marked _node.marked = _node.marked or node.marked # else: # # this guy has no tag # print "lost tag:", self[i].cstr() # XX struct defs acquire marks from members, but XX # XX ordinary definitions do not XX # if node.marked and not self[i].marked: # # one of my descendants is marked # if verbose: # print '5:', self[i].cstr(), '<--', node.cstr() # self[i].marked = True # if verbose: # for node in self: # print '-'*79 # if node.enum: # print str(node.marked) + ': ' + node.cstr() # prune: f = open(".tmp/pruned.txt","w") f.write("// This file autogenerated by '%s' .\n"%__file__) f.write("// List of functions pruned from parse tree, for various reasons.\n\n") i=0 while i<len(self): if not self[i].marked: if verbose: print 'pop:', self[i].cstr() f.write( self[i].cstr() + "\n" ) self.pop(i) # elif self[i].compound: # # XXXX for now, rip out all struct members XXXX # self[i].compound[1:] = [] # XX encapsulation # i = i + 1 else: i = i + 1 for key, value in self.syms.items(): if not value.marked: del self.syms[key] for key, value in self.typedefs.items(): if not value.marked: del self.typedefs[key] for key, value in self.tag_lookup.items(): if not value.marked: del self.tag_lookup[key] # sys.exit(1) def assert_no_dups(self): check={} for node in self.nodes(): assert not check.has_key(id(node)) check[id(node)]=1 def transform(self, verbose=False, test_parse=False, test_types=False ): i=0 while i < len(self): if verbose: print "##"*25 declaration=self[i] if verbose: declaration.psource() if verbose: print declaration.deepstr(),'\n' assert isinstance(declaration,Declaration) if verbose: print "# expose declarators from declaration" # STAGE 1 declaration.transform() if verbose: print declaration.deepstr(),'\n' self[i:i+1] = declaration # expose declarators from declaration for j in range(len(declaration)): declarator=self[i] assert isinstance(declarator,Declarator) if verbose: print "# declarator.transform()" # STAGE 2 declarator.transform() if verbose: print declarator.deepstr(),'\n' if verbose: print "# self.visit_declarator(declarator)" # STAGE 3 self[i] = declarator = self.visit_declarator(declarator) # STAGE 4 if declarator.name: if isinstance(declarator, Typedef): if verbose: print "# typedef %s" % declarator.name self.typedefs[ declarator.name ] = declarator else: if verbose: print "# sym %s" % declarator.name self.syms[ declarator.name ] = declarator for node in declarator.nodes(): if isinstance(node,Taged) and node.tag.name: assert type(node.tag.name)==str, node.deepstr() taged = self.tag_lookup.get( node.tag.name, None ) if taged is None: if verbose: print "# tag lookup %s = %s" % (declarator.name, node.tag.name) self.tag_lookup[ node.tag.name ] = node elif not taged.has_members(): # this is (maybe) the definition of this tag if verbose: print "# definition %s = %s" % (declarator.name, node.tag.name) self.tag_lookup[ node.tag.name ] = node # Annotate the TypeAlias's for node in declarator.deepfilter( TypeAlias ): name = node[0] assert type( name ) == str node.typedef = self.typedefs[ name ] if verbose: print declarator.deepstr(),'\n' #print declarator.ctype().deepstr(),'\n' #assert declarator.clone() == declarator ################################################### # TESTS: if test_parse: # test that parse of cstr gives same answer cstr = declarator.cstr()+';\n' if verbose: print '# '+cstr.replace('\n','\n# ') #print if isinstance(declarator,Typedef): name = declarator[0][0] assert type(name)==str self.lexer.rmtypedef( name ) declaration = cparse.Declaration() self.lexer.lex( cstr ) #print self.lexer.err_string() declaration.parse( self.lexer, Symbols() ) # use new name-space #declaration.parse( Lexer( cstr ), Symbols() ) declaration = self.convert(declaration) declaration.transform() assert len(declaration)==1 decl=declaration[0] decl.transform() decl = self.visit_declarator(decl) if decl!=declarator: if verbose: print "#???????????" if verbose: print decl.deepstr(),'\n\n' #if verbose: print declaration.deepstr(),'\n\n' #assert 0 elif verbose: print '# OK\n' if test_types: node = declarator.ctype() declare_str= node.declare_str("my_name") if verbose: print "# declarator.ctype() " if verbose: print node.deepstr(),"\n" if verbose: print "#",declare_str.replace('\n','\n# '), '\n' i=i+1 return self def visit(self,node): #print 'visit(%s)'%node for _node in node: if isinstance(_node,Declarator): _node = self.visit_declarator(_node) # XX replace _node elif isinstance(_node,Node): _node = self.visit(_node) # XX replace _node return node def visit_declarator(self,decl): assert isinstance(decl,Declarator) # STAGE 3.a tp = decl.deepfind(Typedef) if tp is not None: decl.deeprm(tp) tp.init_from( decl ) # warning: shallow init decl = tp # STAGE 3.b i=len(decl) # accumulate nodes (they become the children of decl) children=[] while i: i=i-1 node=decl.pop(i) if isinstance(node,Declarator): node = self.visit_declarator(node) # replace node else: node = self.visit(node) # replace node if isinstance(node,Pointer): node+=children children=[node] elif isinstance(node,Function): node+=children children=[node] elif isinstance(node,Array): while children: node.insert(0,children.pop()) children=[node] # array size (if any) at end #elif isinstance(node,Identifier): #node+=children #children=[node] else: # accumulate children.insert(0,node) decl[:]=children return decl cstr = None ctype = None cbasetype = None # remap the global class definitions in genpyx to # point to the definitions in this module gbl = globals() for key, val in gbl.items(): if type(val)==type: if issubclass(val,Node): setattr( genpyx, key, val ) assert genpyx.Node == Node cls_lookup = { # Node : Node , cparse.BasicType : BasicType , cparse.Qualifier : Qualifier , cparse.StorageClass : StorageClass , cparse.Ellipses : Ellipses , cparse.GCCBuiltin : GCCBuiltin , cparse.Identifier : Identifier , cparse.TypeAlias : TypeAlias , cparse.Function : Function , cparse.Pointer : Pointer , cparse.Array : Array , cparse.Tag : Tag , cparse.Compound : Compound , cparse.Struct : Struct , cparse.Union : Union , cparse.Enum : Enum , cparse.Declarator : Declarator , cparse.Typedef : Typedef , cparse.AbstractDeclarator : AbstractDeclarator , cparse.FieldLength : FieldLength , cparse.StructDeclarator : StructDeclarator , cparse.DeclarationSpecifiers : TypeSpecifiers , cparse.TypeSpecifiers : TypeSpecifiers , cparse.Initializer : Initializer , cparse.Declaration : Declaration , cparse.ParameterDeclaration : ParameterDeclaration , cparse.StructDeclaration : StructDeclaration , cparse.TransUnit : TransUnit , }