PlusCal Syntax
For a complete reference see, the PlusCal Manual. Here is the summary of the language features that I have used in my examples; you should be able understand the structure from the examples, so this page focuses on the detailed constructs.
PlusCal Statements
PlusCal is a small syntactic extension on top of TLA+. All expressions and data structures are from TLA, but we can write it down like an imperative program. The following are the PlusCal constructs we used:
- Assignment:
x := y + 1
- Await (When). This adds an enabling condition on the transition. The process waits until it can make a transition. Note that all the following behave exactly the same:
await x > 0; x := x - 1when x > 0; x := x - 1x := x - 1; when x >= 0(condition on post-transition state)x := x - 1; await x >= 0(same, but somewhat confusing style)
- If-Statements are like conditional statements, i.e., the process always takes a step, but depending on the condition different actions could be taken. It does not wait (block the process) if the condition is not true.
if x > 0 then x := 0 else z := 0 end ifif x > 0 then x := 0; y := 2 elsif y > 0 then y := 0 else z := 0 end if
- While-Statements and Goto:
Loop: while TRUE do x := x + 1 end whileLoop: x := x + 1; goto LoopLoop: while x < 10 do x := x + 1 end whileLoop: if x < 10 then x := x + 1; goto Loop end if
- Either models non-deterministic choice:
either x := 1 or x := 2 or x := 3 end eithereither when x > 0; y := 1 or when x < 0; y := -1 end either(This will wait if x is zero)
- With lets us consider a range of values. The model checker will consider all possible values from a given set. It can also be used to just give a name to a variable.
with z in {1,2,3} do x := z end withwith z = x + 1 do y := z * z end with
- Skip does nothing!
TLA+ Expressions: Basic Types
There is basic operations in TLA to work with integers, strings and booleans. Remember that TLA is a logic, so x = y is equality, not assignment. In PlusCal, we initialize variables by giving equations that hold in the initial state, so we also use equality there too, but otherwise we have x := y for assignment and x = y for equality.
- Integers have their usual syntax and arithmetic operations, except division because
/is used for other things.x + 1 \div 10x <= 100
- Strings are also just letters within quotation marks as in most programming languages. You don't need to do much with strings. We only use them as identifiers, but operations like Len and concatenation do exist.
- Booleans are obviously very important. This is a logic, after all. Here are the basic operations that you have seen in any other programming language.
TRUEandFALSEare capitalized.A /\ Bconjunction is true whenever A and B are true.A \/ Bdisjunction is true whenever A or B (or both) are true.~Ais true when A is not.A => Bimplication is the same as~A \/ B.A <=> Bequivalence is the same as equality on booleans.
TLA+ data structures
The key data structures (just like in Java) are Set, Map and List. The last two are called functions and sequences in TLA.
- Sets
- We can build them by listing elements
{1,2,3}or giving a range1..10. - There are built-in sets:
IntandNat. - Checking membership:
1 \in {1,2,3}checks if en element belongs to a set{1,3,5} \subseteq 1..5checks inclusion (subset or equal).
- Standard operations on sets:
{1,2,3} \cap {2,3,4} = {2,3}(intersection).{1,2,3} \cup {2,3,4} = {1,2,3,4}(union).1..5 \ {2,4} = {1,3,5}(set difference, i.e., removes elements).
- Sets of sets:
UNION {{1,2}, {5,6}, 11..14, {20}} = {1,2,5,6,11,12,13,14,20}flattens a set of sets to a single set that contains all elements of each set.SUBSET {1,2,3} = {{}, {1}, {2}, {3}, {1,2}, {1,3}, {2,3}, {1,2,3}}gives all possible subsets.
- Filter and map:
{x \in 0..100 : x < 15 }filters the elements in the set 0..100 that satisfy the property x < 15.{2*x : x \in 1..10}maps the function 2*x to all elements 1..10, so we get the set containing 2, 4, 6, and so on until 20.
- We can build them by listing elements
- Functions (Map)
f = [i \in 1..10 |-> 2*i]builds a function.- Get and Put:
f[1] = 2looks up the element in the map.f[5] := 200updates the map. This is PlusCal syntax, resulting in the same map as before, but with f[5] having a new value, just like in Java.
- Building and merging maps.
f = ("key" :> 10)is the singleton function withf["key"] = 10.(1 :> 100) @@ (2 :> 200)contains the mappings for both 1 and 2.
Predicate and Temporal Logic
...