Pingpong
Now we'll consider specifying an interface for an extremely simple
protocol: pingpong. This protocol represents a simple game that is
played across in interface with two actions" ping and pong.
object intf = {
action ping
action pong
}
hit which, when called, causes it
to hit the ball into the other court. The left player does this by
calling ping, while the right player calls pong.
We begin by specifying the interface actions. The enumerated type
side tells us in which court the ball is.
type side_t = {left,right}
object spec = {
var side : side_t
after init {
side := left
}
ping occurs, the ball must be on the left. It moves to the right.
before intf.ping {
assert side = left;
side := right
}
pong occurs, the ball must be on the rightr. It moves to the left.
before intf.pong {
assert side = right;
side := left
}
}
ball indicating that it
has the ball. On hit, if the player has the ball, it calls ping
to move the ball to the other court and sets ball to false. On
pong, it records the fact that it now has the ball again.
object left_player = {
var ball : bool
init ball
action hit = {
if ball {
call intf.ping;
ball := false
}
}
implement intf.pong {
ball := true
}
}
ping and
pong.
object right_player = {
var ball : bool
init ~ball
action hit = {
if ball {
call intf.pong;
ball := false
}
}
implement intf.ping {
ball := true
}
}
hit action to the environment (otherwise
the program wouldn't do anythihng!).
export left_player.hit
export right_player.hit
ping is a guarantee, while the precondition of pong is
an assumption. The situation is reversed for the right player. When testing
the left player, the right player is abstracted away, and its role is played
by the tester. Notice that in both isolate declarations, we say with spec.
Without this declaration, the spec object would also be abstracted away and
no assertions would be checked.
trusted isolate iso_l = left_player with spec
trusted isolate iso_r = right_player with spec
We can compile and test the two isolates with these commands:
$ ivy_to_cpp target=test isolate=iso_l build=true pingpong.ivy
$ ./pingpong
$ ivy_to_cpp target=test isolate=iso_r build=true pingpong.ivy
$ ./pingpong
Of course, we have to check that we acutally have verified all the assertions. This can be done with the following command:
$ ivy_check pingpong.ivy
Note: to run ivy on the command line in Windows, you need to first do this:
> c:\ivy\scripts\activate.bat