bug 506171: rewrite lower.py and add native IPDL arrays.

This commit is contained in:
Chris Jones 2009-10-16 18:31:53 -05:00
Родитель c0129fa14f
Коммит 36a356411a
23 изменённых файлов: 3746 добавлений и 2214 удалений

Просмотреть файл

@ -672,7 +672,7 @@ PBrowserStreamChild*
PluginInstanceChild::AllocPBrowserStream(const nsCString& url,
const uint32_t& length,
const uint32_t& lastmodified,
const PStreamNotifyChild* notifyData,
PStreamNotifyChild* notifyData,
const nsCString& headers,
const nsCString& mimeType,
const bool& seekable,

Просмотреть файл

@ -97,7 +97,7 @@ protected:
AllocPBrowserStream(const nsCString& url,
const uint32_t& length,
const uint32_t& lastmodified,
const PStreamNotifyChild* notifyData,
PStreamNotifyChild* notifyData,
const nsCString& headers,
const nsCString& mimeType,
const bool& seekable,

Просмотреть файл

@ -84,7 +84,7 @@ PBrowserStreamParent*
PluginInstanceParent::AllocPBrowserStream(const nsCString& url,
const uint32_t& length,
const uint32_t& lastmodified,
const PStreamNotifyParent* notifyData,
PStreamNotifyParent* notifyData,
const nsCString& headers,
const nsCString& mimeType,
const bool& seekable,

Просмотреть файл

@ -83,7 +83,7 @@ public:
AllocPBrowserStream(const nsCString& url,
const uint32_t& length,
const uint32_t& lastmodified,
const PStreamNotifyParent* notifyData,
PStreamNotifyParent* notifyData,
const nsCString& headers,
const nsCString& mimeType,
const bool& seekable,

Просмотреть файл

@ -54,8 +54,9 @@ def typecheck(ast, errout=sys.stderr):
def gencxx(ast, outdir):
for hdr in LowerToCxx().lower(ast):
file = os.path.join(outdir,
*([ns.namespace for ns in ast.protocol.namespaces] + [hdr.filename]))
file = os.path.join(
outdir,
*([ns.name for ns in ast.protocol.namespaces] + [hdr.name]))
tempfile = StringIO()
CxxCodeGen(tempfile).cgen(hdr)

Просмотреть файл

@ -151,7 +151,7 @@ class NamespacedNode(Node):
def qname(self):
return QualifiedId(self.loc, self.name,
[ ns.namespace for ns in self.namespaces ])
[ ns.name for ns in self.namespaces ])
class TranslationUnit(Node):
def __init__(self):
@ -242,7 +242,7 @@ _prettyTable = {
class Namespace(Node):
def __init__(self, loc, namespace):
Node.__init__(self, loc)
self.namespace = namespace
self.name = namespace
class Protocol(NamespacedNode):
def __init__(self, loc):
@ -363,10 +363,11 @@ class Param(Node):
self.typespec = typespec
class TypeSpec(Node):
def __init__(self, loc, spec, state=None):
def __init__(self, loc, spec, state=None, array=0):
Node.__init__(self, loc)
self.spec = spec
self.state = state
self.array = array
def basename(self):
return self.spec.baseid

Просмотреть файл

@ -68,5 +68,6 @@ Includes = (
'nscore.h',
'IPC/IPCMessageUtils.h',
'nsStringGlue.h',
'nsTArray.h',
'mozilla/ipc/ProtocolUtils.h',
)

Просмотреть файл

@ -138,9 +138,16 @@ class Visitor:
def visitExprDeref(self, ed):
self.visitExprPrefixUnop(ed)
def visitExprNot(self, en):
self.visitExprPrefixUnop(en)
def visitExprCast(self, ec):
ec.expr.accept(self)
def visitExprIndex(self, ei):
ei.arr.accept(self)
ei.idx.accept(self)
def visitExprSelect(self, es):
es.obj.accept(self)
@ -154,7 +161,13 @@ class Visitor:
arg.accept(self)
def visitExprNew(self, en):
self.visitExprCall(en)
en.ctype.accept(self)
if en.newargs is not None:
for arg in en.newargs:
arg.accept(self)
if en.args is not None:
for arg in en.args:
arg.accept(self)
def visitExprDelete(self, ed):
ed.obj.accept(self)
@ -188,6 +201,14 @@ class Visitor:
if si.elseb is not None:
si.elseb.accept(self)
def visitStmtFor(self, sf):
if sf.init is not None:
sf.init.accept(self)
if sf.cond is not None:
sf.cond.accept(self)
if sf.update is not None:
sf.update.accept(self)
def visitStmtSwitch(self, ss):
ss.expr.accept(self)
self.visitBlock(ss)
@ -216,26 +237,37 @@ class Node:
class Whitespace(Node):
# yes, this is silly. but we need to stick comments in the
# generated code without resorting to more serious hacks
def __init__(self, ws):
def __init__(self, ws, indent=0):
Node.__init__(self)
self.ws = ws
self.indent = indent
Whitespace.NL = Whitespace('\n')
class File(Node):
def __init__(self, filename):
Node.__init__(self)
self.filename = filename
self.name = filename
# array of stuff in the file --- stmts and preprocessor thingies
self.stuff = [ ]
def addthing(self, thing):
assert thing is not None
assert not isinstance(thing, list)
self.stuff.append(thing)
def addthings(self, things):
for t in things: self.addthing(t)
# "look like" a Block so code doesn't have to care whether they're
# in global scope or not
def addstmt(self, stmt):
assert stmt is not None
assert not isinstance(stmt, list)
self.stuff.append(stmt)
def addstmts(self, stmts):
for s in stmts: self.addstmt(s)
class CppDirective(Node):
'''represents |#[directive] [rest]|, where |rest| is any string'''
def __init__(self, directive, rest):
@ -249,11 +281,12 @@ class Block(Node):
self.stmts = [ ]
def addstmt(self, stmt):
assert stmt is not None
assert not isinstance(stmt, list)
self.stmts.append(stmt)
def addstmts(self, stmts):
for stmt in stmts:
self.addstmt(stmt)
for s in stmts: self.addstmt(s)
##------------------------------
# type and decl thingies
@ -268,7 +301,7 @@ class Type(Node):
def __init__(self, name, const=0,
ptr=0, ptrconst=0, ptrptr=0, ptrconstptr=0,
ref=0,
actor=0):
T=None):
"""
To avoid getting fancy with recursive types, we limit the kinds
of pointer types that can be be constructed.
@ -279,10 +312,10 @@ of pointer types that can be be constructed.
ptrconstptr => T* const*
Any type, naked or pointer, can be const (const T) or ref (T&).
The "actor" flag is used internally when we need to know if the C++
type actually represents an IPDL actor type.
"""
assert isinstance(name, str)
assert not isinstance(const, str)
Node.__init__(self)
self.name = name
self.const = const
@ -291,7 +324,7 @@ type actually represents an IPDL actor type.
self.ptrptr = ptrptr
self.ptrconstptr = ptrconstptr
self.ref = ref
self.actor = actor
self.T = T
# XXX could get serious here with recursive types, but shouldn't
# need that for this codegen
def __deepcopy__(self, memo):
@ -299,7 +332,12 @@ type actually represents an IPDL actor type.
const=self.const,
ptr=self.ptr, ptrconst=self.ptrconst,
ptrptr=self.ptrptr, ptrconstptr=self.ptrconstptr,
ref=self.ref, actor=self.actor)
ref=self.ref,
T=copy.deepcopy(self.T, memo))
Type.BOOL = Type('bool')
Type.INT = Type('int')
Type.INTPTR = Type('intptr_t')
Type.UINT32 = Type('uint32_t')
class TypeArray(Node):
def __init__(self, basetype, nmemb):
@ -323,12 +361,10 @@ class TypeUnion(Node):
def __init__(self, name=None):
Node.__init__(self)
self.name = name
self.components = [ ] # pairs of (Type, name)
self.componentDecls = [ ] # [ Decl ]
self.components = [ ] # [ Decl ]
def addComponent(self, type, name):
self.components.append((type, name))
self.componentDecls.append(Decl(type, name))
self.components.append(Decl(type, name))
class Typedef(Node):
def __init__(self, fromtype, totypename):
@ -349,6 +385,10 @@ class ForwardDecl(Node):
class Decl(Node):
'''represents |Foo bar|, e.g. in a function signature'''
def __init__(self, type, name):
assert type is not None
assert not isinstance(type, str)
assert isinstance(name, str)
Node.__init__(self)
self.type = type
self.name = name
@ -376,9 +416,10 @@ class Class(Block):
self.struct = struct # bool
class Inherit(Node):
def __init__(self, name, viz='public'):
def __init__(self, type, viz='public'):
assert isinstance(viz, str)
Node.__init__(self)
self.name = name
self.type = type
self.viz = viz
class FriendClassDecl(Node):
@ -388,12 +429,15 @@ class FriendClassDecl(Node):
class MethodDecl(Node):
def __init__(self, name, params=[ ], ret=Type('void'),
virtual=0, const=0, pure=0, static=0, typeop=0):
virtual=0, const=0, pure=0, static=0,
typeop=None):
assert not (virtual and static)
assert not pure or virtual # pure => virtual
assert not (static and typeop)
assert not (name and typeop)
assert name is None or isinstance(name, str)
if typeop:
if typeop is not None:
ret = None
Node.__init__(self)
@ -404,8 +448,8 @@ class MethodDecl(Node):
self.const = const # bool
self.pure = pure # bool
self.static = static # bool
self.typeop = typeop # bool
self.typeop = typeop # Type or None
def __deepcopy__(self, memo):
return MethodDecl(self.name,
copy.deepcopy(self.params, memo),
@ -443,6 +487,14 @@ class DestructorDefn(MethodDefn):
##------------------------------
# expressions
class ExprVar(Node):
def __init__(self, name):
assert isinstance(name, str)
Node.__init__(self)
self.name = name
ExprVar.THIS = ExprVar('this')
class ExprLiteral(Node):
def __init__(self, value, type):
'''|type| is a Python format specifier; 'd' for example'''
@ -464,17 +516,18 @@ class ExprLiteral(Node):
ExprLiteral.ZERO = ExprLiteral.Int(0)
ExprLiteral.ONE = ExprLiteral.Int(1)
ExprLiteral.NULL = ExprLiteral.ZERO
class ExprVar(Node):
def __init__(self, name):
Node.__init__(self)
self.name = name
ExprLiteral.TRUE = ExprVar('true')
ExprLiteral.FALSE = ExprVar('false')
class ExprPrefixUnop(Node):
def __init__(self, expr, op):
self.expr = expr
self.op = op
class ExprNot(ExprPrefixUnop):
def __init__(self, expr):
ExprPrefixUnop.__init__(self, expr, '!')
class ExprAddrOf(ExprPrefixUnop):
def __init__(self, expr):
ExprPrefixUnop.__init__(self, expr, '&')
@ -510,9 +563,19 @@ class ExprConditional(Node):
self.cond = cond
self.ife = ife
self.elsee = elsee
class ExprIndex(Node):
def __init__(self, arr, idx):
Node.__init__(self)
self.arr = arr
self.idx = idx
class ExprSelect(Node):
def __init__(self, obj, op, field):
assert obj and op and field
assert not isinstance(obj, str)
assert isinstance(field, str)
Node.__init__(self)
self.obj = obj
self.op = op
@ -527,20 +590,21 @@ class ExprAssn(Node):
class ExprCall(Node):
def __init__(self, func, args=[ ]):
assert hasattr(func, 'accept')
assert isinstance(args, list)
Node.__init__(self)
self.func = func
self.args = args
class ExprNew(ExprCall):
class ExprNew(Node):
# XXX taking some poetic license ...
def __init__(self, type, args=[ ], newargs=None):
assert not (type.const or type.ref)
ctorname = type.name
if type.ptr: ctorname += '*'
elif type.ptrptr: ctorname += '**'
ExprCall.__init__(self, ExprVar(ctorname), args)
def __init__(self, ctype, args=[ ], newargs=None):
assert not (ctype.const or ctype.ref)
Node.__init__(self)
self.ctype = ctype
self.args = args
self.newargs = newargs
class ExprDelete(Node):
@ -559,14 +623,20 @@ class ExprSizeof(ExprCall):
##------------------------------
# statements etc.
class StmtBlock(Block):
def __init__(self):
def __init__(self, stmts=[ ]):
Block.__init__(self)
self.addstmts(stmts)
class StmtDecl(Node):
def __init__(self, decl, init=None):
def __init__(self, decl, init=None, initargs=None):
assert not (init and initargs)
assert not isinstance(init, str) # easy to confuse with Decl
assert not isinstance(decl, tuple)
Node.__init__(self)
self.decl = decl
self.init = init
self.initargs = initargs
class Label(Node):
def __init__(self, name):
@ -591,12 +661,28 @@ class StmtIf(Node):
self.cond = cond
self.ifb = Block()
self.elseb = None
def addifstmt(self, stmt):
self.ifb.addstmt(stmt)
def addifstmts(self, stmts):
self.ifb.addstmts(stmts)
def addelsestmt(self, stmt):
if self.elseb is None: self.elseb = Block()
self.elseb.addstmt(stmt)
def addelsestmts(self, stmts):
if self.elseb is None: self.elseb = Block()
self.elseb.addstmts(stmts)
class StmtFor(Block):
def __init__(self, init=None, cond=None, update=None):
Block.__init__(self)
self.init = init
self.cond = cond
self.update = update
class StmtSwitch(Block):
def __init__(self, expr):
Block.__init__(self)
@ -605,6 +691,11 @@ class StmtSwitch(Block):
def addcase(self, case, block):
'''NOTE: |case| is not checked for uniqueness'''
assert (isinstance(block, StmtBreak)
or isinstance(block, StmtReturn)
or (hasattr(block, 'stmts')
and (isinstance(block.stmts[-1], StmtBreak)
or isinstance(block.stmts[-1], StmtReturn))))
self.addstmt(case)
self.addstmt(block)
self.nr_cases += 1

Просмотреть файл

@ -43,6 +43,8 @@ class CxxCodeGen(CodePrinter, Visitor):
cxxfile.accept(self)
def visitWhitespace(self, ws):
if ws.indent:
self.printdent('')
self.write(ws.ws)
def visitCppDirective(self, cd):
@ -54,11 +56,17 @@ class CxxCodeGen(CodePrinter, Visitor):
self.println('} // namespace '+ ns.name)
def visitType(self, t):
if t.const:
self.write('const ')
self.write(t.name)
if t.T is not None:
self.write('<')
t.T.accept(self)
self.write('>')
ts = ''
if t.const: ts += 'const '
ts += t.name
if t.ptr: ts += '*'
elif t.ptrconst: ts += '* const'
elif t.ptrptr: ts += '**'
@ -85,7 +93,6 @@ class CxxCodeGen(CodePrinter, Visitor):
self.println()
self.dedent()
self.printdent('}')
def visitTypeUnion(self, u):
self.write('union')
@ -94,7 +101,7 @@ class CxxCodeGen(CodePrinter, Visitor):
self.println(' {')
self.indent()
for decl in u.componentDecls:
for decl in u.components:
self.printdent()
decl.accept(self)
self.println(';')
@ -173,7 +180,8 @@ class CxxCodeGen(CodePrinter, Visitor):
self.printdentln('};')
def visitInherit(self, inh):
self.write(inh.viz +' '+ inh.name)
self.write(inh.viz +' ')
inh.type.accept(self)
def visitFriendClassDecl(self, fcd):
self.printdentln('friend class '+ fcd.friend +';')
@ -189,9 +197,16 @@ class CxxCodeGen(CodePrinter, Visitor):
if md.ret:
md.ret.accept(self)
self.write(' ')
self.write(md.name +'(')
if md.typeop is not None:
self.write('operator ')
md.typeop.accept(self)
else:
self.write(md.name)
self.write('(')
self.writeDeclList(md.params)
self.write(')')
if md.const:
self.write(' const')
if md.pure:
@ -265,10 +280,12 @@ class CxxCodeGen(CodePrinter, Visitor):
self.write(ev.name)
def visitExprPrefixUnop(self, e):
self.write('(')
self.write(e.op)
self.write('(')
e.expr.accept(self)
self.write(')')
self.write(')')
def visitExprCast(self, c):
pfx, sfx = '', ''
@ -299,8 +316,16 @@ class CxxCodeGen(CodePrinter, Visitor):
c.elsee.accept(self)
self.write(')')
def visitExprIndex(self, ei):
ei.arr.accept(self)
self.write('[')
ei.idx.accept(self)
self.write(']')
def visitExprSelect(self, es):
self.write('(')
es.obj.accept(self)
self.write(')')
self.write(es.op + es.field)
def visitExprAssn(self, ea):
@ -320,11 +345,15 @@ class CxxCodeGen(CodePrinter, Visitor):
self.write('(')
self.writeExprList(en.newargs)
self.write(') ')
self.visitExprCall(en)
en.ctype.accept(self)
if en.args is not None:
self.write('(')
self.writeExprList(en.args)
self.write(')')
def visitExprDelete(self, ed):
self.write('delete ')
ed.accept(self)
ed.obj.accept(self)
def visitStmtBlock(self, b):
@ -367,6 +396,24 @@ class CxxCodeGen(CodePrinter, Visitor):
self.printdentln('}')
def visitStmtFor(self, sf):
self.printdent('for (')
if sf.init is not None:
sf.init.accept(self)
self.write('; ')
if sf.cond is not None:
sf.cond.accept(self)
self.write('; ')
if sf.update is not None:
sf.update.accept(self)
self.println(') {')
self.indent()
self.visitBlock(sf)
self.dedent()
self.printdentln('}')
def visitStmtSwitch(self, sw):
self.printdent('switch (')
sw.expr.accept(self)
@ -383,6 +430,10 @@ class CxxCodeGen(CodePrinter, Visitor):
def visitStmtDecl(self, sd):
self.printdent()
sd.decl.accept(self)
if sd.initargs is not None:
self.write('(')
self.writeDeclList(sd.initargs)
self.write(')')
if sd.init is not None:
self.write(' = ')
sd.init.accept(self)

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -519,8 +519,15 @@ def p_Param(p):
p[0] = Param(locFromTok(p, 1), p[1], p[2])
def p_Type(p):
"""Type : ActorType
| CxxID""" # ID == CxxType; we forbid qnames here,
"""Type : ScalarType
| ScalarType '[' ']'"""
if 4 == len(p):
p[1].array = 1
p[0] = p[1]
def p_ScalarType(p):
"""ScalarType : ActorType
| CxxID""" # ID == CxxType; we forbid qnames here,
# in favor of the |using| declaration
if isinstance(p[1], TypeSpec):
p[0] = p[1]

Просмотреть файл

@ -35,7 +35,58 @@ import os, sys
from ipdl.ast import CxxInclude, Decl, Loc, QualifiedId, State, TypeSpec, UsingStmt, Visitor, ASYNC, SYNC, RPC, IN, OUT, INOUT, ANSWER, CALL, RECV, SEND
import ipdl.builtin as builtin
class TypeVisitor:
def defaultVisit(self, node, *args):
raise Exception, "INTERNAL ERROR: no visitor for node type `%s'"% (
node.__class__.__name__)
def visitVoidType(self, v, *args):
pass
def visitBuiltinCxxType(self, t, *args):
pass
def visitImportedCxxType(self, t, *args):
pass
def visitStateType(self, s, *args):
pass
def visitMessageType(self, m, *args):
for param in m.params:
param.accept(self, *args)
for ret in m.returns:
ret.accept(self, *args)
if m.cdtype is not None:
m.cdtype.accept(self, *args)
def visitProtocolType(self, p, *args):
# NB: don't visit manager and manages. a naive default impl
# could result in an infinite loop
pass
def visitActorType(self, a, *args):
a.protocol.accept(self, *args)
a.state.accept(self, *args)
def visitUnionType(self, u, *args):
for component in u.components:
component.accept(self, *args)
def visitArrayType(self, a, *args):
a.basetype.accept(self, *args)
class Type:
def __cmp__(self, o):
return cmp(self.fullname(), o.fullname())
def __eq__(self, o):
return (self.__class__ == o.__class__
and self.fullname() == o.fullname())
def __hash__(self):
return hash(self.fullname())
# Is this a C++ type?
def isCxx(self):
return False
@ -53,8 +104,14 @@ class Type:
def name(self): raise Exception, 'NYI'
def fullname(self): raise Exception, 'NYI'
def accept(self, visitor, *args):
visit = getattr(visitor, 'visit'+ self.__class__.__name__, None)
if visit is None:
return getattr(visitor, 'defaultVisit')(self, *args)
return visit(self, *args)
class VoidType(Type):
# the following are not a type-o's (hah): void is both a Cxx and IPDL type
# the following are not type-o's (hah): void is both a Cxx and IPDL type
def isCxx():
return True
def isIPDL():
@ -106,10 +163,6 @@ class ImportedCxxType(CxxType):
def fullname(self):
return str(self.qname)
class GeneratedCxxType(CxxType):
def isGenerated(self): return True
def isVisible(self): return False
##--------------------
class IPDLType(Type):
def isIPDL(self): return True
@ -119,6 +172,7 @@ class IPDLType(Type):
def isProtocol(self): return False
def isActor(self): return False
def isUnion(self): return False
def isArray(self): return False
def isAsync(self): return self.sendSemantics is ASYNC
def isSync(self): return self.sendSemantics is SYNC
@ -219,6 +273,35 @@ class UnionType(IPDLType):
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 isArray(self): return True
def name(self): return self.basetype.name() +'[]'
def fullname(self): return self.basetype.fullname() +'[]'
def iteractortypes(type):
"""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.isUnion():
for c in type.components:
for actor in iteractortypes(c):
yield actor
def hasactor(type):
"""Return true iff |type| is an actor or has one buried within."""
for _ in iteractortypes(type): return True
return False
##--------------------
_builtinloc = Loc('<builtin>', 0)
def makeBuiltinUsing(tname):
@ -448,18 +531,19 @@ class GatherDecls(TcheckVisitor):
fullname = str(qname)
components = [ ]
nactors = 0 # FIXME
for c in ud.components:
ctype = self.symtab.lookup(str(c)).type
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
ctype = cdecl.type
if ctype.isIPDL() and ctype.isProtocol():
ctype = ActorType(ctype)
nactors += 1
if c.array:
ctype = ArrayType(ctype)
components.append(ctype)
if nactors > 1:
self.error(ud.loc, 'sorry, IPDL currently limits you to one actor type per union. file a bug against :cjones')
ud.decl = self.declare(
loc=ud.loc,
type=UnionType(qname, components),
@ -537,22 +621,30 @@ class GatherDecls(TcheckVisitor):
# visit the message decls once more and resolve the state names
# attached to actor params and returns
def resolvestate(param):
if param.type.state is None:
def resolvestate(loc, actortype):
assert actortype.isIPDL() and actortype.isActor()
# already resolved this guy's state
if isinstance(actortype.state, Decl):
return
if actortype.state is None:
# we thought this was a C++ type until type checking,
# when we realized it was an IPDL actor type. But
# that means that the actor wasn't specified to be in
# any particular state
param.type.state = State.ANY
actortype.state = State.ANY
loc = param.loc
statename = param.type.state.name
statename = actortype.state.name
# FIXME/cjones: this is just wrong. we need the symbol table
# of the protocol this actor refers to. low priority bug
# since nobody's using this feature yet
statedecl = self.symtab.lookup(statename)
if statedecl is None:
self.error(
loc,
"protocol `%s' does not have the state `%s'",
param.type.protocol.name(),
actortype.protocol.name(),
statename)
elif not statedecl.type.isState():
self.error(
@ -561,15 +653,17 @@ class GatherDecls(TcheckVisitor):
statename,
statedecl.type.typename())
else:
param.type.state = statedecl
actortype.state = statedecl
for msg in p.messageDecls:
for iparam in msg.inParams:
if iparam.type and iparam.type.isIPDL() and iparam.type.isActor():
resolvestate(iparam)
loc = iparam.loc
for actortype in iteractortypes(iparam.type):
resolvestate(loc, actortype)
for oparam in msg.outParams:
if oparam.type and oparam.type.isIPDL() and oparam.type.isActor():
resolvestate(oparam)
loc = oparam.loc
for actortype in iteractortypes(oparam.type):
resolvestate(loc, actortype)
# FIXME/cjones declare all the little C++ thingies that will
# be generated. they're not relevant to IPDL itself, but
@ -687,6 +781,10 @@ class GatherDecls(TcheckVisitor):
param.typespec.state)
else:
ptype = ptdecl.type
if param.typespec.array:
ptype = ArrayType(ptype)
return self.declare(
loc=ploc,
type=ptype,

Просмотреть файл

@ -56,11 +56,12 @@ LIBXUL_LIBRARY = 1
FORCE_STATIC_LIB = 1
EXPORT_LIBRARY = 1
IPDLTESTS = \
# Please keep these organized in the order "easy"-to-"hard"
IPDLTESTS = \
TestSanity \
TestLatency \
TestManyChildAllocs \
TestSanity \
TestArrays \
$(NULL)
IPDLTESTSRCS = $(addsuffix .cpp,$(IPDLTESTS))

Просмотреть файл

@ -0,0 +1,91 @@
include protocol "PTestArraysSub.ipdl";
namespace mozilla {
namespace _ipdltest {
union IntDouble {
int;
double;
};
union IntDoubleArrays {
int;
int[];
double[];
};
union Actors {
int;
int[];
PTestArraysSub[];
};
union Unions {
int;
int[];
PTestArraysSub[];
Actors[];
};
sync protocol PTestArrays {
manages PTestArraysSub;
child:
PTestArraysSub(int i);
Start();
parent:
~PTestArraysSub();
sync Test1(int[] i1)
returns (int[] o1);
sync Test2(PTestArraysSub[] i1)
returns (PTestArraysSub[] o1);
sync Test3(IntDouble i1,
IntDouble i2)
returns (IntDouble o1,
IntDouble o2);
sync Test4(IntDouble[] i1)
returns (IntDouble[] o1);
sync Test5(IntDoubleArrays i1,
IntDoubleArrays i2,
IntDoubleArrays i3)
returns (IntDoubleArrays o1,
IntDoubleArrays o2,
IntDoubleArrays o3);
sync Test6(IntDoubleArrays[] i1)
returns (IntDoubleArrays[] o1);
sync Test7(Actors i1,
Actors i2,
Actors i3)
returns (Actors o1,
Actors o2,
Actors o3);
sync Test8(Actors[] i1)
returns (Actors[] o1);
sync Test9(Unions i1,
Unions i2,
Unions i3,
Unions i4)
returns (Unions o1,
Unions o2,
Unions o3,
Unions o4);
sync Test10(Unions[] i1)
returns (Unions[] o1);
};
} // namespace _ipdltest
} // namespace mozilla

Просмотреть файл

@ -0,0 +1,12 @@
include protocol "PTestArrays.ipdl";
namespace mozilla {
namespace _ipdltest {
protocol PTestArraysSub {
manager PTestArrays;
// empty
};
} // namespace _ipdltest
} // namespace mozilla

Просмотреть файл

@ -0,0 +1,555 @@
#include "TestArrays.h"
#include "nsIAppShell.h"
#include "nsCOMPtr.h"
#include "nsServiceManagerUtils.h" // do_GetService()
#include "nsWidgetsCID.h" // NS_APPSHELL_CID
#include "IPDLUnitTests.h" // fail etc.
namespace mozilla {
namespace _ipdltest {
static const uint32_t nactors = 10;
#define test_assert(_cond, _msg) \
if (!(_cond)) fail(_msg)
template<typename T>
static void
assert_arrays_equal(nsTArray<T> a, nsTArray<T> b)
{
test_assert(a.Length() == b.Length(), "Length()s different");
for (uint32_t i = 0; i < a.Length(); ++i)
test_assert(a[i] == b[i], "values different");
}
inline static TestArraysSub&
Cast(PTestArraysSubParent* a)
{
return *static_cast<TestArraysSub*>(a);
}
inline static TestArraysSub&
Cast(PTestArraysSubChild* a)
{
return *static_cast<TestArraysSub*>(a);
}
//-----------------------------------------------------------------------------
// parent
TestArraysParent::TestArraysParent()
{
MOZ_COUNT_CTOR(TestArraysParent);
}
TestArraysParent::~TestArraysParent()
{
MOZ_COUNT_DTOR(TestArraysParent);
}
void
TestArraysParent::Main()
{
for (uint32_t i = 0; i < nactors; ++i)
if (!SendPTestArraysSubConstructor(i))
fail("can't alloc actor");
if (!SendStart())
fail("can't send Start()");
}
bool
TestArraysParent::RecvPTestArraysSubDestructor(PTestArraysSubParent* actor)
{
test_assert(Cast(actor).mI == Cast(mKids[0]).mI,
"dtor sent to wrong actor");
mKids.RemoveElementAt(0);
if (mKids.Length() > 0)
return true;
passed("with flying colors");
static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
nsCOMPtr<nsIAppShell> appShell (do_GetService(kAppShellCID));
appShell->Exit();
return true;
}
bool TestArraysParent::RecvTest1(
const nsTArray<int>& ia,
nsTArray<int>* oa)
{
test_assert(5 == ia.Length(), "wrong length");
for (int i = 0; i < 5; ++i)
test_assert(i == ia[i], "wrong value");
*oa = ia;
return true;
}
bool TestArraysParent::RecvTest2(
const nsTArray<PTestArraysSubParent*>& i1,
nsTArray<PTestArraysSubParent*>* o1)
{
test_assert(nactors == i1.Length(), "wrong #actors");
for (uint32_t i = 0; i < i1.Length(); ++i)
test_assert(i == Cast(i1[i]).mI, "wrong mI value");
*o1 = i1;
return true;
}
bool TestArraysParent::RecvTest3(
const IntDouble& i1,
const IntDouble& i2,
IntDouble* o1,
IntDouble* o2)
{
test_assert(42 == i1.get_int(), "wrong value");
test_assert(4.0 == i2.get_double(), "wrong value");
*o1 = i1;
*o2 = i2;
return true;
}
bool TestArraysParent::RecvTest4(
const nsTArray<IntDouble>& i1,
nsTArray<IntDouble>* o1)
{
test_assert(4 == i1.Length(), "wrong length");
test_assert(1 == i1[0].get_int(), "wrong value");
test_assert(2.0 == i1[1].get_double(), "wrong value");
test_assert(3 == i1[2].get_int(), "wrong value");
test_assert(4.0 == i1[3].get_double(), "wrong value");
*o1 = i1;
return true;
}
bool TestArraysParent::RecvTest5(
const IntDoubleArrays& i1,
const IntDoubleArrays& i2,
const IntDoubleArrays& i3,
IntDoubleArrays* o1,
IntDoubleArrays* o2,
IntDoubleArrays* o3)
{
test_assert(42 == i1.get_int(), "wrong value");
const nsTArray<int>& i2a = i2.get_ArrayOfint();
test_assert(3 == i2a.Length(), "wrong length");
test_assert(1 == i2a[0], "wrong value");
test_assert(2 == i2a[1], "wrong value");
test_assert(3 == i2a[2], "wrong value");
const nsTArray<double>& i3a = i3.get_ArrayOfdouble();
test_assert(3 == i3a.Length(), "wrong length");
test_assert(1.0 == i3a[0], "wrong value");
test_assert(2.0 == i3a[1], "wrong value");
test_assert(3.0 == i3a[2], "wrong value");
*o1 = i1;
*o2 = i2a;
*o3 = i3a;
return true;
}
bool TestArraysParent::RecvTest6(
const nsTArray<IntDoubleArrays>& i1,
nsTArray<IntDoubleArrays>* o1)
{
test_assert(3 == i1.Length(), "wrong length");
IntDoubleArrays id1(i1[0]);
test_assert(42 == id1.get_int(), "wrong value");
nsTArray<int> i2a = i1[1].get_ArrayOfint();
test_assert(3 == i2a.Length(), "wrong length");
test_assert(1 == i2a[0], "wrong value");
test_assert(2 == i2a[1], "wrong value");
test_assert(3 == i2a[2], "wrong value");
nsTArray<double> i3a = i1[2].get_ArrayOfdouble();
test_assert(3 == i3a.Length(), "wrong length");
test_assert(1.0 == i3a[0], "wrong value");
test_assert(2.0 == i3a[1], "wrong value");
test_assert(3.0 == i3a[2], "wrong value");
o1->AppendElement(id1);
o1->AppendElement(IntDoubleArrays(i2a));
o1->AppendElement(IntDoubleArrays(i3a));
return true;
}
bool TestArraysParent::RecvTest7(
const Actors& i1,
const Actors& i2,
const Actors& i3,
Actors* o1,
Actors* o2,
Actors* o3)
{
test_assert(42 == i1.get_int(), "wrong value");
nsTArray<int> i2a(i2.get_ArrayOfint());
test_assert(3 == i2a.Length(), "wrong length");
test_assert(1 == i2a[0], "wrong value");
test_assert(2 == i2a[1], "wrong value");
test_assert(3 == i2a[2], "wrong value");
assert_arrays_equal(mKids, i3.get_ArrayOfPTestArraysSubParent());
*o1 = 42;
*o2 = i2a;
*o3 = mKids;
return true;
}
bool TestArraysParent::RecvTest8(
const nsTArray<Actors>& i1,
nsTArray<Actors>* o1)
{
test_assert(3 == i1.Length(), "wrong length");
test_assert(42 == i1[0].get_int(), "wrong value");
const nsTArray<int>& i2a = i1[1].get_ArrayOfint();
test_assert(3 == i2a.Length(), "wrong length");
test_assert(1 == i2a[0], "wrong value");
test_assert(2 == i2a[1], "wrong value");
test_assert(3 == i2a[2], "wrong value");
assert_arrays_equal(mKids, i1[2].get_ArrayOfPTestArraysSubParent());
*o1 = i1;
return true;
}
bool TestArraysParent::RecvTest9(
const Unions& i1,
const Unions& i2,
const Unions& i3,
const Unions& i4,
Unions* o1,
Unions* o2,
Unions* o3,
Unions* o4)
{
test_assert(42 == i1.get_int(), "wrong value");
const nsTArray<int>& i2a = i2.get_ArrayOfint();
test_assert(3 == i2a.Length(), "wrong length");
test_assert(1 == i2a[0], "wrong value");
test_assert(2 == i2a[1], "wrong value");
test_assert(3 == i2a[2], "wrong value");
assert_arrays_equal(mKids, i3.get_ArrayOfPTestArraysSubParent());
const nsTArray<PTestArraysSubParent*>& i4a =
i4.get_ArrayOfActors()[0].get_ArrayOfPTestArraysSubParent();
assert_arrays_equal(mKids, i4a);
*o1 = i1;
*o2 = i2;
*o3 = i3;
*o4 = i4;
return true;
}
bool TestArraysParent::RecvTest10(
const nsTArray<Unions>& i1,
nsTArray<Unions>* o1)
{
test_assert(42 == i1[0].get_int(), "wrong value");
const nsTArray<int>& i2a = i1[1].get_ArrayOfint();
test_assert(3 == i2a.Length(), "wrong length");
test_assert(1 == i2a[0], "wrong value");
test_assert(2 == i2a[1], "wrong value");
test_assert(3 == i2a[2], "wrong value");
assert_arrays_equal(mKids, i1[2].get_ArrayOfPTestArraysSubParent());
const nsTArray<PTestArraysSubParent*>& i4a =
i1[3].get_ArrayOfActors()[0].get_ArrayOfPTestArraysSubParent();
assert_arrays_equal(mKids, i4a);
*o1 = i1;
return true;
}
//-----------------------------------------------------------------------------
// child
TestArraysChild::TestArraysChild()
{
MOZ_COUNT_CTOR(TestArraysChild);
}
TestArraysChild::~TestArraysChild()
{
MOZ_COUNT_DTOR(TestArraysChild);
}
bool
TestArraysChild::RecvStart()
{
puts("[TestArraysChild] starting");
Test1();
Test2();
Test3();
Test4();
Test5();
Test6();
Test7();
Test8();
Test9();
Test10();
for (uint32_t i = 0; i < nactors; ++i)
if (!SendPTestArraysSubDestructor(mKids[i]))
fail("can't send dtor");
return true;
}
void
TestArraysChild::Test1()
{
nsTArray<int> ia;
for (int i = 0; i < 5; ++i)
ia.AppendElement(i);
nsTArray<int> oa;
if (!SendTest1(ia, &oa))
fail("can't send Test1");
assert_arrays_equal(ia, oa);
printf(" passed %s\n", __FUNCTION__);
}
void
TestArraysChild::Test2()
{
nsTArray<PTestArraysSubChild*> oa;
if (!SendTest2(mKids, &oa))
fail("can't send Test2");
assert_arrays_equal(mKids, oa);
printf(" passed %s\n", __FUNCTION__);
}
void
TestArraysChild::Test3()
{
int i1i = 42;
double i2d = 4.0;
IntDouble i1(i1i);
IntDouble i2(i2d);
IntDouble o1, o2;
SendTest3(i1, i2, &o1, &o2);
test_assert(i1i == o1.get_int(), "wrong value");
test_assert(i2d == o2.get_double(), "wrong value");
printf(" passed %s\n", __FUNCTION__);
}
void
TestArraysChild::Test4()
{
nsTArray<IntDouble> i1;
i1.AppendElement(IntDouble(int(1)));
i1.AppendElement(IntDouble(2.0));
i1.AppendElement(IntDouble(int(3)));
i1.AppendElement(IntDouble(4.0));
nsTArray<IntDouble> o1;
if (!SendTest4(i1, &o1))
fail("can't send Test4");
// TODO Union::operator==()
test_assert(i1.Length() == o1.Length(), "wrong length");
test_assert(1 == o1[0].get_int(), "wrong value");
test_assert(2.0 == o1[1].get_double(), "wrong value");
test_assert(3 == o1[2].get_int(), "wrong value");
test_assert(4.0 == o1[3].get_double(), "wrong value");
printf(" passed %s\n", __FUNCTION__);
}
void
TestArraysChild::Test5()
{
IntDoubleArrays i1(int(42));
nsTArray<int> i2;
i2.AppendElement(1); i2.AppendElement(2); i2.AppendElement(3);
nsTArray<double> i3;
i3.AppendElement(1.0); i3.AppendElement(2.0); i3.AppendElement(3.0);
IntDoubleArrays o1, o2, o3;
if (!SendTest5(i1, IntDoubleArrays(i2), IntDoubleArrays(i3),
&o1, &o2, &o3))
fail("can't send Test5");
test_assert(42 == o1.get_int(), "wrong value");
assert_arrays_equal(i2, o2.get_ArrayOfint());
assert_arrays_equal(i3, o3.get_ArrayOfdouble());
printf(" passed %s\n", __FUNCTION__);
}
void
TestArraysChild::Test6()
{
IntDoubleArrays id1(int(42));
nsTArray<int> id2;
id2.AppendElement(1); id2.AppendElement(2); id2.AppendElement(3);
nsTArray<double> id3;
id3.AppendElement(1.0); id3.AppendElement(2.0); id3.AppendElement(3.0);
nsTArray<IntDoubleArrays> i1;
i1.AppendElement(id1);
i1.AppendElement(IntDoubleArrays(id2));
i1.AppendElement(IntDoubleArrays(id3));
nsTArray<IntDoubleArrays> o1;
if (!SendTest6(i1, &o1))
fail("can't send Test6");
test_assert(3 == o1.Length(), "wrong length");
IntDoubleArrays od1(o1[0]);
nsTArray<int> od2 = o1[1].get_ArrayOfint();
nsTArray<double> od3 = o1[2].get_ArrayOfdouble();
test_assert(42 == od1.get_int(), "wrong value");
assert_arrays_equal(id2, od2);
assert_arrays_equal(id3, od3);
printf(" passed %s\n", __FUNCTION__);
}
void
TestArraysChild::Test7()
{
Actors i1(42);
nsTArray<int> i2a;
i2a.AppendElement(1); i2a.AppendElement(2); i2a.AppendElement(3);
Actors o1, o2, o3;
if (!SendTest7(i1, Actors(i2a), Actors(mKids), &o1, &o2, &o3))
fail("can't send Test7");
test_assert(42 == o1.get_int(), "wrong value");
assert_arrays_equal(i2a, o2.get_ArrayOfint());
assert_arrays_equal(mKids, o3.get_ArrayOfPTestArraysSubChild());
printf(" passed %s\n", __FUNCTION__);
}
void
TestArraysChild::Test8()
{
Actors i1e(42);
nsTArray<int> i2a;
i2a.AppendElement(1); i2a.AppendElement(2); i2a.AppendElement(3);
nsTArray<Actors> i1;
i1.AppendElement(i1e);
i1.AppendElement(i2a);
i1.AppendElement(mKids);
nsTArray<Actors> o1;
if (!SendTest8(i1, &o1))
fail("can't send Test8");
test_assert(3 == o1.Length(), "wrong length");
test_assert(42 == o1[0].get_int(), "wrong value");
assert_arrays_equal(i2a, o1[1].get_ArrayOfint());
assert_arrays_equal(mKids, o1[2].get_ArrayOfPTestArraysSubChild());
printf(" passed %s\n", __FUNCTION__);
}
void
TestArraysChild::Test9()
{
Unions i1(int(42));
nsTArray<int> i2a;
i2a.AppendElement(1);
i2a.AppendElement(2);
i2a.AppendElement(3);
nsTArray<Actors> i4a;
i4a.AppendElement(mKids);
Unions o1, o2, o3, o4;
if (!SendTest9(i1, Unions(i2a), Unions(mKids), Unions(i4a),
&o1, &o2, &o3, &o4))
fail("can't send Test9");
test_assert(42 == o1.get_int(), "wrong value");
assert_arrays_equal(i2a, o2.get_ArrayOfint());
assert_arrays_equal(mKids, o3.get_ArrayOfPTestArraysSubChild());
assert_arrays_equal(
mKids,
o4.get_ArrayOfActors()[0].get_ArrayOfPTestArraysSubChild());
printf(" passed %s\n", __FUNCTION__);
}
void
TestArraysChild::Test10()
{
Unions i1a(int(42));
nsTArray<int> i2a;
i2a.AppendElement(1);
i2a.AppendElement(2);
i2a.AppendElement(3);
nsTArray<Actors> i4a;
i4a.AppendElement(mKids);
nsTArray<Unions> i1;
i1.AppendElement(i1a);
i1.AppendElement(Unions(i2a));
i1.AppendElement(Unions(mKids));
i1.AppendElement(Unions(i4a));
nsTArray<Unions> o1;
if (!SendTest10(i1, &o1))
fail("can't send Test10");
test_assert(4 == o1.Length(), "wrong length");
test_assert(42 == o1[0].get_int(), "wrong value");
assert_arrays_equal(i2a, o1[1].get_ArrayOfint());
assert_arrays_equal(mKids, o1[2].get_ArrayOfPTestArraysSubChild());
assert_arrays_equal(
mKids,
o1[3].get_ArrayOfActors()[0].get_ArrayOfPTestArraysSubChild());
printf(" passed %s\n", __FUNCTION__);
}
} // namespace _ipdltest
} // namespace mozilla

Просмотреть файл

@ -0,0 +1,159 @@
#ifndef mozilla__ipdltest_TestArrays_h
#define mozilla__ipdltest_TestArrays_h 1
#include "mozilla/_ipdltest/PTestArraysParent.h"
#include "mozilla/_ipdltest/PTestArraysChild.h"
#include "mozilla/_ipdltest/PTestArraysSubParent.h"
#include "mozilla/_ipdltest/PTestArraysSubChild.h"
namespace mozilla {
namespace _ipdltest {
//-----------------------------------------------------------------------------
// Subprotocol actors
class TestArraysSub :
public PTestArraysSubParent,
public PTestArraysSubChild
{
public:
TestArraysSub(uint32_t i) : mI(i)
{ }
virtual ~TestArraysSub()
{ }
uint32_t mI;
};
//-----------------------------------------------------------------------------
// Main actors
class TestArraysParent :
public PTestArraysParent
{
public:
TestArraysParent();
virtual ~TestArraysParent();
void Main();
protected:
virtual PTestArraysSubParent* AllocPTestArraysSub(const int& i)
{
PTestArraysSubParent* actor = new TestArraysSub(i);
mKids.AppendElement(actor);
return actor;
}
virtual bool DeallocPTestArraysSub(PTestArraysSubParent* actor)
{
delete actor;
return true;
}
virtual bool
RecvPTestArraysSubDestructor(PTestArraysSubParent* actor);
virtual bool RecvTest1(
const nsTArray<int>& i1,
nsTArray<int>* o1);
virtual bool RecvTest2(
const nsTArray<PTestArraysSubParent*>& i1,
nsTArray<PTestArraysSubParent*>* o1);
virtual bool RecvTest3(
const IntDouble& i1,
const IntDouble& i2,
IntDouble* o1,
IntDouble* o2);
virtual bool RecvTest4(
const nsTArray<IntDouble>& i1,
nsTArray<IntDouble>* o1);
virtual bool RecvTest5(
const IntDoubleArrays& i1,
const IntDoubleArrays& i2,
const IntDoubleArrays& i3,
IntDoubleArrays* o1,
IntDoubleArrays* o2,
IntDoubleArrays* o3);
virtual bool RecvTest6(
const nsTArray<IntDoubleArrays>& i1,
nsTArray<IntDoubleArrays>* o1);
virtual bool RecvTest7(
const Actors& i1,
const Actors& i2,
const Actors& i3,
Actors* o1,
Actors* o2,
Actors* o3);
virtual bool RecvTest8(
const nsTArray<Actors>& i1,
nsTArray<Actors>* o1);
virtual bool RecvTest9(
const Unions& i1,
const Unions& i2,
const Unions& i3,
const Unions& i4,
Unions* o1,
Unions* o2,
Unions* o3,
Unions* o4);
virtual bool RecvTest10(
const nsTArray<Unions>& i1,
nsTArray<Unions>* o1);
private:
nsTArray<PTestArraysSubParent*> mKids;
};
class TestArraysChild :
public PTestArraysChild
{
public:
TestArraysChild();
virtual ~TestArraysChild();
protected:
virtual PTestArraysSubChild* AllocPTestArraysSub(const int& i)
{
PTestArraysSubChild* actor = new TestArraysSub(i);
mKids.AppendElement(actor);
return actor;
}
virtual bool DeallocPTestArraysSub(PTestArraysSubChild* actor)
{
delete actor;
return true;
}
virtual bool RecvStart();
private:
void Test1();
void Test2();
void Test3();
void Test4();
void Test5();
void Test6();
void Test7();
void Test8();
void Test9();
void Test10();
nsTArray<PTestArraysSubChild*> mKids;
};
} // namespace _ipdltest
} // namespace mozilla
#endif // ifndef mozilla__ipdltest_TestArrays_h

Просмотреть файл

@ -1,4 +1,6 @@
IPDLSRCS = \
PTestArrays.ipdl \
PTestArraysSub.ipdl \
PTestLatency.ipdl \
PTestManyChildAllocs.ipdl \
PTestManyChildAllocsSub.ipdl \

Просмотреть файл

@ -0,0 +1,3 @@
protocol array_Recursive {
child: Msg(int[][] aa);
};

Просмотреть файл

@ -0,0 +1,4 @@
protocol array_Basic {
child:
Msg(int[] array);
};

Просмотреть файл

@ -0,0 +1,11 @@
include protocol "array_OfActorsSub.ipdl";
protocol array_OfActors {
manages array_OfActorsSub;
child:
Msg(array_OfActorsSub[] p);
array_OfActorsSub();
~array_OfActorsSub();
};

Просмотреть файл

@ -0,0 +1,7 @@
include protocol "array_OfActors.ipdl";
protocol array_OfActorsSub {
manager array_OfActors;
// empty
};

Просмотреть файл

@ -0,0 +1,10 @@
union Union {
int[];
int;
double;
};
sync protocol array_Union {
parent:
sync Msg(Union u, Union[] au) returns (Union r);
};