diff --git a/autocoder/QmParser.py b/autocoder/QmParser.py index d5d3533..568951c 100755 --- a/autocoder/QmParser.py +++ b/autocoder/QmParser.py @@ -41,7 +41,11 @@ def parseTrans(qmTrans: ElementTreeType, number_gen: UniqueNumberGenerator): source = xmiNode.id - target = int(qmTrans.get('target')) if qmTrans.get('target') else None + target = None + + if (qmTrans.get("target") != "None"): + target = int(qmTrans.get('target')) if qmTrans.get('target') else None + kind = qmTrans.get('kind') guard = qmlib.pick_guard(qmTrans) action = flatt.pick_action(qmTrans) @@ -106,6 +110,7 @@ def populateXmiModel(qmRoot: ElementTreeType, # Replace the relative target attributes with ID's for node in qmFix.iter(): target = node.get("target") + if target is not None: targetId = flatt.state_from_target(node).get("id") node.set("target", str(targetId)) diff --git a/autocoder/Stars.py b/autocoder/Stars.py index 5e67998..580bff1 100755 --- a/autocoder/Stars.py +++ b/autocoder/Stars.py @@ -200,8 +200,8 @@ def getQmRoot(modelFileName: str) -> Tuple[ElementTreeType, XmiModel] : print("*** Error - missing namespace argument for the fprime backend") exit(0) else: - fppcoder.generateCode(xmiModel) - fprimecoder.generateCode(qmRoot, args.noImpl, args.namespace) + fppcoder.generateCode(xmiModel) + fprimecoder.generateCode(qmRoot, args.noImpl, args.namespace) diff --git a/autocoder/flattenstatemachine.py b/autocoder/flattenstatemachine.py index f34ed65..7b54c11 100755 --- a/autocoder/flattenstatemachine.py +++ b/autocoder/flattenstatemachine.py @@ -169,12 +169,18 @@ def get_this_state(tran: ElementTreeType) -> Optional[str]: def get_state_from_index(root: ElementTreeType, index: int) -> ElementTreeType: count = 0 + for child in root: if child.tag == 'state' or child.tag == 'tran': count = count + 1 + if index == count: - assert child.tag == 'state' - return child + if (child.tag == "state"): + return child; + else: + assert child.tag == "tran" + + return child assert 0 @@ -202,10 +208,12 @@ def mark_self_transition(tran: ElementTreeType): # ----------------------------------------------------------------------- def state_from_target(tran: ElementTreeType) -> ElementTreeType: target = tran.get('target') + if target is None: return tran.getparent() else: root = tran + for i in target.split('/'): if i == "..": root = root.getparent() diff --git a/autocoder/fprime_backend/fprimeImplTemplates.py b/autocoder/fprime_backend/fprimeImplTemplates.py index 123d62e..2104b81 100644 --- a/autocoder/fprime_backend/fprimeImplTemplates.py +++ b/autocoder/fprime_backend/fprimeImplTemplates.py @@ -17,29 +17,29 @@ class FprimeImplTemplate: # ------------------------------------------------------------------------------- # stateEnumFpp # ------------------------------------------------------------------------------- - def stateEnumFpp(self, smname: str, namespace: str, stateList: List[str]): - template = Template(""" - - enum $(smname)States { - #set $counter = 0 - #for $state in $stateList - $(state) = $counter - #set $counter = $counter + 1 - #end for + def stateEnumFpp(self, smname: str, namespace: str, stateList: List[str]): + template = Template(""" + module $(namespace){ + enum $(smname)_State{ + #set $counter = 0 + #for $state in $stateList + $(state) = $counter + #set $counter = $counter + 1 + #end for + } } - """) - template.smname = smname - template.namespace = namespace - template.stateList = stateList + template.smname = smname + template.namespace = namespace + template.stateList = stateList - return str(template) + return str(template) # ------------------------------------------------------------------------------- # componentHdrFile # ------------------------------------------------------------------------------- - def componentHdrFile(self, smname: str, namespace: str, component: str, funcList: List[str]) -> str: - template = Template(""" + def componentHdrFile(self, smname: str, namespace: str, component: str, funcList: List[str]) -> str: + template = Template(""" #ifndef _SIGNAL_GEN_HPP_ @@ -69,18 +69,18 @@ class $(component) : public $(smname)_Interface { """) - template.funcList = funcList - template.smname = smname - template.namespace = namespace - template.component = component + template.funcList = funcList + template.smname = smname + template.namespace = namespace + template.component = component - return str(template) + return str(template) # ------------------------------------------------------------------------------- # componentFile # ------------------------------------------------------------------------------- - def componentFile(self, smname: str, namespace: str, component: str, guardFunctions: List[ImplFunc], actionFunctions: List[ImplFunc]) -> str: - template = Template(""" + def componentFile(self, smname: str, namespace: str, component: str, guardFunctions: List[ImplFunc], actionFunctions: List[ImplFunc]) -> str: + template = Template(""" \#include "$(component).hpp" \#include "$(smname).hpp" @@ -110,11 +110,11 @@ def componentFile(self, smname: str, namespace: str, component: str, guardFuncti """) - template.guardFunctions = guardFunctions - template.actionFunctions = actionFunctions - template.smname = smname - template.namespace = namespace - template.component = component + template.guardFunctions = guardFunctions + template.actionFunctions = actionFunctions + template.smname = smname + template.namespace = namespace + template.component = component - return str(template) + return str(template) diff --git a/autocoder/fprime_backend/fprimecoder.py b/autocoder/fprime_backend/fprimecoder.py index 3bc7522..1f223a7 100644 --- a/autocoder/fprime_backend/fprimecoder.py +++ b/autocoder/fprime_backend/fprimecoder.py @@ -42,9 +42,11 @@ class FprimeConfig(BaseModel): # # Print the state-machine header file # ----------------------------------------------------------------------- -def printSmHeader(smname: str, - qmRoot: ElementTreeType, - namespace: str): +def printSmHeader( + smname: str, + qmRoot: ElementTreeType, + namespace: str, + ): hFile = open(smname+".hpp", "w") eventList = [] @@ -61,7 +63,7 @@ def printSmHeader(smname: str, funcList = get_function_signatures(qmRoot, smname) - hFile.write(codeTemplate.fileHeader(smname, stateList, eventList, namespace, funcList )) + hFile.write(codeTemplate.fileHeader(smname, stateList, eventList, namespace, funcList)) # --------------------------------------------------------------------------- @@ -401,7 +403,7 @@ def printEnumFpp(smname: str, # Open the generated files - fileName = smname + ".fppi" + fileName = smname + "_State.fpp" file = open(fileName, "w") print(f'Generating {fileName}') @@ -434,7 +436,8 @@ def printEnumFpp(smname: str, # ----------------------------------------------------------------------- def generateCode(qmRoot: ElementTreeType, noImpl: bool, - namespace: str): + namespace: str, + ): global codeTemplate global unitTestTemplate diff --git a/autocoder/fprime_backend/fprimetemplates.py b/autocoder/fprime_backend/fprimetemplates.py index bdece1e..d587674 100644 --- a/autocoder/fprime_backend/fprimetemplates.py +++ b/autocoder/fprime_backend/fprimetemplates.py @@ -15,21 +15,21 @@ class FprimeTemplate: # ------------------------------------------------------------------------------- # target # ------------------------------------------------------------------------------- - def target(self, targ: str) -> str: + def target(self, targ: str) -> str: - template = Template("""this->state = $(target);""") + template = Template("""this->state = $(target);""") - template.target = targ - return str(template) + template.target = targ + return str(template) # ------------------------------------------------------------------------------- # ifGuard # ------------------------------------------------------------------------------- - def ifGuard(self, smname: str, action: str, args: str) -> str: - if args == "": - template = Template("""if ( parent->$(smname)_$(action)(stateMachineId) ) {""") - else: - template = Template("""if (parent->$(smname)_$(action)(stateMachineId, signal, data) ) {""") + def ifGuard(self, smname: str, action: str, args: str) -> str: + if args == "": + template = Template("""if ( parent->$(smname)_$(action)(stateMachineId) ) {""") + else: + template = Template("""if (parent->$(smname)_$(action)(stateMachineId, signal, data) ) {""") template.smname = smname template.action = action @@ -39,18 +39,18 @@ def ifGuard(self, smname: str, action: str, args: str) -> str: # ------------------------------------------------------------------------------- # guardSignature # ------------------------------------------------------------------------------- - def guardSignature(self, smname: str, action: str, args: str) -> str: - if args == "": - template = Template("""bool $(smname)_$(action)(const FwEnumStoreType stateMachineId)""") - elif args == "e": - template = Template("""bool $(smname)_$(action)( + def guardSignature(self, smname: str, action: str, args: str) -> str: + if args == "": + template = Template("""bool $(smname)_$(action)(const FwEnumStoreType stateMachineId)""") + elif args == "e": + template = Template("""bool $(smname)_$(action)( const FwEnumStoreType stateMachineId, const $(smname)_Interface::$(smname)_Signals signal, const Fw::SmSignalBuffer &data)""") - elif args.isdigit(): - template = Template("""bool $(smname)_$(action)(int arg)""") - else: - assert True, "Unknown args" + elif args.isdigit(): + template = Template("""bool $(smname)_$(action)(int arg)""") + else: + assert True, "Unknown args" template.smname = smname @@ -60,105 +60,105 @@ def guardSignature(self, smname: str, action: str, args: str) -> str: # ------------------------------------------------------------------------------- # guardDef # ------------------------------------------------------------------------------- - def guardDef(self, smname: str, action: str, component: str, args: str, namespace) -> str: - if args == "": - template = Template("""bool $(namespace)::$(component)::$(smname)_$(action)(const FwEnumStoreType stateMachineId)""") - elif args == "e": - template = Template("""bool $(namespace)::$(component)::$(smname)_$(action)( + def guardDef(self, smname: str, action: str, component: str, args: str, namespace) -> str: + if args == "": + template = Template("""bool $(namespace)::$(component)::$(smname)_$(action)(const FwEnumStoreType stateMachineId)""") + elif args == "e": + template = Template("""bool $(namespace)::$(component)::$(smname)_$(action)( const FwEnumStoreType stateMachineId, const $(smname)_Interface::$(smname)_Signals signal, const Fw::SmSignalBuffer &data)""") - elif args.isdigit(): - template = Template("""bool $(namespace)::$(component)::$(smname)_$(action)(int arg)""") - else: - assert True, "Unknown args" + elif args.isdigit(): + template = Template("""bool $(namespace)::$(component)::$(smname)_$(action)(int arg)""") + else: + assert True, "Unknown args" - template.smname = smname - template.namespace = namespace - template.action = action - template.component = component - return str(template) + template.smname = smname + template.namespace = namespace + template.action = action + template.component = component + return str(template) # ------------------------------------------------------------------------------- # action # ------------------------------------------------------------------------------- - def action(self, smname: str, action: str, args: str) -> str: - if args == "": - template = Template("""parent->$(smname)_$(action)(stateMachineId);""") - else: - template = Template("""parent->$(smname)_$(action)(stateMachineId, signal, data);""") + def action(self, smname: str, action: str, args: str) -> str: + if args == "": + template = Template("""parent->$(smname)_$(action)(stateMachineId);""") + else: + template = Template("""parent->$(smname)_$(action)(stateMachineId, signal, data);""") - template.smname = smname - template.action = action - template.args = args - return str(template) + template.smname = smname + template.action = action + template.args = args + return str(template) # ------------------------------------------------------------------------------- # actionSignature # ------------------------------------------------------------------------------- - def actionSignature(self, smname: str, action: str, args: str) -> str: - if args == "": - template = Template("""void $(smname)_$(action)(const FwEnumStoreType stateMachineId)""") - elif args == "e": - template = Template(""" void $(smname)_$(action)( + def actionSignature(self, smname: str, action: str, args: str) -> str: + if args == "": + template = Template("""void $(smname)_$(action)(const FwEnumStoreType stateMachineId)""") + elif args == "e": + template = Template(""" void $(smname)_$(action)( const FwEnumStoreType stateMachineId, const $(smname)_Interface::$(smname)_Signals signal, const Fw::SmSignalBuffer &data)""") - elif args.isdigit(): - template = Template("""void $(smname)_$(action)(int arg)""") - else: - assert True, "Unknown args" + elif args.isdigit(): + template = Template("""void $(smname)_$(action)(int arg)""") + else: + assert True, "Unknown args" - template.smname = smname - template.action = action - return str(template) + template.smname = smname + template.action = action + return str(template) # ------------------------------------------------------------------------------- # actionDef # ------------------------------------------------------------------------------- - def actionDef(self, smname: str, action: str, component: str, args: str, namespace: str) -> str: - if args == "": - template = Template("""void $(namespace)::$(component)::$(smname)_$(action)(const FwEnumStoreType stateMachineId)""") - elif args == "e": - template = Template("""void $(namespace)::$(component)::$(smname)_$(action)( + def actionDef(self, smname: str, action: str, component: str, args: str, namespace: str) -> str: + if args == "": + template = Template("""void $(namespace)::$(component)::$(smname)_$(action)(const FwEnumStoreType stateMachineId)""") + elif args == "e": + template = Template("""void $(namespace)::$(component)::$(smname)_$(action)( const FwEnumStoreType stateMachineId, const $(smname)_Interface::$(smname)_Signals signal, const Fw::SmSignalBuffer &data)""") - elif args.isdigit(): - template = Template("""void $(namespace)::$(component)::$(smname)_$(action)(int arg)""") - else: - assert True, "Unknown args" + elif args.isdigit(): + template = Template("""void $(namespace)::$(component)::$(smname)_$(action)(int arg)""") + else: + assert True, "Unknown args" - template.namespace = namespace - template.smname = smname - template.action = action - template.component = component - return str(template) + template.namespace = namespace + template.smname = smname + template.action = action + template.component = component + return str(template) # ------------------------------------------------------------------------------- # stateTransition # ------------------------------------------------------------------------------- - def stateTransition(self, signal: str, transition: str, smname) -> str: - template = Template(""" + def stateTransition(self, signal: str, transition: str, smname) -> str: + template = Template(""" case $(smname)_Interface::$(smname)_Signals::$(signal): $(transition) break; """) - template.signal = signal - template.transition = transition - template.smname = smname - return str(template) + template.signal = signal + template.transition = transition + template.smname = smname + return str(template) # ------------------------------------------------------------------------------- # fileHeader # ------------------------------------------------------------------------------- - def fileHeader(self, smname: str, stateList: List[str], eventList: List[str], namespace: str, implFunctions: List[str]) -> str: - template = Template(""" + def fileHeader(self, smname: str, stateList: List[str], eventList: List[str], namespace: str, implFunctions: List[str]) -> str: + template = Template(""" // ====================================================================== // \\title $(smname).h // \\author Auto-generated by STARS @@ -198,14 +198,8 @@ class $(smname) { public: $(smname)($(smname)_Interface* parent) : parent(parent) {} - - enum $(smname)_States { -#for $state in $stateList - $state, -#end for - }; - enum $(smname)_States state; + enum $(smname)_State::T state; void init(const FwEnumStoreType stateMachineId); void update( @@ -219,20 +213,19 @@ class $(smname) { #endif """) - template.stateList = stateList - template.eventList = eventList - template.smname = smname - template.namespace = namespace - template.implFunctions = implFunctions - return str(template) - + template.stateList = stateList + template.eventList = eventList + template.smname = smname + template.namespace = namespace + template.implFunctions = implFunctions + return str(template) # ------------------------------------------------------------------------------- # stateMachineInit # ------------------------------------------------------------------------------- - def stateMachineInit(self, smname: str, transition: str, namespace: str) -> str: - template = Template(""" + def stateMachineInit(self, smname: str, transition: str, namespace: str) -> str: + template = Template(""" // ====================================================================== // \\title $(smname).cpp // \\author Auto-generated by STARS @@ -258,17 +251,17 @@ def stateMachineInit(self, smname: str, transition: str, namespace: str) -> str: { switch (this->state) { """) - template.smname = smname - template.transition = transition - template.namespace = namespace - return str(template) + template.smname = smname + template.transition = transition + template.namespace = namespace + return str(template) # ------------------------------------------------------------------------------- # stateMachineState # ------------------------------------------------------------------------------- - def stateMachineState(self, state: str) -> str: - template = Template(""" + def stateMachineState(self, state: str) -> str: + template = Template(""" /** * state $state */ @@ -276,31 +269,31 @@ def stateMachineState(self, state: str) -> str: switch (signal) { """) - template.state = state - return str(template) + template.state = state + return str(template) # ------------------------------------------------------------------------------- # stateMachineBreak # ------------------------------------------------------------------------------- - def stateMachineBreak(self) -> str: - template = Template(""" + def stateMachineBreak(self) -> str: + template = Template(""" default: break; } break; """) - return str(template) + return str(template) # ------------------------------------------------------------------------------- # stateMachineFinalBreak # ------------------------------------------------------------------------------- - def stateMachineFinalBreak(self) -> str: - template = Template(""" + def stateMachineFinalBreak(self) -> str: + template = Template(""" default: FW_ASSERT(0); } } """) - return str(template) + return str(template) \ No newline at end of file diff --git a/models/TestModels/nested_states/NestedState.qm b/models/TestModels/nested_states/NestedState.qm new file mode 100644 index 0000000..a5e76b0 --- /dev/null +++ b/models/TestModels/nested_states/NestedState.qm @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +