the sequence of exit actions are not executed correctly #935

Open
vahdat-ab opened this Issue Dec 16, 2016 · 9 comments

Projects

None yet

3 participants

@vahdat-ab
Member

Here is somehow a complete example shows how exit must be treated.
@TimLethbridge @opeyemiAdesina I wonder if you guys can check if the semantics related to execution order is correct or not?

class X{
  sm{
    on{
      exit /{exit_on_execute();}
      e1-> off;
      e2-> on;
      s1{
        exit /{exit_s1_execute();}
        e3-> s2;
        e4-> s1;
        e5-> on;
        e6-> off;
        m1{
          exit /{exit_m1_execute();}
          e7-> m2;
          e8-> m1;
          e9-> s1;
          e10->s2;
          e11->on;
          e12->off;
        } 
        m2{} 
      }
      s2{}
    }
    off{}
  }
  void exit_on_execute(){System.out.println("exited on");}
  void exit_s1_execute(){System.out.println("exited s1");}
  void exit_m1_execute(){System.out.println("exited m1");}
}

The following part shows the execution oders of exits for each event. It shows which is supported currently by Umple.

//e1-> off; : exit_on_execute(); //correct
//e2-> on; : exit_on_execute(); //correct
//e3-> s2; : exit_s1_execute(); //correct
//e4-> s1; : exit_s1_execute(); //correct
//e5-> on; : exit_s1_execute(); -> exit_on_execute(); //Not correct
//e6-> off; : exit_s1_execute(); -> exit_on_execute(); //Not correct
//e7-> m2; : exit_m1_execute(); //correct
//e8-> m1; : exit_m1_execute(); //correct
//e9-> s1; : exit_m1_execute(); ->exit_s1_execute(); //Not correct
//e10->s2; : exit_m1_execute(); ->exit_s1_execute(); //Not correct
//e11->on; : exit_m1_execute(); -> exit_s1_execute(); -> exit_on_execute(); //Not correct
//e12->off; : exit_m1_execute(); -> exit_s1_execute(); -> exit_on_execute(); //Not correct

@vahdat-ab
Member

@opeyemiAdesina
The execution order specified above is logical. it's just for explanation. for e1 it should first exit_on_execute(); and then if there is an entry it must be executed. The generated code doesn't have issues with entry actions. That's the reason I didn't specify it there.

@vahdat-ab
Member

My comments regarding //correct and //Not correct meant to say that Umple supports it or not.
when I say it's correct, it means in the generated code I saw the order and it's fine. Otherwise, generated code doesn't satisfy it.

@TimLethbridge
Member

I had put some answers in #766

I am copying here
Here's my take on Vahdat's comments about 'Not correct'

//e5-> on; : exit_s1_execute(); -> exit_on_execute(); //Not correct
It needs to do exit_m1_execute if it is in m1. But if it is in m2 it doesn't
So yes, incorrect, depending on the starting state.

//e6-> off; : exit_s1_execute(); -> exit_on_execute(); //Not correct
Same comment as above,

//e9-> s1; : exit_m1_execute(); ->exit_s1_execute(); //Not correct
I think this is actually correct.

//e10->s2; : exit_m1_execute(); ->exit_s1_execute(); //Not correct
I think this is actually correct

//e11->on; : exit_m1_execute(); -> exit_s1_execute(); -> exit_on_execute(); //Not correct
Seems correct to me

//e12->off; : exit_m1_execute(); -> exit_s1_execute(); -> exit_on_execute(); //Not correct
Seems correct to me

@jblang94 jblang94 self-assigned this Feb 4, 2017
@jblang94
Contributor
jblang94 commented Feb 11, 2017 edited

@vahdat-ab @TimLethbridge

I read your comments prior to examining the generated code. Below are some questions I have regarding the execution order, and my current understanding. I am wondering if someone could please clarify?

Transitions defined in state "on"

  1. e1 -> off
    Current Execution: exit_on_execute();
    Correct: We are exiting state "on" to go to state "off".

  2. e2 -> on
    Current Execution: exit_on_execute();
    Why is "exit_on_execute()" called even though the transition is not taking us out of state "on"?

Transitions defined in state "s1"

Overall question regarding: e3, e4, e5, e6
For all of these cases, there is no check if "s1" is in state "m1". If "s1" happens to be in state "m1" at the time, shouldn't the execution be exit_m1_execute() and then exit_s1_execute()? Tim noted the same observation above in his comment.

  1. e3 -> s2
    Current Execution: exit_s1_execute();
    Correct (asides from checking for "m1"): We are exiting state "s1" to go to state "s2". "s2" is a state within "on" so we do not call exit_on_execute().

  2. e4 -> s1
    Current Execution: exit_s1_execute();
    Why is "exit_s1_execute()" called even though the transition is not taking us out of state "s1"?

  3. e5 -> on
    Current Execution: exit_s1_execute()
    Correct (asides from checking for "m1"): exit_on_execute() would not be called because "s1" is a state defined in "on", and we are not exiting "on".

  4. e6 -> off
    Current Execution: exit_s1_execute()
    Incorrect: We are missing a call to exit_on_execute(). In addition to exiting state "s1", we are also exiting state "on".

