This part is meant as a brief, but complete reference to Tutch.

The proof checker *Tutch* is invoked by

$ /afs/andrew/scs/cs/15-399/bin/tutch [options] [files]

The files are extended by ``.tut'` if they do not have an extension
already. Options are:

`-h, --help`- Print help message.
`-q, --quiet`- Be quiet, print only version, file access and error messages.
`-Q, --Quiet`- Be really quiet, print only error messages.
`-r, --requirements``file`-
Check Tutch files against requirements in
`file`resp.(this extension is added if no extension is given) and print out check list. The path`file`.req``/afs/andrew/scs/cs/15-399/req'`for`file`is assumed unless`file`starts with a``.'`or``/'`. If no files are given,is assumed as input file.`file`.tut `-v, --verbose`- Be verbose, print justification for each proof line.
`-V, --Verbose`- Print every available message.

Assignments submission is possible via

$ /afs/andrew/scs/cs/15-399/bin/submit -r file [options] [files]

Options are the same as for `tutch`, but `-r` is mandatory.
The status of a submission can be checked via

$ /afs/andrew/scs/cs/15-399/bin/status file

This retrieves the status of the submission `file` handed in via
`submit -r file ...`.

Tutch recognizes a set of *special symbols*. They do not have to be
separated by spaces from the remaining code, but serve as separators
themselves. These symbols are

( ) [ ] ; : = ~ & | => <=>

Furthermore there are *reserved words* which cannot be used as
identifiers:

T F proof begin end

*Identifiers* are made up of letters ``a-zA-Z'`, digits
``0-9'` underscores ``_'` and primes ``''`.

*Atoms* *Q* are identifiers that
start with capital letter. *Propositions* *A*, *B* have the following grammar

A,B::= T % Truth | F % Falsehood |Q% Atom | ~A% Negation |A&B% Conjunction |A|B% Disjunction |A=>B% Implication |A<=>B% Equivalence | (A) % Parentheses

The binary operators ``&'`, ``|'` and ``=>'` are right
associative, ``<=>'` is non-associative. Binding strength decreases
in this order:

~ & | => <=>

A *hypothesis* *H* is just a proposition. A *proof entry*
*E* is either a line or a frame. A *proof* *P* is a
non-empty list of entries.

H::=A% HypothesisE::=A% Line | [H;P] % FrameP::=E% Final step |E;P% Step and remaining proof

A *proof name* `x` is a non-capital identifier.
A *Tutch file* *F* is a sequence of proof declarations. A
*proof declaration* *D* has the following syntax:

D::= proofx:A= beginPend % Proof ofAwith namexF::= % Empty file |D;F% Declaration and remaining file

We extend our list of special symbols and reserved words by the following:

, annotated term fst snd inl inr case of fn abort

Proof terms for propositional logic are formed according to the following grammar:

M,N::=x% Variable | (M,N) % Pair | fstM% First projection | sndM% Second projection | inlM% Left injection | inrM% Right injection | caseMof inlx=>N| inry=>Oend % Case analysis | fnx=>M% Abstraction |MN% Application | () % Empty tuple (proof of truth) | abortM% Falsehood elimination |M: A % Annotation

Application is a "invisible" left-associative infix operator. It has
maximal binding strength, along with the prefix operators ``fst'`,
``snd'`, ``inl'`, ``inr'`, ``abort'`. This enforces use of
parentheses in most cases. E.g.,

(fst x) ((snd x) y)

has already a minimum amount of parentheses. Abstraction ``fn x =>'`
binds less than application and annotation ``:'` least. The following
term is syntactically correct.

fn y => fn x => x y : A => (A => B) => B

*Annotated* proofs *P* are proofs as defined above annotated
with proof terms. This changes the syntax of hypotheses *H*
and proof entries *E*.

H::=x : A% HypothesisE::=M : A% Line | [H;P] % FrameP::=E% Final step |E;P% Step and remaining proof

