Commit f79e60bf authored by Maxime Perrotin's avatar Maxime Perrotin
Browse files

Improve the management of continuous states

parent 9c64e0b3
......@@ -112,6 +112,10 @@ The background pattern was downloaded from www.subtlepatterns.com
Changelog
=========
3.0.3 (05/2020)
- Replace the unicode separator when flattening the model for code generation
- Fix calls to the exit procedure in nested states
3.0.2 (05/2020)
- Fix API change in Pyside2
......
This diff is collapsed.
......@@ -198,12 +198,12 @@ def flatten(process, sep=u'_'):
set_terminator_states(state, prefix)
set_transition_states(state, prefix)
keys = list (state.mapping.keys())
state.mapping = {prefix + key: state.mapping.pop(key)
for key in list(state.mapping.keys())}
# Continuous signal mappings
state.cs_mapping = {prefix + key: state.cs_mapping.pop(key)
for key in list(state.cs_mapping.keys())}
process.transitions.extend(state.transitions)
# Add prefix to local variable names and push them at process level
......@@ -255,17 +255,35 @@ def flatten(process, sep=u'_'):
'params': [], 'tmpVars': []}]
process.transitions[each].actions.insert(0, call_entry)
# If composite state has exit procedure, add the call
# If composite state has exit procedure, add an call to this
# procedure if the transition ends up existing the state with
# a return statement. There are other calls to the exit procedure
# that the code generation backend must add when the state is exited
# from a transition trigger in the super state. See AdaGenerator.py
if state.exit_procedure:
# Build up a list of transitions that contain a return statement
trans_with_return = []
for each in chain(state.transitions, (lab.transition for lab in
state.content.floating_labels)):
if each.terminator.kind == 'return':
call_exit = ogAST.ProcedureCall()
call_exit.inputString = 'exit'
exitproc = u'{pre}exit'.format(pre=prefix)
call_exit.output = [{'outputName': exitproc,
'params': [], 'tmpVars': []}]
each.actions.append(call_exit)
def rec_transition(trans : ogAST.Transition):
if trans.terminator:
if trans.terminator.kind == 'return':
trans_with_return.append (trans)
elif isinstance(trans.actions[-1], ogAST.Decision):
# There is no terminator, so the transition may finish
# with a DECISION, we must check it recursively
for answer in trans.actions[-1].answers:
rec_transition (answer.transition)
rec_transition (each)
for trans in trans_with_return:
call_exit = ogAST.ProcedureCall()
call_exit.inputString = 'exit'
exitproc = u'{pre}exit'.format(pre=prefix)
call_exit.output = [{'outputName': exitproc,
'params': [], 'tmpVars': []}]
trans.actions.append(call_exit)
for inner in state.composite_states:
# Go recursively in inner composite states
......@@ -308,19 +326,27 @@ def flatten(process, sep=u'_'):
processed by each of the substates.
'''
if not isinstance(nested_state, ogAST.StateAggregation):
for _, val in nested_state.mapping.items():
for val in nested_state.mapping.values():
try:
inputlist = context.mapping[nested_state.statename]
val.extend(inputlist)
except (AttributeError, KeyError):
# KeyError in case of StateAggregation
pass
for val in nested_state.cs_mapping.values():
try:
inputlist = context.cs_mapping[nested_state.statename]
val.extend(inputlist)
except (AttributeError, KeyError):
# KeyError in case of StateAggregation
pass
for each in nested_state.composite_states:
# do the same recursively
propagate_inputs(each, nested_state)
#del nested_state.mapping[each.statename]
if not isinstance(nested_state, ogAST.StateAggregation):
del context.mapping[nested_state.statename]
del context.cs_mapping[nested_state.statename]
def set_terminator_states(context, prefix=''):
''' Associate state to terminators, needed to process properly
......
......@@ -27,7 +27,7 @@
See AdaGenerator.py for an example of use.
Copyright (c) 2012-2019 European Space Agency
Copyright (c) 2012-2020 European Space Agency
Designed and implemented by Maxime Perrotin
......@@ -369,7 +369,7 @@ class Answer(object):
# one of ExprEq, ExprNeq, ExprGt, ExprGe, ExprLt, ExprLe (types)
self.openRangeOp = None
# transition is of type Transition
self.transition = None
self.transition : Transition = None
# optional comment symbol
self.comment = None
# optional hyperlink
......
......@@ -2462,12 +2462,6 @@ def primary(root, context):
prim.value = []
prim.exprType = UNKNOWN_TYPE
# Let fix_expression_type resolve this type
# prim.exprType = type('PrES', (object,), {
# 'kind': 'SequenceOfType',
# 'Min': '0',
# 'Max': '0',
# 'type': UNKNOWN_TYPE
# })
elif root.type == lexer.CHOICE:
prim = ogAST.PrimChoiceItem()
choice = root.getChild(0).toString()
......@@ -2506,7 +2500,6 @@ def primary(root, context):
'type': prim_elem.exprType
})
elif root.type == lexer.STATE:
LOG.debug("Primary is state")
prim = ogAST.PrimStateReference()
prim.exprType = type ("StateEnumeratedType", (ENUMERATED,), {})
prim.exprType.kind = 'StateEnumeratedType'
......@@ -2673,6 +2666,8 @@ def composite_state(root, parent=None, context=None):
# Gather the list of states defined in the composite state
# and map a list of transitions to each state
comp.mapping = {name: [] for name in get_state_list(root)}
# Same for continuous signal mapping
comp.cs_mapping = {name: [] for name in get_state_list(root)}
inner_composite, states, floatings, starts = [], [], [], []
for child in root.getChildren():
if child.type == lexer.ID:
......@@ -2749,6 +2744,7 @@ def composite_state(root, parent=None, context=None):
# State aggregation contain only composite states, so we must
# add empty mapping information since there are no transitions
comp.mapping[inner.statename.lower()] = []
comp.cs_mapping[inner.statename.lower()] = []
errors.extend(err)
warnings.extend(warn)
comp.composite_states.append(inner)
......@@ -3494,6 +3490,7 @@ def process_definition(root, parent=None, context=None):
# Prepare the transition/state mapping
process.mapping = {name: [] for name in get_state_list(root)}
process.cs_mapping = {name: [] for name in get_state_list(root)}
for child in root.getChildren():
if child.type == lexer.CIF:
# Get symbol coordinates
......
......@@ -140,7 +140,7 @@ except ImportError:
__all__ = ['opengeode', 'SDL_Scene', 'SDL_View', 'parse']
__version__ = '3.0.2'
__version__ = '3.0.3'
if hasattr(sys, 'frozen'):
# Detect if we are running on Windows (py2exe-generated)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment