% Formatting commands for Natural-Deduction inference rules
% Written by Rujith de Silva 93/01/31

% I've followed a consistent naming scheme, with all commands and parameters
% beginning with `nd'.  If this becomes intrusive and long-winded, the names
% may be changed or shortened.

% Given several premises above the inference line, the following specifies how
% much horizontal space to insert between them
\newdimen\ndgap \ndgap=25pt

% The following specifies how much horizontal space to leave between the
% inference line and the label giving the name of the inference rule.
\newdimen\ndlabelspace \ndlabelspace=2pt

% Because of the complex formatting involved, the commands need the size of
% the largest inference rule name that may occur.  The following sets it to a
% suitable value.
\newdimen\ndlargest \setbox0=\hbox {$\subset\hbox{E}_R$} \ndlargest =\wd0

% To follow the chosen naming scheme, I define the following operators.  The
% user need not use them, preferring to use \forall instead of \ndforall, for
% example.
\let\ndand=\wedge
\let\ndor=\vee
\let\ndnot=\neg
\let\ndimp=\supset
\let\ndeqv=\equiv
\let\ndtrue=\top
\let\ndfalse=\bot
\let\ndforall=\forall
\let\ndexists=\exists

% The following are the inference rules, grouped by function.  Their arguments
% consist of the premises above the inference rule, the conclusion, and the
% label of any hypothesis involved, if any.

% Firstly, the simplest inference rule: introduce a labelled assumption.  For
% example, to generate
%                         ----- u
%                         A v B
%
% use:  \ndlabel{A\ndor B}{u}
\def\ndlabel#1#2{\ndzero {\hbox {$\strut #1$}}{\hbox {\hskip \ndlabelspace
$\scriptstyle #2$}}}

% Then the rules involving conjunction: introduction, left elimination, and
% right elimination.
\def\ndandi#1#2#3{\ndtwo {\hbox {$\strut #1$}}{\hbox {$\strut #2$}}{\hbox
{$\strut #3$}}{\hbox {\hskip \ndlabelspace $\ndand \hbox{I}$}}}
\def\ndandel#1#2{\ndone {\hbox {$\strut #1$}}{\hbox {$\strut #2$}}{\hbox
{\hskip \ndlabelspace $\ndand \hbox {E}_L$}}}
\def\ndander#1#2{\ndone {\hbox {$\strut #1$}}{\hbox {$\strut #2$}}{\hbox
{\hskip \ndlabelspace $\ndand \hbox {E}_R$}}}

% The rules involving disjunction: left introduction, right introduction, and
% elimination.
\def\ndoril#1#2{\ndone {\hbox {$\strut #1$}}{\hbox {$\strut #2$}}{\hbox
{\hskip \ndlabelspace $\ndor \hbox{I}_L$}}}
\def\ndorir#1#2{\ndone {\hbox {$\strut #1$}}{\hbox {$\strut #2$}}{\hbox
{\hskip \ndlabelspace $\ndor \hbox{I}_R$}}}
\def\ndore#1#2#3#4#5{\ndthree {\hbox {$\strut #1$}}{\hbox {$\strut #2$}}{\hbox
{$\strut #3$}}{\hbox {$\strut #4$}}{\hbox {\hskip \ndlabelspace $\ndor \hbox
{E}^{#5}$}}}

% Implication introduction and elimination
\def\ndimpi#1#2#3{\ndone {\hbox {$\strut #1$}}{\hbox {$\strut #2$}}{\hbox
{\hskip \ndlabelspace $\ndimp \hbox {I}^{#3}$}}}
\def\ndimpe#1#2#3{\ndtwo {\hbox {$\strut #1$}}{\hbox {$\strut #2$}}{\hbox
{$\strut #3$}}{\hbox {\hskip \ndlabelspace $\ndimp \hbox{E}$}}}

% Negation introduction and elimination
\def\ndnoti#1#2#3{\ndone {\hbox {$\strut #1$}}{\hbox {$\strut #2$}}{\hbox
{\hskip \ndlabelspace $\ndnot \hbox {I}^{#3}$}}}
\def\ndnote#1#2#3{\ndtwo {\hbox {$\strut #1$}}{\hbox {$\strut #2$}}{\hbox
{$\strut #3$}}{\hbox {\hskip \ndlabelspace $\ndnot \hbox{E}$}}}

% Truth introduction
\def\ndtruei{\ndzero {\hbox {$\strut \ndtrue $}}{\hbox {\hskip \ndlabelspace
$\ndtrue \hbox{I}$}}}

% Falsity elimination
\def\ndfalsee#1#2{\ndone {\hbox {$\strut #1$}}{\hbox {$\strut #2$}}{\hbox
{\hskip \ndlabelspace $\ndfalse \hbox{E}$}}}

% Universal quantification: introduction and elimination
\def\ndforalli#1#2#3{\ndone {\hbox {$\strut #1$}}{\hbox {$\strut #2$}}{\hbox
{\hskip \ndlabelspace $\ndforall \hbox{I}^{#3}$}}}
\def\ndforalle#1#2{\ndone {\hbox {$\strut #1$}}{\hbox {$\strut #2$}}{\hbox
{\hskip \ndlabelspace $\ndforall \hbox{E}$}}}

% Existential quantification: introduction and elimination
\def\ndexistsi#1#2{\ndone {\hbox {$\strut #1$}}{\hbox {$\strut #2$}}{\hbox
{\hskip \ndlabelspace $\ndexists \hbox{I}$}}}
\def\ndexistse#1#2#3#4{\ndtwo {\hbox {$\strut #1$}}{\hbox {$\strut #2$}}{\hbox
{$\strut #3$}}{\hbox {\hskip \ndlabelspace $\ndexists \hbox{E}^{#4}$}}}

% The classical rules of logic: Proof by Contradiction, Double Negation, and
% Excluded Middle:
\def\ndcontr#1#2#3{\ndone {\hbox {$\strut #1$}}{\hbox {$\strut #2$}}{\hbox
{\hskip \ndlabelspace $\ndfalse_C^{#3}$}}}
\def\ndnotnot#1#2{\ndone {\hbox {$\strut #1$}}{\hbox {$\strut #2$}}{\hbox
{\hskip \ndlabelspace $\ndnot \ndnot_C$}}}
\def\ndxm#1{\ndzero {\hbox{$\strut #1$}}{\hbox {\hskip \ndlabelspace XM}}}

% Other inference rules can be easily defined in the above style.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Now the actual formatting commands.  The user should not need to understand
% or change these.

\newdimen\ndlbs\newdimen\ndrbs \newdimen\ndts \newdimen\ndlinebeg
\newdimen\ndlineend \newdimen\ndtemp \newbox\ndtempbox \newbox\ndl \newbox\ndm
\newbox\ndr \newbox\ndb \newcount\ndmode \ndmode=0

\def\ndzero#1#2{\ifcase\ndmode \vcenter{\hbox {{\ndmode =1 \ndone
{#1}{#2}}\hskip \ndlargest }}\else \setbox \ndb =\vbox {#1}\vbox
{\offinterlineskip \halign to \wd \ndb {\hfil ##\hfil \cr \noalign {\vbox
{\hbox {\vrule height 0.5pt width \wd \ndb \vbox to 0pt{\vss \hbox to 0pt
{#2\hss }\vss }}}}\box \ndb \cr}}\fi}

\def\ndone#1#2#3{\ifcase\ndmode \vcenter{\hbox{{\ndmode =1 \ndone
{#1}{#2}{#3}}\hskip \ndlargest }}\or {{\ndmode =2 \global \setbox \ndtempbox
=\vbox {#1}}\ndlbs =\wd \ndtempbox \setbox \ndl =\vbox{#1}\setbox \ndb
=\vbox{#2}\ndts =\wd \ndl \ifdim \ndts <\wd \ndb \ndts =\wd \ndb \vbox
{\offinterlineskip \halign to\ndts {\hfil ##\hfil \cr \box\ndl\cr \noalign
{\vbox {\hbox {\vrule height 0.5pt width\ndts \vbox to 0pt{\vss \hbox to
0pt{#3\hss}\vss}}}} \box \ndb \cr}}\else \ndlinebeg =\wd \ndl \advance
\ndlinebeg by -\ndlbs \divide \ndlinebeg by 2 \ndlineend =\wd\ndl \advance
\ndlineend by \ndlbs \divide \ndlineend by 2 \ndtemp=\ndts \advance \ndtemp by
-\wd \ndb \divide \ndtemp by 2 \ifdim \ndtemp <\ndlinebeg \ndlinebeg =\ndtemp
\fi \ndtemp =\ndts \advance \ndtemp by \wd \ndb \divide \ndtemp by 2 \ifdim
\ndtemp >\ndlineend \ndlineend =\ndtemp \fi \ndtemp =\ndlineend \advance
\ndtemp by -\ndlinebeg \vbox {\offinterlineskip \halign to\ndts {\hfil
##\hfil\cr \box\ndl \cr \noalign {\vbox {\hbox {\hskip \ndlinebeg \vrule
height 0.5pt width \ndtemp \vbox to 0pt{\vss \hbox to 0pt{#3\hss}\vss}}}}
\box\ndb \cr}}\fi }\or #2\fi}

\def\ndtwo#1#2#3#4{\ifcase \ndmode \vcenter {\hbox {{\ndmode =1 \ndtwo
{#1}{#2}{#3}{#4}}\hskip \ndlargest }}\or {{\ndmode =2 \global \setbox
\ndtempbox =\vbox {#1}}\ndlbs =\wd \ndtempbox {\ndmode =2 \global \setbox
\ndtempbox =\vbox {#2}}\ndrbs =\wd \ndtempbox \setbox \ndl =\vbox {#1}\setbox
\ndr =\vbox {#2}\setbox \ndb =\vbox {#3}\ndts =\wd \ndl \advance \ndts by \wd
\ndr \advance \ndts by \ndgap \ifdim \ndts <\wd \ndb \ndts =\wd \ndb \vbox
{\offinterlineskip \halign to \ndts {\hfil ##\hfil \cr \box \ndl \hskip \ndgap
\box \ndr \cr \noalign {\vbox {\hbox {\vrule height 0.5pt width \ndts \vbox to
0pt{\vss \hbox to 0pt{#4\hss }\vss }}}}\box \ndb \cr }}\else \ndlinebeg =\wd
\ndl \advance \ndlinebeg by -\ndlbs \divide \ndlinebeg by 2 \ndlineend =-\wd
\ndr \advance \ndlineend by \ndrbs \divide \ndlineend by 2 \advance \ndlineend
by \ndts \ndtemp =\ndts \advance \ndtemp by -\wd \ndb \divide \ndtemp by 2
\ifdim \ndtemp <\ndlinebeg \ndlinebeg =\ndtemp \fi \ndtemp =\ndts \advance
\ndtemp by \wd \ndb \divide \ndtemp by 2 \ifdim \ndtemp >\ndlineend \ndlineend
=\ndtemp \fi \ndtemp =\ndlineend \advance \ndtemp by -\ndlinebeg
\vbox {\offinterlineskip \halign to \ndts {\hfil ##\hfil \cr \box \ndl \hskip
\ndgap \box \ndr \cr \noalign {\vbox {\hbox {\hskip \ndlinebeg \vrule height
0.5pt width \ndtemp \vbox to 0pt{\vss \hbox to 0pt{#4\hss }\vss }}}}\box \ndb
\cr }}\fi }\or #3\fi}

\def\ndthree#1#2#3#4#5{\ifcase \ndmode \vcenter {\hbox {{\ndmode =1 \ndthree
{#1}{#2}{#3}{#4}{#5}}\hskip \ndlargest }}\or {{\ndmode =2 \global \setbox
\ndtempbox =\vbox {#1}}\ndlbs = \wd \ndtempbox {\ndmode =2 \global \setbox
\ndtempbox =\vbox {#3}}\ndrbs =\wd \ndtempbox \setbox \ndl =\vbox {#1}\setbox
\ndm =\vbox {#2}\setbox \ndr =\vbox {#3}\setbox \ndb =\vbox {#4}\ndts = \wd
\ndl \advance \ndts by \wd \ndm \advance \ndts by \wd \ndr \advance \ndts by
2\ndgap \ifdim \ndts <\wd \ndb \ndts = \wd \ndb \vbox {\offinterlineskip
\halign to \ndts {\hfil ##\hfil \cr \box \ndl \hskip \ndgap \box \ndm \hskip
\ndgap \box \ndr \cr \noalign {\vbox {\hbox {\vrule height 0.5 pt width \ndts
\vbox to 0pt{\vss \hbox to 0pt{#5\hss }\vss }}}}\box \ndb \cr }}\else
\ndlinebeg =\wd \ndl \advance \ndlinebeg by -\ndlbs \divide \ndlinebeg by 2
\ndlineend =-\wd \ndr \advance \ndlineend by \ndrbs \divide \ndlineend by 2
\advance \ndlineend by \ndts \ndtemp =\ndts \advance \ndtemp by -\wd \ndb
\divide \ndtemp by 2 \ifdim \ndtemp <\ndlinebeg \ndlinebeg =\ndtemp \fi
\ndtemp =\ndts \advance \ndtemp by \wd \ndb \divide \ndtemp by 2 \ifdim
\ndtemp >\ndlineend \ndlineend =\ndtemp \fi \ndtemp =\ndlineend \advance
\ndtemp by -\ndlinebeg \vbox {\offinterlineskip \halign to \ndts {\hfil
##\hfil \cr \box \ndl \hskip \ndgap \box \ndm \hskip \ndgap \box \ndr \cr
\noalign {\vbox {\hbox {\hskip \ndlinebeg \vrule height 0.5pt width \ndtemp
\vbox to 0pt{\vss \hbox to 0pt{#5\hss }\vss }}}}\box \ndb \cr }}\fi }\or #4\fi
}