A *Tutch file* *F* now can contain proof, *term* and
*annotated proof* declarations *D*:

D::= proof ... | annotated proofx:A= beginPend % Annotated proof ofAwith namex| termx:A=M% Proof ofAwith namexF::= % Empty file |D;F% Declaration and remaining file

New special symbols and keywords are:

* + -> :: nat bool list 0 s rec true false if then else nil val

*Types* *T*, *T'* have the following grammar:

T,T'::= 1 % Unit type | 0 % Empty type |a% Atom | nat % Natural numbers | bool % Booleans |Tlist % Lists of element typeT|T*T'% Product |T+T'% Disjoint sum |T->T'% Function space | (T) % Parentheses

``list'` is a postfix operator.

The binary operators ``*'`, ``+'` and ``=>'` are right
associative. Binding strength decreases
in this order:

list * + ->

We extend the grammar for *terms* by the following constructs:

M,N::= ... | 0 % Zero | sM% Successor | recMoff0 =>N|f(sx) =>Oend % Recursion over nat | true % True | false % False | ifMthenNelseO% Boolean case distinction | nil % Empty list |M::N% List construction | recMoffnil =>N|f(x::xs) =>Oend % Recursion over list

``0'`, ``true'`, ``false'` and ``nil'` are constants,
``s'` and ``if r then s else'` are prefix operators and

We add one new declaration to the syntax of tutch files:

D::= ... | valx:T=M% Program of typeTwith namexF::= % Empty file |D;F% Declaration and remaining file

Reasoning in First-Order Logic (FOL) requires handling of universally and existentially quantified propositions. New special symbols are

! ? .

We extend our definition of propositions by

A,B::= ... |RM1...Mn% Instantiation | !x:T.A% Universal quantification | ?x:T.A% Existential quantification

Relation symbols *R* are capital identifiers. Only they can be
instantiated by terms *Mi*, e.g. ``A(x)'`, which is the same as
``A x'`. Instantiation binds strongest, as strong as application and
the prefix operators for terms *M*.

Quantification ``! x:T'`
resp.

!x:T. resp. ?x:T., <=>, =>, |, &, ~, instantiation

The ``proof'` declaration supports now also proofs in FOL. Two
judgments can form a statement of the proof: an assertion *A*
(representing ``A true'` and a
term declaration *M : T* expressing "*M* has type
*T*". In the same way there are now two forms of hypotheses:
*x : T*, which introduces a new parameter *x* into the proof,
and *A* which assumes that *A* is true. Furthermore one frame
can introduce several hypotheses, separated by commas. The grammar for proofs
is the following:

H::=A% Hypothesis introduction |x : T% Parameter introductionHs::=H% Last hypothesis |H,Hs% Several hypothesesE::=A% Line: Assertion |M : T% Line: Term declaration | [Hs;P] % FrameP::=E% Final step |E;P% Step and remaining proof

All variables in a proposition that appears in a proof must be bound by quantifiers or be (visible) parameters introduced by frames.

We add the two binary relations "less than" and "equal to" to our definition of propositions

A,B::= ... |M<N%Mless thanN|M=N%Mequal toN

These relations allow us to prove properties about them and defined functions by induction.

Unfortunately, ``='` introduces a ambiguity into our syntax, e.g. in

proof Ex2 : !x:nat. 0 < x => ?y:nat. s(y) = x = ...

While parsing the first ``='`, it is not clear whether it marks the
end of the proposition or stands for the equality relation. This
ambiguity is resolved by the following rule:

Whenever the expression before

`='isdefinitivelya term, then`='is parsed as equality. In all other cases it is parsed as the end of the declaration.

In our case ``s(y)'` is definitively a term. At the next ``='`,
the expression on the left of it is ``s(y)=x'`, which is a
proposition, not a term. Thus the end of the declaration is correctly
recognized. The same happens in the following example:

val nth : nat -> tau list -> tau -> tau = ...

The expression ``tau'` left of the equality symbol is a variable. It
could be a term or a type variable. Thus it is not definitely a term,
and the parser finished parsing the type of ``nth'` here.

Not correctly resolved is the ambiguity in this case:

proof refl : !x:nat. x = x = ...

Since ``x'` is either a term variable or a type variable from the
perspective of mere syntax, it is not definitively a term. Thus the
parser detects falsely the end of the declaration of ``refl'`. The
parser will then try to interpret ``!x:nat.x'` as a proposition, and
fail with the following error message:

Category mismatch: x is a variable, but a proposition is expected in this place

To work around this bug, insert parentheses somewhere around the equality expression, e.g.

proof refl : !x:nat. (x = x) = ...

The introduction and elimination rules for equality and less-than give rise to the following proof terms. All are reserved words:

eq0 eqS eqE0S eqES0 eqESS less0 lessS lessE0 lessES

Of these, two are constants: `eq0` and `less0`. All other are prefix
operators.
For induction we reuse the ``rec'` construct for primitive recursion.

We reuse ``='` for equality on lists. The following proof terms
represent the introduction and elimination rules for equality on
lists. These are new reserved words:

eqN eqC eqENC eqECN eqECC

Except `eqN`, which is a constants, all are prefix operators. The rule
for `eqC` is:

If

M : xs = ys, thenfor an arbitraryeqCM : x::xs = x::ysx.

Here we assume that all these lists *xs, ys, x::xs, x::ys* are
well-formed and of the same type.

This sections summarizes the syntax specification given in the previous sections.

**Special Symbols:**

( ) [ ] ; : = ~ & | => <=> , * + -> :: ! ? . <

**Reserved words:**

annotated proof term val begin end T F nat bool list inl inr case of fst snd fn abort 0 s rec true false if then else nil eq0 eqS eqE0S eqES0 eqESS less0 lessS lessE0 lessES eqN eqC eqENC eqECN eqECC

**Proposition expressions:**

A,B::= T % Truth | F % Falsehood |Q% Atom | ~A% Negation |A&B% Conjunction |A|B% Disjunction |A=>B% Implication |A<=>B% Equivalence |RM1...Mn% Instantiation | !x:T.A% Universal quantification | ?x:T.A% Existential quantification |M<N%Mless thanN|M=N%Mequal toN

**Type expressions:**

T,T'::= 1 % Unit type | 0 % Empty type |a% Atom | nat % Natural numbers | bool % Booleans |Tlist % Lists of element typeT|T*T'% Product |T+T'% Disjoint sum |T->T'% Function space

**Terms:**

M,N::=x% Variable | (M,N) % Pair | fstM% First projection | sndM% Second projection | inlM% Left injection | inrM% Right injection | caseMof inlx=>N| inry=>Oend % Case analysis | fnx=>M% Abstraction |MN% Application | () % Empty tuple (proof of truth) | abortM% Falsehood elimination |M: A % Annotation | 0 % Zero | sM% Successor | recMoff0 =>N|f(sx) =>Oend % Recursion over nat | true % True | false % False | ifMthenNelseO% Boolean case distinction | nil % Empty list |M::N% List construction | recMoffnil =>N|f(x::xs) =>Oend % Recursion over list | eq0 % Proof of0 = 0| eqSM% Proof ofM = N|-s M = s N| eqE0SM% Elimination of0 = s N| eqES0M% Elimination ofs M = 0| eqESSM% Proof ofs M = s N|-M = N| less0M% Proof of0 < s M| lessSM% Proof ofM < N|-s M < s N| lessE0M% Elimination ofs M = 0| lessESM% Proof ofs M = s N|-M = N| eqN % Proof ofnil = nil| eqCM% Proof ofMs = Ns|-M::Ms = M::Ns| eqENCM% Elimination ofnil = M::Ms| eqECNM% Elimination ofM::Ms = nil| eqECCM% Proof ofM::Ms = N::Ns|-Ms = Ns

**Operator precedence:**

_ _ (application) list inl inr fst ... (all atomar prefix ops) :: if M then N else let (x,u) = M in fn x => < = ~ & * | + => -> <=> !x:t. ?x:t.

**Proofs:**

H::=A% Hypothesis introduction |x : T% Parameter introductionHs::=H% Last hypothesis |H,Hs% Several hypothesesE::=A% Line: Assertion |M : T% Line: Term declaration | [Hs;P] % FrameP::=E% Final step |E;P% Step and remaining proof

**Annotated Proofs:**

H::=x : A% HypothesisE::=M : A% Line | [H;P] % FrameP::=E% Final step |E;P% Step and remaining proof

**Declarations:**

D::= proofx:A= beginPend % Proof ofAwith namex| annotated proofx:A= beginPend % Annotated proof ofAwith namex| termx:A=M% Proof ofAwith namex| valx:T=M% Program of typeTwith namexF::= % Empty file |D;F% Declaration and remaining file

A requirements file *F* specifies proof and program tasks, but does
not give any proofs or implementations. Grammar:

S::= proofx:A% Proof specification | annotated proofx:A% Proof specification | termx:A% Term specification | valx:T% Program specificationF::= % Empty file |S;F% Specification and remaining file

We give an inductive definition of the proof checking algorithm
implemented in Tutch via two judgments ``step'` and ``valid'`.
The definition is given as in Twelf syntax.

% Tutch proof checker for propositional logic % any infinite datatype: nat : type. z : nat. s : nat -> nat. % Propositions prop : type. %name prop A. % Formation rules true : prop. false : prop. atom : nat -> prop. & : prop -> prop -> prop. %infix right 14 &. | : prop -> prop -> prop. %infix right 13 |. => : prop -> prop -> prop. %infix right 12 =>. % Notational definitions ~ : prop -> prop = [A:prop] (A => false). %prefix 15 ~. <=> : prop -> prop -> prop = [A:prop][B:prop] (A => B) & (B => A) . %infix none 11 <=>. % One-step inference algorithm step : prop -> type. nonhyp : prop -> type. % available non-hypothetical judgment hyp : prop -> prop -> type. % available hypothetical judgment % immediate tactic imm : nonhyp A -> step A. % introduction tactics trueI : step true. &I : nonhyp A -> nonhyp B -> step (A & B). |IL : nonhyp A -> step (A | B). |IR : nonhyp B -> step (A | B). =>I : hyp A B -> step (A => B). % elimination tactics falseE : nonhyp false -> step A. &EL : nonhyp (A & B) -> step A. &ER : nonhyp (A & B) -> step B. |E : nonhyp (A | B) -> hyp A C -> hyp B C -> step C. =>E : nonhyp (A => C) -> nonhyp A -> step C. % Proofs proof : type. %name proof P. final : prop -> proof. % P, Q ::= A line : prop -> proof -> proof. % | A; P frame : prop -> proof -> proof -> proof. % | [H; P]; Q % Proof checking valid : proof -> prop -> type. vfinal : step A -> valid (final A) A. vline : step A -> (nonhyp A -> valid P B) -> valid (line A P) B. vframe : (nonhyp H -> valid P A) -> (hyp H A -> valid Q B) -> valid (frame H P Q) B.

Here we give a new Twelf implementation of Tutch that includes proof terms. The definition and the typing rules are:

% Tutch proof checker for propositional logic % Version 0.2 proof terms % any infinite datatype: nat : type. z : nat. s : nat -> nat. % Propositions prop : type. %name prop A. % Formation rules true : prop. false : prop. atom : nat -> prop. & : prop -> prop -> prop. %infix right 14 &. | : prop -> prop -> prop. %infix right 13 |. => : prop -> prop -> prop. %infix right 12 =>. % Notational definitions ~ : prop -> prop = [A:prop] (A => false). %prefix 15 ~. <=> : prop -> prop -> prop = [A:prop][B:prop] (A => B) & (B => A) . %infix none 11 <=>. % Proof terms term : type. %name term M. fst : term -> term. snd : term -> term. , : term -> term -> term. %infix right 14 ,. inl : term -> term. inr : term -> term. case : term -> (term -> term) -> (term -> term) -> term. \ : (term -> term) -> term. %prefix 11 \. : term -> term -> term. %infix left 20 . <> : term. abort: term -> term. % Typing judgement in : term -> prop -> type. %infix none 0 in. % Typing rules &I : M in A -> N in B -> (M , N) in A & B. &EL : M in A & B -> fst M in A. &ER : M in A & B -> snd M in B. |IL : M in A -> inl M in A | B. |IR : M in B -> inr M in A | B. |E : M in A | B -> ({x: term} x in A -> N x in C) -> ({y: term} y in B -> L y in C) -> case M N L in C. =>I : ({x: term} x in A -> M x in B) -> \ M in A => B. =>E : M in A => B -> N in A -> M N in B. trueI : <> in true. falseE: M in false -> abort M in C.

We add *annotated proofs*, which need an inference algorithm that
respects proof terms:

% One-step inference algorithm step : term -> prop -> type. % %mode step +A. j0hyp : term -> prop -> type. % available non-hypothetical judgment j1hyp : (term -> term) -> prop -> prop -> type. % available hypothetical judgment % immediate tactic imm : j0hyp M A -> step M A. % introduction tactics bytrueI : step <> true. by&I : j0hyp M A -> j0hyp N B -> step (M , N) (A & B). by|IL : j0hyp M A -> step (inl M) (A | B). by|IR : j0hyp M B -> step (inr M) (A | B). by=>I : j1hyp M A B -> step (\ M) (A => B). % elimination tactics byfalseE : j0hyp M false -> step (abort M) A. by&EL : j0hyp M (A & B) -> step (fst M) A. by&ER : j0hyp M (A & B) -> step (snd M) B. by|E : j0hyp M (A | B) -> j1hyp N A C -> j1hyp L B C -> step (case M N L) C. by=>E : j0hyp M (A => C) -> j0hyp N A -> step (M N) C.

The checking of annotated proofs requires two judgments ``avalid1'`
and ``avalid2'`: The first returns a proof term and the second the
proven proposition.

% Annotated proofs aproof : type. %name aproof P. afinal : term -> prop -> aproof. % P ::= M : A aline : term -> prop -> aproof -> aproof. % | M : A; P aframe : prop -> (term -> aproof) -> aproof -> aproof. % | [x: H; P]; P' % Annotated proof checking avalid1 : aproof -> term -> type. % %mode avalid1 +P -M. avalid2 : aproof -> prop -> type. % %mode avalid2 +P -A. avfinal1 : step M A -> avalid1 (afinal M A) M. avfinal2 : step M A -> avalid2 (afinal M A) A. avline1 : step M A -> (j0hyp M A -> avalid1 P N) -> avalid1 (aline M A P) N. avline2 : step M A -> (j0hyp M A -> avalid2 P B) -> avalid2 (aline M A P) B. avframe1 : ({x:term} j0hyp x H -> avalid1 (P x) (M x)) -> ({x:term} j0hyp x H -> avalid2 (P x) A) -> (j1hyp M H A -> avalid1 Q N) -> avalid1 (aframe H P Q) N. avframe2 : ({x:term} j0hyp x H -> avalid1 (P x) (M x)) -> ({x:term} j0hyp x H -> avalid2 (P x) A) -> (j1hyp M H A -> avalid2 Q B) -> avalid2 (aframe H P Q) B.

Go to the first, previous, next, last section, table of contents.