--- a/ipc/ipdl/ipdl/ast.py
+++ b/ipc/ipdl/ipdl/ast.py
@@ -51,41 +51,26 @@ class Visitor:
t.accept(self)
def visitUsingStmt(self, using):
pass
def visitProtocol(self, p):
for namespace in p.namespaces:
namespace.accept(self)
- for spawns in p.spawnsStmts:
- spawns.accept(self)
- for bridges in p.bridgesStmts:
- bridges.accept(self)
- for opens in p.opensStmts:
- opens.accept(self)
for mgr in p.managers:
mgr.accept(self)
for managed in p.managesStmts:
managed.accept(self)
for msgDecl in p.messageDecls:
msgDecl.accept(self)
def visitNamespace(self, ns):
pass
- def visitSpawnsStmt(self, spawns):
- pass
-
- def visitBridgesStmt(self, bridges):
- pass
-
- def visitOpensStmt(self, opens):
- pass
-
def visitManager(self, mgr):
pass
def visitManagesStmt(self, mgs):
pass
def visitMessageDecl(self, md):
for inParam in md.inParams:
@@ -221,19 +206,16 @@ class Namespace(Node):
Node.__init__(self, loc)
self.name = namespace
class Protocol(NamespacedNode):
def __init__(self, loc):
NamespacedNode.__init__(self, loc)
self.sendSemantics = ASYNC
self.nested = NOT_NESTED
- self.spawnsStmts = [ ]
- self.bridgesStmts = [ ]
- self.opensStmts = [ ]
self.managers = [ ]
self.managesStmts = [ ]
self.messageDecls = [ ]
class StructField(Node):
def __init__(self, loc, type, name):
Node.__init__(self, loc)
self.typespec = type
@@ -244,35 +226,16 @@ class StructDecl(NamespacedNode):
NamespacedNode.__init__(self, loc, name)
self.fields = fields
class UnionDecl(NamespacedNode):
def __init__(self, loc, name, components):
NamespacedNode.__init__(self, loc, name)
self.components = components
-class SpawnsStmt(Node):
- def __init__(self, loc, side, proto, spawnedAs):
- Node.__init__(self, loc)
- self.side = side
- self.proto = proto
- self.spawnedAs = spawnedAs
-
-class BridgesStmt(Node):
- def __init__(self, loc, parentSide, childSide):
- Node.__init__(self, loc)
- self.parentSide = parentSide
- self.childSide = childSide
-
-class OpensStmt(Node):
- def __init__(self, loc, side, proto):
- Node.__init__(self, loc)
- self.side = side
- self.proto = proto
-
class Manager(Node):
def __init__(self, loc, managerName):
Node.__init__(self, loc)
self.name = managerName
class ManagesStmt(Node):
def __init__(self, loc, managedName):
Node.__init__(self, loc)
--- a/ipc/ipdl/ipdl/lower.py
+++ b/ipc/ipdl/ipdl/lower.py
@@ -4,17 +4,17 @@
import os, re, sys
from copy import deepcopy
from collections import OrderedDict
import ipdl.ast
import ipdl.builtin
from ipdl.cxx.ast import *
-from ipdl.type import ActorType, ProcessGraph, TypeVisitor, builtinHeaderIncludes
+from ipdl.type import ActorType, TypeVisitor, builtinHeaderIncludes
##-----------------------------------------------------------------------------
## "Public" interface to lowering
##
class LowerToCxx:
def lower(self, tu):
'''returns |[ header: File ], [ cpp : File ]| representing the
lowered form of |tu|'''
@@ -358,21 +358,16 @@ def _callClearManagedActors(managees):
def _callHasManagedActor(managees, actor):
return ExprCall(ExprSelect(managees, '.', 'Contains'), args=[ actor ])
def _otherSide(side):
if side == 'child': return 'parent'
if side == 'parent': return 'child'
assert 0
-def _sideToTransportMode(side):
- if side == 'parent': mode = 'SERVER'
- elif side == 'child': mode = 'CLIENT'
- return ExprVar('mozilla::ipc::Transport::MODE_'+ mode)
-
def _ifLogging(topLevelProtocol, stmts):
iflogging = StmtIf(ExprCall(ExprVar('mozilla::ipc::LoggingEnabledFor'),
args=[ topLevelProtocol ]))
iflogging.addifstmts(stmts)
return iflogging
# XXX we need to remove these and install proper error handling
def _printErrorMessage(msg):
@@ -1471,61 +1466,27 @@ class _GenerateProtocolCode(ipdl.ast.Vis
# Forward declare our own actors.
self.hdrfile.addthings([
Whitespace.NL,
_makeForwardDeclForActor(p.decl.type, 'Parent'),
_makeForwardDeclForActor(p.decl.type, 'Child')
])
- bridges = ProcessGraph.bridgesOf(p.decl.type)
- for bridge in bridges:
- ppt, pside = bridge.parent.ptype, _otherSide(bridge.parent.side)
- cpt, cside = bridge.child.ptype, _otherSide(bridge.child.side)
- self.hdrfile.addthings([
- Whitespace.NL,
- _makeForwardDeclForActor(ppt, pside),
- _makeForwardDeclForActor(cpt, cside)
- ])
- self.cppIncludeHeaders.append(_protocolHeaderName(ppt._ast, pside))
- self.cppIncludeHeaders.append(_protocolHeaderName(cpt._ast, cside))
-
- opens = ProcessGraph.opensOf(p.decl.type)
- for o in opens:
- optype, oside = o.opener.ptype, o.opener.side
- self.hdrfile.addthings([
- Whitespace.NL,
- _makeForwardDeclForActor(optype, oside)
- ])
- self.cppIncludeHeaders.append(_protocolHeaderName(optype._ast, oside))
-
self.hdrfile.addthing(Whitespace("""
//-----------------------------------------------------------------------------
// Code common to %sChild and %sParent
//
"""% (p.name, p.name)))
# construct the namespace into which we'll stick all our decls
ns = Namespace(self.protocol.name)
self.hdrfile.addthing(_putInNamespaces(ns, p.namespaces))
ns.addstmt(Whitespace.NL)
- # user-facing methods for connecting two process with a new channel
- for bridge in bridges:
- bdecl, bdefn = _splitFuncDeclDefn(self.genBridgeFunc(bridge))
- ns.addstmts([ bdecl, Whitespace.NL ])
- self.funcDefns.append(bdefn)
-
- # user-facing methods for opening a new channel across two
- # existing endpoints
- for o in opens:
- odecl, odefn = _splitFuncDeclDefn(self.genOpenFunc(o))
- ns.addstmts([ odecl, Whitespace.NL ])
- self.funcDefns.append(odefn)
-
edecl, edefn = _splitFuncDeclDefn(self.genEndpointFunc())
ns.addstmts([ edecl, Whitespace.NL ])
self.funcDefns.append(edefn)
# state information
stateenum = TypeEnum('State')
# NB: __Dead is the first state on purpose, so that it has
# value '0'
@@ -1569,65 +1530,16 @@ class _GenerateProtocolCode(ipdl.ast.Vis
self.funcDefns.append(rfDefn)
decls.append(Whitespace.NL)
ns.addstmts(decls)
ns.addstmts([ Whitespace.NL, Whitespace.NL ])
- def genBridgeFunc(self, bridge):
- p = self.protocol
- parentHandleType = _cxxBareType(ActorType(bridge.parent.ptype),
- _otherSide(bridge.parent.side),
- fq=1)
- parentvar = ExprVar('parentHandle')
-
- childHandleType = _cxxBareType(ActorType(bridge.child.ptype),
- _otherSide(bridge.child.side),
- fq=1)
- childvar = ExprVar('childHandle')
-
- bridgefunc = MethodDefn(MethodDecl(
- 'Bridge',
- params=[ Decl(parentHandleType, parentvar.name),
- Decl(childHandleType, childvar.name) ],
- ret=Type.NSRESULT))
- bridgefunc.addstmt(StmtReturn(ExprCall(
- ExprVar('mozilla::ipc::Bridge'),
- args=[ _backstagePass(),
- p.callGetChannel(parentvar), p.callOtherPid(parentvar),
- p.callGetChannel(childvar), p.callOtherPid(childvar),
- _protocolId(p.decl.type),
- ExprVar(_messageStartName(p.decl.type) + 'Child')
- ])))
- return bridgefunc
-
-
- def genOpenFunc(self, o):
- p = self.protocol
- localside = o.opener.side
- openertype = _cxxBareType(ActorType(o.opener.ptype), o.opener.side,
- fq=1)
- openervar = ExprVar('opener')
- openfunc = MethodDefn(MethodDecl(
- 'Open',
- params=[ Decl(openertype, openervar.name) ],
- ret=Type.BOOL))
- openfunc.addstmt(StmtReturn(ExprCall(
- ExprVar('mozilla::ipc::Open'),
- args=[ _backstagePass(),
- p.callGetChannel(openervar), p.callOtherPid(openervar),
- _sideToTransportMode(localside),
- _protocolId(p.decl.type),
- ExprVar(_messageStartName(p.decl.type) + 'Child')
- ])))
- return openfunc
-
-
# Generate code for PFoo::CreateEndpoints.
def genEndpointFunc(self):
p = self.protocol.decl.type
tparent = _cxxBareType(ActorType(p), 'Parent', fq=1)
tchild = _cxxBareType(ActorType(p), 'Child', fq=1)
methodvar = ExprVar('CreateEndpoints')
rettype = Type.NSRESULT
parentpidvar = ExprVar('aParentDestPid')
@@ -2605,20 +2517,16 @@ class _GenerateProtocolActorCode(ipdl.as
Whitespace.NL
])
self.cls = Class(
self.clsname,
inherits=inherits,
abstract=True)
- bridgeActorsCreated = ProcessGraph.bridgeEndpointsOf(ptype, self.side)
- opensActorsCreated = ProcessGraph.opensEndpointsOf(ptype, self.side)
- channelOpenedActors = OrderedDict.fromkeys(bridgeActorsCreated + opensActorsCreated, None)
-
friends = _FindFriends().findFriends(ptype)
if ptype.isManaged():
friends.update(ptype.managers)
# |friend| managed actors so that they can call our Dealloc*()
friends.update(ptype.manages)
# don't friend ourself if we're a self-managed protocol
@@ -2629,23 +2537,16 @@ class _GenerateProtocolActorCode(ipdl.as
_makeForwardDeclForActor(friend, self.prettyside),
Whitespace.NL
])
self.cls.addstmts([
FriendClassDecl(_actorName(friend.fullname(),
self.prettyside)),
Whitespace.NL ])
- for actor in channelOpenedActors:
- self.hdrfile.addthings([
- Whitespace.NL,
- _makeForwardDeclForActor(actor.ptype, actor.side),
- Whitespace.NL
- ])
-
self.cls.addstmt(Label.PROTECTED)
for typedef in p.cxxTypedefs():
self.cls.addstmt(typedef)
for typedef in self.includedActorTypedefs:
self.cls.addstmt(typedef)
self.cls.addstmt(Whitespace.NL)
@@ -2687,27 +2588,16 @@ class _GenerateProtocolActorCode(ipdl.as
virtual=1, pure=1)))
self.cls.addstmt(StmtDecl(MethodDecl(
_deallocMethod(managed, self.side).name,
params=[ Decl(actortype, 'aActor') ],
ret=Type.BOOL,
virtual=1, pure=1)))
- for actor in channelOpenedActors:
- # add the Alloc interface for actors created when a
- # new channel is opened
- actortype = _cxxBareType(actor.asType(), actor.side)
- self.cls.addstmt(StmtDecl(MethodDecl(
- _allocMethod(actor.ptype, actor.side).name,
- params=[ Decl(Type('Transport', ptr=1), 'aTransport'),
- Decl(Type('ProcessId'), 'aOtherPid') ],
- ret=actortype,
- virtual=1, pure=1)))
-
# ActorDestroy() method; default is no-op
self.cls.addstmts([
Whitespace.NL,
MethodDefn(MethodDecl(
_destroyMethod().name,
params=[ Decl(_DestroyReason.Type(), 'aWhy') ],
ret=Type.VOID,
virtual=1, pure=(self.side == 'parent'))),
@@ -2860,21 +2750,16 @@ class _GenerateProtocolActorCode(ipdl.as
if toplevel.isInterrupt():
self.interruptSwitch = StmtSwitch(msgtype)
# implement Send*() methods and add dispatcher cases to
# message switch()es
for md in p.messageDecls:
self.visitMessageDecl(md)
- # Handlers for the creation of actors when a new channel is
- # opened
- if len(channelOpenedActors):
- self.makeChannelOpenedHandlers(channelOpenedActors)
-
# add default cases
default = StmtBlock()
default.addstmt(StmtReturn(_Result.NotKnown))
self.asyncSwitch.addcase(DefaultLabel(), default)
if toplevel.isSync() or toplevel.isInterrupt():
self.syncSwitch.addcase(DefaultLabel(), default)
if toplevel.isInterrupt():
self.interruptSwitch.addcase(DefaultLabel(), default)
@@ -3294,94 +3179,16 @@ class _GenerateProtocolActorCode(ipdl.as
ifstmt,
StmtReturn(_Result.Processed)
])
ifstmt.addifstmt(StmtReturn(_Result.PayloadError))
return case
- def makeChannelOpenedHandlers(self, actors):
- handlers = StmtBlock()
-
- # unpack the transport descriptor et al.
- msgvar = self.msgvar
- tdvar = ExprVar('td')
- pidvar = ExprVar('pid')
- pvar = ExprVar('protocolid')
- iffail = StmtIf(ExprNot(ExprCall(
- ExprVar('mozilla::ipc::UnpackChannelOpened'),
- args=[ _backstagePass(),
- msgvar,
- ExprAddrOf(tdvar), ExprAddrOf(pidvar), ExprAddrOf(pvar) ])))
- iffail.addifstmt(StmtReturn(_Result.PayloadError))
- handlers.addstmts([
- StmtDecl(Decl(Type('TransportDescriptor'), tdvar.name)),
- StmtDecl(Decl(Type('ProcessId'), pidvar.name)),
- StmtDecl(Decl(Type('ProtocolId'), pvar.name)),
- iffail,
- Whitespace.NL
- ])
-
- def makeHandlerCase(actor):
- self.protocolCxxIncludes.append(_protocolHeaderName(actor.ptype._ast,
- actor.side))
-
- case = StmtBlock()
- modevar = _sideToTransportMode(actor.side)
- tvar = ExprVar('t')
- iffailopen = StmtIf(ExprNot(ExprAssn(
- tvar,
- ExprCall(ExprVar('mozilla::ipc::OpenDescriptor'),
- args=[ tdvar, modevar ]))))
- iffailopen.addifstmt(StmtReturn(_Result.ValuError))
-
- pvar = ExprVar('p')
- iffailalloc = StmtIf(ExprNot(ExprAssn(
- pvar,
- ExprCall(
- _allocMethod(actor.ptype, actor.side),
- args=[ _uniqueptrGet(tvar), pidvar ]))))
- iffailalloc.addifstmt(StmtReturn(_Result.ProcessingError))
-
- settrans = StmtExpr(ExprCall(
- ExprSelect(pvar, '->', 'IToplevelProtocol::SetTransport'),
- args=[ExprMove(tvar)]))
-
- case.addstmts([
- StmtDecl(Decl(_uniqueptr(Type('Transport')), tvar.name)),
- StmtDecl(Decl(Type(_actorName(actor.ptype.name(), actor.side),
- ptr=1), pvar.name)),
- iffailopen,
- iffailalloc,
- settrans,
- StmtBreak()
- ])
- label = _messageStartName(actor.ptype)
- if actor.side == 'child':
- label += 'Child'
- return CaseLabel(label), case
-
- pswitch = StmtSwitch(pvar)
- for actor in actors:
- label, case = makeHandlerCase(actor)
- pswitch.addcase(label, case)
-
- die = Block()
- die.addstmts([ _fatalError('Invalid protocol'),
- StmtReturn(_Result.ValuError) ])
- pswitch.addcase(DefaultLabel(), die)
-
- handlers.addstmts([
- pswitch,
- StmtReturn(_Result.Processed)
- ])
- self.asyncSwitch.addcase(CaseLabel('CHANNEL_OPENED_MESSAGE_TYPE'),
- handlers)
-
##-------------------------------------------------------------------------
## The next few functions are the crux of the IPDL code generator.
## They generate code for all the nasty work of message
## serialization/deserialization and dispatching handlers for
## received messages.
##
def implementPickling(self):
# pickling of "normal", non-IPDL types
--- a/ipc/ipdl/ipdl/parser.py
+++ b/ipc/ipdl/ipdl/parser.py
@@ -100,41 +100,37 @@ class Parser:
def locFromTok(p, num):
return Loc(Parser.current.filename, p.lineno(num))
##-----------------------------------------------------------------------------
reserved = set((
- 'as',
'async',
'both',
- 'bridges',
'child',
'class',
'compress',
'compressall',
'__delete__',
'delete', # reserve 'delete' to prevent its use
'from',
'include',
'intr',
'manager',
'manages',
'namespace',
'nested',
'nullable',
- 'opens',
'or',
'parent',
'prio',
'protocol',
'returns',
- 'spawns',
'struct',
'sync',
'union',
'upto',
'using',
'verify'))
tokens = [
'COLONCOLON', 'ID', 'STRING',
@@ -345,71 +341,19 @@ def p_ProtocolDefn(p):
protocol.sendSemantics = p[1][1]
p[0] = protocol
if Parser.current.type == 'header':
_error(protocol.loc, 'can\'t define a protocol in a header. Do it in a protocol spec instead.')
def p_ProtocolBody(p):
- """ProtocolBody : SpawnsStmtsOpt"""
+ """ProtocolBody : ManagersStmtOpt"""
p[0] = p[1]
-##--------------------
-## spawns/bridges/opens stmts
-
-def p_SpawnsStmtsOpt(p):
- """SpawnsStmtsOpt : SpawnsStmt SpawnsStmtsOpt
- | BridgesStmtsOpt"""
- if 2 == len(p):
- p[0] = p[1]
- else:
- p[2].spawnsStmts.insert(0, p[1])
- p[0] = p[2]
-
-def p_SpawnsStmt(p):
- """SpawnsStmt : PARENT SPAWNS ID AsOpt ';'
- | CHILD SPAWNS ID AsOpt ';'"""
- p[0] = SpawnsStmt(locFromTok(p, 1), p[1], p[3], p[4])
-
-def p_AsOpt(p):
- """AsOpt : AS PARENT
- | AS CHILD
- | """
- if 3 == len(p):
- p[0] = p[2]
- else:
- p[0] = 'child'
-
-def p_BridgesStmtsOpt(p):
- """BridgesStmtsOpt : BridgesStmt BridgesStmtsOpt
- | OpensStmtsOpt"""
- if 2 == len(p):
- p[0] = p[1]
- else:
- p[2].bridgesStmts.insert(0, p[1])
- p[0] = p[2]
-
-def p_BridgesStmt(p):
- """BridgesStmt : BRIDGES ID ',' ID ';'"""
- p[0] = BridgesStmt(locFromTok(p, 1), p[2], p[4])
-
-def p_OpensStmtsOpt(p):
- """OpensStmtsOpt : OpensStmt OpensStmtsOpt
- | ManagersStmtOpt"""
- if 2 == len(p):
- p[0] = p[1]
- else:
- p[2].opensStmts.insert(0, p[1])
- p[0] = p[2]
-
-def p_OpensStmt(p):
- """OpensStmt : PARENT OPENS ID ';'
- | CHILD OPENS ID ';'"""
- p[0] = OpensStmt(locFromTok(p, 1), p[1], p[3])
##--------------------
## manager/manages stmts
def p_ManagersStmtOpt(p):
"""ManagersStmtOpt : ManagersStmt ManagesStmtsOpt
| ManagesStmtsOpt"""
if 2 == len(p):
--- a/ipc/ipdl/ipdl/type.py
+++ b/ipc/ipdl/ipdl/type.py
@@ -10,27 +10,16 @@ from ipdl.ast import TypeSpec, UnionDecl
from ipdl.ast import ASYNC, SYNC, INTR
from ipdl.ast import IN, OUT, INOUT
from ipdl.ast import NOT_NESTED, INSIDE_SYNC_NESTED, INSIDE_CPOW_NESTED
import ipdl.builtin as builtin
_DELETE_MSG = '__delete__'
-def _otherside(side):
- if side == 'parent': return 'child'
- elif side == 'child': return 'parent'
- else: assert 0 and 'unknown side "%s"'% (side)
-
-def cartesian_product(s1, s2):
- for e1 in s1:
- for e2 in s2:
- yield (e1, e2)
-
-
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__)
@@ -218,59 +207,36 @@ class MessageType(IPDLType):
def isIn(self): return self.direction is IN
def isOut(self): return self.direction is OUT
def isInout(self): return self.direction is INOUT
def hasImplicitActorParam(self):
return self.isCtor() or self.isDtor()
-class Bridge:
- def __init__(self, parentPtype, childPtype):
- assert parentPtype.isToplevel() and childPtype.isToplevel()
- self.parent = parentPtype
- self.child = childPtype
-
- def __cmp__(self, o):
- return cmp(self.parent, o.parent) or cmp(self.child, o.child)
- def __eq__(self, o):
- return self.parent == o.parent and self.child == o.child
- def __hash__(self):
- return hash(self.parent) + hash(self.child)
-
class ProtocolType(IPDLType):
def __init__(self, qname, nestedRange, sendSemantics):
self.qname = qname
self.nestedRange = nestedRange
self.sendSemantics = sendSemantics
- self.spawns = set() # ProtocolType
- self.opens = set() # ProtocolType
self.managers = [] # ProtocolType
self.manages = [ ]
self.hasDelete = False
self.hasReentrantDelete = False
def isProtocol(self): return True
def name(self):
return self.qname.baseid
def fullname(self):
return str(self.qname)
def addManager(self, mgrtype):
assert mgrtype.isIPDL() and mgrtype.isProtocol()
self.managers.append(mgrtype)
- def addSpawn(self, ptype):
- assert self.isToplevel() and ptype.isToplevel()
- self.spawns.add(ptype)
-
- def addOpen(self, ptype):
- assert self.isToplevel() and ptype.isToplevel()
- self.opens.add(ptype)
-
def managedBy(self, mgr):
self.managers = list(mgr)
def toplevel(self):
if self.isToplevel():
return self
for mgr in self.managers:
if mgr is not self:
@@ -551,20 +517,16 @@ With this information, it finally type c
# and location of declaration
if not runpass(GatherDecls(builtinUsing, self.errors)):
return False
# 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
-
return True
def reportErrors(self, errout):
for error in self.errors:
print >>errout, error
class TcheckVisitor(Visitor):
@@ -784,25 +746,16 @@ class GatherDecls(TcheckVisitor):
type=ipdltype,
shortname=using.type.basename(),
fullname=fullname)
def visitProtocol(self, p):
# protocol scope
self.symtab.enterScope(p)
- for spawns in p.spawnsStmts:
- spawns.accept(self)
-
- for bridges in p.bridgesStmts:
- bridges.accept(self)
-
- for opens in p.opensStmts:
- opens.accept(self)
-
seenmgrs = set()
for mgr in p.managers:
if mgr.name in seenmgrs:
self.error(mgr.loc, "manager `%s' appears multiple times",
mgr.name)
continue
seenmgrs.add(mgr.name)
@@ -846,43 +799,16 @@ class GatherDecls(TcheckVisitor):
# be generated. they're not relevant to IPDL itself, but
# those ("invisible") symbols can clash with others in the
# IPDL spec, and we'd like to catch those before C++ compilers
# are allowed to obfuscate the error
self.symtab.exitScope(p)
- def visitSpawnsStmt(self, spawns):
- pname = spawns.proto
- spawns.proto = self.symtab.lookup(pname)
- if spawns.proto is None:
- self.error(spawns.loc,
- "spawned protocol `%s' has not been declared",
- pname)
-
- def visitBridgesStmt(self, bridges):
- def lookup(p):
- decl = self.symtab.lookup(p)
- if decl is None:
- self.error(bridges.loc,
- "bridged protocol `%s' has not been declared", p)
- return decl
- bridges.parentSide = lookup(bridges.parentSide)
- bridges.childSide = lookup(bridges.childSide)
-
- def visitOpensStmt(self, opens):
- pname = opens.proto
- opens.proto = self.symtab.lookup(pname)
- if opens.proto is None:
- self.error(opens.loc,
- "opened protocol `%s' has not been declared",
- pname)
-
-
def visitManager(self, mgr):
mgrdecl = self.symtab.lookup(mgr.name)
pdecl = mgr.of.decl
assert pdecl
pname, mgrname = pdecl.shortname, mgr.name
loc = mgr.loc
@@ -1102,31 +1028,16 @@ class CheckTypes(TcheckVisitor):
def visitProtocol(self, p):
self.ptype = p.decl.type
# check that we require no more "power" than our manager protocols
ptype, pname = p.decl.type, p.decl.shortname
- if len(p.spawnsStmts) and not ptype.isToplevel():
- self.error(p.decl.loc,
- "protocol `%s' is not top-level and so cannot declare |spawns|",
- pname)
-
- if len(p.bridgesStmts) and not ptype.isToplevel():
- self.error(p.decl.loc,
- "protocol `%s' is not top-level and so cannot declare |bridges|",
- pname)
-
- if len(p.opensStmts) and not ptype.isToplevel():
- self.error(p.decl.loc,
- "protocol `%s' is not top-level and so cannot declare |opens|",
- pname)
-
for mgrtype in ptype.managers:
if mgrtype is not None and ptype.needsMoreJuiceThan(mgrtype):
self.error(
p.decl.loc,
"protocol `%s' requires more powerful send semantics than its manager `%s' provides",
pname, mgrtype.name())
# XXX currently we don't require a delete() message of top-level
@@ -1151,67 +1062,16 @@ class CheckTypes(TcheckVisitor):
self.error(
p.decl.loc,
"top-level protocol `%s' cannot manage itself",
p.name)
return Visitor.visitProtocol(self, p)
- def visitSpawnsStmt(self, spawns):
- if not self.ptype.isToplevel():
- self.error(spawns.loc,
- "only top-level protocols can have |spawns| statements; `%s' cannot",
- self.ptype.name())
- return
-
- spawnedType = spawns.proto.type
- if not (spawnedType.isIPDL() and spawnedType.isProtocol()
- and spawnedType.isToplevel()):
- self.error(spawns.loc,
- "cannot spawn non-top-level-protocol `%s'",
- spawnedType.name())
- else:
- self.ptype.addSpawn(spawnedType)
-
-
- def visitBridgesStmt(self, bridges):
- if not self.ptype.isToplevel():
- self.error(bridges.loc,
- "only top-level protocols can have |bridges| statements; `%s' cannot",
- self.ptype.name())
- return
-
- parentType = bridges.parentSide.type
- childType = bridges.childSide.type
- if not (parentType.isIPDL() and parentType.isProtocol()
- and childType.isIPDL() and childType.isProtocol()
- and parentType.isToplevel() and childType.isToplevel()):
- self.error(bridges.loc,
- "cannot bridge non-top-level-protocol(s) `%s' and `%s'",
- parentType.name(), childType.name())
-
-
- def visitOpensStmt(self, opens):
- if not self.ptype.isToplevel():
- self.error(opens.loc,
- "only top-level protocols can have |opens| statements; `%s' cannot",
- self.ptype.name())
- return
-
- openedType = opens.proto.type
- if not (openedType.isIPDL() and openedType.isProtocol()
- and openedType.isToplevel()):
- self.error(opens.loc,
- "cannot open non-top-level-protocol `%s'",
- openedType.name())
- else:
- self.ptype.addOpen(openedType)
-
-
def visitManagesStmt(self, mgs):
pdecl = mgs.manager.decl
ptype, pname = pdecl.type, pdecl.shortname
mgsdecl = mgs.decl
mgstype, mgsname = mgsdecl.type, mgsdecl.shortname
loc = mgs.loc
@@ -1293,335 +1153,8 @@ class CheckTypes(TcheckVisitor):
"message `%s' in protocol `%s' requests compression but is not async or is special (ctor or dtor)",
mname[:-len('constructor')], pname)
if mtype.isCtor() and not ptype.isManagerOf(mtype.constructedType()):
self.error(
loc,
"ctor for protocol `%s', which is not managed by protocol `%s'",
mname[:-len('constructor')], pname)
-
-
-##-----------------------------------------------------------------------------
-
-class Process:
- def __init__(self):
- self.actors = set() # set(Actor)
- self.edges = { } # Actor -> [ SpawnsEdge ]
- self.spawn = set() # set(Actor)
-
- def edge(self, spawner, spawn):
- if spawner not in self.edges: self.edges[spawner] = [ ]
- self.edges[spawner].append(SpawnsEdge(spawner, spawn))
- self.spawn.add(spawn)
-
- def iteredges(self):
- for edgelist in self.edges.itervalues():
- for edge in edgelist:
- yield edge
-
- def merge(self, o):
- 'Merge the Process |o| into this Process'
- if self == o:
- return
- for actor in o.actors:
- ProcessGraph.actorToProcess[actor] = self
- self.actors.update(o.actors)
- self.edges.update(o.edges)
- self.spawn.update(o.spawn)
- ProcessGraph.processes.remove(o)
-
- def spawns(self, actor):
- return actor in self.spawn
-
- def __cmp__(self, o): return cmp(self.actors, o.actors)
- def __eq__(self, o): return self.actors == o.actors
- def __hash__(self): return hash(id(self))
- def __repr__(self):
- return reduce(lambda a, x: str(a) + str(x) +'|', self.actors, '|')
- def __str__(self): return repr(self)
-
-class Actor:
- def __init__(self, ptype, side):
- self.ptype = ptype
- self.side = side
-
- def asType(self):
- return ActorType(self.ptype)
- def other(self):
- return Actor(self.ptype, _otherside(self.side))
-
- def __cmp__(self, o):
- return cmp(self.ptype, o.ptype) or cmp(self.side, o.side)
- def __eq__(self, o):
- return self.ptype == o.ptype and self.side == o.side
- def __hash__(self): return hash(repr(self))
- def __repr__(self): return '%s%s'% (self.ptype.name(), self.side.title())
- def __str__(self): return repr(self)
-
-class SpawnsEdge:
- def __init__(self, spawner, spawn):
- self.spawner = spawner # Actor
- self.spawn = spawn # Actor
- def __repr__(self):
- return '(%r)--spawns-->(%r)'% (self.spawner, self.spawn)
- def __str__(self): return repr(self)
-
-class BridgeEdge:
- def __init__(self, bridgeProto, parent, child):
- self.bridgeProto = bridgeProto # ProtocolType
- self.parent = parent # Actor
- self.child = child # Actor
- def __repr__(self):
- return '(%r)--%s bridge-->(%r)'% (
- self.parent, self.bridgeProto.name(), self.child)
- def __str__(self): return repr(self)
-
-class OpensEdge:
- def __init__(self, opener, openedProto):
- self.opener = opener # Actor
- self.openedProto = openedProto # ProtocolType
- def __repr__(self):
- return '(%r)--opens-->(%s)'% (self.opener, self.openedProto.name())
- def __str__(self): return repr(self)
-
-# "singleton" class with state that persists across type checking of
-# all protocols
-class ProcessGraph:
- processes = set() # set(Process)
- bridges = { } # ProtocolType -> [ BridgeEdge ]
- opens = { } # ProtocolType -> [ OpensEdge ]
- actorToProcess = { } # Actor -> Process
- visitedSpawns = set() # set(ActorType)
- visitedBridges = set() # set(ActorType)
-
- @classmethod
- def findProcess(cls, actor):
- return cls.actorToProcess.get(actor, None)
-
- @classmethod
- def getProcess(cls, actor):
- if actor not in cls.actorToProcess:
- p = Process()
- p.actors.add(actor)
- cls.processes.add(p)
- cls.actorToProcess[actor] = p
- return cls.actorToProcess[actor]
-
- @classmethod
- def bridgesOf(cls, bridgeP):
- return cls.bridges.get(bridgeP, [])
-
- @classmethod
- def bridgeEndpointsOf(cls, ptype, side):
- actor = Actor(ptype, side)
- endpoints = []
- for b in cls.iterbridges():
- if b.parent == actor:
- endpoints.append(Actor(b.bridgeProto, 'parent'))
- if b.child == actor:
- endpoints.append(Actor(b.bridgeProto, 'child'))
- return endpoints
-
- @classmethod
- def iterbridges(cls):
- for edges in cls.bridges.itervalues():
- for bridge in edges:
- yield bridge
-
- @classmethod
- def opensOf(cls, openedP):
- return cls.opens.get(openedP, [])
-
- @classmethod
- def opensEndpointsOf(cls, ptype, side):
- actor = Actor(ptype, side)
- endpoints = []
- for o in cls.iteropens():
- if actor == o.opener:
- endpoints.append(Actor(o.openedProto, o.opener.side))
- elif actor == o.opener.other():
- endpoints.append(Actor(o.openedProto, o.opener.other().side))
- return endpoints
-
- @classmethod
- def iteropens(cls):
- for edges in cls.opens.itervalues():
- for opens in edges:
- yield opens
-
- @classmethod
- def spawn(cls, spawner, remoteSpawn):
- localSpawn = remoteSpawn.other()
- spawnerProcess = ProcessGraph.getProcess(spawner)
- spawnerProcess.merge(ProcessGraph.getProcess(localSpawn))
- spawnerProcess.edge(spawner, remoteSpawn)
-
- @classmethod
- def bridge(cls, parent, child, bridgeP):
- bridgeParent = Actor(bridgeP, 'parent')
- parentProcess = ProcessGraph.getProcess(parent)
- parentProcess.merge(ProcessGraph.getProcess(bridgeParent))
- bridgeChild = Actor(bridgeP, 'child')
- childProcess = ProcessGraph.getProcess(child)
- childProcess.merge(ProcessGraph.getProcess(bridgeChild))
- if bridgeP not in cls.bridges:
- cls.bridges[bridgeP] = [ ]
- cls.bridges[bridgeP].append(BridgeEdge(bridgeP, parent, child))
-
- @classmethod
- def open(cls, opener, opened, openedP):
- remoteOpener, remoteOpened, = opener.other(), opened.other()
- openerProcess = ProcessGraph.getProcess(opener)
- openerProcess.merge(ProcessGraph.getProcess(opened))
- remoteOpenerProcess = ProcessGraph.getProcess(remoteOpener)
- remoteOpenerProcess.merge(ProcessGraph.getProcess(remoteOpened))
- if openedP not in cls.opens:
- cls.opens[openedP] = [ ]
- cls.opens[openedP].append(OpensEdge(opener, openedP))
-
-
-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):
- 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)
- self.visiting = ptype
- ProcessGraph.getProcess(Actor(ptype, 'parent'))
- ProcessGraph.getProcess(Actor(ptype, 'child'))
- return TcheckVisitor.visitProtocol(self, p)
-
- def visitSpawnsStmt(self, spawns):
- # The picture here is:
- # [ spawner | localSpawn | ??? ] (process 1)
- # |
- # |
- # [ remoteSpawn | ???] (process 2)
- #
- # A spawns stmt tells us that |spawner| and |localSpawn|
- # are in the same process.
- spawner = Actor(self.visiting, spawns.side)
- remoteSpawn = Actor(spawns.proto.type, spawns.spawnedAs)
- ProcessGraph.spawn(spawner, remoteSpawn)
-
- def __init__(self, errors):
- TcheckVisitor.__init__(self, None, errors)
- 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):
- 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)
- self.visiting = ptype
- return TcheckVisitor.visitProtocol(self, p)
-
- def visitBridgesStmt(self, bridges):
- bridgeProto = self.visiting
- parentSideProto = bridges.parentSide.type
- childSideProto = bridges.childSide.type
-
- # the picture here is:
- # (process 1|
- # [ parentSide(Parent|Child) | childSide(Parent|Child) | ... ]
- # | |
- # | (process 2| |
- # [ parentSide(Child|Parent) | bridgeParent ] |
- # | |
- # | | (process 3|
- # [ bridgeChild | childSide(Child|Parent) ]
- #
- # First we have to figure out which parentSide/childSide
- # actors live in the same process. The possibilities are {
- # parent, child } x { parent, child }. (Multiple matches
- # aren't allowed yet.) Then we make ProcessGraph aware of the
- # new bridge.
- parentSideActor, childSideActor = None, None
- pc = ( 'parent', 'child' )
- for parentSide, childSide in cartesian_product(pc, pc):
- pactor = Actor(parentSideProto, parentSide)
- pproc = ProcessGraph.findProcess(pactor)
- cactor = Actor(childSideProto, childSide)
- cproc = ProcessGraph.findProcess(cactor)
- assert pproc and cproc
-
- if pproc == cproc:
- if parentSideActor is not None:
- if parentSideProto != childSideProto:
- self.error(bridges.loc,
- "ambiguous bridge `%s' between `%s' and `%s'",
- bridgeProto.name(),
- parentSideProto.name(),
- childSideProto.name())
- else:
- parentSideActor, childSideActor = pactor.other(), cactor.other()
-
- if parentSideActor is None:
- self.error(bridges.loc,
- "`%s' and `%s' cannot be bridged by `%s' ",
- parentSideProto.name(), childSideProto.name(),
- bridgeProto.name())
-
- ProcessGraph.bridge(parentSideActor, childSideActor, bridgeProto)
-
- def visitOpensStmt(self, opens):
- openedP = opens.proto.type
- opener = Actor(self.visiting, opens.side)
- opened = Actor(openedP, opens.side)
-
- # The picture here is:
- # [ opener | opened ] (process 1)
- # | |
- # | |
- # [ remoteOpener | remoteOpened ] (process 2)
- #
- # An opens stmt tells us that the pairs |opener|/|opened|
- # and |remoteOpener|/|remoteOpened| are each in the same
- # process.
- ProcessGraph.open(opener, opened, openedP)
-
-
-class CheckProcessGraph(TcheckVisitor):
- def __init__(self, errors):
- TcheckVisitor.__init__(self, None, errors)
-
- # TODO: verify spawns-per-process assumption and check that graph
- # is a dag
- def visitTranslationUnit(self, tu):
- if 0:
- print 'Processes'
- for process in ProcessGraph.processes:
- print ' ', process
- for edge in process.iteredges():
- print ' ', edge
- print 'Bridges'
- for bridgeList in ProcessGraph.bridges.itervalues():
- for bridge in bridgeList:
- print ' ', bridge
- print 'Opens'
- for opensList in ProcessGraph.opens.itervalues():
- for opens in opensList:
- print ' ', opens