% !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}