зеркало из https://github.com/mozilla/gecko-dev.git
Bug 560000: Allow IPDL unions and structs to be recursively defined. r=benjamn
This commit is contained in:
Родитель
ca7af8ea8c
Коммит
81dfc13752
|
@ -459,7 +459,8 @@ class FriendClassDecl(Node):
|
|||
|
||||
class MethodDecl(Node):
|
||||
def __init__(self, name, params=[ ], ret=Type('void'),
|
||||
virtual=0, const=0, pure=0, static=0, warn_unused=0, inline=0,
|
||||
virtual=0, const=0, pure=0, static=0, warn_unused=0,
|
||||
inline=0, force_inline=0,
|
||||
typeop=None,
|
||||
T=None):
|
||||
assert not (virtual and static)
|
||||
|
@ -468,6 +469,8 @@ class MethodDecl(Node):
|
|||
assert not (name and typeop)
|
||||
assert name is None or isinstance(name, str)
|
||||
assert not isinstance(ret, list)
|
||||
for decl in params: assert not isinstance(decl, str)
|
||||
assert not isinstance(T, int)
|
||||
|
||||
if typeop is not None:
|
||||
ret = None
|
||||
|
@ -481,19 +484,25 @@ class MethodDecl(Node):
|
|||
self.pure = pure # bool
|
||||
self.static = static # bool
|
||||
self.warn_unused = warn_unused # bool
|
||||
self.inline = (inline or T) # bool
|
||||
self.force_inline = (force_inline or T) # bool
|
||||
self.inline = inline # bool
|
||||
self.typeop = typeop # Type or None
|
||||
self.T = T # Type or None
|
||||
|
||||
def __deepcopy__(self, memo):
|
||||
return MethodDecl(
|
||||
self.name,
|
||||
copy.deepcopy(self.params, memo),
|
||||
copy.deepcopy(self.ret, memo),
|
||||
self.virtual, self.const, self.pure, self.static, self.warn_unused,
|
||||
copy.deepcopy(self.typeop, memo),
|
||||
copy.deepcopy(self.T, memo),
|
||||
self.inline)
|
||||
params=copy.deepcopy(self.params, memo),
|
||||
ret=copy.deepcopy(self.ret, memo),
|
||||
virtual=self.virtual,
|
||||
const=self.const,
|
||||
pure=self.pure,
|
||||
static=self.static,
|
||||
warn_unused=self.warn_unused,
|
||||
inline=self.inline,
|
||||
force_inline=self.force_inline,
|
||||
typeop=copy.deepcopy(self.typeop, memo),
|
||||
T=copy.deepcopy(self.T, memo))
|
||||
|
||||
class MethodDefn(Block):
|
||||
def __init__(self, decl):
|
||||
|
@ -501,8 +510,9 @@ class MethodDefn(Block):
|
|||
self.decl = decl
|
||||
|
||||
class ConstructorDecl(MethodDecl):
|
||||
def __init__(self, name, params=[ ], explicit=0):
|
||||
MethodDecl.__init__(self, name, params=params, ret=None)
|
||||
def __init__(self, name, params=[ ], explicit=0, force_inline=0):
|
||||
MethodDecl.__init__(self, name, params=params, ret=None,
|
||||
force_inline=force_inline)
|
||||
self.explicit = explicit
|
||||
|
||||
def __deepcopy__(self, memo):
|
||||
|
@ -516,12 +526,16 @@ class ConstructorDefn(MethodDefn):
|
|||
self.memberinits = memberinits
|
||||
|
||||
class DestructorDecl(MethodDecl):
|
||||
def __init__(self, name, virtual=0):
|
||||
def __init__(self, name, virtual=0, force_inline=0, inline=0):
|
||||
MethodDecl.__init__(self, name, params=[ ], ret=None,
|
||||
virtual=virtual)
|
||||
virtual=virtual,
|
||||
force_inline=force_inline, inline=inline)
|
||||
|
||||
def __deepcopy__(self, memo):
|
||||
return DestructorDecl(self.name, self.virtual)
|
||||
return DestructorDecl(self.name,
|
||||
virtual=self.virtual,
|
||||
force_inline=self.force_inline,
|
||||
inline=self.inline)
|
||||
|
||||
|
||||
class DestructorDefn(MethodDefn):
|
||||
|
@ -752,6 +766,8 @@ class StmtBreak(Node):
|
|||
|
||||
class StmtExpr(Node):
|
||||
def __init__(self, expr):
|
||||
assert expr is not None
|
||||
|
||||
Node.__init__(self)
|
||||
self.expr = expr
|
||||
|
||||
|
|
|
@ -208,6 +208,8 @@ class CxxCodeGen(CodePrinter, Visitor):
|
|||
self.println('>')
|
||||
self.printdent()
|
||||
|
||||
if md.inline:
|
||||
self.write('inline ')
|
||||
if md.static:
|
||||
self.write('static ')
|
||||
if md.virtual:
|
||||
|
@ -276,6 +278,8 @@ class CxxCodeGen(CodePrinter, Visitor):
|
|||
|
||||
|
||||
def visitDestructorDecl(self, dd):
|
||||
if dd.inline:
|
||||
self.write('inline ')
|
||||
if dd.virtual:
|
||||
self.write('virtual ')
|
||||
|
||||
|
|
|
@ -197,16 +197,15 @@ def _shmemRevokeRights(shmemexpr):
|
|||
def _lookupShmem(idexpr):
|
||||
return ExprCall(ExprVar('LookupSharedMemory'), args=[ idexpr ])
|
||||
|
||||
def _makeForwardDecl(ptype, side):
|
||||
clsname = _actorName(ptype.qname.baseid, side)
|
||||
|
||||
def _makeForwardDeclForQClass(clsname, quals):
|
||||
fd = ForwardDecl(clsname, cls=1)
|
||||
if 0 == len(ptype.qname.quals):
|
||||
if 0 == len(quals):
|
||||
return fd
|
||||
|
||||
outerns = Namespace(ptype.qname.quals[0])
|
||||
outerns = Namespace(quals[0])
|
||||
innerns = outerns
|
||||
for ns in ptype.qname.quals[1:]:
|
||||
for ns in quals[1:]:
|
||||
tmpns = Namespace(ns)
|
||||
innerns.addstmt(tmpns)
|
||||
innerns = tmpns
|
||||
|
@ -214,6 +213,14 @@ def _makeForwardDecl(ptype, side):
|
|||
innerns.addstmt(fd)
|
||||
return outerns
|
||||
|
||||
def _makeForwardDeclForActor(ptype, side):
|
||||
return _makeForwardDeclForQClass(_actorName(ptype.qname.baseid, side),
|
||||
ptype.qname.quals)
|
||||
|
||||
def _makeForwardDecl(type):
|
||||
return _makeForwardDeclForQClass(type.name(), type.qname.quals)
|
||||
|
||||
|
||||
def _putInNamespaces(cxxthing, namespaces):
|
||||
"""|namespaces| is in order [ outer, ..., inner ]"""
|
||||
if 0 == len(namespaces): return cxxthing
|
||||
|
@ -532,30 +539,18 @@ class HasFQName:
|
|||
def fqClassName(self):
|
||||
return self.decl.type.fullname()
|
||||
|
||||
|
||||
class StructDecl(ipdl.ast.StructDecl, HasFQName):
|
||||
@staticmethod
|
||||
def upgrade(structDecl):
|
||||
assert isinstance(structDecl, ipdl.ast.StructDecl)
|
||||
structDecl.__class__ = StructDecl
|
||||
return structDecl
|
||||
|
||||
class _StructField(_HybridDecl):
|
||||
def __init__(self, ipdltype, name, sd, side=None, other=None):
|
||||
special = _hasVisibleActor(ipdltype)
|
||||
fname = name
|
||||
if special:
|
||||
fname += side.title()
|
||||
|
||||
_HybridDecl.__init__(self, ipdltype, fname)
|
||||
class _CompoundTypeComponent(_HybridDecl):
|
||||
def __init__(self, ipdltype, name, side, ct):
|
||||
_HybridDecl.__init__(self, ipdltype, name)
|
||||
self.side = side
|
||||
self.special = special
|
||||
if special:
|
||||
if other is not None:
|
||||
self.other = other
|
||||
else:
|
||||
self.other = _StructField(ipdltype, name, sd, _otherSide(side), self)
|
||||
self.sd = sd
|
||||
self.special = _hasVisibleActor(ipdltype)
|
||||
self.recursive = ct.decl.type.mutuallyRecursiveWith(ipdltype)
|
||||
|
||||
def internalType(self):
|
||||
if self.recursive:
|
||||
return self.ptrToType()
|
||||
else:
|
||||
return self.bareType()
|
||||
|
||||
# @override the following methods to pass |self.side| instead of
|
||||
# forcing the caller to remember which side we're declared to
|
||||
|
@ -574,6 +569,62 @@ class _StructField(_HybridDecl):
|
|||
return _HybridDecl.inType(self, self.side)
|
||||
|
||||
|
||||
class StructDecl(ipdl.ast.StructDecl, HasFQName):
|
||||
@staticmethod
|
||||
def upgrade(structDecl):
|
||||
assert isinstance(structDecl, ipdl.ast.StructDecl)
|
||||
structDecl.__class__ = StructDecl
|
||||
return structDecl
|
||||
|
||||
class _StructField(_CompoundTypeComponent):
|
||||
def __init__(self, ipdltype, name, sd, side=None):
|
||||
fname = name
|
||||
special = _hasVisibleActor(ipdltype)
|
||||
if special:
|
||||
fname += side.title()
|
||||
|
||||
_CompoundTypeComponent.__init__(self, ipdltype, fname, side, sd)
|
||||
|
||||
def getMethod(self, thisexpr=None, sel='.'):
|
||||
meth = self.var()
|
||||
if thisexpr is not None:
|
||||
return ExprSelect(thisexpr, sel, meth.name)
|
||||
return meth
|
||||
|
||||
def initExpr(self, thisexpr):
|
||||
expr = ExprCall(self.getMethod(thisexpr=thisexpr))
|
||||
if self.ipdltype.isIPDL() and self.ipdltype.isActor():
|
||||
expr = ExprCast(expr, self.bareType(), const=1)
|
||||
return expr
|
||||
|
||||
def refExpr(self, thisexpr=None):
|
||||
ref = self.memberVar()
|
||||
if thisexpr is not None:
|
||||
ref = ExprSelect(thisexpr, '.', ref.name)
|
||||
if self.recursive:
|
||||
ref = ExprDeref(ref)
|
||||
return ref
|
||||
|
||||
def argVar(self):
|
||||
return ExprVar('_'+ self.name)
|
||||
|
||||
def memberVar(self):
|
||||
return ExprVar(self.name + '_')
|
||||
|
||||
def initStmts(self):
|
||||
if self.recursive:
|
||||
return [ StmtExpr(ExprAssn(self.memberVar(),
|
||||
ExprNew(self.bareType()))) ]
|
||||
else:
|
||||
return []
|
||||
|
||||
def destructStmts(self):
|
||||
if self.recursive:
|
||||
return [ StmtExpr(ExprDelete(self.memberVar())) ]
|
||||
else:
|
||||
return []
|
||||
|
||||
|
||||
class UnionDecl(ipdl.ast.UnionDecl, HasFQName):
|
||||
def callType(self, var=None):
|
||||
func = ExprVar('type')
|
||||
|
@ -588,7 +639,7 @@ class UnionDecl(ipdl.ast.UnionDecl, HasFQName):
|
|||
return unionDecl
|
||||
|
||||
|
||||
class _UnionMember(_HybridDecl):
|
||||
class _UnionMember(_CompoundTypeComponent):
|
||||
"""Not in the AFL sense, but rather a member (e.g. |int;|) of an
|
||||
IPDL union type."""
|
||||
def __init__(self, ipdltype, ud, side=None, other=None):
|
||||
|
@ -597,16 +648,13 @@ IPDL union type."""
|
|||
if special:
|
||||
flatname += side.title()
|
||||
|
||||
_HybridDecl.__init__(self, ipdltype, 'V'+ flatname)
|
||||
_CompoundTypeComponent.__init__(self, ipdltype, 'V'+ flatname, side, ud)
|
||||
self.flattypename = flatname
|
||||
self.side = side
|
||||
self.special = special
|
||||
if special:
|
||||
if other is not None:
|
||||
self.other = other
|
||||
else:
|
||||
self.other = _UnionMember(ipdltype, ud, _otherSide(side), self)
|
||||
self.ud = ud
|
||||
|
||||
def enum(self):
|
||||
return 'T' + self.flattypename
|
||||
|
@ -619,7 +667,10 @@ IPDL union type."""
|
|||
|
||||
def unionType(self):
|
||||
"""Type used for storage in generated C union decl."""
|
||||
return TypeArray(Type('char'), ExprSizeof(self.bareType()))
|
||||
if self.recursive:
|
||||
return self.ptrToType()
|
||||
else:
|
||||
return TypeArray(Type('char'), ExprSizeof(self.internalType()))
|
||||
|
||||
def unionValue(self):
|
||||
# NB: knows that Union's storage C union is named |mValue|
|
||||
|
@ -641,7 +692,7 @@ IPDL union type."""
|
|||
rhs = ExprCast(rhs, self.bareType(), const=1)
|
||||
return ExprAssn(ExprDeref(self.callGetPtr()), rhs)
|
||||
|
||||
def callPlacementCtor(self, expr=None):
|
||||
def callCtor(self, expr=None):
|
||||
assert not isinstance(expr, list)
|
||||
|
||||
if expr is None:
|
||||
|
@ -651,13 +702,21 @@ IPDL union type."""
|
|||
else:
|
||||
args = [ expr ]
|
||||
|
||||
return ExprNew(self.bareType(self.side),
|
||||
args=args,
|
||||
newargs=[ self.callGetPtr() ])
|
||||
if self.recursive:
|
||||
return ExprAssn(self.callGetPtr(),
|
||||
ExprNew(self.bareType(self.side),
|
||||
args=args))
|
||||
else:
|
||||
return ExprNew(self.bareType(self.side),
|
||||
args=args,
|
||||
newargs=[ self.callGetPtr() ])
|
||||
|
||||
def callPlacementDtor(self):
|
||||
return ExprCall(
|
||||
ExprSelect(self.callGetPtr(), '->', '~'+ self.typedef()))
|
||||
def callDtor(self):
|
||||
if self.recursive:
|
||||
return ExprDelete(self.callGetPtr())
|
||||
else:
|
||||
return ExprCall(
|
||||
ExprSelect(self.callGetPtr(), '->', '~'+ self.typedef()))
|
||||
|
||||
def getTypeName(self): return 'get_'+ self.flattypename
|
||||
def getConstTypeName(self): return 'get_'+ self.flattypename
|
||||
|
@ -669,15 +728,24 @@ IPDL union type."""
|
|||
|
||||
def ptrToSelfExpr(self):
|
||||
"""|*ptrToSelfExpr()| has type |self.bareType()|"""
|
||||
return ExprCast(ExprAddrOf(self.unionValue()),
|
||||
self.ptrToType(),
|
||||
reinterpret=1)
|
||||
v = self.unionValue()
|
||||
if self.recursive:
|
||||
return v
|
||||
else:
|
||||
return ExprCast(ExprAddrOf(v), self.ptrToType(), reinterpret=1)
|
||||
|
||||
def constptrToSelfExpr(self):
|
||||
"""|*constptrToSelfExpr()| has type |self.constType()|"""
|
||||
return ExprCast(ExprAddrOf(self.unionValue()),
|
||||
self.constPtrToType(),
|
||||
reinterpret=1)
|
||||
v = self.unionValue()
|
||||
if self.recursive:
|
||||
return v
|
||||
return ExprCast(ExprAddrOf(v), self.constPtrToType(), reinterpret=1)
|
||||
|
||||
def ptrToInternalType(self):
|
||||
t = self.ptrToType()
|
||||
if self.recursive:
|
||||
t.ref = 1
|
||||
return t
|
||||
|
||||
def defaultValue(self):
|
||||
if self.ipdltype.isIPDL() and self.ipdltype.isActor():
|
||||
|
@ -685,22 +753,6 @@ IPDL union type."""
|
|||
# XXX sneaky here, maybe need ExprCtor()?
|
||||
return ExprCall(self.bareType())
|
||||
|
||||
# @override the following methods to pass |self.side| instead of
|
||||
# forcing the caller to remember which side we're declared to
|
||||
# represent.
|
||||
def bareType(self, side=None):
|
||||
return _HybridDecl.bareType(self, self.side)
|
||||
def refType(self, side=None):
|
||||
return _HybridDecl.refType(self, self.side)
|
||||
def constRefType(self, side=None):
|
||||
return _HybridDecl.constRefType(self, self.side)
|
||||
def ptrToType(self, side=None):
|
||||
return _HybridDecl.ptrToType(self, self.side)
|
||||
def constPtrToType(self, side=None):
|
||||
return _HybridDecl.constPtrToType(self, self.side)
|
||||
def inType(self, side=None):
|
||||
return _HybridDecl.inType(self, self.side)
|
||||
|
||||
##--------------------------------------------------
|
||||
|
||||
class MessageDecl(ipdl.ast.MessageDecl):
|
||||
|
@ -1192,6 +1244,7 @@ child actors.'''
|
|||
def __init__(self):
|
||||
self.protocol = None # protocol we're generating a class for
|
||||
self.file = None # File stuff is stuck in
|
||||
self.structUnionDefns = []
|
||||
|
||||
def lower(self, tu, outcxxfile):
|
||||
self.protocol = tu.protocol
|
||||
|
@ -1212,6 +1265,8 @@ child actors.'''
|
|||
|
||||
ipdl.ast.Visitor.visitTranslationUnit(self, tu)
|
||||
|
||||
f.addthings(self.structUnionDefns)
|
||||
|
||||
f.addthing(Whitespace.NL)
|
||||
f.addthings(_includeGuardEnd(f))
|
||||
|
||||
|
@ -1219,12 +1274,36 @@ child actors.'''
|
|||
def visitCxxInclude(self, inc):
|
||||
self.file.addthing(CppDirective('include', '"'+ inc.file +'"'))
|
||||
|
||||
def processStructOrUnionClass(self, su, which, forwarddecls, cls):
|
||||
clsdecl, methoddefns = _splitClassDeclDefn(cls, inlinedefns=1)
|
||||
|
||||
self.file.addthings(
|
||||
[ Whitespace.NL ]
|
||||
+ forwarddecls
|
||||
+ [ Whitespace("""
|
||||
//-----------------------------------------------------------------------------
|
||||
// Declaration of the IPDL type |%s %s|
|
||||
//
|
||||
"""% (which, su.name)),
|
||||
_putInNamespaces(clsdecl, su.namespaces),
|
||||
])
|
||||
|
||||
self.structUnionDefns.extend([
|
||||
Whitespace("""
|
||||
//-----------------------------------------------------------------------------
|
||||
// Method definitions for the IPDL type |%s %s|
|
||||
//
|
||||
"""% (which, su.name)),
|
||||
_putInNamespaces(methoddefns, su.namespaces),
|
||||
])
|
||||
|
||||
def visitStructDecl(self, sd):
|
||||
self.file.addthings(_generateCxxStruct(sd))
|
||||
return self.processStructOrUnionClass(sd, 'struct',
|
||||
*_generateCxxStruct(sd))
|
||||
|
||||
def visitUnionDecl(self, ud):
|
||||
self.file.addthings(_generateCxxUnionStuff(ud))
|
||||
|
||||
return self.processStructOrUnionClass(ud, 'union',
|
||||
*_generateCxxUnion(ud))
|
||||
|
||||
def visitProtocol(self, p):
|
||||
self.file.addthing(Whitespace("""
|
||||
|
@ -1354,29 +1433,30 @@ class _ComputeTypeDeps(TypeVisitor):
|
|||
types that need forward declaration; (ii) types that need a |using|
|
||||
stmt. Some types generate both kinds.'''
|
||||
|
||||
def __init__(self):
|
||||
def __init__(self, fortype):
|
||||
ipdl.type.TypeVisitor.__init__(self)
|
||||
self.usingTypedefs = [ ]
|
||||
self.forwardDeclStmts = [ ]
|
||||
self.seen = set()
|
||||
self.fortype = fortype
|
||||
|
||||
def maybeTypedef(self, fqname, name):
|
||||
if fqname != name:
|
||||
self.usingTypedefs.append(Typedef(Type(fqname), name))
|
||||
|
||||
def visitBuiltinCxxType(self, t):
|
||||
if t in self.seen: return
|
||||
self.seen.add(t)
|
||||
if t in self.visited: return
|
||||
self.visited.add(t)
|
||||
self.maybeTypedef(t.fullname(), t.name())
|
||||
|
||||
def visitImportedCxxType(self, t):
|
||||
if t in self.seen: return
|
||||
self.seen.add(t)
|
||||
if t in self.visited: return
|
||||
self.visited.add(t)
|
||||
self.maybeTypedef(t.fullname(), t.name())
|
||||
|
||||
def visitActorType(self, t):
|
||||
if t in self.seen: return
|
||||
self.seen.add(t)
|
||||
|
||||
if t in self.visited: return
|
||||
self.visited.add(t)
|
||||
|
||||
fqname, name = t.fullname(), t.name()
|
||||
|
||||
self.maybeTypedef(_actorName(fqname, 'Parent'),
|
||||
|
@ -1385,15 +1465,18 @@ stmt. Some types generate both kinds.'''
|
|||
_actorName(name, 'Child'))
|
||||
|
||||
self.forwardDeclStmts.extend([
|
||||
_makeForwardDecl(t.protocol, 'parent'), Whitespace.NL,
|
||||
_makeForwardDecl(t.protocol, 'child'), Whitespace.NL
|
||||
_makeForwardDeclForActor(t.protocol, 'parent'), Whitespace.NL,
|
||||
_makeForwardDeclForActor(t.protocol, 'child'), Whitespace.NL
|
||||
])
|
||||
|
||||
def visitStructOrUnionType(self, su, defaultVisit):
|
||||
if su in self.seen: return
|
||||
self.seen.add(su)
|
||||
if su in self.visited or su == self.fortype: return
|
||||
self.visited.add(su)
|
||||
self.maybeTypedef(su.fullname(), su.name())
|
||||
|
||||
if su.mutuallyRecursiveWith(self.fortype):
|
||||
self.forwardDeclStmts.append(_makeForwardDecl(su))
|
||||
|
||||
return defaultVisit(self, su)
|
||||
|
||||
def visitStructType(self, t):
|
||||
|
@ -1414,51 +1497,112 @@ stmt. Some types generate both kinds.'''
|
|||
def _generateCxxStruct(sd):
|
||||
''' '''
|
||||
# compute all the typedefs and forward decls we need to make
|
||||
gettypedeps = _ComputeTypeDeps()
|
||||
gettypedeps = _ComputeTypeDeps(sd.decl.type)
|
||||
for f in sd.fields:
|
||||
f.ipdltype.accept(gettypedeps)
|
||||
|
||||
usingTypedefs = gettypedeps.usingTypedefs
|
||||
forwarddeclstmts = gettypedeps.forwardDeclStmts
|
||||
|
||||
struct = Class(sd.name, struct=1)
|
||||
struct.addstmts(
|
||||
[ Label.PRIVATE ]
|
||||
+ usingTypedefs
|
||||
+ [ Whitespace.NL,
|
||||
Label.PUBLIC,
|
||||
ConstructorDefn(ConstructorDecl(sd.name)),
|
||||
Whitespace.NL,
|
||||
ConstructorDefn(
|
||||
ConstructorDecl(
|
||||
sd.name,
|
||||
params=[ Decl(f.constRefType(), '_'+ f.name)
|
||||
for f in sd.fields ]),
|
||||
memberinits=[ ExprCall(f.var(),
|
||||
args=[ ExprVar('_'+ f.name) ])
|
||||
for f in sd.fields ]),
|
||||
Whitespace.NL,
|
||||
Whitespace('// Default copy ctor, op=, and dtor are OK\n\n',
|
||||
indent=1)
|
||||
]
|
||||
+ [ StmtDecl(Decl(f.bareType(), f.name)) for f in sd.fields ])
|
||||
struct = Class(sd.name, struct=1, final=1)
|
||||
struct.addstmts([ Label.PRIVATE ]
|
||||
+ usingTypedefs
|
||||
+ [ Whitespace.NL, Label.PUBLIC ])
|
||||
|
||||
constreftype = Type(sd.name, const=1, ref=1)
|
||||
initvar = ExprVar('Init')
|
||||
callinit = ExprCall(initvar)
|
||||
assignvar = ExprVar('Assign')
|
||||
|
||||
return (
|
||||
[
|
||||
Whitespace("""
|
||||
//-----------------------------------------------------------------------------
|
||||
// Definition of the IPDL type |struct %s|
|
||||
//
|
||||
"""% (sd.name))
|
||||
]
|
||||
+ forwarddeclstmts
|
||||
+ [ _putInNamespaces(struct, sd.namespaces) ])
|
||||
def fieldsAsParamList():
|
||||
return [ Decl(f.inType(), f.argVar().name) for f in sd.fields ]
|
||||
|
||||
def assignFromOther(oexpr):
|
||||
return ExprCall(assignvar,
|
||||
args=[ f.initExpr(oexpr) for f in sd.fields ])
|
||||
|
||||
# Struct()
|
||||
defctor = ConstructorDefn(ConstructorDecl(sd.name))
|
||||
defctor.addstmt(StmtExpr(callinit))
|
||||
struct.addstmts([ defctor, Whitespace.NL ])
|
||||
|
||||
# Struct(const field1& _f1, ...)
|
||||
valctor = ConstructorDefn(ConstructorDecl(sd.name,
|
||||
params=fieldsAsParamList(),
|
||||
force_inline=1))
|
||||
valctor.addstmts([
|
||||
StmtExpr(callinit),
|
||||
StmtExpr(ExprCall(assignvar,
|
||||
args=[ f.argVar() for f in sd.fields ]))
|
||||
])
|
||||
struct.addstmts([ valctor, Whitespace.NL ])
|
||||
|
||||
# Struct(const Struct& _o)
|
||||
ovar = ExprVar('_o')
|
||||
copyctor = ConstructorDefn(ConstructorDecl(
|
||||
sd.name,
|
||||
params=[ Decl(constreftype, ovar.name) ],
|
||||
force_inline=1))
|
||||
copyctor.addstmts([
|
||||
StmtExpr(callinit),
|
||||
StmtExpr(assignFromOther(ovar))
|
||||
])
|
||||
struct.addstmts([ copyctor, Whitespace.NL ])
|
||||
|
||||
# ~Struct()
|
||||
dtor = DestructorDefn(DestructorDecl(sd.name))
|
||||
for f in sd.fields:
|
||||
dtor.addstmts(f.destructStmts())
|
||||
struct.addstmts([ dtor, Whitespace.NL ])
|
||||
|
||||
# Struct& operator=(const Struct& _o)
|
||||
opeq = MethodDefn(MethodDecl(
|
||||
'operator=',
|
||||
params=[ Decl(constreftype, ovar.name) ],
|
||||
force_inline=1))
|
||||
opeq.addstmt(StmtExpr(assignFromOther(ovar)))
|
||||
struct.addstmts([ opeq, Whitespace.NL ])
|
||||
|
||||
# field1& f1()
|
||||
# const field1& f1() const
|
||||
for f in sd.fields:
|
||||
get = MethodDefn(MethodDecl(f.getMethod().name,
|
||||
params=[ ],
|
||||
ret=f.refType(),
|
||||
force_inline=1))
|
||||
get.addstmt(StmtReturn(f.refExpr()))
|
||||
|
||||
getconst = deepcopy(get)
|
||||
getconst.decl.ret = f.constRefType()
|
||||
getconst.decl.const = 1
|
||||
|
||||
struct.addstmts([ get, getconst, Whitespace.NL ])
|
||||
|
||||
# private:
|
||||
struct.addstmt(Label.PRIVATE)
|
||||
|
||||
# Init()
|
||||
init = MethodDefn(MethodDecl(initvar.name))
|
||||
for f in sd.fields:
|
||||
init.addstmts(f.initStmts())
|
||||
struct.addstmts([ init, Whitespace.NL ])
|
||||
|
||||
# Assign(const field1& _f1, ...)
|
||||
assign = MethodDefn(MethodDecl(assignvar.name,
|
||||
params=fieldsAsParamList()))
|
||||
assign.addstmts([ StmtExpr(ExprAssn(f.refExpr(), f.argVar()))
|
||||
for f in sd.fields ])
|
||||
struct.addstmts([ assign, Whitespace.NL ])
|
||||
|
||||
# members
|
||||
struct.addstmts([ StmtDecl(Decl(f.internalType(), f.memberVar().name))
|
||||
for f in sd.fields ])
|
||||
|
||||
return forwarddeclstmts, struct
|
||||
|
||||
##--------------------------------------------------
|
||||
|
||||
def _generateCxxUnionStuff(ud):
|
||||
def _generateCxxUnion(ud):
|
||||
# This Union class basically consists of a type (enum) and a
|
||||
# union for storage. The union can contain POD and non-POD
|
||||
# types. Each type needs a copy ctor, assignment operator,
|
||||
|
@ -1522,11 +1666,11 @@ def _generateCxxUnionStuff(ud):
|
|||
|
||||
def maybeReconstruct(memb, newTypeVar):
|
||||
ifdied = StmtIf(callMaybeDestroy(newTypeVar))
|
||||
ifdied.addifstmt(StmtExpr(memb.callPlacementCtor()))
|
||||
ifdied.addifstmt(StmtExpr(memb.callCtor()))
|
||||
return ifdied
|
||||
|
||||
# compute all the typedefs and forward decls we need to make
|
||||
gettypedeps = _ComputeTypeDeps()
|
||||
gettypedeps = _ComputeTypeDeps(ud.decl.type)
|
||||
for c in ud.components:
|
||||
c.ipdltype.accept(gettypedeps)
|
||||
|
||||
|
@ -1549,8 +1693,8 @@ def _generateCxxUnionStuff(ud):
|
|||
cls.addstmt(Label.PRIVATE)
|
||||
cls.addstmts(
|
||||
usingTypedefs
|
||||
# hacky typedef's that allow placement dtors of builtins
|
||||
+ [ Typedef(c.bareType(), c.typedef()) for c in ud.components ])
|
||||
# hacky typedef's that allow placement dtors of builtins
|
||||
+ [ Typedef(c.internalType(), c.typedef()) for c in ud.components ])
|
||||
cls.addstmt(Whitespace.NL)
|
||||
|
||||
# the C++ union the discunion use for storage
|
||||
|
@ -1565,11 +1709,13 @@ def _generateCxxUnionStuff(ud):
|
|||
# and |const T*|
|
||||
for c in ud.components:
|
||||
getptr = MethodDefn(MethodDecl(
|
||||
c.getPtrName(), params=[ ], ret=c.ptrToType()))
|
||||
c.getPtrName(), params=[ ], ret=c.ptrToInternalType(),
|
||||
force_inline=1))
|
||||
getptr.addstmt(StmtReturn(c.ptrToSelfExpr()))
|
||||
|
||||
getptrconst = MethodDefn(MethodDecl(
|
||||
c.getConstPtrName(), params=[ ], ret=c.constPtrToType(), const=1))
|
||||
c.getConstPtrName(), params=[ ], ret=c.constPtrToType(),
|
||||
const=1, force_inline=1))
|
||||
getptrconst.addstmt(StmtReturn(c.constptrToSelfExpr()))
|
||||
|
||||
cls.addstmts([ getptr, getptrconst ])
|
||||
|
@ -1595,7 +1741,7 @@ def _generateCxxUnionStuff(ud):
|
|||
for c in ud.components:
|
||||
dtorswitch.addcase(
|
||||
CaseLabel(c.enum()),
|
||||
StmtBlock([ StmtExpr(c.callPlacementDtor()),
|
||||
StmtBlock([ StmtExpr(c.callDtor()),
|
||||
StmtBreak() ]))
|
||||
dtorswitch.addcase(
|
||||
DefaultLabel(),
|
||||
|
@ -1611,7 +1757,7 @@ def _generateCxxUnionStuff(ud):
|
|||
# add helper methods that ensure the discunion has a
|
||||
# valid type
|
||||
sanity = MethodDefn(MethodDecl(
|
||||
assertsanityvar.name, ret=Type.VOID, const=1))
|
||||
assertsanityvar.name, ret=Type.VOID, const=1, force_inline=1))
|
||||
sanity.addstmts([
|
||||
_abortIfFalse(ExprBinary(tfirstvar, '<=', mtypevar),
|
||||
'invalid type tag'),
|
||||
|
@ -1624,7 +1770,7 @@ def _generateCxxUnionStuff(ud):
|
|||
MethodDecl(assertsanityvar.name,
|
||||
params=[ Decl(typetype, atypevar.name) ],
|
||||
ret=Type.VOID,
|
||||
const=1))
|
||||
const=1, force_inline=1))
|
||||
sanity2.addstmts([
|
||||
StmtExpr(ExprCall(assertsanityvar)),
|
||||
_abortIfFalse(ExprBinary(mtypevar, '==', atypevar),
|
||||
|
@ -1637,7 +1783,7 @@ def _generateCxxUnionStuff(ud):
|
|||
cls.addstmts([
|
||||
Label.PUBLIC,
|
||||
ConstructorDefn(
|
||||
ConstructorDecl(ud.name),
|
||||
ConstructorDecl(ud.name, force_inline=1),
|
||||
memberinits=[ ExprMemberInit(mtypevar, [ tnonevar ]) ]),
|
||||
Whitespace.NL
|
||||
])
|
||||
|
@ -1648,7 +1794,7 @@ def _generateCxxUnionStuff(ud):
|
|||
copyctor = ConstructorDefn(ConstructorDecl(
|
||||
ud.name, params=[ Decl(c.inType(), othervar.name) ]))
|
||||
copyctor.addstmts([
|
||||
StmtExpr(c.callPlacementCtor(othervar)),
|
||||
StmtExpr(c.callCtor(othervar)),
|
||||
StmtExpr(ExprAssn(mtypevar, c.enumvar())) ])
|
||||
cls.addstmts([ copyctor, Whitespace.NL ])
|
||||
|
||||
|
@ -1661,7 +1807,7 @@ def _generateCxxUnionStuff(ud):
|
|||
copyswitch.addcase(
|
||||
CaseLabel(c.enum()),
|
||||
StmtBlock([
|
||||
StmtExpr(c.callPlacementCtor(
|
||||
StmtExpr(c.callCtor(
|
||||
ExprCall(ExprSelect(othervar,
|
||||
'.', c.getConstTypeName())))),
|
||||
StmtBreak()
|
||||
|
@ -1682,7 +1828,8 @@ def _generateCxxUnionStuff(ud):
|
|||
cls.addstmts([ dtor, Whitespace.NL ])
|
||||
|
||||
# type()
|
||||
typemeth = MethodDefn(MethodDecl('type', ret=typetype, const=1))
|
||||
typemeth = MethodDefn(MethodDecl('type', ret=typetype,
|
||||
const=1, force_inline=1))
|
||||
typemeth.addstmt(StmtReturn(mtypevar))
|
||||
cls.addstmts([ typemeth, Whitespace.NL ])
|
||||
|
||||
|
@ -1736,23 +1883,26 @@ def _generateCxxUnionStuff(ud):
|
|||
getValueVar = ExprVar(c.getTypeName())
|
||||
getConstValueVar = ExprVar(c.getConstTypeName())
|
||||
|
||||
getvalue = MethodDefn(MethodDecl(getValueVar.name, ret=c.refType()))
|
||||
getvalue = MethodDefn(MethodDecl(getValueVar.name,
|
||||
ret=c.refType(),
|
||||
force_inline=1))
|
||||
getvalue.addstmts([
|
||||
StmtExpr(callAssertSanity(expectTypeVar=c.enumvar())),
|
||||
StmtReturn(ExprDeref(c.callGetPtr()))
|
||||
])
|
||||
|
||||
getconstvalue = MethodDefn(MethodDecl(
|
||||
getConstValueVar.name, ret=c.constRefType(), const=1))
|
||||
getConstValueVar.name, ret=c.constRefType(),
|
||||
const=1, force_inline=1))
|
||||
getconstvalue.addstmts([
|
||||
StmtExpr(callAssertSanity(expectTypeVar=c.enumvar())),
|
||||
StmtReturn(ExprDeref(c.callGetConstPtr()))
|
||||
])
|
||||
|
||||
optype = MethodDefn(MethodDecl('', typeop=c.refType()))
|
||||
optype = MethodDefn(MethodDecl('', typeop=c.refType(), force_inline=1))
|
||||
optype.addstmt(StmtReturn(ExprCall(getValueVar)))
|
||||
opconsttype = MethodDefn(MethodDecl(
|
||||
'', const=1, typeop=c.constRefType()))
|
||||
'', const=1, typeop=c.constRefType(), force_inline=1))
|
||||
opconsttype.addstmt(StmtReturn(ExprCall(getConstValueVar)))
|
||||
|
||||
cls.addstmts([ getvalue, getconstvalue,
|
||||
|
@ -1766,17 +1916,7 @@ def _generateCxxUnionStuff(ud):
|
|||
StmtDecl(Decl(typetype, mtypevar.name))
|
||||
])
|
||||
|
||||
return (
|
||||
[
|
||||
Whitespace("""
|
||||
//-----------------------------------------------------------------------------
|
||||
// Definition of the IPDL type |union %s|
|
||||
//
|
||||
"""% (ud.name))
|
||||
]
|
||||
+ forwarddeclstmts
|
||||
+ [ _putInNamespaces(cls, ud.namespaces) ])
|
||||
|
||||
return forwarddeclstmts, cls
|
||||
|
||||
##-----------------------------------------------------------------------------
|
||||
|
||||
|
@ -1880,7 +2020,7 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
|
|||
# this generates the actor's full impl in self.cls
|
||||
tu.protocol.accept(self)
|
||||
|
||||
clsdecl, clsdefn = _ClassDeclDefn().split(self.cls)
|
||||
clsdecl, clsdefn = _splitClassDeclDefn(self.cls)
|
||||
|
||||
# XXX damn C++ ... return types in the method defn aren't in
|
||||
# class scope
|
||||
|
@ -1957,7 +2097,7 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
|
|||
ip = pi.tu.protocol
|
||||
|
||||
self.hdrfile.addthings([
|
||||
_makeForwardDecl(ip.decl.type, self.side),
|
||||
_makeForwardDeclForActor(ip.decl.type, self.side),
|
||||
Whitespace.NL
|
||||
])
|
||||
self.protocolCxxIncludes.append(
|
||||
|
@ -2011,7 +2151,7 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
|
|||
for friend in friends:
|
||||
self.hdrfile.addthings([
|
||||
Whitespace.NL,
|
||||
_makeForwardDecl(friend, self.prettyside),
|
||||
_makeForwardDeclForActor(friend, self.prettyside),
|
||||
Whitespace.NL
|
||||
])
|
||||
self.cls.addstmts([
|
||||
|
@ -3323,7 +3463,6 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
|
|||
outtype = _cxxPtrToType(arraytype, self.side)
|
||||
|
||||
write = MethodDefn(self.writeMethodDecl(intype, var))
|
||||
# FIXME hacky init of |i|
|
||||
forwrite = StmtFor(init=ExprAssn(Decl(Type.UINT32, ivar.name),
|
||||
ExprLiteral.ZERO),
|
||||
cond=ExprBinary(ivar, '<', lenvar),
|
||||
|
@ -3340,7 +3479,6 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
|
|||
|
||||
read = MethodDefn(self.readMethodDecl(outtype, var))
|
||||
avar = ExprVar('a')
|
||||
# FIXME hacky init of |i|
|
||||
forread = StmtFor(init=ExprAssn(Decl(Type.UINT32, ivar.name),
|
||||
ExprLiteral.ZERO),
|
||||
cond=ExprBinary(ivar, '<', lenvar),
|
||||
|
@ -3420,7 +3558,7 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
|
|||
read = MethodDefn(self.readMethodDecl(outtype, var))
|
||||
|
||||
def get(sel, f):
|
||||
return ExprSelect(var, sel, f.name)
|
||||
return ExprCall(f.getMethod(thisexpr=var, sel=sel))
|
||||
|
||||
for f in sd.fields:
|
||||
writefield = StmtExpr(self.write(f.ipdltype, get('.', f), msgvar))
|
||||
|
@ -4162,32 +4300,34 @@ class _GenerateProtocolChildCode(_GenerateProtocolActorCode):
|
|||
## Utility passes
|
||||
##
|
||||
|
||||
class _ClassDeclDefn:
|
||||
def split(self, cls):
|
||||
"""Warning: destructively splits |cls|!"""
|
||||
defns = Block()
|
||||
def _splitClassDeclDefn(cls, inlinedefns=0):
|
||||
"""Destructively split |cls| methods into declarations and
|
||||
definitions (if |not methodDecl.force_inline|). Return classDecl,
|
||||
methodDefns."""
|
||||
defns = Block()
|
||||
|
||||
for i, stmt in enumerate(cls.stmts):
|
||||
if isinstance(stmt, MethodDefn) and not stmt.decl.inline:
|
||||
decl, defn = self.splitMethodDefn(stmt, cls.name)
|
||||
cls.stmts[i] = StmtDecl(decl)
|
||||
defns.addstmts([ defn, Whitespace.NL ])
|
||||
for i, stmt in enumerate(cls.stmts):
|
||||
if isinstance(stmt, MethodDefn) and not stmt.decl.force_inline:
|
||||
decl, defn = _splitMethodDefn(stmt, cls.name, inlinedefns)
|
||||
cls.stmts[i] = StmtDecl(decl)
|
||||
defns.addstmts([ defn, Whitespace.NL ])
|
||||
|
||||
return cls, defns
|
||||
return cls, defns
|
||||
|
||||
def splitMethodDefn(self, md, clsname):
|
||||
saveddecl = deepcopy(md.decl)
|
||||
md.decl.name = (clsname +'::'+ md.decl.name)
|
||||
md.decl.virtual = 0
|
||||
md.decl.static = 0
|
||||
md.decl.warn_unused = 0
|
||||
for param in md.decl.params:
|
||||
if isinstance(param, Param):
|
||||
param.default = None
|
||||
return saveddecl, md
|
||||
def _splitMethodDefn(md, clsname, inlinedefn):
|
||||
saveddecl = deepcopy(md.decl)
|
||||
md.decl.name = (clsname +'::'+ md.decl.name)
|
||||
md.decl.virtual = 0
|
||||
md.decl.static = 0
|
||||
md.decl.warn_unused = 0
|
||||
md.decl.inline = inlinedefn
|
||||
for param in md.decl.params:
|
||||
if isinstance(param, Param):
|
||||
param.default = None
|
||||
return saveddecl, md
|
||||
|
||||
|
||||
# XXX this is tantalizingly similar to _SplitDeclDefn, but just
|
||||
# XXX this is tantalizingly similar to _splitClassDeclDefn, but just
|
||||
# different enough that I don't see the need to define
|
||||
# _GenerateSkeleton in terms of that
|
||||
class _GenerateSkeletonImpl(Visitor):
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
|
||||
import os, sys
|
||||
|
||||
from ipdl.ast import CxxInclude, Decl, Loc, QualifiedId, State, TransitionStmt, TypeSpec, UsingStmt, Visitor, ASYNC, SYNC, RPC, IN, OUT, INOUT, ANSWER, CALL, RECV, SEND
|
||||
from ipdl.ast import CxxInclude, Decl, Loc, QualifiedId, State, StructDecl, TransitionStmt, TypeSpec, UnionDecl, UsingStmt, Visitor, ASYNC, SYNC, RPC, IN, OUT, INOUT, ANSWER, CALL, RECV, SEND
|
||||
import ipdl.builtin as builtin
|
||||
|
||||
_DELETE_MSG = '__delete__'
|
||||
|
@ -56,6 +56,9 @@ def cartesian_product(s1, s2):
|
|||
|
||||
|
||||
class TypeVisitor:
|
||||
def __init__(self):
|
||||
self.visited = set()
|
||||
|
||||
def defaultVisit(self, node, *args):
|
||||
raise Exception, "INTERNAL ERROR: no visitor for node type `%s'"% (
|
||||
node.__class__.__name__)
|
||||
|
@ -90,13 +93,18 @@ class TypeVisitor:
|
|||
a.state.accept(self, *args)
|
||||
|
||||
def visitStructType(self, s, *args):
|
||||
if s in self.visited:
|
||||
return
|
||||
|
||||
self.visited.add(s)
|
||||
for field in s.fields:
|
||||
field.accept(self, *args)
|
||||
|
||||
def visitFieldType(self, f, *args):
|
||||
f.type.accept(self, *args)
|
||||
|
||||
def visitUnionType(self, u, *args):
|
||||
if u in self.visited:
|
||||
return
|
||||
|
||||
self.visited.add(u)
|
||||
for component in u.components:
|
||||
component.accept(self, *args)
|
||||
|
||||
|
@ -109,6 +117,7 @@ class TypeVisitor:
|
|||
def visitShmemChmodType(self, c, *args):
|
||||
c.shmem.accept(self)
|
||||
|
||||
|
||||
class Type:
|
||||
def __cmp__(self, o):
|
||||
return cmp(self.fullname(), o.fullname())
|
||||
|
@ -124,6 +133,9 @@ class Type:
|
|||
# Is this an IPDL type?
|
||||
def isIPDL(self):
|
||||
return False
|
||||
# Is this type neither compound nor an array?
|
||||
def isAtom(self):
|
||||
return False
|
||||
# Can this type appear in IPDL programs?
|
||||
def isVisible(self):
|
||||
return False
|
||||
|
@ -142,13 +154,14 @@ class Type:
|
|||
return visit(self, *args)
|
||||
|
||||
class VoidType(Type):
|
||||
# the following are not type-o's (hah): void is both a Cxx and IPDL type
|
||||
def isCxx():
|
||||
def isCxx(self):
|
||||
return True
|
||||
def isIPDL():
|
||||
def isIPDL(self):
|
||||
return False
|
||||
def isAtom(self):
|
||||
return True
|
||||
def isVisible(self):
|
||||
return True
|
||||
return False
|
||||
def isVoid(self):
|
||||
return True
|
||||
|
||||
|
@ -161,6 +174,8 @@ VOID = VoidType()
|
|||
class CxxType(Type):
|
||||
def isCxx(self):
|
||||
return True
|
||||
def isAtom(self):
|
||||
return True
|
||||
def isBuiltin(self):
|
||||
return False
|
||||
def isImported(self):
|
||||
|
@ -205,6 +220,8 @@ class IPDLType(Type):
|
|||
def isStruct(self): return False
|
||||
def isUnion(self): return False
|
||||
def isArray(self): return False
|
||||
def isAtom(self): return True
|
||||
def isCompound(self): return False
|
||||
def isShmem(self): return False
|
||||
def isChmod(self): return False
|
||||
|
||||
|
@ -340,29 +357,78 @@ class ActorType(IPDLType):
|
|||
def fullname(self):
|
||||
return self.protocol.fullname()
|
||||
|
||||
class StructType(IPDLType):
|
||||
class _CompoundType(IPDLType):
|
||||
def __init__(self):
|
||||
self.defined = False # bool
|
||||
self.mutualRec = set() # set(_CompoundType | ArrayType)
|
||||
def isAtom(self):
|
||||
return False
|
||||
def isCompound(self):
|
||||
return True
|
||||
def itercomponents(self):
|
||||
raise '"pure virtual" method'
|
||||
|
||||
def mutuallyRecursiveWith(self, t, exploring=None):
|
||||
'''|self| is mutually recursive with |t| iff |self| and |t|
|
||||
are in a cycle in the type graph rooted at |self|. This function
|
||||
looks for such a cycle and returns True if found.'''
|
||||
if exploring is None:
|
||||
exploring = set()
|
||||
|
||||
if t.isAtom():
|
||||
return False
|
||||
elif t is self or t in self.mutualRec:
|
||||
return True
|
||||
elif t.isArray():
|
||||
isrec = self.mutuallyRecursiveWith(t.basetype, exploring)
|
||||
if isrec: self.mutualRec.add(t)
|
||||
return isrec
|
||||
elif t in exploring:
|
||||
return False
|
||||
|
||||
exploring.add(t)
|
||||
for c in t.itercomponents():
|
||||
if self.mutuallyRecursiveWith(c, exploring):
|
||||
self.mutualRec.add(c)
|
||||
return True
|
||||
exploring.remove(t)
|
||||
|
||||
return False
|
||||
|
||||
class StructType(_CompoundType):
|
||||
def __init__(self, qname, fields):
|
||||
_CompoundType.__init__(self)
|
||||
self.qname = qname
|
||||
self.fields = fields # [ Type ]
|
||||
|
||||
def isStruct(self): return True
|
||||
def isStruct(self): return True
|
||||
def itercomponents(self):
|
||||
for f in self.fields:
|
||||
yield f
|
||||
|
||||
def name(self): return self.qname.baseid
|
||||
def fullname(self): return str(self.qname)
|
||||
|
||||
class UnionType(IPDLType):
|
||||
class UnionType(_CompoundType):
|
||||
def __init__(self, qname, components):
|
||||
_CompoundType.__init__(self)
|
||||
self.qname = qname
|
||||
self.components = components
|
||||
self.components = components # [ Type ]
|
||||
|
||||
def isUnion(self): return True
|
||||
def itercomponents(self):
|
||||
for c in self.components:
|
||||
yield c
|
||||
|
||||
def isUnion(self): return True
|
||||
def name(self): return self.qname.baseid
|
||||
def fullname(self): return str(self.qname)
|
||||
|
||||
class ArrayType(IPDLType):
|
||||
def __init__(self, basetype):
|
||||
self.basetype = basetype
|
||||
|
||||
def isAtom(self): return False
|
||||
def isArray(self): return True
|
||||
|
||||
def name(self): return self.basetype.name() +'[]'
|
||||
def fullname(self): return self.basetype.fullname() +'[]'
|
||||
|
||||
|
@ -376,25 +442,24 @@ class ShmemType(IPDLType):
|
|||
def fullname(self):
|
||||
return str(self.qname)
|
||||
|
||||
def iteractortypes(type):
|
||||
def iteractortypes(t, visited=None):
|
||||
"""Iterate over any actor(s) buried in |type|."""
|
||||
# XXX |yield| semantics makes it hard to use TypeVisitor
|
||||
if not type or not type.isIPDL():
|
||||
return
|
||||
elif type.isActor():
|
||||
yield type
|
||||
elif type.isArray():
|
||||
for actor in iteractortypes(type.basetype):
|
||||
yield actor
|
||||
elif type.isStruct():
|
||||
for f in type.fields:
|
||||
for actor in iteractortypes(f):
|
||||
yield actor
|
||||
elif type.isUnion():
|
||||
for c in type.components:
|
||||
for actor in iteractortypes(c):
|
||||
yield actor
|
||||
if visited is None:
|
||||
visited = set()
|
||||
|
||||
# XXX |yield| semantics makes it hard to use TypeVisitor
|
||||
if not t.isIPDL():
|
||||
return
|
||||
elif t.isActor():
|
||||
yield t
|
||||
elif t.isArray():
|
||||
for actor in iteractortypes(t.basetype, visited):
|
||||
yield actor
|
||||
elif t.isCompound() and t not in visited:
|
||||
visited.add(t)
|
||||
for c in t.itercomponents():
|
||||
for actor in iteractortypes(c, visited):
|
||||
yield actor
|
||||
|
||||
def hasactor(type):
|
||||
"""Return true iff |type| is an actor or has one buried within."""
|
||||
|
@ -613,6 +678,28 @@ class GatherDecls(TcheckVisitor):
|
|||
for using in tu.using:
|
||||
using.accept(self)
|
||||
|
||||
# first pass to "forward-declare" all structs and unions in
|
||||
# order to support recursive definitions
|
||||
for su in tu.structsAndUnions:
|
||||
qname = su.qname()
|
||||
if 0 == len(qname.quals):
|
||||
fullname = None
|
||||
else:
|
||||
fullname = str(qname)
|
||||
|
||||
if isinstance(su, StructDecl):
|
||||
sutype = StructType(qname, [ ])
|
||||
elif isinstance(su, UnionDecl):
|
||||
sutype = UnionType(qname, [ ])
|
||||
else: assert 0 and 'unknown type'
|
||||
|
||||
su.decl = self.declare(
|
||||
loc=su.loc,
|
||||
type=sutype,
|
||||
shortname=su.name,
|
||||
fullname=fullname)
|
||||
|
||||
# second pass to check each definition
|
||||
for su in tu.structsAndUnions:
|
||||
su.accept(self)
|
||||
|
||||
|
@ -634,17 +721,6 @@ class GatherDecls(TcheckVisitor):
|
|||
self.symtab.declare(pi.tu.protocol.decl)
|
||||
|
||||
def visitStructDecl(self, sd):
|
||||
qname = sd.qname()
|
||||
if 0 == len(qname.quals):
|
||||
fullname = None
|
||||
else:
|
||||
fullname = str(qname)
|
||||
|
||||
sd.decl = self.declare(
|
||||
loc=sd.loc,
|
||||
type=StructType(qname, [ ]),
|
||||
shortname=sd.name,
|
||||
fullname=fullname)
|
||||
stype = sd.decl.type
|
||||
|
||||
self.symtab.enterScope(sd)
|
||||
|
@ -666,26 +742,15 @@ class GatherDecls(TcheckVisitor):
|
|||
self.symtab.exitScope(sd)
|
||||
|
||||
def visitUnionDecl(self, ud):
|
||||
qname = ud.qname()
|
||||
if 0 == len(qname.quals):
|
||||
fullname = None
|
||||
else:
|
||||
fullname = str(qname)
|
||||
components = [ ]
|
||||
|
||||
utype = ud.decl.type
|
||||
|
||||
for c in ud.components:
|
||||
cdecl = self.symtab.lookup(str(c))
|
||||
if cdecl is None:
|
||||
self.error(c.loc, "unknown component type `%s' of union `%s'",
|
||||
str(c), ud.name)
|
||||
continue
|
||||
components.append(self._canonicalType(cdecl.type, c))
|
||||
|
||||
ud.decl = self.declare(
|
||||
loc=ud.loc,
|
||||
type=UnionType(qname, components),
|
||||
shortname=ud.name,
|
||||
fullname=fullname)
|
||||
utype.components.append(self._canonicalType(cdecl.type, c))
|
||||
|
||||
def visitUsingStmt(self, using):
|
||||
fullname = str(using.type)
|
||||
|
@ -944,35 +1009,27 @@ class GatherDecls(TcheckVisitor):
|
|||
ploc = param.typespec.loc
|
||||
|
||||
ptdecl = self.symtab.lookup(ptname)
|
||||
|
||||
if ptdecl is None:
|
||||
self.error(
|
||||
ploc,
|
||||
"argument typename `%s' of message `%s' has not been declared",
|
||||
ptname, msgname)
|
||||
return None
|
||||
ptype = VOID
|
||||
else:
|
||||
ptype = self._canonicalType(ptdecl.type, param.typespec,
|
||||
chmodallowed=1)
|
||||
return self.declare(
|
||||
loc=ploc,
|
||||
type=ptype,
|
||||
progname=param.name)
|
||||
return self.declare(loc=ploc,
|
||||
type=ptype,
|
||||
progname=param.name)
|
||||
|
||||
for i, inparam in enumerate(md.inParams):
|
||||
pdecl = paramToDecl(inparam)
|
||||
if pdecl is not None:
|
||||
msgtype.params.append(pdecl.type)
|
||||
md.inParams[i] = pdecl
|
||||
else:
|
||||
md.inParams[i].type = None
|
||||
msgtype.params.append(pdecl.type)
|
||||
md.inParams[i] = pdecl
|
||||
for i, outparam in enumerate(md.outParams):
|
||||
pdecl = paramToDecl(outparam)
|
||||
if pdecl is not None:
|
||||
msgtype.returns.append(pdecl.type)
|
||||
md.outParams[i] = pdecl
|
||||
else:
|
||||
md.outParams[i].type = None
|
||||
msgtype.returns.append(pdecl.type)
|
||||
md.outParams[i] = pdecl
|
||||
|
||||
self.symtab.exitScope(md)
|
||||
|
||||
|
@ -1096,6 +1153,45 @@ def formatcycles(cycles):
|
|||
r.append("`%s'" % s)
|
||||
return ", ".join(r)
|
||||
|
||||
|
||||
def fullyDefined(t, exploring=None):
|
||||
'''The rules for "full definition" of a type are
|
||||
defined(atom) := true
|
||||
defined(array basetype) := defined(basetype)
|
||||
defined(struct f1 f2...) := defined(f1) and defined(f2) and ...
|
||||
defined(union c1 c2 ...) := defined(c1) or defined(c2) or ...
|
||||
'''
|
||||
if exploring is None:
|
||||
exploring = set()
|
||||
|
||||
if t.isAtom():
|
||||
return True
|
||||
elif t.isArray():
|
||||
return fullyDefined(t.basetype, exploring)
|
||||
elif t.defined:
|
||||
return True
|
||||
assert t.isCompound()
|
||||
|
||||
if t in exploring:
|
||||
return False
|
||||
|
||||
exploring.add(t)
|
||||
for c in t.itercomponents():
|
||||
cdefined = fullyDefined(c, exploring)
|
||||
if t.isStruct() and not cdefined:
|
||||
t.defined = False
|
||||
break
|
||||
elif t.isUnion() and cdefined:
|
||||
t.defined = True
|
||||
break
|
||||
else:
|
||||
if t.isStruct(): t.defined = True
|
||||
elif t.isUnion(): t.defined = False
|
||||
exploring.remove(t)
|
||||
|
||||
return t.defined
|
||||
|
||||
|
||||
class CheckTypes(TcheckVisitor):
|
||||
def __init__(self, errors):
|
||||
# don't need the symbol table, we just want the error reporting
|
||||
|
@ -1110,6 +1206,17 @@ class CheckTypes(TcheckVisitor):
|
|||
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):
|
||||
if not fullyDefined(ud.decl.type):
|
||||
self.error(ud.decl.loc,
|
||||
"union `%s' is only partially defined", ud.name)
|
||||
|
||||
|
||||
def visitProtocol(self, p):
|
||||
self.ptype = p.decl.type
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче