% \iffalse meta-comment
% (The MIT License)
%
% Copyright (c) 2021-2022 Yegor Bugayenko
%
% Permission is hereby granted, free of charge, to any person obtaining a copy
% of this software and associated documentation files (the 'Software'), to deal
% in the Software without restriction, including without limitation the rights
% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
% copies of the Software, and to permit persons to whom the Software is
% furnished to do so, subject to the following conditions:
%
% The above copyright notice and this permission notice shall be included in all
% copies or substantial portions of the Software.
%
% THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
% SOFTWARE.
% \fi

% \CheckSum{0}
%
% \CharacterTable
%  {Upper-case    \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
%   Lower-case    \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
%   Digits        \0\1\2\3\4\5\6\7\8\9
%   Exclamation   \!     Double quote  \"     Hash (number) \#
%   Dollar        \$     Percent       \%     Ampersand     \&
%   Acute accent  \'     Left paren    \(     Right paren   \)
%   Asterisk      \*     Plus          \+     Comma         \,
%   Minus         \-     Point         \.     Solidus       \/
%   Colon         \:     Semicolon     \;     Less than     \<
%   Equals        \=     Greater than  \>     Question mark \?
%   Commercial at \@     Left bracket  \[     Backslash     \\
%   Right bracket \]     Circumflex    \^     Underscore    \_
%   Grave accent  \`     Left brace    \{     Vertical bar  \|
%   Right brace   \}     Tilde         \~}

% \GetFileInfo{eolang.dtx}
% \DoNotIndex{\endgroup,\begingroup,\let,\else,\s,\n,\r,\\,\1,\fi}

% \iffalse
%<*driver>
\ProvidesFile{eolang.dtx}
%</driver>
%<package>\NeedsTeXFormat{LaTeX2e}
%<package>\ProvidesPackage{eolang}
%<*package>
[2022-10-25 0.0.2 Formulas and Graphs for EO Programming Language]
%</package>
%<*driver>
\documentclass{ltxdoc}
\usepackage[maxnames=1,minnames=1,maxbibnames=1,natbib=true,citestyle=authoryear,bibstyle=authoryear,doi=false,url=false,isbn=false,isbn=false]{biblatex}
\addbibresource{main.bib}
\usepackage[tt=false, type1=true]{libertine}
\usepackage{microtype}
\usepackage{graphicx}
\usepackage[runs=1,dtx]{docshots}
\usepackage{eolang}
\usepackage{href-ul}
\PageIndex
\EnableCrossrefs
\CodelineIndex
\RecordChanges
\begin{document}
	\DocInput{eolang.dtx}
	\PrintChanges
	\PrintIndex
\end{document}
%</driver>
% \fi

% \title{\includegraphics[height=1in]{cactus.pdf} \\ |eolang|: \LaTeX{} Package \\ for Formulas and Graphs \\ of EO Programming Language \\ and $\varphi$-calculus\thanks{The sources are in GitHub at \href{https://github.com/objectionary/eolang.sty}{objectionary/eolang.sty}}}
% \author{Yegor Bugayenko \\ \texttt{yegor256@gmail.com}}
% \date{\filedate, \fileversion}
%
% \maketitle
%
% \textbf{NB!}
% You must run \TeX{} processor with |--shell-escape| option
% and you must have \href{https://www.perl.org}{Perl} installed.

% \section{Introduction}
%
% This package helps you print formulas of $\varphi$-calculus,
% which is a formal foundation of \href{https://www.eolang.org}{EO}
% programming language. The calculus was introduced by \citet{bugayenko2021eolang}
% and later formalized by \citet{kudasov2021}. Here is how you render
% a simple expression:
% \begin{docshot}
% \documentclass{article}
% \pagestyle{empty}
% \usepackage{eolang}
% \begin{document}
% \begin{phiquation*}
% a -> [[
%   ^ !-> $.b,
%   b -> [[ c -> |fn|(56),
%     @ -> |hello|($),
%     \Delta ~> |01-FE-C3| ]]]],

% x -> [[ \alpha_0 -> ? ]]
% \end{phiquation*}
% \end{document}
% \end{docshot}

% \DescribeEnv{phiquation}
% The environment |phiquation| lets you write a $\varphi$-calculus expressions
% using simple plain-text notation, where:
% \begin{itemize}\setlength\itemsep{0em}
%   \item ``|@|'' maps to ``$\varphi$''
%     (|\varphi|),
%   \item ``|^|'' maps to ``$\rho$''
%     (|\rho|),
%   \item ``|$|'' maps to ``$\xi$''
%     (|\xi|),
%   \item ``|&|'' maps to ``$\sigma$''
%     (|\sigma|),
%   \item ``|?|'' maps to ``$\varnothing$''
%     (|\varnothing|),
%   \item ``|->|'' maps to ``$\mapsto$''
%     (|\mapsto|),
%   \item ``|!->|'' maps to ``$\mapstochar\relbar\mathrel{\mkern-12mu}\mapsto$''
%     (|\mapstochar\relbar\mathrel{\mkern-12mu}\mapsto|),
%   \item ``|~>|'' maps to ``$\mapstochar\dashrightarrow$''
%     (|\mapstochar\dashrightarrow|),
%   \item ``|[[|'' maps to ``$\llbracket$''
%     (|\llbracket|),
%   \item ``|]]|'' maps to ``$\rrbracket$''
%     (|\rrbracket|),
%   \item ``$\vert$|abc|$\vert$'' maps to ``\texttt{abc}''
%     (|\texttt{abc}|).
% \end{itemize}
% Also, a few symbols are supported for $\varphi$PU architecture:
% \begin{itemize}\setlength\itemsep{0em}
%   \item ``|-abc>|'' maps to ``$\xrightarrow{\text{\sffamily\scshape abc}}$''
%     (|\xrightarrow{\text{\sffamily\scshape abc}}|),
%   \item ``|:=|'' maps to ``$\vDash$''
%     (|\vDash|).
% \end{itemize}

% \DescribeMacro{\phiq}
% The command |\phiq| lets you inline a $\varphi$-calculus expressions
% using the same simple plain-text notation:
% \begin{docshot}
% \documentclass{article}
% \usepackage[paperwidth=2in]{geometry}
% \pagestyle{empty}
% \usepackage{eolang}
% \begin{document}
% A simple object
% \phiq{x -> [[@ -> y]]}
% is a decorator of
% the data object
% \phiq{y -> [[\Delta ~> 42]]}.
% \end{document}
% \end{docshot}

% \DescribeEnv{sodg}
% The environment |sodg| allows you to draw a \href{https://github.com/objectionary/sodg}{SODG} graph:
% \begin{docshot}
% \documentclass{article}
% \pagestyle{empty}
% \usepackage{eolang}
% \begin{document}
% \begin{sodg}
% v0
% v1 xy:v0,-2,+1 data:|42|
% v0->v1 a:$x$ rho
% v2 xy:v0,+1,+1 atom:$\xi.x+1$
% v1->v2 a:|hi| bend:-15
% v2->v0 pi bend:10
% \end{sodg}
% \end{document}
% \end{docshot}
% The content of the environment is parsed line by line. Markers in each line are
% separated by a single space. The first marker is either a unique name of a
% vertex, like |v1| in the example above, or an edge, like |v0->v1|. All other markers are either
% unary like |rho| or binary like |atom:$\xi.x+1$|. Binary markers have two
% parts, separated by colon. The following markers are supported for a vertex:
% \begin{itemize}\setlength\itemsep{0em}
%   \item ``|data:[<box>]|'' makes it a data vertex with an optional attached |<box>|,
%   \item ``|atom:[<box>]|'' makes it an atom with an optional attached |<box>|,
%   \item ``|box:<txt>|'' attaches a |<box>| to it,
%   \item ``|xy:<v>,<r>,<d>|'' places this vertex in a position relative to the vertex |<v>|,
%     shifting it right by |<r>| % and down by |<d>| centimetres.
% \end{itemize}
% The following markers are supported for an edge:
% \begin{itemize}\setlength\itemsep{0em}
%   \item ``|rho|'' places a backward snake arrow to the edge,
%   \item ``|rrho|'' places a reverse |rho|,
%   \item ``|bend:<angle>|'' bend it right by the amount of |<angle>|,
%   \item ``|a:<txt>|'' attaches label |<txt>| to it,
%   \item ``|pi|'' makes it dotted, with $\pi$ label.
% \end{itemize}

% \StopEventually{}

% \section{Implementation}

% First, we include a few packages:
%    \begin{macrocode}
\RequirePackage{stmaryrd}
\RequirePackage{amsmath}
\RequirePackage{amssymb}
\RequirePackage{amsfonts}
\RequirePackage{iexec}
\RequirePackage{fancyvrb}
%    \end{macrocode}

% \begin{macro}{\eolang@env}
% \changes{0.0.2}{2022/10/21}{The symbols ``['' and ``]'' replaced with ``[['' and ``]]'' for abstract object brackets, because they conflicted with normal square brackets}
% \changes{0.0.2}{2022/10/21}{New symbol added for basket slots}
% \changes{0.0.2}{2022/10/21}{Parsing of symbols ``@,'' ``\^{},'' and ``\&'' enabled (varphi, rho, and sigma)}
% Then, we define |\eolang@env| supplementary command.
% It is implemented with the help of |\iexec| from
% \href{https://github.com/yegor256/iexec}{iexec} package:
%    \begin{macrocode}
\makeatletter\newcommand\eolang@env[2]{
  \iexec[trace]{
    /bin/echo -n '\\begin{#1}\\begin{split} &'
    &&
    /bin/echo -n '\detokenize{#2}'
      | perl -pe 's/^\\r\\+//g'
      | perl -pe 's/\\r\\+$//g'
      | perl -pe 's/\\?/\\\\varnothing/g'
      | perl -pe 's/@/\\\\varphi/g'
      | perl -pe 's/&/\\\\sigma/g'
      | perl -pe 's/\\^/\\\\rho/g'
      | perl -pe 's/\\$/\\\\xi/g'
      | perl -pe 's/-([a-z]+)>/\\\\xrightarrow{\\\\text{\\\\sffamily\\\\scshape \\1}}/g'
      | perl -pe 's/!->/\\\\mapstochar\\\\relbar\\\\mathrel{\\\\mkern-12mu}\\\\mapsto/g'
      | perl -pe 's/->/\\\\mapsto/g'
      | perl -pe 's/:=/\\\\vDash/g'
      | perl -pe 's/\unexpanded{~}>/\\\\mapstochar\\\\dashrightarrow/g'
      | perl -pe 's/\\|([^\\|]+)\\|/\\\\texttt{\\1}/g'
      | perl -pe 's/\\[\\[/\\\\llbracket/g'
      | perl -pe 's/\\]\\]/\\\\rrbracket/g'
      | perl -pe 's/\\r\\r/\\\\\\\\ \&/g'
      | perl -pe 's/\\r/\\\\\\\\[-4pt] \&/g'
      | perl -pe 's/([^& ]) {2}([^ ])/\\1 \\2/g'
      | perl -pe 's/ {2}/\\\\quad{}/g'
      &&
    /bin/echo -n '\\end{split}\\end{#1}\\endinput'
  }%
}\makeatother
%    \end{macrocode}
% \end{macro}

% \begin{macro}{phiquation}
% Then, we define |phiquation| and |phiquation*| environments:
%    \begin{macrocode}
\makeatletter
\NewDocumentEnvironment{phiquation*}{b}{%
  \eolang@env{equation*}{#1}
}{}
\NewDocumentEnvironment{phiquation}{b}{%
  \eolang@env{equation}{#1}
}{}
\makeatother
\AddToHook{env/phiquation*/begin}{\obeylines\obeyspaces}
\AddToHook{env/phiquation/begin}{\obeylines\obeyspaces}
%    \end{macrocode}
% \end{macro}

% \begin{macro}{\phiq}
% \changes{0.0.2}{2022/10/21}{Parsing of additional symbols enabled}
% Then, we define |\phiq| command:
%    \begin{macrocode}
\newcommand\phiq[1]{
  \iexec[trace]{
    /bin/echo -n '$'
    &&
    /bin/echo -n '\detokenize{#1}'
      | perl -pe 's/\\^/\\\\rho/g'
      | perl -pe 's/\\$/\\\\xi/g'
      | perl -pe 's/&/\\\\sigma/g'
      | perl -pe 's/\\?/\\\\varnothing/g'
      | perl -pe 's/@/\\\\varphi/g'
      | perl -pe 's/!->/\\\\mapstochar\\\\relbar\\\\mathrel{\\\\mkern-12mu}\\\\mapsto/g'
      | perl -pe 's/->/\\\\mapsto/g'
      | perl -pe 's/-([a-z]+)>/\\\\xrightarrow{\\\\text{\\\\sffamily\\\\scshape \\1}}/g'
      | perl -pe 's/\unexpanded{~}>/\\\\mapstochar\\\\dashrightarrow/g'
      | perl -pe 's/:=/\\\\vDash/g'
      | perl -pe 's/\\[\\[/\\\\llbracket/g'
      | perl -pe 's/\\]\\]/\\\\rrbracket/g'
    &&
    /bin/echo -n '$\\endinput'
  }%
}
%    \end{macrocode}
% \end{macro}

% \begin{macro}{Perl}
% \changes{0.0.2}{2022/10/24}{The Perl file now has a fixed name, which doesn't depend on the name of the TeX job. This file may be shared among jobs, no need to make it uniquely named.}
% Then, create a Perl script:
%    \begin{macrocode}
\begin{VerbatimOut}{eolang.pl}
$tex = $ARGV[0];
$tex =~ s/^\s+|\s+$//g;
$tex =~ s/(\\[a-zA-Z]+)\s+/\1/g;
$tex =~ s/\r\s+/\r/g;
$tex =~ s/\|([^\|]+)\|/\\texttt{\1}/g;
my @cmds = split (/\r/g, $tex);
print '\begin{phig}', "\n";
foreach my $c (@cmds) {
  my ($head, $tail) = split (/ /, $c, 2);
  my %opts = {};
  foreach my $p (split (/ /, $tail)) {
    my ($q, $t) = split (/:/, $p);
    $opts{$q} = $t;
  }
  if (index($head, '->') == -1) {
    print '\node[';
    if (exists $opts{'xy'}) {
      my ($v, $right, $down) = split(/,/, $opts{'xy'});
      print ',below right=';
      print $down;
      print 'cm and ';
      print $right;
      print 'cm of ';
      print $v;
    }
    if (exists $opts{'data'}) {
      print ',phi-data';
      if (not $opts{'data'} eq '') {
        $opts{'box'} = $opts{'data'};
      }
    } elsif (exists $opts{'atom'}) {
      print ',phi-atom';
      if (not $opts{'atom'} eq '') {
        $opts{'box'} = $opts{'atom'};
      }
    } else {
      print ',phi-object';
    }
    print ']';
    print ' (', $head, ')';
    print ' {$';
    if ($head eq 'v0') {
      print '\Phi';
    } else {
      print 'v_', substr($head, 1);
    }
    print '$}';
    if (exists $opts{'box'}) {
      print ' node[phi-box] at (';
      print $head, '.south east) {';
      print $opts{'box'}, '}';
    }
  } else {
    print '\draw[';
    if (exists $opts{'pi'}) {
      print ',phi-pi';
      if (not exists $opts{'a'}) {
        $opts{'a'} = '$\pi$';
      }
    }
    print ']';
    my ($from, $to) = split (/->/, $head);
    print ' (', $from, ') ';
    if (exists $opts{'bend'}) {
      print 'edge [bend right=', $opts{'bend'}, ']';
    } else {
      print '--';
    }
    if (exists $opts{'rho'} or exists $opts{'rrho'}) {
      print ' pic[sloped,phi-rho]{parallel arrow={';
      print '-' if not exists $opts{'rrho'};
      print '0.3,-0.15}}';
    }
    if (exists $opts{'a'}) {
      print ' node [phi-attr] {', $opts{'a'}, '}';
    }
    print ' (', $to, ')';
  }
  print ";\n";
}
print '\end{phig}', "\n", '\endinput';
\end{VerbatimOut}
\message{^^Jeolang: File with Perl script (eolang.pl) saved^^J}%
\iexec[trace,null]{perl -pi -e 's/(\\\\[a-zA-Z])\\s+/\\1/g' eolang.pl}
%    \end{macrocode}
% \end{macro}

% \begin{macro}{tikz}
% Then, we include |tikz| package and its libraries:
%    \begin{macrocode}
\RequirePackage{tikz}
  \usetikzlibrary{arrows}
  \usetikzlibrary{shapes}
  \usetikzlibrary{decorations}
  \usetikzlibrary{decorations.pathmorphing}
  \usetikzlibrary{intersections}
  \usetikzlibrary{positioning}
  \usetikzlibrary{calc}
  \usetikzlibrary{shapes.arrows}
%    \end{macrocode}
% \end{macro}

% \begin{macro}{phig}
% Then, we define internal environment |phig|:
%    \begin{macrocode}
\newenvironment{phig}%
  {\noindent\begin{tikzpicture}[
    ->,>=stealth',node distance=0,thick,
    pics/parallel arrow/.style={
      code={\draw[-latex,phi-rho] (##1) -- (-##1);}}]}%
  {\end{tikzpicture}}
\tikzstyle{transforms} = [fill=white!80!black, single arrow,
  minimum height=0.5cm, minimum width=0.5cm,
  single arrow head extend=2mm]
\tikzstyle{phi-thing} = [thick,inner sep=0pt,minimum height=2.4em,
  draw,font={\small}]
\tikzstyle{phi-object} = [phi-thing,circle]
\tikzstyle{phi-data} = [phi-thing,regular polygon,
  regular polygon sides=8]
\tikzstyle{phi-empty} = [phi-object]
\tikzstyle{phi-rho} = [draw,decorate,decoration={
  snake,amplitude=.4mm,segment length=2mm,post length=1mm}]
\tikzstyle{phi-pi} = [draw,dotted]
\tikzstyle{phi-atom} = [phi-object,double]
\tikzstyle{phi-box} = [xshift=-5pt,yshift=3pt,draw,fill=white,
  rectangle,thin,minimum width=1.2em,anchor=north west,
  font={\scriptsize}]
\tikzstyle{phi-attr} = [midway,sloped,inner sep=0pt,
  above=2pt,sloped/.append style={transform shape},
  font={\scriptsize},color=black]
%    \end{macrocode}
% \end{macro}

% \begin{macro}{sodg}
% \changes{0.0.2}{2022/10/20}{The environment ``phigure'' renamed to ``sodg'' for the sake of better semantic. The graph in the picture is solely a SODG graph, that's why the name ``sodg'' is better.}
% Then, create a new environment |sodg|, as suggested
% \href{https://tex.stackexchange.com/questions/661056}{here}:
%    \begin{macrocode}
\NewDocumentEnvironment{sodg}{b}{%
  \catcode`\ =10 %
  \catcode`\^^M=5 %
  \iexec[trace,stdout=\jobname.tex.eolang]{
    perl eolang.pl '\detokenize{#1}'}%
}{}
\AddToHook{env/sodg/before}{\bgroup\obeylines\obeyspaces}
\AddToHook{env/sodg/after}{\egroup}
%    \end{macrocode}
% \end{macro}

% \Finale

% \clearpage
% \printbibliography
% \clearpage

% \PrintChanges
% \clearpage
% \PrintIndex
