The Guarded Command Language (GCL) is a programming language defined by Edsger Dijkstra for predicate transformer semantics in EWD472. [1] It combines programming concepts in a compact way. It makes it easier to develop a program and its proof hand-in-hand, with the proof ideas leading the way; moreover, parts of a program can actually be calculated.
An important property of GCL is nondeterminism. For example, in the if-statement, several alternatives may be true, and the choice of which to choose is done at runtime, when the if-statement is executed. This frees the programmer from having to make unnecessary choices and is an aid in the formal development of programs.
GCL includes the multiple assignment statement. For example, execution of the statement x, y:= y, x
is done by first evaluating the righthand side values and then storing them in the lefthand variables. Thus, this statement swaps the values of x and y.
The following books discuss the development of programs using GCL:
A guarded command consists of a boolean condition or guard, and a statement "guarded" by it. The statement is only executed if the guard is true, so when reasoning about the statement, the condition can be assumed true. This makes it easier to prove the program meets a specification.
A guarded command is a statement of the form G → S, where
skip and abort are important statements in the guarded command language. abort is the undefined instruction: do anything. It does not even need to terminate. It is used to describe the program when formulating a proof, in which case the proof usually fails. skip is the empty instruction: do nothing. It is often used when the syntax requires a statement but the state should not change.
skip
abort
Assigns values to variables.
v := E
or
v0, v1, ..., vn := E0, E1, ..., En
where
Statements are separated by one semicolon (;)
The selection (often called the "conditional statement" or "if statement") is a list of guarded commands, of which one is chosen to execute. If more than one guard is true, one statement whose guard is true is arbitrarily chosen to be executed. If no guard is true, the result is undefined, that is, equivalent to abort. Because at least one of the guards must be true, the empty statement skip is often needed. The statement if fi has no guarded commands, so there is never a true guard. Hence, if fi is equivalent to abort.
if G0 → S0 □ G1 → S1 ... □ Gn → Sn fi
Upon execution of a selection, the guards are evaluated. If none of the guards is true, then the selection aborts, otherwise one of the clauses with a true guard is chosen arbitrarily and its statement is executed.
GCL does not specify an implementation. Since guards cannot have side effects and the choice of clause is arbitrary, an implementation may evaluate the guards in any sequence and choose the first true clause, for example.
In pseudocode:
if a < b then set c to True else set c to False
In guarded command language:
if a < b → c := true □ a ≥ b → c := false fi
In pseudocode:
if error is True then set x to 0
In guarded command language:
if error → x := 0 □ error → skipfi
If the second guard is omitted and error is False, the result is abort.
if a ≥ b → max := a □ b ≥ a → max := b fi
If a = b, either a or b is chosen as the new value for the maximum, with equal results. However, the implementation may find that one is easier or faster than the other. Since there is no difference to the programmer, any implementation will do.
Execution of this repetition, or loop, is shown below.
do G0 → S0 □ G1 → S1 ... □ Gn → Sn od
Execution of the repetition consists of executing 0 or more iterations, where an iteration consists of arbitrarily choosing a guarded command Gi → Si whose guard Gi is true and executing the command Si. Thus, if all guards are initially false, the repetition terminates immediately, without executing an iteration. Execution of the repetition do od, which has no guarded commands, executes 0 iterations, so do od is equivalent to skip.
a, b := A, B; do a < b → b := b - a □ b < a → a := a - b od
This repetition ends when a = b, in which case a and b hold the greatest common divisor of A and B.
Dijkstra sees in this algorithm a way of synchronizing two infinite cycles a := a - b
and b := b - a
in such a way that a≥0
and b≥0
remains true.
a, b, x, y, u, v := A, B, 1, 0, 0, 1; do b ≠ 0 → q, r := a div b, a mod b; a, b, x, y, u, v := b, r, u, v, x - q*u, y - q*v od
This repetition ends when b = 0, in which case the variables hold the solution to Bézout's identity: xA + yB = gcd(A,B) .
do a>b → a, b := b, a □ b>c → b, c := c, b □ c>d → c, d := d, c od
The program keeps on permuting elements while one of them is greater than its successor. This non-deterministic bubble sort is not more efficient than its deterministic version, but easier to prove: it will not stop while the elements are not sorted and that each step it sorts at least 2 elements.
x, y = 1, 1; do x≠n → if f(x) ≤ f(y) → x := x+1 □ f(x) ≥ f(y) → y := x; x := x+1 fiod
This algorithm finds the value 1 ≤ y ≤ n for which a given integer function f is maximal. Not only the computation but also the final state is not necessarily uniquely determined.
Generalizing the observational congruence of Guarded Commands into a lattice has led to Refinement Calculus. [2] This has been mechanized in Formal Methods like B-Method that allow one to formally derive programs from their specifications.
Guarded commands are suitable for quasi-delay-insensitive circuit design because the repetition allows arbitrary relative delays for the selection of different commands. In this application, a logic gate driving a node y in the circuit consists of two guarded commands, as follows:
PullDownGuard → y := 0 PullUpGuard → y := 1
PullDownGuard and PullUpGuard here are functions of the logic gate's inputs, which describe when the gate pulls the output down or up, respectively. Unlike classical circuit evaluation models, the repetition for a set of guarded commands (corresponding to an asynchronous circuit) can accurately describe all possible dynamic behaviors of that circuit. Depending on the model one is willing to live with for the electrical circuit elements, additional restrictions on the guarded commands may be necessary for a guarded-command description to be entirely satisfactory. Common restrictions include stability, non-interference, and absence of self-invalidating commands. [3]
Guarded commands are used within the Promela programming language, which is used by the SPIN model checker. SPIN verifies correct operation of concurrent software applications.
The Perl module Commands::Guarded implements a deterministic, rectifying variant on Dijkstra's guarded commands.
Structured programming is a programming paradigm aimed at improving the clarity, quality, and development time of a computer program by making extensive use of the structured control flow constructs of selection (if/then/else) and repetition, block structures, and subroutines.
In computer science, control flow is the order in which individual statements, instructions or function calls of an imperative program are executed or evaluated. The emphasis on explicit control flow distinguishes an imperative programming language from a declarative programming language.
In computer science, a semaphore is a variable or abstract data type used to control access to a common resource by multiple threads and avoid critical section problems in a concurrent system such as a multitasking operating system. Semaphores are a type of synchronization primitive. A trivial semaphore is a plain variable that is changed depending on programmer-defined conditions.
Hoare logic is a formal system with a set of logical rules for reasoning rigorously about the correctness of computer programs. It was proposed in 1969 by the British computer scientist and logician Tony Hoare, and subsequently refined by Hoare and other researchers. The original ideas were seeded by the work of Robert W. Floyd, who had published a similar system for flowcharts.
In computer programming, a block or code block or block of code is a lexical structure of source code which is grouped together. Blocks consist of one or more declarations and statements. A programming language that permits the creation of blocks, including blocks nested within other blocks, is called a block-structured programming language. Blocks are fundamental to structured programming, where control structures are formed from blocks.
In computer science, conditionals are programming language constructs that perform different computations or actions or return different values depending on the value of a Boolean expression, called a condition.
In computer science, a for-loop or for loop is a control flow statement for specifying iteration. Specifically, a for-loop functions by running a section of code repeatedly until a certain condition has been satisfied.
In computer programming, the ternary conditional operator is a ternary operator that is part of the syntax for basic conditional expressions in several programming languages. It is commonly referred to as the conditional operator, ternary if, or inline if. An expression a ? b : c
evaluates to b
if the value of a
is true, and otherwise to c
. One can read it aloud as "if a then b otherwise c". The form a ? b : c
is the most common, but alternative syntax do exist; for example, Raku uses the syntax a ?? b !! c
to avoid confusion with the infix operators ?
and !
, whereas in Visual Basic .NET, it instead takes the form If(a, b, c)
.
ALGOL 68 is an imperative programming language that was conceived as a successor to the ALGOL 60 programming language, designed with the goal of a much wider scope of application and more rigorously defined syntax and semantics.
Short-circuit evaluation, minimal evaluation, or McCarthy evaluation is the semantics of some Boolean operators in some programming languages in which the second argument is executed or evaluated only if the first argument does not suffice to determine the value of the expression: when the first argument of the AND
function evaluates to false
, the overall value must be false
; and when the first argument of the OR
function evaluates to true
, the overall value must be true
.
Predicate transformer semantics were introduced by Edsger Dijkstra in his seminal paper "Guarded commands, nondeterminacy and formal derivation of programs". They define the semantics of an imperative programming paradigm by assigning to each statement in this language a corresponding predicate transformer: a total function between two predicates on the state space of the statement. In this sense, predicate transformer semantics are a kind of denotational semantics. Actually, in guarded commands, Dijkstra uses only one kind of predicate transformer: the well-known weakest preconditions.
In computer science, the Actor model and process calculi are two closely related approaches to the modelling of concurrent digital computation. See Actor model and process calculi history.
In digital logic design, an asynchronous circuit is quasi delay-insensitive (QDI) when it operates correctly, independent of gate and wire delay with the weakest exception necessary to be turing-complete.
Unifying Theories of Programming (UTP) in computer science deals with program semantics. It shows how denotational semantics, operational semantics and algebraic semantics can be combined in a unified framework for the formal specification, design and implementation of programs and computer systems.
PROMELA is a verification modeling language introduced by Gerard J. Holzmann. The language allows for the dynamic creation of concurrent processes to model, for example, distributed systems. In PROMELA models, communication via message channels can be defined to be synchronous, or asynchronous. PROMELA models can be analyzed with the SPIN model checker, to verify that the modeled system produces the desired behavior. An implementation verified with Isabelle/HOL is also available, as part of the Computer Aided Verification of Automata (CAVA) project. Files written in Promela traditionally have a .pml
file extension.
Casio fx-3650P is a programmable scientific calculator manufactured by Casio Computer Co., Ltd. It can store 12 digits for the mantissa and 2 digits for the exponent together with the expression each time when the "EXE" button is pressed. Also, the calculator can use the previous result to do calculations by pressing "Ans".
Goto is a statement found in many computer programming languages. It performs a one-way transfer of control to another line of code; in contrast a function call normally returns control. The jumped-to locations are usually identified using labels, though some languages use line numbers. At the machine code level, a goto
is a form of branch or jump statement, in some cases combined with a stack adjustment. Many languages support the goto
statement, and many do not.
Joyce is a secure programming language for concurrent computing designed by Per Brinch Hansen in the 1980s. It is based on the sequential language Pascal and the principles of communicating sequential processes (CSP). It was created to address the shortcomings of CSP to be applied as a programming language, and to provide a tool, mainly for teaching, for distributed computing system implementation.
Tcl is a high-level, general-purpose, interpreted, dynamic programming language. It was designed with the goal of being very simple but powerful. Tcl casts everything into the mold of a command, even programming constructs like variable assignment and procedure definition. Tcl supports multiple programming paradigms, including object-oriented, imperative, functional, and procedural styles.
In computer science, interference freedom is a technique for proving partial correctness of concurrent programs with shared variables. Hoare logic had been introduced earlier to prove correctness of sequential programs. In her PhD thesis under advisor David Gries, Susan Owicki extended this work to apply to concurrent programs.