尝试匹配接收语句中的 typedef 值会导致 "bad node type 44" 错误消息

Trying to match to a typedef value in a receive statement causes "bad node type 44" error message

当我尝试匹配接收语句中的消息时,我收到 "bad node type 44" 错误消息。当消息的类型是 typedef 时会发生这种情况。错误消息相当含糊,并没有提供太多信息。

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

我猜这个错误与结构化类型的限制有关。一个限制是它们不能作为一个单元来处理,要分配或比较它们必须一次一个字段进行。

例如,如果写入:x == y,其中 x 和 y 是 typedef 类型的变量,则会显示以下错误:Error: incomplete structure ref 'x' saw 'operator: =='

在后台,当尝试比较通道的队列以匹配 eval 时,会触发一些指示比较无法完成的东西,然后引发 "bad node type" 消息。

注意: 这可能是也可能不是 Spin 中的错误:显然,语法允许使用结构变量作为eval()的一个论据,但看起来这种情况并没有得到正确的处理(在我有限的理解范围内)。我鼓励您联系 Promela/Spin 的维护者并提交您的模型。

不过,对于您报告的问题 (见下文)

有一个解决方法

与报道相反here

NAME

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

SYNTAX

eval( any_expr )

EVAL 的实际 promela grammar 看起来有点不同:

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 ]

外卖:

  • 显然,eval 允许将 结构 作为参数(因为 name可能是typedef结构的标识符[?])

  • eval 也可以将 结构字段

  • 作为参数
  • 当一个人打算将消息过滤应用于整个结构时,它可以扩展结构本身


示例:

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");
}

模拟输出:

~$ 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

生成验证器不会导致编译错误:

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

注意: 同时使用 消息过滤 消息轮询 (就像在您的模型示例中一样),受消息过滤影响的结构字段应该放在它的开头。

显然这是一个错误,link 到 github 问题:https://github.com/nimble-code/Spin/issues/17

更新:错误现已修复。

更新 2:Bug 实际上已部分修复,但仍然存在一些异常行为的边缘情况。

更新 3:据我所知,bug 现在已经修复了。唯一的缺点是现在似乎对您在接收参数中放置的内容有严格的限制。它们必须与通道中声明的类型完全匹配。不再有部分匹配或展开结构字段。