619789f2ed56522d8c152aa05a1b0e9db4e4c438
[phd-thesis.git] / top / top.tex
1 \documentclass[../thesis.tex]{subfiles}
2
3 \input{subfilepreamble}
4
5 \begin{document}
6 \ifSubfilesClassLoaded{
7 \pagenumbering{arabic}
8 }{}
9
10 \chapter{Introduction to \texorpdfstring{\gls{IOT}}{IoT} programming}%
11 \label{chp:top4iot}
12 \todo{betere chapter naam}
13 \begin{chapterabstract}
14 This chapter introduces \gls{MTASK} and puts it into perspective compared to traditional microprocessor programming.
15 \end{chapterabstract}
16
17 Traditionally, the first program that one writes when trying a new language is the so called \emph{Hello World!} program.
18 This program has the single task of printing the text \emph{Hello World!} to the screen and exiting again, useful to become familiarised with the syntax and verify that the toolchain and runtime environment is working.
19 On microprocessors, there often is no screen for displaying text.
20 Nevertheless, almost always there is a monochrome $1\times1$ pixel screen, namely an---often builtin---\gls{LED}.
21 The \emph{Hello World!} equivalent on microprocessors blinks this \gls{LED}.
22
23 \Cref{lst:arduinoBlink} shows how the logic of a blink program might look when using \gls{ARDUINO}'s \gls{CPP} dialect.
24 Every \gls{ARDUINO} program contains a \arduinoinline{setup} and a \arduinoinline{loop} function.
25 The \arduinoinline{setup} function is executed only once on boot, the \arduinoinline{loop} function is continuously called afterwards and contains the event loop.
26 After setting the \gls{GPIO} pin to the correct mode, blink's \arduinoinline{loop} function alternates the state of the pin representing the \gls{LED} between \arduinoinline{HIGH} and \arduinoinline{LOW}, turning the \gls{LED} off and on respectively.
27 In between it waits for 500 milliseconds so that the blinking is actually visible for the human eye.
28 Compiling this results in a binary firmware that needs to be flashed onto the program memory.
29
30 Translating the traditional blink program to \gls{MTASK} can almost be done by simply substituting some syntax as seen in \cref{lst:blinkImp}.
31 E.g.\ \arduinoinline{digitalWrite} becomes \cleaninline{writeD}, literals are prefixed with \cleaninline{lit} and the pin to blink is changed to represent the actual pin for the builtin \gls{LED} of the device used in the exercises.
32 In contrast to the imperative \gls{CPP} dialect, \gls{MTASK} is a \gls{TOP} language and therefore there is no such thing as a loop, only task combinators to combine tasks.
33 To simulate a loop, the \cleaninline{rpeat} task can be used, this task executes the argument task and, when stable, reinstates it.
34 The body of the \cleaninline{rpeat} contains similarly named tasks to write to the pins and to wait in between.
35 The tasks are connected using the sequential \cleaninline{>>|.} combinator that for all current intents and purposes executes the tasks after each other.
36
37 \begin{figure}[ht]
38 \begin{subfigure}[b]{.5\linewidth}
39 \begin{lstArduino}[caption={Blink program.},label={lst:arduinoBlink}]
40 void setup() {
41 pinMode(D2, OUTPUT);
42 }
43
44 void loop() {
45 digitalWrite(D2, HIGH);
46 delay(500);
47 digitalWrite(D2, LOW);
48 delay(500);
49 }\end{lstArduino}
50 \end{subfigure}%
51 \begin{subfigure}[b]{.5\linewidth}
52 \begin{lstClean}[caption={Blink program.},label={lst:blinkImp}]
53 blink :: Main (MTask v ()) | mtask v
54 blink =
55 declarePin D2 PMOutput \d2->
56 {main = rpeat (
57 writeD d2 true
58 >>|. delay (lit 500)
59 >>|. writeD d2 false
60 >>|. delay (lit 500)
61 )
62 }\end{lstClean}
63 \end{subfigure}
64 \end{figure}
65
66 \section{Threaded blinking}
67 Now say that we want to blink multiple blinking patterns on different \glspl{LED} concurrently.
68 For example, blink three \glspl{LED} connected to \gls{GPIO} pins $1,2$ and $3$ at intervals of $500,300$ and $800$ milliseconds.
69 Intuitively you want to lift the blinking behaviour to a function and call this function three times with different parameters as done in \cref{lst:blinkthreadno}
70
71 \begin{lstArduino}[caption={Naive approach to multiple blinking patterns.},label={lst:blinkthreadno}]
72 void setup () { ... }
73
74 void blink (int pin, int wait) {
75 digitalWrite(pin, HIGH);
76 delay(wait);
77 digitalWrite(pin, LOW);
78 delay(wait);
79 }
80
81 void loop() {
82 blink (D1, 500);
83 blink (D2, 300);
84 blink (D3, 800);
85 }\end{lstArduino}
86
87 Unfortunately, this does not work because the \arduinoinline{delay} function blocks all further execution.
88 The resulting program will blink the \glspl{LED} after each other instead of at the same time.
89 To overcome this, it is necessary to slice up the blinking behaviour in very small fragments so it can be manually interleaved~\citep{feijs_multi-tasking_2013}.
90 Listing~\ref{lst:blinkthread} shows how three different blinking patterns might be achieved in \gls{ARDUINO} using the slicing method.
91 If we want the blink function to be a separate parametrizable function we need to explicitly provide all references to the required state.
92 Furthermore, the \arduinoinline{delay} function can not be used and polling \arduinoinline{millis} is required.
93 The \arduinoinline{millis} function returns the number of milliseconds that have passed since the boot of the microprocessor.
94 Some devices use very little energy when in \arduinoinline{delay} or sleep state.
95 Resulting in \arduinoinline{millis} potentially affects power consumption since the processor is basically busy looping all the time.
96 In the simple case of blinking three \glspl{LED} on fixed intervals, it might be possible to calculate the delays in advance using static analysis and generate the appropriate \arduinoinline{delay} code.
97 Unfortunately, this is very hard when for example the blinking patterns are determined at runtime.
98
99 \begin{lstArduino}[label={lst:blinkthread},caption={Threading three blinking patterns.}]
100 long led1 = 0, led2 = 0, led3 = 0;
101 bool st1 = false, st2 = false, st3 = false;
102
103 void blink(int pin, int dlay, long *lastrun, bool *st) {
104 if (millis() - *lastrun > dlay) {
105 digitalWrite(pin, *st = !*st);
106 *lastrun += dlay;
107 }
108 }
109
110 void loop() {
111 blink(D1, 500, &led1, &st1);
112 blink(D2, 300, &led2, &st1);
113 blink(D3, 800, &led3, &st1);
114 }\end{lstArduino}
115
116 This method is very error prone, requires a lot of pointer juggling and generally results into spaghetti code.
117 Furthermore, it is very difficult to represent dependencies between threads, often state machines have to be explicitly programmed by hand to achieve this.
118
119 \section{Blinking in \texorpdfstring{\gls{MTASK}}{mTask}}
120 The \cleaninline{delay} \emph{task} does not block the execution but \emph{just} emits no value when the target waiting time has not yet passed and emits a stable value when the time is met.
121 In contrast, the \arduinoinline{delay()} \emph{function} on the \gls{ARDUINO} is blocking which prohibits interleaving.
122 To make code reuse possible and make the implementation more intuitive, the blinking behaviour is lifted to a recursive function instead of using the imperative \cleaninline{rpeat} construct.
123 The function is parametrized with the current state, the pin to blink and the waiting time.
124 Creating recursive functions like this is not possible in the \gls{ARDUINO} language because the program would run out of stack in an instant and nothing can be interleaved.
125 With a parallel combinator, tasks can be executed in an interleaved fashion.
126 Therefore, blinking three different blinking patterns is as simple as combining the three calls to the \cleaninline{blink} function with their arguments as seen in \cref{lst:blinkthreadmtask}.
127
128 % VimTeX: SynIgnore on
129 \begin{lstClean}[label={lst:blinkthreadmtask},caption={Threaded blinking.}]
130 blinktask :: MTask v () | mtask v
131 blinktask =
132 declarePin D1 PMOutput \d1->
133 declarePin D2 PMOutput \d2->
134 declarePin D3 PMOutput \d3->
135 fun \blink=(\(st, pin, wait)->
136 delay wait
137 >>|. writeD d13 st
138 >>|. blink (Not st, pin, wait)) In
139 {main = blink (true, d1, lit 500)
140 .||. blink (true, d2, lit 300)
141 .||. blink (true, d3, lit 800)
142 }\end{lstClean}
143 % VimTeX: SynIgnore off
144
145 \chapter{The \texorpdfstring{\gls{MTASK}}{mTask} \texorpdfstring{\gls{DSL}}{DSL}}%
146 \label{chp:mtask_dsl}
147 \begin{chapterabstract}
148 This chapter serves as a complete guide to the \gls{MTASK} language, from an \gls{MTASK} programmer's perspective.
149 \end{chapterabstract}
150
151 The \gls{MTASK} system is a \gls{TOP} programming environment for programming microprocessors.
152 It is implemented as an\gls{EDSL} in \gls{CLEAN} using class-based---or tagless-final---embedding (See \cref{ssec:tagless}).
153 Due to the nature of the embedding technique, it is possible to have multiple interpretations of---or views on---programs written in the \gls{MTASK} language.
154 The following interpretations are available for \gls{MTASK}.
155
156 \begin{itemize}
157 \item Pretty printer
158
159 This interpretation converts the expression to a string representation.
160 \item Simulator
161
162 The simulator converts the expression to a ready-for-work \gls{ITASK} simulation in which the user can inspect and control the simulated peripherals and see the internal state of the tasks.
163 \item Compiler
164
165 The compiler compiles the \gls{MTASK} program at runtime to a specialised bytecode.
166 Using a handful of integration functions and tasks, \gls{MTASK} tasks can be executed on microprocessors and integrated in \gls{ITASK} as if they were regular \gls{ITASK} tasks.
167 Furthermore, with special language constructs, \glspl{SDS} can be shared between \gls{MTASK} and \gls{ITASK} programs.
168 \end{itemize}
169
170 When using the compiler interpretation in conjunction with the \gls{ITASK} integration, \gls{MTASK} is a heterogeneous \gls{DSL}.
171 I.e.\ some components---e.g.\ the \gls{RTS} on the microprocessor---is largely unaware of the other components in the system.
172 Furthermore, it is executed on a completely different architecture.
173 The \gls{MTASK} language consists of a host language---a simply-typed $\lambda$-calculua with support for some basic types, function definition and data types (see \cref{sec:expressions})---enriched with a task language (see \cref{sec:top}).
174
175 \section{Types}
176 To leverage the type checker of the host language, types in the \gls{MTASK} language are expressed as types in the host language, to make the language type safe.
177 However, not all types in the host language are suitable for microprocessors that may only have \qty{2}{\kibi\byte} of \gls{RAM} so class constraints are therefore added to the \gls{DSL} functions.
178 The most used class constraint is the \cleaninline{type} class collection containing functions for serialization, printing, \gls{ITASK} constraints \etc.
179 Many of these functions can be derived using generic programming.
180 An even stronger restriction on types is defined for types that have a stack representation.
181 This \cleaninline{basicType} class has instances for many \gls{CLEAN} basic types such as \cleaninline{Int}, \cleaninline{Real} and \cleaninline{Bool}.
182 The class constraints for values in \gls{MTASK} are omnipresent in all functions and therefore often omitted throughout throughout the chapters for brevity and clarity.
183
184 \begin{table}[ht]
185 \centering
186 \begin{tabular}{lll}
187 \toprule
188 \gls{CLEAN}/\gls{MTASK} & \gls{CPP} type & \textnumero{}bits\\
189 \midrule
190 \cleaninline{Bool} & \cinline{bool} & 16\\
191 \cleaninline{Char} & \cinline{char} & 16\\
192 \cleaninline{Int} & \cinline{int16_t} & 16\\
193 \cleaninline{:: Long} & \cinline{int32_t} & 32\\
194 \cleaninline{Real} & \cinline{float} & 32\\
195 \cleaninline{:: T = A \| B \| C} & \cinline{enum} & 16\\
196 \bottomrule
197 \end{tabular}
198 \caption{Mapping from \gls{CLEAN}/\gls{MTASK} data types to \gls{CPP} datatypes.}%
199 \label{tbl:mtask-c-datatypes}
200 \end{table}
201
202 The \gls{MTASK} language consists of a core collection of type classes bundled in the type class \cleaninline{class mtask}.
203 Every interpretation implements the type classes in the \cleaninline{mtask} class
204 There are also \gls{MTASK} extensions that not every interpretation implements such as peripherals and integration with \gls{ITASK}.
205
206 \Cref{lst:constraints} contains the definitions for the type constraints and shows some example type signatures for typical \gls{MTASK} expressions and tasks.
207 \todo{uitleggen}
208
209 \begin{lstClean}[caption={Classes and class collections for the \gls{MTASK} language.},label={lst:constraints}]
210 :: Main a = { main :: a }
211 :: In a b = (In) infix 0 a b
212
213 class type t | iTask, ... ,fromByteCode, toByteCode t
214 class basicType t | type t where ...
215
216 class mtask v | expr, ..., int, real, long v
217
218 someExpr :: v Int | mtask v
219 someExpr = ...
220
221 someTask :: MTask v Int | mtask v
222 someTask =
223 sensor1 config1 \sns1->
224 sensor2 config2 \sns2->
225 fun \fun1= ( ... )
226 In fun \fun2= ( ... )
227 In {main=mainexpr}
228 \end{lstClean}
229
230 \section{Expressions}\label{sec:expressions}
231 \Cref{lst:expressions} shows the \cleaninline{expr} class containing the functionality to lift values from the host language to the \gls{MTASK} language (\cleaninline{lit}); perform number and boolean arithmetics; do comparisons; and conditional execution.
232 For every common arithmetic operator in the host language, an \gls{MTASK} variant is present, suffixed by a period to not clash with \gls{CLEAN}'s builtin operators.
233
234 \begin{lstClean}[caption={The \gls{MTASK} class for expressions},label={lst:expressions}]
235 class expr v where
236 lit :: t -> v t | type t
237 (+.) infixl 6 :: (v t) (v t) -> v t | basicType, +, zero t
238 ...
239 (&.) infixr 3 :: (v Bool) (v Bool) -> v Bool
240 (|.) infixr 2 :: (v Bool) (v Bool) -> v Bool
241 Not :: (v Bool) -> v Bool
242 (==.) infix 4 :: (v a) (v a) -> v Bool | Eq, basicType a
243 ...
244 If :: (v Bool) (v t) (v t) -> v t | type t
245 \end{lstClean}
246
247 Conversion to-and-fro data types is available through the overloaded functions \cleaninline{int}, \cleaninline{long} and \cleaninline{real}.
248
249 \begin{lstClean}[caption={Type conversion functions in \gls{MTASK}.}]
250 class int v a :: (v a) -> v Int
251 class real v a :: (v a) -> v Real
252 class long v a :: (v a) -> v Long
253 \end{lstClean}
254
255 Finally, values from the host language must be explicitly lifted to the \gls{MTASK} language using the \cleaninline{lit} function.
256 For convenience, there are many lower-cased macro definitions for often used constants such as \cleaninline{true :== lit True}, \cleaninline{false :== lit False}, \etc.
257
258 \Cref{lst:example_exprs} shows some examples of these expressions.
259 \cleaninline{e0} defines the literal $42$, \cleaninline{e1} calculates the literal $42.0$ using real numbers.
260 \cleaninline{e2} compares \cleaninline{e0} and \cleaninline{e1} as integers and if they are equal it returns the \cleaninline{e2}$/2$ and \cleaninline{e0} otherwise.
261 \cleaninline{approxEqual} performs an approximate equality---albeit not taking into account all floating point pecularities---and demonstrates that \gls{CLEAN} can be used as a macro language, i.e.\ maximise linguistic reuse~\cite{krishnamurthi_linguistic_2001}.
262 \todo{uitzoeken waar dit handig is}
263 When calling \cleaninline{approxEqual} in an \gls{MTASK} function, the resulting code is inlined.
264
265 \begin{lstClean}[label={lst:example_exprs},caption={Example \gls{MTASK} expressions.}]
266 e0 :: v Int | expr v
267 e0 = lit 42
268
269 e1 :: v Real | expr v
270 e1 = lit 38.0 + real (lit 4)
271
272 e2 :: v Int | expr v
273 e2 = if' (e0 ==. int e1)
274 (int e1 /. lit 2) e0
275
276 approxEqual :: (v Real) (v Real) (v Real) -> v Real | expr v
277 approxEqual x y eps = if' (x == y) true
278 ( if' (x > y)
279 (y -. x < eps)
280 (x -. y < eps)
281 )
282 \end{lstClean}
283
284 \subsection{Data Types}
285 Most of \gls{CLEAN}'s basic types have been mapped on \gls{MTASK} types.
286 However, it can be useful to have access to compound types as well.
287 All types in \gls{MTASK} must have a fixed size representation on the stack so sum types are not (yet) supported.
288 While it is possible to lift types using the \cleaninline{lit} function, you cannot do anything with the types besides passing them around but they are being produced by some parallel task combinators (see \cref{sssec:combinators_parallel}).
289 To be able to use types as first class citizens, constructors and field selectors are required.
290 \Cref{lst:tuple_exprs} shows the scaffolding for supporting tuples in \gls{MTASK}.
291 Besides the constructors and field selectors, there is also a helper function available that transforms a function from a tuple of \gls{MTASK} expressions to an \gls{MTASK} expression of a tuple.
292
293 \begin{lstClean}[label={lst:tuple_exprs},caption={Tuple constructor and field selectors in \gls{MTASK}.}]
294 class tupl v where
295 tupl :: (v a) (v b) -> v (a, b) | type a & type b
296 first :: (v (a, b)) -> v a | type a & type b
297 second :: (v (a, b)) -> v b | type a & type b
298
299 tupopen f :== \v->f (first v, second v)
300 \end{lstClean}
301
302 \subsection{Functions}
303 Adding functions to the language is achieved by one multi-parameter class to the \gls{DSL}.
304 By using \gls{HOAS}, both the function definition and the calls to the function can be controlled by the \gls{DSL}~\citep{pfenning_higher-order_1988,chlipala_parametric_2008}.
305 As \gls{MTASK} only supports first-order functions and does not allow partial function application.
306 Using a type class of this form, this restriction can be enforced on the type level.
307 Instead of providing one instance for all functions, a single instance per function arity is defined.
308 Also, \gls{MTASK} only supports top-level functions which is enforced by the \cleaninline{Main} box.
309 The definition of the type class and the instances for an example interpretation are as follows:
310 \todo{uitbreiden}
311
312 \begin{lstClean}[caption={Functions in \gls{MTASK}.}]
313 class fun a v :: ((a -> v s) -> In (a -> v s) (Main (MTask v u)))
314 -> Main (MTask v u)
315
316 instance fun () Inter where ...
317 instance fun (Inter a) Inter | type a where ...
318 instance fun (Inter a, Inter b) Inter | type a where ...
319 instance fun (Inter a, Inter b, Inter c) Inter | type a where ...
320 ...
321 \end{lstClean}
322
323 Deriving how to define and use functions from the type is quite the challenge even though the resulting syntax is made easier using the infix type \cleaninline{In}.
324 \Cref{lst:function_examples} show the factorial function, a tail-call optimised factorial function and a function with zero arguments to demonstrate the syntax.
325 Splitting out the function definition for each single arity means that that for every function arity and combination of arguments, a separate class constraint must be created.
326 Many of the often used functions are already bundled in the \cleaninline{mtask} class constraint collection.
327 \cleaninline{factorialtail} shows a manually added class constraint.
328 Definiting zero arity functions is shown in the \cleaninline{zeroarity} expression.
329 Finally, \cleaninline{swapTuple} shows an example of a tuple being swapped.
330
331 % VimTeX: SynIgnore on
332 \begin{lstClean}[label={lst:function_examples},caption={Function examples in \gls{MTASK}.}]
333 factorial :: Main (v Int) | mtask v
334 factorial =
335 fun \fac=(\i->if' (i <. lit 1)
336 (lit 1)
337 (i *. fac (i -. lit 1)))
338 In {main = fac (lit 5) }
339
340 factorialtail :: Main (v Int) | mtask v & fun (v Int, v Int) v
341 factorialtail =
342 fun \facacc=(\(acc, i)->if' (i <. lit 1)
343 acc
344 (fac (acc *. i, i -. lit 1)))
345 In fun \fac=(\i->facacc (lit 1, i))
346 In {main = fac (lit 5) }
347
348 zeroarity :: Main (v Int) | mtask v
349 zeroarity =
350 fun \fourtytwo=(\()->lit 42)
351 In fun \add=(\(x, y)->x +. y)
352 In {main = add (fourtytwo (), lit 9)}
353
354 swapTuple :: Main (v (Int, Bool)) | mtask v
355 swapTuple =
356 fun \swap=(tupopen \(x, y)->tupl y x)
357 In {main = swap (tupl true (lit 42)) }
358 \end{lstClean}
359 % VimTeX: SynIgnore off
360
361 \section{Tasks}\label{sec:top}
362 \Gls{MTASK}'s task language can be divided into three categories, namely
363 \begin{enumerate*}
364 \item Basic tasks, in most \gls{TOP} systems, the basic tasks are called editors, modelling the interactivity with the user.
365 In \gls{MTASK}, there are no \emph{editors} in that sense but there is interaction with the outside world through microprocessor peripherals such as sensors and actuators.
366 \item Task combinators provide a way of describing the workflow.
367 They combine one or more tasks into a compound task.
368 \item \glspl{SDS} in \gls{MTASK} can be seen as references to data that can be shared using many-to-many communication and are only accessible from within the task language to ensure atomicity.
369 \end{enumerate*}
370
371 As \gls{MTASK} is integrated with \gls{ITASK}, the same stability distinction is made for task values.
372 A task in \gls{MTASK} is denoted by the \gls{DSL} type synonym shown in \cref{lst:task_type}.
373
374 \begin{lstClean}[label={lst:task_type},caption={Task type in \gls{MTASK}.}]
375 :: MTask v a :== v (TaskValue a)
376 :: TaskValue a
377 = NoValue
378 | Value a Bool
379 \end{lstClean}
380
381 \subsection{Basic tasks}
382 The most rudimentary basic tasks are the \cleaninline{rtrn} and \cleaninline{unstable} tasks.
383 They lift the value from the \gls{MTASK} expression language to the task domain either as a stable value or an unstable value.
384 There is also a special type of basic task for delaying execution.
385 The \cleaninline{delay} task---given a number of milliseconds---yields an unstable value while the time has not passed.
386 Once the specified time has passed, the time it overshot the planned time is yielded as a stable task value.
387 See \cref{sec:repeat} for an example task using \cleaninline{delay}.
388
389 \begin{lstClean}[label={lst:basic_tasks},caption={Function examples in \gls{MTASK}.}]
390 class rtrn v :: (v t) -> MTask v t
391 class unstable v :: (v t) -> MTask v t
392 class delay v :: (v n) -> MTask v n | long v n
393 \end{lstClean}
394
395 \subsubsection{Peripherals}\label{sssec:peripherals}
396 For every sensor or actuator, basic tasks are available that allow interaction with the specific peripheral.
397 The type classes for these tasks are not included in the \cleaninline{mtask} class collection as not all devices nor all language interpretations have such peripherals connected.
398 \todo{Historically, peripheral support has been added \emph{by need}.}
399
400 \Cref{lst:dht,lst:gpio} show the type classes for \glspl{DHT} sensors and \gls{GPIO} access.
401 Other peripherals have similar interfaces, they are available in the \cref{sec:aux_peripherals}.
402 For the \gls{DHT} sensor there are two basic tasks, \cleaninline{temperature} and \cleaninline{humidity}, that---will given a \cleaninline{DHT} object---produce a task that yields the observed temperature in \unit{\celcius} or relative humidity as a percentage as an unstable value.
403 Currently, two different types of \gls{DHT} sensors are supported, the \emph{DHT} family of sensors connect through $1$-wire protocol and the \emph{SHT} family of sensors connected using \gls{I2C} protocol.
404 Creating such a \cleaninline{DHT} object is very similar to creating functions in \gls{MTASK} and uses \gls{HOAS} to make it type safe.
405
406 \begin{lstClean}[label={lst:dht},caption{The \gls{MTASK} interface for \glspl{DHT} sensors.}]
407 :: DHT //abstract
408 :: DHTInfo
409 = DHT_DHT Pin DHTtype
410 | DHT_SHT I2CAddr
411 :: DHTtype = DHT11 | DHT21 | DHT22
412 class dht v where
413 DHT :: DHTInfo ((v DHT) -> Main (v b)) -> Main (v b) | type b
414 temperature :: (v DHT) -> MTask v Real
415 humidity :: (v DHT) -> MTask v Real
416
417 measureTemp :: Main (MTask v Real) | mtask v & dht v
418 measureTemp = DHT (DHT_SHT (i2c 0x36)) \dht->
419 {main=temperature dht}
420 \end{lstClean}
421
422 \Gls{GPIO} access is divided into three classes: analog, digital and pin modes.
423 For all pins and pin modes an \gls{ADT} is available that enumerates the pins.
424 The analog \gls{GPIO} pins of a microprocessor are connected to an \gls{ADC} that translates the voltage to an integer.
425 Analog \gls{GPIO} pins can be either read or written to.
426 Digital \gls{GPIO} pins only report a high or a low value.
427 The type class definition is a bit more complex since analog \gls{GPIO} pins can be used as digital \gls{GPIO} pins as well.
428 Therefore, if the \cleaninline{p} type implements the \cleaninline{pin} class---i.e.\ either \cleaninline{APin} or \cleaninline{DPin}---the \cleaninline{dio} class can be used.
429 \Gls{GPIO} pins usually operate according to a certain pin mode that states whether the pin acts as an input pin, an input with an internal pull-up resistor or an output pin.
430 This setting can be applied using the \cleaninline{pinMode} class by hand or by using the \cleaninline{declarePin} \gls{GPIO} pin constructor.
431 Setting the pin mode is a task that immediately finisheds and fields a stable unit value.
432 Writing to a pin is also a task that immediately finishes but yields the written value instead.
433 Reading a pin is a task that yields an unstable value---i.e.\ the value read from the actual pin.
434
435 \begin{lstClean}[label={lst:gpio},caption={The \gls{MTASK} interface for \gls{GPIO} access.}]
436 :: APin = A0 | A1 | A2 | A3 | A4 | A5
437 :: DPin = D0 | D1 | D2 | D3 | D4 | D5 | D6 | D7 | D8 | D9 | D10 | D11 | D12 | D13
438 :: PinMode = PMInput | PMOutput | PMInputPullup
439 :: Pin = AnalogPin APin | DigitalPin DPin
440 class pin p :: p -> Pin
441
442 class aio v where
443 writeA :: (v APin) (v Int) -> MTask v Int
444 readA :: (v APin) -> MTask v Int
445
446 class dio p v | pin p where
447 writeD :: (v p) (v Bool) -> MTask v Bool
448 readD :: (v p) -> MTask v Bool | pin p
449
450 class pinMode v where
451 pinMode :: (v PinMode) (v p) -> MTask v () | pin p
452 declarePin :: p PinMode ((v p) -> Main (v a)) -> Main (v a) | pin p
453 \end{lstClean}
454
455 \begin{lstClean}[label={lst:gpio_examples},caption={\Gls{GPIO} example in \gls{MTASK}.}]
456 task1 :: MTask v Int | mtask v
457 task1 = declarePin A3 PMInput \a3->{main=readA a3}
458
459 task2 :: MTask v Int | mtask v
460 task2 = declarePin D3 PMOutput \d3->{main=writeD d3 true}
461 \end{lstClean}
462
463 \subsection{Task combinators}
464 Task combinators are used to combine multiple tasks into one to describe workflows.
465 There are three main types of task combinators, namely:
466 \begin{enumerate*}
467 \item Sequential combinators that execute tasks one after the other, possibly using the result of the left hand side.
468 \item Parallel combinators that execute tasks at the same time combining the result.
469 \item Miscellaneous combinators that change the semantics of a task---e.g.\ repeat it or delay execution.
470 \end{enumerate*}
471
472 \subsubsection{Sequential}
473 Sequential task combination allows the right-hand side task to observe the left-hand side task value.
474 All seqential task combinators are expressed in the \cleaninline{expr} class and can be---and are by default---derived from the Swiss army knife step combinator \cleaninline{>>*.}.
475 This combinator has a single task on the left-hand side and a list of \emph{task continuations} on the right-hand side.
476 The list of task continuations is checked every rewrite step and if one of the predicates matches, the task continues with the result of this combination.
477 \cleaninline{>>=.} is a shorthand for the bind operation, if the left-hand side is stable, the right-hand side function is called to produce a new task.
478 \cleaninline{>>|.} is a shorthand for the sequence operation, if the left-hand side is stable, it continues with the right-hand side task.
479 The \cleaninline{>>~.} and \cleaninline{>>..} combinators are variants of the ones above that ignore the stability and continue on an unstable value as well.
480
481 \begin{lstClean}[label={lst:mtask_sequential},caption={Sequential task combinators in \gls{MTASK}.}]
482 class step v | expr v where
483 (>>*.) infixl 1 :: (MTask v t) [Step v t u] -> MTask v u
484 (>>=.) infixl 0 :: (MTask v t) ((v t) -> MTask v u) -> MTask v u
485 (>>|.) infixl 0 :: (MTask v t) (MTask v u) -> MTask v u
486 (>>~.) infixl 0 :: (MTask v t) ((v t) -> MTask v u) -> MTask v u
487 (>>..) infixl 0 :: (MTask v t) (MTask v u) -> MTask v u
488
489 :: Step v t u
490 = IfValue ((v t) -> v Bool) ((v t) -> MTask v u)
491 | IfStable ((v t) -> v Bool) ((v t) -> MTask v u)
492 | IfUnstable ((v t) -> v Bool) ((v t) -> MTask v u)
493 | Always (MTask v u)
494 \end{lstClean}
495
496 \todo{more examples step?}
497
498 The following listing shows an example of a step in action.
499 The \cleaninline{readPinBin} function produces an \gls{MTASK} task that classifies the value of an analogue pin into four bins.
500 It also shows that the nature of embedding allows the host language to be used as a macro language.
501 Furthermore
502
503 \begin{lstClean}[label={lst:mtask_readpinbin},caption={Read an analog pin and bin the value in \gls{MTASK}.}]
504 readPinBin :: Int -> Main (MTask v Int) | mtask v
505 readPinBin lim = declarePin PMInput A2 \a2->
506 { main = readA a2 >>*.
507 [ IfValue (\x->x <. lim) (\_->rtrn (lit bin))
508 \\ lim <-[64,128,192,256]
509 & bin <- [0..]]}
510 \end{lstClean}
511
512 \subsubsection{Parallel}\label{sssec:combinators_parallel}
513 The result of a parallel task combination is a compound that actually executes the tasks at the same time.
514
515 There are two types of parallel task combinators (see \cref{lst:mtask_parallel}).
516 The conjunction combinator (\cleaninline{.&&.}) combines the result by putting the values from both sides in a tuple.
517 The stability of the task depends on the stability of both children.
518 If both children are stable, the result is stable, otherwise the result is unstable.
519 The disjunction combinator (\cleaninline{.\|\|.}) combines the results by picking the leftmost, most stable task.
520 The semantics are easily described using \gls{CLEAN} functions shown in \cref{lst:semantics_con,lst:semantics_dis}.
521
522 \begin{figure}[ht]
523 \centering
524 \begin{subfigure}[t]{.5\textwidth}
525 \begin{lstClean}[caption={Semantics of the\\conjunction combinator.},label={lst:semantics_con}]
526 con :: (TaskValue a) (TaskValue b)
527 -> TaskValue (a, b)
528 con NoValue r = NoValue
529 con l NoValue = NoValue
530 con (Value l ls) (Value r rs)
531 = Value (l, r) (ls && rs)
532
533 \end{lstClean}
534 \end{subfigure}%
535 \begin{subfigure}[t]{.5\textwidth}
536 \begin{lstClean}[caption={Semantics of the\\disjunction combinator.},label={lst:semantics_dis}]
537 dis :: (TaskValue a) (TaskValue a)
538 -> TaskValue a
539 dis NoValue r = r
540 dis l NoValue = l
541 dis (Value l ls) (Value r rs)
542 | rs = Value r True
543 | otherwise = Value l ls
544 \end{lstClean}
545 \end{subfigure}
546 \end{figure}
547
548 \begin{lstClean}[label={lst:mtask_parallel},caption={Parallel task combinators in \gls{MTASK}.}]
549 class (.&&.) infixr 4 v :: (MTask v a) (MTask v b) -> MTask v (a, b)
550 class (.||.) infixr 3 v :: (MTask v a) (MTask v a) -> MTask v a
551 \end{lstClean}
552
553 \Cref{lst:mtask_parallel_example} gives an example of the parallel task combinator.
554 This program will read two pins at the same time, returning when one of the pins becomes \arduinoinline{HIGH}.
555 If the combinator was the \cleaninline{.&&.} instead, the type would be \cleaninline{MTask v (Bool, Bool)} and the task would only return when both pins have been \arduinoinline{HIGH} but not necessarily at the same time.
556
557 \begin{lstClean}[label={lst:mtask_parallel_example},caption={Parallel task combinator example in \gls{MTASK}.}]
558 task :: MTask v Bool
559 task =
560 declarePin D0 PMInput \d0->
561 declarePin D1 PMInput \d1->
562 let monitor pin = readD pin >>*. [IfValue (\x->x) \x->rtrn x]
563 In {main = monitor d0 .||. monitor d1}
564 \end{lstClean}
565
566 \subsubsection{Repeat}\label{sec:repeat}
567 The \cleaninline{rpeat} combinator executes the child task.
568 If a stable value is observed, the task is reinstated.
569 The functionality of \cleaninline{rpeat} can also be simulated by using functions and sequential task combinators and even made to be stateful as can be seen in \cref{lst:blinkthreadmtask}.
570
571 \begin{lstClean}[label={lst:mtask_repeat},caption={Repeat task combinators in \gls{MTASK}.}]
572 class rpeat v where
573 rpeat :: (MTask v a) -> MTask v a
574 \end{lstClean}
575
576 To demonstrate the combinator, \cref{lst:mtask_repeat_example} show \cleaninline{rpeat} in use.
577 This task will mirror the value read from analog \gls{GPIO} pin \cleaninline{A1} to pin \cleaninline{A2} by constantly reading the pin and writing the result.
578
579 \begin{lstClean}[label={lst:mtask_repeat_example},caption={Exemplatory repeat task in \gls{MTASK}.}]
580 task :: MTask v Int | mtask v
581 task =
582 declarePin A1 PMInput \a1->
583 declarePin A2 PMOutput \a2->
584 {main = rpeat (readA a1 >>~. writeA a2 >>|. delay (lit 1000))}
585 \end{lstClean}
586
587 \subsection{\texorpdfstring{\Glsxtrlongpl{SDS}}{Shared data sources}}
588 \Glspl{SDS} in \gls{MTASK} are by default references to shared memory but can also be references to \glspl{SDS} in \gls{ITASK} (see \cref{sec:liftsds}).
589 Similar to peripherals (see \cref{sssec:peripherals}), they are constructed at the top level and are accessed through interaction tasks.
590 The \cleaninline{getSds} task yields the current value of the \gls{SDS} as an unstable value.
591 This behaviour is similar to the \cleaninline{watch} task in \gls{ITASK}.
592 Writing a new value to an \gls{SDS} is done using \cleaninline{setSds}.
593 This task yields the written value as a stable result after it is done writing.
594 Getting and immediately after setting an \gls{SDS} is not necessarily an \emph{atomic} operation in \gls{MTASK} because it is possible that another task accesses the \gls{SDS} in between.
595 To circumvent this issue, \cleaninline{updSds} is created, this task atomically updates the value of the \gls{SDS}.
596 The \cleaninline{updSds} task only guarantees atomicity within \gls{MTASK}.
597
598 \begin{lstClean}[label={lst:mtask_sds},caption={\Glspl{SDS} in \gls{MTASK}.}]
599 :: Sds a // abstract
600 class sds v where
601 sds :: ((v (Sds t)) -> In t (Main (MTask v u))) -> Main (MTask v u)
602 getSds :: (v (Sds t)) -> MTask v t
603 setSds :: (v (Sds t)) (v t) -> MTask v t
604 updSds :: (v (Sds t)) ((v t) -> v t) -> MTask v t
605 \end{lstClean}
606
607 \Cref{lst:mtask_sds_examples} shows an example using \glspl{SDS}.
608 The \cleaninline{count} function takes a pin and returns a task that counts the number of times the pin is observed as high by incrementing the \cleaninline{share} \gls{SDS}.
609 In the \cleaninline{main} expression, this function is called twice and the results are combined using the parallel or combinator (\cleaninline{.||.}).
610 Using a sequence of \cleaninline{getSds} and \cleaninline{setSds} would be unsafe here because the other branch might write their old increment value immediately after writing, effectively missing a count.\todo{beter opschrijven}
611
612 \begin{lstClean}[label={lst:mtask_sds_examples},caption={Examples with \glspl{SDS} in \gls{MTASK}.}]
613 task :: MTask v Int | mtask v
614 task = declarePin D3 PMInput \d3->
615 declarePin D5 PMInput \d5->
616 sds \share=0
617 In fun \count=(\pin->
618 readD pin
619 >>* [IfValue (\x->x) (\_->updSds (\x->x +. lit 1) share)]
620 >>| delay (lit 100) // debounce
621 >>| count pin)
622 In {main=count d3 .||. count d5}
623 \end{lstClean}
624
625 \chapter{Green computing with \texorpdfstring{\gls{MTASK}}{mTask}}%
626 \label{chp:green_computing_mtask}
627
628 \chapter{Integration with \texorpdfstring{\gls{ITASK}}{iTask}}%
629 \label{chp:integration_with_itask}
630 The \gls{MTASK} language is a multi-view \gls{DSL}, i.e.\ there are multiple interpretations possible for a single \gls{MTASK} term.
631 Using the byte code compiler (\cleaninline{BCInterpret}) \gls{DSL} interpretation, \gls{MTASK} tasks are fully integrated in \gls{ITASK} and executed as if they were regular \gls{ITASK} tasks and communicate using \gls{ITASK} \glspl{SDS}.
632 \Gls{MTASK} devices contain a domain-specific \gls{OS} (\gls{RTS}) and are little \gls{TOP} servers in their own respect, being able to execute tasks.
633 \Cref{fig:mtask_integration} shows the architectural layout of a typical \gls{IOT} system created with \gls{ITASK} and \gls{MTASK}.
634 The entire system is written as a single \gls{CLEAN} specification where multiple tasks are executed at the same time.
635 Tasks can access \glspl{SDS} according to many-to-many communication and multiple clients can work on the same task.
636 Devices are integrated into the system using the \cleaninline{widthDevice} function (see \cref{sec:withdevice}).
637 Using \cleaninline{liftmTask}, \gls{MTASK} tasks are lifted to a device (see \cref{sec:liftmtask}).
638 \Gls{ITASK} \glspl{SDS} are lifted to the \gls{MTASK} device using \cleaninline{liftsds} (see \cref{sec:liftmtask}).
639
640 \begin{figure}[ht]
641 \centering
642 \includestandalone{mtask_integration}
643 \caption{\Gls{MTASK}'s integration with \gls{ITASK}.}%
644 \label{fig:mtask_integration}
645 \end{figure}
646
647 \section{Devices}\label{sec:withdevice}
648 \Gls{MTASK} tasks in the byte code compiler view are always executed on a certain device.
649 All communication with this device happens through a so-called \emph{channels} \gls{SDS}.
650 The channels contain three fields, a queue of messages that are received, a queue of messages to send and a stop flag.
651 Every communication method that implements the \cleaninline{channelSync} class can provide the communication with an \gls{MTASK} device.
652 As of now, serial port communication, direct \gls{TCP} communication and \gls{MQTT} over \gls{TCP} are supported as communication providers.
653 The \cleaninline{withDevice} function transforms a communication provider and a task that does something with this device to an \gls{ITASK} task.
654 This task sets up the communication, exchanges specifications, handles errors and cleans up after closing.
655 \Cref{lst:mtask_device} shows the types and interface to connecting devices.
656
657 \begin{lstClean}[label={lst:mtask_device},caption={Device communication interface in \gls{MTASK}.}]
658 :: MTDevice //abstract
659 :: Channels :== ([MTMessageFro], [MTMessageTo], Bool)
660
661 class channelSync a :: a (sds () Channels Channels) -> Task () | RWShared sds
662
663 withDevice :: (a (MTDevice -> Task b) -> Task b) | iTask b & channelSync, iTask a
664 \end{lstClean}
665
666 \section{Lifting tasks}\label{sec:liftmtask}
667 Once the connection with the device is established, \ldots
668 \begin{lstClean}
669 liftmTask :: (Main (BCInterpret (TaskValue u))) MTDevice -> Task u | iTask u
670 \end{lstClean}
671
672 \section{Lifting \texorpdfstring{\glsxtrlongpl{SDS}}{shared data sources}}\label{sec:liftsds}
673 \begin{lstClean}[label={lst:mtask_itasksds},caption={Lifted \gls{ITASK} \glspl{SDS} in \gls{MTASK}.}]
674 class liftsds v where
675 liftsds :: ((v (Sds t))->In (Shared sds t) (Main (MTask v u)))
676 -> Main (MTask v u) | RWShared sds
677 \end{lstClean}
678
679 \chapter{Implementation}%
680 \label{chp:implementation}
681 IFL19 paper, bytecode instructieset~\cref{chp:bytecode_instruction_set}
682
683 \section{Integration with \texorpdfstring{\gls{ITASK}}{iTask}}
684 IFL18 paper stukken
685
686 \chapter{\texorpdfstring{\gls{MTASK}}{mTask} history}
687 \section{Generating \texorpdfstring{\gls{C}/\gls{CPP}}{C/C++} code}
688 A first throw at a class-based shallowly \gls{EDSL} for microprocessors was made by \citet{plasmeijer_shallow_2016}.
689 The language was called \gls{ARDSL} and offered a type safe interface to \gls{ARDUINO} \gls{CPP} dialect.
690 A \gls{CPP} code generation backend was available together with an \gls{ITASK} simulation backend.
691 There was no support for tasks or even functions.
692 Some time later in the 2015 \gls{CEFP} summer school, an extended version was created that allowed the creation of imperative tasks, \glspl{SDS} and the usage of functions~\citep{koopman_type-safe_2019}.
693 The name then changed from \gls{ARDSL} to \gls{MTASK}.
694
695 \section{Integration with \texorpdfstring{\gls{ITASK}}{iTask}}
696 Mart Lubbers extended this in his Master's Thesis by adding integration with \gls{ITASK} and a bytecode compiler to the language~\citep{lubbers_task_2017}.
697 \Gls{SDS} in \gls{MTASK} could be accessed on the \gls{ITASK} server.
698 In this way, entire \gls{IOT} systems could be programmed from a single source.
699 However, this version used a simplified version of \gls{MTASK} without functions.
700 This was later improved upon by creating a simplified interface where \glspl{SDS} from \gls{ITASK} could be used in \gls{MTASK} and the other way around~\citep{lubbers_task_2018}.
701 It was shown by Matheus Amazonas Cabral de Andrade that it was possible to build real-life \gls{IOT} systems with this integration~\citep{amazonas_cabral_de_andrade_developing_2018}.
702 Moreover, a course on the \gls{MTASK} simulator was provided at the 2018 \gls{CEFP}/\gls{3COWS} winter school in Ko\v{s}ice, Slovakia~\citep{koopman_simulation_2018}.
703
704 \section{Transition to \texorpdfstring{\gls{TOP}}{TOP}}
705 The \gls{MTASK} language as it is now was introduced in 2018~\citep{koopman_task-based_2018}.
706 This paper updated the language to support functions, tasks and \glspl{SDS} but still compiled to \gls{CPP} \gls{ARDUINO} code.
707 Later the bytecode compiler and \gls{ITASK} integration was added to the language~\citep{lubbers_interpreting_2019}.
708 Moreover, it was shown that it is very intuitive to write microprocessor applications in a \gls{TOP} language~\citep{lubbers_multitasking_2019}.
709 One reason for this is that a lot of design patterns that are difficult using standard means are for free in \gls{TOP} (e.g.\ multithreading).
710 In 2019, the \gls{CEFP} summer school in Budapest, Hungary hosted a course on developing \gls{IOT} applications with \gls{MTASK} as well~\citep{lubbers_writing_2019}.
711
712 \section{\texorpdfstring{\gls{TOP}}{TOP}}
713 In 2022, the SusTrainable summer school in Rijeka, Croatia hosted a course on developing greener \gls{IOT} applications using \gls{MTASK} as well (the lecture notes are to be written).
714 Several students worked on extending \gls{MTASK} with many useful features:
715 Erin van der Veen did preliminary work on a green computer analysis, built a simulator and explored the possibilities for adding bounded datatypes~\citep{veen_van_der_mutable_2020}; Michel de Boer investigated the possibilities for secure communication channels~\citep{boer_de_secure_2020}; and Sjoerd Crooijmans added abstractions for low-power operation to \gls{MTASK} such as hardware interrupts and power efficient scheduling~\citep{crooijmans_reducing_2021}.
716 Elina Antonova defined a preliminary formal semantics for a subset of \gls{MTASK}~\citep{antonova_MTASK_2022}.
717 Moreover, plans for student projects and improvements include exploring integrating \gls{TINYML} into \gls{MTASK}; and adding intermittent computing support to \gls{MTASK}.
718
719 In 2023, the SusTrainable summer school in Coimbra, Portugal will host a course on \gls{MTASK} as well.
720
721 \section{\texorpdfstring{\gls{MTASK}}{mTask} in practise}
722 Funded by the Radboud-Glasgow Collaboration Fund, collaborative work was executed with Phil Trinder, Jeremy Singer and Adrian Ravi Kishore Ramsingh.
723 An existing smart campus application was developed using \gls{MTASK} and quantitively and qualitatively compared to the original application that was developed using a traditional \gls{IOT} stack~\citep{lubbers_tiered_2020}.
724 The collaboration is still ongoing and a journal article is under review comparing four approaches for the edge layer: \gls{PYTHON}, \gls{MICROPYTHON}, \gls{ITASK} and \gls{MTASK}.
725 Furthermore, power efficiency behaviour of traditional versus \gls{TOP} \gls{IOT} stacks is being compared as well adding a \gls{FREERTOS} implementation to the mix as well
726
727 \input{subfilepostamble}
728 \end{document}