From 209f5ef51d0f63ed47230a5a0e4226b4c2487fff Mon Sep 17 00:00:00 2001 From: Mart Lubbers Date: Tue, 20 Jun 2017 18:45:04 +0200 Subject: [PATCH] sweeeeep --- conclusion.tex | 76 ++++++++++++++--------- methods.dsl.tex | 14 +++++ results.arch.tex | 4 +- results.itasks.tex | 15 ++--- results.mtask.tex | 146 +++++++++++++++++++++++---------------------- thesis.tex | 2 +- 6 files changed, 149 insertions(+), 108 deletions(-) diff --git a/conclusion.tex b/conclusion.tex index 406c744..0473625 100644 --- a/conclusion.tex +++ b/conclusion.tex @@ -1,11 +1,6 @@ -\section{Discussion} -\todo{class based shallow doesn't have multiple backend support} -\todo{slow client software because of interpretation} -\todo{What happens if a device dies? Task resending, add to handshake} - -\section{Future Research} -The system is still crude and a proof of concept. Improvements and extension -for the system are amply available in several fields of study. +\section{Discussion \& Future Research} +The system is still a crude prototype and a proof of concept. Improvements and +extension for the system are amply available in several fields of study. \subsection{Simulation} An additional simulation view to the \gls{mTask}-\gls{EDSL} could be added that @@ -17,8 +12,8 @@ the \emph{POSIX}-client is the reference client and contains debugging code. Adding a simulation view to the system allows for easy interactive debugging. However, it might not be easy to devise a simulation tool that accurately simulates the \gls{mTask} system accurately on some levels. The semantics can -be simulated but timing and peripheral input/output are more -difficult to simulate properly. +be simulated but timing and peripheral input/output are more difficult to +simulate properly. \subsection{Optimization} True multitasking could be added to the client software. This allows @@ -33,14 +28,20 @@ the multithreading capabilities of the client. Hardly any work has been done in the interpreter. The current interpreter is a no nonsense stack machine. A lot of improvements can be done in this part. For example, precomputed \emph{gotos} can improve jumping to the correct part of -the code corresponding to the correct instruction. +the code corresponding to the correct instruction. Moreover, the stack +currently consists of 16-bit values. All operations work on 16-bit values and +this simplifies the interpreter implementation. A memory improvement can be +made by converting the stack to 8-bit values. This does pose some problems +since an equality instruction must work on single-byte booleans \emph{and} +two-byte integers. Adding specialized instructions per word size could overcome +this problem. \subsection{Resources} Resource analysis during compilation can be useful to determine if an \gls{mTask}-\gls{Task} is suitable for a specific device. If the device does -not contain the correct peripherals such as an \gls{LCD} then the +not contain the correct peripherals --- such as an \gls{LCD} --- then the \gls{mTask}-\gls{Task} should be rejected and feedback to the user must be -given. +given. It might even be possible to do this statically on the type level. This idea could be extended to the analysis of stack size and possibly communication bandwidth. With this functionality ever more reliable fail-over @@ -54,9 +55,9 @@ embedding. It might even be possible to encode the resource allocation in the type system itself using forms of dependant types. \subsection{Functionality} -More \gls{Task}-combinators already existing in the \gls{iTasks}-system could -be added to the \gls{mTask}-system to allow for more fine-grained control flow -between \gls{mTask}-\glspl{Task}. In this way the new system follows the +More \gls{Task}-combinators --- already existing in the \gls{iTasks}-system --- +could be added to the \gls{mTask}-system to allow for more fine-grained control +flow between \gls{mTask}-\glspl{Task}. In this way the new system follows the \gls{TOP} paradigm even more and makes programming \glspl{mTask} for \gls{TOP}-programmers more seamless. Some of the combinators require previously mentioned extension such as the parallel combinator. Others might be achieved @@ -69,20 +70,41 @@ programming and less communication resources. Adding these semantics requires modifications to the client software and extensions to the communication protocol since relations between \glspl{Task} also need to be encoded and communicated. + +\subsection{Robustness} +The robustness of the system can be greatly improved. Devices that lose +connection are in the current system not well supported. The device will stop +functioning and have to be emptied for a reconnect. \Glspl{Task} residing on a +device that disconnected should be kept on the server to allow a swift +reconnect and restoration of the \glspl{Task}. This holds the same for the +client software. The client drops all existing \glspl{Task} on a shutdown +request. An extra specialization of the shutdown could be added that drops the +connection but keeps the \glspl{Task} in memory. During the downtime the +\glspl{Task} can still be executed but publications need to be delayed. If the +same server connects to the client the delayed publications can be sent +anyways. + +Moreover, devices could send their current \glspl{Task} back at the +server to synchronize it. This allows interchanging servers without +interrupting the client. Allowing the client to send \glspl{Task} to the server +is something to handle with care because it can easily cause high bandwidth +usage. + \section{Conclusion} -This thesis introduces a new view for the existing \gls{mTask}-\gls{EDSL}. -The new view for the \gls{EDSL} compiles the language in to bytecode that can -be interpreted by an \gls{mTask}-client. Clients have been written for several -microcontrollers and consumer architectures that can be connected through -various means of communication such as serial, bluetooth, wifi and wired -network communication. The bytecode on the devices is interpreted using a -simple stack machine and provides the programmer interfaces to the peripherals. -The semantics of the \glspl{mTask} tries to resemble the \gls{iTasks} semantics -as close as possible. +This thesis introduces a novel system for add \gls{IoT} functionality to +the \gls{TOP} implementation \gls{iTasks}. A new view for the existing +\gls{mTask}-\gls{EDSL} has been created which compiles the program +into bytecode that can be interpreted by a client. Clients have +been written for several microcontrollers and consumer architectures which can +be connected through various means of communication such as serial port, +bluetooth, wifi and wired network communication. The bytecode on the devices is +interpreted using a stack machine and provides the programmer interfaces +to the peripherals. The semantics of the \glspl{mTask} tries to resemble the +\gls{iTasks} semantics as close as possible. The host language has a very efficient compiler and code generator. Therefore, -the \gls{mTask}-system is also relatively fast because the compilation of -\glspl{mTask} is nothing more than running some functions in the host language. +compiling \glspl{mTask} is also fast. Compiling \glspl{mTask} is nothing +more than running some functions native to the host language. The dynamic nature allows the microcontroller to be programmed once and used many times. The program memory of microcontrollers often guarantees around diff --git a/methods.dsl.tex b/methods.dsl.tex index be8bf74..8304262 100644 --- a/methods.dsl.tex +++ b/methods.dsl.tex @@ -110,6 +110,9 @@ must be updated accordingly to prevent possible runtime errors. When an extension is added in a new class, this problem does not arise and views can choose to implement only parts of the collection of classes. +In contrast to deep embedding, it is very well possible to have multiple views +applied on the same expression. This is also shown in the following listing. + \begin{lstlisting}[label={lst:exclassshallow},% caption={A minimal class based shallow \gls{EDSL}}] :: Env = ... // Some environment @@ -133,4 +136,15 @@ instance intArith PrettyPrinter where lit x = toString x add x y = x +++ "+" +++ y ... + +... + +Start :: (PP String, Bool) +Start = (print e0, eval e0) +where + e0 :: a Bool | intArith a & boolArith a + e0 = eq (lit 42) (lit 21 +. lit 21) + + print (PP p) = p + eval (Evaluator e) env = e env \end{lstlisting} diff --git a/results.arch.tex b/results.arch.tex index 1c0f7f7..1e57c62 100644 --- a/results.arch.tex +++ b/results.arch.tex @@ -90,7 +90,7 @@ available for storing \glspl{Task} and \glspl{SDS} and the size of the stack. \section{Device Storage} All devices available in the system are stored in a big \gls{SDS} that contains a list of \CI{MTaskDevice}s. The exact specification is defined as in -Listing~\ref{lst:mtaskdevice} with the accompanying classes and types. +Listing~\ref{lst:mtaskdevice} accompanied with the used classes and types. The \CI{deviceResource} component of the record must implement the \CI{MTaskDuplex} interface that provides a function that launches a \gls{Task} @@ -143,7 +143,7 @@ class MTaskDuplex a where The communication from the server to the client and vice versa is just a character stream containing encoded \gls{mTask} messages. The specific encoding is visible in Appendix~\ref{app:communication-protocol}. The type holding the -messages in Listing~\ref{lst:avmsg}. Detailed explaination about the message +messages in Listing~\ref{lst:avmsg}. Detailed explanation about the message types will be given in the following subsections. \begin{lstlisting}[label={lst:avmsg},caption={Available messages}] diff --git a/results.itasks.tex b/results.itasks.tex index 3c25317..a3ecffa 100644 --- a/results.itasks.tex +++ b/results.itasks.tex @@ -1,14 +1,15 @@ -The glue in the system is written in \gls{iTasks}. Functions for managing -devices, \glspl{Task} and \glspl{SDS} are created. An interface is made that +The server side of the system is written in \gls{iTasks}. Functions for managing +devices, \glspl{Task} and \glspl{SDS} have been created to support the +functionality. An interactive application has been created that allows an interactive management console for the \gls{mTask} system. This interface provides functionality to list \glspl{SDS}, add \glspl{Task}, remove \glspl{Task}, administrate devices and view the state of the system. \section{Integration} -When the system starts up the devices residing in the \gls{SDS} must be cleaned -up. It might be the case that they contain \glspl{Task}, \glspl{SDS} or errors. -A user or programmer can then choose to reconnect some devices using the -\CI{connectDevice} function. +When the system starts up the devices from the previous execution still +residing in the \gls{SDS} must be cleaned up. It might be the case that they +contain \glspl{Task}, \glspl{SDS} or errors that are no longer applicable in +this run. A user or programmer can later choose to reconnect to some devices. \begin{lstlisting}[caption={Starting up the devices},% label={lst:startupdevs}] @@ -34,7 +35,7 @@ a device after a restart of the server application. \begin{figure}[H] \centering \includegraphics[width=\linewidth]{manage} - \caption{The device management interface}\label{lst:management} + \caption{The device management interface}\label{lst:manageme} \end{figure} \section{Shares} diff --git a/results.mtask.tex b/results.mtask.tex index 83cc709..20a51f1 100644 --- a/results.mtask.tex +++ b/results.mtask.tex @@ -1,20 +1,20 @@ The \glspl{Task} suitable for a client are called \glspl{mTask} and are written in the aforementioned \gls{mTask}-\gls{EDSL}. 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. +original \gls{mTask}-\gls{EDSL} will not be used in this system. 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. \section{Semantics} The current \gls{mTask} engine for devices does not support \glspl{Task} in the sense that the \gls{C}-view does. \Glspl{Task} used with the \gls{C}-view are a -main program that runs some \glspl{Task}. \glspl{Task} in the new system are -\CI{Main} objects with a program inside that does not contain \glspl{Task} but -are a \gls{Task} as a whole. Sending a \gls{Task} always goes together with -choosing a scheduling strategy. This strategy can be one of the following three -strategies as reflected in the \CI{MTTask}. +main program that executes code and launches \glspl{Task}. It was also possible +to just have a main program. The current \gls{mTask}-system only supports main +programs. Sending a \gls{Task} always goes together with choosing a scheduling +strategy. This strategy can be one of the following three strategies as +reflected in the \CI{MTTask} message type. \begin{itemize} \item\CI{OneShot} @@ -39,15 +39,16 @@ strategies as reflected in the \CI{MTTask}. \end{itemize} \subsection{\glspl{SDS}} -\Glspl{SDS} on a client are available on the server as well. However, the same -freedom is not given on the \glspl{SDS} that reside on the client. Not all -types are suitable to be located on a client. Moreover, \glspl{SDS} behave a -little bit differently on an \gls{mTask} device than in the \gls{iTasks} -system. In an \gls{iTasks} system, when the \gls{SDS} is updated, a broadcast -to everyone in the system watching is made to notify them of an update. -\glspl{SDS} on the device can update very often and the update might not be the -final value it will get. Therefore a device must publish the \gls{SDS} -explicitly to save bandwidth. +\Glspl{SDS} on a client are available on the server as well as regular +\gls{SDS}. However, the same freedom is not given on the \glspl{SDS} that +reside on the client. Not all types are suitable to be located on a client. +Moreover, \glspl{SDS} behave a little different on an \gls{mTask} device +compared to the \gls{iTasks} system. In an \gls{iTasks} system, when the \gls{SDS} +is updated, a broadcast to everyone in the system watching is made to notify +them of the update. \glspl{SDS} can update very often and the +update might not be the final value it will get. This results in a lot of +expensive unneeded bandwidth usage. Therefore a device must publish the +\gls{SDS} explicitly to save bandwidth. To add this functionality, the \CI{sds} class could be extended. However, this would result in having to update all existing views that use the \CI{sds} @@ -71,20 +72,21 @@ The state contains fresh variable names and a register of \glspl{SDS} used. 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 a \gls{RWST} is often put into the \emph{Reader} part of -the monad. However, not all code is compiled immediately and later on the fresh -variable stream cannot contain variables that were used before. Therefore this -information is put in the state which is kept between compilations. +\CI{ByteCode} object to be able to make use of the \gls{RWST} functionality +such as return values. Tailor made access functions are used to achieve this +with ease. The fresh variable stream in a compiler using a \gls{RWST} is often +put into the \emph{Reader} part of the monad. However, not all code is compiled +immediately and later on the fresh variable stream cannot contain variables +that were used before. Therefore this information is put in the state which is +kept between compilations. 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} +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. +the moment a simple encoding scheme is used that uses single byte prefixes to +detect the type of the value. The devices know these prefixes and can apply the +same detection if necessary. \begin{lstlisting}[label={lst:bcview},caption={Bytecode view}] :: ByteCode a p = BC (RWS () [BC] BCState ()) @@ -114,15 +116,14 @@ instance serial ByteCode \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. +kept large, but under $255$, to get the highest expressively while keeping all +instruction one byte. -The interpreter is a -stack machine. Therefore 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. +The interpreter running in the client is a stack machine. The virtual +instruction \CI{BCLab} is added to allow for an easy implementation of jumping. +However, this is not a real instruction and the labels are resolved to actual +program memory addresses in the final step of compilation to save instructions +and avoid label lookups at runtime. \begin{lstlisting}[label={bc:instr},% caption={Bytecode instruction set}] @@ -150,11 +151,10 @@ instructions. | BCReturn \end{lstlisting} -All instructions 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. +All single byte instructions can be converted automatically using the generic +function \CI{consIndex} which returns the index of the constructor. The index +of the constructor is the byte value for all instructions. The last step of the +compilation is transforming the list of bytecode instructions to actual bytes. \subsection{Helper functions} The \CI{ByteCode} type is just a boxed \gls{RWST} and that gives us access to @@ -183,8 +183,8 @@ unBC (BC x) = x \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. +\CI{boolExpr} and the classes for the peripherals are implemented using the +same strategy. \begin{lstlisting}[label={lst:arithview},caption={% Bytecode view implementation for arithmetic and peripheral classes}] @@ -199,13 +199,14 @@ 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 into 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 anyway. +Implementing the sequence operator 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 into 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 anyway. \begin{lstlisting}[label={lst:controlflow},% caption={Bytecode view for \texttt{arith}}] @@ -232,8 +233,8 @@ instance noOp ByteCode where Shared data sources must be acquired from the state and constructing one involves 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 \gls{SDS} to -the actual state with the value obtained from the function. The exact +instruction is written and the body is generated to finally add the \gls{SDS} +to the actual state with the value obtained from the function. The exact implementation is shown in Listing~\ref{lst:shareview}. \begin{lstlisting}[label={lst:shareview},% @@ -242,7 +243,7 @@ freshshare = get >>= \st=:{freshs}->put {st & freshs=freshs+1} >>| pure freshs instance sds ByteCode where sds f = {main = BC (freshshare - >>= \sdsi->pure {BCShare | sdsi=sdsi,sdsval=BCValue 0} + >>= \sdsi->pure {BCShare|sdsi=sdsi,sdsval=BCValue 0} >>= \sds->pure (f (tell` [BCSdsFetch sds])) >>= \(v In bdy)->modify (addSDS sds v) >>| unBC (unMain bdy)) @@ -253,13 +254,15 @@ instance sdspub ByteCode where addSDS sds v s = {s & sdss=[{sds & sdsval=BCValue v}:s.sdss]} \end{lstlisting} -All assignable types compile to a \gls{RWST} that writes one instruction. For -example, using a \gls{SDS} always results in an expression of the form +All assignable types compile to a \gls{RWST} that writes one fetch instruction. +For example, using a \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}. +one \CI{BCSdsFetch} instruction with the correct \gls{SDS} embedded. Assigning +to an analog pin will result in the \gls{RWST} containing the \CI{BCAnalogRead} +instruction. When the assignable is not a read from but assigned to, the +instruction will be rewritten as a store instruction. Resulting in an +\CI{BCSdsStore} or \CI{BCAnalogWrite} instruction respectively. The +implementation for this is given in Listing~\ref{lst:assignmentview}. \begin{lstlisting}[label={lst:assignmentview},% caption={Bytecode view implementation for assignment.}] @@ -274,13 +277,14 @@ makeStore [...] = [...] \section{Actual Compilation} 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 +The \glspl{SDS} that were not already sent to the device are also added as 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. Then 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 anyway in the end. +First, the \gls{RWST} is executed. Then, the \emph{Jump} statements that +jump to labels are transformed to jump to program memory 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 +anyway in the end. \begin{lstlisting}[label={lst:compilation},% caption={Actual compilation.}] @@ -327,11 +331,11 @@ position in the program memory. \section{Interpreter} The client contains an interpreter to execute a \gls{Task}'s bytecode. -First some preparatory work is done. The stack will be initialized and the -program counter and stack pointer are set to zero and the bottom respectively. -Then the interpreter executes one step at the time while the program counter is -smaller than the program length. The code for this is listed in -Listing~\ref{lst:interpr}. One execution step is basically a big switch +Before execution some preparatory work is done. The stack will be initialized +and the program counter and stack pointer are set to zero and the bottom +respectively. Then, the interpreter executes one step at the time while the +program counter is smaller than the program length. The code for this is listed +in Listing~\ref{lst:interpr}. One execution step is basically a big switch statement going over all possible bytecode instructions. Some instructions are detailed upon in the listing. The \CI{BCPush} instruction is a little more complicated in real life because some decoding will take place as not all diff --git a/thesis.tex b/thesis.tex index 5be4938..2cb098d 100644 --- a/thesis.tex +++ b/thesis.tex @@ -58,7 +58,7 @@ \chapter{Integration with iTasks}\label{chp:itasksint} \input{results.itasks} -\chapter{Conclusion \& Discussion}\label{chp:conclusion} +\chapter{Discussion \& Conclusion}\label{chp:conclusion} \input{conclusion} \appendix\label{chp:appendix} -- 2.20.1