add stuff about assignments, class implementation etc
[msc-thesis1617.git] / results.mtask.tex
index aaa2515..9580dec 100644 (file)
-\section{mTask}
-\subsection{Semantics}
-\todo{Uitleggen wat het systeem precies doet}
+Some functionality of the original \gls{mTask}-\gls{EDSL} will not be used in
+this extension \gls{EDSL}. Conversely, some functionality needed was not
+available in the existing \gls{EDSL}. Due to the nature of class based shallow
+embedding this obstacle is very easy to solve. A type housing the \gls{EDSL}
+does not have to implement all the available classes. Moreover, classes can be
+added at will without interfering with the existing views.
 
-\subsection{Extension on the \gls{mTask}-\gls{EDSL}}
-\todo{Aanpassingen aan de mTask DSL}
+\section{Semantics}
+\todo{semantics}
 
-\section{iTasks}
-\subsection{Shares}
-\todo{Semantiek van shares, hoe ze in iTasks zijn, hoe typering}
+\section{Bytecode compilation}
+The \glspl{mTask} are sent to the device in bytecode and are saved in the
+memory of the device. To compile the \gls{EDSL} code to bytecode, a view is
+added to the \gls{mTask}-system called \CI{ByteCode}. As shown in
+Listing~\ref{lst:bcview}, the \CI{ByteCode} view is a boxed \gls{RWST} that
+writes bytecode instructions (\CI{BC}) while carrying around a \CI{BCState}.
+The state is kept between devices and contains fresh variable names and a
+register of shares used.
 
-\subsection{Lifting}
-\todo{Lift mTask taken naar echte taken, hoe werkt dat?}
+Types implementing the \gls{mTask} classes must have two free type variables.
+Therefore the \gls{RWST} is wrapped with a constructor and two phantom type
+variables are added. This means that the programmer has to unbox the
+\CI{ByteCode} object to be able to use return values for the monad. Tailor made
+access functions are used to achieve this with ease. The fresh variable stream
+in a compiler using an \gls{RWST} is often put in to the \emph{Reader} part of
+the monad. However, not all code is compiled immediately and later on the fresh
+variable stream can not contain variables that were used before. Therefore this
+information is put in the state which is kept between compilations.
 
