Bug 521898, part 5: Prepare for TU .protocol possibly being null (for headers). r=bent
authorChris Jones <jones.chris.g@gmail.com>
Fri, 08 Jun 2012 17:25:36 -0700
changeset 101027 fece9a6bae3f360c8878362e91ae4fce46653aa7
parent 101026 f713eb64e8e1370a38c12a9bd4a73f269cc3a6a2
child 101028 54a3bbdcfe04da3c89587181f19ce2ad7d184630
push id1316
push userakeybl@mozilla.com
push dateMon, 27 Aug 2012 22:37:00 +0000
treeherdermozilla-beta@db4b09302ee2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbent
bugs521898
milestone16.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 521898, part 5: Prepare for TU .protocol possibly being null (for headers). r=bent
ipc/ipdl/ipdl.py
ipc/ipdl/ipdl/ast.py
ipc/ipdl/ipdl/lower.py
ipc/ipdl/ipdl/parser.py
ipc/ipdl/ipdl/type.py
--- a/ipc/ipdl/ipdl.py
+++ b/ipc/ipdl/ipdl.py
@@ -80,17 +80,19 @@ for f in files:
 
 # Second pass: generate code
 for f in files:
     # Read from parser cache
     filename = normalizedFilename(f)
     ast = ipdl.parse(None, filename, includedirs=includedirs)
     ipdl.gencxx(filename, ast, headersdir, cppdir)
     