Transitions defined in state "m1"

  1. e7 -> m2
    Current Execution: exit_m1_execute()
    Correct: We are exiting "m1" to go to state "m2". "m2" is a state defined in "s1".

  2. e8 -> m1
    Current Execution: exit_m1_execute()
    Why is "exit_m1_execute()" called even though the transition is not taking us out of state "m1"?

  3. e9 -> s1
    Current Execution: exit_m1_execute()
    Correct: We are exiting "m1" and not exiting state "s1", hence exit_s1_execute() is not called.

  4. e10 -> s2
    Current Execution: exit_m1_execute()
    Incorrect: We are exiting "s1" as well. The execution should be exit_m1_execute() -> exit_s1_execute().

  5. e11 -> on
    Current Execution: exit_m1_execute()
    Incorrect: Same comment as e10

  6. e12 -> off
    Current Execution: exit_m1_execute()
    Incorrect: We are exiting states "s1", and "on" as well. The execution should be exit_m1_execute() -> exit_s1_execute() -> exit_on_execute().

@jblang94
Contributor

I noticed today that the PHP and Java code generation differ for some events. For instance, in e2, the PHP code does not call "$this->exitSm()", which in turn calls "exit_on_execute()". In the Java code, e2 calls "exitSm()" which in turn calls "exit_on_execute()".

For e1, both PHP and Java. Is PHP supposed to differ from Java for generated event methods?

Java Generated Code for e2
public boolean e2()
  {
    boolean wasEventProcessed = false;
    
    Sm aSm = sm;
    switch (aSm)
    {
      case on:
        exitSm();
        setSm(Sm.on);
        wasEventProcessed = true;
        break;
      default:
        // Other states do respond to this event
    }

    return wasEventProcessed;
  }
PHP Generated Code for e2
public function e2()
  {
    $wasEventProcessed = false;
    
    $aSm = $this->sm;
    if ($aSm == self::$SmOn)
    {
      $this->setSm(self::$SmOn);
      $wasEventProcessed = true;
    }
    return $wasEventProcessed;
  }
@vahdat-ab
Member

e2 -> on
Current Execution: exit_on_execute();
Why is "exit_on_execute()" called even though the transition is not taking us out of state "on"?

There are two concepts related to this situation. They are called internal and external transitions. In internal transitions, exit actions are executed, but in the external transitions, they don't. Umple accepted just the external transitions. That's the reason we run that method.

shouldn't the execution be exit_m1_execute() and then exit_s1_execute()? Tim noted the same observation above in his comment.

Correct.

e4 -> s1
Current Execution: exit_s1_execute();
Why is "exit_s1_execute()" called even though the transition is not taking us out of state "s1"?

The reason was described above.

e5 -> on
Current Execution: exit_s1_execute()
Correct (asides from checking for "m1"): exit_on_execute() would not be called because "s1" is a state defined in "on", and we are not exiting "on".

No, asides from checking for m1, this sequence must be executed exit_s1_execute(); -> exit_on_execute()

e8 -> m1
Current Execution: exit_m1_execute()
Why is "exit_m1_execute()" called even though the transition is not taking us out of state "m1"?

The reason was described above.

e9 -> s1
Current Execution: exit_m1_execute()
Correct: We are exiting "m1" and not exiting state "s1", hence exit_s1_execute() is not called.

We need exit_s1_execute() because e9 is an external transition.

e11 -> on
Current Execution: exit_m1_execute()
Incorrect: Same comment as e10

The sequence is exit_m1_execute(); -> exit_s1_execute(); -> exit_on_execute()

All of the transitions in Umple must be treated as external transitions. Most of your comments were about internal transitions.

@vahdat-ab
Member

I noticed today that the PHP and Java code generation differ for some events. For instance, in e2, the PHP code does not call "$this->exitSm()", which in turn calls "exit_on_execute()". In the Java code, e2 calls "exitSm()" which in turn calls "exit_on_execute()".

The most valid semantics is the one you see in Java. PHP code generator might not be up to date. The way PHP is dealing might be different, but the sequences of actions must be the same for all target languages.

@jblang94
Contributor

@vahdat-ab Thank you for your feedback. I have a couple of follow up clarifications/questions below.

In internal transitions, exit actions are executed, but in the external transitions, they don't.

I think you meant that "In external transitions, exit actions are executed, but in the internal transitions, they don't." ?

Also for e1 and e2, I think we should also check if "on" is in state "s1", and if "s1" is in state "m1". Potentially, for both of these transitions, the execution could be
exit_m1_execute() -> exit_s1_execute() -> exit_on_execute()
Is this correct? I made this statement based on my understanding of external transitions, and from following the logic for e3 to e6.

My plan now is to first tackle the Java code generation. I believe my changes will be going in UmpleToJava's "state_machine_Event.ump". After getting the Java code generation to work, I will then transfer the fix into UmpleToPHP's "state_machine_Event.ump".

@vahdat-ab
Member

@jblang94

I think you meant that "In external transitions, exit actions are executed, but in the internal transitions, they don't." ?

Yes. my bad.

Is this correct? I made this statement based on my understanding of external transitions, and from following the logic for e3 to e6.

Yes. This is called hierarchical state. It means it doesn't matter in which internal state the system is, once an event comes in the top state, the internal states must be left. This is also applied to parallel regions as well.

My plan now is to first tackle the Java code generation.

Yes. Work on Java

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment