From 01542e56f589b79b14fd08e0a2c652194b94085f Mon Sep 17 00:00:00 2001 From: Marius Bozga <Marius.Bozga@univ-grenoble-alpes.fr> Date: Wed, 17 Nov 2021 16:15:40 +0100 Subject: [PATCH] fix state name binding in hierarchical / concurrent states --- src/model/action.C | 51 ++++++---------------------------------------- src/model/state.C | 31 ++++++++++++++++++++++++++++ src/model/state.h | 3 ++- 3 files changed, 39 insertions(+), 46 deletions(-) diff --git a/src/model/action.C b/src/model/action.C index ea18e5b..c6a0f14 100644 --- a/src/model/action.C +++ b/src/model/action.C @@ -874,53 +874,14 @@ void IfNextstateAction::PreCompile() { int ok = 1; - /* - * - * state name ~ literal_1 @ literal_2 @ ... @ literal_n - * - * implemented too early ;-) - - IfState* base[3] = {NULL, NULL, NULL}; - - base[0] = (IfState*) CONTEXT.Top(-3); - base[1] = ((IfProcessEntity*) CONTEXT[1])->GetEntry(); - if (base[0] == base[1]) base[1] = NULL; - - for(int i = 0; base[i]; i++) { - - IfState* current = base[i]; - for(int k = 0, j;; ) { - - char literal[256] = ""; - for(j = 0; m_pStateName[k] != '\0' && - m_pStateName[k] != '@'; j++, k++) - literal[j] = m_pStateName[k]; - literal[j] = '\0'; - - if (m_pStateName[k] == '@') - k++; - - current = current->GetStates()->Find(literal); - if (current == NULL) - break; - - if (m_pStateName[k] == '\0') { - m_pState = current; - break; - } - } - - if (m_pState) + IfState* context_state = NULL; + for(int i = CONTEXT.GetCount() - 1; i >= 0; i--) + if (CONTEXT[i]->IsState()) { + context_state = (IfState*) CONTEXT[i]; break; - } - - * - * - */ + } - IfState* top = ((IfProcessEntity*) CONTEXT[1])->GetEntry(); - - m_pState = top->Find(m_pStateName); + m_pState = context_state->FindVisible(m_pStateName); ok &= m_pState != NULL; diff --git a/src/model/state.C b/src/model/state.C index 203541d..007ef79 100644 --- a/src/model/state.C +++ b/src/model/state.C @@ -96,6 +96,37 @@ IfState* IfState::Find(const char* Name) const { return state; } +IfState* IfState::FindVisibleRec(const char* Name) const { + IfState* state = NULL; + if (!strcmp(m_pName, Name)) + state = (IfState*) this; + if (!state && !IsConcurrent()) + for(int i = 0; i < m_pStates->GetCount() && !state; i++) + state = m_pStates->GetAt(i)->FindVisibleRec(Name); + return state; +} + +IfState* IfState::FindVisible(const char* Name) const { + IfState* state = NULL; + if (!strcmp(m_pName, Name)) + state = (IfState*) this; + if (!state && m_pParent != NULL && !m_pParent->IsConcurrent()) + for(int i = 0; i < m_pParent->GetStates()->GetCount() && !state; i++) { + IfState* brother = m_pParent->GetStates()->GetAt(i); + if (!strcmp(brother->GetName(), Name)) + state = brother; + } + if (!state) + state = this->FindVisibleRec(Name); + if (!state && m_pParent != NULL && !m_pParent->IsConcurrent()) { + IfState* ancestor = m_pParent; + while (ancestor->m_pParent != NULL && !ancestor->m_pParent->IsConcurrent()) + ancestor = ancestor->m_pParent; + state = ancestor->FindVisibleRec(Name); + } + return state; +} + void IfState::Dump(FILE* file) const { fprintf(file, "%sstate %s%s%s%s%s%s;\n", indent(DEPTH), m_pName, IsStart() ? " #start " : "", diff --git a/src/model/state.h b/src/model/state.h index 893060c..755f997 100644 --- a/src/model/state.h +++ b/src/model/state.h @@ -79,7 +79,8 @@ class IfState : public IfObject { inline IfAutomatonEntity* GetProcess() const { return m_pProcess; } IfState* Find(const char*) const; - + IfState* FindVisible(const char*) const; + IfState* FindVisibleRec(const char*) const; virtual const char* GetClass() const { return "state"; } -- GitLab