From 4c3c9734d91c19e41eb4424944247adad214d188 Mon Sep 17 00:00:00 2001 From: Mart Lubbers Date: Tue, 6 Jun 2017 15:09:39 +0200 Subject: [PATCH] add control flow and bytecode example --- methods.mtask.tex | 4 +-- results.mtask.tex | 81 +++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 80 insertions(+), 5 deletions(-) diff --git a/methods.mtask.tex b/methods.mtask.tex index 1662d6d..df05035 100644 --- a/methods.mtask.tex +++ b/methods.mtask.tex @@ -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} diff --git a/results.mtask.tex b/results.mtask.tex index 377a8cb..0c50555 100644 --- a/results.mtask.tex +++ b/results.mtask.tex @@ -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} -- 2.20.1