1

When I try to match a message in a receive statement I get a "bad node type 44" error message. This happens when the message's type is a typedef. The error message is rather cryptic and doesn't give much insight.

typedef t {
    int i
}
init {
    chan c = [1] of {t}
    t x;
    !(c ?? [eval(x)]) // <--- ERROR
}
tgonzalez89
  • 621
  • 1
  • 6
  • 26

3 Answers3

1

Note: This may, or may not, be a bug in Spin: apparently, the grammar allows using a structure variable as an argument for eval(), but it does not look like this situation is handled correctly (within the extent of my limited understanding). I would encourage you to contact the maintainers of Promela/Spin and submit your model.

Nevertheless, there is a work-around for the issue you reported (see below).


Contrary to what is reported here:

NAME

eval - predefined unary function to turn an expression into a constant.

SYNTAX

eval( any_expr )

The actual promela grammar for EVAL looks a bit different:

receive : varref '?' recv_args      /* normal receive */
    | varref '?' '?' recv_args  /* random receive */
    | varref '?' '<' recv_args '>'  /* poll with side-effect */
    | varref '?' '?' '<' recv_args '>'  /* ditto */

recv_args: recv_arg [ ',' recv_arg ] *  |  recv_arg '(' recv_args ')'

recv_arg : varref | EVAL '(' varref ')' | [ '-' ] const

varref  : name [ '[' any_expr ']' ] [ '.' varref ]

Take-aways:

  • apparently, eval is allowed to take as argument a structure (because name may be the identifier of a typedef structure [?])

  • eval can also take as argument a structure field

  • when one aims to apply message filtering to an entire structure, it can expand the relevant fields of the structure itself


Example:

typedef Message {
    int _filter;
    int _value;
}

chan inout = [10] of { Message }


active proctype Producer()
{
    Message msg;

    byte cc = 0;
    for (cc: 1 .. 10) {
        int id;
        select(id: 0..1);
        msg._filter = id;
        msg._value = cc;
        atomic {
            printf("Sending: [%d|%d]\n", msg._filter, msg._value);
            inout!msg;
        }
    }

    printf("Sender Stops.\n");
}

active proctype Consumer()
{
    Message msg;
    msg._filter = 0;

    bool ignored;
    do
        :: atomic {
            inout??[eval(msg._filter)] ->
                inout??eval(msg._filter), msg._value;
                printf("Received: [%d|%d]\n", msg._filter, msg._value);
            }
        :: timeout -> break;
    od;

    printf("Consumer Stops.\n");
}

simulation output:

~$ spin test.pml 
      Sending: [1|1]
      Sending: [0|2]
          Received: [0|2]
      Sending: [0|3]
          Received: [0|3]
      Sending: [0|4]
          Received: [0|4]
      Sending: [0|5]
          Received: [0|5]
      Sending: [1|6]
      Sending: [0|7]
          Received: [0|7]
      Sending: [0|8]
          Received: [0|8]
      Sending: [1|9]
      Sending: [1|10]
      Sender Stops.
      timeout
          Consumer Stops.
2 processes created

Generating a verifier does not result in a compilation error:

~$ spin -a test.pml 
~$ gcc -o run pan.c

Note: when using both message filtering and message polling (like in your model sample), the fields of the structure that are subject to message filtering should be placed at the beginning of it.

Patrick Trentin
  • 7,126
  • 3
  • 23
  • 40
  • 1
    Although the issue was because of bug in Spin, this answer still provides value because 1) works around the bug in the meantime and 2) shows that you can use part of the struct as the filter and that can be useful. – tgonzalez89 Dec 11 '19 at 15:06
1

Apparently it's a bug, link to github issue: https://github.com/nimble-code/Spin/issues/17

Update: Bug is now fixed.

Update 2: Bug was actually partially fixed, there are still some edge cases where it's behaving weirdly.

Update 3: As far as I can tell bug looks fixed now. The only downside is that it seems that now there is a strict restriction on what you put in the receive args. They have to match exactly the types declared in the channel. No more partial matches or unrolling struct fields.

tgonzalez89
  • 621
  • 1
  • 6
  • 26
  • 1
    You should probably set this answer as the **accepted** one. The other post does not really answer the question so you may consider to either (i) incorporate its content in this answer with an edit or (ii) delete it altogether. Please take a look at the [tour](https://stackoverflow.com/tour) if you haven't already. – Patrick Trentin Dec 11 '19 at 02:00
0

My guess is that this error is related to the restrictions that structured types have. One restriction is that they can't be handled as a unit, to assign or compare them one must do it one field at a time.

For example, if one writes: x == y, where x and y are variables of a typedef type, the following error is shown: Error: incomplete structure ref 'x' saw 'operator: =='

Under the hood, when trying to compare the channel's queue to match the eval something is triggered that indicates that the comparison can't be done and then raises the "bad node type" message.

tgonzalez89
  • 621
  • 1
  • 6
  • 26