diff options
Diffstat (limited to 'Master/texmf-dist/source/latex/stex/presentation/presentation.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/stex/presentation/presentation.dtx | 1368 |
1 files changed, 1368 insertions, 0 deletions
diff --git a/Master/texmf-dist/source/latex/stex/presentation/presentation.dtx b/Master/texmf-dist/source/latex/stex/presentation/presentation.dtx new file mode 100644 index 00000000000..57e2352ede5 --- /dev/null +++ b/Master/texmf-dist/source/latex/stex/presentation/presentation.dtx @@ -0,0 +1,1368 @@ +% \iffalse meta-comment +% An Infrastructure for Presenting Semantic Macros in sTeX +% Copyright (C) 2004-2007 Michael Kohlhase, all rights reserved +% This file is released under the LaTeX Project Public License (LPPL) +% +% The development version of this file can be found at +% $HeadURL: https://svn.kwarc.info/repos/stex/trunk/sty/presentation/presentation.dtx $ +% \fi +% +% \iffalse +%<package>\NeedsTeXFormat{LaTeX2e}[1999/12/01] +%<package>\ProvidesPackage{presentation}[2010/06/25 v1.0 presentation for semantic macros] +% +%<*driver> +\documentclass{ltxdoc} +\usepackage{url,array,presentation,float,stex-logo} +\usepackage[show]{ed} +\usepackage[hyperref=auto,style=alphabetic]{biblatex} +\bibliography{kwarc} +\usepackage{../ctansvn} +\usepackage{hyperref} +\usepackage[eso-foot,today]{svninfo} +\svnInfo $Id: presentation.dtx 1502 2010-07-20 08:17:00Z kohlhase $ +\svnKeyword $HeadURL: https://svn.kwarc.info/repos/stex/trunk/sty/presentation/presentation.dtx $ +\makeindex +\floatstyle{boxed} +\newfloat{exfig}{thp}{lop} +\floatname{exfig}{Example} +\begin{document}\DocInput{presentation.dtx}\end{document} +%</driver> +% \fi +% +% \CheckSum{557} +% +% \changes{v0.9}{2005/06/14}{First Version with Documentation} +% \changes{v0.9a}{2005/07/01}{Completed Documentation} +% \changes{v0.9b}{2005/08/06}{Complete functionality and Updated Documentation} +% \changes{v0.9c}{2006/01/13}{more packaging} +% \changes{v0.9d}{2006/10/13}{adding mixfix declarations} +% \changes{v0.9d}{2006/10/13}{dealing with precedences in keyword arguments} +% \changes{v0.9e}{2007/09/03}{fixing argument precedences, adding LaTeXML bindings} +% \changes{v0.9f}{2007/12/09}{adding general elision} +% \changes{v0.9g}{2008/06/17}{getting the LaTeXML right} +% \changes{v0.9h}{2009/02/27}{turning the precedence order around to make this compatible +% with the latest OMDoc, change all precedences $n$ to $1000-n$} +% \changes{v0.9h}{2009/07/30}{adding brackets to the generated notation elements} +% \changes{v0.9h}{2010/06/18}{considering done now} +% \GetFileInfo{presentation.sty} +% +% \MakeShortVerb{\|} +%\def\scsys#1{{{\sc #1}}\index{#1@{\sc #1}}} +% \def\xml{\scsys{Xml}} +% \def\mathml{\scsys{MathML}} +% \def\omdoc{\scsys{OMDoc}} +% \def\openmath{\scsys{OpenMath}} +% \def\latexml{\scsys{LaTeXML}} +% \def\perl{\scsys{Perl}} +% \def\cmathml{Content-{\sc MathML}\index{Content {\sc MathML}}\index{MathML@{\sc MathML}!content}} +% \def\activemath{\scsys{ActiveMath}} +% \def\twin#1#2{\index{#1!#2}\index{#2!#1}} +% \def\twintoo#1#2{{#1 #2}\twin{#1}{#2}} +% \def\atwin#1#2#3{\index{#1!#2!#3}\index{#3!#2 (#1)}} +% \def\atwintoo#1#2#3{{#1 #2 #3}\atwin{#1}{#2}{#3}} +% \title{{\texttt{presentation.sty}}: An Infrastructure for Presenting Semantic +% Macros in {\stex}\thanks{Version {\fileversion} (last revised {\filedate})}} +% \author{Michael Kohlhase \& Deyan Ginev\\ +% Jacobs University, Bremen\\ +% \url{http://kwarc.info/kohlhase}} +% \date{\today} +% \maketitle +% +% \begin{abstract} +% The |presentation| package is a central part of the {\stex} collection, a version of +% {\TeX/\LaTeX} that allows to markup {\TeX/\LaTeX} documents semantically without +% leaving the document format, essentially turning {\TeX/\LaTeX} into a document format +% for mathematical knowledge management (MKM). +% +% This package supplies an infrastructure that allows to specify the presentation of +% semantic macros, including preference-based bracket elision. This allows to markup the +% functional structure of mathematical formulae without having to lose high-quality +% human-oriented presentation in {\LaTeX}. Moreover, the notation definitions can be +% used by MKM systems for added-value services, either directly from the {\sTeX} +% sources, or after translation. +% \end{abstract} +% +% \setcounter{tocdepth}{2}\tableofcontents\newpage +% +%\section{Introduction}\label{sec:presentation} +% +% The |presentation| package supplies an infrastructure that allows to specify the +% presentation of semantic macros, including preference-based bracket elision. This allows +% to markup the functional structure of mathematical formulae without having to lose +% high-quality human-oriented presentation in {\LaTeX}. Moreover, the notation definitions +% can be used by MKM systems for added-value services, either directly from the {\sTeX} +% sources, or after translation. +% +% {\stex} is a version of {\TeX/\LaTeX} that allows to markup {\TeX/\LaTeX} documents +% semantically without leaving the document format, essentially turning {\TeX/\LaTeX} into +% a document format for mathematical knowledge management (MKM). +% +% The setup for semantic macros described in the {\stex} |modules| package works well for +% simple mathematical functions: we make use of the macro application syntax in {\TeX} to +% express function application. For a simple function called ``foo'', we would just +% declare |\symdef{foo}[1]{foo(#1)}| and have the concise and intuitive syntax |\foo{x}| +% for $foo(x)$. But mathematical notation is much more varied and interesting than just +% this. +% +% \section{The User Interface}\label{sec:user} +% +% In this package we will follow the {\sTeX} approach and assume that there are four basic +% types of mathematical expressions: symbols, variables, applications and +% binders. Presentation of the variables is relatively straightforward, so we will not +% concern ourselves with that. The application of functions in mathematics is mostly +% presented in the form $f(a_1,\ldots,a_n)$, where $f$ is the function and the $a_i$ are +% the arguments. However, many commonly-used functions from this presentational scheme: +% for instance binomial coefficients: $\bigl({n\atop k}\bigr)$, pairs: $\langle +% a,b\rangle$, sets: $\{x\in S\,\vert\, x^2\ne0\}$, or even simple addition: $3+5+7$. Note +% that in all these cases, the presentation is determined by the (functional) head of the +% expression, so we will bind the presentational infrastructure to the operator. +% +% \subsection{Prefix \& Postfix Notations}\label{sec:prepostfix} +% +% The default notation for an object that is obtained by applying a function $f$ to +% arguments $a_1$ to $a_n$ is $f(a_1,\ldots,a_n)$. The \DescribeMacro{\prefix}|\prefix| +% macro allows to specify a prefix presentation for a function (the usual presentation in +% mathematics). Note that it is better to specify |\symdef{uminus}[1]{\prefix{-}{#1}}| +% than just |\symdef{uminus}[1]{-#1}|, since we can specify the bracketing behavior in the +% former (see Section~\ref{sec:elision}). +% +% The \DescribeMacro{\postfix}|\postfix| macro is similar, only that the function is +% presented after the argument as for e.g. the factorial function: $5!$ stands for the +% result of applying the factorial function to the number 5. Note that the function is +% still the first argument to the |\postfix| macro: we would specify the presentation for +% the factorial function with |\symdef{factorial}[1]{\postfix{!}{#1}}|. +% +% |\prefix| and |\postfix| have $n$-ary variants \DescribeMacro{\prefixa}|\prefixa| and +% \DescribeMacro{\postfixa}|\postfixa| that take an arbitrary number of arguments +% (mathematically; syntactically grouped into one {\TeX} argument). These take an extra +% separator argument.\ednote{think of a good example!} +% +% \subsection{Mixfix Notations}\label{sec:mixfix} +% +% For the presentation of more complex operators, we will follow the approach used by the +% Isabelle theorem prover. There, the presentation of an $n$-ary function (i.e. one that +% takes $n$ arguments) is specified as +% \meta{pre}\meta{arg$_0$}\meta{mid$_1$}$\cdots$\meta{mid$_n$}\meta{arg$_n$}\meta{post}, +% where the \meta{arg$_i$} are the arguments and \meta{pre}, \meta{post}, and the +% \meta{mid$_i$} are presentational material. For instance, in infix operators like the +% binary subset operator, \meta{pre} and $\meta{post}$ are empty, and \meta{mid$_1$} is +% $\subseteq$. For the ternary conditional operator in a programming language, we might +% have the presentation pattern +% |if|\meta{arg$_1$}|then|\meta{arg$_2$}|else|\meta{arg$_3$}|fi| that utilizes all +% presentation positions. +% +% \DescribeMacro{\mixfix*}The |presentation| package provides mixfix declaration macros +% |\mixfixi|, |\mixfixii|, and |\mixfixiii| for unary, binary, and ternary functions. This +% covers most of the cases, larger arities would need a different argument +% pattern.\footnote{If you really need larger arities, contact the author!} The call +% pattern of these macros is just the presentation pattern above. In general, the mixfix +% declaration of arity $i$ has $2n+1$ arguments, where the even-numbered ones are for the +% arguments of the functions and the odd-numbered ones are for presentation material. For +% instance, to define a semantic macro for the subset relation and the conditional, we +% would use the markup in Figure~\ref{fig:mixfix}. +% \begin{exfig} +% \begin{verbatim} +% \symdef{sseteq}[2]{\mixfixii{}{#1}{\subseteq}{#2}{}} +% \symdef{sseteq}[2]{\infix\subseteq{#1}{#2}} +% \symdef{ite}[2]{\mixfixiii{{\tt{if}}\;}{#1} +% {\;{\tt{then}}\;}{#2} +% {\;{\tt{else}}\;}{#3}{\;{\tt{fi}}}} +% \end{verbatim} +% \vspace*{-1.5em} +% \begin{center} +% \begin{tabular}{|l|l|}\hline +% source & presentation \\\hline +% |\sseteq{S}T| & $(S\subseteq T)$\\\hline +% |\ite{x<0}{-x}x| & ${\tt{if}}\,x<0\,{\tt{then}}\,-x\,{\tt{else}}\,x\,{\tt{fi}}$\\\hline +% \end{tabular} +% \end{center} +% \caption{Declaration of mixfix operators}\label{fig:mixfix} +% \end{exfig} +% +% For certain common cases, the |presentation| package provides shortcuts for the mixfix +% declarations. For instance, we provide the \DescribeMacro{\infix}|\infix| macro for +% binary operators that are written between their arguments (see Figure~\ref{fig:mixfix}).\ednote{really?} +% +% \subsection{\texorpdfstring{$n$}{n}-ary Associative Operators}\label{sec:assoc} +% +% Take for instance the operator for set union: formally, it is a binary function on +% sets that is associative (i.e. $(S_1\cup S_2)\cup S_3=S_1\cup (S_2\cup S_3)$), therefore +% the brackets are often elided, and we write $S_1\cup S_2\cup S_3$ instead (once we have +% proven associativity). Some authors even go so far to introduce set union as a $n$-ary +% operator, i.e. a function that takes an arbitrary (positive) number of arguments. We will +% call such operators {\bf{$n$-ary +% associative}\atwin{n-ary}{associative}{operator}}. +% +% Specifying the presentation\ednote{introduce the notion of presentation above} of +% $n$-ary associative operators in |\symdef| forms is not straightforward, so we provide +% some infrastructure for that. As we cannot predict the number of arguments for $n$-ary +% operators, we have to give them all at once, if we want to maintain our use of {\TeX} +% macro application to specify function application. So a semantic macro for an $n$-ary +% operator will be applied as |\nunion{|\meta{$a_1$}|,|\ldots|,|\meta{$a_n$}|}|, where the +% sequence of $n$ logical arguments \meta{$a_i$} are supplied as one {\TeX} argument which +% contains a comma-separated list. We provide variants of the mixfix declarations +% presented in section~\ref{sec:mixfix} which deal with associative arguments. For +% instance, the variant \DescribeMacro{\mixfixa}|\mixfixa| allows to specify $n$-ary +% associative operators. +% |\mixfixa{|\meta{pre}|}{|\meta{arg}|}{|\meta{post}|}{|\meta{op}|}| specifies a +% presentation, where \meta{arg} is the associative argument and \meta{op} is the +% corresponding operator that is mapped over the argument list; as above, {\meta{pre}}, +% \meta{post}, are prefix and postfix presentational material. For instance, the finite +% set constructor could be constructed as +% \begin{verbatim} +% \newcommand{\fset}[1]{\mixfixa[p=1000]{\{}{#1}{\}}{,}} +% \end{verbatim} +% +% The \DescribeMacro{\assoc}|\assoc| macro is a convenient abbreviation of a |\mixfixa| +% that can be used in cases, where \meta{pre} and \meta{post} are empty (i.e. in the +% majority of cases). It takes two arguments: the presentation of a binary operator, and a +% comma-separated list of arguments, it replaces the commas in the second argument with +% the operator in the first one. For instance |\assoc\cup{S_1,S_2,S_3}| will be formatted +% to $S_1\cup S_2\cup S_3$. Thus we can use |\def\nunion#1{\assoc\cup{#1}}| or even +% |\def\nunion{\assoc\cup}|, to define the $n$-ary operator for set union in {\TeX}. For +% the definition of a semantic macro in {\stex}, we use the second form, since we are more +% conscious of the right number of arguments and would declare +% |\symdef{nunion}[1]{\assoc\cup{#1}}|.\ednote{think about big operators for ACI +% functions} +% +% The |\mixfixii| macro has variants \DescribeMacro{\mixfixia}|\mixfixia| and +% \DescribeMacro{\mixfixai}|\mixfixai| which allow to make one or two arguments in a +% binary function associative. A use case for the second macro is an nary function type +% operator |\fntype|, which can be defined via +% \begin{verbatim} +% \def\fntype#1#2{\mixfixai{}{#1}\rightarrow{#2}{}\times} +% \end{verbatim} +% \def\fntype#1#2{\mixfixai{}{#1}\rightarrow{#2}{}\times} +% and which will format |\fntype{\alpha,\beta,\gamma}\delta| as +% $\fntype{\alpha,\beta,\gamma}\delta$ +% +% Finally, the |\mixfixiii| macro has the variants |\mixfixaii|, |\mixfixiai|, and +% |\mixfixiia| as above\footnote{If you really need larger arities with associative +% arguments, contact the package author!}. For instance we can use the first variant for +% a typing judgment using +% \begin{verbatim} +% \def\typej#1#2#3{\mixfixaii{}{#1}{\vdash_{\Sigma}}{#2}\colon{#3}{}{,}} +% \end{verbatim} +% \def\typej#1#2#3{\mixfixaii{}{#1}{\vdash_{\Sigma}}{#2}\colon{#3}{}{,}} +% which formats |\typej{\Gamma,[x:\alpha],[y:\beta]}{f(x,y)}{\beta}| as +% \[\typej{\Gamma,[x:\alpha],[y:\beta]}{f(x,y)}{\beta}.\] +% +% \subsection{Precedence-Based Bracket Elision}\label{sec:elision} +% +% In the infrastructure discussed above, we have completely ignored the fact that we use +% brackets to disambiguate the formula structure. The general baseline rule here is that +% we enclose any presented subformula with (round) brackets to mark it as a logical unit. +% If we applied this to the following formula that combines set union and set intersection +% \begin{equation}\label{cupcap} +% |\nunion{\ninters{a,b},\ninters{c,d}}| +% \end{equation} +% this would yield $((a\cap b)\cup (c\cap d))$, and not $a\cap b\cup c\cap d$ as we are +% used to. In mathematics, brackets are elided, whenever the author anticipates that the +% reader can understand the formula without them, and would be overwhelmed with them. To +% achieve this, there are set of common conventions that govern bracket elision --- +% ``$\cap$ binds stronger than $\cup$'' in (\ref{cupcap}). The most common is to assign +% precedences to all operators, and elide brackets, if the {\index*{precedence}} of the +% operator is larger than that of the context it is presented in (or equivalently: we only +% write brackets, if the operator precedence is smaller or equal to the context +% precedence). Note that this is more selective that simply dropping outer brackets which +% would yield $a\cap b\cup c\cap d$ for (\ref{capcup}), where we would have liked $(a\cup +% b)\cap(c\cup d)$ +% \begin{equation}\label{capcup} +% |\ninters{\nunion{a,b},\nunion{c,d}}| +% \end{equation} +% In our example above, we would assign $\cap$ a larger precedence than $\cup$ (and both a +% larger precedence than the initial precedence to avoid outer brackets). To compute the +% presentation of (\ref{capcup}) we start out with the |\ninters|, elide its brackets +% (since the precedence $n$ of $\cup$ is larger than the initial precedence $i$), and set +% the context precedence for the arguments to $n$. When we present the arguments, we +% present the brackets, since the precedence of |nunion| is larger than the context +% precedence $n$. +% +% This algorithm --- which we call {\textbf{precedence-based bracket elision}} --- goes a +% long way towards approximating mathematical practice. Note that full bracket elision in +% mathematical practice is a reader-oriented process, it cannot be fully mechanical, +% e.g. in $(a\cap b\cap c\cap d\cap e\cap f\cap g)\cup h$ we better put the brackets +% around the septary intersection to help the reader even though they could have been +% elided by our algorithm. Therefore, the author has to retain full control\ednote{think +% about how to implement that. We need a way to override precedences locally} over +% bracketing in a bracket elision architecture. Otherwise it would become impossible to +% explain the concept of associativity in $(a\circ b)\circ c =a\circ(b\circ c)$, where we +% need the brackets for this one time on an otherwise associative operation $\circ$. +% +% \begin{figure}[htb] +% \begin{center} +% \begin{tabular}{|l|l|l|}\hline +% Precedence & Operators & Comment\\\hline\hline +% 800 & +,- & unary \\\hline +% 800 & $\hat{}$ & exponentiation \\\hline +% 600 & $*,\land,\cap$ & multiplicative \\\hline +% 500 & $+,-,\lor,\cup$ & additive\\\hline +% 400 & / & fraction \\\hline +% 300 & $=, \ne, \leq, <, >, \geq$ & relation\\\hline +% \end{tabular} +% \end{center}\vspace*{-1em} +% \caption{Common Operator Precedences}\label{fig:precedence} +% \end{figure} +% +% Furthermore, we supply an optional keyval arguments to the mixfix declarations and their +% abbreviations that allow to specify precedences: The key \DescribeMacro{p}|p| key is +% used to specify the {\bf{operator precedence}}, and the keys +% \DescribeMacro{pi}\DescribeMacro{pii}\DescribeMacro{piii}|p|\meta{i} can be used to +% specify the {\bf{argument precedence}s}. The latter will set the precedence level while +% processing the arguments, while the operator precedence invokes brackets, if it is +% smaller than the current precedence level --- which is set by the appropriate argument +% precedence by the dominating operators or the outer precedence. The values of the +% precedence keys can be integers or \DescribeMacro{\iprec}|\iprec| for the infinitely +% large precedence or \DescribeMacro{\niprec}|\niprec| for the infinitely small +% precedence. +% +% If none of the precedences is specified, then the defaults are assumed. The operator +% precedence is set to the default operator precedence, which defaults to 0. The argument +% precedences default to the operator precedence. +% +% Figure~\ref{fig:precedence} gives an overview over commonly used precedences. Note that +% most operators have precedences higher than the default precedence of 0, otherwise the +% brackets would not be elided. For our examples above, we would define +% \begin{verbatim} +% \newcommand{\nunion}[1]{\assoc[p=500]{\cup}{#1}} +% \newcommand{\ninters}[1]{\assoc[p=600]{\cap}{#1}} +% \end{verbatim} +% to get the desired behavior. +% +% Note that the presentation macros uses round brackets for grouping by default. We can +% specify other brackets via two more keywords: \DescribeMacro{lbrack}|lbrack| and +% \DescribeMacro{rbrack}|rbrack|. +% +% Note that formula parts that look like brackets usually are not. For instance, we should +% not define the finite set constructor via +% \begin{equation}\label{wrongset} +% |\newcommand{\fset}[1]{\assoc[lbrack=\{,rbrack=\}]{,}{#1}}| +% \end{equation} +% where the curly braces are used as brackets, but as presented in section~\ref{sec:assoc} +% even though both would format |\fset{a,b,c}| as $\{a,b,c\}$. In the encoding here, an +% operator with suitably high operator precedence (it is the best practice u)would be able +% to make the brackets disappear. Thus the correct version of (\ref{wrongset}) is +% \begin{equation}\label{goodset} +% |\newcommand{\fset}[1]{\mixfixa[p=\iprec,pi=0]{\{}{#1}{\}}{,}}| +% \end{equation} +% Note that |\prefix| and |\postfix| and their variants declared in +% section~\ref{sec:prepostfix} have brackets that do not participate (actively) in the +% precedence-based elision: function application brackets are not subject to elision. But +% the operator precedence |p| is still taken into account for outer brackets. The argument +% precedence |pi| has negative infinity as a default to avoid spurious brackets for +% arguments. +% +% \subsection{Flexible Elision}\label{sec:flexible-elision} +% +% There are several situations in which it is desirable to display only some parts of the +% presentation: +% \begin{itemize} +% \item We have already seen the case of redundant brackets above +% \item Arguments that are strictly necessary are omitted to simplify the notation, and the +% reader is trusted to fill them in from the context. +% \item Arguments are omitted because they have default values. For example $\log_{10}x$ +% is often written as $\log x$. +% \item Arguments whose values can be inferred from the other arguments are usually +% omitted. For example, matrix multiplication formally takes five arguments, namely the +% dimensions of the multiplied matrices and the matrices themselves, but only the latter +% two are displayed. +% \end{itemize} +% +% Typically, these elisions are confusing for readers who are getting acquainted with a +% topic, but become more and more helpful as the reader advances. For experienced readers +% more is elided to focus on relevant material, for beginners representations are more +% explicit. In the process of writing a mathematical document for traditional (print) +% media, an author has to decide on the intended audience and design the level of elision +% (which need not be constant over the document though). With electronic media we have new +% possibilities: we can make elisions flexible. The author still chooses the elision level +% for the initial presentation, but the reader can adapt it to her level of competence and +% comfort, making details more or less explicit. +% +% To provide this functionality, the |presentation| package provides the +% \DescribeMacro{\elide}|\elide| macro allows to associate a text with an integer +% {\textbf{visibility level}} and group them into {\textbf{elision groups}}. High levels +% mean high elidability. +% +% Elision can take various forms in print and digital media. In static media like +% traditional print on paper or the PostScript format, we have to fix the elision level, +% and can decide at presentation time which elidable tokens will be printed and which will +% not. In this case, the presentation algorithm will take visibility thresholds $T_g$ for +% every elidability group $g$ as a user parameter and then elide (i.e. not print) all +% tokens in visibility group $g$ with level $l>T_g$. We specify this threshold for via the +% \DescribeMacro{\setegroup}|\setegroup| macro. For instance in the example below, we have +% a two type annotations |par| for type parameters and |typ| for type annotations +% themselves. +% +% \begin{exfig}[ht] +% \begin{verbatim} +% $\mathbf{I}\elide{par}{500}{^\alpha}\elide{typ}{100}{_{\alpha\to\alpha}} +% :=\lambda{X\elide{typ}{500}{_\alpha}}.X$ +% \end{verbatim}\vspace*{-2em} +% \caption{Elision with Elision Groups}\label{ex:elision} +% \end{exfig} +% +% The visibility levels in the example encode how redundant the author thinks the elided +% parts of the formula are: low values show high redundancy. In our example the intuition +% is that the type parameter on the $\mathbf{I}$ combinator and the type annotation on the +% bound variable $X$ in the $\lambda$ expression are of the same obviousness to the +% reader. So in a document that contains |\setegroup{typ}{0}| and |\setegroup{par}{0}| +% Figure~\ref{ex:elision} will show $\mathbf{I}:=\lambda{X}.X$ eliding all redundant +% information. If we have both values at 600, then we will see +% $\mathbf{I}^\alpha:=\lambda{X_\alpha}.X$ and only if the threshold for |typ| rises above +% 900, then we see the full information: +% $\mathbf{I}^\alpha_{\alpha\to\alpha}:=\lambda{X_\alpha}.X$. +% +% In an output format that is capable of interactively changing its appearance, e.g. +% dynamic XHTML+MathML (i.e. XHTML with embedded Presentation {\mathml} formulas, which +% can be manipulated via JavaScript in browsers), an application can export the +% information about elision groups and levels to the target format, and can then +% dynamically change the visibility thresholds by user interaction. Here the visibility +% threshold would also be used, but here it only determines the default rendering; a user +% can then fine-tune the document dynamically to reveal elided material to support +% understanding or to elide more to increase conciseness. +% +% The price the author has to pay for this enhanced user experience is that she has to +% specify elided parts of a formula that would have been left out in conventional +% {\LaTeX}. Some of this can be alleviated by good coding practices. Let us consider the +% log base case. This is elided in mathematics, since the reader is expected to pick it up +% from context. Using semantic macros, we can mimic this behavior: defining two semantic +% macros: |\logC| which picks up the log base from the context via the |\logbase| macro +% and |\logB| which takes it as a (first) argument. +% +% \begin{verbatim} +% \provideEdefault{logbase}{10} +% \symdef{logB}[2]{\prefix{\mathrm{log}\elide{base}{100}{_{#1}}}{#2}} +% \abbrdef{logC}[1]{\logB{\fromEcontext{logbase}}{#1}} +% \end{verbatim} +% +% \DescribeMacro{\provideEdefault} Here we use the |\provideEdefault| macro to initialize +% a {\LaTeX} token register for the |logbase| default, which we can pick up from the +% elision context using \DescribeMacro{\fromEcontext}|\fromEcontext| in the definition of +% |\logC|. Thus |\logC{x}| would render as $\mathrm{log}_{10}(x)$ with a threshold of 50 +% for |base| and as $\mathrm{log}_2$, if the local {\TeX} group e.g. given by the +% |assertion| environment contains a +% \DescribeMacro{setEdefault}|\setEdefault{logbase}{2}|. +% +% \subsection{Variable Names}\label{sec:inter:vname} +% +% In mathematics we often use complex variable names like $x'$, $g_n$, $f^1$, +% $\widetilde\phi_i^j$ or even $foo$; for presentation-oriented {\LaTeX}, this is not a +% problem, but if we want to generate content markup, we must show that are complex +% identifiers (otherwise the variable name $foo$ might be mistaken for the product $f\cdot +% o\cdot o$). In careful mathematical typesetting, |$sin$| is distinguished from |$\sin$|, +% but we cannot rely on this effect for variable names. +% +% \DescribeMacro{\vname} |\vname| identifies a token sequence as a name, and allows the +% user to provide an ASCII ({\xml}-compatible) identifier for it. The optional argument is +% the identifier, and the second one the LaTeX representation. The identifier can also be +% used with \DescribeMacro{\vname} |\vnref| for referencing. So, if we have used +% |\vnname[xi]{x_i}|, then we can later use |\vnref{xi}| as a short name for +% |\vname{x_i}|. Note that in output formats that are capable of generating structure +% sharing, |\vnref{xi}| would be represented as a cross-reference. +% +% Since indexed variable names make a significant special case of complex identifiers, we +% provides the macros \DescribeMacro{\livar}|\livar| that allows to mark up variables with +% lower indices. If |\livar| is given an optional first argument, this is taken as a +% name. Thus |\livar[foo]{x}1| is ``short'' for |\vname[foo]{x_1}|. The macros +% \DescribeMacro{\livar}|\livar|, serve the analogous purpose for variables with upper +% indices, and \DescribeMacro{\ulivar}|\ulivar| for upper and lower indices. Finally, +% \DescribeMacro{\primvar}|\primvar| and \DescribeMacro{\pprimvar}|\pprimvar| do the same +% for variables with primes and double primes (triple primes are bad style). +% +% \StopEventually{\newpage\PrintIndex\newpage\PrintChanges\printbibliography} +% +% \section{The Implementation}\label{sec:implementation} +% +% The |presentation| package generates to files: the {\LaTeX} package (all the code +% between {\textsf{$\langle$*package$\rangle$}} and {\textsf{$\langle$/package$\rangle$}}) and the +% {\latexml} bindings (between {\textsf{$\langle$*ltxml$\rangle$}} and +% {\textsf{$\langle$/ltxml$\rangle$}}). We keep the corresponding code fragments together, +% since the documentation applies to both of them and to prevent them from getting out of +% sync. +% +% We first make sure that the KeyVal package is loaded (in the right +% version). For {\latexml}, we also initialize the package inclusions. +% \begin{macrocode} +%<package>\RequirePackage{keyval}[1997/11/10] +%<*ltxml> +# -*- CPERL -*- +package LaTeXML::Package::Pool; +use strict; +use LaTeXML::Package; +%</ltxml> +% \end{macrocode} +% We will first specify the default precedences and brackets, together with the macros +% that allow to set them. +% \begin{macrocode} +%<*package> +\def\pres@default@precedence{0} +\def\pres@infty{1000000} +\def\iprec{\pres@infty} +\def\niprec{-\pres@infty} +\def\pres@initial@precedence{0} +\def\pres@current@precedence{\pres@initial@precedence} +\def\pres@default@lbrack{(}\def\pres@lbrack{\pres@default@lbrack} +\def\pres@default@rbrack{)}\def\pres@rbrack{\pres@default@rbrack} +%</package> +%<*ltxml> +DefMacro('\iprec','1000000'); +DefMacro('\niprec','-1000000'); +%</ltxml> +% \end{macrocode} +% +% \subsection{The System Commands}\label{sec:impl:syscommands} +% +% \begin{macro}{\PrecSet} +% |\PrecSet| will set the default precedence.\ednote{need to implement this in {\latexml}?} +% \begin{macrocode} +%<*package> +\def\PrecSet#1{\def\pres@default@precedence{#1}} +%</package> +%<*ltxml> +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\PrecWrite} +% |\PrecWrite| will write a bracket, if the precedence mandates it, i.e. if |\pres@p| is +% greater than the current precedence specified by |\pres@current@precedence| +% \begin{macrocode} +%<*package> +\def\PrecWrite#1{\ifnum\pres@p>\pres@current@precedence\else{#1}\fi} +%</package> +% \end{macrocode} +% \end{macro} +% +% \subsection{Prefix \& Postfix Notations}\label{sec:impl:prepostfix} +% +% We first define the keys for the keyval arguments for |\prefix| and |\postfix|. +% +% \begin{macrocode} +%<*package> +\def\prepost@clearkeys{\def\pres@p@key{\pres@default@precedence}\def\pres@pi@key{\niprec} +\def\pres@lbrack{\pres@default@lbrack}\def\pres@rbrack{\pres@default@rbrack}} +\define@key{prepost}{lbrack}{\def\pres@lbrack{#1}} +\define@key{prepost}{rbrack}{\def\pres@lbrack{#1}} +\define@key{prepost}{p}{\def\pres@p@key{#1}} +\define@key{prepost}{pi}{\def\pres@pi@key{#1}} +%</package> +% \end{macrocode} +% +% \begin{macro}{\prefix} +% In prefix we always write the brackets. +% \begin{macrocode} +%<*package> +\newcommand{\prefix}[3][]%key, fn, arg +{\prepost@clearkeys\setkeys{prepost}{#1} +{#2}\pres@lbrack{\edef\pres@current@precedence{\pres@pi@key}#3}\pres@rbrack} +%</package> +%<*ltxml> +DefMacro('\prefix[]{}{}','\@prefix[#1]{$\crossrefOp[fun]{#2}$}{$#3 $}'); +DefConstructor('\@prefix OptionalKeyVals:mi {}{}', + "<omdoc:rendering " + . "?&defined(&KeyVal(#1,'p'))(precedence='&KeyVal(#1,'p')') " + . "argprec='&argument_precedence(#1)'>" + . "<m:mrow>" + . "#2" + . "<m:mrow>" + . "<m:mo fence='true'>(</m:mo>" + . "#3" + . "<m:mo fence='true'>)</m:mo>" + . "</m:mrow>" + . "</m:mrow>" + ."</omdoc:rendering>", + afterDigest=>sub { + #Default argument precedence is -\infty + my $keyval = $_[1]->getArg(1); + $keyval->setValue('pi',-1000000) unless ($keyval && defined($keyval->getValue('pi'))); + applyPrecedencePreferences(@_); + }, + properties=>sub { getSymmdefProperties($_[1]); }); +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\postfix} +% \begin{macrocode} +%<*package> +\newcommand{\postfix}[3][]%key, fn, arg +{\prepost@clearkeys\setkeys{prepost}{#1} +\pres@lbrack{\edef\pres@current@precedence{\pres@pi@key}#3}\pres@rbrack{#2}} +%</package> +%<*ltxml> +DefMacro('\postfix []{}{}','\@postfix[#1]{$\crossrefOp[fun]{#2}$}{$#3 $}'); +DefConstructor('\@postfix OptionalKeyVals:mi {}{}', + "<omdoc:rendering " + . "?&defined(&KeyVal(#1,'p'))(precedence='&KeyVal(#1,'p')') " + ."argprec='&argument_precedence(#1)'>" + . "<m:mrow>" + . "<m:mrow>" + . "<m:mo fence='true'>(</m:mo>" + . "#3" + . "<m:mo fence='true'>)</m:mo>" + . "</m:mrow>" + . "#2" + . "</m:mrow>" + ."</omdoc:rendering>", + afterDigest=>sub { + #Default argument precedence is -\infty + my $keyval = $_[1]->getArg(1); + $keyval->setValue('pi',-1000000) unless ($keyval && defined($keyval->getValue('pi'))); + applyPrecedencePreferences(@_); + }, + properties=>sub { getSymmdefProperties($_[1]); }); +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \subsection{Mixfix Operators}\label{sec:impl:mixfix} +% +% We need to enable notation definitions of the operators that have +% argument- and precedence-aware renderings. To this end, we +% circumvent {\latexml}'s limitations induced by its internal +% processing stages, by pulling most of the argument rendering +% functionality to the XSLT which produces the final {\omdoc} result. +% +% In the {\latexml} bindings, the internal structure of the mixfix +% operators is generically preserved, via the |symdef_presentation_pmml| subroutine +% in the Modules package. Nevertheless, in the current module we add the promised syntactic +% enhancements to each element of the mixfix family. Also, we use the +% |argument_precedence| subroutine to store the precedences given by +% the 'pi', 'pii', etc. keys as a temporary |argprec| +% attribute of the rendering, to be abolished during the final {\omdoc} generation. +% This setup is finally utilized by the XSLT stylesheet which combines +% the operator structure with the preserved precedences to produce the +% proper form of the argument render elements. +% +% \begin{macrocode} +%<*package> +\def\clearkeys{\let\pres@p@key=\relax +\let\pres@pi@key=\relax% +\let\pres@pi@key=\relax% +\let\pres@pii@key=\relax% +\let\pres@piii@key=\relax} +\define@key{mi}{nobrackets}[yes]{\def\pres@p@key{\pres@infty}% +\def\pres@pi@key{-\pres@infty}} +\define@key{mi}{lbrack}{\def\pres@lbrack@key{#1}} +\define@key{mi}{rbrack}{\def\pres@lbrack@key{#1}} +\define@key{mi}{p}{\def\pres@p@key{#1}} +\define@key{mi}{pi}{\def\pres@pi@key{#1}} +\def\prep@keys@mi% +{\edef\pres@lbrack{\@ifundefined{pres@lbrack@key}\pres@default@lbrack\pres@lbrack@key} +\edef\pres@rbrack{\@ifundefined{pres@rbrack@key}\pres@default@rbrack\pres@rbrack@key} +\edef\pres@p{\@ifundefined{pres@p@key}\pres@default@precedence\pres@p@key} +\edef\pres@pi{\@ifundefined{pres@pi@key}\pres@p\pres@pi@key}} +%</package> +%<*ltxml> +our $max_arguments = 10; #Currently max 10 arguments to \symdef. +DefKeyVal('mi','lbrack','Semiverbatim'); +DefKeyVal('mi','rbrack','Semiverbatim'); +DefKeyVal('mi','p','Semiverbatim'); +DefKeyVal('mi','pi','Semiverbatim'); +DefKeyVal('mi','pii','Semiverbatim'); #Why are we using this at mixfixai ? +DefKeyVal('mi','cd','Semiverbatim'); +DefKeyVal('mi','name','Semiverbatim'); +DefKeyVal('mi','nobrackets','Semiverbatim'); +sub argument_precedence { + my ($keyval) = @_; + my $attr = 'pi'; + my @precs = (); + foreach (1..$max_arguments) { + if (defined KeyVal($keyval,$attr)) { + push @precs, ToString(KeyVal($keyval,$attr)) + } else { + push @precs, ""; + } + $attr = $attr.'i'; + } + return join(" ",@precs)." "; +} +sub applyPrecedencePreferences { + my ($stomach,$whatsit) = @_; + my @args = $whatsit->getArgs; + my $keyvals = shift @args; + return unless (defined $keyvals); + my %kvhash = %{$keyvals->getKeyVals}; + #Default p (operator precedence) if not set: + my $default_precedence = LookupValue('default_precedence'); + $keyvals->setValue('p',$default_precedence) unless defined($keyvals->getValue('p')); + return unless (exists $kvhash{'nobrackets'}); + $keyvals->setValue('p',1000000); + $keyvals->setValue('pi',-1000000); + $keyvals->setValue('pii',-1000000); + $keyvals->setValue('piii',-1000000); + return; +}#$ +%</ltxml> +% \end{macrocode} +% +% \begin{macro}{\mixfixi} +% \begin{macrocode} +%<*package> +\newcommand{\mixfixi}[4][]%key, pre, arg, post +{\clearkeys\setkeys{mi}{#1}\prep@keys@mi% +\PrecWrite\pres@lbrack% +#2{\edef\pres@current@precedence{\pres@pi}#3}#4% +\PrecWrite\pres@rbrack} +%</package> +%<*ltxml> +DefMacro('\mixfixi[]{}{}{}', + '\@mixfixi[#1]{$\crossrefOp[fun]{#2}$}{$#3 $}' + . '{$\crossrefOp[fun]{#4}$}'); +DefConstructor('\@mixfixi OptionalKeyVals:mi {}{}{}', + "<omdoc:rendering" + . "?&defined(&KeyVal(#1,'p'))(precedence='&KeyVal(#1,'p')')" + . " argprec='&argument_precedence(#1)'>" + . "<m:mrow>" + . "<m:mo egroup='fence' fence='true'>(</m:mo>" + . "#2 #3 #4" + . "<m:mo egroup='fence' fence='true'>)</m:mo>" + . "</m:mrow>" + ."</omdoc:rendering>", + afterDigest=>sub { applyPrecedencePreferences(@_);}, + properties=>sub { getSymmdefProperties($_[1]); });#$ +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@assoc} +% We are using functionality from the {\LaTeX} core packages here to iterate over the +% arguments. +% \begin{macrocode} +%<*package> +\def\@assoc#1#2#3{% precedence, function, argv +\let\@tmpop=\relax% do not print the function the first time round +\@for\@I:=#3\do{\@tmpop% print the function +% write the i-th argument with locally updated precedence +{\edef\pres@current@precedence{#1}\@I}% +\let\@tmpop=#2}}%update the function +%</package> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\mixfixa} +% \begin{macrocode} +%<*package> +\newcommand{\mixfixa}[5][]%key, pre, arg, post, assocop +{\clearkeys\setkeys{mi}{#1}\prep@keys@mi% +\PrecWrite\pres@lbrack{#2}{\@assoc\pres@pi{#5}{#3}}{#4}\PrecWrite\pres@rbrack} +%</package> +%<*ltxml> +DefMacro('\mixfixa[]{}{}{}{}', + '\@mixfixa[#1]{$\crossrefOp[fun]{#2}$}{$#3 $}' + . '{$\crossrefOp[fun]{#4}$}' + . '{$\crossrefOp[fun]{#5}$}'); +DefConstructor('\@mixfixa OptionalKeyVals:mi {}{}{}{}', + "<omdoc:rendering " + . "?&defined(&KeyVal(#1,'p'))(precedence='&KeyVal(#1,'p')')>" + . "<m:mrow>" + . "<m:mo egroup='fence' fence='true'>(</m:mo>" + . "#2" + . "<omdoc:iterate name='args' " + . "?&defined(&KeyVal(#1,'pi'))(precedence='&KeyVal(#1,'pi')')>" + . "<omdoc:separator>#5</omdoc:separator>" + . "<omdoc:render name='arg' " + . "?&defined(&KeyVal(#1,'pi'))(precedence='&KeyVal(#1,'pi')')/>" + . "</omdoc:iterate>" + . "#4" + . "<m:mo egroup='fence' fence='true'>)</m:mo>" + . "</m:mrow>" + ."</omdoc:rendering>", + afterDigest=>sub { applyPrecedencePreferences(@_);}, + properties=>sub { getSymmdefProperties($_[1]); });#$ +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +%<*package> +\define@key{mii}{nobrackets}[yes]{\def\pres@p@key{\pres@infty}% +\def\pres@pi@key{-\pres@infty}\def\pres@pii@key{-\pres@infty}} +\define@key{mii}{lbrack}{\def\pres@lbrack@key{#1}} +\define@key{mii}{rbrack}{\def\pres@lbrack@key{#1}} +\define@key{mii}{p}{\def\pres@p@key{#1}} +\define@key{mii}{pi}{\def\pres@pi@key{#1}} +\define@key{mii}{pii}{\def\pres@pii@key{#1}} +\def\prep@keys@mii{\prep@keys@mi% +\edef\pres@pii{\@ifundefined{pres@pii@key}\pres@p\pres@pii@key}} +%</package> +%<*ltxml> +DefKeyVal('mii','lbrack','Semiverbatim'); +DefKeyVal('mii','rbrack','Semiverbatim'); +DefKeyVal('mii','p','Semiverbatim'); +DefKeyVal('mii','pi','Semiverbatim'); +DefKeyVal('mii','pii','Semiverbatim'); +DefKeyVal('mii','cd','Semiverbatim'); +DefKeyVal('mii','name','Semiverbatim'); +DefKeyVal('mii','nobrackets','Semiverbatim'); +%</ltxml> +% \end{macrocode} +% +% \begin{macro}{\mixfixii} +% \begin{macrocode} +%<*package> +\newcommand{\mixfixii}[6][]%key, pre, arg1, mid, arg2, post +{\clearkeys\setkeys{mii}{#1}\prep@keys@mii% +\PrecWrite\pres@lbrack% write bracket if necessary +#2{\edef\pres@current@precedence{\pres@pi}#3}% +#4{\edef\pres@current@precedence{\pres@pii}#5}#6% +\PrecWrite\pres@rbrack} +%</package> +%<*ltxml> +DefMacro('\mixfixii[]{}{}{}{}{}', + '\@mixfixii[#1]{$\crossrefOp[fun]{#2}$}{$#3 $}' + . '{$\crossrefOp[fun]{#4}$}{$#5 $}' + . '{$\crossrefOp[fun]{#6}$}'); +DefConstructor('\@mixfixii OptionalKeyVals:mi {}{}{}{}{}', + "<omdoc:rendering " + . "?&defined(&KeyVal(#1,'p'))(precedence='&KeyVal(#1,'p')') " + . "argprec='&argument_precedence(#1)'>" + . "<m:mrow>" + . "<m:mo egroup='fence' fence='true'>(</m:mo>" + . "#2 #3 #4 #5 #6" + . "<m:mo egroup='fence' fence='true'>)</m:mo>" + . "</m:mrow>" + ."</omdoc:rendering>", + afterDigest=>sub { applyPrecedencePreferences(@_);}, + properties=>sub { getSymmdefProperties($_[1]); });#$ +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\mixfixia} +% \begin{macrocode} +%<*package> +\newcommand{\mixfixia}[7][]%key, pre, arg1, mid, arg2, post, assocop +{\clearkeys\setkeys{mii}{#1}\prep@keys@mii% +\PrecWrite\pres@lbrack% write bracket if necessary +#2{\edef\pres@current@precedence{\pres@pi}#3}% +#4{\@assoc\pres@pii{#7}{#5}}#6% +\PrecWrite\pres@rbrack} +%</package> +%<*ltxml> +DefMacro('\mixfixia[]{}{}{}{}{}{}', + '\@mixfixia[#1]{$\crossrefOp[fun]{#2}$}{$#3 $}' + . '{$\crossrefOp[fun]{#4}$}{$#5 $}' + . '{$\crossrefOp[fun]{#6}$}' + . '{$\crossrefOp[fun]{#7}$}'); +DefConstructor('\@mixfixia OptionalKeyVals:mi {}{}{}{}{}{}', + "<omdoc:rendering " + . "?&defined(&KeyVal(#1,'p'))(precedence='&KeyVal(#1,'p')') " + . " argprec='&argument_precedence(#1)'>" + . "<m:mrow>" + . "<m:mo egroup='fence' fence='true'>(</m:mo>" + . "#2 #3 #4" + . "<omdoc:iterate name='args' " + . "?&defined(&KeyVal(#1,'pi'))(precedence='&KeyVal(#1,'pi')')>" + . "<omdoc:separator>#7</omdoc:separator>" + . "<omdoc:render name='arg' " + . "?&defined(&KeyVal(#1,'pi'))(precedence='&KeyVal(#1,'pi')')/>" + . "</omdoc:iterate>" + . "#6" + . "<m:mo egroup='fence' fence='true'>)</m:mo>" + . "</m:mrow>" + ."</omdoc:rendering>", + afterDigest=>sub { applyPrecedencePreferences(@_);}, + properties=>sub { getSymmdefProperties($_[1]); });#$ +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\mixfixai} +% \begin{macrocode} +%<*package> +\newcommand{\mixfixai}[7][]%key, pre, arg1, mid, arg2, post, assocop +{\clearkeys\setkeys{mii}{#1}\prep@keys@mii% +\PrecWrite\pres@lbrack% write bracket if necessary +#2{\@assoc\pres@pi{#7}{#3}}% +#4{\edef\pres@current@precedence{\pres@pii}#5}#6% +\PrecWrite\pres@rbrack} +%</package> +%<*ltxml> +DefMacro('\mixfixai[]{}{}{}{}{}{}', + '\@mixfixai[#1]{$\crossrefOp[fun]{#2}$}{$#3 $}' + .'{$\crossrefOp[fun]{#4}$}{$#5 $}' + .'{$\crossrefOp[fun]{#6}$}' + .'{$\crossrefOp[fun]{#7}$}'); +DefConstructor('\@mixfixai OptionalKeyVals:mi {}{}{}{}{}{}', + "<omdoc:rendering " + . "?&defined(&KeyVal(#1,'p'))(precedence='&KeyVal(#1,'p')') " + . " argprec='&argument_precedence(#1)'>" + . "<m:mrow>" + . "<m:mo egroup='fence' fence='true'>(</m:mo>" + . "#2" + . "<omdoc:iterate name='args' " + . "?&defined(&KeyVal(#1,'pi'))(precedence='&KeyVal(#1,'pi')')>" + . "<omdoc:separator>#7</omdoc:separator>" + . "<omdoc:render name='arg' " + . "?&defined(&KeyVal(#1,'pi'))(precedence='&KeyVal(#1,'pi')')/>" + . "</omdoc:iterate>" + . "#4 #5 #6" + . "<m:mo egroup='fence' fence='true'>)</m:mo>" + . "</m:mrow>" + ."</omdoc:rendering>", + afterDigest=>sub { applyPrecedencePreferences(@_);}, + properties=>sub { getSymmdefProperties($_[1]); });#$ +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +%<*package> +\define@key{miii}{nobrackets}[yes]{\def\pres@p@key{\pres@infty}% +\def\pres@pi@key{-\pres@infty}\def\pres@pii@key{-\pres@infty}\def\pres@pii@key{-\pres@infty}} +\define@key{miii}{lbrack}{\def\pres@lbrack@key{#1}} +\define@key{miii}{rbrack}{\def\pres@lbrack@key{#1}} +\define@key{miii}{p}{\def\pres@p@key{#1}} +\define@key{miii}{pi}{\def\pres@pi@key{#1}} +\define@key{miii}{pii}{\def\pres@pii@key{#1}} +\define@key{miii}{piii}{\def\pres@piii@key{#1}} +\def\prep@keys@miii{\prep@keys@mii\edef\pres@piii{\@ifundefined{pres@piii@key}{\pres@p}{\pres@piii@key}}} +%</package> +%<*ltxml> +DefKeyVal('miii','lbrack','Semiverbatim'); +DefKeyVal('miii','rbrack','Semiverbatim'); +DefKeyVal('miii','p','Semiverbatim'); +DefKeyVal('miii','pi','Semiverbatim'); +DefKeyVal('miii','pii','Semiverbatim'); +DefKeyVal('miii','piii','Semiverbatim'); +DefKeyVal('miii','cd','Semiverbatim'); +DefKeyVal('miii','name','Semiverbatim'); +DefKeyVal('miii','nobrackets','Semiverbatim'); +%</ltxml> +% \end{macrocode} +% +% \begin{macro}{\mixfixiii} +% \begin{macrocode} +%<*package> +\newcommand{\mixfixiii}[8][]%key, pre, arg1, mid1, arg2, mid2, arg3, post +{\clearkeys\setkeys{miii}{#1}\prep@keys@miii% +\PrecWrite\pres@lbrack% write bracket if necessary +#2{\edef\pres@current@precedence{\pres@pi}#3}% +#4{\edef\pres@current@precedence{\pres@pii}#5}% +#6{\edef\pres@current@precedence{\pres@pii}#7}#8% +\PrecWrite\pres@rbrack} +%</package> +%<*ltxml> +DefMacro('\mixfixiii[]{}{}{}{}{}{}{}', + '\@mixfixiii[#1]{$\crossrefOp[fun]{#2}$}{$#3 $}' + . '{$\crossrefOp[fun]{#4}$}{$#5 $}' + . '{$\crossrefOp[fun]{#6}$}{$#7 $}' + . '{$\crossrefOp[fun]{#8}$}'); +DefConstructor('\@mixfixiii OptionalKeyVals:mi {}{}{}{}{}{}{}', + "<omdoc:rendering " + . "?&defined(&KeyVal(#1,'p'))(precedence='&KeyVal(#1,'p')') " + . " argprec='&argument_precedence(#1)'>" + . "<m:mrow>" + . "<m:mo egroup='fence' fence='true'>(</m:mo>" + . "#2 #3 #4 #5 #6 #7 #8" + . "<m:mo egroup='fence' fence='true'>)</m:mo>" + . "</m:mrow>" + ."</omdoc:rendering>", + afterDigest=>sub { applyPrecedencePreferences(@_);}, + properties=>sub { getSymmdefProperties($_[1]); });#$ +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\mixfixaii} +% \begin{macrocode} +%<*package> +\newcommand{\mixfixaii}[9][]%key, pre, arg1, mid1, arg2, mid2, arg3, post, sep +{\clearkeys\setkeys{miii}{#1}\prep@keys@miii% +\PrecWrite\pres@lbrack% write bracket if necessary +#2{\@assoc\pres@pi{#9}{#3}}% +#4{\edef\pres@current@precedence{\pres@pii}#5}% +#6{\edef\pres@current@precedence{\pres@pii}#7}#8% +\PrecWrite\pres@rbrack} +%</package> +%<*ltxml> +DefMacro('\mixfixaii[]{}{}{}{}{}{}{}{}', + '\@mixfixaii[#1]{$\crossrefOp[fun]{#2}$}{$#3 $}' + . '{$\crossrefOp[fun]{#4}$}{$#5 $}' + . '{$\crossrefOp[fun]{#6}$}{$#7 $}' + . '{$\crossrefOp[fun]{#8}$}' + . '{$\crossrefOp[fun]{#9}$}'); +DefConstructor('\@mixfixaii OptionalKeyVals:mi {}{}{}{}{}{}{}{}', + "<omdoc:rendering " + . "?&defined(&KeyVal(#1,'p'))(precedence='&KeyVal(#1,'p')') " + . " argprec='&argument_precedence(#1)'>" + . "<m:mrow>" + . "<m:mo egroup='fence' fence='true'>(</m:mo>" + . "#2" + . "<omdoc:iterate name='args' " + . "?&defined(&KeyVal(#1,'pi'))(precedence='&KeyVal(#1,'pi')')>" + . "<omdoc:separator>#9</omdoc:separator>" + . "<omdoc:render name='arg' " + . "?&defined(&KeyVal(#1,'pi'))(precedence='&KeyVal(#1,'pi')')/>" + . "</omdoc:iterate>" + . "#4 #5 #6 #7 #8" + . "<m:mo egroup='fence' fence='true'>)</m:mo>" + . "</m:mrow>" + ."</omdoc:rendering>", + afterDigest=>sub { applyPrecedencePreferences(@_);}, + properties=>sub { getSymmdefProperties($_[1]); });#$ +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\mixfixiai} +% \begin{macrocode} +%<*package> +\newcommand{\mixfixiai}[9][]%key, pre, arg1, mid1, arg2, mid2, arg3, post, assocop +{\clearkeys\setkeys{miii}{#1}\prep@keys@miii% +\PrecWrite\pres@lbrack% write bracket if necessary +#2{\edef\pres@current@precedence{\pres@pi}#3}% +#4{\@assoc\pres@pi{#9}{#5}}% +#6{\edef\pres@current@precedence{\pres@pii}#7}#8% +\PrecWrite\pres@rbrack} +%</package> +%<*ltxml> +DefMacro('\mixfixiai[]{}{}{}{}{}{}{}{}', + '\@mixfixiai[#1]{$\crossrefOp[fun]{#2}$}{$#3 $}' + . '{$\crossrefOp[fun]{#4}$}{$#5 $}' + . '{$\crossrefOp[fun]{#6}$}{$#7 $}' + . '{$\crossrefOp[fun]{#8}$}' + . '{$\crossrefOp[fun]{#9}$}'); +DefConstructor('\@mixfixiai OptionalKeyVals:mi {}{}{}{}{}{}{}', + "<omdoc:rendering " + . "?&defined(&KeyVal(#1,'p'))(precedence='&KeyVal(#1,'p')') " + . " argprec='&argument_precedence(#1)'>" + . "<m:mrow>" + . "<m:mo egroup='fence' fence='true'>(</m:mo>" + . "#2 #3 #4" + . "<omdoc:iterate name='args' " + . "?&defined(&KeyVal(#1,'pi'))(precedence='&KeyVal(#1,'pi')')>" + . "<omdoc:separator>#9</omdoc:separator>" + . "<omdoc:render name='arg' " + . "?&defined(&KeyVal(#1,'pi'))(precedence='&KeyVal(#1,'pi')')/>" + . "</omdoc:iterate>" + . "#6 #7 #8" + . "<m:mo egroup='fence' fence='true'>)</m:mo>" + . "</m:mrow>" + ."</omdoc:rendering>", + afterDigest=>sub { applyPrecedencePreferences(@_);}, + properties=>sub { getSymmdefProperties($_[1]); });#$ +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\mixfixiia} +% \begin{macrocode} +%<*package> +\newcommand{\mixfixiia}[9][]%key, pre, arg1, mid1, arg2, mid2, arg3, post,assocop +{\clearkeys\setkeys{miii}{#1}\prep@keys@miii% +\PrecWrite\pres@lbrack% write bracket if necessary +#2{\edef\pres@current@precedence{\pres@pi}#3}% +#4{\edef\pres@current@precedence{\pres@pii}#5}% +#6{\@assoc\pres@pi{#9}{#7}}#8% +\PrecWrite\pres@rbrack} +%</package> +%<*ltxml> +DefMacro('\mixfixiia[]{}{}{}{}{}{}{}{}', + '\@mixfixiia[#1]{$\crossrefOp[fun]{#2}$}{$#3 $}' + . '{$\crossrefOp[fun]{#4}$}{$#5 $}' + . '{$\crossrefOp[fun]{#6}$}{$#7 $}' + . '{$\crossrefOp[fun]{#8}$}' + . '{$\crossrefOp[fun]{#9}$}'); +DefConstructor('\@mixfixiia OptionalKeyVals:mi {}{}{}{}{}{}{}', + "<omdoc:rendering " + . "?&defined(&KeyVal(#1,'p'))(precedence='&KeyVal(#1,'p')') " + . " argprec='&argument_precedence(#1)'>" + . "<m:mrow>" + . "<m:mo egroup='fence' fence='true'>(</m:mo>" + . "#2 #3 #4 #5 #6" + . "<omdoc:iterate name='args' " + . "?&defined(&KeyVal(#1,'pi'))(precedence='&KeyVal(#1,'pi')')>" + . "<omdoc:separator>#9</omdoc:separator>" + . "<omdoc:render name='arg' " + . "?&defined(&KeyVal(#1,'pi'))(precedence='&KeyVal(#1,'pi')')/>" + . "</omdoc:iterate>" + . "#8" + . "<m:mo egroup='fence' fence='true'>)</m:mo>" + . "</m:mrow>" + ."</omdoc:rendering>", + afterDigest=>sub { applyPrecedencePreferences(@_);}, + properties=>sub { getSymmdefProperties($_[1]); });#$ +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\prefixa} +% In prefix we always write the brackets. +% \begin{macrocode} +%<*package> +\newcommand{\prefixa}[4][]%keys, fn, arg, sep +{\prepost@clearkeys\setkeys{prepost}{#1} +{#2}\pres@lbrack{\@assoc\pres@pi@key{#3}{#4}}\pres@rbrack} +%</package> +%<*ltxml> +DefMacro('\prefixa[]{}{}{}','\@prefixa[#1]{$\crossrefOp[fun]{#2}$}{$#3 $}{$#4 $}'); +DefConstructor('\@prefixa OptionalKeyVals:mi {}{}{}', + "<omdoc:rendering " + . "?&defined(&KeyVal(#1,'p'))(precedence='&KeyVal(#1,'p')') " + . "argprec='&argument_precedence(#1)'>" + . "<m:mrow>" + . "#2" + . "<m:mrow>" + . "<m:mo fence='true'>(</m:mo>" + . "<omdoc:iterate name='args' " + . "?&defined(&KeyVal(#1,'pi'))(precedence='&KeyVal(#1,'pi')')>" + . "<omdoc:separator>#4</omdoc:separator>" + . "<omdoc:render name='arg' " + . "?&defined(&KeyVal(#1,'pi'))(precedence='&KeyVal(#1,'pi')')/>" + . "</omdoc:iterate>" + . "<m:mo fence='true'>)</m:mo>" + . "</m:mrow>" + . "</m:mrow>" + ."</omdoc:rendering>", + afterDigest=>sub { + #Default argument precedence is -\infty + my $keyval = $_[1]->getArg(1); + $keyval->setValue('pi',-1000000) unless ($keyval && defined($keyval->getValue('pi'))); + applyPrecedencePreferences(@_); + }, + properties=>sub { getSymmdefProperties($_[1]); }); +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\postfixa} +% \begin{macrocode} +%<*package> +\newcommand{\postfixa}[4][]%keys, fn, arg, sep +{\prepost@clearkeys\setkeys{prepost}{#1} +\pres@lbrack{\@assoc\pres@pi@key{#3}{#4}}\pres@rbrack{#2}} +%</package> +%<*ltxml> +DefMacro('\postfixa []{}{}{}','\@postfixa[#1]{$\crossrefOp[fun]{#2}$}{$#3 $}{$#4 $}'); +DefConstructor('\@postfixa OptionalKeyVals:mi {}{}{}', + "<omdoc:rendering " + . "?&defined(&KeyVal(#1,'p'))(precedence='&KeyVal(#1,'p')') " + ."argprec='&argument_precedence(#1)'>" + . "<m:mrow>" + . "<m:mrow>" + . "<m:mo fence='true'>(</m:mo>" + . "<omdoc:iterate name='args' " + . "?&defined(&KeyVal(#1,'pi'))(precedence='&KeyVal(#1,'pi')')>" + . "<omdoc:separator>#4</omdoc:separator>" + . "<omdoc:render name='arg' " + . "?&defined(&KeyVal(#1,'pi'))(precedence='&KeyVal(#1,'pi')')/>" + . "</omdoc:iterate>" + . "<m:mo fence='true'>)</m:mo>" + . "</m:mrow>" + . "#2" + . "</m:mrow>" + ."</omdoc:rendering>", + afterDigest=>sub { + #Default argument precedence is -\infty + my $keyval = $_[1]->getArg(1); + $keyval->setValue('pi',-1000000) unless ($keyval && defined($keyval->getValue('pi'))); + applyPrecedencePreferences(@_); + }, + properties=>sub { getSymmdefProperties($_[1]); }); +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\infix} +% |\infix|\ednote{need infixl as well, use counters for precedences here.} is a simple +% special case of |\mixfixii|. +% \begin{macrocode} +%<ltxml>RawTeX(' +%<*package|ltxml> +\newcommand{\infix}[4][]{\mixfixii[#1]{}{#3}{#2}{#4}{}} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\assoc} +% \begin{macrocode} +\newcommand{\assoc}[3][]{\mixfixa[#1]{}{#3}{}{#2}} +%</package|ltxml> +%<ltxml>'); +% \end{macrocode} +% \end{macro} +% +% \subsection{General Elision}\label{sec:impl:elision} +% +% \ednote{all of these still need to be tested and implemented in LaTeXML.} +% \begin{macro}{\setegroup} +% The elision macros are quite simple, a group |foo| is internally represented by a +% macro |foo@egroup|, which we set by a |\gdef|. +% \begin{macrocode} +%<*package> +\def\setegroup#1#2{\expandafter\def\csname #1@egroup\endcsname{#2}} +%</package> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\elide} +% Then the elision command is picks up on this (flags an error) if the internal macro +% does not exist and prints the third argument, if the elision value threshold is above +% the elision group threshold in the paper.\ednote{do we need to turn this around as +% well?} We test the implementation with Figure~\ref{ex:elision-test}. +% \begin{macrocode} +%<*package> +\def\elide#1#2#3{\@ifundefined{#1@egroup}% +{\def\@elevel{0} +\PackageError{presentation}{undefined egroup #1, assuming value 0}% +{When calling \protect\elide{#1}... the elision group #1 has be have\MessageBreak +been set by \protect\setegroup before, e.g. by \protect\setegroup{an}{0}.}}% +{\edef\@elevel{\csname #1@egroup\endcsname}}% +\ifnum\@elevel>#2\else{#3}\fi} +%</package> +%<*ltxml> +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{figure}[ht]\centering +% \begin{tabular}{|l|l|l|l|}\hline +% {\texttt{par}} & {\texttt{typ}} & result & expected \\\hline\hline +% 0 & 0 & \setegroup{par}{0}\setegroup{typ}{0} +% $\mathbf{I}\elide{par}{500}{^\alpha}\elide{typ}{100}{_{\alpha\to\alpha}} +% :=\lambda{X\elide{typ}{500}{_\alpha}}.X$ +% & $\mathbf{I}:=\lambda{X}.X$\\\hline +% 600 & 600 & \setegroup{par}{600}\setegroup{typ}{600} +% $\mathbf{I}\elide{par}{500}{^\alpha}\elide{typ}{100}{_{\alpha\to\alpha}} +% :=\lambda{X\elide{typ}{500}{_\alpha}}.X$ +% & $\mathbf{I}^\alpha:=\lambda{X_\alpha}.X$\\\hline +% 600 & 1000 & \setegroup{par}{600}\setegroup{typ}{1000} +% $\mathbf{I}\elide{par}{500}{^\alpha}\elide{typ}{100}{_{\alpha\to\alpha}} +% :=\lambda{X\elide{typ}{500}{_\alpha}}.X$ +% & $\mathbf{I}^\alpha_{\alpha\to\alpha}:=\lambda{X_\alpha}.X$\\\hline +% \end{tabular} +% \caption{Testing Elision with the example in Figure~\protect\ref{ex:elision}}\label{ex:elision-test} +% \end{figure} +% +% \begin{macro}{\provideEdefault} +% The |\provideEdefault| macro sets up the context for an elision default by locally +% defining the internal macro \meta{default}|@edefault| and (if necessary) exporting it +% from the module. +% \begin{macrocode} +%<*package> +\def\provideEdefault#1#2{\expandafter\def\csname#1@edefault\endcsname{#2} +\@ifundefined{this@module}{}% +{\expandafter\g@addto@macro\this@module{\expandafter\def\csname#1@edefault\endcsname{#2}}}} +%</package> +%<*ltxml> +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\setEdefault} +% The |\setEdefault| macro just redefines the internal \meta{default}|@edefault| in the +% local group +% \begin{macrocode} +%<*package> +\def\setEdefault#1#2{\expandafter\def\csname #1@edfault\endcsname{#2}} +%</package> +%<*ltxml> +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\fromEcontext} +% The |\fromEcontext| macro just calls internal \meta{default}|@edefault| macro. +% \begin{macrocode} +%<*package> +\def\fromEcontext#1{\csname #1@edefault\endcsname} +%</package> +%<*ltxml> +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \subsection{Variable Names}\label{sec:impl:vname} +% +% \begin{macro}{\vname} +% a name macro; the first optional argument is an identifier \meta{id}, this is standard +% for {\LaTeX}, but for {\latexml}, we want to generate attributes +% |xml:id="cvar.|\meta{id}|"| and |name="|\meta{id}|"|. However, if no id was given in +% we default them to |xml:id="cvar.|\meta{count}|"| and +% |name="name.cvar.|\meta{count}|"|. +% \begin{macrocode} +%<*package> +\newcommand{\vname}[2][]{#2\def\@opt{#1}\ifx\@opt\@empty\else\expandafter\gdef\csname MOD@name@#1\endcsname{#2}\fi} +%</package> +%<*ltxml> +sub cvar_id { + my ($id)=@_; + $id=ToString($id); + if (!$id) { + $id=LookupValue('cvar_id'); + $id=0 unless $id; + $id++; + AssignValue('cvar_id',$id,'global'); + } + $id="cvar.$id"; $id;} +DefConstructor('\vname[]{}', + "<ltx:XMWrap role='ID' xml:id='&cvar_id(#1)'>#2</ltx:XMWrap>", + requireMath=>1); +DefConstructor('\crossrefOp[]{}', + "?#2(<ltx:XMApp role='CROSSREFOP'>" + . "<ltx:XMTok role='CROSSREFOP' cr='?#1(#1)(fun)'/>" + . "<ltx:XMWrap>#2</ltx:XMWrap>" + ."</ltx:XMApp>)()", + requireMath=>1); +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\vnref} +% \begin{macrocode} +%<*package> +\def\vnref#1{\csname MOD@name@#1\endcsname} +%</package> +%<*ltxml> +DefMacro('\vnref{}','\@XMRef{#1}'); +%</ltxml> +% \end{macrocode} +% \end{macro} +% \ednote{the following macros are just ideas, they need to be implemented and documented} +% \begin{macro}{\uivar} +% constructors for variables\ednote{these are document them above} +% \begin{macrocode} +%<ltxml>RawTeX(' +%<*package|ltxml> +\newcommand{\primvar}[2][]{\vname[#1]{#2^\prime}} +\newcommand{\pprimvar}[2][]{\vname[#1]{#2^{\prime\prime}}} +\newcommand{\uivar}[3][]{\vname[#1]{{#2}^{#3}}} +\newcommand{\livar}[3][]{\vname[#1]{{#2}_{#3}}} +\newcommand{\ulivar}[4][]{\vname[#1]{{#2}^{#3}_{#4}}} +%</package|ltxml> +%<ltxml>'); +% \end{macrocode} +% \end{macro} +% +% \subsection{Finale} +% +% Finally, we need to terminate the file with a success mark for perl. +% \begin{macrocode} +%<ltxml>1; +% \end{macrocode} +% \Finale +\endinput +% +% LocalWords: dtx CPERL RequirePackage keyval lbrack rbrack DefKeyVal omdoc cd +% LocalWords: Semiverbatim DefConstructor OptionalKeyVals pmml ltx XMath mii +% LocalWords: pii miii piii KeyVal egroup namedef attr precs foreach ToString +% LocalWords: DefMacro locator stex srcref argprec mrow getSymmdefProperties +% LocalWords: args arg LaTeX cvar iffalse scsys sc sc mathml openmath latexml +% LocalWords: cmathml activemath twintoo atwin atwintoo texttt fileversion foo +% LocalWords: Deyan Ginev maketitle setcounter tocdepth tableofcontents symdef +% LocalWords: newpage ldots bigl bigr langle ary cdots subseteq mixfixi exfig +% LocalWords: mixfixii mixfixiii vspace hline sseteq ite tt tt tt tt uminus rb +% LocalWords: texorpdfstring assoc ednote nunion mixfixa mixfixa postfixa leq +% LocalWords: postfixa mixfixia mixfixia mixfixai mixfixai fntype rightarrow +% LocalWords: mixfixaii mixfixiai mixfixiia typej vdash cupcap ninters ninters +% LocalWords: capcup geq prec fset textbf textbf setegroup setegroup mathbf fn +% LocalWords: provideEdefault provideEdefault fromEcontext fromEcontext mathrm +% LocalWords: setEdefault setEdefault widetilde cdot vname vname vnref vnname +% LocalWords: ulivar ulivar primvar primvar pprimvar pprimvar textsf textsf +% LocalWords: printbibliography ltxml infty ifnum clearkeys nobrackets whatsit +% LocalWords: ifundefined keyvals kvhash newcommand setkeys crossrefOp argv +% LocalWords: tmpop i-th assocop textbackslash infixl gdef expandafter csname +% LocalWords: endcsname edefault edfault ifx prepostfix circ circ circ circ +% LocalWords: iprec iprec niprec niprec wrongset goodset prepost prepkeys |