add real front-end support for multiple start states in IPDL

This commit is contained in:
Chris Jones 2009-08-19 18:35:22 -05:00
parent 3480e9a0e0
commit 809d7382e0
3 changed files with 19 additions and 11 deletions

View File

@ -226,6 +226,7 @@ class Protocol(Node):
self.managesStmts = [ ] self.managesStmts = [ ]
self.messageDecls = [ ] self.messageDecls = [ ]
self.transitionStmts = [ ] self.transitionStmts = [ ]
self.startStates = [ ]
def addOuterNamespace(self, namespace): def addOuterNamespace(self, namespace):
self.namespaces.insert(0, namespace) self.namespaces.insert(0, namespace)
@ -315,17 +316,20 @@ class ANSWER:
def direction(cls): return IN def direction(cls): return IN
class State(Node): class State(Node):
def __init__(self, loc, name): def __init__(self, loc, name, start=False):
Node.__init__(self, loc) Node.__init__(self, loc)
self.name = name self.name = name
self.start = start
def __eq__(self, o): def __eq__(self, o):
return isinstance(o, State) and o.name == self.name return (isinstance(o, State)
and o.name == self.name
and o.start == self.start)
def __hash__(self): def __hash__(self):
return hash(repr(self)) return hash(repr(self))
def __ne__(self, o): def __ne__(self, o):
return not (self == o) return not (self == o)
def __repr__(self): return '<State %r>'% (self.name) def __repr__(self): return '<State %r start=%s>'% (self.name, self.start)
def __str__(self): return '<State %s>'% (self.name) def __str__(self): return '<State %s start=%s>'% (self.name, self.start)
class Param(Node): class Param(Node):
def __init__(self, loc, typespec, name): def __init__(self, loc, typespec, name):

View File

@ -403,12 +403,13 @@ def p_TransitionStmtsNonEmpty(p):
def p_TransitionStmt(p): def p_TransitionStmt(p):
"""TransitionStmt : OptionalStart STATE State ':' Transitions""" """TransitionStmt : OptionalStart STATE State ':' Transitions"""
p[3].start = p[1]
p[0] = TransitionStmt(locFromTok(p, 2), p[3], p[5]) p[0] = TransitionStmt(locFromTok(p, 2), p[3], p[5])
def p_OptionalStart(p): def p_OptionalStart(p):
"""OptionalStart : START """OptionalStart : START
| """ | """
pass p[0] = (len(p) == 2) # True iff 'start' specified
def p_Transitions(p): def p_Transitions(p):
"""Transitions : Transitions Transition """Transitions : Transitions Transition

View File

@ -318,7 +318,7 @@ With this information, it finally type checks the AST.'''
if not runpass(CheckTypes(self.errors)): if not runpass(CheckTypes(self.errors)):
return False return False
if (tu.protocol.startState is not None if (len(tu.protocol.startStates)
and not runpass(CheckStateMachine(self.errors))): and not runpass(CheckStateMachine(self.errors))):
return False return False
@ -471,9 +471,11 @@ class GatherDecls(TcheckVisitor):
p.states = { } p.states = { }
if len(p.transitionStmts): if len(p.transitionStmts):
p.startState = p.transitionStmts[0] p.startStates = [ ts for ts in p.transitionStmts
else: if ts.state.start ]
p.startState = None if 0 == len(p.startStates):
p.startStates = [ p.transitionStmts[0] ]
# declare each state before decorating their mention # declare each state before decorating their mention
for trans in p.transitionStmts: for trans in p.transitionStmts:
p.states[trans.state] = trans p.states[trans.state] = trans
@ -923,8 +925,9 @@ upon trigger |t|, or None if |t| is not a trigger in |S|.'''
visited.add(ts.state) visited.add(ts.state)
for outedge in ts.transitions: for outedge in ts.transitions:
explore(p.states[outedge.toState]) explore(p.states[outedge.toState])
explore(p.startState) for root in p.startStates:
explore(root)
for ts in p.transitionStmts: for ts in p.transitionStmts:
if ts.state not in visited: if ts.state not in visited:
self.error(ts.loc, "unreachable state `%s' in protocol `%s'", self.error(ts.loc, "unreachable state `%s' in protocol `%s'",