+\subsection{Compiler infrastructure}
+The bytecode compiler interpretation for the \gls{MTASK} language is implemented as a monad stack containing a writer monad and a state monad.
+The writer monad is used to generate code snippets locally without having to store them in the monadic values.
+The state monad accumulates the code, and stores the state the compiler requires.
+\Cref{lst:compiler_state} shows the data type for the state, storing:
+function the compiler currently is in;
+code of the main expression;
+context (see \cref{ssec:step});
+code for the functions;
+next fresh label;
+a list of all the used \glspl{SDS}, either local \glspl{SDS} containing the initial value (\cleaninline{Left}) or lifted \glspl{SDS} (see \cref{sec:liftsds}) containing a reference to the associated \gls{ITASK} \gls{SDS};
+and finally there is a list of peripherals used.
+
+\begin{lstClean}[label={lst:compiler_state},caption={The type for the \gls{MTASK} byte code compiler.}]
+:: BCInterpret a :== StateT BCState (WriterT [BCInstr] Identity) a
+:: BCState =
+ { bcs_infun :: JumpLabel
+ , bcs_mainexpr :: [BCInstr]
+ , bcs_context :: [BCInstr]
+ , bcs_functions :: Map JumpLabel BCFunction
+ , bcs_freshlabel :: JumpLabel
+ , bcs_sdses :: [Either String255 MTLens]
+ , bcs_hardware :: [BCPeripheral]
+ }
+:: BCFunction =
+ { bcf_instructions :: [BCInstr]
+ , bcf_argwidth :: UInt8
+ , bcf_returnwidth :: UInt8
+ }
+\end{lstClean}
+
+Executing the compiler is done by providing an initial state and running the monad.
+After compilation, several post-processing steps are applied to make the code suitable for the microprocessor.
+First, in all tail call \cleaninline{BCReturn} instructions are replaced by \cleaninline{BCTailCall} instructions to optimise the tail calls.
+Furthermore, all byte code is concatenated, resulting in one big program.
+Many instructions have commonly used arguments so shorthands are introduced to reduce the program size.
+For example, the \cleaninline{BCArg} instruction is often called with argument \numrange{0}{2} and can be replaced by the \numrange[parse-numbers=false]{\cleaninline{BCArg0}}{\cleaninline{BCArg2}} shorthands.
+Furthermore, redundant instructions such as pop directly after push are removed as well in order not to burden the code generation with these intricacies.
+Finally the labels are resolved to represent actual program addresses instead of the freshly generated identifiers.
+After the byte code is ready, the lifted \glspl{SDS} are resolved to provide an initial value for them.
+The byte code, \gls{SDS} specification and perpipheral specifications are the result of the process, ready to be sent to the device.
+