2022-08-23 17:25:52 +03:00
% !TEX TS-program = pdflatex
% !TeX spellcheck = en_US
% !TEX root = lama-spec.tex
2020-02-04 05:49:12 +03:00
\section { Expressions}
\label { sec:expressions}
2021-02-01 09:52:28 +03:00
The syntax definition for expressions is shown in Fig.~\ref { expressions} . The top-level construct is \emph { sequential composition} , expressed
2020-02-18 03:39:42 +03:00
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
2021-02-01 09:52:28 +03:00
in Fig.~\ref { builtin_ infixes} with the precedence level increasing top-to-bottom.
2020-02-18 03:39:42 +03:00
\begin { figure} [h]
2020-02-05 20:49:50 +03:00
\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 \\
2020-02-18 03:39:42 +03:00
\lstinline |*|, \lstinline |/|, \lstinline |%| & multiplication, quotient, remainder & left-associative
2020-02-05 20:49:50 +03:00
\end { tabular}
\caption { The precedence and associativity of built-in infix operators}
\label { builtin_ infixes}
\end { figure}
2020-02-05 01:18:20 +03:00
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
2021-02-01 09:52:28 +03:00
property is syntactically ensured using an inference system shown in Fig.~\ref { reference_ inference} ; here $ \mathcal { R } \, ( e ) $ designates the
2020-02-05 01:18:20 +03:00
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|".
2020-02-18 03:39:42 +03:00
\begin { figure} [h]
2024-07-09 14:53:56 +02:00
\renewcommand { \Ref } [1]{ \mathcal { R} \, ({ #1} )}
2020-02-18 03:39:42 +03:00
\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}
2020-02-05 20:49:50 +03:00
2021-02-01 09:52:28 +03:00
There are two postfix forms of expressions:
2020-02-05 01:18:20 +03:00
\begin { itemize}
\item function call, designated as postfix form "\lstinline |($ arg _ 1 , \dots , arg _ k $ )|";
2021-02-01 09:52:28 +03:00
\item array element selection, designated as "\lstinline |[$ index $ ]|".
2020-02-05 01:18:20 +03:00
\end { itemize}
2021-02-01 09:52:28 +03:00
Also, see postfix ``dot'' notation (Section~\ref { sec:dot-notation} ).
2020-02-05 01:18:20 +03:00
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}
2020-02-05 20:49:50 +03:00
The basic form of expression is \nonterm { primary} . The simplest form of primary is an identifier or constant. Keywords \lstinline |true| and \lstinline |false|
2021-02-01 09:52:28 +03:00
designate integer constants 1 and 0 respectively, character constant is implicitly converted into its \textsc { ASCII} code. String constants designate arrays
2020-02-19 15:28:29 +03:00
of one-byte characters. Infix constants allow to reference a functional value associated with corresponding infix operator (however, a value associated with
2020-04-13 04:28:43 +03:00
builtin assignment operator "\lstinline |:=|" can not be taken), and functional constant (\emph { lambda-expression} )
2021-02-01 09:52:28 +03:00
designates an anonymous functional value in the form of a closure.
2020-02-05 01:18:20 +03:00
2020-02-18 03:39:42 +03:00
\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 \\
2021-02-01 09:52:28 +03:00
& & \term { (} \s \nonterm { scopeExpression} \s \term { )} & \alt \\
2020-02-18 03:39:42 +03:00
& & \nonterm { listExpression} & \alt \\
& & \nonterm { arrayExpression} & \alt \\
& & \nonterm { S-expression} & \alt \\
& & \nonterm { ifExpression} & \alt \\
2021-02-01 09:52:28 +03:00
& & \nonterm { whileDoExpression} & \alt \\
& & \nonterm { doWhileExpression} & \alt \\
2020-02-18 03:39:42 +03:00
& & \nonterm { forExpression} & \alt \\
2024-07-09 14:53:56 +02:00
& & \nonterm { caseExpression} & \alt \\
& & \nonterm { letExpression} &
2020-02-18 03:39:42 +03:00
\end { array}
\]
\caption { Expression concrete syntax}
\label { expressions}
\end { figure}
\FloatBarrier
2021-02-01 09:52:28 +03:00
\subsection { \texttt { skip} Expression}
2020-02-05 01:18:20 +03:00
2020-02-05 20:49:50 +03:00
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).
2020-02-05 01:18:20 +03:00
2020-02-18 03:39:42 +03:00
\subsection { Arrays, Lists, and S-expressions}
2020-02-05 01:18:20 +03:00
2020-02-18 03:39:42 +03:00
\begin { figure} [h]
2020-02-05 20:49:50 +03:00
\[
\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}
2020-02-05 01:18:20 +03:00
\end { figure}
2024-07-09 14:53:56 +02:00
There are three forms of expressions to specify composite values: arrays, lists and S-expressions (see Fig.~\ref { composite_ expressions} ).
\FloatBarrier
\subsection { Let Expressions}
2025-03-09 21:34:17 +03:00
\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.
2024-07-09 14:53:56 +02:00
\FloatBarrier
2020-02-05 20:49:50 +03:00
\subsection { Conditional Expressions}
2020-02-18 03:39:42 +03:00
\begin { figure} [h]
2020-02-05 01:18:20 +03:00
\[
2020-02-05 20:49:50 +03:00
\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} &
2020-02-05 01:18:20 +03:00
\end { array}
\]
2020-02-05 20:49:50 +03:00
\caption { If-expression concrete syntax}
\label { if_ expression}
\end { figure}
2020-02-18 03:39:42 +03:00
Conditional expression branches the control depending in the value of a certain expression; the value zero is treated as falsity, nonzero as truth. An
2020-02-05 20:49:50 +03:00
extended form
\begin { lstlisting}
if $ \; c _ 1 \; $ then $ \; e 1 \; $
elif $ \; c _ 2 \; $ then $ \; e _ 2 \; $
...
else $ \; e _ { k + 1 } \; $
fi
\end { lstlisting}
2020-02-18 03:39:42 +03:00
is equivalent to a nested form
2020-02-05 20:49:50 +03:00
\begin { lstlisting}
if $ \; c _ 1 \; $ then $ \; e 1 \; $
else if $ \; c _ 2 \; $ then $ \; e _ 2 \; $
...
else $ \; e _ { k + 1 } \; $
fi
\end { lstlisting}
2020-02-18 03:39:42 +03:00
\FloatBarrier
2020-02-05 20:49:50 +03:00
\subsection { Loop Expressions}
\begin { figure} [t]
\[
\begin { array} { rcl}
2021-02-01 09:52:28 +03:00
\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} \\
2020-02-05 20:49:50 +03:00
& & \term { do} \nonterm { scopeExpresssion} \s \term { od}
\end { array}
\]
\caption { Loop expressions concrete syntax}
\label { loop_ expression}
\end { figure}
2021-02-01 09:52:28 +03:00
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.
2020-02-05 20:49:50 +03:00
2021-02-01 09:52:28 +03:00
The construct "\lstinline |do $ \; e \; $ while $ \; c \; $ od|" is derived and operationally equivalent to
2020-02-05 20:49:50 +03:00
\begin { lstlisting}
2021-02-01 09:52:28 +03:00
$ e \; $ ; while $ \; c \; $ do $ \; e \; $ od
2020-02-05 20:49:50 +03:00
\end { lstlisting}
2021-02-01 09:52:28 +03:00
However, the top-level local declarations in the body of "\lstinline |do$ \dots $ while$ \dots $ od|"-loop are visible in the condition expression:
2020-02-05 20:49:50 +03:00
\begin { lstlisting}
2021-02-01 09:52:28 +03:00
do var x = read () while x od
2020-02-05 20:49:50 +03:00
\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}
2021-02-01 09:52:28 +03:00
for var i; i := 0, i < 10, i := i + 1 do write (i) od
2020-02-05 20:49:50 +03:00
\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 \\
2021-02-01 09:52:28 +03:00
& & \term { \# } \s \term { box} & \alt \\
& & \term { \# } \s \term { val} & \alt \\
& & \term { \# } \s \term { str} & \alt \\
2020-02-05 20:49:50 +03:00
& & \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}
2020-02-05 01:18:20 +03:00
\end { figure}
2020-02-07 15:31:14 +03:00
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;
2021-02-01 09:52:28 +03:00
\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;
2020-02-07 15:31:14 +03:00
\item round brackets can be used for grouping.
\end { itemize}
2020-02-18 03:39:42 +03:00
All identifiers, occurred in a pattern, have to be pairwise distinct.
2020-02-07 15:31:14 +03:00
The matching against patterns in case-expression is performed deterministically in a top-down manner: a pattern
2020-02-18 03:39:42 +03:00
is matched against only if all previous matchings were unsuccessful. If no matching pattern is found, the execution
2020-02-07 15:31:14 +03:00
of the program stops with an error.
2020-02-05 20:49:50 +03:00
\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}
2020-02-18 03:39:42 +03:00
%\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}
2020-02-05 20:49:50 +03:00
2020-02-04 05:49:12 +03:00