\documentclass{article} \usepackage{luacas} \usepackage{amsmath} \usepackage{amssymb} \usepackage[margin=1in]{geometry} \usepackage[shortlabels]{enumitem} \usepackage{pgfplots} \pgfplotsset{compat=1.18} \usetikzlibrary{positioning,calc} \usepackage{forest} \usepackage{minted} \usemintedstyle{pastie} \usepackage[hidelinks]{hyperref} \usepackage{parskip} \usepackage{multicol} \usepackage[most]{tcolorbox} \tcbuselibrary{xparse,documentation} \usepackage{microtype} \usepackage{makeidx} \usepackage{fontawesome5} \usepackage{marginnote} \usepackage[ backend=biber, style=numeric, ]{biblatex} \addbibresource{sources.bib} \definecolor{rose}{RGB}{128,0,0} \definecolor{roseyellow}{RGB}{222,205,99} \definecolor{roseblue}{RGB}{167,188,214} \definecolor{rosenavy}{RGB}{79,117,139} \definecolor{roseorange}{RGB}{232,119,34} \definecolor{rosegreen}{RGB}{61,68,30} \definecolor{rosewhite}{RGB}{223,209,167} \definecolor{rosebrown}{RGB}{108,87,27} \definecolor{rosegray}{RGB}{84,88,90} \definecolor{codegreen}{HTML}{49BE25} \newtcolorbox{codebox}[1][sidebyside]{ enhanced,skin=bicolor, #1, arc=1pt, colframe=brown, colback=brown!15,colbacklower=white, boxrule=1pt, notitle } \newtcolorbox{codehead}[1][]{ enhanced, frame hidden, colback=rosegray!15, boxrule=0mm, leftrule=5mm, rightrule=5mm, boxsep=0mm, arc=0mm, outer arc=0mm, left=3mm, right=3mm, top=1mm, bottom=1mm, toptitle=1mm, bottomtitle=1mm, oversize, #1 } \usepackage{varwidth} \newtcolorbox{newcodehead}[2][]{ enhanced, frame hidden, colback=rosegray!15, boxrule=0mm, leftrule=5mm, rightrule=5mm, boxsep=0mm, arc=0mm, outer arc=0mm, left=3mm, right=3mm, top=1mm, bottom=1mm, toptitle=1mm, bottomtitle=1mm, oversize, #1, fonttitle=\bfseries\ttfamily\footnotesize, coltitle=rosegray, attach boxed title to top text right, boxed title style={frame hidden,size=small,bottom=-1mm, interior style={fill=none, top color=white, bottom color=white}}, title={#2} } \makeindex \newcommand{\coderef}[2]{% \begin{codehead}[sidebyside,segmentation hidden]% \mintinline{lua}{#1}% \tcblower% \begin{flushright}% \mintinline{lua}{#2}% \end{flushright}% \end{codehead}% } \newcommand{\newcoderef}[3]{% \begin{newcodehead}[sidebyside,segmentation hidden]{#3}% \mintinline{lua}{#1}% \tcblower% \begin{flushright}% \mintinline{lua}{#2}% \end{flushright}% \end{newcodehead}% } \begin{document} \subsection{Core Classes} There are several classes in the core module; but only some classes are concrete: \begin{multicols}{2} \begin{center} \underline{Abstract classes:} \begin{itemize} \item \texttt{Expression} \item \texttt{AtomicExpression} \item \texttt{CompoundExpression} \item \texttt{ConstantExpression} \end{itemize} \underline{Concrete classes:} \begin{itemize} \item \texttt{SymbolExpression} \item \texttt{BinaryOperation} \item \texttt{FunctionExpression} \end{itemize} \end{center} \end{multicols} The abstract classes provide a unified interface for the concrete classes (expressions) using inheritance. \emph{Every} expression in \texttt{luacas} inherits from either {\ttfamily AtomicExpression} or {\ttfamily CompoundExpression} which, in turn, inherit from {\ttfamily Expression}. \coderef{function SymbolExpression:new(string)}{return SymbolExpression} \index{Core!Classes!\texttt{SymbolExpression}} \addcontentsline{toc}{subsubsection}{\ttfamily SymbolExpression} Creates a new \texttt{SymbolExpression}. For example: \begin{codebox}[] \begin{minted}[breaklines,fontsize=\small]{lua} foo = SymbolExpression("bar") tex.sprint("The Lua variable ``foo'' is the SymbolExpression: ", foo:tolatex(),".") \end{minted} \tcblower \directlua{ foo = SymbolExpression("bar") tex.sprint("The Lua variable 'foo' is the SymbolExpression: ", foo:tolatex(),".") } \end{codebox} \subsubsection*{Fields} \texttt{SymbolExpression}s have only one field: \texttt{symbol}. In the example above, the string \mintinline{lua}{"bar"} is stored in \mintinline{lua}{foo.symbol}. \subsubsection*{Parsing} The command \mintinline{lua}{vars()} in \texttt{test.parser} creates a new \texttt{SymbolExpression} for every string in the argument; each such \texttt{SymbolExpression} is assigned to a variable of the same name. For example: \begin{minted}{lua} vars('x','y') \end{minted} is equivalent to: \begin{minted}{lua} x = SymbolExpression("x") y = SymbolExpression("y") \end{minted} \newcoderef{function BinaryOperation:new(operation, expressions)}{return BinaryOperation}{operation function, expressions table} \index{Core!Classes!\texttt{BinaryOperation}} \addcontentsline{toc}{subsubsection}{\ttfamily BinaryOperation} Creates a new \texttt{BinaryOperation} expression. For example: \begin{codebox} \begin{minted}[fontsize=\small]{lua} vars('x','y','z') w = BinaryOperation( BinaryOperation.ADD, {BinaryOperation( BinaryOperation.MUL, {x,y} ),y,z} ) tex.print("\\[w=",w:tolatex(),"\\]") \end{minted} \tcblower \directlua{ vars('x','y','z') w = BinaryOperation( BinaryOperation.ADD, {BinaryOperation( BinaryOperation.MUL, {x,y} ),y,z} ) tex.print("\\[w=",w:tolatex(),"\\]") } \end{codebox} The variable \texttt{operation} must be a function \mintinline{lua}{function f(a,b)} assigned to one of the following types: \bgroup \setdescription{style=multiline, topsep=10pt, leftmargin=4.5cm, font=\ttfamily } \begin{description} \item[BinaryOperation.ADD:] \mintinline{lua}{return a + b} \item[BinaryOperation.SUB:] \mintinline{lua}{return a - b} \item[BinaryOperation.MUL:] \mintinline{lua}{return a * b} \item[BinaryOperation.DIV:] \mintinline{lua}{return a / b} \item[BinaryOperation.IDIV:] \mintinline{lua}{return a // b} \item[BinaryOperation.MOD:] \mintinline{lua}{return a % b} \item[BinaryOperation.POW:] \mintinline{lua}{return a ^ b} \end{description} \egroup The variable \texttt{expressions} must be a table of \texttt{Expression}s index by Lua numbers. \subsubsection*{Fields} \texttt{BinaryOperation}s have the following fields: \texttt{name}, \texttt{operation}, and \texttt{expressions}. In the example above, we have: \begin{itemize} \item the variable \texttt{expressions} is stored in \mintinline{lua}{w.expressions}; \item \mintinline{lua}{w.name} stores the string \mintinline{lua}{"+"}; and \item \mintinline{lua}{w.operation} stores the function: \begin{minted}{lua} BinaryOperation.ADD = function(a, b) return a + b end \end{minted} \end{itemize} \begin{multicols}{2} The entries of \texttt{w.expressions} can be used/fetched in a reasonable way: \begin{codebox}[] \begin{minted}[fontsize=\small]{latex} $\print{w.expressions[1]} \quad \print{w.expressions[2]} \quad \print{w.expressions[3]}$ \end{minted} \tcblower $\print{w.expressions[1]} \quad \print{w.expressions[2]} \quad \print{w.expressions[3]}$ \end{codebox} \begin{center} \bracketset{action character = @} \parseshrub{w} \begin{forest} for tree = {font = \ttfamily, draw, rounded corners = 1pt, fill = gray!20, l sep = 1.5cm, s sep = 2cm} @\shrubresult \end{forest} \end{center} \end{multicols} \subsubsection*{Parsing} Thank goodness for this. Creating new \texttt{BinaryOperation}s isn't nearly as cumbersome as the above would indicate. Using Lua's powerful metamethods, we can parse expressions easily. For example, the construction of \texttt{w} given above can be done much more naturally using: \begin{codebox} \begin{minted}[fontsize=\small]{lua} vars('x','y','z') w = x*y+y+z tex.print("\\[w=", w:tolatex(), "\\]") \end{minted} \tcblower \directlua{ vars('x','y','z') w = x*y+y+z tex.print("\\[w=", w:tolatex(), "\\]") } \end{codebox} \reversemarginpar {\bf Warning:}\marginnote{\color{rose}\faExclamationTriangle} There are escape issues to be aware of with the operator \mintinline{latex}{%}. If you're writing custom \texttt{luacas} functions in a separate \texttt{.lua} file, then there are no issues; use \mintinline{latex}{%} with reckless abandon. But when using the operator \mintinline{latex}{%} within, say \mintinline{latex}{\begin{CAS}..\end{CAS}}, then one should write \mintinline{latex}{\%} in place of \mintinline{latex}{%}: \begin{codebox} \begin{minted}[breaklines,fontsize=\small]{latex} \begin{CAS} a = 17 b = 5 c = a \% b \end{CAS} \[ \print{c} \equiv \print{a} \bmod{\print{b}} \] \end{minted} \tcblower \begin{CAS} a = 17 b = 5 c = a \% b \end{CAS} \[ \print{c} \equiv \print{a} \bmod{\print{b}} \] \end{codebox} The above escape will {\bf not} work with \mintinline{latex}{\directlua}, but it will work for \mintinline{latex}{\luaexec} from the \texttt{luacode} package. Indeed, the \texttt{luacode} package was designed (in part) to make escapes like this more manageable. Here is the equivalent code using \mintinline{latex}{\luaexec}: \begin{codebox}[] \begin{minted}[fontsize=\small]{lua} a = Integer(17) b = Integer(5) c = a \% b tex.print("\\[",c:tolatex(),"\\equiv",a:tolatex(), "\\bmod{",b:tolatex(),"} \\]") \end{minted} \tcblower \luaexec{ a = Integer(17) b = Integer(5) c = a \% b tex.print("\\[", c:tolatex(), "\\equiv", a:tolatex(), "\\bmod{", b:tolatex(), "} \\]") } \end{codebox} \newcoderef{function FunctionExpression:new(name,expressions)}{return FunctionExpression}{name string|SymbolExpression, expressions table} \index{Core!Classes!\texttt{FunctionExpression}} \addcontentsline{toc}{subsubsection}{\ttfamily FunctionExpression} Creates a generic function. For example: \begin{codebox} \begin{minted}[fontsize=\small]{lua} vars('x','y') f = FunctionExpression('f',{x,y}) tex.print("\\[",f:tolatex(),"\\]") \end{minted} \tcblower \luaexec{ vars('x','y') f = FunctionExpression('f',{x,y}) tex.print("\\[",f:tolatex(),"\\]") } \end{codebox} The variable \texttt{name} can be a string (like above), or another \texttt{SymbolExpression}. But in this case, the variable \texttt{name} just takes the value of the string \mintinline{lua}{SymbolExpression.symbol}. The variable \texttt{expressions} must be a table of \texttt{Expression}s indexed by Lua numbers. \subsubsection*{Fields} \texttt{FunctionExpression}s have the following fields: \texttt{name}, \texttt{expressions}, \texttt{variables}, \texttt{derivatives}. In the example above, we have: \begin{itemize} \item the variable \texttt{name}, i.e. the string \mintinline{lua}{'f'}, is stored in \mintinline{lua}{f.name}; and \item the variable \texttt{expressions}, i.e. the table \mintinline{lua}{{x,y}} is stored in \mintinline{lua}{f.expressions}. \end{itemize} Wait a minute, what about \texttt{variables} and \texttt{derivatives}!? The field \texttt{variables} essentially stores a copy of the variable \texttt{expressions} \textit{as long as} the entries in that table are atomic. If they aren't, then \texttt{variables} will default to $x,y,z$, or $x_1,x_2,\ldots$ if the number of variables exceeds $3$. For example: \begin{codebox} \begin{minted}[fontsize=\small]{lua} vars('s','t') f = FunctionExpression('f',{s*s,s+t+t}) tex.print("The variables of f are:") for _,symbol in ipairs(f.variables) do tex.print(symbol:tolatex()) end \end{minted} \tcblower \luaexec{ vars('s','t') f = FunctionExpression('f',{s*s,s+t+t}) tex.print("The variables of f are:") for _,symbol in ipairs(f.variables) do tex.print(symbol:tolatex()) end } \end{codebox} The field \texttt{derivatives} is a table of \texttt{Integer}s indexed by Lua numbers whose length equals \mintinline{lua}{#o.variables}. The default value for this table is a table of (\texttt{Integer}) zeros. So for the example above, we have: \begin{codebox} \begin{minted}[fontsize=\small]{lua} for _,integer in ipairs(f.derivatives) do if integer == Integer.zero() then tex.print("I'm a zero.\\newline") end end \end{minted} \tcblower \luaexec{ for _,integer in ipairs(f.derivatives) do if integer == Integer.zero() then tex.print("I'm a zero.\\newline") end end } \end{codebox} We can change the values of \texttt{variables} and \texttt{derivatives} manually (or more naturally by other gizmos found in \texttt{luacas}). For example, keeping the variables from above, we have: \begin{multicols}{2} \begin{codebox}[] \begin{minted}[fontsize=\small]{lua} f.derivatives = {Integer.one(), Integer.one()} tex.print("\\[", f:simplify():tolatex(), "\\]") \end{minted} \tcblower \luaexec{ f.derivatives = {Integer.one(),Integer.one()} tex.print("\\[", f:simplify():tolatex(), "\\]") } \end{codebox} \begin{center} \parseshrub{f} \bracketset{action character = @} \begin{forest} for tree = {font = \ttfamily, draw, rounded corners = 1pt, fill = gray!20, l sep = 1.5cm, s sep = 0.75cm} @\shrubresult \end{forest} \end{center} \end{multicols} \subsubsection*{Parsing} Thank goodness for this too. The parser nested within the \LaTeX{} environment \mintinline{latex}{\begin{CAS}..\end{CAS}} allows for fairly natural function assignment; the name of the function must be declared in \mintinline{lua}{vars(...)} (or rather, as a \texttt{SymbolExpression}) beforehand: \begin{codebox} \begin{minted}[fontsize=\small]{latex} \begin{CAS} vars('s','t','f') f = f(s^2,s+2*t) f.derivatives = {1,1} \end{CAS} \[ \print{f} \] \end{minted} \tcblower \begin{CAS} vars('s','t','f') f = f(s^2,s+2*t) f.derivatives = {1,1} \end{CAS} \[ \print{f} \] \end{codebox} \end{document}