From: Mart Lubbers Date: Sun, 4 Jun 2023 18:25:53 +0000 (+0200) Subject: comments ms X-Git-Url: https://git.martlubbers.net/?a=commitdiff_plain;h=5c7ffbabc8f4fe9d21b4ab0095155ee87e32ed6e;p=phd-thesis.git comments ms --- diff --git a/bib/other.bib b/bib/other.bib index bedbf9d..2b7145c 100644 --- a/bib/other.bib +++ b/bib/other.bib @@ -2209,3 +2209,44 @@ Publisher: {ACM}}, author = {Bender, Emily}, year = {2019}, } + +@inproceedings{radanne_eliom_2016, + location = {Cham}, + title = {Eliom: A Core {ML} Language for Tierless Web Programming}, + isbn = {978-3-319-47958-3}, + abstract = {Eliom is a dialect of {OCaml} for Web programming in which server and client pieces of code can be mixed in the same file using syntactic annotations. This allows to build a whole application as a single distributed program, in which it is possible to define in a composable way reusable widgets with both server and client behaviors. Our language also enables simple and type-safe communication. Eliom matches the specificities of the Web by allowing the programmer to interleave client and server code while maintaining efficient one-way server-to-client communication. The Eliom language is both sufficiently small to be implemented on top of an existing language and sufficiently powerful to allow expressing many idioms of Web programming.}, + pages = {377--397}, + booktitle = {Programming Languages and Systems}, + publisher = {Springer International Publishing}, + author = {Radanne, Gabriel and Vouillon, Jérôme and Balat, Vincent}, + editor = {Igarashi, Atsushi}, + date = {2016}, +} + +@thesis{decker_tierless_2015, + location = {United States}, + title = {Tierless Programming for the Internet of Things}, + url = {https://www.osti.gov/biblio/1169934}, + abstract = {The Internet of Things ({IoT}) is about Internet-addressability and connectivity for everyday devices. The goal of this project was to create a framework to allow developers to more easily control {IoT} devices and turn their interactions into meaningful applications. We leveraged a tierless approach for Software Defined Networking ({SDN}) to build this framework. We expanded Flowlog, a tierless programming language for {SDN} controllers, to support {IoT} devices developed by Spark {IO} to build this framework.}, + pagetotal = {18}, + institution = {Brown University}, + type = {Master's Thesis}, + author = {Decker, Brett}, + date = {2015-02-01}, + doi = {10.2172/1169934}, + keywords = {97 {MATHEMATICS} {AND} {COMPUTING}}, + file = {Decker - 2015 - Tierless Programming for the Internet of Things.pdf:/home/mrl/.local/share/zotero/storage/CZ9DV6SW/Decker - 2015 - Tierless Programming for the Internet of Things.pdf:application/pdf}, +} + +@inproceedings{nelson_tierless_2014, + location = {Seattle, {WA}}, + title = {Tierless Programming and Reasoning for Software-Defined Networks}, + isbn = {978-1-931971-09-6}, + url = {https://www.usenix.org/conference/nsdi14/technical-sessions/presentation/nelson}, + pages = {519--531}, + booktitle = {11th {USENIX} Symposium on Networked Systems Design and Implementation ({NSDI} 14)}, + publisher = {{USENIX} Association}, + author = {Nelson, Tim and Ferguson, Andrew D. and Scheer, Michael J. G. and Krishnamurthi, Shriram}, + date = {2014-04}, + file = {Nelson et al. - 2014 - Tierless Programming and Reasoning for Software-De.pdf:/home/mrl/.local/share/zotero/storage/3AXEWJ4I/Nelson et al. - 2014 - Tierless Programming and Reasoning for Software-De.pdf:application/pdf}, +} diff --git a/dsl/class.tex b/dsl/class.tex index 88b58bc..7bab63d 100644 --- a/dsl/class.tex +++ b/dsl/class.tex @@ -56,10 +56,10 @@ While this chapter is written as a literate with Class'': TFP 2022.\ Zenodo.\ \url{https://doi.org/10.5281/zenodo.6650880}.} \section{Deep embedding} -Pick the language of literal integers and addition \citep{bender_benderrule_2019}\todo{nodig? grappig?}. +Let us consider the language of literal integers and addition.% \citep{bender_benderrule_2019}. %Pick a \gls{DSL}, any \gls{DSL}, pick the language of literal integers and addition. In deep embedding, terms in the language are represented by data in the host language. -Hence, defining the constructs is as simple as creating the following algebraic data type\footnote{All data types and functions are subscripted to indicate the evolution. When definitions are omitted for version $n$, version $n-1$ is assumed.}. +Hence, defining the constructs is as simple as creating the following algebraic data type\footnote{All data types and functions are subscripted to indicate the evolution. When definitions are omitted for version $n$, version $n\shortminus{}1$ is assumed.}. \begin{lstHaskellLhstex} data Expr_0 @@ -76,8 +76,7 @@ eval_0 (Lit_0 e) = e eval_0 (Add_0 e1 e2) = eval_0 e1 + eval_0 e2 \end{lstHaskellLhstex} -Adding semantics---e.g.\ a printer---just means adding another function while the existing functions remain untouched. -I.e.\ the key property of deep embedding. +Adding semantics---e.g.\ a printer---just means adding another function while the existing functions remain untouched, i.e.\ the key property of deep embedding. The following function, transforming the \haskelllhstexinline{Expr_0} data type to a string, defines a simple printer for our language. \begin{lstHaskellLhstex} @@ -621,7 +620,7 @@ instance Eval_g v => GDict (EvalDict_g v) where gdict = EvalDict_g eval_g \end{lstHaskellLhstex} -Finally, the implementations for the instances can be ported without complication show using the optimisation instance of \haskelllhstexinline{Not_g}: +Finally, the implementations for the instances can be ported without complication using the optimisation instance of \haskelllhstexinline{Not_g}: \begin{lstHaskellLhstex} instance (Typeable d, GDict (d (Not_g d)), HasOpt_g d) => Opt_g (Not_g d) where @@ -661,7 +660,7 @@ Furthermore, pattern matching on extensions becomes a bit more complicated but i Tagless-final embedding is the shallowly embedded counterpart of classy deep embedding and was invented for the same purpose; overcoming the issues with standard shallow embedding \citep{carette_finally_2009}. Classy deep embedding was organically grown from observing the evolution of tagless-final embedding. -The main difference between tagless-final embedding and classy deep embedding---and in general between shallow and deep embedding---is that intensional analyses of the abstract syntax tree is more difficult because there is no tangible abstract syntax tree data structure. +The main difference between tagless-final embedding and classy deep embedding---and in general between shallow and deep embedding---is that intensional analyses of the abstract syntax tree are more difficult because there is no tangible abstract syntax tree data structure. In classy deep embedding, it is possible to define transformations even across extensions. Furthermore, in classy deep embedding, defining (mutual) dependent interpretations is automatically supported whereas in tagless-final embedding this requires some amount of code duplication \citep{sun_compositional_2022}. @@ -680,7 +679,7 @@ The \emph{poly.} style of embedding---including tagless-final---falls short of t Intensional analysis is an umbrella term for pattern matching and transformations. In shallow embedding, intensional analysis is more complex and requires stateful views describing context, but it is possible to implement though. -Simple type system describes the whether it is possible to encode this embedding technique without many type system extensions. +Simple type system describes whether it is possible to encode this embedding technique without many type system extensions. In classy deep embedding, there is either a bit more scaffolding and boilerplate required or advanced type system extensions need to be used. Minimal boilerplate denotes the amount of scaffolding and boilerplate required. @@ -730,7 +729,7 @@ For example, hybrid embedding requires a transcoding step between the deep synta Classy deep embedding is a novel organically grown embedding technique that alleviates deep embedding from the extensibility problem in most cases. By abstracting the semantics functions to type classes they become overloaded in the language constructs. -Thus, making it possible to add new language constructs in a separate type. +This upgrade makes it possible to add new language constructs in a separate type. These extensions are brought together in a special extension constructor residing in the main data type. This extension case is overloaded by the language construct using a data type containing the class dictionary. As a result, orthogonal extension is possible for language constructs and semantics using only little syntactic overhead or type annotations. diff --git a/dsl/first.tex b/dsl/first.tex index 313b14f..2bc712d 100644 --- a/dsl/first.tex +++ b/dsl/first.tex @@ -57,7 +57,8 @@ It does so by providing an implementation in \gls{TH} for a typical \gls{DSL} wi Furthermore, we show that by utilising quasiquotation, there is hardly any burden on the syntax. Finally, the chapter also serves as a gentle introduction to \gls{TH} and reflects on the process of using \gls{TH}. -\section{Tagless-final embedding} +\section{Tagless-final embedding}% +\label{sec:tagless-final} Tagless-final embedding is an upgrade to standard shallow embedding achieved by lifting all language construct functions to type classes. As a result, views on the \gls{DSL} are data types implementing these classes. @@ -789,7 +790,7 @@ The scaffolding---e.g.\ generating the pairs, sums and injections---for embeddin The key difference to our approach is that we specialise the implementation for each of the interpretations instead of providing a general implementation of data type handling operations. Furthermore, our implementation does not require a generic function to trace all constructors, resulting in problems with (mutual) recursion. -\Citet{young_adding_2021} added pattern matching to a deeply \gls{EDSL} using a compiler plugin. +\Citet{young_adding_2021} added pattern matching to a deeply embedded \gls{DSL} using a compiler plugin. This plugin implements an \haskellinline{externalise :: a -> E a} function that allows lifting all machinery required for pattern matching automatically from the host language to the \gls{DSL}. Under the hood, this function translates the pattern match to constructors, deconstructors, and constructor predicates. The main difference with this work is that it requires a compiler plugin while our metaprogramming approach works on any compiler supporting a metaprogramming system similar to \gls{TH}. @@ -807,7 +808,7 @@ They all differ slightly in functionality from our domain and can be divided int Using \gls{TH} or other metaprogramming systems it is possible to add extra code to your program. The original \gls{TH} paper showed that it is possible to create variadic functions such as \haskellinline{printf} using \gls{TH} that would be almost impossible to define without \citep{sheard_template_2002}. \Citet{hammond_automatic_2003} used \gls{TH} to generate parallel programming skeletons. -In practise, this means that the programmer selects a skeleton and, at compile time, the code is massaged to suit the pattern and information about the environment is inlined for optimisation. +In practice, this means that the programmer selects a skeleton and, at compile time, the code is massaged to suit the pattern and information about the environment is inlined for optimisation. \Citet{polak_automatic_2006} implemented automatic GUI generation using \gls{TH}. \Citet{duregard_embedded_2011} wrote a parser generator using \gls{TH} and the custom quasiquoting facilities. @@ -850,7 +851,7 @@ The original \gls{TH} quasiquotation paper \citep{mainland_why_2007} shows how t Also, \citet{kariotis_making_2008} used \gls{TH} to automatically construct monad stacks without having to resort to the monad transformers library which requires advanced type system extensions. \Citet{najd_everything_2016} uses the compile time to be able to do normalisation for a \gls{DSL}, dubbing it \glspl{QDSL}. -They utilise the quasiquation facilities of \gls{TH} to convert \gls{HASKELL} \gls{DSL} code to constructs in the \gls{DSL}, applying optimisations such as eliminating lambda abstractions and function applications along the way. +They utilise the quasiquotation facilities of \gls{TH} to convert \gls{HASKELL} \gls{DSL} code to constructs in the \gls{DSL}, applying optimisations such as eliminating lambda abstractions and function applications along the way. \Citet{egi_embedding_2022} extended \gls{HASKELL} to support non-free data type pattern matching---i.e.\ data type with no standard form, e.g.\ sets, graphs---using \gls{TH}. Using quasiquotation, they make a complicated embedding of non-linear pattern matching available through a simple lens. diff --git a/intro/intro.tex b/intro/intro.tex index c0a43b7..edf9850 100644 --- a/intro/intro.tex +++ b/intro/intro.tex @@ -39,7 +39,7 @@ In a traditional setting, an \gls{IOT} engineer has to program each device and t This results in semantic friction, which makes programming and maintaining \gls{IOT} systems a complex and error-prone process. This dissertation describes the research carried out around orchestrating these complex \gls{IOT} systems using \gls{TOP}. -\Gls{TOP} is an innovative tierless programming paradigm for interactive multi-layered systems\todo{tierless introductie mist een beetje}. +\Gls{TOP} is an innovative tierless programming paradigm for interactive multi-layered systems. By utilising advanced compiler technologies, much of the internals, communication, and interoperation between the tiers or layers of the applications are automatically generated. The compiler generates an application controlling all interconnected components from a single declarative specification of the required work. For example, the \gls{TOP} system \gls{ITASK} is used to program all layers of multi-user distributed web applications from a single source specification. @@ -50,7 +50,7 @@ This is where an additional \glspl{DSL} must play its part. \Glspl{DSL} are programming languages tailored to a specific domain. Consequently, jargon is not expressed in terms of the language itself, but is built into the language. Furthermore, the \gls{DSL} can eschew language or system features that are irrelevant for the domain. -Using \glspl{DSL}, hardware requirements can be drastically lowered, even while maintaining a high abstraction level for the specified domain. +Using \glspl{DSL}, hardware requirements can be drastically lowered, even while maintaining a high abstraction level for the specified domain.\todo{why?} To incorporate the plethora of edge devices in the orchestra of a \gls{TOP} system, the \gls{MTASK} system is used. The \gls{MTASK} language is a novel programming language for programming \gls{IOT} edge devices using \gls{TOP}. @@ -71,7 +71,7 @@ The chapters can be read independently of each other. Hence, the chapters in this episode are best read in order. It introduces \gls{IOT} edge device programming, shows the complete \gls{MTASK} language, provides details on how \gls{MTASK} is integrated with \gls{ITASK}, shows how the byte code compiler is implemented, presents a guide for green computing with \gls{MTASK}, and ends with a conclusion and overview of future and related work. \Cref{prt:tvt} consists of a single chapter that is based on a journal article. -The chapter provides a qualitative and quantitative comparison of traditional tiered \gls{IOT} programming and tierless programming using a real-world application. +The chapter provides a qualitative and quantitative comparison of traditional tiered \gls{IOT} programming and tierless programming using a real-world application. The chapter is readable independently. The following sections in this prelude provide background material on the \gls{IOT}, \glspl{DSL}, and \gls{TOP} after which a detailed overview of the contributions is presented. @@ -274,7 +274,6 @@ As an example, \cref{lst:todo,fig:todo} show the code and \gls{UI} for an intera The user modifies a shared to-do list through an editor directly or using some predefined actions. Furthermore, in parallel, the length of the list is shown to demonstrate \glspl{SDS}. Using \gls{ITASK}, complex collaborations of users and tasks are described on a high level. -In this way, the \gls{ITASK} system is a tierless system taking care of both the presentation and application layer (see \cref{fig:iot-layers}). \cleaninputlisting[float=p,firstline=6,lastline=22,tabsize=3,numbers=left,caption={The code for a shared to-do list in \gls{ITASK}.},label={lst:todo}]{lst/sharedlist.icl} @@ -295,7 +294,7 @@ Special combinators (e.g.\ \cleaninline{@>>} at \cref{lst:todo_ui}) are used to \subsection{The mTask system} The work for \gls{IOT} edge devices can often be succinctly described by \gls{TOP} programs. -Software on microcontrollers is usually composed of smaller basic tasks, are interactive, and shares data with other components or the server. +Software on microcontrollers is usually composed of smaller basic tasks, is interactive, and shares data with other components or the server. The \gls{ITASK} system seems an obvious candidate for bringing \gls{TOP} to \gls{IOT} edge devices. However, an \gls{ITASK} application contains many features that are not needed on \emph{edge devices} such as higher-order tasks, support for a distributed architecture, a multi-user web server, and facilities to generate \glspl{GUI} for any user-defined type. Furthermore, \gls{IOT} edge devices are in general not powerful enough to run or interpret \gls{CLEAN}\slash\gls{ABC} code, they just lack the processor speed and memory. @@ -367,6 +366,19 @@ Such a formal specification allows for symbolic execution, hint generation, but %The engine is the software or hardware that executes these specifications as a ready-for-work application. %Defining comparable semantics for the \gls{MTASK} language is in progress \citep{antonova_mtask_2022}. +\subsection{Tierless programming} +Both \gls{ITASK} and \imtask{} are so called tierless systems. +Tierless programming is an entirely different development paradigm compared to traditional, tiered, programming. +In tiered programming, every component\slash{}tier is separately developed, possibly in different programming languages and programming paradigms, and integrated in the system as a whole. +On the one hand, it is an advantage to be able to choose the most suitable programming language for the specific tier. +But on the other, it increases the amount of integration work that needs to be done and it may increase the semantic friction between the tiers. +In contrast, tierless programming languages synthesise all tiers of a software stack from a single high-level specification. +Hence, reducing the semantic friction, increasing the maintainability costs, and reducing the possibility for runtime errors. +The term tierless programming originated from the web programming system Links \citep{cooper2006links}. +In Links, code for each tier simultaneously checked by the compiler, and compiled to HTML and JavaScript for the web client and to SQL on the server to interact with the database system. +The \gls{ITASK} system is a tierless system taking care of both the presentation and application layer (see \cref{fig:iot-layers}). +When \gls{ITASK} is used in conjunction with \gls{MTASK}, all layers of an \gls{IOT} system can be programmed from a single source and hence they are a tierless \gls{IOT} system. + \section{Contributions}% \label{sec:contributions} This section provides a thorough overview of the relation between the scientific publications and the contents of this thesis. @@ -383,7 +395,7 @@ This paper-based episode is based on the following papers: \item \emph{First-\kern-1ptClass Data Types in Shallow Embedded Domain-Specific Languages} \citep*{lubbers_first-class_2022}\label{enum:first-class} is the basis for \cref{chp:first-class_datatypes}. It shows how to inherit data types from the host language in \glspl{EDSL} using metaprogramming by providing a proof-of-concept implementation using \gls{HASKELL}'s metaprogramming system: \glsxtrlong{TH}. The chapter also serves as a gentle introduction to, and contains a thorough literature study on \glsxtrlong{TH}. - The paper was published at the \ifl{} 2022 in Kopenhagen, Denmark. + The paper was published at the \ifl{} 2022 in Copenhagen, Denmark. \end{enumerate} \paragraph{Contribution:} diff --git a/preamble/bibliography.tex b/preamble/bibliography.tex index e1f3f7f..0a87344 100644 --- a/preamble/bibliography.tex +++ b/preamble/bibliography.tex @@ -22,7 +22,7 @@ \addbibresource[glob]{bib/*.bib} \usepackage{ragged2e} -\renewcommand{\bibfont}{\footnotesize}%\RaggedRight} +\renewcommand{\bibfont}{\scriptsize}%\RaggedRight} \setlength\bibitemsep{0pt} \newcommand{\refurl}[2]{\url{#1}, accessed on: #2} diff --git a/thesis.tex b/thesis.tex index 3a12242..814365b 100644 --- a/thesis.tex +++ b/thesis.tex @@ -40,7 +40,7 @@ %Colophon \hypertarget{colophon}{} -\bookmark[level=section,dest=colophon]{Titlepage} +\bookmark[level=section,dest=colophon]{Colophon} \subfile{front/colophon} %Titlepage diff --git a/todo.txt b/todo.txt index 69d0430..72ea6db 100644 --- a/todo.txt +++ b/todo.txt @@ -1 +1,8 @@ Introduction stuk over tierless? +Why shallow and not deep? +Why is a DSL better for hardware constraints? +Mary is interested in (7.4.2) generating C code +Any measurement regarding time drift accuracy? timing in general? +mTask direct comm between devices? + +mTask more brittle than iTask? eval diff --git a/top/4iot.tex b/top/4iot.tex index 3baf7cb..845dae7 100644 --- a/top/4iot.tex +++ b/top/4iot.tex @@ -65,7 +65,7 @@ Such web applications often form the core of the topmost two layers of \gls{IOT} Furthermore, \gls{IOT} edge devices are typically programmed with similar workflow-like programs for which \gls{TOP} is very suitable. Directly incorporating the perception layer, and thus edge devices, in \gls{ITASK} however is not straightforward. All \gls{ITASK} applications carry the weight of multi-user \gls{TOP} programs that can generically generate webpages, communication, and storage for all data types in the program. -As a result, the \gls{ITASK} system targeting relatively fast and hence energy-hungry systems with large amounts of \gls{RAM} and a speedy connection. +As a result, the \gls{ITASK} system targets relatively fast and hence energy-hungry systems with large amounts of \gls{RAM} and a speedy connection. Edge devices in \gls{IOT} systems are typically slow but energy efficient and do not have the memory to run the naturally heap-heavy feature-packed functional programs that \gls{ITASK} programs are. The \gls{MTASK} system bridges this gap by providing a domain-specific \gls{TOP} language for \gls{IOT} edge devices. Domain-specific knowledge is embedded in the language and execution platform and unnecessary features for edge devices are removed to drastically lower the hardware requirements. @@ -224,8 +224,8 @@ Microcontrollers have significantly different characteristics to regular compute Programming them happens through compiled firmwares using low-level imperative programming languages. Due to the lack of an \gls{OS}, writing applications that perform multiple tasks at the same time is error-prone, becomes complex, and requires a lot of boilerplate such as manual scheduling code. With the \gls{MTASK} system, a \gls{TOP} programming language for \gls{IOT} edge devices, this limitation can be overcome. -Since a lot domain-specific knowledge is built into the language and \gls{RTS}, the hardware requirements can be kept relatively low while maintaining a high abstraction level. -Tasks in \gls{MTASK} are high-level specifications of the work that needs to be done, they can be combined using task combinators, and share data using \glspl{SDS}. +Since a lot of domain-specific knowledge is built into the language and \gls{RTS}, the hardware requirements can be kept relatively low while maintaining a high abstraction level. +Tasks in \gls{MTASK} are high-level specifications of the work that needs to be done, they can be combined using task combinators, and share data using \glspl{SDS} with each other and with the server. Furthermore, the programs are automatically integrated with \gls{ITASK}, a \gls{TOP} system for creating interactive distributed web applications, allowing for data sharing, task coordination, and dynamic construction of tasks over all layers of an \gls{IOT} system. The following chapters of this monograph thoroughly introduce all aspects of the \gls{MTASK} system. diff --git a/top/finale.tex b/top/finale.tex index b50d05b..bfd6917 100644 --- a/top/finale.tex +++ b/top/finale.tex @@ -32,8 +32,9 @@ It is a full-fledged \gls{TOP} language hosted in a tiny \gls{FP} language. Besides the usual \gls{FP} constructs, it contains basic tasks, task combinators, support for sensors and actuators, and interrupts. It integrates seamlessly into \gls{ITASK}, a \gls{TOP} system for interactive web applications. In \gls{ITASK}, abstractions are available for the gritty details of interactive web applications such as program distribution, web applications, data storage, and user management. -The \gls{MTASK} system abstracts away of all technicalities specific to edge devices such as communication, abstractions for sensors and actuators, interrupts and (multi) task scheduling. -When \gls{MTASK} is used together with \gls{MTASK}, all layers of the \gls{IOT} application are programmed from a single declarative specification. +The \gls{MTASK} system abstracts away all technicalities specific to edge devices such as communication, abstractions for sensors and actuators, interrupts and (multi) task scheduling. +When \gls{MTASK} is used together with \gls{ITASK}, all layers of the \gls{IOT} application are programmed from a single declarative specification.\todo{is this demonstrated anywhere in the thesis? +Could you point to an example (perhaps in a paper not in the thesis)} Any device equipped with the \gls{MTASK} \gls{RTS} can be used in the system and dynamically receive tasks for execution. This domain-specific \gls{OS} only is uploaded once, hence saving precious write cycles on the program memory. @@ -54,9 +55,10 @@ For example, for the popular ESP8266 chip there are ports of \gls{MICROPYTHON}, All of these languages, except the Lisp dialect uLisp (see \cref{sec:related_fp}), are imperative and do not support multitasking out of the box. They lay pretty hefty constraints on the memory and as a result do not work on smaller microcontrollers. Another interpretation solution for the tiniest devices is Firmata, a protocol for remotely controlling the microcontroller using a server as the interpreter host \citep{steiner_firmata:_2009}. -\citet{grebe_haskino:_2016} wrapped this in a remote monad for integration with \gls{HASKELL} that allowed imperative code to be interpreted on the microprocessors. +\citet{decker_tierless_2015} describes a FlowLog \citep{nelson_tierless_2014} extension to incorporate \gls{IOT} devices into their tierless sytem for software-defined network controllers in a similar way as firmata. +\citet{grebe_haskino:_2016} wrapped Firmata in a remote monad for integration with \gls{HASKELL} that allowed imperative code to be interpreted on the microprocessors. Later this system was extended to support multithreading as well, stepping away from Firmata as the basis and using their own \gls{RTS} \citep{grebe_threading_2019}. -It differs from our approach because it is required to mark continuation points by hand and there is no automatic safe data communication. +Both differ from our approach because it is required to mark continuation points by hand and there is no automatic safe data communication. \Citet{baccelli_reprogramming_2018} provide a single language \gls{IOT} system based on the RIOT \gls{OS} that allows runtime deployment of code snippets called containers. Both client and server are written in JavaScript. @@ -66,7 +68,7 @@ Mat\`e is an example of a tierless framework for sensor networks where devices r \subsection{DSLs}\label{sec:related_dsl} Many \glspl{DSL} provide higher-level programming abstractions for microcontrollers, for example providing strong typing or memory safety. Examples of this are Copilot \citep{hess_arduino-copilot_2020} and Ivory \citep{elliott_guilt_2015}. -Both imperative \glspl{DSL} embedded in a functional language that compile to \ccpp{}. +Both are imperative \glspl{DSL} embedded in a functional language that compiles to \ccpp{}. \subsection{Functional programming}\label{sec:related_fp} \Citet{haenisch_case_2016} showed that there are major benefits to using functional languages on edge devices. @@ -146,7 +148,7 @@ Tasks in \gls{TOP} are also event driven and can be combined with combinators. \Gls{TOP} allows for more complex collaboration patterns than \gls{FRP} \citep{wang_maintaining_2018}. Consequently, \gls{TOP} is unable to provide strong guarantees on memory usage, something \gls{FRP} is capable of. For example, arrowised \gls{FRP} can give guarantees on upper memory bounds \citep{nilsson_functional_2002}. -The way \gls{FRP}, and for that matter \gls{TOP}, systems are programmed stays close to the design when the domain matches suits the paradigm. +The way \gls{FRP}, and for that matter \gls{TOP}, systems are programmed stays close to the design when the domain matches the paradigm. The \gls{IOT} domain seems to suit this style of programming very well in just the device layer but also for entire \gls{IOT} systems. For example, Potato is an \gls{FRP} language for building entire \gls{IOT} systems using powerful devices such as the Raspberry Pi leveraging the Erlang \gls{VM} \citep{troyer_building_2018}. @@ -214,7 +216,7 @@ Promising research has gone into translating purely functional code to \gls{FPGA It would be interesting to see how and whether (parts of) \gls{TOP} programs or the functionality of the \gls{MTASK} \gls{OS} could be translated to \gls{FPGA} specifications. \subsection{Formal semantics} -Semantics allow reasoning about the language and programs in order do (symbolic) simulation, termination checking, task equivalence, or otherwise. +Semantics allow reasoning about the language and programs in order to do (symbolic) simulation, termination checking, task equivalence, or otherwise. For \gls{ITASK} there have been two attempts to formally specify the language. First \citet{koopman_executable_2011} defined a semantics used for property based testing based on a minimal version of \gls{ITASK}. Then \citet{plasmeijer_task-oriented_2012} formalised \gls{ITASK} by providing an executable semantics for the language. @@ -229,8 +231,7 @@ From these simple combinators, complex collaboration patterns can be expressed. The \gls{ITASK} language is designed exactly the opposite. From just a few super combinators, all other combinators are derived. However, this approach requires a very powerful host language in which task combinators can be defined in terms of the host language. -It could be fruitful to investigate which workflows cannot be specified with the limited set of combinators available in \gls{MTASK}. -Furthermore, it is unclear whether all derived combinators from \gls{ITASK} can be expressed in terms of \gls{MTASK} combinators. +It would be fruitful to investigate which workflows cannot be specified with the limited set of combinators available in \gls{MTASK}. \Citet{van_der_aalst_workflow_2003} defines a benchmark set of workflow patterns. It is interesting to see which patterns can already be implemented with just \gls{MTASK}, which require a round-trip with the server, and what additional combinators would be needed. @@ -252,7 +253,7 @@ Recent approaches in interactive editors for programming language source code su If the editor produces correct \gls{MTASK} code by construction, much of the problems could be avoided. In the same respect, as \gls{MTASK} is a tagless-final \gls{EDSL} and uses \gls{HOAS}, the error messages are complex and larded with host language features. Much research has gone into simplifying these error messages by translating them to the \gls{DSL} domain, see for example the work by \citep{serrano_type_2018}. -De Roos briefly investigated these methods in their research internship. +De Roos briefly investigated these methods in their research internship.\todo{cite? but how} A future directions could be to extend these findings and apply more \gls{EDSL} error message techniques on \gls{MTASK} as well. \subsection{Language features} @@ -268,7 +269,7 @@ However, it should be possible to make abstractions over an increasing number of For example, the pin mode could be made a type parameter of the \gls{GPIO} pins, or interrupt handling could be made safer by incorporating the capabilities of the devices in order to reduce run-time errors. \subsection{Scheduling} -The scheduling in \gls{MTASK} works quite well, but it is not real time. +The scheduling in \gls{MTASK} works quite well, but it is not real time.\todo{mention evaluation} There is a variant of \gls{FRP} called \gls{PFRP} that allows for real-time operation \citep{belwal_variable_2013}. Furthermore, an alternative to reducing the energy consumption by going to sleep is stepping down the processor frequency. So called \gls{DVFS} is a scheduling technique that slows down the processor in order to reach the goals as late as possible, reducing the power consumption. @@ -281,7 +282,7 @@ Many colleagues and students have worked on aspects of the \gls{MTASK} system in This section provides an exhaustive overview of the work on \gls{MTASK} and its predecessors. \subsection{Generating \ccpp{} code} -A first throw at a class-based shallowly \gls{EDSL} for microcontrollers was made by \citet{plasmeijer_shallow_2016}. +A first throw at a class-based shallow \gls{EDSL} for microcontrollers was made by \citet{plasmeijer_shallow_2016}. The language was called \gls{ARDSL} and offered a type safe interface to \gls{ARDUINO} \gls{CPP} dialect. A \gls{CPP} code generation interpretation was available together with an \gls{ITASK} simulation interpretation. There was no support for tasks nor functions. @@ -295,6 +296,7 @@ In this way, entire \gls{IOT} systems could be programmed from a single source. However, this version used a simplified version of \gls{MTASK} without functions. 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}. It was shown by \citet{amazonas_cabral_de_andrade_developing_2018} that it was possible to build real-life \gls{IOT} systems with this integration. +They did so by creating a functioning prototype of a smart home application. Moreover, a course on the \gls{MTASK} simulator was provided at the 2018 \gls{3COWS} winter school in Ko\v{s}ice, Slovakia \citep{koopman_simulation_2023}. \subsection{Transition to Task-oriented programming} @@ -311,7 +313,7 @@ Several students worked on extending \gls{MTASK} with many useful features: \citet{van_der_veen_mutable_2020} did preliminary work on a green computing analysis, built a simulator, and explored the possibilities for adding bounded datatypes; de Roos explored beautifying error messages; \citet{de_boer_secure_2020} investigated the possibilities for secure communication channels; \citeauthor{crooijmans_reducing_2021} \citeyearpar{crooijmans_reducing_2021,crooijmans_reducing_2022} added abstractions for low-power operation to \gls{MTASK} such as hardware interrupts and power efficient scheduling; and \citet{antonova_mtask_2022} defined a preliminary formal semantics for a subset of \gls{MTASK}. In 2023, the SusTrainable summer school in Coimbra, Portugal will host a course on \gls{MTASK}. -\subsection{Using mTask in practise} +\subsection{Using mTask in practice} Funded by the Radboud-Glasgow Collaboration Fund, collaborative work was executed with Phil Trinder, Jeremy Singer, and Adrian Ravi Kishore Ramsingh. An existing smart campus application was developed using \gls{MTASK} and quantitatively and qualitatively compared to the original application that was developed using a traditional \gls{IOT} stack \citep{lubbers_tiered_2020}. This research was later extended to include a four-way comparison: \gls{PYTHON}, \gls{MICROPYTHON}, \gls{ITASK}, and \gls{MTASK} \citep{lubbers_could_2023} (see \cref{chp:smart_campus}). diff --git a/top/green.tex b/top/green.tex index 8e8fe8c..7981def 100644 --- a/top/green.tex +++ b/top/green.tex @@ -23,7 +23,7 @@ Furthermore, many of these devices operate on batteries and higher energy consum It is therefore crucial to lower their energy consumption. To reduce the power consumption of an \gls{IOT} edge device, the specialised low-power sleep modes of the microprocessors can be leveraged. -Different sleep mode achieve different power reductions because of their run time characteristics. +Different sleep modes achieve different power reductions because of their run time characteristics. These specifics range from disabling or suspending the \gls{WIFI} radio; stop powering (parts) of the \gls{RAM}; disabling peripherals; or even turning off the processor completely, requiring an external signal to wake up again. Determining exactly when, and for how long it is safe to sleep is expensive in the general case. In practise, it means that either annotations in the source code, a \gls{RTOS}, or a scheduler is required. @@ -83,14 +83,15 @@ Each cycle, a single rewrite step is performed on all task trees. During rewriting, each step, tasks do a bit of their work and progress steadily, allowing interleaved and seemingly parallel operation. Atomic blocks, such as \gls{IO}, are always contained within a rewrite step. This is very convenient, since the system can inspect the current state of all \gls{MTASK} expressions after a rewrite and decide if sleeping and how long is possible. -After each loop, the \gls{RTS} knows which task is waiting on which triggers and is thus determines when it is possible and safe to sleep and choose the optimal sleep mode according to the sleeping time. +After each loop, the \gls{RTS} knows which task is waiting on which triggers. +With this information, the system determines when it is possible and safe to sleep, and chooses the optimal sleep mode according to the sleeping time. %As a consequence, we cannot have fair multitasking. %When a single rewrite step would take forever due to an infinite sequence of function calls, this would block the entire \gls{IOT} node. %Even infinite sequences rewrite steps are perfectly fine. %The \gls{MTASK} system does proper tail-call optimisations to facilitate this. \section{Rewrite interval} -Some \gls{MTASK} programs contain one or more explicit \cleaninline{delay} primitives, offering a natural place a pause. +Some \gls{MTASK} programs contain one or more explicit \cleaninline{delay} primitives, offering a natural pause. However, there are many \gls{MTASK} programs that just specify a repeated set of primitives. A typical example is the program that reads the temperature for a sensor and sets the system \gls{LED} if the reading is below some given \cleaninline{goal}. @@ -127,7 +128,7 @@ This has the advantage that the programmer does not have to deal with them expli \subsection{Basic tasks} We start by assigning default rewrite rates to basic tasks. These rewrite rates reflect the expected change rates of sensors and other inputs. -Basic tasks to set a value of a sensor or actuator have a rate of $\rewriterate{0}{0}$, this is never delayed. +Basic tasks to set a value of a sensor or actuator have a rate of $\rewriterate{0}{0}$, i.e.\ this is never delayed. An example of such a one-shot task in the task that writes to a \gls{GPIO} pin. Basic tasks that continuously read a sensor or otherwise interact with a peripheral have default rewrite rates that fit standard usage of the sensor. \Cref{tbl:rewrite} shows the default values for the basic tasks. @@ -165,6 +166,7 @@ Based on these default rewrite rates, the system automatically derives rewrite r \left\{\begin{array}{ll} \mathcal{R}(t) & \text{if $t$ is unstable}\\ \rewriterate{r_1-\mathit{start}}{r_2-\mathit{start}} & \text{otherwise}\\ + & \text{\bf where } \mathcal{R}(t) = \rewriterate{r_1}{r_2}\\ \end{array}\right.\\ \mathcal{R} (\mathit{waitUntil}~d) & = \rewriterate{e-\mathit{time}}{e-\mathit{time}}\label{R:delay}\\ \mathcal{R} (t) & = @@ -189,9 +191,9 @@ Evaluating a task earlier should not change its result but just consumes more en \begin{equ} \[ X \cap_{\textit{safe}} Y = \left\{% - \begin{array}{ll} + \begin{array}{lll} X\cap Y & X\cap Y \neq \emptyset\\ - Y & Y_2 < X_1\\ + Y & Y_2 < X_1 & \text{\bf where } Y = \rewriterate{Y_1}{Y_2} \text{ and } X = \rewriterate{X_1}{X_2}\\ X & \text{otherwise}\\ \end{array} \right. @@ -213,7 +215,7 @@ In case of the \cleaninline{rpeat} task, the default refresh rate is $\rewritera \subsubsection{Delay combinators} Upon installation, a \cleaninline{delay} task is stored as a \cleaninline{waitUntil} task, containing the time of installation added to the specified time to wait. -Execution wise, it waits until the current time exceeds the time is greater than the argument time. +Execution wise, it waits until the current time exceeds the time the argument time. \subsubsection{Other tasks} All other tasks are captured by \cref{R:other}. @@ -222,7 +224,8 @@ In all other cases, the values from \cref{tbl:rewrite} apply where $r_l$ and $r_ \subsection{Example} The rewrite intervals associated with various steps of the thermostat program from \cref{lst:thermostat} are given in \cref{tbl:intervals}. -The rewrite steps and intervals are circular, after step 2 we continue with step 0 again. +The rewrite steps and intervals are circular. +After step 2 we continue with step 0 again. Only the actual reading of the sensor with \cleaninline{temperature dht} offers the possibility for a non-zero delay. %%\begin{table}[tb] @@ -358,7 +361,7 @@ timedPulseNaive = declarePin D0 PMOutput \d0-> \section{Task scheduling in the mTask engine}\label{sec:scheduling} The rewrite rates from the previous section only tell us how much the next evaluation of the task can be delayed. -In the \gls{MTASK} system, an \gls{IOT} edge devices can run multiple tasks. +In the \gls{MTASK} system, an \gls{IOT} edge device can run multiple tasks. In addition, it has to communicate with a server to collect new tasks and updates of \glspl{SDS}. Hence, the rewrite intervals cannot be used directly to let the microcontroller sleep, so a scheduler is involved. Our scheduler has the following objectives. @@ -396,14 +399,14 @@ Nevertheless, we try to make time handling as reliable as possible. This is achieved by adding the start time of this round of task evaluations rather than the current time to compute absolute execution intervals. \subsection{Scheduling Tasks} -Apart from the task to execute, the device maintains the connection with the server and check there for new tasks and updates of \gls{SDS}. +Apart from the task to execute, the device maintains the connection with the server and checks there for new tasks and updates of \gls{SDS}. When the microcontroller is active, the connection is checked and updates from the server are processed. After that, the tasks that are within the execution window are executed. Next, the microcontroller goes to light sleep for the minimum of a predefined interval and the task delay. In general, the microcontroller executes multiple \gls{MTASK} tasks at the same time. -The \gls{MTASK} device repeatedly check for inputs from the server and executes all tasks that cannot be delayed to the next evaluation round one step. -The tasks are stored in a priority queue to check efficiently which of them need to be stepped. +The \gls{MTASK} device repeatedly checks for inputs from the server and executes all tasks that cannot be delayed to the next evaluation round one step. +The tasks are stored in a priority queue to check efficiently which of them need stepping. The \gls{MTASK} tasks are ordered at their latest start time in this queue; earliest deadline first. We use the earliest deadline to order tasks with equal latest deadline. @@ -411,12 +414,12 @@ It is very complicated to make an optimal scheduling algorithm for tasks to mini We use a simple heuristic to evaluate tasks and determine sleep time rather than wasting energy on a fancy evaluation algorithm. \Cref{lst:evalutionRound} gives this algorithm in pseudo code. First the edge device checks for new tasks and updates of \glspl{SDS}. -This communication adds the new task to the queue, if there where any. +This communication adds the new task to the queue, if there were any. The \cleaninline{stepped} set contains all tasks evaluated in this evaluation round. Next, we evaluate tasks from the queue until we encounter a task that has an evaluation interval that has not started. This may result in evaluating tasks earlier than required, but maximises the opportunities to sleep after this evaluation round. %Using the \prog{stepped} set ensures that we evaluate each task at most once during an evaluation round. -Executed tasks are temporarily stored in the \cleaninline{stepped} set instead of inserted directly into the queue to ensure that they are evaluated at most once in a evaluation round to ensure that there is frequent communication with the server. +Executed tasks are temporarily stored in the \cleaninline{stepped} set instead of inserted directly into the queue to ensure that they are evaluated at most once in an evaluation round to ensure that there is frequent communication with the server. A task that produces a stable value is completed and is not queued again. \begin{algorithm} @@ -445,19 +448,19 @@ A task that produces a stable value is completed and is not queued again. The \cleaninline{sleep} function determines the maximum sleep time based on the top of the queue. The computed sleep time and the characteristics of the microprocessor determine the length and depth of the sleep. -For very short sleep times it is not be worthwhile to put the processor in sleep mode. +For very short sleep times it is not worthwhile to put the processor in sleep mode. In the current \gls{MTASK} \gls{RTS}, the thresholds are determined by experimentation but can be tuned by the programmer. On systems that lose the content of their \gls{RAM} it is not possible to go to deep sleep mode. \section{Interrupts}\label{lst:interrupts} Most microcontrollers have built-in support for processor interrupts. -These interrupts are hard-wired signals that interrupts the normal flow of the program or sleep state in order to execute a small piece of code, the \gls{ISR}. +These interrupts are hard-wired signals that interrupt the normal flow of the program or sleep state in order to execute a small piece of code, the \gls{ISR}. While the \glspl{ISR} look like regular functions, they do come with some limitations. For example, they must be very short, in order not to miss future interrupts; can only do very limited \gls{IO}; cannot reliably check the clock; and they operate in their own stack, and thus communication must happen via global variables. After the execution of the \gls{ISR}, the normal program flow is resumed. Interrupts are heavily used internally in the firmware of microcontrollers to perform timing critical operations such as \gls{WIFI}, \gls{I2C}, or \gls{SPI} communication; completed \gls{ADC} conversions; software timers; exception handling; \etc. -Using interrupts in \gls{MTASK} task offer two substantial benefits: fewer missed events and better energy usage. +Using interrupts in an \gls{MTASK} task offer two substantial benefits: fewer missed events and better energy usage. Sometimes an external event such as a button press only occurs for a small duration, making it possible to miss it due to it happening right between two polls. Using interrupts is not a fool-proof way of never missing an event. Events could still be missed if they occur during the execution of an \gls{ISR} or while the microcontroller was in the process of waking up from a triggered interrupt. @@ -489,7 +492,7 @@ When the user presses the button connected to \gls{GPIO} pin 11, the state of th As buttons sometimes induce noise shortly after pressing, events within \qty{30}{\ms} after pressing are ignored. In between the button presses, the device goes into deep sleep using the \arduinoinline{LowPower} library to handle the processor specific sleep interface. -\Crefrange{lst:arduino_interrupt:defs_fro}{lst:arduino_interrupt:defs_to} defines the pin and debounce constants. +\Crefrange{lst:arduino_interrupt:defs_fro}{lst:arduino_interrupt:defs_to} define the pin and debounce constants. \Cref{lst:arduino_interrupt:state} defines the current state of the \gls{LED}, it is declared \arduinoinline{volatile} to exempt it from compiler optimisations because it is accessed in the interrupt handler. \Cref{lst:arduino_interrupt:cooldown} flags whether the program is in debounce state, i.e.\ events should be ignored for a short period of time. @@ -580,9 +583,9 @@ At the time of registration, the \gls{RTS} checks whether the interrupt is valid Moreover, an exception is thrown if multiple types of interrupts are registered on the same pin. \subsubsection{Triggering interrupts} -Once an interrupt fires, tasks registered to that interrupt are not immediately evaluated because it is usually not safe to do. +Once an interrupt fires, tasks registered to that interrupt are not immediately evaluated because it is usually not safe. For example, the interrupt could fire in the middle of a garbage collection process, resulting in corrupt memory. -Furthermore, to insure the \gls{ISR} to be very short, just a flag in the event administration is set to be processed later. +Furthermore, to ensure the \gls{ISR} to be very short, just a flag in the event administration is set to be processed later. Interrupt event flags are processed at the beginning of the event loop, before tasks are executed. For each subscribed task, the task tree is searched for nodes listening for the particular interrupt. When found, the node is flagged and the pin status is written. @@ -591,7 +594,7 @@ Finally, the event is removed from the registration and the interrupt is disable The interrupt can be disabled as all tasks waiting for the interrupt become stable after firing. More occurrences of the interrupts do not change the value of the task as stable tasks keep the same value forever. Therefore, it is no longer necessary to keep the interrupt enabled, and it is relatively cheap to enable it again if needed in the future. -Evaluating interrupt task node in the task tree is trivial because all the work was already done when the interrupt was triggered. +Evaluating an interrupt task node in the task tree is trivial because all the work was already done when the interrupt was triggered. The task emits the status of the pin as a stable value if the information in the task shows that it was triggered. Otherwise, no value is emitted. @@ -604,8 +607,8 @@ Furthermore, the execution intervals offer an elegant and efficient way to add i Those interrupts offer a more elegant and energy efficient implementation of watching an input than polling this input. The actual reduction of the energy is of course highly dependent on the number and nature of the task shipped to the edge device. -Our examples show a reduction in energy consumption of two orders of magnitude (see \citep{crooijmans_reducing_2022}). -Those reductions are a necessity for edge devices running of battery power. +Our examples show a reduction in energy consumption of two orders of magnitude (see \citep*{crooijmans_reducing_2022}). +Those reductions are a necessity for edge devices running on battery power. Given the exploding number of \gls{IOT} edge devices, such savings are also mandatory for other devices to limit the total power consumption of the \gls{IOT}. \input{subfilepostamble} diff --git a/top/imp.tex b/top/imp.tex index 1169187..6231b4b 100644 --- a/top/imp.tex +++ b/top/imp.tex @@ -537,9 +537,9 @@ The \cleaninline{MTLens} is a type synonym for \pgls{SDS} that represents the ty This is done so that the \cleaninline{withDevice} task can write the received \gls{SDS} updates to the according \gls{SDS} while the \gls{SDS} is not in scope. The \gls{ITASK} notification mechanism then takes care of the rest. Such \pgls{SDS} is created by using the \cleaninline{mapReadWriteError} which, given a pair of read and write functions with error handling, produces \pgls{SDS} with the lens embedded. -The read function transforms converts the typed value to a typeless serialised value. +The read function transforms the typed value to a typeless serialised value. The write function will, given a new serialised value and the old typed value, produce a new typed value. -It tries to decode the serialised value, if that succeeds, it is written to the underlying \gls{SDS}, an error is thrown otherwise. +It tries to decode the serialised value, if that succeeds, it is written to the underlying \gls{SDS}, otherwise, an error is thrown otherwise. \Cref{lst:mtask_itasksds_lens} shows the implementation for this. % VimTeX: SynIgnore on @@ -572,7 +572,8 @@ Once a device is programmed with the \gls{MTASK} \gls{RTS}, it can continuously The \gls{OS} is written in portable \ccpp{} and only contains a small device-specific portion. In order to keep the abstraction level high and the hardware requirements low, much of the high-level functionality of the \gls{MTASK} language is implemented not in terms of lower-level constructs from \gls{MTASK} language but in terms of \ccpp{} code. -Most microcontrollers software consists of a cyclic executive instead of an \gls{OS}, this one loop function is continuously executed and all work is performed there. +Most microcontroller software consists of a cyclic executive instead of an \gls{OS}. +This one loop function is continuously executed and all work is performed there. In the \gls{RTS} of the \gls{MTASK} system, there is also such an event loop function. It is a function with a relatively short execution time that gets called repeatedly. The event loop consists of three distinct phases. @@ -643,7 +644,7 @@ Expressions in the tree are always strictly evaluated by the interpreter. When a new task is received, the main expression is evaluated to produce a task tree. A task tree is a tree structure in which each node represents a task combinator and the leaves are basic tasks. If a task is not initialised yet, i.e.\ the pointer to the current task tree is still null, the byte code of the main function is interpreted. -The main expression of \gls{MTASK} programs sent to the device fore execution always produces a task tree. +The main expression of \gls{MTASK} programs sent to the device before execution always produces a task tree. Execution of a task consists of continuously rewriting the task until its value is stable. Rewriting is a destructive process, i.e.\ the rewriting is done in place. diff --git a/top/int.tex b/top/int.tex index 209c48e..3c70a28 100644 --- a/top/int.tex +++ b/top/int.tex @@ -137,7 +137,7 @@ The first argument is the task and the second argument is the device which is an First a fresh identifier for the task is generated using the device state. With this identifier, the cleanup hook can be installed. This is done to assure the task is removed from the edge device if the \gls{ITASK} task coordinating it is destroyed. -Tasks in \gls{ITASK} are destroyed when for example it is executed in parallel with another task and the parallel combinator terminates, or when the condition to step holds in a sequential task combination. +Tasks in \gls{ITASK} are destroyed when for example they are executed in parallel with another task and the parallel combinator terminates, or when the condition to step holds in a sequential task combination. Then the \gls{MTASK} compiler is invoked, its only argument besides the task is a function doing something with the results of the compilation, i.e.\ the lowered \glspl{SDS} and the messages containing the compiled and serialised task. With the result of the compilation, the task can be executed. First the messages are put in the channels, sending them to the device. @@ -238,7 +238,7 @@ The following section contains an elaborate example using all integration functi \section{Home automation} This section presents an interactive home automation program (\cref{lst:example_home_automation}) to illustrate the dynamic integration of the \gls{MTASK} language and the \gls{ITASK} system. All layers of \gls{IOT} systems are used in this application. -The presentation layer consists of an automatically generated web interface for the user to control which tasks sent to a device for execution. +The presentation layer consists of an automatically generated web interface for the user to control which tasks are sent to a device for execution. The application layer is the \gls{ITASK} server, the coordinator of the tasks in the system that also stores the data. The perception layer is populated by two devices: an \gls{ARDUINO} UNO, and an ESP8266 based prototyping board called {NodeMCU}. \Crefrange{lst:example:spec1}{lst:example:spec2} show the specification for the devices. diff --git a/top/lang.tex b/top/lang.tex index 7b901c8..2e1b0de 100644 --- a/top/lang.tex +++ b/top/lang.tex @@ -29,14 +29,14 @@ Furthermore, this particular type of embedding has the property that it is exten Adding a language construct is as simple as adding a type class. Adding an interpretation is done by creating a new data type and providing implementations for the various type classes. -In order to reduce the hardware requirements for devices running \gls{MTASK} programs, several measures have been taken.\todo{by whom? would be good here to be more explicit to make it clear at this point whether that's part of the contribution} +In order to reduce the hardware requirements for devices running \gls{MTASK} programs, several measures have been taken that are reflected in the language design. Programs in \gls{MTASK} are written in the \gls{MTASK} \gls{DSL}, separating them from the host \gls{ITASK} program. This allows the tasks to be constructed at compile time in order to tailor-make them for the specific work requirements. Furthermore, the \gls{MTASK} language is restricted: there are no recursive data structures, no higher-order functions, strict evaluation, and functions and objects can only be declared at the top level. \section{Class-based shallow embedding} -Let us illustrate this technique by taking the very simple language of literal values. -\todo{show how this relates to the general embedding discussion previously} +The \gls{MTASK} language is implemented as a class-based shallow, also known as tagless-final, embedded \gls{DSL} (see also \cref{sec:tagless-final}). +In order to demonstrate the technique, it is first illustrated by showing 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}. The type variable \cleaninline{v} of the type class represents the view on the language, the interpretation. @@ -93,7 +93,7 @@ Creating such a function, e.g.\ one that both prints and evaluates an expression \section{Types} 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. +As it is shallow 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. @@ -141,7 +141,7 @@ Peripheral, \gls{SDS}, and function definitions are always defined at the top le This is enforced by the \cleaninline{Main} type. 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. -To illustrate the structure of a \gls{MTASK} programs, \cref{lst:mtask_types} shows a skeleton of a program. +To illustrate the structure of \gls{MTASK} programs, \cref{lst:mtask_types} shows a skeleton of a program. % VimTeX: SynIgnore on \begin{lstClean}[caption={Auxiliary types and example task in the \gls{MTASK} language.},label={lst:mtask_types}] @@ -227,7 +227,7 @@ 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 and hence compiled at run time. +The \gls{MTASK} language is shallow 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 peculiarities. @@ -287,7 +287,7 @@ Deriving how to define and use functions from the type is quite a challenge even Splitting out the function definition for each single arity means that for every function arity and combination of arguments, a separate class constraint is required. Many of the often used functions signatures are in the \cleaninline{mtask} class constraint collection. \Cref{lst:function_examples} show some examples of functions to illustrate the syntax. -The \cleaninline{factorial} functions shows a recursive version of the factorial function. +The \cleaninline{factorial} function shows a recursive version of the factorial function. The \cleaninline{factorialtail} function is a tail-call optimised version of the above. It also illustrates a manually added class constraint, as they are required when functions are used that have signatures not present in the \cleaninline{mtask} class collection. Zero-arity functions are always called with unit as an argument, which is shown in the \cleaninline{zeroarity} function. @@ -345,7 +345,8 @@ The task language of \gls{MTASK} is divided into three categories: \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 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. + The data is available for tasks using many-to-many communication. + Reading, writing and updating \glspl{SDS} is an atomic operation on the task level. \end{description} As \gls{MTASK} is integrated with \gls{ITASK}, a stability distinction is made for task values just as in \gls{ITASK}. @@ -370,7 +371,7 @@ The most rudimentary non-interactive basic tasks in the task language of \gls{MT 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---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. +Once the specified time has passed, the exact time the task overshot the target time is yielded as a stable task value.\todo{unclear?} See \cref{sec:repeat} for an example task using \cleaninline{delay}. \begin{lstClean}[label={lst:basic_tasks},caption={Non-interactive basic tasks in \gls{MTASK}.}] @@ -692,11 +693,12 @@ It uses expressions based a simply-typed $\lambda$-calculus with support for som \section{Conclusion} This chapter gave an overview of the complete \gls{MTASK} \gls{DSL}. The \gls{MTASK} language is a rich \gls{TOP} language tailored for \gls{IOT} edge devices. -The language is implemented as a class-based shallowly embedded \gls{DSL} in the pure functional host language \gls{CLEAN}. +The language is implemented as a class-based shallow embedded \gls{DSL} in the pure functional host language \gls{CLEAN}. The language uses an enriched lambda calculus as a host language, providing additional 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. When using the byte code compiler, terms in the \gls{MTASK} language are type checked at compile time but are constructed and compiled at run time. This facilitates tailor-making tasks for the current work requirements. +\todo{would be nice to see an example of this} \input{subfilepostamble} \end{document} diff --git a/tvt/tvt.tex b/tvt/tvt.tex index 085acc6..efae48e 100644 --- a/tvt/tvt.tex +++ b/tvt/tvt.tex @@ -32,13 +32,13 @@ Conventional \gls{IOT} software architectures require the development of separat \begin{enumerate*} \item Interoperating components in multiple languages and paradigms increases the developer's cognitive load who must simultaneously think in multiple languages and paradigms, i.e.\ manage significant semantic friction. \item The developer must correctly interoperate the components, e.g.\ adhere to the \gls{API} or communication protocols between components. - \item To ensure correctness the developer must maintain type safety across a range of very different languages and diverse type systems.\todo[inline]{what do you mean by type safety here precisely? how can that happend if non type safe languages are in the mix} + \item To ensure correctness the developer must maintain type safety across a range of very different languages and diverse type systems. \item The developer must deal with the potentially diverse failure modes of each component, and of component interoperation. \end{enumerate*} A radical alternative development paradigm uses a single \emph{tierless} language that synthesises all components\slash{}tiers in the software stack. There are established \emph{tierless} languages for web stacks, e.g.\ Links \citep{cooper2006links} or Hop \citep{serrano2006hop}. In a tierless language the developer writes the application as a single program. The code for different tiers is simultaneously checked by the compiler, and compiled to the required component languages. For example, Links compiles to HTML and JavaScript for the web client and to SQL on the server to interact with the database system. Tierless languages for \gls{IOT} stacks are more recent and less common, examples include -Potato \citep{troyer_building_2018} and \gls{CLEAN} with \imtask{} \citep{lubbers_interpreting_2019}. +Potato \citep{troyer_building_2018}, and \gls{CLEAN} with \imtask{} \citep{lubbers_interpreting_2019}. \Gls{IOT} sensor nodes may be microcontrollers with very limited compute resources, or supersensors: resource-rich single board computers like a Raspberry Pi. A tierless language may target either class of sensor node, and microcontrollers are the more demanding target due to the limited resources, e.g.\ small memory, executing on bare metal, \etc. @@ -202,8 +202,6 @@ Only a small fraction of these systems are described in the academic literature, \label{sec_t4t:characteristics} This study compares a pair of tierless \gls{IOT} languages with conventional tiered \gls{PYTHON} \gls{IOT} software. \Citask{} and \cimtask{} represent a specific set of tierless language design decisions, however many alternative designs are available. Crucially the limitations of the tierless \gls{CLEAN} languages, e.g.\ that they currently provide limited security, should not be seen as limitations of tierless technologies in general. This section briefly outlines key design decisions for tierless \gls{IOT} languages, discusses alternative designs, and describes the \gls{CLEAN} designs. The \gls{CLEAN} designs are illustrated in the examples in the following section. -\todo{again, here it would be good to have a general definition of tierless, and then describe what the possible design choices are, and where in the space iTask/mTask fits} - \subsubsection{Tier splitting and placement} A key challenge for a tierless language is to determine which parts of the program correspond to a particular tier and hence should be executed by a specific component on a specific host.