Calvin-L / ezpsl

The easy parallel algorithm specification language
MIT License
4 stars 1 forks source link
concurrency language model-checking

EzPSL

Build Status

The easy parallel algorithm specification language.

This is a small, imperative, untyped, pseudocode-like language for describing simple parallel algorithms. The language "compiles" to TLA+ so that it can be exhaustively checked.

Getting Started

There are no binary distributions. You will need to install the Stack build system and compile this tool from source:

git clone https://github.com/Calvin-L/ezpsl.git
cd ezpsl
stack build
stack test # optional!
cp `stack exec -- which ezpsl` .

Usage:

./ezpsl FILE

If the file is a .tla file, then the tool looks for a line of the form \* #include FILE.ezs and replaces that line with the compiled TLA+ code. If a compilation was previously done, then the old compilation is replaced with the new one.

If the file is a .ezs file, then the tool prints the compiled TLA+ code on standard out.

You can use the -o OUT option to control where the output gets written, regardless of the input file extension.

For instance, to compile the Test example, run:

./ezpsl examples/Test.ezs

Or, to update the Test TLA+ module, run:

./ezpsl examples/Test.tla

The Language

Example file:

\* ----------------
\* Global variables

var v1 := 2;
var v2 \in {3, 4};

\* ----------------
\* Procedures

proc helper(x) {
    var tmp := x + 1;
    return tmp;
}

@entry
proc main() {
    v1 := call helper(v2);
}

Comments begin with \* and are completely ignored by the tool.

All global variables must be listed before any procedures, and local variables within a procedure must be declared first, before any statements in the procedure. Variables must be initialized. They can either be initialized with an exact value using := or nondeterministically (as an arbitrary element of a set using \in or as an arbitrary subset of a set using \subseteq).

Procedures may be listed in any order.

Each procedure may have zero or more annotations. Annotations may be listed in any order.

Expressions: a subset of TLA+ including integers and records. Additionally, the special constant self refers to the current thread ID. EzPSL also has a different set-comprehension syntax than TLA+. For example:

The TLA+ comprehensions {x \in S : P} and {e : x \in S} are not supported, since they can be expressed using the general set-comprehension primitive.

Statements:

Details About the TLA+ Output

EzPSL's TLA+ output always requires that your specification EXTENDS the following built-in modules:

The generated TLA+ declares the following constants:

The generated TLA+ declares the following variables:

The generated TLA+ declares the following operators:

NOTE: The generated TLA+ system uses one step per statement, meaning that a logically atomic block of code goes through multiple TLA+ states. However, the global variables only change when a process yields or terminates. Between yield points, processes use a private snapshot of the global variables and all changes are applied simultaneously when the process yields or terminates.

If you are curious for more details about the TLA+ output, look through the compiled TLA+ output in the examples folder.

Specifying Correctness Properties

No Assertion Failures

The compiled TLA+ code always contains an invariant definition named NoAssertionFailures asserting that no process has failed an assert statement. You can tell TLC to check NoAssertionFailures as an invariant to find assertion failures.

Global Invariants

To write a global invariant, place the invariant's definition after the compiled output. Even if a process makes multiple changes to the global variables between yield points, the global variables are only modified when the process yields. Therefore, your invariant will never "see" intermediate states between yield points.

Refinement

Refinement works the same way as global invariants. See examples/Refinement.tla for an example.

Deadlock

EzPSL generates TLA+ that supports deadlock checking. Deadlock checking is enabled by default in TLC.

Comparison to PlusCal

EzPSL is similar to PlusCal, another simple imperative language that can be compiled to TLA+ for model checking.

There are a few ways in which EzPSL is better than PlusCal:

There are also ways in which PlusCal is better than EzPSL: