Using arguments in events

Hi, in the example I see events defined as this:

  in void turnon();
  in void turnoff();

Is it possible to define events this way?

in void turn(bool on);

I have a serial port which accepts commands. The commands are composed by the command id and the frame with the payload. If there are 20 commands I do not want to define 20 in void commandX(); events. I want to define a single command(subint X) event which passes the X to the subfunction which processes the command.

F.I:
on.receive(cmd): {state = State.ProcessCmd; commandToProcess = cmd;}
or:
on.receive(cmd): {state = State.ProcessCmd; processCmd(cmd);}

In some other cases I would like to use the argument to take a decision in the state machine, like
[cmd == 1] on.receive(cmd): {state = State.ProcessCmd1;}
[cmd == 2] on.receive(cmd): {state = State.ProcessCmd2;}
[otherwise] on.receive(cmd): {state = State.Idle;}

I’ve been looking at the examples to see how the syntax could be supporting this, and trying some guessings, but with no luck.

Maybe I am not really catching the point and I have to switch-on some concepts in my mind to try the good approach.

Thanks. Regards.

Tx.

For instance, this is the best I could arrive:

extern int $int$;
interface ISeriallink
{

  in void request(int cmd);
  out void response(int cmd);

  behaviour {
    on request: {}
  }
}
...
component MyController
{
  provides ISeriallink serialink;
  behaviour {
    enum State {Idle, AcceptingCommand, ServingCommand1, ServingCommand2};
    State state = State.Idle;
    int cmdToProcess = $0$;
    [state.Idle] {
      on serialink.request(cmd):{
        state = State.AcceptingCommand; cmdToProcess = cmd;}
    }
    [state.AcceptingCommand] {
      [cmdToProcess == $1$] on serialink.request(cmd):{state = State.ServingCommand1;}
      [cmdToProcess == $2$] on serialink.request(cmd):{state = State.ServingCommand2;}
    }
  }
}

Then, trying to generate an state machine I receive:


.. 
In dzn/vm/evaluate.scm:
    63:27  2 (_ (("state" . (enum-literal** (scope.name-node* ("S…))) …)
In oop/goops.scm:
  1567:11  1 (cache-miss (("state" . (enum-literal** (scope.name-…))) …)
   1585:2  0 (_ _ _)

oop/goops.scm:1585:2: No applicable method for #<<generic> eval-expression (3)> in call (eval-expression (("state" . (enum-literal** (scope.name-node* ("State")) "AcceptingCommand"))) #f)

Regards.

Hi,

In Dezyne there is (still) a distinction between state types and other data types: see
extern data type
Currently event parameter lists only accept extern data types: see events

In the (near) future we aim to add data contracts that will allow using arbitrary data as state variables, etc.

In the meantime I would advise todo something like:
extern boolean $bool$;
in void turn(boolean on);

in bool inspect(boolean on); // a function to map the extern boolean to the Dezyne bool.
Note this function must be part of an interface and the implemention of this interface cannot be done in Dezyne, the interface must be implemented in the target language.

I hope this helps,
regtur

I have added issue: 64 to our bug tracking list

Hi, firstable thanks a lot for your kind and fast support.

I honestly don’t know what to do with the answer. Probably I am very newbie (I discovered Dezyne yesterday) and I am missing some concepts.

So, my guessings are:

  1. The issue opened means the [cmdToProcess == $1$] was the correct way of achieving it, but a bug is preventing it to work?
  2. Will I be able to apply the solution given for booleans to integers? This means mapping the ints to subints and then implementing the inspect function in the interface?
  3. The sentence " the implemention of this interface cannot be done in Dezyne" means that if I get the system correctly “compiling”, Dezyne will not be able to simulate or validate it?

Regarding my guessing 2:

extern int $int$;
interface ISeriallink
{
subint intcommand {0..2};

  in void request(int cmd);
  out void response(int cmd);
  in intcommand inspect(int number);

gives the same error of my previous post:
oop/goops.scm:1585:2: No applicable method for #<<generic> eval-expression (3)> in call (eval-expression (("state" . (enum-literal** (scope.name-node* ("State")) "AcceptingCommand"))) #f)

Thanks again. Regards…
Tx.

Hi txinto,

  1. Currently we do not support this syntax [cmdToProcess == $1$].
    The way to achieve this, is to map the extern value $1$ via an explicit interface to a Dezyne supported state type, i.e. bool, enum or subint. An example of such an interface is this:
extern int $int$;
interface ICommand
{
  subint I {0..2};
  enum E {FOO,BAR,BAZ};
  in I iconvert(int cmd);
  in E econvert(int cmd);
  behavior
  {
    on iconvert: reply(0);
    on iconvert: reply(1);
    on iconvert: reply(2);
    on econvert: reply(enumcommand.FOO);
    on econvert: reply(enumcommand.BAR);
    on econvert: reply(enumcommand.BAZ);
  }

  component Command
  {
      provides ICommand command;
      // a foreign component does not define an implementation in Dezyne,
      // i.e. neither a behavior block, nor a system block
  }

Now you must implement this interface in your target language, where you map the “real” int to the Dezyne subint I, or Dezyne enum E. You can use a foreign component for this purpose. The code generator will generate a base class for the foreign component, and you can implement the functions yourself by inheriting from that base class, see foreign and integration.

  1. Sadly no, it should be flagged as a syntactical error. Because this construct is not supported you get a stacktrace. Therefore I have added this to our bug tracking list.

  2. It literally means that the language makes a distinction between extern data types and its “own” state types. Therefore you cannot convert a C/C++ int to some Dezyne state type in Dezyne itself. You must do this outside Dezyne in C/C++. But if you use an interface to define this mapping, you can perform verification and simulation in Dezyne.

I can share a full compiling and running example of what you need. Let me know if that would help.

Best regards,
regtur