summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2026-02-15 04:35:24 +0100
committerEugen Wissner <belka@caraus.de>2026-02-15 04:35:24 +0100
commit580bd7e8579f1de36d151249500de6601e43f4a1 (patch)
treee69d02bb786488aaf5cc6ba6671aa449f02223be
parent5959fbb5524bbeb05a96eb15aba59e961a3efcb7 (diff)
downloadelna-580bd7e8579f1de36d151249500de6601e43f4a1.tar.gz
Add documentation
-rw-r--r--doc/appendix.tex179
-rw-r--r--doc/credits.bib5
-rw-r--r--doc/language.tex339
-rw-r--r--doc/report.tex46
-rw-r--r--doc/type-system.tex126
-rw-r--r--rakelib/doc.rake32
6 files changed, 727 insertions, 0 deletions
diff --git a/doc/appendix.tex b/doc/appendix.tex
new file mode 100644
index 0000000..0777d55
--- /dev/null
+++ b/doc/appendix.tex
@@ -0,0 +1,179 @@
+\part{Appendix}
+\appendix
+
+\chapter{Syntax}
+
+\begin{grammar}
+<letter> = `A' | `B' | … | `Z' | `a' | `b' | … | `z' | `\_'.
+
+<counting-digit> = `1' | `2' | `3' | `4' | `5' | `6' | `7' | `8' | `9'.
+
+<decimal-digit> = `0' | <counting-digit>.
+
+<hex-digit> = <decimal-digit> | `A' | `B' | … | `F' | `a' | `b' | … | `f'.
+
+<binary-digit> = `0' | `1'.
+
+<hex-character> = `\\x' <hex-digit> <hex-digit>.
+
+<escaped-character> = `\\' \\
+ (`n' | `a' | `b' | `t' | `f' | `r' | `v' | `\\' | `\textquotesingle' | `\textquotedbl' | `?\@' | `0').
+
+<printable-character> = \enspace? a printable ASCII character\space?.
+
+<character> = <printable-character> | <escaped-character> | <hex-digit>.
+
+<identifier> = <letter> \{<letter> | <decimal-digit>\}.
+
+<identifier-definition> = <identifier> [`*'].
+
+<trait-identifier> = `#' <identifier>.
+
+<integer-literal> = `0' | <counting-digit> \{<decimal-digit>\}.
+
+<word-literal> = <integer-literal> `u'
+ \alt{} `0' (`X' | `x') <hex-digit> \{<hex-digit>\}
+ \alt{} `0' (`B' | `b') <binary-digit> \{<binary-digit>\}.
+
+<real-literal> = <integer-literal> `.\@' <decimal-digit> \{<decimal-digit>\}
+ \alt{} <integer-literal>\} `e' [`+' | `-'] <decimal-digit> \{<decimal-digit>\}.
+
+<string-literal> = `\textquotedbl' \{<character>\} `\textquotedbl'.
+
+<character-literal> = `\textquotesingle' <character> `\textquotesingle'.
+
+<literal> = <integer-literal> | <word-literal> | <real-literal>
+ \alt{} <string-literal> | <character-literal>
+ \alt{} `true' | `false' | `nil'.
+
+<trait> = <trait-identifier> `(' [<types>] `)'.
+
+<cast> = `cast' `(' <expression> `:\@' <type> `)'.
+
+<procedure-call> = <designator> `(' [<expressions>] `)'.
+
+<relation-operator> = `=' | `<>' | `<' | `>' | `<=' | `>='.
+
+<multiplication-operator> = `*' | `/' | `\%'.
+
+<addition-operator> = `+' | `-'.
+
+<shift-operator> = `<<' | `>>'.
+
+<unary-operator> = `@' | `~' | `-'.
+
+<selector> = `[' <expression> `]' | `.\@' <identifier> | `^'.
+
+<case> = <expressions> `:\@' <optional-statements>.
+
+<designator> = <reference> <selector> | <identifier>.
+
+<reference> = <literal>
+ \alt{} <designator>
+ \alt{} <trait>
+ \alt{} <cast>
+ \alt{} <procedure-call>
+ \alt{} `(' <expression> `)'.
+
+<factor> = <unary-operator> <factor> | <reference>.
+
+<term> = <factor> \{<multiplication-operator> <factor>\}.
+
+<simple-expression> = <term> \{<addition-operator> <term>\}.
+
+<comparand> = <simple-expression> \{<shift-operator> <simple-expression>\}.
+
+<relation> = <comparand> \{<relation-operator> <comparand>\}.
+
+<operand> = <relation> \{`&' <relation>\}.
+
+<expression> = <operand> \{(`or' | `xor') <operand>\}.
+
+<expressions> = <expression> \{`,' <expression>\}.
+
+<identifier-definitions> = <identifier-definition> \{`,' <identifier-definition>\}.
+
+<types> = <type> \{`,' <type>\}.
+
+<required-statements> = <statement> \{`;' <statement>\}.
+
+<optional-statements> = [<required-statements>].
+
+<return-declaration> = [`->' `!\@' | `->' type].
+
+<field> = <identifier> `:\@' <type>.
+
+<array-type> = `[' <expression> `]' <type>.
+
+<pointer-type> = `^' <type>.
+
+<record-type> = `record' [`(' <identifier> `)'] [<field> \{`;' <field>\}] `end'.
+
+<enumeration-type> = `(' <identifier> \{`,' <identifier>\} `)'.
+
+<procedure-type> = `proc' `(' [<types>] `)' <return-declaration>.
+
+<type> = <array-type>
+ \alt{} <pointer-type>
+ \alt{} <record-type>
+ \alt{} <enumeration-type>
+ \alt{} <procedure-type>
+ \alt{} <identifier>.
+
+<assignment> = <designator> `:=' <expression>.
+
+<if-statement> = `if' <expression> `then' <optional-statements> \\
+ \{`elsif' <expression> `then' <optional-statements>\} \\
+ {[`else' <optional-statements>]} `end'.
+
+<while-statement> = `while' <expression> `do' <optional-statements> \\
+ \{`elsif' <expression> `do' <optional-statements>\} `end'.
+
+<defer-statement> = `defer' <optional-statements> `end'.
+
+<case-statement> = `case' <expression> `of' <case> \{`|' case\} \\
+ {[`else' <optional-statements>]} `end'.
+
+<label-declaration> = `.\@' <identifier>.
+
+<goto-statement> = `goto' <identifier>.
+
+<statement> = <assignment> | <procedure-call> | <defer-statement>
+ | <label-declaration> | <goto-statement> |
+ | <while-statement> | <if-statement> | <case-statement>.
+
+<statement-part> = [`begin' <required-statements>
+ \alt{} `return' <expression>
+ \alt{} `begin' <required-statements> `;' `return' <expression>].
+
+<constant-declaration> = <identifier-definition> `:=' <expression>.
+
+<constant-part> = [`const' \{<constant-declaration> `;'\}].
+
+<variable-declaration> = <identifier-definitions> `:\@' <type> \\
+ {[`:=' (<expression> | `extern')]}.
+
+<variable-part> = [`var' \{<variable-declaration> `;'\}].
+
+<type-declaration> = <identifier-definition> `=' <type>.
+
+<type-part> = [`type' \{<type-declaration> `;'\}].
+
+<import-declaration> = <identifier> \{`.\@' <identifier>\}.
+
+<import-part> = [`import' \{import-declaration `;'\}].
+
+<procedure-heading> = `proc' <identifier-definition> \\
+ `(' [<field> \{`,' <field>\}] `)' <return-declaration>.
+
+<block> = <constant-part> <variable-part> <statement-part> `end'.
+
+<procedure-declaration> = <procedure-heading> `;' (block | `extern').
+
+<declaration-sequence> = <import-part> \\
+ <constant-part> <type-part> <variable-part> \\
+ \{<procedure-declaration> `;'\}.
+
+<program> = `program' `;' <declaration-sequence> <statement-part> `end' `.\@'
+ \alt{} `module' `;' <declaration-sequence> `end' `.\@'.
+\end{grammar}
diff --git a/doc/credits.bib b/doc/credits.bib
new file mode 100644
index 0000000..0af1709
--- /dev/null
+++ b/doc/credits.bib
@@ -0,0 +1,5 @@
+@book{oberon,
+ author = "Niklaus Wirth",
+ title = "The Programming Language Oberon",
+ year = 2016
+}
diff --git a/doc/language.tex b/doc/language.tex
new file mode 100644
index 0000000..9112127
--- /dev/null
+++ b/doc/language.tex
@@ -0,0 +1,339 @@
+\part{Language}
+
+An Elna program consists of one or more source files, called \textbf{modules}.
+
+Each module can declare \textbf{types}, \textbf{global variables} and
+\textbf{procedures}, used by this module or exported to be used by other
+modules.
+
+Each procedure can get some input and produce an output as a result of
+executing a \textbf{statement block}, a list, where each \textbf{statement}
+is executed in the order it appears in the block.
+
+Statement components are other statement blocks and \textbf{expressions},
+where a statement has control over the evaluation of its components.
+Statements can also modify the state of the procedure or the program by
+mutating variables.
+
+\chapter{Expressions}
+
+Expressions are constructs denoting rules of computation whereby constants and current values of
+variables are combined to derive other values by the application of operators and function
+procedures. Expressions consist of operands and operators. Parentheses may be used to express
+specific associations of operators and operands.
+
+\section{Literal constants}
+
+\begin{grammar}
+<literal> = <integer-literal> | <word-literal> | <real-literal>
+ \alt{} <string-literal> | <character-literal>
+ \alt{} `true' | `false' | `nil'.
+\end{grammar}
+
+Literal constants are
+
+\begin{itemize}
+ \item signed and unsigned integers,
+ \item real numbers,
+ \item booleans,
+ \item characters,
+ \item strings,
+ \item and enumerations.
+\end{itemize}
+
+\section{Call expressions}
+
+\subsection*{Procedure call}
+
+\begin{grammar}
+<procedure-call> = <designator> `(' [<expressions>] `)'.
+\end{grammar}
+
+If the designator object is a procedure followed by a (possibly empty) parameter list,
+the designator implies an activation of the procedure and stands for the value resulting
+from its execution. The (types of the) actual parameters must correspond to the formal
+parameters as specified in the procedure's declaration.
+
+\subsection*{Type cast}
+
+\begin{grammar}
+<cast> = `cast' `(' <expression> `:\@' <type> `)'.
+\end{grammar}
+
+The type of an object can be reinterpreted with a cast expression: \\
+\verb|cast(object: Type)|.
+
+\subsection*{Traits}
+
+\begin{grammar}
+<trait-identifier> = `#' <identifier>.
+
+<trait> = <trait-identifier> `(' [<types>] `)'.
+\end{grammar}
+
+Traits allow to query some information about the types, like their size or
+field offset or alignment. Calling a trait looks like a procedure call but
+trait names start with a \verb|#| and their arguments are type expressions and
+not value expressions.
+
+Supported compiler traits:
+
+\begin{itemize}
+ \item \verb|#size(T)| queries type size.
+ \item \verb|#align(T)| queries type alignment.
+ \item \verb|#offset(T, F)| queries the offset of the field \verb|F| in the record \verb|T|.
+\end{itemize}
+
+\section{Object designators}
+
+\begin{grammar}
+<selector> = `[' <expression> `]' | `.\@' <identifier> | `^'.
+
+<designator> = <reference> <selector> | <identifier>.
+
+<reference> = <literal>
+ \alt{} <designator>
+ \alt{} <trait>
+ \alt{} <cast>
+ \alt{} <procedure-call>
+ \alt{} `(' <expression> `)'.
+\end{grammar}
+
+With the exception of literal constants and call expressions, operands are denoted by
+\textit{designators}. A designator consists of an identifier referring to the constant,
+variable, or procedure to be designated. This identifier or any other expression may be
+followed by selectors, if the designated object is an element of a structure.
+
+Designators are addressable, meaning that it is possible to get the address of the
+designated object or assign a value to it (if the designated object is mutable).
+
+\subsection*{Subscript selector}
+
+If \verb|A| designates an array or a string, then \verb|A[E]| denotes that element of
+\verb|A| whose index is the current value of the expression \verb|E|. The type of
+\verb|E| must be of type \verb|Word| or \verb|Int|. The first element has index 1,
+the second 2 and so on.
+
+\subsection*{Dereference selector}
+
+If \verb|P| designates a pointer, \verb|P^| denotes the object which is
+referenced by \verb|P|.
+
+\subsection*{Field selector}
+
+If \verb|R| designates a record, then \verb|R.f| denotes the field \verb|f| of
+\verb|R|.
+
+\subsection*{Variable designator}
+
+If the designated object is a variable, then the designator refers to the
+variable's current value.
+
+If the designated object is a procedure, a designator without parameter list
+refers to the address of the procedure. Procedure designators designate
+immutable objects.
+
+\subsection*{Selector evaluation order}
+
+Selectors are evaluated from left to right.
+
+For example the expression \verb|r^.field| includes 3 designators:
+
+\begin{enumerate}
+ \item Variable designator \verb|r|.
+ \item \verb|r^| dereferences the pointer \verb|r| and refers
+ to the object at the address in \verb|r|.
+ \item \verb|r^.field| accesses the field \verb|field| in that object.
+\end{enumerate}
+
+\section{Unary expressions}
+
+\begin{grammar}
+<unary-operator> = `@' | `~' | `-'.
+
+<factor> = <unary-operator> <factor> | <reference>.
+\end{grammar}
+
+Unary expressions are expressions with a prefix operator followed by one
+operand. Unary operators in table~\ref{table:unary} associate from right
+to left.
+
+$@$ takes the address of its operand. The operand expression should be
+addressable.
+
+$\sim$ applied on a boolean acts as logical not. Applied on an integer --- as
+bitwise not.
+
+\begin{table}[ht]
+\centering
+\begin{tabularx}{0.7\textwidth}{%
+ r
+ l
+ >{\centering\arraybackslash}X
+}
+ \textbf{Symbol} & \textbf{Symbol name} & \textbf{Description} \\
+ \toprule
+ $@$ & \textit{at sign} & Address \\
+ \midrule
+ $-$ & \textit{minus} & Sign inversion \\
+ \midrule
+ $+$ & \textit{plus} & Identity operation \\
+ \midrule
+ $\sim$ & \textit{tilde} & Negation \\
+ \bottomrule
+\end{tabularx}
+\caption{Unary operators}\label{table:unary}
+\end{table}
+
+\section{Binary expressions}
+
+\begin{grammar}
+<term> = <factor> \{<multiplication-operator> <factor>\}.
+
+<simple-expression> = <term> \{<addition-operator> <term>\}.
+
+<comparand> = <simple-expression> \{<shift-operator> <simple-expression>\}.
+
+<relation> = <comparand> \{<relation-operator> <comparand>\}.
+
+<operand> = <relation> \{`&' <relation>\}.
+
+<expression> = <operand> \{(`or' | `xor') <operand>\}.
+\end{grammar}
+
+The syntax of expressions distinguishes between several classes of
+operators with different precedences (binding strengths). Operators of
+the same precedence associate from left to right. For example, $x - y - z$
+stands for $(x - y) - z$.
+
+The available operators are listed in the table~\ref{table:binary}.
+In some instances, several different operations are designated by
+the same operator symbol. In these cases, the actual operation is
+identified by the type of the operands.
+
+\begin{table}[ht]
+\centering
+\begin{tabularx}{\textwidth}{%
+ c
+ >{\centering\arraybackslash}X
+ >{\raggedright\arraybackslash}X
+}
+ \textbf{Precedence} & \textbf{Operator} & \textbf{Description} \\
+ \toprule
+ 1 & $* \quad / \quad \%$ & Multiplication, division and remainder. \\
+ \midrule
+ 2 & $+ \quad -$ & Addition and subtraction. \\
+ \midrule
+ 3 & $<< \quad >>$ & Left and right shifts. \\
+ \midrule
+ 4 & $= \quad <> \quad > \quad < \quad <= \quad >=$ & Relational operators. \\
+ \midrule
+ 5 & $\&$ & Logical conjuction. \\
+ \midrule
+ 6 & $or \quad xor \quad$ & Logical disjunction operators. \\
+ \bottomrule
+\end{tabularx}
+\caption{Operator precedence}\label{table:binary}
+\end{table}
+
+\subsection*{Logical and bitwise operators}
+
+Meaning of the operators in table~\ref{table:logical} depends on the
+operand type:
+
+Applied on booleans they act as logical operators.
+
+Applied on integers they perform the corresponding logical operation
+bitwise, on each pair of bits of their operands.
+
+$or$ and $\&$ are short-circuiting, if the evaluation of the left
+side of the operation is enough to determine the final result,
+the right side should not be evaluated.
+
+\begin{table}[ht]
+\centering
+\begin{tabularx}{\textwidth}{%
+ r
+ l
+ >{\centering\arraybackslash}X
+ >{\centering\arraybackslash}X
+}
+ \textbf{Symbol} & \textbf{Description} &
+ \textbf{$p \cdot q$ with $\cdot$ as logical operator stands for} &
+ \textbf{As bitwise operator} \\
+ \toprule
+ $or$ & Inclusive disjunction & If $p$ then $true$, else $q$ & Bitwise or \\
+ \midrule
+ $xor$ & Exclusive disjunction & If $p$ then not $q$, else $q$ & Bitwise xor \\
+ \midrule
+ $\&$ & Conjuction & If $p$ then $q$, else $false$ & Bitwise and \\
+ \bottomrule
+\end{tabularx}
+\caption{Logical operators}\label{table:logical}
+\end{table}
+
+\subsection*{Arithmetic operators}
+
+Operators in table~\ref{table:arithmetic} apply to operands of numeric
+types. Both operands must be of the same type, which is also the type of
+the result.
+
+Let $q = x / y$, and $r = x \% y$. Then quotient $q$ and remainder $r$ are
+defined by the equation
+
+\[
+x = q * y + r \mid 0 \leq r < y
+\]
+
+Division on integer operands performs integer division.
+
+\begin{table}[ht]
+\centering
+\begin{tabular}{r l}
+ \textbf{Symbol} & \textbf{Result} \\
+ \toprule
+ $+$ & Sum \\
+ \midrule
+ $-$ & Difference \\
+ \midrule
+ $*$ & Product \\
+ \midrule
+ $/$ & Quotient \\
+ \midrule
+ $\%$ & Modulus \\
+ \bottomrule
+\end{tabular}
+\caption{Arithmetic operators}\label{table:arithmetic}
+\end{table}
+
+\subsection*{Relations}
+
+Relations in table~\ref{table:relation} are boolean. The ordering
+relations $<$, $<=$, $>$, $>=$ apply to the numeric types. The
+relations $=$ and $<>$ apply to all types.
+
+\begin{table}[ht]
+\centering
+\begin{tabular}{r l}
+ \textbf{Symbol} & \textbf{Result} \\
+ \toprule
+ $=$ & Equal \\
+ \midrule
+ $<>$ & Unequal \\
+ \midrule
+ $<$ & Less \\
+ \midrule
+ $<=$ & Less or equal \\
+ \midrule
+ $>$ & Greater \\
+ \midrule
+ $>=$ & Greater or equal \\
+ \bottomrule
+\end{tabular}
+\caption{Relational operators}\label{table:relation}
+\end{table}
+
+\chapter{Statements}
+
+\section{Conditional statements}
+\section{Loop statements}
diff --git a/doc/report.tex b/doc/report.tex
new file mode 100644
index 0000000..e3ed640
--- /dev/null
+++ b/doc/report.tex
@@ -0,0 +1,46 @@
+\documentclass{scrreprt}
+
+\usepackage[T1]{fontenc}
+\usepackage{tabularx}
+\usepackage{booktabs}
+\usepackage{listings}
+\usepackage{syntax}
+\usepackage[backend=biber,style=verbose-ibid,dashed=false]{biblatex}
+
+% Do not start chapter on a new page.
+\RedeclareSectionCommand[
+ style=section,
+ indent=0pt
+]{chapter}
+
+\bibliography{credits}
+
+\title{The programming language Elna}
+\author{Eugen Wissner}
+
+\begin{document}
+
+\maketitle
+\tableofcontents
+
+\addchap{Introduction}
+
+Elna is a simple, imperative, low-level programming language.
+
+It is intendet to accompany other languages in the areas, where a high-level
+language doesn't fit well. It is also supposed to be an intermediate
+representation for a such high-level hypothetical programming language.
+
+\addchap{Credits}
+
+Since Elna syntactically resembles Oberon larger parts of this specification
+are derived from the Oberon report\footnote{\cite[]{oberon}}.
+
+\include{language}
+\include{type-system}
+\include{appendix}
+
+% \addcontentsline{toc}{chapter}{References}
+\printbibliography[heading=bibintoc, title=References]{}
+
+\end{document}
diff --git a/doc/type-system.tex b/doc/type-system.tex
new file mode 100644
index 0000000..3ae8a30
--- /dev/null
+++ b/doc/type-system.tex
@@ -0,0 +1,126 @@
+\part{Type system}
+
+\begin{grammar}
+<type> = <array-type>
+ \alt{} <pointer-type>
+ \alt{} <record-type>
+ \alt{} <enumeration-type>
+ \alt{} <procedure-type>
+ \alt{} <identifier>.
+\end{grammar}
+
+\chapter{Primitive types}
+
+\begin{itemize}
+ \item Pointer
+ \item Word
+ \item Int
+ \item Bool
+ \item String
+ \item Char
+\end{itemize}
+
+\chapter{Pointer types}
+
+\begin{grammar}
+<pointer-type> = `^' <type>.
+\end{grammar}
+
+\begin{lstlisting}[caption=Example]
+program;
+var
+ x: Int;
+ y: ^Int;
+begin
+ y := @x;
+ y^ := 0
+end.
+\end{lstlisting}
+
+\chapter{Static array}
+
+\begin{grammar}
+<array-type> = `[' <expression> `]' <type>.
+\end{grammar}
+
+\begin{lstlisting}[caption=Example]
+program;
+var
+ array: [3]Int := [1, 2, 3];
+begin
+ array[1] := array[2]
+end.
+\end{lstlisting}
+
+\chapter{Procedure types}
+
+\begin{grammar}
+<procedure-heading> = `proc' <identifier-definition> \\
+ `(' [<field> \{`,' <field>\}] `)' <return-declaration>.
+
+<block> = <constant-part> <variable-part> <statement-part> `end'.
+
+<procedure-declaration> = <procedure-heading> `;' (block | `extern').
+
+<return-declaration> = [`->' `!\@' | `->' type].
+
+<procedure-type> = `proc' `(' [<types>] `)' <return-declaration>.
+\end{grammar}
+
+\begin{lstlisting}[caption=Example]
+program;
+var
+ a: proc(Int) -> Int;
+
+proc f(x: Int) -> Int;
+end;
+
+begin
+ a := f;
+ a(0)
+end.
+\end{lstlisting}
+
+\chapter{Records}
+
+\begin{grammar}
+<field> = <identifier> `:\@' <type>.
+
+<record-type> = `record' [`(' <identifier> `)'] [<field> \{`;' <field>\}] `end'.
+\end{grammar}
+
+\begin{lstlisting}[caption=Example]
+program;
+type
+ T = record
+ x: Int
+ end;
+ U = record(T)
+ y: Int;
+ z: Int
+ end;
+
+var
+ u: U;
+begin
+ u := U(0, 1, 2);
+ u.x := 3
+end.
+\end{lstlisting}
+
+\chapter{Enumerations}
+
+\begin{grammar}
+<enumeration-type> = `(' <identifier> \{`,' <identifier>\} `)'.
+\end{grammar}
+
+\begin{lstlisting}[caption=Example]
+program;
+type
+ E = (one, two, three);
+var
+ e: E;
+begin
+ e := E.one
+end.
+\end{lstlisting}
diff --git a/rakelib/doc.rake b/rakelib/doc.rake
new file mode 100644
index 0000000..54f5d35
--- /dev/null
+++ b/rakelib/doc.rake
@@ -0,0 +1,32 @@
+# This Source Code Form is subject to the terms of the Mozilla Public License,
+# v. 2.0. If a copy of the MPL was not distributed with this file, You can
+# obtain one at https://mozilla.org/MPL/2.0/.
+# frozen_string_literal: true
+
+require 'pathname'
+require 'rake/clean'
+
+CLEAN.include 'build/doc'
+directory 'build/doc'
+
+rule '.bbl' => '.bcf' do |t|
+ task_target = Pathname.new t.name
+ chdir = 'doc'
+ output_directory = task_target.dirname.relative_path_from(chdir).to_path
+ source = task_target.basename('.bbl').to_path
+
+ sh 'biber', '-output-directory', output_directory, source, chdir:
+end
+
+namespace :doc do
+ task :tex do
+ sh 'pdflatex', '-output-directory', '../build/doc', 'report', chdir: 'doc'
+ end
+end
+
+desc 'Generate documentation'
+task doc: 'doc:tex' do
+ Rake::Task['build/doc/report.bbl'].invoke
+ Rake::Task['doc:tex'].reenable
+ Rake::Task['doc:tex'].invoke
+end