-\section{Demo}
-\todo{Wat voorbeeld code}
+Not all types are suitable for usage in bytecode compiled programs. Every value
+used in the bytecode view must fit in the \CI{BCValue} type which restricts
+the content. Most notably, the type must be bytecode encodable.  A \CI{BCValue}
+must be encodable and decodable without losing type or value information. At
+the moment a simple encoding scheme is used that uses a single byte prefixes to
+detect which type the value is. The devices know of these prefixes and act
+accordingly.
+
+\begin{lstlisting}[label={lst:bcview},caption={Bytecode view}]
+:: ByteCode a p = BC (RWS () [BC] BCState ())
+:: BCValue = E.e: BCValue e & mTaskType, TC e
+:: BCShare = {
+               sdsi :: Int,
+               sdsval :: BCValue
+       }
+:: BCState = {
+               freshl :: [Int],
+               freshs :: [Int],
+               sdss :: [BCShare]
+       }
+
+class toByteCode a :: a -> String
+class fromByteCode a :: String -> a
+class mTaskType a | toByteCode, fromByteCode, iTask, TC a
+
+instance toByteCode Int, ... , UserLED, BCValue
+instance fromByteCode Int, ... , UserLED, BCValue
+
+instance arith ByteCode
+...
+instance serial ByteCode
+\end{lstlisting}
+
+\section{Implementation}
+\subsection{Instruction Set}
+The instruction set is given in Listing~\ref{bc:instr}. The instruction set is
+kept large, but under $255$, to get the highest expressivity for the lowest
+program size. 
+
+The interpreter is a
+stack machine. Therefore the it needs instructions like \emph{Push} and
+\emph{Pop}. The virtual instruction \CI{BCLab} is added to allow for an easy
+implementation. However, this is not a real instruction and the labels are
+resolved to actual addresses in the final step of compilation to save
+instructions.
+
+\begin{lstlisting}[label={bc:instr},%
+       caption={Bytecode instruction set}]
+:: BC = BCNop
+       | BCLab Int          | BCPush BCValue     | BCPop
+       //SDS functions
+       | BCSdsStore BCShare | BCSdsFetch BCShare | BCSdsPublish BCShare
+       //Unary ops
+       | BCNot
+       //Binary Int ops
+       | BCAdd              | BCSub              | BCMul
+       | BCDiv
+       //Binary Bool ops
+       | BCAnd              | BCOr
+       //Binary ops
+       | BCEq               | BCNeq              | BCLes             | BCGre
+       | BCLeq              | BCGeq
+       //Conditionals and jumping
+       | BCJmp Int          | BCJmpT Int         | BCJmpF Int
+       //UserLED
+       | BCLedOn            | BCLedOff
+       //Pins
+       | BCAnalogRead Pin   | BCAnalogWrite Pin  | BCDigitalRead Pin | BCDigitalWrite Pin
+       //Return
+       | BCReturn
+\end{lstlisting}
+
+All instructions are can be converted semi-automatically using the generic
+function \CI{consIndex\{*\}} that gives the index of the constructor. This
+constructor index is the actual byte value for the instruction. The
+\CI{BCValue} type contains existentially quantified types and therefore must
+have a given implementation for all generic functions.
+
+\subsection{Helper functions}
+The \CI{ByteCode} type is just a boxed \gls{RWST} and that gives us access to
+the whole range of \gls{RWST} functions. However, to apply a function the type
+must be unboxed. After application the type must be boxed again. To achieve
+this some helper functions have been created. They are listed in
+Listing~\ref{lst:helpers}. The \CI{op} and \CI{op2} function is crafted to make
+operators that pop one or two values off the stack respectively. The \CI{tell`}
+is a wrapper around the \gls{RWST} function \CI{tell} that appends the argument
+to the \emph{Writer} value.
+
+\begin{lstlisting}[label={lst:helpers},caption={Some helper functions}]
+op2 :: (ByteCode a p1) (ByteCode a p2) BC -> ByteCode b Expr
+op2 (BC x) (BC y) bc = BC (x >>| y >>| tell [bc])
+
+op :: (ByteCode a p) BC -> ByteCode a Expr
+op (BC x) bc = BC (x >>| tell [bc])
+
+tell` :: [BC] -> (ByteCode a p)
+tell` x = BC (tell x)
+
+unBC :: (ByteCode a p) -> RWS () [BC] BCState ()
+unBC (BC x) = x
+\end{lstlisting}
+
+\subsection{Arithmetics \& Peripherals}
+Almost all of the code from the simple classes use exclusively helper
+functions. Listing~\ref{lst:arithview} shows some implementations. The classes
+\CI{boolExpr} and the classes for the peripherals are implemented in the same
+fashion.
+
+\begin{lstlisting}[label={lst:arithview},caption={%
+       Bytecode view implementation for arithmetic and peripheral classes}]
+instance arith ByteCode where
+       lit x = tell` [BCPush (BCValue x)]
+       (+.) x y = op2 x y BCDiv
+       ...
+
+instance userLed ByteCode where
+       ledOn  l = op l BCLedOn
+       ledOff l = op l BCLedOff
+\end{lstlisting}
+
+\subsection{Control Flow}
+\begin{lstlisting}[label={lst:controlflow},%
+       caption={Bytecode view for \texttt{arith}}]
+instance noOp ByteCode where
+       noOp = tell` [BCNop]
+\end{lstlisting}
+
+\subsection{Shared Data Sources \& Assignment}
+Shared data sources must be acquired from the state and constructing one
+happens via multiple steps. First a fresh identifier is grabbed from the state.
+Then a \CI{BCShare} record is created with that identifier. A \CI{BCSdsFetch}
+instruction is written and the body is generated to finally add the share to
+the actual state. The exact implementation is shown in
+Listing~\ref{lst:shareview}.
+
+\begin{lstlisting}[label={lst:shareview},%
+       caption={Bytecode view for \texttt{arith}}]
+instance sds ByteCode where
+       sds f = {main = BC (freshs
+                               >>= \sdsi->pure {BCShare | sdsi=sdsi,sdsval=BCValue 0}
+                               >>= \sds->pure (f (tell` [BCSdsFetch sds]))
+                               >>= \(v In bdy)->modify (addSDS sds v)
+                               >>| unBC (unMain bdy))}
+       pub (BC x) = BC (censor (\[BCSdsFetch s]->[BCSdsPublish s]) x)
+
+addSDS sds v s = {s & sdss=[{sds & sdsval=BCValue v}:s.sdss]}
+\end{lstlisting}
+
+All assignable types compile to an \gls{RWST} that writes one instruction. For
+example, using an \gls{SDS} always results in an expression of the form
+\CI{sds \x=4 In ...}. The actual \CI{x} is the \gls{RWST} that always writes
+one \CI{BCSdsFetch} instruction with the correct \gls{SDS} embedded. When the
+call of the \CI{x} is not a read but an assignment,  the instruction will be
+rewritten as a \CI{BCSdsStore}. The implementation for this is given in
+Listing~\ref{lst:assignmentview}.
+
+\begin{lstlisting}[label={lst:assignmentview},%
+       caption={Bytecode view implementation for assignment.}]
+instance assign ByteCode where
+       (=.) (BC v) (BC e) = BC (e >>| censor makeStore v)
+
+makeStore [BCSdsFetch i]    = [BCSdsStore i]
+makeStore [BCDigitalRead i] = [BCDigitalWrite i]
+makeStore [...]             = [...]
+\end{lstlisting}
+
+\section{Actual Compilation}
+\todo{hulp functies voor compileren}