本节详细说明了模块实例化的几个方面:
实例化本质上是一种代换,通过代换待实例化模块中的符号,最终得到的表达式只包含
T
L
A
+
TLA^+
T L A + 的内建运算符和当前模块定义的常量和参数;
也可以将实例作为入参,这样只需要一条实例化定义语句即可;
一条
INSTANCE
\text{INSTANCE}
INSTANCE 语句必须对待实例化模块的每个参数都有代换。如果有些参数
p
p
p 没有显式的代换,那么必然有一个隐式的代换
p
←
p
p \leftarrow p
p ← p ;
只需要模块的一个实例时,可以不对实例重命名,如果有代换,则必须在参数的声明或定义的范围内定义
INSTANCE
\text{INSTANCE}
INSTANCE 语句;
在实际中除了用于隐藏变量这种习惯用法外,其实很少用到
INSTANCE
\text{INSTANCE}
INSTANCE 语句。所以,大多数读者可以跳过这一部分,直接翻到第4.3节。
4.2.1 实例化是一种代换(Instantiation Is Substitution)
考虑第30页
C
h
a
n
n
e
l
Channel
C h a n n e l 模块中的
N
e
x
t
Next
N e x t 的定义,我们可以将定义中的符号用该符号的定义来代替。例如,我们可以通过展开
S
e
n
d
Send
S e n d 的定义来消除表达式
S
e
n
d
(
d
)
Send(d)
S e n d ( d ) ,这个过程可以不断重复。表达式
1
−
@
1-@
1 − @ 中出现的“
−
-
− ”(通过展开
S
e
n
d
Send
S e n d 的定义获得)可以通过使用
N
a
t
u
r
a
l
s
Naturals
N a t u r a l s 模块中的“
−
-
− ”定义来消除,重复这种方式,我们最终获得
N
e
x
t
Next
N e x t 的定义,它只包含
T
L
A
+
TLA^+
T L A + 的内建运算符和
C
h
a
n
n
e
l
Channel
C h a n n e l 模块的参数
D
a
t
a
Data
D a t a 和
c
h
a
n
chan
c h a n 。我们认为这是
C
h
a
n
n
e
l
Channel
C h a n n e l 模块
N
e
x
t
Next
N e x t 的“真正”定义。
I
n
C
h
a
n
≜
INSTANCE
C
h
a
n
n
e
l
WITH
D
a
t
a
←
M
e
s
s
a
g
e
,
c
h
a
n
←
i
n
InChan \triangleq \text{INSTANCE }Channel \text{ WITH } Data \leftarrow Message,chan \leftarrow in
I n C h a n ≜ INSTANCE C h a n n e l WITH D a t a ← M e s s a g e , c h a n ← i n
上述
I
n
n
e
r
F
I
F
O
InnerFIFO
I n n e r F I F O 模块中定义的
I
n
C
h
a
n
!
N
e
x
t
InChan!Next
I n C h a n ! N e x t 是在
N
e
x
t
Next
N e x t 的“真正”定义中用
M
e
s
s
a
g
e
Message
M e s s a g e 代换
D
a
t
a
Data
D a t a ,
i
n
in
i n 代换
c
h
a
n
chan
c h a n 之后得到的公式。这样定义的
I
n
C
h
a
n
!
N
e
x
t
InChan!Next
I n C h a n ! N e x t 只有
T
L
A
+
TLA^+
T L A + 的内置运算符和模块
I
n
n
e
r
F
I
F
O
InnerFIFO
I n n e r F I F O 的参数
M
e
s
s
a
g
e
Message
M e s s a g e 和
i
n
in
i n 。
让我们考虑一条任意的
INSTANCE
\text{INSTANCE}
INSTANCE 语句:
I
M
≜
INSTANCE
M
WITH
p
1
←
e
1
,
⋯
,
p
n
←
e
n
IM \triangleq \text{INSTANCE } M \text{ WITH }p_{1} \leftarrow e_{1},\cdots,p_{n} \leftarrow e_{n}
I M ≜ INSTANCE M WITH p 1 ← e 1 , ⋯ , p n ← e n
设
Σ
\Sigma
Σ 为模块
M
M
M 中定义的符号,设
d
d
d 为其“真实”定义。
INSTANCE
\text{INSTANCE}
INSTANCE 语句定义
I
M
!
Σ
IM!\Sigma
I M ! Σ 是通过对任一
i
i
i ,将
d
d
d 中的
p
i
p_{i}
p i 用
e
i
e_{i}
e i 替换得到表达式。
I
M
!
Σ
IM!\Sigma
I M ! Σ 的定义必须只包含当前模块的参数(已声明的常量和变量),而不包含模块
M
M
M 的参数。因此,
p
i
p_{i}
p i 必须包含模块
M
M
M 的所有参数,
e
i
e_{i}
e i 必须是在当前模块中有意义的表达式。
4.2.2 参数化实例化(Parametrized Instantiation)
FIFO规约使用了
C
h
a
n
n
e
l
Channel
C h a n n e l 模块的两个实例,一个用
i
n
in
i n 代换
c
h
a
n
chan
c h a n ,另一个用
o
u
t
out
o u t 代换
c
h
a
n
chan
c h a n 。我们也可以使用一个单一的参数化实例,如:
C
h
a
n
(
c
h
)
≜
INSTANCE
C
h
a
n
n
e
l
WITH
D
a
t
a
←
M
e
s
s
a
g
e
,
c
h
a
n
←
c
h
Chan(ch) \triangleq \text{INSTANCE }Channel \text{ WITH } Data \leftarrow Message,chan \leftarrow ch
C h a n ( c h ) ≜ INSTANCE C h a n n e l WITH D a t a ← M e s s a g e , c h a n ← c h
对于定义在
C
h
a
n
n
e
l
Channel
C h a n n e l 模块中的任意符号
Σ
\Sigma
Σ 和任意表达式
e
x
p
exp
e x p ,
C
h
a
n
(
e
x
p
)
!
Σ
Chan(exp)!\Sigma
C h a n ( e x p ) ! Σ 等价于在公式
Σ
\Sigma
Σ 中用
M
e
s
s
a
g
e
Message
M e s s a g e 代换
D
a
t
a
Data
D a t a ,用
e
x
p
exp
e x p 代换
c
h
a
n
chan
c h a n 。在通道
i
n
in
i n 上的动作可以被记作
C
h
a
n
(
i
n
)
!
R
c
v
Chan(in)!Rcv
C h a n ( i n ) ! R c v ,
S
e
n
d
(
m
s
g
)
Send(msg)
S e n d ( m s g ) 在
o
u
t
out
o u t 通道上也可以记作
C
h
a
n
(
o
u
t
)
!
S
e
n
d
(
m
s
g
)
Chan(out)!Send(msg)
C h a n ( o u t ) ! S e n d ( m s g ) 。
上述实例化定义了
C
h
a
n
!
S
e
n
d
Chan!Send
C h a n ! S e n d 为有两个入参的运算符。用
C
h
a
n
(
o
u
t
)
!
S
e
n
d
(
m
s
g
)
Chan(out)!Send(msg)
C h a n ( o u t ) ! S e n d ( m s g ) 取代
C
h
a
n
!
S
e
n
d
(
o
u
t
,
m
s
g
)
Chan!Send(out,msg)
C h a n ! S e n d ( o u t , m s g ) 只是语法的一种特性,它看起来和中缀运算符的语法一样奇怪。(中缀运算符要求我们写
a
+
b
a + b
a + b 而不是
+
(
a
,
b
)
+(a,b)
+ ( a , b ) 。)
参数化实例化仅在
T
L
A
+
TLA^+
T L A + 语言中用于变量隐藏,在后面的第4.3节中有描述。你可以在不了解它的情况下使用它,不了解任何有关参数化实例化的知识也没关系。
扫描二维码关注公众号,回复:
8907265 查看本文章
4.2.3 隐式代换(Implicit Subsititutions)
因为我们之前在异步
C
h
a
n
n
e
l
Channel
C h a n n e l 规约中的使用了命名
D
a
t
a
Data
D a t a ,在FIFO规约中使用
M
e
s
s
a
g
e
Message
M e s s a g e 作为传输数值集合的名称就有点奇怪了,假设我们使用
D
a
t
a
Data
D a t a 代代替
M
e
s
s
a
g
e
Message
M e s s a g e 作为
I
n
n
e
r
F
I
F
O
InnerFIFO
I n n e r F I F O 模块的常量参数,第一条实例化语句应该是:
I
n
C
h
a
n
≜
INSTANCE
C
h
a
n
n
e
l
WITH
D
a
t
a
←
D
a
t
a
,
c
h
a
n
←
i
n
InChan \triangleq \text{INSTANCE }Channel \text{ WITH } Data \leftarrow Data,chan \leftarrow in
I n C h a n ≜ INSTANCE C h a n n e l WITH D a t a ← D a t a , c h a n ← i n
D
a
t
a
←
D
a
t
a
Data \leftarrow Data
D a t a ← D a t a 代换表示用当前模块的表达式
D
a
t
a
Data
D a t a 代换实例化
C
h
a
n
n
e
l
Channel
C h a n n e l 模块的常量参数
D
a
t
a
Data
D a t a 。
T
L
A
+
TLA^+
T L A + 允许我们删除任何形式的代换
Σ
←
Σ
\Sigma \leftarrow \Sigma
Σ ← Σ 。因此,上面的表述可以写成
I
n
C
h
a
n
≜
INSTANCE
C
h
a
n
n
e
l
WITH
c
h
a
n
←
i
n
InChan \triangleq \text{INSTANCE }Channel \text{ WITH } chan \leftarrow in
I n C h a n ≜ INSTANCE C h a n n e l WITH c h a n ← i n
我们知道存在一个隐含的
D
a
t
a
←
D
a
t
a
Data \leftarrow Data
D a t a ← D a t a 代换是因为一条
INSTANCE
\text{INSTANCE}
INSTANCE 语句必须对实例化模块的每个参数都有代换。如果有些参数
p
p
p 没有显式的代换,那么必然有一个隐式的代换
p
←
p
p \leftarrow p
p ← p 。这意味着
INSTANCE
\text{INSTANCE}
INSTANCE 声明必须在符号
p
p
p 的声明或者定义的范围内。
用隐式代换进行实例化操作是比较常见的。通常,每个参数都有一个隐式代换,在这种情况下,显式代换列表是空的,
WITH
\text{WITH}
WITH 语句可以被省略。
4.2.4 无重命名的实例化(Instantiation Without Renaming)
到目前为止,我们使用的所有实例化都与重命名有关。例如,
C
h
a
n
n
e
l
Channel
C h a n n e l 模块的第一条实例化语句将定义的符号
S
e
n
d
Send
S e n d 重命名为
I
n
C
h
a
n
!
S
e
n
d
InChan!Send
I n C h a n ! S e n d 。如果要使用模块的多个实例或单个参数化实例,则需要使用这种重命名。模块
I
n
n
e
r
F
I
F
O
InnerFIFO
I n n e r F I F O 中的
I
n
C
h
a
n
!
I
n
i
t
InChan!Init
I n C h a n ! I n i t 和
O
u
t
C
h
a
n
!
I
n
i
t
OutChan!Init
O u t C h a n ! I n i t 是不同的公式,它们需要不同的命名。
有时我们只需要模块的一个实例。例如,假设我们要定义的系统只有一个异步通道,则我们只需要一个
C
h
a
n
n
e
l
Channel
C h a n n e l 实例,因此不必重命名。在这种情况下,我们可以这样写:
INSTANCE
C
h
a
n
n
e
l
WITH
D
a
t
a
←
D
,
c
h
a
n
←
x
\text{INSTANCE }Channel \text{ WITH }Data \leftarrow D,chan \leftarrow x
INSTANCE C h a n n e l WITH D a t a ← D , c h a n ← x
上述
C
h
a
n
n
e
l
Channel
C h a n n e l 的实例化语句没用重命名,但是使用了代换,它将
R
c
v
Rcv
R c v 定义为
C
h
a
n
n
e
l
Channel
C h a n n e l 模块中的同名公式,只是其中用
D
D
D 代换了
D
a
t
a
Data
D a t a ,用
c
h
a
n
chan
c h a n 代换了
x
x
x 。在使用表达式代换实例化模块的参数之前必须先定义它,所以这个
INSTANCE
\text{INSTANCE}
INSTANCE 语句必须在
D
D
D 和
x
x
x 的定义或声明的范围之内。