ArticlePDF Available
The L1.0Primer
Christoph Walther
Markus Aderhold
Andreas Schlosser
Fachgebiet Programmiermethodik
Fachbereich Informatik
Technische Universit¨at Darmstadt
http://verifun.org
verifun@informatik.tu-darmstadt.de
Technical Report VFR 06/01
April 4, 2006 (Update June 10, 2006)
Abstract
This document denes syntax and semantics of the functional programming language L(version
1.0)whichisusedinXeriFun 3.0 [Ver] for writing programs and stating lemmas about them.
The use of Lis illustrated by several examples and a small case study.
Contents
1 Preface 3
2SyntaxofL4
2.1 DataStructures..................................... 4
2.1.1 Denitions ................................... 4
2.1.2 TypesandTerms................................ 5
2.1.3 FixityDeclarations............................... 7
2.2 Procedures ....................................... 9
2.2.1 Denitions ................................... 9
2.2.2 Let-Expressions................................. 11
2.2.3 Incompletely DenedProcedures....................... 12
2.3 Lemmas ......................................... 13
2.3.1 Denitions ................................... 13
2.3.2 Connectives................................... 14
3 Semantics of L16
3.1 SemanticsofDataStructuresandProcedures.................... 16
3.1.1 TheExceptionGuard ............................. 16
3.1.2 TheComputationCalculus .......................... 17
3.1.3 The Interpreter evalP............................. 19
3.1.4 Termination of L-Programs .......................... 20
3.2 SemanticsofLemmas ................................. 22
3.3 DomainProcedures................................... 22
4 The Tautology Checker - A Case Study 25
4.1 Preliminaries ...................................... 25
4.2 TheTautologyCheckingProcedure.......................... 26
4.3 SoundnessoftheTautologyCheckingProcedure .................. 28
4.4 CompletenessoftheTautologyCheckingProcedure................. 29
5Appendix 30
5.1 CharacterSet...................................... 30
5.2 NameSpaces ...................................... 30
5.3 NamingConventions.................................. 30
5.4 ReservedWordsandSymbols ............................. 31
5.5 SeparationofSymbols ................................. 31
5.6 Predened and Implicitly DenedProceduresandLemmas ............ 31
5.7 Aliases.......................................... 32
1
Index 35
Bibliography 35
2
1. Preface
This document describes the functional programming language L(version 1.0) which is used
in the verication tool XeriFun 3.0 [Ver] for writing programs and stating lemmas about them.
The development of Lis not meant as an attempt to invent just another programming language.
There are no features in Lwhich cannot be found in other languages, and worse, many useful
feature of these languages are (still) missing.
In fact, the intention at the beginning of the development was not to dene a program-
ming language. It rather was the need for a simple notation to state propositions about data
structures and procedures in order to investigate reasoning problems arising when proving these
propositions by machine. Since the reasoning problems had been the focus of attention, not
much care was given to the notation, which grew up rather rampantly taking the notation used
in the former inka system [BHHW86] as a starting point.
The development of XeriFun started as a small student project but grew up more successfully
than anticipated. New language features were needed to write up more ambitious case studies in
order to challenge the verier. It was a rather obvious choice to incorporate features well known
from programming languages. But when we noticed that we were dening our own functional
language, it was too late to switch over to a “real” programming language. Simply too much time
hadbeenspenttodeveloptheverier and to build a lot of software. This makes it impossible in
an academic environment to restart from scratch to reimplement the whole system for another
language. This might apologize why we came up with a further programming language and also
answers the question “Why don’t you use a ’real’ functional language” sometimes heard.
But there is another point: Since our concern is verication, it does not help to use a “real”
language containing features the verier does not support. This would rather mean to dene
subsets of the “real” language by restricting it to language features the verier can cope with.
But it takes time to set up a verier to support all these beautiful language features coming
with “real” functional languages. So this answers another question sometimes heard: “Why
does your language not support mutual recursion, higher-order functions, a more exible type
system, etc.?” This is simply because we rst have to develop the reasoning mechanisms for a
feature before we can integrate it into the language. And the development of those mechanisms
requires numerous experiments and tests, unfortunately always taking much more time than
expected.
Having extended our “notation” from time to time with the development of the XeriFun
system, we felt that the time was ripe to give it a name and–more importantly–to present the
formal denition for it. So in the sequel, we dene syntax and semantics of L,tryingtobeas
brief as possible but as precise as necessary. We also illustrate the use of Lby several examples
and present a small case study which–as we hope–helps to become quickly familiar with the
language.
3
2. Syntax of L
2.1. Data Structures
2.1.1. Denitions
Adata structure is dened by an L-expression of form
structure struct[@V1,...,@Vl]<=con s 1(sel1,1:type1,1,...,sel1,n1:type1,n1)
...
con s k(selk,1:typek,1,...,sel k,nk:typek,nk)
(2.1)
where l0, k1andni0foreachi{1,...,k}.Thesymbolstruct is called a type
constructor of arity land the symbols @V1,...,@Vlare called type variables.
The L-expression (2.1) denes a type struct[@V1,...,@Vl] and must satisfy for each i
{1,...,k}and each h{1,...,n
i}:
typei,h is a type built by the type variables @V1,...,@Vl,typestruct [@V1,...,@Vl]
and the type constructors (dierent from the predened type bool –see Example 1) dened
previously by other data structures,
the symbols struct,co ns iand sel i,h are pairwise dierent as well as dierent from all
identiers that have been previously introduced by data structure, procedure and lemma
denitions.
In addition,
each type variable @Vjis used in one of the types typei,h dierent from struct [@V1,...,@Vl]
for some i{1,...,k}and some h{1,...,n
i}at least, and
typei,h 6=struct[@V1,...,@Vl] must hold for some i{1,...,k}and each h{1,...,n
i}.
One writes simply con s iinstead of cons i() if ni= 0 as well as structure struct <=...
instead of structure struct []<=... if l=0. struct is called a monomorphic type in such a
case, and struct[@V1,...,@Vl]isapolymorphic type otherwise.
Example 1.
1. The monomorphic type bool is dened by the L-expression
structure bool <=true,false .
This data structure is predened in L.
4
2. The monomorphic type Nis dened by the L-expression
structure N<=0,+(:N).
This data structure–dening the natural numbers IN –is predened in L. The constructor
function symbol +(denoting the successor function) can be alternatively written as succ,
the selector function symbol (denoting the predecessor function) can be alternatively
written as pred and the type Ncan be alternatively written as nat.1
3. The polymorphic type SEXPR [@ITEM ]is dened by the L-expression
structure SEXPR [@ITEM ]<=
NIL,
ATOM (DATA :@ITEM ),
CONS(CAR :SEXPR [@ITEM ],CDR :SEXPR [@ITEM ]) .
This data structure (related to the s-expressions of Lisp)denes binary trees which hold
their data in the leaves.
4. The polymorphic type LIST [@ITEM ]is dened by the L-expression
structure LIST [@ITEM ]<=
EMPTY ,
ADD(HD :@ITEM ,TL :LIST [@ITEM ]) .
This data structure denes linear lists, where EMPTY stands for the empty list and ADD
builds a new list kby placing some new list element HD(k)in front of another list TL(k).
5. The polymorphic type tree [@ITEM ]is dened by the L-expression
structure tree [@ITEM ]<=
leaf (data :@ITEM ),
node(descendants :LIST [tree [@ITEM ]]) .
This data structure denes nitely branching trees the inner nodes of which may have
dierent outdegrees and the leaves hold the data. ¥
2.1.2. Types and Terms
Types are built with type constructors and type variables, where the arity of the type construc-
tors has to be respected. A type containing type variables is called polymorphic,andother-
wisethetypeismonomorphic. By replacing type variables in a polymorphic type by types,
further types are obtained. So, for the data structure denitions of Example 1, SEXPR [N],
LIST [N], LIST [SEXPR [N]] and SEXPR [LIST [N]] are monomorphic types, and the types
SEXPR [SEXPR [@ITEM ]] and LIST [LIST [@ITEM ]] are polymorphic. However, when build-
ing further types, type variables must not be replaced by the type bool ,soe.g. SEXPR [bool ]
and LIST [bool ] are no legal types.2
Each data structure denition DS as given in (2.1) denes a signature in terms of types for
the function symbols introduced by DS :Foreachi{1,...,k}and each h{1,...,n
i}:
1Note that “:” always has to be enclosed in blanks in a type declaration of a selector.
2Type boo l receives special treatment as function symbols p:τ1×...×τnbool adopt the rˆole of predicate
symbols in L.
5
con s i:typei,1×... ×typei,nistruct [@V1,...,@Vl], called a constructor function
symbol,
?consi:struct [@V1,...,@Vl]boo l , called a structure predicate symbol, and
seli,nh:struct[@V1,...,@Vl]typei,nh, called a selector function symbol.
Using this signature, terms tcan be dened and assigned a type τ(denoted t:τfor short)
as usual (see e.g. [CW85]). For example,
true and false are terms of type bool ,
0, +(0), +(+(0)), +((0)), (+(0)), +(+(+(0))) are terms of type N,
CONS(NIL,NIL), CONS (NIL,CONS (NIL,NIL)) are terms of type SEXPR [@ITEM ],
and
CONS(NIL,NIL), CONS (NIL,ATOM (+(0))), CONS (CONS (NIL,ATO M ((0))),NIL)are
terms of type SEXPR [N].
OnemayalsousenumeralstowritetermsoftypeN,wherenstands for napplications of +
to 0. So e.g., 1 stands for +(0), 2 for +(+(0)), 3 for +(+(+(0))) etc.
For building terms, the following function symbols are available in addition for each type τ
dierent from a type variable:
=:τ×τbool ,whereτ6=bool ,
if :bool ×τ×ττ,and
cas e :τ0×τ×...×τ
|{z }
ktimes
τ,whereτ0is some type dened by a data structure with k
constructors.
The symbol =denotes equality and is written in inxnotation.
Boolean conditionals (also called if -expressions) of type τare written in functional or in
procedural notation,viz.
if {a, b, c},or
if athen belse cend if .
Structural conditionals (also called cas e -expressions) of type τdened by a data structure
with constructors con s 1,...,cons kare written in functional or in procedural notation,viz.
cas e {t;cons 0
1:t1, ... , con s 0
k:tk},
cas e {t;cons 0
1:t1, ... , con s 0
h:th,other:t0},
case tof cons0
1:t1, ... , con s 0
k:tkend cas e ,or
case tof cons0
1:t1, ... , con s 0
h:th,other :t0end cas e ,3
where {con s 0
1,...,con s 0
k}={con s 1,...,cons k}and {co ns 0
1,...,con s 0
h}Ã{con s 1,...,cons k}.
Instead of end if or end cas e ,end as well as pairs of parentheses instead of pairs of curly
brackets may be used when writing conditional expressions in functional notation.
3Note that “:” always has to be enclosed in blanks in a ca se -expression.
6
2.1.3. Fixity Declarations
Each function symbol in a data structure denition of form (2.1) may be preceded by a xity
declaration of form
[prex],
[postx],
[outx],
[inx],
[inxl,N],or
[inxr,N ]
where N, called the precedence of the function symbol, is a numeral dierent from 0.
prexand post x
Fixity prexis assumed by default if a xity declaration is missing and xity postxplaces a
function symbol behind the list of arguments, i.e. (...)!for a postxfunction symbol !as
compared to !(...)if!is declared prexor no xity is declared for !at all.
Constant symbols cannot have a xity other than prex. Also structure predicates ?cons
have always xity prex, except if the constructor cons has xity outx(see below).
outx
If xity outxis declared, 2 function symbols (not dened elsewhere) separated by a colon
(enclosed in blanks) may (but need not) be used. For example, one may write
structure bintree [@ITEM ]<=
,
[outx]l:m(left :bintree [@ITEM ],key :@ITEM ,right :bintree [@ITEM ]) .
and terms of type bintree [N]thenarewrittenas
l,0,m,
ll,0,m,1,m,
ll,5,m,1,l,3,mmetc.4
Axity declaration of form “[outx]symbol” is treated like “[outx]symbol :symbol”. So if
one replaces “[outx]l:m”by“[outx]|”intheabovedenition, terms of type bintree [N]are
written as
•|,0,|,
•||,0,|,1,|,
4Note that the argument list of an outxfunction symbol always has to be enclosed in blanks.
7
•||,5,|,1,|,3,||etc.
Theapplicationofastructurepredicate of a constructor “[outx]left :right ”toanargument
tis written as “?left tright”. So one writes e.g. ?ltmfor the constructor of bintree.In
cas e -expressions, one writes “left right” for those constructors, for example
case tof :... , lm:... end case .
inx,inxr and inxl
These xity declarations are reserved for binary function symbols. One may dene, for example,
structure SEXPR [@ITEM ]<=
NIL,
ATOM (DATA :@ITEM ),
[inx](CAR :SEXPR [@ITEM ],CDR :SEXPR [@ITEM ])
and terms of type SEXPR [N] then are written as
(NIL NIL),
(NIL ATO M (1)),
((NIL ATOM (1)) NIL)etc.,
where “” has to be enclosed in blanks. If one replaces [inx]by[inxl ,2]intheabovedenition,
parenthesesmaybeomittedinleft-nested-terms. For instance, terms of type SEXPR [N]now
can (but need not) be written as
NIL NIL,
NIL ATOM (1),
NIL ATOM (1) NIL
where the latter term is the same as
((NIL ATOM (1)) NIL)
hence dierent to
(NIL (ATOM (1) NIL)).
The precedence of a function symbol, e.g. 2 for the constructor in the example, is used to
resolve ambiguities. A term ab¤cstands for (ab)¤c,iftheinxl function symbol
has a greater precedence than the inxl function symbol ¤,anditstandsfora(b¤c)if
theprecedenceof¤is greater than the precedence of .Ifbothfunctionsymbolshavesame
precedence, ab¤cis not a syntactically correct term, hence parentheses must be used to
resolve ambiguities explicitly.
Similarly, inxr is used to omit parentheses in terms which then are treated as right-nested.
Further examples:
8
Example 2.
1. The polymorphic type pair [@ITEM1 ,@ITEM2 ]is dened by the L-expression
structure pair [@ITEM1,@ITEM2]<=
[inx] ([postx] 1: @ITEM1, [postx] 2:@ITEM2)
and
(2 3) is a term of type pair [N,N],
(1 (2 3)) is a term of type pair [N,pair [N,N]],
((1 2) 3) is a term of type pai r [pair [N,N],N],
(1 (2 3))1is a term of type N,and
(1 (2 3))2is a term of type pair [N,N].
2. The polymorphic type list [@ITEM ]is dened by the L-expression
structure list [@ITEM]<=
ø,[inxr,100] ::(hd : @ITEM, tl : list[@ITEM])
and
1::2::3::4::øisatermoftypelist [N],
(1 2) :: (3 4) :: øisatermoftypelist [pair [N,N]],and
(1 :: 2 :: ø):: (3 :: 4 :: ø)::øisatermoftypelist [list [N]].¥
2.2. Procedures
2.2.1. Denitions
Aprocedure is dened by an L-expression of form
function proc(x1:type1,...,x
k:typek):type <=body proc (2.2)
where k1andforeachi, j {1,...,k}:
proc, called the name of the procedure, is an identier dierent from all identiers that
have been previously introduced by data structure, procedure and lemma denitions,
xiis a symbol dierent from all type constructors and function symbols of the data struc-
ture and procedure denitions introduced so far,
xi6=xj,ifi6=j,
typeiis a type variable or a type built with type constructors dierent from bool dened
previously by some data structures,
type is a type variable or a type built with type constructors denedpreviouslybysome
data structures, and
9
each type variable in type also appears in some of the types typei.
A procedure denition as given in (2.2) extends the signature by a
procedure function symbol proc :typei×...×typektype.
The symbols xiin (2.2) are called the formal parameters of procedure proc and are used as
variable symbols of type typei. The expression bod y proc is called the body of procedure proc and
it is demanded that
body proc is a term of type type using only
function symbols of the data structure and procedure denitions introduced so far,
the procedure function symbol proc,and
the formal parameters xi, such that
thetypeofeachactual parameter tiis identical to typeifor each occurrence of proc(t1,...,t
k)
in body proc,and
bis free of if -andca se -expressions for each subterm if {b, . . .}or ca se {b;...}of bod y proc .
Like for constructor and selector function symbols in a data structure denition, the pro-
cedure function symbol may be preceded by a xity declaration in the head of the procedure
denition, cf. Section 2.1.3. Also formal parameters sharing a common type may be written as
x1,...,x
k:type instead of x1:type,...,x
k:type intheprocedurehead.
Example 3.
1. The greater-than relation on natural numbers can be dened by the procedure
function [inxl,1] >(x : N,y: N):bool<=
if ?0(x) then false else if ?0(y) then true else (x) >(y) end if end if .
Procedure >is predened in L.5
2. Addition of natural numbers can be dened by the procedure
function [inxr,10] +(x, y : N): N<=
if ?0(x) then yelse +((x) + y) end .
3. Multiplication of natural numbers can be dened by the procedure
function [inxr,20] (x, y : N): N<=
if ?0(x) then 0else (x) y+yend .
4. The factorial function can be dened by the procedure
function [postx] !(x : N): N<=
if ?0(x) then 1else ((x))!xend .
5Note that “:” always has to be enclosed in blanks in a type declaration of a formal parameter.
10
5. List concatenation can be dened by the procedure
function [inxr,10] <>(k, l : list[@ITEM]) : list[@ITEM]<=
if ?ø(k) then lelse hd(k) :: (tl(k) <> l) end .
6. Thelengthofalistcanbecomputedbytheprocedure
function [outx] |(k : list[@ITEM]): N<=
if ?ø(k) then 0else +(|tl(k) |)end .
7. Deletion of list elements can be dened by the procedure
function [inxr,100] \(k : list[@ITEM], i : @ITEM) : list[@ITEM] <=
if ?ø(k)
then ø
else if i=hd(k)then tl(k) else hd(k) :: (tl(k) \i) end
end .
8. The product of the members of a list of natural numbers can be dened by the procedure
function Π(k : list[N]): N<=
if ?ø(k) then 1else hd(k) Π(tl(k)) end .¥
2.2.2. Let-Expressions
Procedure bodies may contain so-called let-expressions, i.e. expressions of the form
let var := tin rend let
where
var is some identier–called a local variable–which is dierent from the formal para-
meters of the procedure and from all type constructors and function symbols of the data
structure and procedure denitions introduced so far, and
risatermwhichmayalsocontainvar and other local variables introduced by further
let-expressions surrounding the let-expression in the procedure body.
The local variable var of a let-expression is assigned the type of term tand the whole let-
expression is assigned the type of term r. Instead of procedural notation,let -expressions may
also be written in functional notation ,viz.
let{var := t;r}.
Instead of end let,end as well as pairs of parentheses instead of pairs of curly brackets may
be used when writing let-expressions in functional notation.
11
Example 4.
1. The depth of binary trees represented by terms of type SEXPR [@ITEM ]can be computed
by the procedure
function depth(x : SEXPR [@ITEM ]): N<=
case xof
CONS : let CAR-depth := depth(CAR(x)) in
let CDR-depth := depth(CDR(x)) in
if CAR-depth >CDR-depth then +(CAR-depth) else +(CDR-depth) end
end let
end let ,
other :0
end case .
2. The minimal element of a list of natural numbers can be dened by the procedure
function minimum(k : list [N]): N<=
if ?ø(k)
then 0
else if ?ø(tl(k))
then hd(k)
else let min-tl := minimum(tl(k)) in
if hd(k) >min-tl then min-tl else hd(k) end if
end let
end if
end if .¥
2.2.3. Incompletely Dened Procedures
For some procedures, a meaningful result cannot be dened for certain inputs or it is impossible
to stipulate a result for certain inputs at all. For example, it is not meaningful to dene the
minimum of an empty list as done by procedure minimum of Example 4. And worse, one cannot
give a procedure for computing the last element of a polymorphic list as no result can be dened
for the empty list.
As a remedy, the wildcard symbol may be used to denote an unspecied result in a pro-
cedure body by writing in the alternatives of a conditional, yielding a incompletely dened
procedure. Incompletely dened procedures (also known as loose specications or underspeci-
cations in the literature) are in particular useful to avoid articial results using “default” values
in case of invalid inputs, see [WS05b] for further details. For instance, 0 may be replaced in
procedure minimum of Example 4 by . Further examples:
12
Example 5.
1. Subtraction of natural numbers can be dened by the procedure
function [inxl,10] (x, y : N): N<=
if ?0(y) then xelse if ?0(x)thenelse (x) (y) end end .
2. Truncated division of natural numbers can be dened by the procedure
function [inxl,20] /(x, y : N): N<=
if ?0(y) then else if y>xthen 0else +((x y) /y) end end .
3. The remainder function for natural numbers can be dened by the procedure
function [inxr,20] mod(x, y : N):N<=
if ?0(y) then else if y>xthen xelse (x y) mod y end end .
4. The last element of a non-empty polymorphic list can be dened by the procedure
function last(k : list [@ITEM]): @ITEM<=
if ?ø(k)
then
else if ?ø(tl(k)) then hd(k) else last(tl(k)) end
end .¥
2.3. Lemmas
2.3.1. Denitions
Alemma is dened by an L-expression of form
lemma lem <=x1:type1, ... , x
k:typekbody lem (2.3)
where k0andforeachi, j {1,...,k}:
lem–called the name of the lemma–is an identier dierent from all identiers that have
been previously introduced by data structure, procedure and lemma denitions,
xiis an identier–called a variable of the lemma–dierent from all identiers denoting
type constructors and function symbols of the data structure and procedure denitions
introduced so far,
xi6=xj,ifi6=j,
typeiis an identier denoting a type variable or a type built with type constructors dierent
from bool dened previously by some data structures, and
13
body lem –called the body of the lemma–is a term of type bool using only
the lemma variables xiof type typei,and
the function symbols of the data structure and procedure denitions introduced so far.
Like in procedure denitions, the variables of a lemma sharing a common type may be written
as x1,...,x
k:type instead of x1:type,...,x
k:type in a lemma denition. Also let -expressions may
be used in the lemma body, cf. Section 2.2, where, however, the local variables must be dierent
from the variables of the lemma. The universal quantier “” may be written alternatively as
all ” and is omitted if k=0.
2.3.2. Connectives
The following table illustrates how the usual connectives are represented by the constants true
and false and the boolean conditional if ,whereaand bstand for boolean terms in the table:
Connective Boolean Term
¬aif {a, false,true }
abif {a, true,b}
abif {a, b, false}
abif {a, b, true}
abif {a, b, if {b, false,true }}
¬abif {a, false,b}
Instead of writing if {a, false,true}to denote the negated boolean term a, the negation operators
¬or not may be used, i.e. ¬aor not amay be written alternatively.
Example 6.
1. The following lemma states facts about the minimal element a list of natural numbers:
lemma minsort sorts-lemma#1 <=k : list[N], n : N
if {?ø(k),
true,
if {n>hd(k),
let{min-k := minimum(k);
if {min-k = n,
true,
if {min-k = hd(k),
¬min-k >minimum(n :: tl(k)),
¬min-k >minimum(hd(k) :: (tl(k) \min-k))}}},
let{min-k := minimum(n :: tl(k));
if {min-k = n, ¬min-k >minimum(k), true}}}} .
2. Associativity of + is stated by the lemma
lemma +associative<=x, y, z : N(x+y)+z=x+y+z .
14
3. Distributivity of + and is stated by the lemma
lemma distributes over + <=x, y, z : N
if {(x + y) z=xz+yz, x (y + z) = x y+xz, false }.
15
3. Semantics of L
Here we present a brief account on the semantics of Land refer to [Sch06] for details.
3.1. Semantics of Data Structures and Procedures
We dene an operational semantics for L, thus providing a meaning for the expressions of the
language: Given an L-program Pas a list of data structure and procedure denitions, we write
G(P)τfor the set of ground terms of a monomorphic type τin Pbuilt with the function symbols
introduced by the data structure and procedure denitions of P,andweletC(P)τdenote the
set of constructor ground terms of a monomorphic type τin P, i.e. those terms of G(P)τwhich
contain constructor function symbols only.
The elements of C(P):=SτC(P)τdenote the set of all values given for the program Pand
the elements of G(P):=SτG(P)τdenote the set of all expressions for which values shall be
computed by the procedures of P. Such computations are formally dened by a partial mapping
evalP:G(P)7G(P)
which assigns the result evalP(t)G(P) computed for a term tG(P)tothisterm. The
mapping evalPis called the interpreter of the L-program P.
Since Pmay contain non-terminating procedures, cf. Section 3.1.4, evalPis a partial map-
ping only, which means that evalP(t) may not exist for some program Pand some term tG(P).
Wesayinsuchacase,thatthecomputationoftdiverges and write evalP(t)=for denoting
divergence. Otherwise, either evalP(t)C(P), called a succeeding computation of t, because a
value is obtained for t,orevalP(t)G(P)\C(P) else, which means that the computation of t
has failed.TheresultevalP(t) is called a stuck computation of tin such a case.
3.1.1. The Exception Guard
To care for the computation of calls of incompletely dened procedures, cf. Section 2.2.3, a
so-called ex cept ion g uard ex cept proc is associated with each procedure proc as dened in (2.2) of
Section 2.2: For each occurrence πof the wildcard symbol inthebodyofprocedureproc,all
conditions leading to this occurrence are collected in a set Cπ. The exception guard exceptproc
then is dened as a boolean term representing the formula WπΠVcCπc,whereΠis the set
of all occurrences of inthebodyofprocedureproc.
One may think of the exception guard as a requirement such that exceptproc [x1/q1,...,x
n/qn]
is satised for q1,...,q
nC(P)ithe computation of the procedure call proc(q1,...,q
n)raises
an exception, see [WS05b] for further details.1
1We wr i t e t[x1/t1,...,x
n/tn] for the term obtained from term tby replacing each variable symbol xiof t
by the term ti.
16
Example 7.
1. For all procedures of Example 3, the exception guards are given as false.
2. For procedure from Example 5, exceptis given as if {?0(y), false, ?0(x)}.
3. For the procedures /and modfrom Example 5, except/and exceptmod both are given
as ?0(y).
4. For the procedure
function log2(x : N): N<=
if ?0(x)
then
else if ?0((x))
then 0
else if ?0(x mod 2) then +(log2(x /2))) else end
end
end
(computing the binary logarithm of powers of 2), the exception guard exceptlog2is given
as if {?0(x), true, if {?0((x)), false, ¬?0(x mod 2)}}.¥
3.1.2. The Computation Calculus
The interpreter evalPis dened by the so-called computation calculus which stipulates how
evalP(t) is computed for an expression tG(P). This calculus consists of so-called computation
rules of form t
r,ifcond(t, r)
where t, r G(P)andcond(t, r) is a side condition controlling the application of the computation
rule.
We write t1Pt2and call the replacement of t1by t2acomputation step , if some com-
putation rule applies for t1and t2, i.e. cond(t1,t
2)issatised for the pair of terms t1,t2.As
usual, +
Pdenotes the transitive closure of Pand
Pis the reexive closure of +
P.We
write t!
Pt0it
Pt0for some t0G(P)andt0;Pt00 for each t00 G(P). tPis dened as
t0iexactly one t0such that t!
Pt0exists.
Subsequently, we treat ¬bas an abbreviation for if (b, false,true ),andweassumethatdata
structure and procedure denitions are given in the same format as in (2.1) and (2.2) respectively.
Rules for Constructors, Selectors and Equality
?consi(con s i(q1,...,q
ni))
true ,ifq1,...,q
niC(P) (3.1)
?consj(con s i(q1,...,q
ni))
false ,ifq1,...,q
niC(P)andj6=i(3.2)
17
seli,h (con s i(q1,...,q
ni))
qh
,ifq1,...,q
niC(P) (3.3)
q1=q2
true ,ifq1,q
2C(P)andq1=q2(3.4)
q1=q2
false ,ifq1,q
2C(P)andq16=q2(3.5)
Rules for Conditionals
if {b, t1,t
2}
if {b0,t
1,t
2},ifbPb0(3.6)
if {true,t
1,t
2}
t1
(3.7)
if {false,t
1,t
2}
t2
(3.8)
case {c;co ns 1:t1,...,co ns k:tk}
cas e {c0;cons 1:t1,...,co ns k:tk},ifcPc0(3.9)
cas e {cons i(q1,...,q
ni); con s 1:t1,...,con s k:tk}
ti
,ifq1,...,q
niC(P) (3.10)
cas e {c;cons π(1) :tπ(1) ,...,co ns π(h):tπ(h),other :t}
case {c0;co ns π(1) :tπ(1),...,con s π(h):tπ(h),other :t},
if cPc0,whereπ:{1,...,k}{1,...,k}is a bijective mapping
(3.11)
case {co ns i(q1,...,q
ni); con s π(1) :tπ(1),...,con s π(h):tπ(h),other :t}
ti
,
if q1,...,q
niC(P)andi=π(j)forsomejh,
where π:{1,...,k}{1,...,k}is a bijective mapping
(3.12)
18
case {co ns i(q1,...,q
ni); con s π(1) :tπ(1),...,con s π(h):tπ(h),other :t}
t,
if q1,...,q
niC(P)andi6=π(j)foreachjh,
where π:{1,...,k}{1,...,k}is a bijective mapping
(3.13)
Rules for let-Expressions
let{var:= t;r}
let{var := t0;r},iftPt0(3.14)
let{var:= t;r}
r[var/t],ift=tP(3.15)
Rules for Function Applications
f(t1,...,t
i,...,t
n)
f(t1,...,t
0
i,...,t
n),iff/{if ,cas e ,let}and tiPt0
i(3.16)
proc(q1,...,q
k)
body proc [x1/q1,...,x
k/qk],if q1,...,q
kC(P)and
exceptproc [x1/q1,...,x
k/qk]P=false (3.17)
3.1.3. The Interpreter evalP
The computation relation Pneither is noetherian (as Pmay contain non-terminating proce-
dures, cf. Section 3.1.4) nor deterministic (by presence of computation rule (3.16)). However,
Pis conuent, i.e. for all t, t1,t
2G(P) such that t1
Pt
Pt2some rG(P) satisfying
t1
Pr
Pt2exists.
Each constructor ground term is P-minimal,i.e.q!
Pqfor each qC(P), as no compu-
tation rule can be applied to a term qC(P). Each term tG(P)\C(P) satisfying t!
Ptis
called a stuck computation. Those terms stem from
the application of a selector to a constructor it does not belong to, as e.g. (0), CAR(NIL),
DATA(CONS (...)), CDR(ATOM (...)) for the data structures of Example 1,
the call of a procedure with arguments for which the exception guard is computed to a
term 6=false,e.g. 1/0, 1 mod (1/(0)), log2(3) for the procedures of Examples 5 and 7,
the computation of a conditional having a stuck computation as rst argument, e.g.
if (?0(log2(3)),...,...), case (CAR(NIL); ...), and
the application of a function symbol dierent from if and case to one stuck argument
at least, e.g. CDR(CAR(NIL)), CONS (NIL,CDR(NIL)), (1/0) mod 2, log2(3)/1=5,
+((0)).
19
By the conuence of P,foreachtG(P)atmostonerG(P) satisfying t!
Prexists,
hence r=tPin such a case. Consequently, evalPis well-dened by stipulating
evalP(t):=
tP,ift!
Prfor some rG(P)
,otherwise.
3.1.4. Termination of L-Programs
Completely Dened Programs without Polymorphic Types
By presence of the wildcard symbol and the stuck computations caused by selectors applied
to constructors they do not belong to, L-programs are inherently incompletely dened.We
therefore call an L-program completely dened [WS05b] i
the wildcard symbol is not used in any procedure body, and
witness terms ωseli,h containing only a variable xof type struct –given as in (2.1)–at
most are provided for each selector seli,h for dening the result of a selector applied to a
constructor it does not belong to.2
Aprocedure
function proc(x1:type1,...,x
k:typek):type <=body proc
of a completely dened L-program Pwithout polymorphic types terminates i
evalP(proc(q1,...,q
k)) C(P)type
for each q1C(P)type1,...,q
kC(P)typek.3
A completely dened L-program Pwithout polymorphic types terminates i
1. each procedure proc of Pterminates, and
2. evalP(ωsel i,h [x/q]) C(P)typei,h for each qC(P)type.
Incompletely Dened Programs without Polymorphic Types
For dening termination of incompletely dened L-programs Pwithout polymorphic types, the
notion of a fair completion of program Pis used: A completely dened program P0is a fair
completion of program Pithebodyofeachprocedure
function proc(x1:type1,...,x
k:typek):type <=body proc
in Pcoincides with the body of some procedure
function proc(x1:type1,...,x
k:typek):type <=body 0
proc
2There is no feature in Lallowing to assign witness terms. We abstain from extending Lby such a feature
as their is no practical use for those programs.
3evalP(t)C(P)isequivalenttoevalP(t)6=as evalP(t)G(P)\C(P) is impossible by the requirements
for completely dened programs with monomorphic types.
20
in P0except for the unspecied -cases in body proc. Almost any result may be stipulated for those
cases in body 0
proc , however the fairness requirement demand that (i) termination of procedure
proc in P0not be spoiled just because procedure proc was completed by a non-terminating
result in a -case or (ii) a non-terminating witness term was assigned to a selector seli,h used in
body 0
proc .
Aprocedure
function proc(x1:type1,...,x
k:typek):type <=body proc
of an incompletely dened L-program Pwithout polymorphic types terminates i
evalP0(proc(q1,...,q
k)) C(P)type
for each fair completion P0of P,and
for each q1C(P)type1,...,q
kC(P)typek.
An incompletely dened L-program Pwithout polymorphic types terminates ieach procedure
proc of Pterminates, see [WS05b] for further details.
Incompletely Dened Programs with Polymorphic Types
For dening termination of general L-programs P, we consider additional data structure deni-
tions in a fair completion P0of program Ptoo.
Aprocedure
function proc(x1:type1,...,x
k:typek):type <=body proc
of an L-program Pterminates i
evalP0(proc(q1,...,q
k)) C(P)θ(type)
for each fair completion P0of P,
for each type substitution θwhich replaces the type variables in type1,...,typek,type by
monomorphic types of P0yielding the monomorphic types θ(type1),...,θ(typek),
θ(type), and
for each q1C(P)θ(type1),...,q
kC(P)θ(typek).foreachqiC(P)typei.
An L-program Pterminates ieach procedure proc of Pterminates.
It should be noted that the existence of a diverging computation of a procedure call proc(q1,...,
qk)withargumentsqiC(P) entails non-termination of procedure proc. However, the converse
does not hold as there are non-terminating procedures causing no divergent computations.
21
Example 8.
1. Procedure
function null(x : N): N<=if ?0(x) then else null(null((x))) end
does not terminate as a non-terminating fair completion of this procedure exists, viz.
function null(x : N): N<=if ?0(x) then 1else null(null((x))) end .
However, each call of null with arguments from Ncauses a failed computation only, i.e.
no such procedure call results in a diverging computation although procedure null does
not terminate.
2. Each call of procedure
function loop(x : N):N<=loop(+(x)) end
with arguments from Ncauses a diverging computation, hence procedure loop does not
terminate.
3. All procedures of Examples 3, 4, 5 and 7 terminate. ¥
3.2. Semantics of Lemmas
A lemma
lemma lem <=x1:type1, ... , x
k:typekbody lem
of a terminating L-program Pis dened to be true i
evalP0(bod y lem [x1/q1,...,x
k/qk]) = true
for each fair completion P0of P,
for each type substitution θwhich replaces the type variables in type1,...,typekby monomor-
phic types of P0yielding the monomorphic types θ(type1),...,θ(typek), and
for each q1C(P)θ(type1),...,q
kC(P)θ(typek).
3.3. Domain Procedures
Partial denitions are a means to model undenedness, cf. the procedures of Example 5 and pro-
cedure log2of Example 7. However, formally a procedure call like log2(0) denotes an unknown
value causing a failed computation only, whereas a procedure call like loop(0), cf. Example 8,
causes a diverging computation and does not denote a value at all.
22
By the semantics of L-lemmas, cf. Section 3.2, a lemma like
lemma lem1 <=x:Nx/0=xmod 0
is false, because a fair completion P0containing the fairly completed procedures “/”and“mod
exists such that e.g. evalP0(0/0) = 0 but evalP0(0 mod 0) = 1. However, a lemma like
lemma lem2 <=x:Nx/0=x/0
is true, because evalP0(q/0=q/0) = true for each qC(P)Nand for any fair completion P0
containing the fairly completed procedure “/”, although evalPcomputes a stuck computation
as evalP(q/0=q/0) = q/0=q/0.
In order to recognize such unwanted truths caused by the dierences between the
semantics of data structures and procedures of an L-program Pgiven by the interpreter
evalPand the
semantics of lemmas given by the interpreters evalP0of all fairly completed programs P0,
so-called domain procedures [WS05b] may be used: For any function symbol
f:type1×...×typektype
of an L-program with f/{if ,cas e }, it is demanded that this L-program contains a domain
procedure
function f(x1:type1,...,x
k:typek):bool <=bod y f
satisfying for each type substitution θwhich replaces the type variables in type1,...,typekby
monomorphic types of P–yielding the monomorphic types θ(type1),...,θ(typek)–and for each
q1C(P)θ(type1),...,q
kC(P)θ(typek)
1. evalP(f(q1,...,q
k)) G(P)evalP(f(q1,...,q
k)) G(P),
2. evalP(f(q1,...,q
k)) C(P)evalP(f(q1,...,q
k)) G(P), and
3. evalP(f(q1,...,q
k)) = true evalP(f(q1,...,q
k)) C(P).4
By requirement (1), the computation of f(q1,...,q
k)diverges ithe computation of
f(q1,...,q
k) diverges. By requirement (2), stuck computations are never obtained by call-
ing domain procedures. Finally by requirement (3), a domain procedure fdecides for each
list q1,...,q
kof actual parameters whether a non-diverging computation of f(q1,...,q
k)fails
or succeeds. Section 4 provides examples for the use of domain procedures.
Example 9.
1. The domain procedure for procedure “+” from Example 3 is given as
function +(x, y : N): bool <=true .
4In XeriFun, domain procedures (with xity prex) are automatically synthesized for each function symbol
dierent from a conditional.
23
2. The domain procedure for procedure mod from Example 5 is given as
function mod(x, y : N): bool <=¬?0(y) .
3. The domain procedure for procedure log2from Example 7 is given as
function log2(x : N): boo l <=
if ?0(x)
then false
else if ?0((x))
then true
else if ?0(x mod 2) then log2(x /2) else false end
end
end .5¥
5Note that evalP(exceptproc [x1/q1,...,x
k/qk]) = true entails evalP(proc(q1,...,q
k)) = false but
evalP(proc(q1,...,q
k)) = false does not entail evalP(exceptproc [x1/q1,...,x
k/qk]) = true. For example,
evalP(log2(6)) = false,butevalP(exceptlog2[x/6]) = false as well.
24
4. The Tautology Checker - A Case Study
We illustrate the use of Lby a small case study taken from [BM79]. In this example, syntax
and semantics of a propositional language are dened, a tautology checker for formulas of this
language is given and lemmas stating soundness and completen ess of this procedure are provided.
We also give some of the auxiliary lemmas which are required to prove both main statements in
XeriFun .
4.1. Preliminaries
The propositional language is dened by the data structure
structure IF.Expr <=
T,
F,
PROP(index : N),
IF(test : IF.Expr, left : IF.Expr, right : IF.Expr)
where the constructor constants Tand Fare intended to denote truth and falsity,propositional
variables are given as PROP(0),PROP(1),PROP(2),... and IF is the only connectiv e of the
language intended to denote (ab)(¬ac)byatermIF(a, b, c).
As usual, the meaning of a propositional formula is given by a valuation, i.e. a mapping
which assigns truth values to propositional variables. As each propositional formula consists
of nitely many propositional variables only, a mapping assigning truth values to nitely many
propositional variables suces. The graph of such a partial valuation can be represented by a
nite list of pairs (i, tv), where idenotes the index of the propositional variable PROP( i)to
which the truth value tv is assigned.
Truth values, pairs and lists are dened by the data structures
structure TruthValue <=TRUE,FALSE
structure pair[@ITEM1,@ITEM2] <=
[inxr,100] ([postx] 1:@ITEM1,[postx] 2:@ITEM2)
structure list[@ITEM] <=ø,[inxr,100] ::(hd : @ITEM, tl : list[@ITEM])
so that partial valuations can be represented by terms of type list [pair [N,TruthValue]]. This
type is an instance of the type list [pair [@ITEM1 ,@ITEM2 ]] the terms of which represent so-
called association lists. For those lists, the data associated with a certain key can be computed
by the procedure
25
function [inxl, 20] c
°(alist : list[pair[@ITEM1, @ITEM2]], key : @ITEM1) : @ITEM2 <=
if ?ø(alist)
then
else let head := hd(alist) in
if key = (head)1then (head)2else tl(alist) c
°key end if
end let
end if .
Since no data can be retrieved by procedure c
°if a key cannot be found in the association list,
the result of c
°is indetermined in such a case.1Consequently, the domain procedure of c
°is
given as
function c
°(alist : list[pair[@ITEM1, @ITEM2]], key : @ITEM1) : bool <=
if ?ø(alist)
then false
else if key = (hd(alist))1then true else c
°(tl(alist), key) end if
end if .
Using these denitions, the semantics of propositional formulas is dened by a procedure
function [inxr,10] ²(σ: list[pair[ N, TruthValue]], x : IF.Expr) : bool <=
case x o f
T : true ,
F:false,
PROP : ?TRUE( σc
°index(x)) ,
IF : if σ²test(x) then σ²left(x) else σ²right(x) end if
end case .
Procedure ²implements the satisfaction relation yielding true if a partial valuation σsatises
a propositional formula x, and yielding false if σfalsies x. However, since it is not guaranteed
that each propositional variable of formula xconsidered by procedure ²is mentioned in the
partial valuation σ, computation of σ²xmight fail with a stuck computation.
4.2. The Tautology Checking Procedure
The base idea of the tautology checking algorithm is to decide for a propositional formula x
whether a given partial valuation σcan be extended to a valuation which falsies x.Ifso,the
extended valuation is returned, and otherwise the algorithm reports failure about computing a
falsifying extension of σ. Now to check whether xis a tautology, the algorithm is called with
the empty valuation ø. If failure is reported, no falsifying valuation for xexists–hence each
valuation must satisfy x–and so xis a tautology. Otherwise there is some valuation falsifying
x,andthenxcannot be a tautology.
Theresulttypeofthetautologycheckerisgivenbythetypeofvaluationsexpandedbysome
failure indication. We therefore introduce the data structure
structure yields[@ITEM] <=,return(result : @ITEM))
1By abuse of notation, c
°” stands for “content”.
26
to be used for dening the result type of the tautology checker.2This algorithm now can
implemented by the procedure
function 0(σ:list[pair[N, TruthValue]], x : IF.Expr) : yields[list[pair[N,TruthValue]]] <=
case x of
T:,
F : return( σ),
PROP : let prop := index(x) in
if c
°(σ, prop)
then if ?FALSE( σc
°prop) then return( σ)else end if
else return((prop FA LS E ) :: σ)
end if
end let ,
IF : case test(x) of
T:σ0left(x) ,
F:σ0right(x) ,
PROP : let prop := index(test(x)) in
if c
°(σ,prop)
then if ?TRUE( σc
°prop) then σ0left(x) else σ0right(x) end if
else let ρ:= (prop TRUE) :: σ0left(x) in
if ? (ρ)then (prop FA L SE ) :: σ0right(x) else ρend if
end let
end if
end let ,
IF :
end case
end case .
Procedure 0recursively explores a propositional formula x:Ifx=T,failureis reported
as Tcannot be falsied, and the input valuation σis returned for x=F,asσ(vacuously)
falsies F.Ifxis a propositional variable, domain procedure c
°is used to decide whether xis
assigned a truth value by the partial valuation σ:Ifxis assigned FAL SE , the input valuation σ
is returned as σfalsies x.Ifxis assigned TRUE , failure is reported as xcannot be falsied
by any extension of σ.If,however,xis not assigned a truth value, xcan be falsied by assigning
FAL S E to it, and this extension of σis returned as result.
If xis built with the IF -constructor, the result of 0is computed depending on the propo-
sitional formula test(x)inthetestofx:Iftest(x)isTor F, the respective alternatives have
to be explored recursively by 0.Iftest (x) is a propositional variable, domain procedure c
°
is used again to decide whether test(x) is assigned a truth value by σ. Ifso,therespective
alternatives recursively have to be explored by 0. Otherwise the partial valuation σhas to be
extended: First it is tried to falsify the left branch of the IF -conditional under the additional
assumption that test(x)isTRUE . If this computation succeeds, the computed extension of σ
is returned. Otherwise it is tried to falsify the right branch of the IF -conditional under the
additional assumption that test(x)isFAL S E , and the result of this computation denes the
nal result of 0.
2Data structure yields is generally useful to dene the result type of procedures which–like the tautology
checkerdecide whether some problem is solvable and return some solution if possible. Further examples for
those kinds of procedures are a unication algorithm or a parser.
27
The result of 0when applied to a propositional formula of form IF (IF (...),...)isleft
unspecied by procedure 0. This means that computations succeed only if 0is called with
propositional formulas free of IF ’s in the tests. We say that such formulas are in IF-normal
form, and one may verify that each propositional formula can be transformed into an equivalent
formula in IF -normal form.
The IF -normal form of a propositional formula is computed by procedure
function [outx] k(x : IF.Expr) : IF.Expr <=
if ?IF(x)
then if ?IF(test(x))
then kIF(test(test(x)),
IF(left(test(x)), left(x), right(x)),
IF(right(test(x)), left(x), right(x))) k
else IF(test(x), kleft(x) k,kright(x) k)
end if
else x
end if
and
lemma normalization is sound <=σ: list[pair[ N, TruthValue]], x : IF.Expr
if {σ²kxk,σ²x, ¬σ²x}
states that normalization of a propositional formula xby procedure kcomputes a formula
equivalent to xin fact. The fact that computations of 0always succeed for formulas in IF -
normal form is expressed by
lemma normalization y0 determination <=
σ: list[pair[ N, TruthValue]], x : IF.Expr 0(σ, kxk).
3
4.3. Soundness of the Tautology Checking Procedure
Soundness of the tautology checker is stated by
lemma 0is sound <=σ: list[pair[ N, TruthValue]], x : IF.Expr
if {?0kxk), σ²x , true}
asserting that eac h partial valuation σsatises a propositional formula xwhenever the tautology
checker–called with the normal form of xand the empty valuation ø–reports failure .To
prove this theorem, two auxiliary lemmas are needed:
lemma ²ignores assignments <=x:IF.Expr,σ: list[pair[ N, TruthValue]], n : N
if {(n (σc
°n)) :: σ²x, σ²x, ¬σ²x},
states that duplicated assignments for propositional variables do not aect the satisfaction re-
lation, and
lemma 0soundness-lemma <=x:IF.Expr,σ,θ:list[pair[N, TruthValue]]
if {?(θ0kxk), θ<²x, true},
3Lemmas normalization is sound and normalization y0 determination are not required to verify soundness
and completeness of the tautology checker.
28
states that each partial valuation θ<satises a propositional formula xwhenever the
tautology checker–called with the normal form of xand some partial valuation θ–reports
failure .4This lemma is the “key lemma” of the soundness proof, and lemma “0is sound
follows immediately from lemma “0soundness-lemma”simplybyreplacingθwith ø.
4.4. Completeness of the Tautology Checking Procedure
A tautology checker is complete ian armative answer is returned when checking a propo-
sitional formula xwhich is satised by each valuation σof the propositional variables in x.
Consequently, the contraposition of this requirement demands that a falsifying valuation for a
formula xexists, if the tautology checker returns a negative answer for x.
When using procedure 0as the tautology checker, a negative answer is represented by a
result of form return(σ), where σis a falsifying valuation for x. Hence completeness of 0can
be stated by
x:IF .Expr ?return(ø0kxk)→∃σ:list[pa ir [N,TruthValue]] ¬σ²x. (4.1)
However, statement (4.1) cannot be written as an L-lemma, because it is not a universal formula
by presence of the existential quantier in the conclusion of the implication. Hence a stronger
statement is formulated, viz.
x:IF .Expr ?return(ø0kxk)¬res ult (ø0kxk)²x(4.2)
and, obviously, statement (4.2) entails statement (4.1). Since statement (4.2) is a universal
formula, completeness of the tautology checker now can be formulated by the L-lemma
lemma 0is complete <=x:IF.Expr
let{ρ:= ø 0kxk;if{?return( ρ), ¬result( ρ)²x, true}} .5
To prove this theorem, two further auxiliary lemmas are needed:
lemma 0extends valuations <=σ:list[pair[N, TruthValue]], x : IF.Expr, n : N
let{ρ:= σ0kxk;
if {?return( ρ), if {c
°(σ,n),σc
°n=result(ρ)c
°n, true}, true}} ,
states that 0computes an extension of the input valuation σindeed (provided 0returns a
valuation at all), and
lemma 0falsies <=x:IF.Expr,σ: list[pair[ N, TruthValue]]
let{ρ:= σ0kxk;if{?return( ρ),¬result( ρ)²x, true}} ,
states that 0returns a valuation which falsies the input formula x,provided0returns a
valuation at all. This lemma is the “key lemma” of the completeness proof, and lemma “0is
com ple te ” follows immediately from lemma “0falsies”simplybyreplacingσwith ø.
4<>” denotes list concatenation dened by procedure <> in Example 3.
5This example illustrates the general approach for the elimination of existential quantiers in order to
formulate statements by L-lemmas: For a conjecture of form (1) x:τxy:τyφ[x, y], a procedure fwith signature
f:τxτyhas to be dened, such that (2) x:τxφ[x, f (x)] holds. Then with a proof of (2), (1) is proved as
well.
29
5. Appendix
5.1. Character Set
L-expressions are formed of characters from a subset of unicode.1
5.2. Name Spaces
The following name spaces must be disjoint:
the set of all type variables,
the set of all type constructors,
the set of all function symbols,
the set of all formal parameters, local variables and variables of a lemma, and
the set of all lemma names.
5.3. Naming Conventions
type variables: any alphanumeric sequence of ascii characters preceded by “@” and not
containing blanks.
type constructors, function symbols, formal parameters, local variables, variables of a
lemma: any sequence of unicode characters not preceded by “@”, “”or“” and not
containing blanks as well as any sequence of unicode characters beginning and ending
with “ 0”.
lemma names: any sequence of unicode characters neither preceded by “@” nor con-
taining “<=” as well as any sequence of unicode characters beginning and ending with
0”.
1XeriFun provides a table of all unicode characters available for writing L-expressions.
30
5.4. Reserved Words and Symbols
(Nall esac inxr postx
:)bool false lemma pred
,{>case let prex
;}=else function nat structure
+[0end if not succ
]¬end case in of then
<=:= end if inx other true
end let inxl outx
as well as identiers
preceded by “” and not containing blanks,
preceded by “p” and not containing blanks, where pis a superscripted number,
ending with “p-bounded”, where pis a number,
ending with “p-projection”, where pis a number, or
containing one of the symbols with code 0x2592, 0x22D5, 0x2019.
5.5. Separation of Symbols
The following symbols have to be enclosed in blanks:
function symbols of xity inx,inxl and inxr as well as the predened symbols “=
(equality) and “>”(greater),
the argument list of function symbols with xity outx,
the negation operators “¬”and“not ”,
:”whenusedinatypedeclarationoracas e -expression.
5.6. Predened and Implicitly Dened Procedures and Lemmas
The data structures bool and N, cf. Example 1, and procedure “>”, cf. Example 3, are
predened in L.
Certain lemmas about +,,=and >are predened in L.2
Domain procedures fare implicitly dened for each function symbol fdierent from if
and case , cf. Section 3.3.
Dierence procedures pfare implicitly dened for some function symbols f, cf. [WS05a].
Boundedness- and projection lemmas “fp-bounded”or“fp-projection” are implicitly
dened for some of the dierence procedures pf.
2These lemmas are collected in the folder Predefined which is part of each XeriFun session.
31
5.7. Aliases
The following aliases ease typing of L-expressions:3
Symbol Alias
Nnat
+(...)succ (...)
(...)pred (...)
{...}(...)
end if end
end case end
end let end
all
¬not
x1:type,...,x
k:type x1,...,x
k:type
+(...
+
|{z }
ntimes
(0) ...)n,wheren42
3The use of parentheses instead of curly brackets may introduce syntactical ambiguities an L-parser cannot
resolve. Therefore curly brackets have to be used in those rare cases.
32
Index
actual parameter, 10
all,14
ascii,30
bool ,4,31
C(P), 16
C(P)τ,16
cas e ,6
cas e -expression, 6, 8
computation
calculus, 17
diverging, 16
failing, 16
rule, 17
step, 17
stuck, 16, 19
succeeding, 16
conditional
boolean, 6
structural, 6
connective, 14
constructor function, 6
constructor ground term, 16
data structure, 4
domain procedure, 23, 31
end,6,11
end cas e ,6
end if ,6
evalP, 16, 20
exceptproc,16
exception, 16
exception guard, 16
fair completion, 20, 21
xity declaration, 7, 10
formal parameter, 10, 30
functional notation, 6, 11
G(P), 16
G(P)τ,16
ground term, 16
if ,6
if -expression, 6
in,11
inx,7,8,31
inxl,7,8,31
inxr,7,8,31
interpreter, 16
L-programm, 16
lemma, 13
let,11
let-expression, 11, 14
local variable, 11, 14, 30
nat,5
N,5,31
not,14
notation
functional, 6, 11
procedural, 6, 11
other ,6
outx,7,31
parameter
actual, 10
formal, 10, 30
postx,7
precedence, 7, 8
predened, 4, 10
prex,7
procedural notation, 6, 11
procedure, 9
incompletely dened, 12
selector function, 6
structure predicate, 6—8
stuck computation, 16, 19
33
term, 6
constructor ground, 16
ground, 16
termination
of procedures, 20
of programs, 20
type, 4, 5
constructor, 4, 30
monomorphic, 4, 5
polymorphic, 4, 5
variable, 4, 30
unicode,30
variable
local, 11, 14, 30
of a lemma, 13, 30
P,17
P,17
!
P,17
+
P,17
P,17
=,6,31
>, 10, 31
, 12, 16
34
Bibliography
[BHHW86] Susanne Biundo, Birgit Hummel, Dieter Hutter, and Christoph
Wa lt h e r . The Karlsruhe Induction Theorem Proving System. In J. H. Siek-
mann, editor, “Proc. of the 8th Inter. Conf. on Automated Deduction (CADE-8)”,
volume 230 of “Lecture Notes in Articial Intelligence”, pages 672—674, Oxford, UK
(1986). Springer.
[BM79] Robert S. Boyer and J Strother Moore. “A Computational Logic”. Aca-
demic Press, NY (1979).
[CW85] Luca Cardelli and Peter Wegner. On Understanding Types, Data Abstrac-
tion, and Polymorphism. Computing Surveys 17(4), 471—522 (1985).
[Sch06] Stephan Schweitzer. Symbolische Auswertung und Heuristiken f¨ur Induktions-
beweise. Dissertation, Technische Universit¨at Darmstadt, to appear (2006).
[Ver] http://www.verifun.org.
[WS05a] Christoph Walther and Stephan Schweitzer. Automated Termination
Analysis for Incompletely Dened Programs. In Franz Baader and Andrei
Voronkov, editors, “Proc. of the 11th Inter. Conf. on Logic for Programming, Ar-
ticial Intelligence and Reasoning (LPAR-11)”, volume 3452 of “Lecture Notes in
Articial Intelligence”, pages 332—346, Montevideo, Uruguay (2005). Springer.
[WS05b] Christoph Walther and Stephan Schweitzer. Reasoning about Incompletely
Dened Programs. In Geoff Sutcliffe and Andrei Voronkov,editors,“Proc.
of the 12th Inter. Conf. on Logic for Programming, Articial Intelligence and Rea-
soning (LPAR-12)”, volume 3835 of “Lect. Notes in Artif. Intell.”, pages 427—442,
Montego Bay, Jamaica (2005). Springer.
35
... L 2.0 extends the functional programming language L 1.0 that is used in eriFun 3.2.2 [90] from a first-order programming language to a secondorder programming language. ...
... Like L 1.0, L 2.0 features an ML-style polymorphic type system [38,73,90]. For instance, one can define a type list[@A] for polymorphic lists (also called generic lists). ...
... Furthermore, each function symbol can be assigned a fixity [90]: ...
... We develop the X eriFun system [1], [10], [12], an interactive system for the verification of statements about programs written in the functional programming language L [7]. This language consists of a definition principle for freely generated polymorphic data types, a definition principle for procedures operating on these data types based on recursion, case analyses, let-expressions and functional composition, and a definition principle for statements (called "lemmas" in the language) about the data types and the procedures. ...
... ih m ) → goal (2) is satisfied by each model of AX P plus the verified lemmas of P , where AX P is a set of first-order formulas representing the definitions of the data types and procedures in P , v * ∈ V * is a sequence of the free variables in seq (given by a set V of typed variables) and u * j ∈ U * are sequences of the universally quantified variables in the induction hypotheses ih j of seq (given by a set U of typed variables). Sequent seq is true iff (2) is satisfied by the initial model of AX P , cf. [7], [6], [14], hence validity of seq entails truth of seq (but not vice versa). ...
... Symbolic evaluation as presented here has been developed, refined and optimized by surveying theorem proving power and runtime performance for a large number of case studies, see [1], [7], [8], [9], [11], [12] for examples. It has been integrated into the X eriFun system and proved successful upon verification of functional programs. ...
Technical Report
Full-text available
We report about a first-order theorem prover which is implemented in the interactive verification tool VeriFun to prove the base and step cases of an induction proof. The use in an interactive environment requires a terminating system providing a satisfying balance between theorem proving power and runtime performance as well as the supply of results being useful for carrying on with a proof attempt (by some user interaction, say) if a proof cannot be found. The latter requirement is particularly important because non-valid formulas are frequently encountered when proving theorems by induction. Our prover is based on symbolic evaluation, i.e. a method which combines symbolic execution of programs with techniques from classical theorem proving and term rewriting. We illustrate how to integrate the use of lemmas and induction hypotheses into symbolic evaluation and discuss the incorporation of equality reasoning in particular. We call our approach "pragmatic" because no interesting formal qualities (except soundness) can be assigned to it, but it successfully performs when running VeriFun to prove statements about programs.
... In this paper, we present such a disprover for statements about programs written in the functional programming language L [14], which has been integrated into an experimental version [12] of the interactive verification tool eriFun [15,16]. The procedures of L-programs operate over freely generated Figure 1 shows an example of an L-program that defines a polymorphic data type list[@A], list concatenation <>, and list reversal rev . ...
... Subsequently, we let Σ(P ) denote the signature of all function symbols defined by an L-program P , and Σ(P ) c is the signature of all constructor function symbols in P . An operational semantics for L-programs P is defined by an interpreter eval P : T (Σ(P )) → T (Σ(P ) c ) which maps ground terms to constructor ground terms of the respective monomorphic data types using the definition of the procedures and data types in P , cf. [10,14,18]. ...
... The S-calculus consists of the inference rules (5)-(19), to which the additional side condition (*) applies as well. Rules (5)-(10) are the same as in the E-calculus, rules (11 )- (14 ) are "structural" rules to merge (in)equations, to replace variables with terms, and to solve equations v . ...
Conference Paper
Full-text available
We present a disprover for universal formulas stating conjectures about functional programs. The quantified variables range over freely generated polymorphic data types, thus the domains of discourse are infinite in general. The objective in the development was to quickly find counter-examples for as many false conjectures as possible without wasting too much time on true statements. We present the reasoning method underlying the disprover and illustrate its practical value in several applications in an experimental version of the verification tool VeriFun.
... This paper is concerned with the integration of axiomatic specifications into the eriFun system [1, 19,20], an interactive theorem prover for the verification of programs written in the functional programming language L [18]. This language consists of a definition principle for freely generated polymorphic data types, a definition principle for procedures operating on these data types based on recursion, case analyses, and functional composition, and a definition principle for statements (called "lemmas" in L) about the data types and the procedures. ...
... The operational semantics for L-programs P is defined in [17,18] by an interpreter eval P : τ T (Σ(P )) τ → τ T (Σ(P ) c ) τ which maps ground terms of arbitrary monomorphic data types τ to constructor ground terms of the respective monomorphic data types using the definition of the procedures and data types in P . In [3] the language is extended to L * including higher-order functions. ...
Conference Paper
Full-text available
Axiomatic specifications stipulate properties of operations axiomatically and are used to reason about mathematical structures like groups, rings, fields, etc. on an abstract layer. Axiomatic specifications allow the organization of the mathematical structures under investigation in a modularized and hierarchical manner, thus supporting well- structured presentations. They also provide representations of non-freely generated data types like integers in a way which supports automated reasoning. A further advantage is that concrete implementations inherit the instances of all proven properties of a specification after it has been proved that the implementation satisfies the axioms of the specification. To utilize these benefits, the interactive verification tool VeriFun has been extended to support axiomatic specifications. We illustrate the expressiveness of our approach by several examples and compare the features provided with those known from other proposals.
... We develop the eriFun system [1,14,15], an interactive system for the verification of statements about programs written in the functional first-order programming language L [12]. This language consists of definition principles for freely generated polymorphic data types, for procedures operating on these data types based on recursion, case analyses, let-expressions and functional composition, and for statements (called "lemmas" in L) about the data types and the procedures. ...
... where the type hypotheses are literals of form γ(x i ) with γ ∈ P, where γ(x i ) := true is omitted if γ ∈ P. 12 The initial sequent of a prooftree for a lemma lem as given in (2) is τ 1 (x 1 ),. .. , τ k (x k ); ; body lem. ...
Article
Full-text available
We present two enhancements of the functional language L which is used in the ✓eriFun system to write programs and formulate statements about them. Context dependent procedures allow to stipulate the context under which procedures are sensibly executed, thus avoiding runtime tests in program code as well as verification of absence of exceptions by proving stuck-freeness of procedure calls. Computed types lead to more compact code, increase the readability of programs, and make the well-known benefits of type systems available to non-freely generated data types as well. Since satisfaction of context requirements as well as type checking becomes undecidable, proof obligations are synthesized to be proved by the verifier at hand, thus supporting static code analysis. Information about the type hierarchy is utilized for increasing the performance and efficiency of the verifier.
... The eriFun system [13] is an interactive system for the verification of statements about programs written in the functional first-order programming language L [12]. This language consists of definition principles for freely generated polymorphic data types, for procedures operating on these data types based on recursion, case analyses, letexpressions and functional composition, and statements (called "lemmas" in L) about the data types and the procedures. ...
Article
Full-text available
The Elliptic Curve Cryptography (ECC) is widely known as secure and reliable cryptographic scheme. In many situations the original cryptographic algorithm is modified to improve its efficiency in terms like power consumption or memory consumption which were not in the focus of the original algorithm. For all this modification it is crucial that the functionality and correctness of the original algorithm is preserved. In particular, various projective coordinate systems are applied in order to reduce the computational complexity of elliptic curve encryption by avoiding division in finite fields. This work investigates the possibilities of automated proofs on the correctness of different algorithmic variants. We introduce the theorems which are required to prove the correctness of a modified algorithm variant and the lemmas and definitions which are necessary to prove these goals. The correctness proof of the projective coordinate system transformation has practically been performed with the help of the an interactive formal verification system XeriFun.
Article
Hume is a Turing-complete programming language, designed to guarantee space and time bounds whilst still working on a high-level. Formal properties of Hume programs, such as invariants and transformations, have previously been verified using the temporal logic of actions (TLA). TLA prop- erties are verified in an inductive way, which often requires lemma discovery or generalisations. Rippling was developed for guiding inductive proofs, and supports lemmas and generalisation dis- covery through proof critics. In this paper we show how rippling and proof critics can be used in the verification of Hume invariants represented in TLA. Our approach is based on existing work on the problem of verifying and discovering loop invariants for an imperative program. We then extend this work to Hume program transformations.
Conference Paper
For proofs by induction it is often necessary to generalize statements to strengthen the induction hypotheses. This paper presents improved heuristics to generalize away subterms, unnecessary conditions and function symbols in a formula. This resolves shortcomings that we encountered within an experimental evaluation of generalization heuristics from the literature. Our generalization method has been implemented in the verification tool \checkmark\checkmark eriFun . An evaluation with examples from the literature as well as several case studies of our own demonstrates the success of our development.
Conference Paper
Many algorithms on data structures such as terms (nitely branching trees) are naturally implemented by second-order recursion: A rst-order procedure f passes itself as an argument to a second-order procedure like map, forall, foldl, foldr, etc. to recursively apply f to the direct subterms of a term. We present a method for automated termina- tion analysis of such procedures. It extends the approach of argument- bounded functions in two respects: Firstly, it also inspects components of types. Secondly, it adds a facility to take care of second-order recursion. Our method has been implemented and automatically solves the exam- ples considered in the literature. This improves the state of the art of inductive theorem provers that required user interaction before, even for termination proofs of simple second-order recursive procedures.
Conference Paper
In order to support the verification of programs, verification tools such as ACL2 or Isabelle try to extract suitable induction axioms from the definitions of terminating, recursively defined procedures. However, these extraction techniques have difficulties with procedures that are defined by second-order recursion: There a first-order procedure f passes itself as an argument to a second-order procedure like \(\mathit{map}\), \(\mathit{every}\), \(\mathit{foldl}\), etc., which leads to indirect recursive calls. For instance, second-order recursion is commonly used in algorithms on data structures such as terms (variadic trees). We present a method to automatically extract induction axioms from such procedures. Furthermore, we describe how the induction axioms can be optimized (i. e., generalized and simplified). An implementation of our methods demonstrates that the approach facilitates straightforward inductive proofs in a verification tool.
Conference Paper
Full-text available
Incompletely defined programs provide an elegant and easy way to write and to reason about programs which may halt with a run time error by throwing an exception or printing an error message, e.g. when attempting to divide by zero. Due to the presence of stuck computations, which arise when calling incompletely defined procedures with invalid arguments, we cannot use the method of argument bounded algorithms for proving termination by machine. We analyze the problem and present a solution to improve this termination analysis method so that it works for incompletely defined programs as well. Our technique of proving the termination of incompletely defined programs maintains performance as well as simplicity of the original method and proved successful by an implementation in the verification tool VeriFun.
Conference Paper
Full-text available
We consider automated reasoning about recursive partial functions with decidable domain, i.e. functions computed by incompletely defined but terminating functional programs. Incomplete definitions provide an elegant and easy way to write and to reason about programs which may halt with a run time error by throwing an exception or printing an error message, e.g. when attempting to divide by zero. We investigate the semantics of incompletely defined programs, define an interpreter for those programs and discuss the termination of incompletely defined procedures. We then analyze which problems need to be solved if a theorem prover designed for verification of completely defined programs is modified to work for incompletely defined programs as well. We also discuss how to reason about stuck computations which arise when calling incompletely defined procedures with invalid arguments. Our method of automated reasoning about incompletely defined programs has been implemented in the verification tool VeriFun . We conclude by discussing experiences obtained in several case studies with this implementation and also compare and relate our proposal to other work.