-    allprotocols.append('%sMsgStart' % ast.protocol.name)
+    if ast.protocol:
+        allprotocols.append('%sMsgStart' % ast.protocol.name)
+
 
 allprotocols.sort()
 
 ipcmsgstart = StringIO()
 
 print >>ipcmsgstart, """
 // CODE GENERATED by ipdl.py. Do not edit.
 
--- a/ipc/ipdl/ipdl/ast.py
+++ b/ipc/ipdl/ipdl/ast.py
@@ -13,17 +13,19 @@ class Visitor:
         for cxxInc in tu.cxxIncludes:
             cxxInc.accept(self)
         for inc in tu.includes:
             inc.accept(self)
         for su in tu.structsAndUnions:
             su.accept(self)
         for using in tu.using:
             using.accept(self)
-        tu.protocol.accept(self)
+        if tu.protocol:
+            tu.protocol.accept(self)
+
 
     def visitCxxInclude(self, inc):
         pass
 
     def visitInclude(self, inc):
         # Note: we don't visit the child AST here, because that needs delicate
         # and pass-specific handling
         pass
--- a/ipc/ipdl/ipdl/lower.py
+++ b/ipc/ipdl/ipdl/lower.py
@@ -20,30 +20,38 @@ EMIT_LOGGING_CODE = ('win32' == sys.plat
 ##
 class LowerToCxx:
     def lower(self, tu):
         '''returns |[ header: File ], [ cpp : File ]| representing the
 lowered form of |tu|'''
         # annotate the AST with IPDL/C++ IR-type stuff used later
         tu.accept(_DecorateWithCxxStuff())
 
-        pname = tu.protocol.name
-
-        pheader, pcpp = File(pname +'.h'), File(pname +'.cpp')
+        name = tu.name
+        pheader, pcpp = File(name +'.h'), File(name +'.cpp')
+
         _GenerateProtocolCode().lower(tu, pheader, pcpp)
-
-        parentheader, parentcpp = File(pname +'Parent.h'), File(pname +'Parent.cpp')
-        _GenerateProtocolParentCode().lower(
-            tu, pname+'Parent', parentheader, parentcpp)
-
-        childheader, childcpp = File(pname +'Child.h'), File(pname +'Child.cpp')
-        _GenerateProtocolChildCode().lower(
-            tu, pname+'Child', childheader, childcpp)
-
-        return [ pheader, parentheader, childheader ], [ pcpp, parentcpp, childcpp ]
+        headers = [ pheader ]
+        cpps = [ pcpp ]
+
+        if tu.protocol:
+            pname = tu.protocol.name
+
+            parentheader, parentcpp = File(pname +'Parent.h'), File(pname +'Parent.cpp')
+            _GenerateProtocolParentCode().lower(
+                tu, pname+'Parent', parentheader, parentcpp)
+
+            childheader, childcpp = File(pname +'Child.h'), File(pname +'Child.cpp')
+            _GenerateProtocolChildCode().lower(
+                tu, pname+'Child', childheader, childcpp)
+
+            headers += [ parentheader, childheader ]
+            cpps += [ parentcpp, childcpp ]
+
+        return headers, cpps
 
 
 ##-----------------------------------------------------------------------------
 ## Helper code
 ##
 
 _NULL_ACTOR_ID = ExprLiteral.ZERO
 _FREED_ACTOR_ID = ExprLiteral.ONE
@@ -1337,23 +1345,25 @@ class _GenerateProtocolCode(ipdl.ast.Vis
 
         cf = self.cppfile
         cf.addthings((
             [ _DISCLAIMER, Whitespace.NL ]
             + [ CppDirective('include','"'+h+'.h"')
                 for h in self.cppIncludeHeaders ]
             + [ Whitespace.NL ]
         ))
-       
-        # construct the namespace into which we'll stick all our defns
-        ns = Namespace(self.protocol.name)
-        cf.addthing(_putInNamespaces(ns, self.protocol.namespaces))
-        ns.addstmts(([ Whitespace.NL]
-                     + self.funcDefns
-                     +[ Whitespace.NL ]))
+
+        if self.protocol:       
+            # construct the namespace into which we'll stick all our defns
+            ns = Namespace(self.protocol.name)
+            cf.addthing(_putInNamespaces(ns, self.protocol.namespaces))
+            ns.addstmts(([ Whitespace.NL]
+                         + self.funcDefns
+                         +[ Whitespace.NL ]))
+
         cf.addthings(self.structUnionDefns)
 
 
     def visitCxxInclude(self, inc):
         self.hdrfile.addthing(CppDirective('include', '"'+ inc.file +'"'))
 
     def processStructOrUnionClass(self, su, which, forwarddecls, cls):
         clsdecl, methoddefns = _splitClassDeclDefn(cls)
@@ -2435,16 +2445,18 @@ class _GenerateProtocolActorCode(ipdl.as
             clsdefn,
             Whitespace.NL,
             Whitespace.NL
         ])
 
 
     def visitInclude(self, inc):
         ip = inc.tu.protocol
+        if not ip:
+            return
 
         self.hdrfile.addthings([
             _makeForwardDeclForActor(ip.decl.type, self.side),
             Whitespace.NL
         ])
         self.protocolCxxIncludes.append(
             CppDirective(
                 'include',
--- a/ipc/ipdl/ipdl/parser.py
+++ b/ipc/ipdl/ipdl/parser.py
@@ -201,18 +201,19 @@ def p_TranslationUnit(p):
             if tu.protocol is not None:
                 _error(thing.loc, "only one protocol definition per file")
             tu.protocol = thing
         else:
             assert(0)
 
     # The "canonical" namespace of the tu, what it's considered to be
     # in for the purposes of C++: |#include "foo/bar/TU.h"|
-    tu.namespaces = tu.protocol.namespaces
-    tu.name = tu.protocol.name
+    if tu.protocol:
+        tu.namespaces = tu.protocol.namespaces
+        tu.name = tu.protocol.name
 
     p[0] = tu
 
 ##--------------------
 ## Preamble
 def p_Preamble(p):
     """Preamble : Preamble PreambleStmt ';'
                 |"""
--- a/ipc/ipdl/ipdl/type.py
+++ b/ipc/ipdl/ipdl/type.py
@@ -561,17 +561,18 @@ With this information, it finally type c
         # now that the nodes have decls, type checking is much easier.
         if not runpass(CheckTypes(self.errors)):
             return False
 
         if not (runpass(BuildProcessGraph(self.errors))
                 and runpass(CheckProcessGraph(self.errors))):
             return False
 
-        if (len(tu.protocol.startStates)
+        if (tu.protocol
+            and len(tu.protocol.startStates)
             and not runpass(CheckStateMachine(self.errors))):
             return False
         return True
 
     def reportErrors(self, errout):
         for error in self.errors:
             print >>errout, error
 
@@ -607,47 +608,51 @@ class GatherDecls(TcheckVisitor):
         tu.symtab = SymbolTable(self.errors)
         savedSymtab = self.symtab
         self.symtab = tu.symtab
 
         # pretend like the translation unit "using"-ed these for the
         # sake of type checking and C++ code generation
         tu.using = self.builtinUsing + tu.using
 
-        p = tu.protocol
+        if tu.protocol:
+            assert tu.name == tu.protocol.name
+
+            p = tu.protocol
 
-        # for everyone's sanity, enforce that the filename and
-        # protocol name match
-        basefilename = os.path.basename(tu.filename)
-        expectedfilename = '%s.ipdl'% (p.name)
+            # for everyone's sanity, enforce that the filename and
+            # protocol name match
+            basefilename = os.path.basename(tu.filename)
+            expectedfilename = '%s.ipdl'% (p.name)
 
-        if basefilename != expectedfilename:
-            self.error(p.loc,
-                       "expected file defining protocol `%s' to be named `%s'; instead it's named `%s'",
-                       p.name, expectedfilename, basefilename)
+            if basefilename != expectedfilename:
+                self.error(p.loc,
+                           "expected file defining protocol `%s' to be named `%s'; instead it's named `%s'",
+                           p.name, expectedfilename, basefilename)
 
-        # FIXME/cjones: it's a little weird and counterintuitive to put
-        # both the namespace and non-namespaced name in the global scope.
-        # try to figure out something better; maybe a type-neutral |using|
-        # that works for C++ and protocol types?
-        qname = p.qname()
-        if 0 == len(qname.quals):
-            fullname = None
-        else:
-            fullname = str(qname)
-        p.decl = self.declare(
-            loc=p.loc,
-            type=ProtocolType(qname, p.sendSemantics,
-                              stateless=(0 == len(p.transitionStmts))),
-            shortname=p.name,
-            fullname=fullname)
+            # FIXME/cjones: it's a little weird and counterintuitive
+            # to put both the namespace and non-namespaced name in the
+            # global scope.  try to figure out something better; maybe
+            # a type-neutral |using| that works for C++ and protocol
+            # types?
+            qname = p.qname()
+            if 0 == len(qname.quals):
+                fullname = None
+            else:
+                fullname = str(qname)
+            p.decl = self.declare(
+                loc=p.loc,
+                type=ProtocolType(qname, p.sendSemantics,
+                                  stateless=(0 == len(p.transitionStmts))),
+                shortname=p.name,
+                fullname=fullname)
 
-        # XXX ugh, this sucks.  but we need this information to compute
-        # what friend decls we need in generated C++
-        p.decl.type._ast = p
+            # XXX ugh, this sucks.  but we need this information to compute
+            # what friend decls we need in generated C++
+            p.decl.type._ast = p
 
         # make sure we have decls for all dependent protocols
         for pinc in tu.includes:
             pinc.accept(self)
 
         # declare imported (and builtin) C++ types
         for using in tu.using:
             using.accept(self)
@@ -676,32 +681,35 @@ class GatherDecls(TcheckVisitor):
                 type=sutype,
                 shortname=su.name,
                 fullname=fullname)
 
         # second pass to check each definition
         for su in tu.structsAndUnions:
             su.accept(self)
 
-        # grab symbols in the protocol itself
-        p.accept(self)
+        if tu.protocol:
+            # grab symbols in the protocol itself
+            p.accept(self)
+
 
         tu.type = VOID
 
         self.symtab = savedSymtab
 
 
     def visitInclude(self, inc):
         if inc.tu is None:
             self.error(
                 inc.loc,
                 "(type checking here will be unreliable because of an earlier error)")
             return
         inc.tu.accept(self)
-        self.symtab.declare(inc.tu.protocol.decl)
+        if inc.tu.protocol:
+            self.symtab.declare(inc.tu.protocol.decl)
 
     def visitStructDecl(self, sd):
         stype = sd.decl.type
 
         self.symtab.enterScope(sd)
 
         for f in sd.fields:
             ftypedecl = self.symtab.lookup(str(f.typespec))
@@ -1187,17 +1195,18 @@ class CheckTypes(TcheckVisitor):
         TcheckVisitor.__init__(self, None, errors)
         self.visited = set()
         self.ptype = None
 
     def visitInclude(self, inc):
         if inc.tu.filename in self.visited:
             return
         self.visited.add(inc.tu.filename)
-        inc.tu.protocol.accept(self)
+        if inc.tu.protocol:
+            inc.tu.protocol.accept(self)
 
 
     def visitStructDecl(self, sd):
         if not fullyDefined(sd.decl.type):
             self.error(sd.decl.loc,
                        "struct `%s' is only partially defined", sd.name)
 
     def visitUnionDecl(self, ud):
@@ -1589,17 +1598,18 @@ class BuildProcessGraph(TcheckVisitor):
     class findSpawns(TcheckVisitor):
         def __init__(self, errors):
             TcheckVisitor.__init__(self, None, errors)
 
         def visitTranslationUnit(self, tu):
             TcheckVisitor.visitTranslationUnit(self, tu)
 
         def visitInclude(self, inc):
-            inc.tu.protocol.accept(self)
+            if inc.tu.protocol:
+                inc.tu.protocol.accept(self)
 
         def visitProtocol(self, p):
             ptype = p.decl.type
             # non-top-level protocols don't add any information
             if not ptype.isToplevel() or ptype in ProcessGraph.visitedSpawns:
                 return
 
             ProcessGraph.visitedSpawns.add(ptype)
@@ -1626,17 +1636,18 @@ class BuildProcessGraph(TcheckVisitor):
         self.visiting = None            # ActorType
         self.visited = set()            # set(ActorType)
 
     def visitTranslationUnit(self, tu):
         tu.accept(self.findSpawns(self.errors))
         TcheckVisitor.visitTranslationUnit(self, tu)
 
     def visitInclude(self, inc):
-        inc.tu.protocol.accept(self)
+        if inc.tu.protocol:
+            inc.tu.protocol.accept(self)
 
     def visitProtocol(self, p):
         ptype = p.decl.type
         # non-top-level protocols don't add any information
         if not ptype.isToplevel() or ptype in ProcessGraph.visitedBridges:
             return
 
         ProcessGraph.visitedBridges.add(ptype)