add control flow and bytecode example
authorMart Lubbers <mart@martlubbers.net>
Tue, 6 Jun 2017 13:09:39 +0000 (15:09 +0200)
committerMart Lubbers <mart@martlubbers.net>
Tue, 6 Jun 2017 13:09:39 +0000 (15:09 +0200)
methods.mtask.tex
results.mtask.tex

index 1662d6d..df05035 100644 (file)
@@ -211,7 +211,7 @@ blink = task \blink=(\x.
 
 thermostat :: Main (View () Stmt)
 thermostat = {main =
-  IF (analogRead A0 >. 50)
+  IF (analogRead A0 >. lit 50)
        ( digitalWrite D0 (lit True)  )
     ( digitalWrite D0 (lit False) )
   }
@@ -219,5 +219,5 @@ thermostat = {main =
 thermostat` :: Main (View () Stmt)
 thermostat` = let 
   a0 = aIO A0
-  d0 = dIO D0 in {main = IF (a0 >. 50) (d0 =. lit True) (d0 =. lit False) }
+  d0 = dIO D0 in {main = IF (a0 >. lit 50) (d0 =. lit True) (d0 =. lit False) }
 \end{lstlisting}
index 377a8cb..0c50555 100644 (file)
@@ -119,7 +119,7 @@ to the \emph{Writer} value.
 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 :: (ByteCode a p) BC -> ByteCode b c
 op (BC x) bc = BC (x >>| tell [bc])
 
 tell` :: [BC] -> (ByteCode a p)
@@ -148,8 +148,31 @@ instance userLed ByteCode where
 \end{lstlisting}
 
 \subsection{Control Flow}
+Sequence is very straightforward in the bytecode view. The function just
+sequences the two \glspl{RWST}. The \emph{If} statement requires some detailed
+explanation since labels come in to play. The implementation speaks for itself
+in Listing~\ref{lst:controlflow}. First all the labels are gathered and then
+they are placed in the correct order in the bytecode sequence. It can happen
+that multiple labels appear consecutively in the code. This is not a problem
+since the labels are resolved to real addresses later on anyways.
+
 \begin{lstlisting}[label={lst:controlflow},%
        caption={Bytecode view for \texttt{arith}}]
+freshlabel = get >>= \st=:{freshl=[fr:frs]}->put {st & freshl=frs} >>| pure fr
+
+instance If ByteCode Stmt Stmt Stmt where If b t e = BCIfStmt b t e
+instance If ByteCode e Stmt Stmt    where If b t e = BCIfStmt b t e
+instance If ByteCode Stmt e Stmt    where If b t e = BCIfStmt b t e
+instance If ByteCode x y Stmt       where If b t e = BCIfStmt b t e
+instance IF ByteCode where
+       IF b t e = BCIfStmt b t e
+       (?) b t = BCIfStmt b t (tell` [])
+BCIfStmt (BC b) (BC t) (BC e) = BC (
+       freshlabel >>= \else->freshlabel >>= \endif->
+       b >>| tell [BCJmpF else] >>|
+       t >>| tell [BCJmp endif, BCLab else] >>|
+       e >>| tell [BCLab endif]
+       )
 instance noOp ByteCode where
        noOp = tell` [BCNop]
 \end{lstlisting}
@@ -164,8 +187,10 @@ implementation is shown in Listing~\ref{lst:shareview}.
 
 \begin{lstlisting}[label={lst:shareview},%
        caption={Bytecode view for \texttt{arith}}]
+freshshare = get >>= \st=:{freshl=[fr:frs]}->put {st & freshl=frs} >>| pure fr
+
 instance sds ByteCode where
-       sds f = {main = BC (freshs
+       sds f = {main = BC (freshshare
                        >>= \sdsi->pure {BCShare | sdsi=sdsi,sdsval=BCValue 0}
                        >>= \sds->pure (f (tell` [BCSdsFetch sds]))
                        >>= \(v In bdy)->modify (addSDS sds v)
@@ -195,4 +220,54 @@ makeStore [...]             = [...]
 \end{lstlisting}
 
 \section{Actual Compilation}
-\todo{hulp functies voor compileren}
+All the previous functions are tied together with the \CI{toMessages} function.
+This function compiles the bytecode and transforms the \gls{Task} in a message.
+The \glspl{SDS} that were not already sent to the device are also placed in
+messages to be sent to the device. This functionality is listed in
+Listing~\ref{lst:compilation}. The compilation process consists of two steps.
+First the \gls{RWST} is executed, secondly the \emph{Jump} statements that jump
+to labels are transformed to jump to addresses. The translation of labels is
+possible in one sweep because no labels are reused. Reusing labels would not
+give a speed improvement since the labels are removed anyways in the end.
+
+\begin{lstlisting}[label={lst:compilation},%
+       caption={Actual compilation.}]
+bclength :: BC -> Int
+bclength (BCPush s) = 1 + size (toByteCode s)
+bclength ... = ...
+bclength x = 1 + consNum{|*|} x
+
+computeGotos :: [BC] Int -> ([BC], Map Int Int)
+computeGotos [] _ = ([], newMap)
+computeGotos [BCLab l:xs] i = appSnd ('DM'.put l i) (computeGotos xs i)
+computeGotos [x:xs] i = appFst (\bc->[x:bc]) (computeGotos xs (i + bclength x))
+
+toRealByteCode :: (ByteCode a b) BCState -> (String, BCState)
+toRealByteCode x s
+# (s, bc) = runBC x s
+# (bc, gtmap) = computeGotos bc 1
+= (concat (map (toString o toByteVal) (map (implGotos gtmap) bc)), s)
+
+toMessages :: MTaskInterval (Main (ByteCode a b)) BCState -> ([MTaskMSGSend], BCState)
+toMessages interval x oldstate
+# (bc, newstate) = toRealByteCode (unMain x) oldstate
+# newsdss = difference newstate.sdss oldstate.sdss 
+= ([MTSds sdsi e\\{sdsi,sdsval=e}<-newsdss] ++ [MTTask interval bc], newstate)
+\end{lstlisting}
+
+\section{Example}
+The heating example given previously in Listing~\ref{lst:exmtask} would be
+compiled to the following code. The left column indicates the
+position in the program memory.
+
+\begin{lstlisting}[caption={Thermostat bytecode},language=c]
+ 1-2 : BCAnalogRead (Analog A0)
+ 3-6 : BCPush (Int 50)
+ 7   : BCGre
+ 8-9 : BCJmpF 17                   //Jump to else
+10-12: BCPush (Bool 1)
+13-14: BCDigitalWrite (Digital D0)
+15-16: BCJmp 21                    //Jump to end of if
+17-19: BCPush (Bool 0)             //Else label
+20   : BCDigitalWrite (Digital D0)
+\end{lstlisting}