尝试匹配接收语句中的 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 现在已经修复了。唯一的缺点是现在似乎对您在接收参数中放置的内容有严格的限制。它们必须与通道中声明的类型完全匹配。不再有部分匹配或展开结构字段。
当我尝试匹配接收语句中的消息时,我收到 "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 现在已经修复了。唯一的缺点是现在似乎对您在接收参数中放置的内容有严格的限制。它们必须与通道中声明的类型完全匹配。不再有部分匹配或展开结构字段。