% !TEX TS-program = pdflatex
% !TeX spellcheck = en_US
% !TEX root = lama-spec.tex
\begin{figure}[t]
  \[
    \begin{array}{rclc}
      \defterm{scopeExpression}                & : & \nonterm{definition}^\star\s[\s\nonterm{expression}\s]&\\
      \defterm{definition}                     & : & \nonterm{variableDefinition}&\alt\\
                                               &   & \nonterm{functionDefinition}&\alt\\
                                               &   & \nonterm{infixDefinition}&\\
      \defterm{variableDefinition}             & : & (\s\term{var}\alt\term{public}\s)\s\nonterm{variableDefinitionSequence}\s\term{;}&\\
      \defterm{variableDefinitionSequence}     & : & \nonterm{variableDefinitionItem}\s(\s\term{,}\s\nonterm{variableDefinitionItem}\s)^\star&\\
      \defterm{variableDefinitionItem}         & : & \token{LIDENT}\s[\s\term{=}\s\nonterm{basicExpression}\s]&\\
      \defterm{functionDefinition}             & : & [\s\term{public}\s]\s\term{fun}\s\token{LIDENT}\s\term{(}\s\nonterm{functionArguments}\s\term{)}&\\
                                               &   & \phantom{XXXXX}\nonterm{functionBody}&\\
      \defterm{functionArguments}              & : & [\s\token{LIDENT}\s(\s\term{,}\s\token{LIDENT}\s)^\star\s]&\\
      \defterm{functionBody}                   & : & \term{\{}\s\nonterm{scopeExpression}\s\term{\}}&
    \end{array}
  \]
  \caption{Scope expression concrete syntax}
  \label{scope_expression}
\end{figure}

\section{Scope Expressions}
\label{sec:scope_expressions}

Scope expressions provide a mean to put expressions is a scoped context. The definitions in scoped expressions comprise of function definitions and
variable definitions (see Fig.~\ref{scope_expression}). For example:

\begin{lstlisting}
    var x, y, z; -- variable definitions

    fun id (x) {x} -- function definition
\end{lstlisting}

As scope expressions are expressions, they can be nested:

\begin{lstlisting}
    var x;

    ( -- nested scope begins here
      var y;
      skip
    ) -- nested scope ends here
\end{lstlisting}

The definitions on the top-level of compilation unit can be tagged as ``\lstinline|public|'', in which case they are exported and become visible by
other units which import a given one. Nested scopes can not contain public definitions.

The nesting relation has the shape of a tree, and in a concrete node of the tree all definitions in all enclosing scopes are visible:

\begin{lstlisting}
    var x;

    (var y; 
      (var z;
        skip -- x, y, and z are visible here
      );
      (var t;
        skip -- x, y, and t are visible here
      );
      skip -- x and y are visible here
    );
    skip -- only x is visible here
\end{lstlisting}

Multiple definitions of the same name in the same scope are prohibited:

\begin{lstlisting}
    var x;
    fun x () {0} -- error
\end{lstlisting}

However, a definition is a nested scope can override a definition in an enclosing one:

\begin{lstlisting}
    var x;

    (
      fun x () {0} -- ok
      skip         -- here x is associated with the function
    );

    skip -- here x is associated with the variable
\end{lstlisting}

A function can freely use all visible definitions; in particular, functions defined in the
same scope can be mutually recursive:

\begin{lstlisting}
    var x;
    fun f () {0}

    ( 
      fun g () {f () + h () + y} -- ok
      fun h () {g () + x}        -- ok
      var y;
      skip
    );
    skip
\end{lstlisting}

A variable, defined in a scope, can be attributed with an expression, calculating its initial value.
These expressions, however, are evaluated in the order of variable declaration. Thus, while
technically it is possible to have forward references in the initialization expression, their
behavior is undefined. For example:

\begin{lstlisting}
    var x = y + 2; -- undefined, as y is not yet initialized at this point
    var y = x + 2;
    skip
\end{lstlisting}
