final frontend support for protocol state machines. patch includes a minor refactoring as well.

This commit is contained in:
Chris Jones 2009-07-09 13:11:52 -05:00
Родитель 6fcfe5da8f
Коммит 8e88e8c3e2
3 изменённых файлов: 102 добавлений и 50 удалений

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

@ -318,13 +318,17 @@ class Param(Node):
self.typespec = typespec
class TypeSpec(Node):
def __init__(self, loc, spec):
def __init__(self, loc, spec, state=None):
Node.__init__(self, loc)
self.spec = spec
self.state = state
def basename(self):
return self.spec.baseid
def isActor(self):
return self.state is not None
def __str__(self): return str(self.spec)
class QualifiedId: # FIXME inherit from node?

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

@ -405,11 +405,23 @@ def p_ParamList(p):
p[0] = p[1]
def p_Param(p):
"""Param : ID ID"""
"""Param : Type ID"""
p[0] = Param(locFromTok(p, 1), p[1], p[2])
def p_Type(p):
"""Type : ActorType
| ID""" # ID == CxxType; we forbid qnames here,
# in favor of the |using| declaration
if isinstance(p[1], TypeSpec):
p[0] = p[1]
else:
loc = locFromTok(p, 1)
p[0] = TypeSpec(loc, QualifiedId(loc, p[1]))
def p_ActorType(p):
"""ActorType : ID ':' State"""
loc = locFromTok(p, 1)
p[0] = Param(loc,
TypeSpec(loc, QualifiedId(loc, p[1])),
p[2])
p[0] = TypeSpec(loc, QualifiedId(loc, p[1]), state=p[3])
##--------------------
## C++ stuff

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

@ -37,13 +37,13 @@ import ipdl.builtin as builtin
class Type:
# Is this a C++ type?
def isCxx():
def isCxx(self):
return False
# Is this an IPDL type?
def isIPDL():
def isIPDL(self):
return False
# Can this type appear in IPDL programs?
def isVisible():
def isVisible(self):
return False
def isVoid(self):
return False
@ -117,6 +117,7 @@ class IPDLType(Type):
def isState(self): return False
def isMessage(self): return False
def isProtocol(self): return False
def isActor(self): return False
def isAsync(self): return self.sendSemantics is ASYNC
def isSync(self): return self.sendSemantics is SYNC
@ -190,6 +191,17 @@ class ProtocolType(IPDLType):
def isToplevel(self):
return not self.isManaged()
class ActorType(IPDLType):
def __init__(self, protocol, state):
self.protocol = protocol
self.state = state
def isActor(self): return True
def name(self):
return self.protocol.name()
def fullname(self):
return self.protocol.fullname()
##--------------------
_builtinloc = Loc('<builtin>', 0)
def makeBuiltinUsing(tname):
@ -440,6 +452,37 @@ class GatherDecls(Visitor):
for trans in p.transitionStmts:
trans.accept(self)
# visit the message decls once more and resolve the state names
# attached to actor params and returns
def resolvestate(param):
loc = param.loc
statename = param.type.state.name
statedecl = self.symtab.lookup(statename)
if statedecl is None:
self.errors.append(
errormsg(
loc,
"protocol `%s' does not have the state `%s'",
param.type.protocol.name(),
statename))
elif not statedecl.type.isState():
self.errors.append(
errormsg(
loc,
"tag `%s' is supposed to be of state type, but is instead of type `%s'",
statename,
statedecl.type.typename()))
else:
param.type.state = statedecl
for msg in p.messageDecls:
for iparam in msg.inParams:
if iparam.type.isIPDL() and iparam.type.isActor():
resolvestate(iparam)
for oparam in msg.outParams:
if oparam.type.isIPDL() and oparam.type.isActor():
resolvestate(oparam)
# FIXME/cjones declare all the little C++ thingies that will
# be generated. they're not relevant to IPDL itself, but
# those ("invisible") symbols can clash with others in the
@ -553,50 +596,43 @@ class GatherDecls(Visitor):
ctor=isctor, dtor=isdtor, cdtype=cdtype)
# replace inparam Param nodes with proper Decls
def paramToDecl(param):
ptname = param.typespec.basename()
ploc = param.typespec.loc
ptdecl = self.symtab.lookup(ptname)
if ptdecl is None:
self.errors.append(
errormsg(
ploc,
"argument typename `%s' of message `%s' has not been declared",
ptname, msgname))
return None
else:
pdecl = Decl(ploc)
pdecl.progname = param.name
ptype = None
if ptdecl.type.isIPDL() and ptdecl.type.isProtocol():
ptype = ActorType(ptdecl.type,
param.typespec.state)
else:
ptype = ptdecl.type
pdecl.type = ptype
self.symtab.declare(pdecl)
return pdecl
for i, inparam in enumerate(md.inParams):
inptname = inparam.typespec.basename()
inploc = inparam.typespec.loc
inptdecl = self.symtab.lookup(inptname)
if inptdecl is None:
self.errors.append(
errormsg(
inploc,
"inparam typename `%s' of message `%s' has not been declared",
inptname, msgname))
else:
inpdecl = Decl(inploc)
inpdecl.progname = inparam.name
inpdecl.type = inptdecl.type
self.symtab.declare(inpdecl)
msgtype.params.append(inpdecl.type)
md.inParams[i] = inpdecl
# replace outparam Param with proper Decls
pdecl = paramToDecl(inparam)
if pdecl is not None:
msgtype.params.append(pdecl.type)
md.inParams[i] = pdecl
for i, outparam in enumerate(md.outParams):
outptname = outparam.typespec.basename()
outploc = outparam.typespec.loc
outptdecl = self.symtab.lookup(outptname)
if outptdecl is None:
self.errors.append(
errormsg(
outploc,
"outparam typename `%s' of message `%s' has not been declared",
outptname, msgname))
else:
outpdecl = Decl(outploc)
outpdecl.progname = outparam.name
outpdecl.type = outptdecl.type
self.symtab.declare(outpdecl)
msgtype.returns.append(outpdecl.type)
md.outParams[i] = outpdecl
pdecl = paramToDecl(outparam)
if pdecl is not None:
msgtype.returns.append(pdecl.type)
md.outParams[i] = pdecl
self.symtab.exitScope(md)