From: Mart Lubbers Date: Sat, 4 Feb 2023 17:08:35 +0000 (+0100) Subject: updates X-Git-Url: https://git.martlubbers.net/?a=commitdiff_plain;h=adcda9a326216c71bcc240dfc6882f95b183b102;p=phd-thesis.git updates --- diff --git a/asbook.tex b/asbook.tex index 11ba090..f3c5484 100644 --- a/asbook.tex +++ b/asbook.tex @@ -5,6 +5,6 @@ \begin{document} %\includepdf[landscape,booklet,pages={69-128}]{thesis.pdf}%chktex 29 chktex 8 -\includepdf[landscape,booklet,pages={1-}]{top/lang.pdf}%chktex 29 chktex 8 +\includepdf[landscape,booklet,pages={1-}]{top/green.pdf}%chktex 29 chktex 8 %\includepdf[pages={211,212}]{thesis.pdf}%chktex 29 chktex 8 \end{document} diff --git a/back/samenvatting.tex b/back/samenvatting.tex index f050544..ae94658 100644 --- a/back/samenvatting.tex +++ b/back/samenvatting.tex @@ -11,31 +11,31 @@ %\noindent% Het aantal computers om ons heen groeit enorm en hiermee ook de complexiteit van de systemen waarin ze zich bevinden. Veel van deze computers zijn \emph{randcomputers} die onderdeel zijn van het Internet of Things (IoT). -Binnen deze orkesten interacteert deze apparatuur met de buitenwereld door sensoren en actuatoren. +Binnen deze orkesten interacteren randcomputers met de buitenwereld door sensoren en actuatoren. Randcomputers bevatten vaak goedkope microcontrollers die speciaal ontworpen zijn voor ge\"{\i}ntegreerde systemen. Enerzijds hebben ze weinig geheugen, langzame rekenkernen en trage communicatie. -Anderzijds zijn ze klein en hoogst energie effici\"{e}nt. -Het programmeren van deze IoT systemen is complex omdat ze dynamisch, interactief, gedistribueerd, samenwerkend, meerlaags en multitasking zijn. -De complexiteit wordt verder opgestuwd door de semantische wrijving die voortkomt uit de grote verscheidenheid aan hard- en software karakteristieken tussen de lagen. +Anderzijds zijn ze klein en hoogst energie-effici\"{e}nt. +Het programmeren van deze IoT-systemen is complex omdat ze dynamisch, interactief, gedistribueerd, samenwerkend, meerlaags en multitasking zijn. +Ook draagt de semantische wrijving die voortkomt uit de grote verscheidenheid aan hard- en software karakteristieken tussen de lagen verder bij aan dit probleem. Taakge\"{o}rienteerd programmeren (TOP) is hierbij een oplossing. In TOP zijn taken, abstracte representaties van werk, de bouwstenen. Tijdens het uitvoeren van taken kan de huidige waarde geobserveerd worden en hierop kunnen andere taken reageren. Door taken samen te voegen of te transformeren kunnen samenwerkingsvormen uitgedrukt worden. -Vanuit deze beschrijving wordt een computer systeem gegenereerd dat gebruikers begeleid in het uitvoeren van het werk. -Een voorbeeld van een TOP-systeem is iTask, ontworpen om interactieve web toepassingen te beschrijven. +Vanuit deze beschrijving wordt een computersysteem gegenereerd dat gebruikers begeleidt in het uitvoeren van het werk. +Een voorbeeld van een TOP-systeem is iTask, ontworpen om interactieve webtoepassingen te beschrijven. De wens is om TOP ook voor randcomputers te gebruiken, maar het is niet evident hoe TOP-systemen op dusdanig beperkte middelen in te zetten. -Deze dissertatie laat zien hoe gehele IoT systemen georkestreerd kunnen worden met {TOP}. +Deze dissertatie laat zien hoe gehele IoT-systemen georkestreerd kunnen worden met {TOP}. Allereerst laat ik een wat technieken zien om ingebedde domein-specifieke talen te maken. Daarna beschrijf ik mTask, een TOP-systeem voor randcomputers ingebed in iTask. -Taken worden tijdens het uitvoeren opgebouwd waardoor ze afgestemd kunnen worden op de huidige werkeisen. +Taken worden tijdens het uitvoeren opgebouwd, waardoor ze afgestemd kunnen worden op de huidige werkeisen. Vervolgens worden ze naar het apparaat gestuurd ter interpretatie. -Een randcomputer is geschikt voor een mTask systeem als het uitgerust is met het lichtgewicht domeinspecifieke besturingssysteem. -Dit stuurprogramma voert de ontvangen taken energiezuinig uit en automatiseert alle communicatie en data verwerking. -Alle aspecten van het mTask systeem worden beschreven voorbeeldprogramma's, taalontwerp, implementatiedetails, integratie met iTask en de energiezuinige functionaliteit. -Indien samen met iTask gebruikt, kan een geheel IoT systeem laagloos geprogrammeerd worden, gebruik makend van \'e\'en broncode, programmeertaal en paradigma, abstractieniveau en typesysteem. -Eveneens worden problemen verzacht zoals semantische wrijving, onderhouds- en robuustheidsproblematiek en moeizame onderlinge samenwerking. +Een randcomputer is geschikt voor een mTask als het uitgerust is met het lichtgewicht domeinspecifieke besturingssysteem. +Dit stuurprogramma voert de ontvangen taken energiezuinig uit en automatiseert tevens alle communicatie en dataverwerking. +Alle aspecten van het mTask-systeem worden beschreven: voorbeeldprogramma's, taalontwerp, implementatiedetails, integratie met iTask en de energiezuinige functionaliteit. +Indien samen met iTask gebruikt, kan een geheel IoT-systeem laagloos geprogrammeerd worden, gebruik makend van \'e\'en broncode, programmeertaal en paradigma, abstractieniveau en typesysteem. +Eveneens wordt de semantische wrijving, onderhouds- en robuustheidsproblematiek en moeizame onderlinge samenwerking verzacht. %\end{center} \input{subfilepostamble} \selectlanguage{british} diff --git a/thesis.tex b/thesis.tex index 93a20d7..4d629dd 100644 --- a/thesis.tex +++ b/thesis.tex @@ -9,8 +9,8 @@ % To show hboxes even when in non-draft mode %\overfullrule=1pt -\showboxdepth=\maxdimen% -\showboxbreadth=\maxdimen% +%\showboxdepth=\maxdimen% +%\showboxbreadth=\maxdimen% % \showboxdepth=5 % \showboxbreadth=5 \setlength{\overfullrule}{20pt} diff --git a/top/lang.tex b/top/lang.tex index 4677ada..0d2f3ab 100644 --- a/top/lang.tex +++ b/top/lang.tex @@ -11,7 +11,7 @@ \begin{chapterabstract} This chapter introduces the \gls{TOP} language \gls{MTASK} by: \begin{itemize} - \item introducing the setup of the language; + \item introducing class-based shallow embedding and the setup of the \gls{MTASK} language; \item describing briefly the various interpretations; \item demonstrating how the type system is leveraged to enforce all constraints; \item showing the language interface for expressions, datatypes, and functions; @@ -19,14 +19,16 @@ \end{itemize} \end{chapterabstract} -The \gls{MTASK} system is a complete \gls{TOP} programming environment for programming microcontrollers. -This means that it not only contains a \gls{TOP} language but also a \gls{TOP} engine. -Due to the nature of the embedding technique, it is possible to have multiple interpretations for programs written in the \gls{MTASK} language. +Regular \gls{FP} and \gls{TOP} languages do not run on resource-constrained edge devices. +A \gls{DSL} is therefore used as the basis of the \gls{MTASK} system, a complete \gls{TOP} programming environment for programming microcontrollers. It is implemented as an \gls{EDSL} in \gls{CLEAN} using class-based---or tagless-final---embedding. This means that the language interface, i.e.\ the language constructs, are a collection of type classes. Interpretations of this interface are data types implementing these classes. -This particular type of embedding results in the language being is extensible both in language constructs and in intepretations. +Due to the nature of this embedding technique, it is possible to have multiple interpretations for programs written in the \gls{MTASK} language. +Furthermore, this particular type of embedding has the property that it is extensible both in language constructs and in intepretations. Adding a language construct is as simple as adding a type class and adding an interpretation is done by creating a new data type and providing implementations for the various type classes. + +\section{Class-based shallow embedding} Let us illustrate this technique by taking the very simple language of literal values. This language interface can be described using a single type constructor class with a single function \cleaninline{lit}. This function is for lifting values, when it has a \cleaninline{toString} instance, from the host language to our new \gls{DSL}. @@ -50,8 +52,8 @@ instance literals Eval where lit a = Eval a \end{lstClean} -Extending our language with a printer happens by defining a new data type and providing instances for the type constructor classes. -The printer shown below only stores a printed representation and hence the type is just a phantom type: +Extending the language with a printer is done by defining a new data type and providing instances for the type constructor classes. +The printer shown below only stores a printed representation and hence the type variable is just a phantom type: \begin{lstClean} :: Printer a = Printer String @@ -79,75 +81,20 @@ instance addition Printer where Terms in our toy language can be overloaded in their interpretation, they are just an interface. For example, $1+5$ is written as \cleaninline{add (lit 1) (lit 5)} and has the type \cleaninline{v Int \| literals, addition v}. -However, due to the way polymorphism is implemented in most functional languages, it is not always straightforward to use multiple interpretations in one function. +However, due to the way let-polymorphism is implemented in most functional languages, it is not always straightforward to use multiple interpretations in one function. Creating such a function, e.g.\ one that both prints and evaluates an expression, requires rank-2 polymorphism (see \cref{lst:rank2_mtask}). -\section{Interpretations} -This section describes all the interpretations tha the \gls{MTASK} language has. -Not all of these interpretations are necessarily \gls{TOP} engines, i.e.\ not all the interpretations execute the resulting tasks. -Some may perform an analysis over the program or typeset the program so that a textual representation can be shown. - -\subsection{Pretty printer} -The pretty printer interpretation converts the expression to a string representation. -As the host language \gls{CLEAN} constructs the \gls{MTASK} expressions at run time, it can be useful to show the constructed expression at run time as well. -The only function exposed for this interpretation is the \cleaninline{showMain} function (\cref{lst:showmain}). -It runs the pretty printer and returns a list of strings containing the pretty printed result. -The pretty printing function does the best it can but obviously cannot reproduce the layout, curried functions, and variable names. -This shortcoming is illustrated by printing a blink task that contains a function and currying in \cref{lst:showexample}. - -\begin{lstClean}[caption={The entrypoint for the pretty printing interpretation.},label={lst:showmain}] -:: Show a // from the mTask pretty printing library -showMain :: (Main (Show a)) -> [String] -\end{lstClean} - -\begin{lstClean}[caption={Pretty printing interpretation example.},label={lst:showexample}] -blinkTask :: Main (MTask v Bool) | mtask v -blinkTask = - fun \blink=(\state-> - writeD d13 state >>|. delay (lit 500) >>=. blink o Not - ) In {main = blink true} - -// output when printing: -// fun f0 a1 = writeD(D13, a1) >>= \a2.(delay 1000) -// >>| (f0 (Not a1)) in (f0 True) -\end{lstClean} - -\subsection{Simulator} -The simulator converts the expression to a ready-for-work \gls{ITASK} simulation. -The task resulting from the \cleaninline{simulate} function presents the user with an interactive simulation environment (see \cref{lst:simulatemain,fig:sim}). -The simulation allows the user to (partially) execute tasks, control the simulated peripherals, inspect the internal state of the tasks, and interact with \glspl{SDS}. - -\begin{lstClean}[caption={The entrypoint for the simulation interpretation.},label={lst:simulatemain}] -:: TraceTask a // from the mTask simulator library -simulate :: (Main (TraceTask a)) -> [String] -\end{lstClean} - -\begin{figure} - \centering - \includegraphics[width=\linewidth]{simg} - \caption{Simulator interface for the blink program.}\label{fig:sim} -\end{figure} - -\subsection{Byte code compiler} -The main interpretation of the \gls{MTASK} system is the byte code compiler (\cleaninline{:: BCInterpret}). -With it, and a handful of integration functions and tasks, \gls{MTASK} tasks can be executed on microcontrollers and integrated in \gls{ITASK} as if they were regular \gls{ITASK} tasks. -Furthermore, with a special language construct, \glspl{SDS} can be shared between \gls{MTASK} and \gls{ITASK} programs as well. -For this chapter, the focus lies on the language itself. -The integration with \gls{ITASK} is explained thoroughly later in \cref{chp:integration_with_itask}. - -When using the byte code compiler interpretation in conjunction with the \gls{ITASK} integration, \gls{MTASK} is a heterogeneous \gls{DSL}. -I.e.\ some components---for example the \gls{RTS} on the microcontroller that executes the tasks---is largely unaware of the other components in the system, and it is executed on a completely different architecture. -The \gls{MTASK} language is based on a simply-typed $\lambda$-calculus with support for some basic types, arithmetic operations, and function definitions. -As the language is a \gls{TOP} language, is is enriched with a task language (see \cref{sec:top}). - \section{Types} -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. -However, not all types in the host language are suitable for microcontrollers that may only have \qty{2}{\kibi\byte} of \gls{RAM} so class constraints are therefore added to the \gls{DSL} functions. -The most used class constraint is the \cleaninline{type} class collection containing functions for serialization, printing, \gls{ITASK} constraints, \etc. -Many of these functions are usually automatically derived using generic programming but can be specialised when needed. -An even stronger restriction on types is defined for types that have a stack representation. +The \gls{MTASK} language is a tagless-final \gls{EDSL} as well. +As it is shallowly embedded, the types of the terms in the language can be constrained by type classes. +Types in the \gls{MTASK} language are expressed as types in the host language, to make the language type safe. +However, not all types in the host language are suitable for microcontrollers that may only have \qty{2}{\kibi\byte} of \gls{RAM}, so class constraints are added to the \gls{DSL} functions. +\Cref{tbl:mtask-c-datatypes} shows the mapping from \gls{CLEAN} types to \ccpp{} types. +The most used class constraint is the \cleaninline{type} class collection containing functions for serialization, printing, \gls{ITASK} constraints, \etc\ \citep[\citesection{6.9}]{plasmeijer_clean_2021}. +Most of these functions are automatically derivable using generic programming but can be specialised when needed. +An even stronger restriction is defined for types that have a stack representation. This \cleaninline{basicType} class has instances for many \gls{CLEAN} basic types such as \cleaninline{Int}, \cleaninline{Real} and \cleaninline{Bool}. -The class constraints for values in \gls{MTASK} are omnipresent in all functions and therefore usually omitted for brevity and clarity. +These class constraints for values in \gls{MTASK} are omnipresent in all functions and therefore usually omitted for brevity and clarity. \begin{table}[ht] \centering @@ -155,11 +102,11 @@ The class constraints for values in \gls{MTASK} are omnipresent in all functions \label{tbl:mtask-c-datatypes} \begin{tabular}{lll} \toprule - \cmtask{} & \ccpp{} type & \textnumero{}bits\\ + \cmtask{} & \ccpp{} & \textnumero{}bits\\ \midrule \cleaninline{Bool} & \cinline{bool} & 16\\ \cleaninline{Char} & \cinline{char} & 16\\ - \cleaninline{Int} & \cinline{int16_t} & 16\\ + \cleaninline{Int} & \cinline{int16_t}\footnotemark{} & 16\\ \cleaninline{Real} & \cinline{float} & 32\\ \cleaninline{:: Long} & \cinline{int32_t} & 32\\ \cleaninline{:: T = A \| B \| C} & \cinline{enum} & 16\\ @@ -167,26 +114,30 @@ The class constraints for values in \gls{MTASK} are omnipresent in all functions \end{tabular} \end{table} +\footnote{In \gls{ARDUINO} \ccpp{} this usually equals a \cinline{long}.} \Cref{lst:constraints} contains the definitions for the auxiliary types and type constraints (such as \cleaninline{type} and \cleaninline{basicType}) that are used to construct \gls{MTASK} expressions. -The \gls{MTASK} language interface consists of a core collection of type classes bundled in the type class \cleaninline{class mtask}. -Every interpretation implements the type classes in the \cleaninline{mtask} class -There are also \gls{MTASK} extensions that not every interpretation implements and are thus not included in the \cleaninline{mtask} class collection such as peripherals and \gls{ITASK} integration. \begin{lstClean}[caption={Classes and class collections for the \gls{MTASK} language.},label={lst:constraints}] class type t | iTask, ... , fromByteCode, toByteCode t class basicType t | type t where ... +\end{lstClean} + +The \gls{MTASK} language interface consists of a core collection of type classes bundled in the type class \cleaninline{class mtask} (see \cref{lst:collection}). +Every interpretation of \gls{MTASK} terms implements the type classes in the \cleaninline{mtask} class collection. +Optional \gls{MTASK} constructs such as perpipherals or lowered \gls{ITASK} \glspl{SDS} are not included in this class collection because not all devices or interpretations support this. +\begin{lstClean}[caption={Class collection for the \gls{MTASK} language.},label={lst:collection}] class mtask v | expr, ..., int, real, long v \end{lstClean} -Peripheral, \gls{SDS}, and function definitions are always defined at the top level. +Peripheral, \gls{SDS}, and function definitions are always defined at the top level of \gls{MTASK} programs. This is enforced by the \cleaninline{Main} type. -Most top level definitions, such as functions, are defined using \gls{HOAS}. +Most top level definitions are defined using \gls{HOAS}. To make their syntax friendlier, the \cleaninline{In} type---an infix tuple---is used to combine these top level definitions. -An example of this can be seen in \cleaninline{someTask} shown in \cref{lst:mtask_types}. +To illustrate the structure of a \gls{MTASK} programs, \cref{lst:mtask_types} shows a skeleton of a program. % VimTeX: SynIgnore on -\begin{lstClean}[caption={Example task and auxiliary types in the \gls{MTASK} language.},label={lst:mtask_types}] +\begin{lstClean}[caption={Auxiliary types and example task in the \gls{MTASK} language.},label={lst:mtask_types}] // From the mTask library :: Main a = { main :: a } :: In a b = (In) infix 0 a b @@ -205,11 +156,11 @@ someTask = Expressions in the \gls{MTASK} language are usually overloaded in their interpretation (\cleaninline{v}). In \gls{CLEAN}, all free variables in a type are implicitly universally quantified. -In order to use the \gls{MTASK} expressions with multiple interpretations, rank-2 polymorphism is required \citep{odersky_putting_1996}\citep[\citesection{3.7.4}]{plasmeijer_clean_2021}. +In order to use the \gls{MTASK} expressions with multiple interpretations, rank-2 polymorphism is required \citep{odersky_putting_1996}. \Cref{lst:rank2_mtask} shows an example of a function that simulates an \gls{MTASK} expression while showing the pretty printed representation in parallel. -Providing a type for the \cleaninline{simulateAndPrint} function is mandatory as the compiler cannot infer the type of rank-2 polymorphic functions. +Providing a type for the \cleaninline{simulateAndPrint} function is mandatory as the compiler cannot infer the type of rank-2 polymorphic functions\citep[\citesection{3.7.4}]{plasmeijer_clean_2021}. -\begin{lstClean}[label={lst:rank2_mtask},caption={Rank-2 polymorphism to allow multiple interpretations}] +\begin{lstClean}[label={lst:rank2_mtask},caption={Rank-2 polymorphism to allow multiple interpretations.}] simulateAndPrint :: (A.v: Main (MTask v a) | mtask v) -> Task a | type a simulateAndPrint mt = simulate mt @@ -217,11 +168,16 @@ simulateAndPrint mt = \end{lstClean} \section{Expressions}\label{sec:expressions} -This section shows all \gls{MTASK} constructs for expressions. -\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 numeric and boolean arithmetics; do comparisons; and conditional execution. -For every common boolean and 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. - -\begin{lstClean}[caption={The \gls{MTASK} class for expressions},label={lst:expressions}] +This section shows all \gls{MTASK} language constructs for expressions. +\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 numeric and boolean arithmetics; +do comparisons; +and perform conditional execution. +For every common boolean and arithmetic operator in the host language, an \gls{MTASK} variant is present. +The operators are suffixed by a period to not clash with the built-in operators in \gls{CLEAN}. + +\begin{lstClean}[caption={The \gls{MTASK} class for expressions.},label={lst:expressions}] class expr v where lit :: t -> v t | type t (+.) infixl 6 :: (v t) (v t) -> v t | basicType, +, zero t @@ -245,11 +201,11 @@ class long v a :: (v a) -> v Long \end{lstClean} Values from the host language must be explicitly lifted to the \gls{MTASK} language using the \cleaninline{lit} function. -For convenience, there are many lower-cased macro definitions for often used constants such as \cleaninline{true :== lit True}, \cleaninline{false :== lit False}. +For convenience, there are many lower-cased macro definitions for often-used constants such as \cleaninline{true :== lit True}, \cleaninline{false :== lit False}. -\Cref{lst:example_exprs} shows some examples of expressions in the language. +\Cref{lst:example_exprs} shows some examples of expressions in the \gls{MTASK} language. Since they are only expressions, there is no need for a \cleaninline{Main}. -\cleaninline{e0} defines the literal \num{42}, \cleaninline{e1} calculates the literal \num{42.0} using real numbers. +\cleaninline{e0} defines the literal \num{42}, \cleaninline{e1} calculates the literal \num{42.0} using real numbers and uses a type conversion. \cleaninline{e2} compares \cleaninline{e0} and \cleaninline{e1} as integers and if they are equal it returns $\frac{\text{\cleaninline{e2}}}{2}$ and \cleaninline{e0} otherwise. \begin{lstClean}[label={lst:example_exprs},caption={Example \gls{MTASK} expressions.}] @@ -264,9 +220,10 @@ e2 = If (e0 ==. int e1) (int e1 /. lit 2) e0 \end{lstClean} -The \gls{MTASK} language is shallowly embedded in \gls{CLEAN} and the terms are constructed at run time. -This means that \gls{MTASK} programs can also be tailor-made at run time or constructed using \gls{CLEAN} functions maximising the linguistic reuse \citep{krishnamurthi_linguistic_2001}. -The \cleaninline{approxEqual} function in \cref{lst:example_macro} performs a simple approximate equality---admittedly not taking into account all floating point pecularities. +The \gls{MTASK} language is shallowly embedded in \gls{CLEAN} and the terms are constructed and hence compiled at run time. +This means that \gls{MTASK} programs can also be tailor-made at run time using \gls{CLEAN} functions, maximising the linguistic reuse \citep{krishnamurthi_linguistic_2001}. +The \cleaninline{approxEqual} function in \cref{lst:example_macro} is an example of this. +It performs a simple approximate equality---admittedly not taking into account all floating point pecularities. When calling \cleaninline{approxEqual} in an \gls{MTASK} expression, the resulting code is inlined. \begin{lstClean}[label={lst:example_macro},caption={Approximate equality as an example of linguistic reuse in \gls{MTASK}.}] @@ -279,14 +236,15 @@ approxEqual x y eps = If (x ==. y) true \end{lstClean} \subsection{Data types} -Most of \gls{CLEAN}'s fixed-size basic types are mapped on \gls{MTASK} types (see \cref{tbl:mtask-c-datatypes}). +Most of the fixed-size basic types from \gls{CLEAN} are mapped on \gls{MTASK} types (see \cref{tbl:mtask-c-datatypes}). However, it is useful to have access to compound types as well. -All types in \gls{MTASK} must have a fixed-size representation on the stack, so sum types are not (yet) supported. -While it is possible to lift any 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}). +All types in \gls{MTASK} have a fixed-size representation on the stack, so sum types are not (yet) supported. +It is possible to lift any types, e.g.\ tuples, using the \cleaninline{lit} function as long as they have instances for the required type classes. +However, you cannot do anything with values of the types besides passing them around. To be able to use types as first-class citizens, constructors, and field selectors or deconstructors are required (see \cref{chp:first-class_datatypes}). -\Cref{lst:tuple_exprs} shows the scaffolding for supporting tuples in \gls{MTASK}. +\Cref{lst:tuple_exprs} shows the scaffolding required for supporting tuples in \gls{MTASK}. 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, a deconstructor. -Examples for using tuples can be found later in \cref{sec:mtask_functions}. +Examples of \gls{MTASK} programs using tuples are seen later in \cref{sec:mtask_functions}. \begin{lstClean}[label={lst:tuple_exprs},caption={Tuple constructor and field selectors in \gls{MTASK}.}] class tupl v where @@ -294,16 +252,18 @@ class tupl v where first :: (v (a, b)) -> v a | type a & type b second :: (v (a, b)) -> v b | type a & type b + tupopen :: ((v a, v b) -> v c) -> ((v (a, b)) -> v c) tupopen f :== \v->f (first v, second v) \end{lstClean} \subsection{Functions}\label{sec:mtask_functions} Adding functions to the language is achieved by one type class to the \gls{DSL}. 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}. -The \gls{MTASK} language only allows first-order functions and does not allow partial function application. -This is restricted by using a multi-parameter type class where the first parameter represents the arguments and the second parameter the view or interpretation. +The \gls{MTASK} language only allows first-order functions and no partial function application. +To restrict this, a multi-paramater type class is used instead of a type class with one type variable. +The first parameter represents the shape of the arguments, the second parameter the interpretation. An instance is provided for each function arity instead of providing an instance for all possible arities to enforce that all functions are first order. -By using tuples for the arguments, partial function applications is eradicated. +By using argument tuples to represent the arity of the function, partial function applications are eradicated. The definition of the type class and some instances for the pretty printer are as follows: \begin{lstClean}[caption={Functions in \gls{MTASK}.}] @@ -318,16 +278,18 @@ instance fun (Show a, Show b, Show c) Show | type a, ... where ... \end{lstClean} 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}. -\Cref{lst:function_examples} show some examples of functions to demonstrate the syntax for functions. +\Cref{lst:function_examples} show some examples of functions to illustrate the syntax. Splitting out the function definition for each single arity means that for every function arity and combination of arguments, a separate class constraint must be created. Many of the often used functions are already bundled in the \cleaninline{mtask} class constraint collection. The \cleaninline{factorial} functions shows a recursive version of the factorial function. -In the \cleaninline{factorialtail} function, a tail-call optimised version of the factorial function, a manually added class constraint can be seen. -Definiting zero arity functions, always called with the unit as an argument, is shown in the \cleaninline{zeroarity} expression. +The \cleaninline{factorialtail} function is a tail-call optimised version of the factorial function. +It contains a manually added class constraint. +Zero-arity functions are always called with unit as an argument. +An illustration of this is seen in the \cleaninline{zeroarity} expression. Finally, \cleaninline{swapTuple} shows an example of a tuple being swapped. % VimTeX: SynIgnore on -\begin{lstClean}[label={lst:function_examples},caption={Function examples in \gls{MTASK}.}] +\begin{lstClean}[label={lst:function_examples},caption={Examples of various functions in \gls{MTASK}.}] factorial :: Main (v Int) | mtask v factorial = fun \fac=(\i->If (i <. lit 1) @@ -358,30 +320,33 @@ swapTuple = \section{Tasks and task combinators}\label{sec:top} This section describes the task language of \gls{MTASK}. -\Gls{TOP} languages are languages enriched with tasks. +\Gls{TOP} languages are programming languages enriched with tasks. Tasks represent abstract pieces of work and can be combined using combinators. -Creating tasks is done by evaluating expressions and this is called a task tree, a run time representation of a task. -After evaluation, the resulting task tree is \emph{rewritten}, i.e.\ they are continuously given a small slice of execution time after which a task value is yielded. -This task value is observable by other tasks and can be acted upon. +Creating tasks is done by evaluating expressions. +The result of an evaluated task expression is called a task tree, a run time representation of a task. +In order to evaluate a task, the resulting task tree is \emph{rewritten}, i.e.\ similar to rewrite systems, they perform a bit of work, step by step. +With each step, a task value is yielded that is observable by other tasks and can be acted upon. \todo{dui\-de\-lijk ge\-noeg?} The implementation in the \gls{MTASK} \gls{RTS} for task execution is shown in \cref{chp:implementation}. -The following sections show the definition of the functions for creating tasks. -They also show the semantics of tasks, their observable value in relation to the work that the task represents. -The task language of \gls{MTASK} is divided into three categories, namely +The following sections show the definitions of the functions for creating tasks. +They also show the semantics of tasks: their observable value in relation to the work that the task represents. +The task language of \gls{MTASK} is divided into three categories: \begin{description} \item [Basic tasks] are the leaves in the task trees. In most \gls{TOP} systems, the basic tasks are called editors, modelling the interactivity with the user. - In \gls{MTASK}, there are no \emph{editors} in that sense but there is interaction with the outside world through microcontroller peripherals such as sensors and actuators. - \item [Task combinators] provide a way of describing the workflow. + In \gls{MTASK}, there are no editors in that sense. + Editors in \gls{MTASK} model the interaction with the outside world through peripherals such as sensors and actuators. + \item [Task combinators] provide a way of describing the workflow or collaboration. They combine one or more tasks into a compound task. - \item [\Glspl{SDS}] are references to data in \gls{MTASK}. + \item [\Glspl{SDS}] are typed references to shared memory in \gls{MTASK}. The data is available for tasks using many-to-many communication but only from within the task language to ensure atomicity. \end{description} As \gls{MTASK} is integrated with \gls{ITASK}, a stability distinction is made for task values just as in \gls{ITASK}. -A task in \gls{MTASK} is denoted by the \gls{DSL} type synonym shown in \cref{lst:task_type}, an expression of the type \cleaninline{TaskValue a} in interpretation \cleaninline{v}. +A task in \gls{MTASK} is denoted by the \gls{DSL} type synonym shown in \cref{lst:task_type}. +A task is an expression of the type \cleaninline{TaskValue a} in interpretation \cleaninline{v}. \begin{lstClean}[label={lst:task_type},caption={Task type in \gls{MTASK}.}] :: MTask v a :== v (TaskValue a) @@ -393,63 +358,42 @@ A task in \gls{MTASK} is denoted by the \gls{DSL} type synonym shown in \cref{ls \end{lstClean} \subsection{Basic tasks} -The most rudimentary basic tasks are the \cleaninline{rtrn} and \cleaninline{unstable} tasks. -They lift the value from the \gls{MTASK} expression language to the task domain either as a stable value or an unstable value. +The \gls{MTASK} language contains interactive and non-interactive basic tasks. +The most rudimentary non-interactive basic tasks in the task language of \gls{MTASK} are \cleaninline{rtrn} and \cleaninline{unstable}. +They lift the value from the \gls{MTASK} expression language to the task domain either as a stable or unstable value. There is also a special type of basic task for delaying execution. -The \cleaninline{delay} task---given a number of milliseconds---yields an unstable value while the time has not passed. +The \cleaninline{delay} task---parametrised by a number of milliseconds---yields an unstable value while the time has not passed. Once the specified time has passed, the time it overshot the planned time is yielded as a stable task value. See \cref{sec:repeat} for an example task using \cleaninline{delay}. -\begin{lstClean}[label={lst:basic_tasks},caption={Function examples in \gls{MTASK}.}] +\begin{lstClean}[label={lst:basic_tasks},caption={Non-interactive basic tasks in \gls{MTASK}.}] class rtrn v :: (v t) -> MTask v t class unstable v :: (v t) -> MTask v t class delay v :: (v n) -> MTask v n | long v n \end{lstClean} \subsubsection{Peripherals}\label{sssec:peripherals} -In order for the edge devices to interact with their environment, peripherals such as sensors and actuators are employed. +In order for the edge device to interact with the environment, peripherals such as sensors and actuators are employed. Some peripherals are available on the microcontroller package, others are connected with wires using protocols such as \gls{I2C}. For every supported sensor or actuator, basic tasks are available that allow interaction with the specific peripheral. -The type classes for these tasks are not included in the \cleaninline{mtask} class collection as not all devices nor all language interpretations support all peripherals connected. - -\Cref{lst:dht} shows the type classes for \glspl{DHT} sensors. -Other peripherals have similar interfaces, they are available in the \cref{sec:aux_peripherals}. -For the \gls{DHT} sensor there are two basic tasks, \cleaninline{temperature} and \cleaninline{humidity}, that produce a task that yields the observed temperature in \unit{\celcius} or relative humidity as a percentage as an unstable value. -Currently, two different types of \gls{DHT} sensors are supported, the \emph{DHT} family of sensors connect through the \gls{ONEWIRE} protocol and the \emph{SHT} family of sensors connected using the \gls{I2C} protocol. -Creating such a \cleaninline{DHT} object is very similar to creating functions in \gls{MTASK} and uses \gls{HOAS} to make it type safe. - -\begin{lstClean}[label={lst:dht},caption={The \gls{MTASK} interface for \glspl{DHT} sensors.}] -:: DHT //abstract -:: DHTInfo - = DHT_DHT Pin DHTtype - | DHT_SHT I2CAddr -:: DHTtype = DHT11 | DHT21 | DHT22 -class dht v where - DHT :: DHTInfo ((v DHT) -> Main (v b)) -> Main (v b) | type b - temperature :: (v DHT) -> MTask v Real - humidity :: (v DHT) -> MTask v Real - -measureTemp :: Main (MTask v Real) | mtask v & dht v -measureTemp = DHT (DHT_SHT (i2c 0x36)) \dht-> - {main=temperature dht} -\end{lstClean} +The type classes for these tasks are not included in the \cleaninline{mtask} class collection as not all devices nor all language interpretations support every peripherals connected. An example of a built-in peripheral is the \gls{GPIO} system. This array of digital and analogue pins is controlled through software. -\Gls{GPIO} access is divided into three classes: analogue \gls{IO}, digital \gls{IO} and pin modes configuration (see \cref{lst:gpio}). -For all pins and pin modes an \gls{ADT} is available that enumerates the pins. +\Gls{GPIO} access is divided into three classes: analogue \gls{IO}, digital \gls{IO} and pin mode configuration (see \cref{lst:gpio}). +For all pins and pin modes, an \gls{ADT} is available that enumerates the pins. The analogue \gls{GPIO} pins of a microcontroller are connected to an \gls{ADC} that translates the measured voltage to an integer. Digital \gls{GPIO} pins of a microcontroller report either a high or a low value. Both analogue and digital \gls{GPIO} pins can be read or written to, but it is advised to set the pin mode accordingly. -The \cleaninline{pin} type class allows functions to be overloaded in either the analogue or digital pins, e.g.\ analogue pins can be considered as digital pins as well. +The \cleaninline{pin} type class allows functions to be overloaded in either the analogue or digital pins, e.g.\ analogue pins can be considered digital pins as well. For digital \gls{GPIO} interaction, the \cleaninline{dio} type class is used. The first argument of the functions in this class is overloaded, i.e.\ it accepts either an \cleaninline{APin} or a \cleaninline{DPin}. Analogue \gls{GPIO} tasks are bundled in the \cleaninline{aio} type class. \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. -This setting can be applied using the \cleaninline{pinMode} class by hand or by using the \cleaninline{declarePin} \gls{GPIO} pin constructor. -Setting the pin mode is a task that immediately finisheds and fields a stable unit value. -Writing to a pin is also a task that immediately finishes but yields the written value instead. +This setting can be set using the \cleaninline{pinMode} class by hand or by using the \cleaninline{declarePin} \gls{GPIO} pin constructor to declare it at the top level. +Setting the pin mode is a task that immediately finisheds and yields a stable unit value. +Writing to a pin is also a task that immediately finishes, but yields the written value. Reading a pin is a task that yields an unstable value---i.e.\ the value read from the actual pin. \begin{lstClean}[label={lst:gpio},caption={The \gls{MTASK} interface for \gls{GPIO} access.}] @@ -488,21 +432,45 @@ task2 :: MTask v Int | mtask v task2 = declarePin D3 PMOutput \d3->{main=writeD d3 true} \end{lstClean} +Peripherals are bundled by their functionality in \gls{MTASK}. +For example, \cref{lst:dht} shows the type classes for all supported \gls{DHT} sensors. +Currently, two different types of \gls{DHT} sensors are supported, the \emph{DHT} family of sensors connect through the \gls{ONEWIRE} protocol and the \emph{SHT} family of sensors connected using the \gls{I2C} protocol. +Creating such a \cleaninline{DHT} object is very similar to creating functions in \gls{MTASK} and uses \gls{HOAS} to make it type safe. +When provided a configuration and a configuration function, the \gls{DHT} object can be brought into scope. +For the \gls{DHT} sensor there are two basic tasks, \cleaninline{temperature} and \cleaninline{humidity}, that produce a task that yields the observed temperature in \unit{\celcius} or the relative humidity as an unstable value. +Other peripherals have similar interfaces, they are available in \cref{sec:aux_peripherals}. + +\begin{lstClean}[label={lst:dht},caption={The \gls{MTASK} interface for \glspl{DHT} sensors.}] +:: DHT //abstract +:: DHTInfo + = DHT_DHT Pin DHTtype + | DHT_SHT I2CAddr +:: DHTtype = DHT11 | DHT21 | DHT22 +class dht v where + DHT :: DHTInfo ((v DHT) -> Main (v b)) -> Main (v b) | type b + temperature :: (v DHT) -> MTask v Real + humidity :: (v DHT) -> MTask v Real + +measureTemp :: Main (MTask v Real) | mtask, dht v +measureTemp = DHT (DHT_SHT (i2c 0x36)) \dht->{main=temperature dht} +\end{lstClean} + \subsection{Task combinators} Task combinators are used to combine multiple tasks to describe workflows. The \gls{MTASK} language has a set of simpler combinators from which more complicated workflow can be derived. There are three main types of task combinators, namely: -\begin{enumerate} +\begin{itemize} \item sequential combinators that execute tasks one after the other, possibly using the result of the left-hand side; \item parallel combinators that execute tasks at the same time, combining the result; \item miscellaneous combinators that change the semantics of a task---for example a combinator that repeats the child task. -\end{enumerate} +\end{itemize} \subsubsection{Sequential} Sequential task combination allows the right-hand side expression to \emph{observe} the left-hand side task value. -All sequential task combinators are expressed in the \cleaninline{step} class and are by default derived from the Swiss Army knife step combinator \cleaninline{>>*.}. +All sequential task combinators are defined in the \cleaninline{step} class and are by default defined in terms of the Swiss Army knife step combinator (\cleaninline{>>*.}, \cref{lst:mtask_sequential}). This combinator has a single task on the left-hand side and a list of \emph{task continuations} on the right-hand side. -The list of task continuations is checked during evaluation of the left-hand side and if one of the predicates matches, the task continues with the result of this combination. +Every rewrite step, the list of task continuations are tested on the task value. +If one of the predicates matches, the task continues with the result of this continuations. Several shorthand combinators are derived from the step combinator. \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. \cleaninline{>>\|.} is a shorthand for the sequence operation, if the left-hand side is stable, it continues with the right-hand side task. @@ -532,13 +500,13 @@ readPinBin :: Int -> Main (MTask v Int) | mtask v readPinBin lim = declarePin PMInput A2 \a2-> { main = readA a2 >>*. [ IfValue (\x->x <. lim) (\_->rtrn (lit bin)) - \\ lim <-[64,128,192,256] + \\ lim <- [64,128,192,256] & bin <- [0..]]} \end{lstClean} \subsubsection{Parallel}\label{sssec:combinators_parallel} -The result of a parallel task combination is a compound task that actually results in both tasks being executed at the same time. -There are two types of parallel task combinators (see \cref{lst:mtask_parallel}). +The result of a parallel task combination is a compound task that executes both tasks at the same time. +There are two types of parallel task combinators in the \gls{MTASK} language (see \cref{lst:mtask_parallel}). \begin{lstClean}[label={lst:mtask_parallel},caption={Parallel task combinators in \gls{MTASK}.}] class (.&&.) infixr 4 v :: (MTask v a) (MTask v b) -> MTask v (a, b) @@ -549,7 +517,7 @@ The conjunction combinator (\cleaninline{.&&.}) combines the result by putting t The stability of the task depends on the stability of both children. If both children are stable, the result is stable, otherwise the result is unstable. The disjunction combinator (\cleaninline{.\|\|.}) combines the results by picking the leftmost, most stable task. -The semantics are most easily described using the \gls{CLEAN} functions shown in \cref{lst:semantics_con,lst:semantics_dis}. +The semantics of both parallel combinators are most easily described using the \gls{CLEAN} functions shown in \cref{lst:semantics_con,lst:semantics_dis}. \begin{figure}[ht] \centering @@ -579,7 +547,7 @@ dis (Value l ls) (Value r rs) \Cref{lst:mtask_parallel_example} gives an example program that uses the parallel task combinator. This task read two pins at the same time, returning when one of the pins becomes high. -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 are high but not necessarily at the same time. +If the combinator was the \cleaninline{.&&.}, the type would be \cleaninline{MTask v (Bool, Bool)} and the task would only return when both pins are high but not necessarily at the same time. \begin{lstClean}[label={lst:mtask_parallel_example},caption={Parallel task combinator example in \gls{MTASK}.}] task :: MTask v Bool @@ -591,41 +559,40 @@ task = \end{lstClean} \subsubsection{Repeat}\label{sec:repeat} -In many workflows, tasks are to be executed continuously. +In many workflows, tasks are to be executed repeatedly. The \cleaninline{rpeat} combinator does this by executing the child task until it becomes stable. Once a stable value is observed, the task is reinstated. -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}. +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 from the blink example from \cref{chp:top4iot}. \begin{lstClean}[label={lst:mtask_repeat},caption={Repeat task combinators in \gls{MTASK}.}] class rpeat v where rpeat :: (MTask v a) -> MTask v a \end{lstClean} -To demonstrate the combinator, \cref{lst:mtask_repeat_example} shows the \cleaninline{rpeat} combinator in use. +\Cref{lst:mtask_repeat_example} shows an example of a task that uses the \cleaninline{rpeat} combinator. This resulting task mirrors the value read from analogue \gls{GPIO} pin \cleaninline{A1} to pin \cleaninline{A2} by constantly reading the pin and writing the result. \begin{lstClean}[label={lst:mtask_repeat_example},caption={Repeat task combinator example in \gls{MTASK}.}] task :: MTask v Int | mtask v -task = - declarePin A1 PMInput \a1-> - declarePin A2 PMOutput \a2-> - {main = rpeat (readA a1 >>~. writeA a2 >>|. delay (lit 1000))} +task = declarePin A1 PMInput \a1-> + declarePin A2 PMOutput \a2-> + {main = rpeat (readA a1 >>~. writeA a2 >>|. delay (lit 1000))} \end{lstClean} \subsection{\texorpdfstring{\Glsxtrlongpl{SDS}}{Shared data sources}} -Tasks not always communicate using their observable task values. +For some collaborations it is cumbersome to only communicate data using task values. \Glspl{SDS} are a safe abstraction over any data that fill this gap. -It allows tasks to safely and atomically read, write and update data stores in order to share this data with other tasks in the system. +It allows tasks to safely and atomically read, write and update data stores in order to share data with other tasks. \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}). -There are no combinators or user-defined \gls{SDS} types in \gls{MTASK}. -Similar to peripherals and functions, \glspl{SDS} are constructed at the top level with the \cleaninline{sds} function. +There are no combinators or user-defined \gls{SDS} types in \gls{MTASK} as there are in \gls{ITASK}. +Similar to peripherals and functions, \glspl{SDS} are defined at the top level with the \cleaninline{sds} function. They are accessed through interaction tasks. The \cleaninline{getSds} task yields the current value of the \gls{SDS} as an unstable value. This behaviour is similar to the \cleaninline{watch} task in \gls{ITASK}. Writing a new value to \pgls{SDS} is done using \cleaninline{setSds}. This task yields the written value as a stable result after it is done writing. -Getting and immediately after setting \pgls{SDS} is not necessarily an \emph{atomic} operation in \gls{MTASK} because it is possible that another task accesses the \gls{SDS} in between. -To circumvent this issue, \cleaninline{updSds} is available by which \pgls{SDS} can be atomacally updated. +Getting and immediately setting \pgls{SDS} is not necessarily an \emph{atomic} operation in \gls{MTASK} because it is possible that another task accesses the \gls{SDS} in between. +To circumvent this issue, \cleaninline{updSds} is available by which \pgls{SDS} can be atomically updated. The \cleaninline{updSds} task only guarantees atomicity within \gls{MTASK}. \begin{lstClean}[label={lst:mtask_sds},caption={\Glspl{SDS} in \gls{MTASK}.}] @@ -639,8 +606,9 @@ class sds v where \Cref{lst:mtask_sds_examples} shows an example task that uses \glspl{SDS}. 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}. -In the \cleaninline{main} expression, this function is called twice and the results are combined using the parallel or combinator (\cleaninline{.\|\|.}). -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} +In the \cleaninline{main} expression, this function is called twice with a different argument. +The results are combined using the parallel disjunction combinator (\cleaninline{.\|\|.}). +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. \begin{lstClean}[label={lst:mtask_sds_examples},caption={Examples with \glspl{SDS} in \gls{MTASK}.}] task :: MTask v Int | mtask v @@ -655,13 +623,72 @@ task = declarePin D3 PMInput \d3-> In {main=count d3 .||. count d5} \end{lstClean} +\section{Interpretations} +This section describes all the interpretations that the \gls{MTASK} language has. +Not all of these interpretations are necessarily \gls{TOP} engines, i.e.\ not all the interpretations execute the resulting tasks. +Some may perform an analysis over the program or typeset the program. + +\subsection{Pretty printer} +The pretty printer interpretation converts an \gls{MTASK} term to a string representation. +As the host language \gls{CLEAN} constructs the \gls{MTASK} expressions at run time, it can be useful to show the constructed expression at run time as well. +The only function exposed for this interpretation is the \cleaninline{showMain} function (\cref{lst:showmain}). +It runs the pretty printer and returns a list of strings containing the pretty printed result. +The pretty printing function does the best it can but obviously cannot reproduce layout, curried functions, and variable names. +This shortcoming is illustrated by printing a blink task that contains a function and currying in \cref{lst:showexample}. + +\begin{lstClean}[caption={The entrypoint for the pretty printing interpretation.},label={lst:showmain}] +:: Show a // from the mTask pretty printing library +showMain :: (Main (Show a)) -> [String] +\end{lstClean} + +\begin{lstClean}[caption={Pretty printing interpretation example.},label={lst:showexample}] +blinkTask :: Main (MTask v Bool) | mtask v +blinkTask = + fun \blink=(\state-> + writeD d13 state >>|. delay (lit 500) >>=. blink o Not + ) In {main = blink true} + +// output when printing: +// fun f0 a1 = writeD(D13, a1) >>= \a2.(delay 1000) +// >>| (f0 (Not a1)) in (f0 True) +\end{lstClean} + +\subsection{Simulator} +The simulator converts the expression to a ready-for-work \gls{ITASK} simulation. +There is one entrypoint for this interpretation (see \cref{lst:simulatemain}). +The task resulting from the \cleaninline{simulate} function presents the user with an interactive simulation environment (see \cref{fig:sim}). +The simulation allows the user to (partially) execute tasks, control the simulated peripherals, inspect the internal state of the tasks, and interact with \glspl{SDS}. + +\begin{lstClean}[caption={The entrypoint for the simulation interpretation.},label={lst:simulatemain}] +:: TraceTask a // from the mTask simulator library +simulate :: (Main (TraceTask a)) -> [String] +\end{lstClean} + +\begin{figure} + \centering + \includegraphics[width=\linewidth]{simg} + \caption{Simulator interface for a blink program written in \gls{MTASK}.}\label{fig:sim} +\end{figure} + +\subsection{Byte code compiler} +The main interpretation of the \gls{MTASK} system is the byte code compiler (\cleaninline{:: BCInterpret}). +With it, and a handful of integration functions, \gls{MTASK} tasks can be executed on microcontrollers and integrated in \gls{ITASK} as if they were regular \gls{ITASK} tasks. +Furthermore, with a special language construct, \glspl{SDS} can be shared between \gls{MTASK} and \gls{ITASK} programs as well. +The integration with \gls{ITASK} is explained thoroughly later in \cref{chp:integration_with_itask}. + +The \gls{MTASK} language together with \gls{ITASK} is a heterogeneous \gls{DSL}. +I.e.\ some components---for example the \gls{RTS} on the microcontroller that executes the tasks---is largely unaware of the other components in the system, and it is executed on a completely different architecture. +The \gls{MTASK} language is based on a simply-typed $\lambda$-calculus with support for some basic types, arithmetic operations, and function definitions. +As the language is a \gls{TOP} language, it is also enriched with a task language (see \cref{sec:top}). + \section{Conclusion} The \gls{MTASK} language is a rich \gls{TOP} language tailored for \gls{IOT} edge devices. -It is embedded in the pure functional language \gls{CLEAN} and uses an enriched lambda calculus as a host language. -It provides support for all common arithmetic expressions, conditionals, functions, but also several basic tasks, task combinators, peripheral support and integration with \gls{ITASK}. -By embedding domain-specific knowledge in the language itself, it achieves the same abstraction level and dynamicity as other \gls{TOP} languages while targetting tiny computers instead. -As a result, a single declarative specification can describe an entire \gls{IOT} system. -\todo[inline]{Uitbreiden?} +The language is implemented as a class-based shallowly \gls{EDSL} in the pure functional host language \gls{CLEAN}. +The language is an enriched lambda calculus as a host language. +It provides language constructs for arithmetic expressions, conditionals, functions, but also non-interactive basic tasks, task combinators, peripheral support, and integration with \gls{ITASK}. +Terms in the language are just interfaces and can be interpreted by one or more interpretations. +The most important interpretation of the language is the byte code compiler. +\todo{Uit\-brei\-den?} \input{subfilepostamble} \end{document}