\end{lstlisting}
\subsection{Higher order functions}\label{ssec:high}
-The nature of the type checking algorithm already included type checking and
-inferring the type of higher order functions. Since we allow constants there is
-a difference between \SI{read} and \SI{read()}. To make this difference we
-introduced a separate type of expression called a \SI{FuncType}, this type
-encodes a function with arity $0$.
+As extension this compiler can handle function types. Function types are
+pointers to functions that may or may not have arguments already curried in. We
+use the simple approach instead of the full fledged closure approach because of
+time reasons. Adding the functionality in the lexer and parser was trivial
+because of the modular nature. There was one small distinction that we had to
+make which was the difference between a $0$-arity function call and a $0$-arity
+function pointer. Currently \SI{read} is parsed as a function pointer and
+\SI{read()} is parsed as a function call. Adding the functionality in the
+semantic analysis was actually done from the start since the
+\emph{Hindley-Milner} algorithm already supported it.
As all other data types, a function type object occupies one item on the stack
which contains a heap pointer. The heap pointer points to a position on the
-heap that stores, in increasing addresses, the function identification number,
-the number of arguments already given and finally the argument values.
-For example the following snippet shows the representation of the incomplete
-function \SI{plus} that already has two arguments.
-\begin{SPLCode}
+heap that stores the function identification number, the number of arguments
+already given and finally the argument values. For example the snippet in
+Listing~\ref{lst:highex} shows the representation of the incomplete function
+\SI{plus} that already has two arguments.
+
+\begin{lstlisting}[
+ language=SPLCode,
+ label={lst:highex},
+ caption={Heap layout of curried functions}]
//SPLCode
plus(x, y, z){ return x + y + z; }
var a = plus(4, 3);
}
-/*# | Stack
-001 | 001 //Pointer to the
-... |
-
- # | Heap
+/*# | Heap
001 | 008 //Function identification number
002 | 002 //Available arguments
003 | 004 //Argument 1
004 | 003 //Argument 2
*/
-\end{SPLCode}
+\end{lstlisting}
When an incomplete function is declared we save the remaining arity in our
state to be able to know when a function is complete and can be executed. When
a function is still not complete the function is copied in totality and the
available arguments position on the heap is increased accordingly and the
-arguments are added on the heap.
+arguments are added on the heap. The reason we store the number of already
+given arguments in the heap is because we need that information at run-time
+since you can not know this at compile-time.
-Function numbers are integers that identify the function. Normally we address
-functions using labels but it is not possible to store labels on the heap or on
-the stack. Therefore we include a function in the preamble that is basically a
-dictionary from integers to labels. All functions have their unique number that
-identifies them via the function dictionary called \SI{1func}. When we want to
+Normally we jump to functions using labels. But since we can not put labels on
+the heap or stack we have introduced a function in the preamble that translate
+integers to the corresponding label called \SI{1func}. When we want to
call a function that is identified by an address instead of a label we first
collect all the arguments from the heap and add the arguments given in the
function call. Calculating the number of arguments that have to be popped from
the heap is done at runtime using the \emph{Available Arguments} value stored
-on the heap. Instead of jumping to a label we jump to the \SI{1func} function
-and make sure the identification is situated in register R5. \SI{1func} then
-makes sure the correct function is branched to and the caller can resume the
-normal execution path.
+on the heap. Instead of jumping to a label we jump with a \texttt{bsr} to the
+\SI{1func} function and make sure the identification is situated in register
+R5. \SI{1func} then makes sure the correct function is branched to with a
+\texttt{bra} and the caller can resume the normal execution path. In this way
+the function can still use the \texttt{ret} instruction to leave the function.