mirror of
https://github.com/ProgramSnail/Lama.git
synced 2025-12-06 06:48:48 +00:00
346 lines
17 KiB
TeX
346 lines
17 KiB
TeX
% !TEX TS-program = pdflatex
|
|
% !TeX spellcheck = en_US
|
|
% !TEX root = lama-spec.tex
|
|
\section{Expressions}
|
|
\label{sec:expressions}
|
|
|
|
The syntax definition for expressions is shown in Fig.~\ref{expressions}. The top-level construct is \emph{sequential composition}, expressed
|
|
using right-associative connective "\term{;}". The basic blocks of sequential composition have the form of \nonterm{binaryExpression}, which is
|
|
a composition of infix operators and operands. The description above is given in a highly ambiguous form as it does not specify explicitly the
|
|
precedence and associativity of infix operators. The precedences and associativity of predefined built-in infix operators are shown
|
|
in Fig.~\ref{builtin_infixes} with the precedence level increasing top-to-bottom.
|
|
|
|
\begin{figure}[h]
|
|
\begin{tabular}{c|l|l}
|
|
infix operator(s) & description & associativity \\
|
|
\hline
|
|
\lstinline|:=| & assignment & right-associative \\
|
|
\lstinline|:| & list constructor & right-associative \\
|
|
\lstinline|!!| & disjunction & left-associative \\
|
|
\lstinline|&&| & conjunction & left-associative \\
|
|
\lstinline|==|, \lstinline|!=|, \lstinline|<=|, \lstinline|<|, \lstinline|>=|, \lstinline|>| & integer comparisons & non-associative \\
|
|
\lstinline|+|, \lstinline|-| & addition, subtraction & left-associative \\
|
|
\lstinline|*|, \lstinline|/|, \lstinline|%| & multiplication, quotient, remainder & left-associative
|
|
\end{tabular}
|
|
\caption{The precedence and associativity of built-in infix operators}
|
|
\label{builtin_infixes}
|
|
\end{figure}
|
|
|
|
Apart from assignment and list constructor all other built-in infix operators operate on signed integers; in conjunction and disjunction
|
|
any non-zero value is treated as truth and zero as falsity, and the result respects this convention.
|
|
|
|
The assignment operator is unique among all others in the sense that it requires its left operand to designate a \emph{reference}. This
|
|
property is syntactically ensured using an inference system shown in Fig.~\ref{reference_inference}; here $\mathcal{R}\,(e)$ designates the
|
|
property ``$e$ is a reference''. The result of assignment operator coincides with its right operand, thus
|
|
|
|
\begin{lstlisting}
|
|
x := y := 3
|
|
\end{lstlisting}
|
|
|
|
assigns 3 to both "\lstinline|x|" and "\lstinline|y|".
|
|
|
|
\begin{figure}[h]
|
|
\renewcommand{\Ref}[1]{\mathcal{R}\,({#1})}
|
|
\renewcommand{\arraystretch}{4}
|
|
\[
|
|
\begin{array}{cc}
|
|
\Ref{x},\,x\;\mbox{is a variable}&\dfrac{\Ref{e}}{\Ref{\lstinline|$e$ [$\dots$]|}}\\
|
|
\dfrac{\Ref{e_i}}{\Ref{\mbox{\lstinline|if $\dots$ then $\;e_1\;$ else $\;e_2\;$ fi|}}} & \dfrac{\Ref{e_i}}{\Ref{\mbox{\lstinline|case $\dots$ of $\;\dots\;$ -> $\;e_1\;\dots\;\dots\;$ -> $\;e_k\;$ esac|}}}\\
|
|
\multicolumn{2}{c}{\dfrac{\Ref{e}}{\Ref{\lstinline|$\dots\;$;$\;e$|}}}
|
|
\end{array}
|
|
\]
|
|
\caption{Reference inference system}
|
|
\label{reference_inference}
|
|
\end{figure}
|
|
|
|
\subsection{Postfix Expressions}
|
|
|
|
There are two postfix forms of expressions:
|
|
|
|
\begin{itemize}
|
|
\item function call, designated as postfix form "\lstinline|($arg_1, \dots, arg_k$)|";
|
|
\item array element selection, designated as "\lstinline|[$index$]|".
|
|
\end{itemize}
|
|
|
|
Also, see postfix ``dot'' notation (Section~\ref{sec:dot-notation}).
|
|
|
|
Multiple postfixes are allowed, for example
|
|
|
|
\begin{lstlisting}
|
|
x () [3] (1, 2, 3) . string
|
|
x . string [4]
|
|
x . length . string
|
|
x . string . length
|
|
\end{lstlisting}
|
|
|
|
The basic form of expression is \nonterm{primary}. The simplest form of primary is an identifier or constant. Keywords \lstinline|true| and \lstinline|false|
|
|
designate integer constants 1 and 0 respectively, character constant is implicitly converted into its \textsc{ASCII} code. String constants designate arrays
|
|
of one-byte characters. Infix constants allow to reference a functional value associated with corresponding infix operator (however, a value associated with
|
|
builtin assignment operator "\lstinline|:=|" can not be taken), and functional constant (\emph{lambda-expression})
|
|
designates an anonymous functional value in the form of a closure.
|
|
|
|
\begin{figure}[h]
|
|
\[
|
|
\begin{array}{rcll}
|
|
\defterm{expression} & : & \nonterm{basicExpression}\s(\s\term{;}\s\nonterm{expression}\s)&\\
|
|
\defterm{basicExpression} & : & \nonterm{binaryExpression}&\\
|
|
\defterm{binaryExpression} & : & \nonterm{binaryOperand}\s\token{INFIX}\s\nonterm{binaryOperand}&\alt\\
|
|
& & \nonterm{binaryOperand}&\\
|
|
\defterm{binaryOperand} & : & \nonterm{binaryExpression}&\alt\\
|
|
& & [\s\term{-}\s]\s\nonterm{postfixExpression}&\\
|
|
\defterm{postfixExpression} & : & \nonterm{primary}&\alt\\
|
|
& & \nonterm{postfixExpression}\s\term{(}\s[\s\nonterm{expression}\s(\s\term{,}\s\nonterm{expression}\s)^\star\s]\s\term{)}&\alt\\
|
|
& & \nonterm{postfixExpression}\s\term{[}\s\nonterm{expression}\s\term{]}&\alt\\
|
|
\defterm{primary} & : & \token{DECIMAL}&\alt\\
|
|
& & \token{STRING}&\alt\\
|
|
& & \token{CHAR}&\alt\\
|
|
& & \token{LIDENT}&\alt\\
|
|
& & \term{true}&\alt\\
|
|
& & \term{false}&\alt\\
|
|
& & \term{infix}\s\token{INFIX}&\alt\\
|
|
& & \term{fun}\s\term{(}\s\nonterm{functionArguments}\s\term{)}\s\nonterm{functionBody}&\alt\\
|
|
& & \term{skip}&\alt\\
|
|
& & \term{(}\s\nonterm{scopeExpression}\s\term{)}&\alt\\
|
|
& & \nonterm{listExpression}&\alt\\
|
|
& & \nonterm{arrayExpression}&\alt\\
|
|
& & \nonterm{S-expression}&\alt\\
|
|
& & \nonterm{ifExpression}&\alt\\
|
|
& & \nonterm{whileDoExpression}&\alt\\
|
|
& & \nonterm{doWhileExpression}&\alt\\
|
|
& & \nonterm{forExpression}&\alt\\
|
|
& & \nonterm{caseExpression}&\alt\\
|
|
& & \nonterm{letExpression}&
|
|
\end{array}
|
|
\]
|
|
\caption{Expression concrete syntax}
|
|
\label{expressions}
|
|
\end{figure}
|
|
|
|
\FloatBarrier
|
|
\subsection{\texttt{skip} Expression}
|
|
|
|
Expression \lstinline|skip| can be used to designate a no-value when no action is needed (for example, in the body of unit which contains only declarations).
|
|
|
|
\subsection{Arrays, Lists, and S-expressions}
|
|
|
|
\begin{figure}[h]
|
|
\[
|
|
\begin{array}{rcl}
|
|
\defterm{arrayExpression} & : & \term{[}\s[\s\nonterm{expression}\s(\s\term{,}\s\nonterm{expression}\s)^\star\s]\s\term{]}\\
|
|
\defterm{listExpression} & : & \term{\{}\s[\s\nonterm{expression}\s(\s\term{,}\s\nonterm{expression}\s)^\star\s]\s\term{\}}\\
|
|
\defterm{S-expression} & : & \token{UIDENT}\s[\s\term{(}\s\nonterm{expression}\s[\s(\s\term{,}\s\nonterm{expression}\s)^\star\s]\term{)}\s]
|
|
\end{array}
|
|
\]
|
|
\caption{Array, list, and S-expressions concrete syntax}
|
|
\label{composite_expressions}
|
|
\end{figure}
|
|
|
|
There are three forms of expressions to specify composite values: arrays, lists and S-expressions (see Fig.~\ref{composite_expressions}).
|
|
|
|
\FloatBarrier
|
|
|
|
\subsection{Let Expressions}
|
|
|
|
\begin{figure}[h]
|
|
\[
|
|
\begin{array}{rcll}
|
|
\defterm{letExpression} & : & \term{let}\s\nonterm{pattern}\s\term{=}\s\nonterm{expression}\s\term{in}\s\nonterm{expression}
|
|
\end{array}
|
|
\]
|
|
\caption{Let-expression syntax}
|
|
\label{let_expression}
|
|
\end{figure}
|
|
|
|
Let expression is a derived syntactic form for a one-branch case-expression. An expression
|
|
|
|
\begin{lstlisting}
|
|
let p = e in b
|
|
\end{lstlisting}
|
|
|
|
is equivalent to
|
|
|
|
\begin{lstlisting}
|
|
case e of
|
|
p -> b
|
|
esac
|
|
\end{lstlisting}
|
|
|
|
As let expression lacks an explicit ending specifier its scope extends to the right while possible; multiple let expressions on
|
|
the same nesting level associate to the right.
|
|
|
|
|
|
\FloatBarrier
|
|
|
|
\subsection{Conditional Expressions}
|
|
|
|
\begin{figure}[h]
|
|
\[
|
|
\begin{array}{rcll}
|
|
\defterm{ifExpression} & : & \term{if}\s\nonterm{expression}\s\term{then}\s\nonterm{scopeExpression}\s[\s\nonterm{elsePart}\s]\s\term{fi}&\\
|
|
\defterm{elsePart} & : & \term{elif}\s\nonterm{expression}\s\term{then}\s\nonterm{scopeExpression}\s[\s\nonterm{elsePart}\s]&\alt\\
|
|
& & \term{else}\s\nonterm{scopeExpression}&
|
|
\end{array}
|
|
\]
|
|
\caption{If-expression concrete syntax}
|
|
\label{if_expression}
|
|
\end{figure}
|
|
|
|
Conditional expression branches the control depending in the value of a certain expression; the value zero is treated as falsity, nonzero as truth. An
|
|
extended form
|
|
|
|
\begin{lstlisting}
|
|
if $\;c_1\;$ then $\;e1\;$
|
|
elif $\;c_2\;$ then $\;e_2\;$
|
|
...
|
|
else $\;e_{k+1}\;$
|
|
fi
|
|
\end{lstlisting}
|
|
|
|
is equivalent to a nested form
|
|
|
|
\begin{lstlisting}
|
|
if $\;c_1\;$ then $\;e1\;$
|
|
else if $\;c_2\;$ then $\;e_2\;$
|
|
...
|
|
else $\;e_{k+1}\;$
|
|
fi
|
|
\end{lstlisting}
|
|
|
|
\FloatBarrier
|
|
|
|
\subsection{Loop Expressions}
|
|
|
|
\begin{figure}[t]
|
|
\[
|
|
\begin{array}{rcl}
|
|
\defterm{whileDoExpression} & : & \term{while}\s\nonterm{expression}\s\term{do}\s\nonterm{scopeExpression}\s\term{od}\\
|
|
\defterm{doWhileExpression} & : & \term{do}\s\nonterm{scopeExpression}\s\term{while}\s\nonterm{expression}\s\term{od}\\
|
|
\defterm{forExpression} & : & \term{for}\s\nonterm{scopeExpression}\s\term{,}\s\nonterm{expression}\s\term{,}\s\nonterm{expression}\\
|
|
& & \term{do}\nonterm{scopeExpresssion}\s\term{od}
|
|
\end{array}
|
|
\]
|
|
\caption{Loop expressions concrete syntax}
|
|
\label{loop_expression}
|
|
\end{figure}
|
|
|
|
There are three forms of loop expressions~--- "\lstinline|while$\dots$do$\dots$od|", "\lstinline|do$\dots$while$\dots$od|", and "\lstinline|for$\dots$|", among
|
|
which "\lstinline|while$\dots$do$\dots$od|" is the basic one (see Fig.~\ref{loop_expression}). In "\lstinline|while$\dots$do$\dots$od|" expression the evaluation
|
|
of the body is repeated as long as the evaluation of condition provides a non-zero value. The condition is evaluated before the body on each iteration of the loop,
|
|
and the body is evaluated in the context of condition evaluation results.
|
|
|
|
The construct "\lstinline|do $\;e\;$ while $\;c\;$ od|" is derived and operationally equivalent to
|
|
|
|
\begin{lstlisting}
|
|
$e\;$; while $\;c\;$ do $\;e\;$ od
|
|
\end{lstlisting}
|
|
|
|
However, the top-level local declarations in the body of "\lstinline|do$\dots$while$\dots$od|"-loop are visible in the condition expression:
|
|
|
|
\begin{lstlisting}
|
|
do var x = read () while x od
|
|
\end{lstlisting}
|
|
|
|
|
|
The construct "\lstinline|for $\;i\;$, $\;c\;$, $\;s\;$ do $\;e\;$ od|" is also derived and operationally equivalent to
|
|
|
|
\begin{lstlisting}
|
|
$i\;$; while $\;c\;$ do $\;e\;$; $\;s\;$ od
|
|
\end{lstlisting}
|
|
|
|
However, the top-level local definitions of the the first expression ("$i$") are visible in the rest of the construct:
|
|
|
|
\begin{lstlisting}
|
|
for var i; i := 0, i < 10, i := i + 1 do write (i) od
|
|
\end{lstlisting}
|
|
|
|
\subsection{Pattern Matching}
|
|
|
|
\begin{figure}[t]
|
|
\[
|
|
\begin{array}{rcll}
|
|
\defterm{pattern} & : & \nonterm{consPattern}\alt\nonterm{simplePattern}&\\
|
|
\defterm{consPattern} & : & \nonterm{simplePattern}\s\term{:}\s\nonterm{pattern}&\\
|
|
\defterm{simplePattern} & : & \nonterm{wildcardPattern} & \alt\\
|
|
& & \nonterm{S-exprPattern} & \alt \\
|
|
& & \nonterm{arrayPattern} & \alt \\
|
|
& & \nonterm{listPattern} & \alt \\
|
|
& & \token{LIDENT}\s[\s\term{@}\s\nonterm{pattern} \s] & \alt \\
|
|
& & [\s\term{-}\s]\s\token{DECIMAL}& \alt \\
|
|
& & \token{STRING} & \alt \\
|
|
& & \token{CHAR} & \alt \\
|
|
& & \term{true} & \alt \\
|
|
& & \term{false} & \alt \\
|
|
& & \term{\#}\s\term{box} & \alt \\
|
|
& & \term{\#}\s\term{val} & \alt \\
|
|
& & \term{\#}\s\term{str} & \alt \\
|
|
& & \term{\#}\s\term{array} & \alt \\
|
|
& & \term{\#}\s\term{sexp} & \alt \\
|
|
& & \term{\#}\s\term{fun} & \alt \\
|
|
& & \term{(}\s\nonterm{pattern}\s\term{)} & \\
|
|
\defterm{wildcardPattern} & : & \term{\_} &\\
|
|
\defterm{S-exprPattern} & : & \token{UIDENT}\s[\s\term{(}\s\nonterm{pattern}\s(\s\term{,}\s\nonterm{pattern})^\star\s\term{)}\s] &\\
|
|
\defterm{arrayPattern} & : & \term{[}\s[\s\nonterm{pattern}\s(\s\term{,}\s\nonterm{pattern})^\star\s]\s\term{]} &\\
|
|
\defterm{listPattern} & : & \term{\{}\s[\s\nonterm{pattern}\s(\s\term{,}\s\nonterm{pattern})^\star\s]\s\term{\}} &
|
|
\end{array}
|
|
\]
|
|
\caption{Pattern concrete syntax}
|
|
\label{pattern}
|
|
\end{figure}
|
|
|
|
Pattern matching is introduced into the language by the mean of \emph{case-expression} (see Fig.~\ref{case_expression}). A case-expression
|
|
evaluates an expression, called \emph{scrutinee}, and performs branching depending on its structure. This structure is specified by
|
|
means of \emph{patterns} (see Fig.~\ref{pattern}). If succeeded, a matching against a pattern delivers a
|
|
set of bindings~--- variables with their bindings to the (sub)values of the scrutinee.
|
|
|
|
The semantics of patterns is as follows:
|
|
|
|
\begin{itemize}
|
|
\item a pattern "\lstinline|$p_1$:$p_2$|" matches a list with a head matched with $p_1$ and a tail matched with $p_2$;
|
|
\item wildcard pattern "\lstinline|_|" matches every value;
|
|
\item S-expression pattern "\lstinline|$C\;$ ($p_1$,$\dots$,$\;p_k$)|" matches a value with corresponding top-level
|
|
tag ("$C$") and arguments matched by subpatterns $p_i$ respectively; note, patterns can discriminate on the
|
|
number of arguments for the same constructor, thus the same tag with different number of arguments can be
|
|
used in different branches of the same case expression (see below);
|
|
\item array and list patterns match arrays and lists of the specified length with each element matched with
|
|
corresponding subpattern;
|
|
\item an identifier matches every value and binds itself to that value in the corresponding branch of
|
|
case-expression (see below);
|
|
\item a "\lstinline|$x$@$p$|"-pattern matches what pattern $p$ matches, and additionally binds the
|
|
matched value to the identifier $x$;
|
|
\item constant patterns match corresponding constants;
|
|
\item six "\lstinline|#|"-patterns match values of corresponding shapes (reference values (\lstinline|box|), primitive values (\lstinline|val|),
|
|
strings (\lstinline|str|), arrays, S-expressions or closures (\lstinline|fun|)) regardless their content;
|
|
\item round brackets can be used for grouping.
|
|
\end{itemize}
|
|
|
|
All identifiers, occurred in a pattern, have to be pairwise distinct.
|
|
|
|
The matching against patterns in case-expression is performed deterministically in a top-down manner: a pattern
|
|
is matched against only if all previous matchings were unsuccessful. If no matching pattern is found, the execution
|
|
of the program stops with an error.
|
|
|
|
\begin{figure}[t]
|
|
\[
|
|
\begin{array}{rcl}
|
|
\defterm{caseExpression} & : & \term{case}\s\nonterm{expression}\s\term{of}\s\nonterm{caseBranches}\s\term{esac}\\
|
|
\defterm{caseBranches} & : & \nonterm{caseBranch}\s[\s(\s\term{$\mid$}\s\nonterm{caseBranch}\s)^\star\s]\\
|
|
\defterm{caseBranch} & : & \nonterm{pattern}\s\term{$\rightarrow$}\s\nonterm{scopeExpression}
|
|
\end{array}
|
|
\]
|
|
\caption{Case-expression concrete syntax}
|
|
\label{case_expression}
|
|
\end{figure}
|
|
|
|
%\subsection{Examples}
|
|
%\label{sec:expression_examples}
|
|
%
|
|
%Some other examples with comments:
|
|
%
|
|
%\begin{tabular}{ll}
|
|
% "\lstinline|x !! y && z + 3|" & is equivalent to "\lstinline|x !! (y && (z + 3))|"\\
|
|
% "\lstinline|x == y < 4|" & invalid \\
|
|
% "\lstinline|x [y := 8] := 6|" & is equivalent to "\lstinline|y := 8; x [8] := 6|"\\
|
|
% "\lstinline|(write (3); x) := (write (4); z)|" & is equivalent to "\lstinline|write (3); write (4); x := z|"
|
|
%\end{tabular}
|
|
|
|
|