\begin{document}
\input{subfileprefix}
\ifSubfilesClassLoaded{\appendix}{}
-\chapter{\texorpdfstring{\glsentrytext{CLEAN}}{Clean} for \texorpdfstring{\glsentrytext{HASKELL}}{Haskell} programmers}%
+\chapter{Clean for Haskell programmers}%
\label{chp:clean_for_haskell_programmers}
This appendix is meant give people who are familiar with the \gls{FP} language \gls{HASKELL} a consise overview of the programming language \gls{CLEAN} and how it differs from \gls{HASKELL}.
Metadata about the types is available using the \cleaninline{of} syntax that gives the function access to metadata records, as can be seen in \cref{lst:generic_print} showing a generic print function. This abundance of metadata allows for very complex generic functions that near the expression level of template metaprogramming (see \cref{chp:first-class_datatypes,sec:ccodegen}).
\cleaninputlisting[language=Clean,firstline=4,label={lst:generic_print},caption={Generic print function}]{lst/generic_print.icl}
-\subsection{\texorpdfstring{\glsentrytext{GADT}}{GADT}s}
+\subsection{GADTs}
\Glspl{GADT} are enriched data types that allow the type instantiation of the constructor to be explicitly defined \citep{cheney_first-class_2003,hinze_fun_2003}.
While \glspl{GADT} are not natively supported in \gls{CLEAN}, they can be simulated using embedding-projection pairs or equivalence types \citep[\citesection{2.2}]{cheney_lightweight_2002}.
To illustrate this, \cref{lst:gadt_haskell} shows a \gls{GADT} in \gls{HASKELL}\requiresGHCmod{GADTs} that can be implemented as in \cref{lst:gadt_clean}.
\begin{document}
\input{subfileprefix}
\ifSubfilesClassLoaded{\appendix\setcounter{chapter}{1}}{}
-\chapter{Auxiliary \texorpdfstring{\glsentrytext{MTASK}}{mTask} type classes}%
+\chapter{Auxiliary mTask type classes}%
\label{chp:mtask_aux}
\lstset{basicstyle=\tt\footnotesize}
\section{Peripherals}\label{sec:aux_peripherals}
soundLevel :: (v SoundDetector) -> MTask v Bool | tupl, aio v
\end{lstClean}
-\subsection{\texorpdfstring{\gls{I2C}}{I\textsuperscript{2}C} buttons}
+\subsection{\IIC{} buttons}
The \gls{MTASK} language supports one type of \gls{I2C} buttons (the \gls{I2C} buttons from the \gls{WEMOS} d1 mini \gls{OLED} shield).
The buttons from this shield provide more information than just the status (see \cleaninline{ButtonStatus}).
The complete interface containing the constructor and the measurement tasks is shown in \cref{lst:mtask_i2cbutton}.
BButton :: (v I2CButton) -> MTask v ButtonStatus
\end{lstClean}
-\subsection{\texorpdfstring{\gls{LED}}{LED} matrix}
+\subsection{LED matrix}
The \gls{MTASK} language supports one type of \gls{LED} matrix (the $8\times8$ \gls{LED} matrix shield for the \gls{WEMOS} d1 mini).
Instead of containing a \gls{TOP}-like interface, the \gls{ARDUINO} interface is directly translated to \gls{MTASK}.
As a result, every task immediately returns a stable value indicating the result.
e3 = neg_4 (Lit_4 42 `sub_4` Lit_4 38) `Add_4` Lit_4 1
\end{lstHaskellLhstex}
-\section{\texorpdfstring{\Glsxtrlongpl{GADT}}{Generalised algebraic data types}}%
+\section{Generalised algebraic data types}%
\Glspl{GADT} are enriched data types that allow the type instantiation of the constructor to be explicitly defined \citep{cheney_first-class_2003,hinze_fun_2003}.
Leveraging \glspl{GADT}, deeply embedded \glspl{DSL} can be made statically type safe even when different value types are supported.
Even when \glspl{GADT} are not supported natively in the language, they can be simulated using embedding-projection pairs or equivalence types \citep[\citesection{2.2}]{cheney_lightweight_2002}.
getOpt_g (OptDict_g e) = e
\end{lstHaskellLhstex}
-\begin{lstHaskellLhstex}[caption={\texorpdfstring{\haskelllhstexinline{GDict}}{GDict} instances.}]
+\begin{lstHaskellLhstex}[caption={{\tt GDict} instances.}]
instance Print_g v => GDict (PrintDict_g v) where
gdict = PrintDict_g print_g
instance Opt_g v => GDict (OptDict_g v) where
\begin{document}
\input{subfileprefix}
-\chapter{First-class data types in shallow \texorpdfstring{embedded domain-specific languages}{\glsxtrlongpl{EDSL}} using metaprogramming}%
+\chapter{First-class data types in shallow embedded domain-specific languages using metaprogramming}%
\label{chp:first-class_datatypes}%
\begin{chapterabstract}
\Gls{FP} languages are excellent for hosting \glspl{EDSL} because of their rich type systems, minimal syntax, and referential transparency.
Reification is done using the \haskellinline{reify :: Name -> Q Info} function.
The \haskellinline{Info} type is an \gls{ADT} containing all the---known to the compiler---information about the matching type: constructors, instances, \etc.
-\section{Metaprogramming for generating \texorpdfstring{\glsxtrshort{DSL}}{DSL} functions}
+\section{Metaprogramming for generating DSL functions}
With the power of metaprogramming, we can generate the boilerplate code for our user-defined data types automatically at compile time.
To generate the code required for the \gls{DSL}, we define the \haskellinline{genDSL} function.
The type belonging to the name passed as an argument to this function is made available for the \gls{DSL} by generating the \haskellinline{typeDSL} class and view instances.
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}.
-\subsection{Related work on \texorpdfstring{\glsxtrlong{TH}}{Template Haskell}}
+\subsection{Related work on Template Haskell}
Metaprogramming in general is a very broad research topic and has been around for years already.
We therefore do not claim an exhaustive overview of related work on all aspects of metaprogramming.
However, we have have tried to present most research on metaprogramming in \gls{TH}.
\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.
-\subsubsection{\texorpdfstring{\Glsxtrlong{TTH}}{Typed Template Haskell}}\label{ssec_fcd:typed_template_haskell}
+\subsubsection{Typed Template Haskell}\label{ssec_fcd:typed_template_haskell}
\Gls{TTH} is a very recent extension/alternative to normal \gls{TH} \citep{pickering_multi-stage_2019,xie_staging_2022}.
Where in \gls{TH} you can manipulate arbitrary parts of the syntax tree, add top-level splices of data types, definitions and functions, in \gls{TTH} the programmer can only splice expressions but the \gls{AST} fragments representing the expressions are well-typed by construction instead of untyped.
H.P. (Howard) Lovecraft
}
\epigraph{%
- \selectlanguage{russian}Рукописи не горят.\\
- \selectlanguage{british} (Manuscripts don't burn.)
+ \foreignlanguage{russian}{Рукописи не горят.}\\
+ (Manuscripts don't burn.)
}{%
- \selectlanguage{russian}М.А.\ (Mихаил) Булгаков\\
- \selectlanguage{british} (M.A.\ (Mikhail) Bulgakov)
+ \foreignlanguage{russian}{М.А.\ (Mихаил) Булгаков}\\
+ (M.A.\ (Mikhail) Bulgakov)
}
\epigraph{%
You start a question, and it's like starting a stone.
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.
-\section{\texorpdfstring{\Glsxtrlong{IOT}}{Internet of things}}%
+\section{Internet of things}%
\label{sec:back_iot}
The \gls{IOT} is growing rapidly, and it is changing the way people and machines interact with each other and the world.
While the term \gls{IOT} briefly gained interest around 1999 to describe the communication of \gls{RFID} devices \citep{ashton_internet_1999,ashton_that_2009}, it probably already popped up halfway the eighties in a speech by \citet{lewis_speech_1985}:
This dissertation describes a \gls{DSL} that includes the high-level programming concepts of \gls{TOP}, while it can be executed on edge devices with very limited hardware requirements.
It does so by compiling the \gls{DSL} to byte code that is executed in a feather-light domain-specific \gls{OS}.
-\section{\texorpdfstring{\Glsxtrlongpl{DSL}}{Domain-specific languages}}%
+\section{Domain-specific languages}%
\label{sec:back_dsl}
% General
Programming languages can be divided up into two categories: \glspl{DSL} and \glspl{GPL} \citep{fowler_domain_2010}.
The interpreter running on the edge device has no knowledge of the higher level task specification.
It just interprets the byte code it was sent and takes care of the communication.
-\section{\texorpdfstring{\Glsxtrlong{TOP}}{Task-oriented programming}}%
+\section{Task-oriented programming}%
\label{sec:back_top}
\Gls{TOP} is a declarative programming paradigm for modelling interactive systems \citep{plasmeijer_task-oriented_2012}.
Instead of dividing problems into layers, \gls{TOP} deals with separation of concerns in a novel way.
The second view is that edge devices contain miniature \gls{TOP} systems in itself.
The individual components in the miniature systems, the tasks, the \glspl{SDS}, are, in the eventual execution, connected to the main system.
-\subsection{The \texorpdfstring{\gls{ITASK}}{iTask} system}
+\subsection{The iTask system}
The concept of \gls{TOP} originated from the \gls{ITASK} framework, a declarative language and \gls{TOP} engine for defining interactive multi-user distributed web applications.
The \gls{ITASK} system is implemented as an \gls{EDSL} in the programming language \gls{CLEAN}\footnote{\Cref{chp:clean_for_haskell_programmers} contains a guide for \gls{CLEAN} tailored to \gls{HASKELL} programmers.} \citep{plasmeijer_itasks:_2007,plasmeijer_task-oriented_2012}.
It has been under development for over fifteen years and has proven itself through use in industry for some time now as well \citep{top_software_viia_2023}.
\label{fig:todo}
\end{figure}
-\subsection{The \texorpdfstring{\gls{MTASK}}{mTask} system}
+\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 share data with other components or the server.
The \gls{ITASK} system seems an obvious candidate for bringing \gls{TOP} to \gls{IOT} edge devices.
intBlink :: (Shared sds Int) -> Main (MTask v Int) | mtask v & ...\end{lstClean}
\cleaninputlisting[aboveskip=0pt,firstnumber=4,firstline=23,numbers=left,caption={The \gls{MTASK} code for the interactive blinking application.},label={lst:intro_blink_mtask}]{lst/blink.icl}
-\subsection{Other \texorpdfstring{\glsxtrshort{TOP}}{TOP} languages}
+\subsection{Other TOP languages}
While \gls{ITASK} conceived \gls{TOP}, it is no longer the only \gls{TOP} system.
Some \gls{TOP} languages were created to fill a gap encountered in practise.
Toppyt \citep{lijnse_toppyt_2022} is a general purpose \gls{TOP} language written in \gls{PYTHON} used to host frameworks for modelling command \& control systems, and hTask \citep{lubbers_htask_2022}, a vessel for experimenting with asynchronous \glspl{SDS}.
The paper also serves as a gentle introduction to, and contains a thorough literature study on \glsxtrlong{TH}.
\end{enumerate}
-%\paragraph{Other publications on \texorpdfstring{\glspl{EDSL}}{eDSLs}:}
+\todo[inline]{add stack paper?}
+%\paragraph{Other publications on eDSLs:}
%Furthermore, I co-authored a paper that is not part of the \gls{MTASK} system yet and hence not part of the dissertation.
%
%\begin{enumerate}[resume]
\usepackage[utf8]{inputenc} % Input encoding
-\usepackage[T2A,T1]{fontenc} % Font encoding
+\usepackage[X2,T1]{fontenc} % Font encoding
\usepackage{ifxetex}
\ifxetex%
\usepackage{amsmath} % extra math
% Crossreferences, urls and hyperlinks
\input{preamble/crossref}
-% Glossaries and acronyms
-\input{preamble/glossaries}
-
% Custom commands
\input{preamble/commands}
+% Glossaries and acronyms
+\input{preamble/glossaries}
+
% File structure, this must be last of the preamble
\usepackage{subfiles}
\newcommand{\aramsingh}{Ramsingh, A.\ (University of Glasgow)}
\newcommand{\dcolon}[0]{\mathbin{::}}
\newcommand{\doifmt}[1]{\href{https://doi.org/#1}{#1}}
-\newcommand{\etc}{{\itshape\/\&\kern-0.2em c}}
+\newcommand{\etc}{{\fontfamily{cmr}\selectfont{\itshape\/\&\kern-0.2em c}}}
\newcommand{\jsinger}{Singer, J.\ (University of Glasgow)}
\newcommand{\mlubbers}{Lubbers, M.\ (Radboud University)}
\newcommand{\pkoopman}{Koopman, P.\ (Radboud University)}
\newcommand{\cschemeE}[2]{\mathcal{E}\llbracket#1\rrbracket~#2}
\newcommand{\cschemeF}[1]{\mathcal{F}\llbracket#1\rrbracket}
\newcommand{\cschemeS}[3]{\mathcal{S}\llbracket#1\rrbracket~#2~#3}
+
+\newcommand{\IOT}{\texorpdfstring{Io\kern-1ptT}{IoT}}
+\newcommand{\IIC}{I\textsuperscript{2}C}
\usepackage[nolangwarn,nonumberlist,prefix]{glossaries-extra}
-\setabbreviationstyle{long-short-sc}
+\setabbreviationstyle{long-short}
\setabbreviationstyle[noexpand]{short-nolong}
-\setabbreviationstyle[scabbr]{short-sc-nolong}
+%\setabbreviationstyle[scabbr]{short-sc-nolong}
\Addlcwords{of}
\glssetcategoryattribute{abbreviation}{glossname}{uc}
\glssetcategoryattribute{noexpand}{glossname}{uc}
% Acronyms
\newacronym[description={the CO\textsubscript{2} concentration calculated from \glsxtrshort{TVOC} measurements}]{ECO2}{(eCO\textsubscript{2})}{equivalent carbon dioxide}
-\newacronym[category=scabbr,description={a open data interchange format using human readable text}]{JSON}{{\scshape JSON}}{(JavaScript object notation)}
-\newacronym[category=scabbr,description={a publish-subscribe network protocol designed for resource constrained devices}]{MQTT}{{\scshape MQTT}}{(MQ telemetry transport)}
+\newacronym[description={a open data interchange format using human readable text}]{JSON}{JSON}{(JavaScript object notation)}
+\newacronym[description={a publish-subscribe network protocol designed for resource constrained devices}]{MQTT}{MQTT}{(MQ telemetry transport)}
\newacronym[description={a pure lazy \glsxtrlong{FP} language based on graph rewriting}]{CLEAN}{Clean}{(Clean language of East-Anglia and Nijmegen)}
-\newacronym[description={a simple serial communication protocol often used to connect sensors to microcontrollers}]{I2C}{I\textsuperscript{2}C}{(inter-integrated circuit)}
-\newacronym[category=scabbr,description={passive infrared}]{PIR}{{\scshape PIR}}{}
-\newacronym[category=scabbr,description={task-oriented programming}]{TOP}{{\scshape TOP}}{}
-\newacronym[category=scabbr,description={the three ``CO'' (composability, comprehensibility, correctness) of working software}]{3COWS}{{\scshape 3COWS}}{}
+\newacronym[description={a simple serial communication protocol often used to connect sensors to microcontrollers}]{I2C}{\IIC{}}{(inter-integrated circuit)}
+\newacronym[description={passive infrared}]{PIR}{PIR}{}
+\newacronym[description={task-oriented programming}]{TOP}{TOP}{}
+\newacronym[description={the three ``CO'' (composability, comprehensibility, correctness) of working software}]{3COWS}{3COWS}{}
% Initialisms
-\newabbreviation{ADC}{adc}{analog-to-digital converter}
-\newabbreviation{ADT}{adt}{algebraic data type}
-\newabbreviation{AST}{ast}{abstract syntax tree}
-\newabbreviation{API}{api}{application programming interface}
-\newabbreviation{ARDSL}{ardsl}{\gls{ARDUINO} \glsxtrshort{DSL}}
-\newabbreviation[category=noexpand]{CEFP}{cefp}{Central European \glsxtrlong{FP} School}
-\newabbreviation{CRS}{crs}{\gls{CLEAN} Raspberry Pi system}
-\newabbreviation{CRTS}{crts}{\gls{CLEAN} Raspberry Pi temperature sensor}
-\newabbreviation{CWS}{cws}{\gls{CLEAN} \gls{WEMOS} system}
-\newabbreviation{CWTS}{cwts}{\gls{CLEAN} \gls{WEMOS} temperature sensor}
-\newabbreviation{DHT}{dht}{digital humidity and temperature}
-\newabbreviation{DSL}{dsl}{domain-specific language}
-\newabbreviation{DVFS}{dvfs}{dynamic voltage and frequency scaling}
-\newabbreviation{EDSL}{edsl}{embedded \glsxtrlong{DSL}}
-\newabbreviation[prefixfirst={a\ },prefix={an\ }]{FP}{fp}{functional programming}
-\newabbreviation[prefixfirst={a\ },prefix={an\ }]{FRP}{frp}{functional reactive programming}
-\newabbreviation[prefixfirst={a\ },prefix={an\ }]{FPGA}{fpga}{field-programmable gate array}
-\newabbreviation{GADT}{gadt}{generalised \glsxtrshort{ADT}}
-\newabbreviation{GHC}{ghc}{Glasgow \gls{HASKELL} Compiler}
-\newabbreviation{GPIO}{gpio}{general-purpose \glsxtrlong{IO}}
-\newabbreviation{GPL}{gpl}{general-purpose language}
-\newabbreviation{GRS}{grs}{graph rewriting system}
-\newabbreviation{GUI}{gui}{graphical \glsxtrlong{UI}}
-\newabbreviation{HOAS}{hoas}{high-order abstract syntax}
-%\newabbreviation{IOT}{Io\kern-.3mmT}{internet of things}
-\newabbreviation{IOT}{iot}{internet of things}
-\newabbreviation[category=noexpand]{IDE}{ide}{integrated development environment}
-\newabbreviation[category=noexpand]{IO}{i/o}{input/output}
-\newabbreviation{IR}{ir}{intermediate representation}
-\newabbreviation{ISR}{isr}{interrupt service routine}
-\newabbreviation[category=noexpand,prefixfirst={a\ },prefix={an\ }]{LED}{led}{light-emitting diode}
-\newabbreviation[category=noexpand]{OLED}{oled}{organic \glsxtrshort{LED}}
-\newabbreviation[category=noexpand]{OS}{os}{operating system}
-\newabbreviation{OTA}{ota}{over-the-air}
+\newabbreviation{ADC}{ADC}{analog-to-digital converter}
+\newabbreviation{ADT}{ADT}{algebraic data type}
+\newabbreviation{AST}{AST}{abstract syntax tree}
+\newabbreviation{API}{API}{application programming interface}
+\newabbreviation{ARDSL}{ARDSL}{\gls{ARDUINO} \glsxtrshort{DSL}}
+\newabbreviation[category=noexpand]{CEFP}{CEFP}{Central European \glsxtrlong{FP} School}
+\newabbreviation{CRS}{CRS}{\gls{CLEAN} Raspberry Pi system}
+\newabbreviation{CRTS}{CRTS}{\gls{CLEAN} Raspberry Pi temperature sensor}
+\newabbreviation{CWS}{CWS}{\gls{CLEAN} \gls{WEMOS} system}
+\newabbreviation{CWTS}{CWTS}{\gls{CLEAN} \gls{WEMOS} temperature sensor}
+\newabbreviation{DHT}{DHT}{digital humidity and temperature}
+\newabbreviation{DSL}{DSL}{domain-specific language}
+\newabbreviation{DVFS}{DVFS}{dynamic voltage and frequency scaling}
+\newabbreviation{EDSL}{EDSL}{embedded \glsxtrlong{DSL}}
+\newabbreviation[prefixfirst={a\ },prefix={an\ }]{FP}{FP}{functional programming}
+\newabbreviation[prefixfirst={a\ },prefix={an\ }]{FRP}{FRP}{functional reactive programming}
+\newabbreviation[prefixfirst={a\ },prefix={an\ }]{FPGA}{FPGA}{field-programmable gate array}
+\newabbreviation{GADT}{GADT}{generalised \glsxtrshort{ADT}}
+\newabbreviation{GHC}{GHC}{Glasgow \gls{HASKELL} Compiler}
+\newabbreviation{GPIO}{GPIO}{general-purpose \glsxtrlong{IO}}
+\newabbreviation{GPL}{GPL}{general-purpose language}
+\newabbreviation{GRS}{GRS}{graph rewriting system}
+\newabbreviation{GUI}{GUI}{graphical \glsxtrlong{UI}}
+\newabbreviation{HOAS}{HOAS}{high-order abstract syntax}
+\newabbreviation{IOT}{\IOT{}}{internet of things}
+\newabbreviation[category=noexpand]{IDE}{IDE}{integrated development environment}
+\newabbreviation[category=noexpand]{IO}{I/O}{input/output}
+\newabbreviation{IR}{IR}{intermediate representation}
+\newabbreviation{ISR}{ISR}{interrupt service routine}
+\newabbreviation[category=noexpand,prefixfirst={a\ },prefix={an\ }]{LED}{LED}{light-emitting diode}
+\newabbreviation[category=noexpand]{OLED}{OLED}{organic \glsxtrshort{LED}}
+\newabbreviation[category=noexpand]{OS}{OS}{operating system}
+\newabbreviation{OTA}{OTA}{over-the-air}
\newabbreviation{PFRP}{p-frp}{priority-based \glsxtrshort{FRP}}
-\newabbreviation{PRS}{prs}{\gls{PYTHON} Raspberry Pi system}
-\newabbreviation{PWS}{pws}{\gls{MICROPYTHON} \gls{WEMOS} system}
-\newabbreviation{PRTS}{prts}{\gls{PYTHON} Raspberry Pi temperature sensor}
-\newabbreviation{PWTS}{pwts}{\gls{MICROPYTHON} \gls{WEMOS} temperature sensor}
-\newabbreviation{QDSL}{qdsl}{quoted \glsxtrshort{DSL}}
-\newabbreviation[category=noexpand]{RAM}{ram}{random-access memory}
-\newabbreviation{RFID}{rfid}{radio-frequency identification}
-\newabbreviation{RTOS}{rtos}{real-time \glsxtrshort{OS}}
-\newabbreviation{RTS}{rts}{run-time system}
-\newabbreviation[prefixfirst={a\ },prefix={an\ }]{SDS}{sds}{shared data source}
-\newabbreviation[prefixfirst={a\ },prefix={an\ }]{SN}{sn}{sensor network}
-\newabbreviation{SLOC}{sloc}{source lines of code}
+\newabbreviation{PRS}{PRS}{\gls{PYTHON} Raspberry Pi system}
+\newabbreviation{PWS}{PWS}{\gls{MICROPYTHON} \gls{WEMOS} system}
+\newabbreviation{PRTS}{PRTS}{\gls{PYTHON} Raspberry Pi temperature sensor}
+\newabbreviation{PWTS}{PWTS}{\gls{MICROPYTHON} \gls{WEMOS} temperature sensor}
+\newabbreviation{QDSL}{QDSL}{quoted \glsxtrshort{DSL}}
+\newabbreviation[category=noexpand]{RAM}{RAM}{random-access memory}
+\newabbreviation{RFID}{RFID}{radio-frequency identification}
+\newabbreviation{RTOS}{RTOS}{real-time \glsxtrshort{OS}}
+\newabbreviation{RTS}{RTS}{run-time system}
+\newabbreviation[prefixfirst={a\ },prefix={an\ }]{SDS}{SDS}{shared data source}
+\newabbreviation[prefixfirst={a\ },prefix={an\ }]{SN}{SN}{sensor network}
+\newabbreviation{SLOC}{SLOC}{source lines of code}
\newabbreviation[description={a synchronous serial communication protocol often used to connect sensors to microcontrollers}]{SPI}{SPI}{Serial Peripheral Interface}
-\newabbreviation{TH}{th}{Template \gls{HASKELL}}
-\newabbreviation[category=noexpand]{TCP}{tcp}{transmission control protocol}
-\newabbreviation{TOSD}{tosd}{task-oriented software development}
-\newabbreviation{TRS}{trs}{term rewriting system}
-\newabbreviation{TTH}{tth}{typed \glsxtrlong{TH}}
-\newabbreviation{TVOC}{tvoc}{total volatile organic compounds}
-\newabbreviation{UI}{ui}{user interface}
-\newabbreviation{UOD}{uod}{universe of discourse}
-\newabbreviation{UOG}{uog}{University of Glasgow}
-\newabbreviation{VM}{vm}{virtual machine}
+\newabbreviation{TH}{TH}{Template \gls{HASKELL}}
+\newabbreviation[category=noexpand]{TCP}{TCP}{transmission control protocol}
+\newabbreviation{TOSD}{TOSD}{task-oriented software development}
+\newabbreviation{TRS}{TRS}{term rewriting system}
+\newabbreviation{TTH}{TTH}{typed \glsxtrlong{TH}}
+\newabbreviation{TVOC}{TVOC}{total volatile organic compounds}
+\newabbreviation{UI}{UI}{user interface}
+\newabbreviation{UOD}{UOD}{universe of discourse}
+\newabbreviation{UOG}{UOG}{University of Glasgow}
+\newabbreviation{VM}{VM}{virtual machine}
% Glossaries
\newglossaryentry{ABC}{%
re-i-fi-ca-tion
pro-gram-mer
Nij-me-gen
+ pa-ra-me-tri-sed
}
\def\addToLiterate#1{\edef\lst@literate{\unexpanded\expandafter{\lst@literate}\unexpanded{#1}}}
\lst@Key{moreliterate}{}{\addToLiterate{#1}}
\makeatother
+\definecolor{lstbg}{gray}{.95}
% General listings settings
\lstset{%
basewidth=0.5em,
\everymath{\it\/}
-%\DeclareMathSymbol{\shortminus}{\mathbin}{AMSa}{"39} %chktex 18
-\newcommand{\shortminus}{-}
+\DeclareMathSymbol{\shortminus}{\mathbin}{AMSa}{"39} %chktex 18
+%\newcommand{\shortminus}{-}
+
+%\DeclareFontEncoding{X2}{lmr}{}
+\DeclareFontFamily{X2}{lmr}{}
+\DeclareFontShape{X2}{lmr}{m}{n}{ <-> ssub * cmr/m/n }{}
\input{preamble}
% To show hboxes even when in non-draft mode
-%\overfullrule=1pt
-%\showboxdepth=\maxdimen%
-%\showboxbreadth=\maxdimen%
-% \showboxdepth=5
-% \showboxbreadth=5
\setlength{\overfullrule}{20pt}
% Just for the todonotes, can go when it's finished
\label{prt:top}
\subfile{top/4iot} % TOP for the IoT
\subfile{top/lang} % mTask DSL
-\subfile{top/imp} % Implementation
\subfile{top/int} % Integration with iTask
+\subfile{top/imp} % Implementation
\subfile{top/green} % Green computing
\subfile{top/finale} % Conclusion
\begin{document}
\input{subfileprefix}
-\chapter{\texorpdfstring{\Glsxtrlong{TOP} for the \glsxtrlong{IOT}}{Task-oriented programming for the internet of things}}%
+\chapter{Task-oriented programming for the internet of things}%
\label{chp:top4iot}
\begin{chapterabstract}
This chapter introduces the monograph. It compares traditional edge device programming to \gls{TOP} by:
Originally it was designed for the in-house developed open-source hardware with the same name but the setup allows porting to many architectures by vendor-provided \emph{cores}.
It provides an \gls{IDE} and toolchain automation to easily run code with a single press of a button.
-\section{\texorpdfstring{\Glsxtrshort{TOP} for the \glsxtrshort{IOT}}{TOP for the IoT}}
+\section{TOP for the IoT}
\Gls{TOP} is a programming paradigm that allows multi-tier interactive systems to be generated from a single declarative source (see \cref{sec:back_top}).
An example of a \gls{TOP} system is \gls{ITASK}, a general-purpose \gls{TOP} language for programming interactive distributed web applications.
Such web applications often form the core of the top two layers of an \gls{IOT} application.
delay(500);
}\end{lstArduino}
-\subsection{Blinking the \texorpdfstring{\glsxtrshort{LED}}{LED} in \texorpdfstring{\gls{MTASK}}{mTask}.}
+\subsection{Blinking the LED in mTask}
Naively translating the traditional blink program to \gls{MTASK} can be done by simply substituting some syntax as seen in \cref{lst:blinkImp}.
E.g.\ \arduinoinline{digitalWrite} becomes \cleaninline{writeD}, literals are prefixed with \cleaninline{lit}, and \arduinoinline{pinMode} becomes \arduinoinline{declarePin}.
In contrast to the imperative \gls{CPP} dialect, \gls{MTASK} is a \gls{TOP} language and therefore there is no such thing as a loop, only task combinators to combine tasks.
blink(D3, 800, &led3, &st1);
}\end{lstArduino}
-\subsection{Multitasking in \texorpdfstring{\gls{MTASK}}{mTask}}
+\subsection{Multitasking in mTask}
In contrast to the \arduinoinline{delay} function in \gls{ARDUINO}, \gls{MTASK}'s \cleaninline{delay} \emph{task} does not block the execution.
It has no observable value until the target waiting time has passed, and thence is \emph{stable}.
To make code reuse possible and make the implementation more intuitive, the blinking behaviour is lifted to a recursive function as well instead of using the imperatively looking \cleaninline{rpeat} task combinator.
The following chapters thoroughly introduce all aspects of the \gls{MTASK} system.
First the language setup and interface is shown in \cref{chp:mtask_dsl}.
-Then, \cref{chp:implementation} provides the implementation of the \gls{DSL}, the compilation schemes, instruction set and details on the interpreter.
\Cref{chp:integration_with_itask} shows the integration of \gls{MTASK} and \gls{ITASK}.
+Then, \cref{chp:implementation} provides the implementation of the \gls{DSL}, the compilation schemes, instruction set and details on the interpreter.
\Cref{chp:green_computing_mtask} explains all green computing aspects of \gls{MTASK}, i.e.\ task scheduling and processor interrupts.
Finally, \cref{chp:finale} concludes and shows related work together with a short history of \gls{MTASK}.
\begin{document}
\begin{tikzpicture}[node distance=1em]
\node (s1) {\verb#>>|.#};
- \node (d1) [left=of s1.north,yshift=-3em] {\verb#delay#};
+ \node (d1) [left=of s1.north,yshift=-3em] {\verb#delay 500#};
\node (s2) [right=of s1.north,yshift=-3em] {\verb#>>=.# $\lambda x\shortrightarrow$};
- \node (wd) [left=of s2.north,yshift=-3em] {\verb#writeD#};
+ \node (wd) [left=of s2.north,yshift=-3em] {\verb#writeD D3 st#};
\node (rec) [right=of s2.north,yshift=-3em,fill=gray!15,label={[xshift=1em,label distance=-5pt]above:{\tiny interpreter}}] {\verb#blink (Not x)#};
\draw (s1.south) -- (d1.north);
\draw (s1.south) -- (s2.north);
\draw (s2.south) -- (wd.north);
\draw (s2.south) -- ([xshift=-1.5em]rec.north);
- \draw [->,dashed] ([xshift=-1.5em]rec.north) to [out=25,in=25] (s1.east);
+% \draw [->,dashed] ([xshift=-1.5em]rec.north) to [out=25,in=25] (s1.east);
\end{tikzpicture}
\end{document}
However, there is no integration between the client and the server other than that they are programmed from a single source.
Mat\`e is an example of an early tierless sensor network framework where devices are provided with a virtual machine using TinyOS for dynamic provisioning \citep{levis_mate_2002}.
-\subsection{\texorpdfstring{\Glsxtrlongpl{DSL}}{DSLs}}\label{sec:related_dsl}
+\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{}.
-\subsection{\texorpdfstring{\Glsxtrlong{FP}}{Functional programming}}\label{sec:related_fp}
+\subsection{Functional programming}\label{sec:related_fp}
\Citet{haenisch_case_2016} showed that there are major benefits to using functional languages on edge devices.
They show that using function languages increased the security and maintainability of the applications.
Traditional implementations of general purpose functional languages have high memory requirements rendering them unusable for resource-constrained computers.
\end{threeparttable}
\end{table}
-\subsection{\texorpdfstring{\Glsxtrlong{FRP}}{Functional reactive programming}}\label{sec:related_frp}
+\subsection{Functional reactive programming}\label{sec:related_frp}
The \gls{TOP} paradigm is often compared to \gls{FRP} because they appear similar.
\Gls{FRP} was introduced by \citet{elliott_functional_1997}.
The paradigm strives to make modelling systems safer, more efficient, and composable.
Other examples are CFRP \citep{suzuki_cfrp_2017}, XFRP \citep{10.1145/3281366.3281370}, Juniper \citep{helbling_juniper:_2016}, Hailstorm \citep{sarkar_hailstorm_2020}, Haski \citep{valliappan_towards_2020}, arduino-copilot \citep{hess_arduino-copilot_2020}.
-\subsection{\texorpdfstring{\Glsxtrlong{TOP}}{Task-oriented programming}}\label{sec:related_top}
+\subsection{Task-oriented programming}\label{sec:related_top}
\Gls{TOP} as a paradigm has proven to be effective for implementing distributed, multi-user applications in many domains.
Examples are conference management \citep{plasmeijer_conference_2006}, coastal protection \citep{lijnse_capturing_2011}, incident coordination \citep{lijnse_incidone:_2012}, crisis management \citep{jansen_towards_2010} and telemedicine \citep{van_der_heijden_managing_2011}.
In general, \gls{TOP} results in a higher maintainability, a high separation of concerns, and more effective handling of interruptions of workflow.
\Citet{antonova_mtask_2022} compared parts of \gls{MTASK} to the semantics of \gls{TOPHAT} semantics and created a preliminary semantics for a subset of \gls{MTASK}.
Future research into extending the formal semantics of \gls{MTASK} is useful to give more guarantees on \gls{MTASK} programs.
-\subsection{\texorpdfstring{\Glsxtrlong{TOP}}{Task-oriented programming}}
+\subsection{Task-oriented programming}
In order to keep the resource constraints low, the \gls{MTASK} language contains only a minimal set of simple task combinators.
From these simple combinators, complex collaboration patterns can be expressed.
The \gls{ITASK} language is designed exactly the opposite.
\Citet{belwal_variable_2013} use \gls{PFRP} with \gls{DVFS} to reduce the energy consumption.
It is interesting to investigate the possibilities for \gls{DVFS} in \gls{MTASK} and \gls{TOP} in general.
-\section{History of \texorpdfstring{\gls{MTASK}}{mTask}}
+\section{History of mTask}
The development of \gls{MTASK} or its predecessors has been going on for almost seven years now though it really set off during my master's thesis.
Many colleagues and students have worked on aspects of the \gls{MTASK} system in collaborations, internships and Bachelor and Master's theses.
This section provides an exhaustive overview of the work on \gls{MTASK} and its predecessors.
Some time later in the 2015 \gls{CEFP} summer school, an extended version was created that allowed the creation of imperative tasks, local \glspl{SDS} and the usage of functions \citep{koopman_type-safe_2019}.
The name then changed from \gls{ARDSL} to \gls{MTASK}.
-\subsection{Integration with \texorpdfstring{\gls{ITASK}}{iTask}}
+\subsection{Integration with iTask}
\Citet{lubbers_task_2017} extended this in his Master's Thesis by adding integration with \gls{ITASK} and a bytecode compiler to the language.
\Gls{SDS} in \gls{MTASK} could be accessed on the \gls{ITASK} server.
In this way, entire \gls{IOT} systems could be programmed from a single source.
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.
Moreover, a course on the \gls{MTASK} simulator was provided at the 2018 \gls{CEFP}\slash\gls{3COWS} winter school in Ko\v{s}ice, Slovakia \citep{koopman_simulation_2023}.
-\subsection{Transition to \texorpdfstring{\glsxtrlong{TOP}}{Task-oriented programming}}
+\subsection{Transition to Task-oriented programming}
The \gls{MTASK} language as it is now was introduced in 2018 \citep{koopman_task-based_2018}.
This paper updated the language to support functions, simple tasks, and \glspl{SDS} but still compiled to \gls{ARDUINO} \gls{CPP} code.
Later the byte code compiler and \gls{ITASK} integration was added to the language \citep{lubbers_interpreting_2019}.
One reason for this is that a lot of design patterns that are difficult using standard means are for free in \gls{TOP} (e.g.\ multithreading).
In 2019, the \gls{CEFP}\slash\gls{3COWS} summer school in Budapest, Hungary hosted a course on developing \gls{IOT} applications with \gls{MTASK} as well \citep{lubbers_writing_2023}.
-\subsection{\texorpdfstring{\Glsxtrlong{TOP}}{Task-oriented programming}}
+\subsection{Task-oriented programming}
In 2022, the SusTrainable summer school in Rijeka, Croatia hosted a course on developing greener \gls{IOT} applications using \gls{MTASK} \citep{lubbers_green_2022}.
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{\texorpdfstring{\gls{MTASK}}{mTask} in practise}
+\subsection{Using mTask in practise}
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_2022}.
\begin{document}
\input{subfileprefix}
-\chapter{Green computing with \texorpdfstring{\gls{MTASK}}{mTask}}%
+\chapter{Green computing with mTask}%
\label{chp:green_computing_mtask}
\begin{chapterabstract}
This chapter demonstrate the energy-saving features of \gls{MTASK} by:
\endgroup
\end{table}
-\section{Green \texorpdfstring{\glsxtrshort{IOT}}{IoT} computing}
+\section{Green \IOT{} computing}
The data in \cref{tbl:top_sleep} shows that it is worthwhile to put the system in some sleep mode when there is temporarily no work to be done.
A deeper sleep mode saves more energy, but also requires more work to restore the software to its working state.
A processor like the ESP8266 driving the \gls{WEMOS} D1 mini loses the content of its \gls{RAM} in deep sleep mode.
| RangeS (v Int) (v Int) // yields [+$\rewriterate{x \times 1000}{y \times 1000}$+]
\end{lstClean}
-\subsubsection{Sensors and \texorpdfstring{\glspl{SDS}}{shared data sources}}
+\subsubsection{Sensors and shared data sources}
In some applications, it is necessary to read sensors or \glspl{SDS} at a different rate than the default rate given in \cref{tbl:rewrite}, i.e.\ to customise the rewrite rate.
This is achieved by calling the access functions with a custom rewrite rate as an additional argument (suffixed with the backtick (\cleaninline{`}))
The adaptions to other classes are similar and omitted for brevity.
delayTime :: TimingInterval v | mtask v
delayTime = BeforeS (lit 60) // 1 minute in seconds
-devTask :: Main (MTask v Real) | mtask, dht, liftsds v
+devTask :: Main (MTask v Real) | mtask, dht, lowerSds v
devTask =
DHT (DHT_DHT pin DHT11) \dht =
- liftsds \localSds = tempSds
+ lowerSds \localSds = tempSds
In {main = rpeat (temperature` delayTime dht >>~. setSds localSds)}
\end{lstClean}
}
\end{lstClean}
-\section{Task scheduling in the \texorpdfstring{\gls{MTASK}}{mTask} engine}\label{sec:scheduling}
+\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 addition, it has to communicate with a server to collect new tasks and updates of \glspl{SDS}.
}[+\label{lst:arduino_interrupt:isr_to}+]
\end{lstArduino}
-\subsection{The \texorpdfstring{\gls{MTASK}}{mTask} language}
+\subsection{The mTask language}
\Cref{lst:mtask_interrupts} shows the interrupt interface in \gls{MTASK}.
The \cleaninline{interrupt} class contains a single function that, given an interrupt mode and a \gls{GPIO} pin, produces a task that represents this interrupt.
Lowercase variants of the various interrupt modes such as \cleaninline{change :== lit Change} are available as convenience macros (see \cref{sec:expressions}).
>>|. writeD ledpin true) }
\end{lstClean}
-\subsection{The \texorpdfstring{\gls{MTASK}}{mTask} engine}
+\subsection{The mTask engine}
While interrupt tasks have their own node type in the task tree, they differ slightly from other node types because they require a more elaborate setup and teardown.
Enabling and disabling interrupts is done in a general way in which tasks register themselves after creation and deregister after deletion.
\begin{document}
\input{subfileprefix}
-\chapter{The implementation of \texorpdfstring{\gls{MTASK}}{mTask}}%
+\chapter{The implementation of mTask}%
\label{chp:implementation}
\begin{chapterabstract}
This chapter shows the implementation of the \gls{MTASK} system by:
\begin{itemize}
+ \item showing the compilation and execution toolchain;
\item elaborating on the implementation and architecture of the \gls{RTS} of \gls{MTASK};
\item showing the implementation of the byte code compiler for the \gls{MTASK} language;
\item and explaining the machinery used to automatically serialise and deserialise data to-and-fro the device.
The \gls{MTASK} system targets resource-constrained edge devices that have little memory, processor speed, and communication.
Such edge devices are often powered by microcontrollers, tiny computers specifically designed for embedded applications.
The microcontrollers usually have flash-based program memory which wears out fairly quickly.
-For example, the flash memory of the popular atmega328p powering the \gls{ARDUINO} UNO is rated for 10000 write cycles.
+For example, the flash memory of the popular atmega328p powering the \gls{ARDUINO} UNO is rated for \num{10000} write cycles.
While this sounds like a lot, if new tasks are sent to the device every minute or so, a lifetime of only seven days is guaranteed.
Hence, for dynamic applications, storing the program in the \gls{RAM} of the device and interpreting this code is necessary in order to save precious write cycles of the program memory.
In the \gls{MTASK} system, the \gls{MTASK} \gls{RTS}, a domain-specific \gls{OS}, is responsible for interpreting the programs.
-\section{\texorpdfstring{\Glsxtrlong{RTS}}{Run time system}}
+Programs in \gls{MTASK} are \gls{DSL} terms constructed at run time in an \gls{ITASK} system.
+\Cref{fig:toolchain} shows the compilation and execution toolchain of such programs.
+First, the source code is compiled to a byte code specification, this specification contains the compiled main expression, the functions, and the \gls{SDS} and peripheral configuration.
+How an \gls{MTASK} task is compiled to this specification is shown in \cref{sec:compiler_imp}.
+This package is then sent to the \gls{RTS} of the device for execution, shown in \cref{sec:compiler_rts}.
+On the device, the \gls{RTS} may have multiple tasks at the same time active.
+
+\begin{figure}
+ \centering
+ \centerline{\includestandalone{toolchain}}
+ \caption{Compilation and execution toolchain of \gls{MTASK} programs.}%
+ \label{fig:toolchain}
+\end{figure}
+
+\section{Run-time system}\label{sec:compiler_rts}
The \gls{RTS} is a customisable domain-specific \gls{OS} that takes care of the execution of tasks.
Furthermore, it also takes care of low-level mechanisms such as the communication, multitasking, and memory management.
Once a device is programmed with the \gls{MTASK} \gls{RTS}, it can continuously receive new tasks without the need for reprogramming.
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}, the \gls{RTS} of the \gls{MTASK} system is implemented as such also.
-It consists of a loop function with a relatively short execution time, similar to the one in \gls{ARDUINO}, that gets called repeatedly.
+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.
+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.
After doing the three phases, the devices goes to sleep for as long as possible (see \cref{chp:green_computing_mtask} for more details on task scheduling).
This combinator has a \cleaninline{writeD} task at the left-hand side that becomes stable after one rewrite step in which it writes the value to the given pin.
When \cleaninline{writeD} becomes stable, the written value is the task value that is observed by the right-hand side of the \cleaninline{>>=.} combinator.
This will call the interpreter to evaluate the expression, now that the argument of the function is known.
-The result of the function is the original task tree again, but now with the state inversed.
+The result of the function is again a task tree, but now with different arguments to the tasks, e.g.\ the state in \cleaninline{writeD} is inversed.
\begin{figure}
\centering
For task trees---stored in the heap---the \gls{RTS} already marks tasks and task trees as trash during rewriting so the heap can be compacted in a single pass.
This is possible because there is no sharing or cycles in task trees and nodes contain pointers pointers to their parent.
-\section{Compiler}
+\section{Compiler}\label{sec:compiler_imp}
\subsection{Compiler infrastructure}
The bytecode compiler interpretation for the \gls{MTASK} language is implemented as a monad stack containing a writer monad and a state monad.
The writer monad is used to generate code snippets locally without having to store them in the monadic values.
context (see \cref{ssec:step});
code for the functions;
next fresh label;
-a list of all the used \glspl{SDS}, either local \glspl{SDS} containing the initial value (\cleaninline{Left}) or lifted \glspl{SDS} (see \cref{sec:liftsds}) containing a reference to the associated \gls{ITASK} \gls{SDS};
+a list of all the used \glspl{SDS}, either local \glspl{SDS} containing the initial value (\cleaninline{Left}) or lowered \glspl{SDS} (see \cref{sec:liftsds}) containing a reference to the associated \gls{ITASK} \gls{SDS};
and finally there is a list of peripherals used.
\begin{lstClean}[label={lst:compiler_state},caption={The type for the \gls{MTASK} byte code compiler.}]
For example, the \cleaninline{BCArg} instruction is often called with argument \numrange{0}{2} and can be replaced by the \numrange[parse-numbers=false]{\cleaninline{BCArg0}}{\cleaninline{BCArg2}} shorthands.
Furthermore, redundant instructions such as pop directly after push are removed as well in order not to burden the code generation with these intricacies.
Finally the labels are resolved to represent actual program addresses instead of the freshly generated identifiers.
-After the byte code is ready, the lifted \glspl{SDS} are resolved to provide an initial value for them.
+After the byte code is ready, the lowered \glspl{SDS} are resolved to provide an initial value for them.
The byte code, \gls{SDS} specification and perpipheral specifications are the result of the process, ready to be sent to the device.
\subsection{Instruction set}
...
\end{lstClean}
-
\section{Compilation rules}
This section describes the compilation rules, the translation from \gls{AST} to byte code.
The compilation scheme consists of three schemes\slash{}functions.
First the context is evaluated.
The context contains arguments from functions and steps that need to be preserved after rewriting.
The evaluated context is combined with the left-hand side task value by means of a \cleaninline{.&&.} combinator to store it in the task tree so that it is available after a rewrite.
-This means that the task tree is be transformed as follows as
+This means that the task tree is be transformed as seen in \cref{lst:context_tree}.
\begin{figure}
\begin{subfigure}{.5\textwidth}
\includestandalone{contexttree1}
-
- \end{subfigure}
+ \caption{Without the embedded context.}
+ \end{subfigure}%
\begin{subfigure}{.5\textwidth}
\includestandalone{contexttree2}
+ \caption{With the embedded context.}
\end{subfigure}
+ \caption{Context embedded in a task tree.}%
+ \label{lst:context_tree}
\end{figure}
The translation to \gls{CLEAN} is given in \cref{lst:imp_seq}.
val = retrieveArgs steplabel zero lhswidth
\end{lstClean}
-\subsection{\texorpdfstring{\Glspl{SDS}}{Shared data sources}}
+\subsection{Shared data sources}\label{lst:imp_sds}
The compilation scheme for \gls{SDS} definitions is a trivial extension to $\mathcal{F}$ since there is no code generated as seen below.
\begin{align*}
{} & \mathbin{\phantom{=}} \text{\cleaninline{BCMkTask}} (\text{\cleaninline{BCSdsSet}} s);\\
\end{align*}
-While there is no code generated in the definition, the byte code compiler is storing the \gls{SDS} data in the \cleaninline{bcs_sdses} field in the compilation state.
+While there is no code generated in the definition, the byte code compiler is storing all \gls{SDS} data in the \cleaninline{bcs_sdses} field in the compilation state.
+Regular \glspl{SDS} are stored as \cleaninline{Right String255} values.
The \glspl{SDS} are typed as functions in the host language so an argument for this function must be created that represents the \gls{SDS} on evaluation.
For this, an \cleaninline{BCInterpret} is created that emits this identifier.
When passing it to the function, the initial value of the \gls{SDS} is returned.
-This initial value is stored as a byte code encoded value in the state and the compiler continues with the rest of the program.
+In the case of a local \gls{SDS}, this initial value is stored as a byte code encoded value in the state and the compiler continues with the rest of the program.
+\Cref{lst:comp_sds} shows the implementation of the \cleaninline{sds} type class.
First, the initial \gls{SDS} value is extracted from the expression by bootstrapping the fixed point with a dummy value.
This is safe because the expression on the right-hand side of the \cleaninline{In} is never evaluated.
Then, using \cleaninline{addSdsIfNotExist}, the identifier for this particular \gls{SDS} is either retrieved from the compiler state or generated freshly.
This identifier is then used to provide a reference to the \cleaninline{def} definition to evaluate the main expression.
Compiling \cleaninline{getSds} is a matter of executing the \cleaninline{BCInterpret} representing the \gls{SDS}, which yields the identifier that can be embedded in the instruction.
-Lifted SDSs are compiled in a very similar way \cref{sec:liftsds}.
Setting the \gls{SDS} is similar: the identifier is retrieved and the value is written to put in a task tree so that the resulting task can remember the value it has written.
% VimTeX: SynIgnore on
\end{lstClean}
% VimTeX: SynIgnore off
-\section{\texorpdfstring{\Gls{C}}{C} code generation}\label{sec:ccodegen}
-All communication between the \gls{ITASK} server and the \gls{MTASK} server is type-parametrised.
+Lowered \glspl{SDS} are stored in the compiler state as \cleaninline{Right MTLens} values.
+The compilation of the code and the serialisation of the data throws away all typing information.
+The \cleaninline{MTLens} is a type synonym for \pgls{SDS} that represents the typeless serialised value of the underlying \gls{SDS}.
+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 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.
+\Cref{lst:mtask_itasksds_lens} shows the implementation for this.
+
+% VimTeX: SynIgnore on
+\begin{lstClean}[label={lst:mtask_itasksds_lens},caption={Lens applied to lowered \gls{ITASK} \glspl{SDS} in \gls{MTASK}.}]
+lens :: (Shared sds a) -> MTLens | type a & RWShared sds
+lens sds = mapReadWriteError
+ ( \r-> Ok (fromString (toByteCode{|*|} r)
+ , \w r-> ?Just <$> iTasksDecode (toString w)
+ ) ?None sds
+\end{lstClean}
+% VimTeX: SynIgnore off
+
+\Cref{lst:mtask_itasksds_lift} shows the code for the implementation of \cleaninline{lowerSds} that uses the \cleaninline{lens} function shown earlier.
+It is very similar to the \cleaninline{sds} constructor in \cref{lst:comp_sds}, only now a \cleaninline{Right} value is inserted in the \gls{SDS} administration.
+
+% VimTeX: SynIgnore on
+\begin{lstClean}[label={lst:mtask_itasksds_lift},caption={The implementation for lowering \glspl{SDS} in \gls{MTASK}.}]
+instance lowerSds BCInterpret where
+ lowerSds def = {main =
+ let (t In _) = def (abort "lowerSds: expression too strict")
+ in addSdsIfNotExist (Right $ lens t)
+ >>= \sdsi->let (_ In e) = def (pure (Sds sdsi)) in e.main
+ }\end{lstClean}
+% VimTeX: SynIgnore off
+
+\section{C code generation}\label{sec:ccodegen}
+All communication between the \gls{ITASK} server and the \gls{MTASK} server is type parametrised.
From the structural representation of the type, a \gls{CLEAN} parser and printer is constructed using generic programming.
Furthermore, a \ccpp{} parser and printer is generated for use on the \gls{MTASK} device.
The technique for generating the \ccpp{} parser and printer is very similar to template metaprogramming and requires a rich generic programming library or compiler support that includes a lot of metadata in the record and constructor nodes.
\begin{document}
\input{subfileprefix}
-\chapter{Integration of \texorpdfstring{\gls{MTASK}}{mTask} and \texorpdfstring{\gls{ITASK}}{iTask}}%
+\chapter{Integration of mTask and iTask}%
\label{chp:integration_with_itask}
\begin{chapterabstract}
This chapter shows the integration of \gls{MTASK} and \gls{ITASK} by showing:
\end{chapterabstract}
The \gls{MTASK} language is a multi-view \gls{DSL}, there are multiple interpretations possible for a single \gls{MTASK} term.
-When using the byte code compiler (\cleaninline{BCInterpret}) \gls{DSL} interpretation, \gls{MTASK} tasks are fully integrated in \gls{ITASK}.
+When using the byte code compiler (\cleaninline{:: BCInterpret a}) \gls{DSL} interpretation, \gls{MTASK} tasks are fully integrated in \gls{ITASK}.
They execute as regular \gls{ITASK} tasks and they can access \glspl{SDS} from \gls{ITASK}.
Devices in the \gls{MTASK} system are set up with a domain-specific \gls{OS} and become little \gls{TOP} engines in their own respect, being able to execute tasks.
failover [] _ = throw "Exhausted device pool"
failover [d:ds] mtask = try (withDevice d (liftmTask mtask)) except
where except MTEUnexpectedDisconnect = failover ds mtask
- except _ = throw e
+ except _ = throw e
\end{lstClean}
-\section{Lifting \texorpdfstring{\gls{MTASK}}{mTask} tasks}\label{sec:liftmtask}
+\section{Lifting mTask tasks}\label{sec:liftmtask}
Once the connection with the device is established, \gls{MTASK} tasks are lifted to \gls{ITASK} tasks using the \cleaninline{liftmTask} function (see \cref{lst:liftmtask}).
Given an \gls{MTASK} task in the \cleaninline{BCInterpret} view and a device handle obtained from \cleaninline{withDevice}, an \gls{ITASK} task is returned.
This \gls{ITASK} task proxies the \gls{MTASK} task that is executed on the microcontroller.
preloadTask :: (Main (MTask BCInterpret a)) -> Task String
\end{lstClean}
-\section{Lowering \texorpdfstring{\gls{ITASK}}{iTask} \texorpdfstring{\glsxtrlongpl{SDS}}{shared data sources}}\label{sec:liftsds}
+\section{Lowering iTask shared data sources}\label{sec:liftsds}
Lowering \gls{ITASK} \glspl{SDS} to \gls{MTASK} \glspl{SDS} is something that mostly happens at the \gls{DSL} level using the \cleaninline{lowerSds} function (see \cref{lst:mtask_itasksds}).
Lowering \pgls{SDS} proxies the \gls{ITASK} \gls{SDS} for use in \gls{MTASK}.
\Glspl{SDS} in \gls{MTASK} always have an initial value.
On the device, there is just one difference between lowered \glspl{SDS} and regular \glspl{SDS}: after changing a lowered \gls{SDS}, a message is sent to the server containing this new value.
The \cleaninline{withDevice} task (see \cref{sec:withdevice}) receives and processes this message by writing to the \gls{ITASK} \gls{SDS}.
Tasks watching this \gls{SDS} get notified then through the normal notification mechanism of \gls{ITASK}.
+\Cref{lst:imp_sds} shows the implementation of this type class for the byte code compiler.
\begin{lstClean}[label={lst:mtask_itasksds},caption={Lowered \gls{ITASK} \glspl{SDS} in \gls{MTASK}.}]
class lowerSds v where
In {main=f true}
\end{lstClean}
-\subsection{Implementation}
-The compilation of the code and the serialisation of the data throws away all typing information.
-\Glspl{SDS} are stored in the compiler state as a map from identifiers to either an initial value or an \cleaninline{MTLens}.
-The \cleaninline{MTLens} is a type synonym for \pgls{SDS} that represents the typeless serialised value of the underlying \gls{SDS}.
-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 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.
-\Cref{lst:mtask_itasksds_lens} shows the implementation for this.
-
-% VimTeX: SynIgnore on
-\begin{lstClean}[label={lst:mtask_itasksds_lens},caption={Lens applied to lowered \gls{ITASK} \glspl{SDS} in \gls{MTASK}.}]
-lens :: (Shared sds a) -> MTLens | type a & RWShared sds
-lens sds = mapReadWriteError
- ( \r-> Ok (fromString (toByteCode{|*|} r)
- , \w r-> ?Just <$> iTasksDecode (toString w)
- ) ?None sds
-\end{lstClean}
-% VimTeX: SynIgnore off
-
-\Cref{lst:mtask_itasksds_lift} shows the code for the implementation of \cleaninline{lowerSds} that uses the \cleaninline{lens} function shown earlier.
-First, the \gls{SDS} to be lowered is extracted from the expression by bootstrapping the fixed point with a dummy value.
-This is safe because the expression on the right-hand side of the \cleaninline{In} is never evaluated.
-Then, using \cleaninline{addSdsIfNotExist}, the identifier for this particular \gls{SDS} is either retrieved from the compiler state or generated freshly.
-This identifier is then used to provide a reference to the \cleaninline{def} definition to evaluate the main expression.
-
-% VimTeX: SynIgnore on
-\begin{lstClean}[label={lst:mtask_itasksds_lift},caption={The implementation for lowering \glspl{SDS} in \gls{MTASK}.}]
-instance lowerSds BCInterpret where
- lowerSds def = {main =
- let (t In _) = def (abort "lowerSds: expression too strict")
- in addSdsIfNotExist (Right $ lens t)
- >>= \sdsi->let (_ In e) = def (pure (Sds sdsi)) in e.main
- }\end{lstClean}
-% VimTeX: SynIgnore off
-
\section{Conclusion}
When \gls{IOT} edge devices run the \gls{MTASK} \gls{RTS}, they become little \gls{TOP} engines of their own.
Using just three \gls{ITASK} functions, \gls{MTASK} devices are integrated in \gls{ITASK} seamlessly.
All details regarding interoperation are automatically taken care of.
The following section contains an elaborate example using all integration functions that has deliberately been placed after the conclusion so that the code listing and description are on facing pages.
-\begin{figure}[p]
- \begin{leftfullpage}
- \vspace{\headsep}
-\section{Home automation}
-This section presents an interactive home automation program (\cref{lst:example_home_automation}) to illustrate the integration of the \gls{MTASK} language and the \gls{ITASK} system.
-It consists of a web interface for the user to control which tasks are executed on either one of two connected devices: an \gls{ARDUINO} UNO, connected via a serial port; and an ESP8266 based prototyping board called NodeMCU, connected via \gls{TCP} over \gls{WIFI}.
-
-\Crefrange{lst:example:spec1}{lst:example:spec2} show the specification for the devices.
-The UNO is connected via serial using the unix filepath \path{/dev/ttyACM0} and the default serial port settings.
-The NodeMCU is connected via \gls{WIFI} and hence the \cleaninline{TCPSettings} record is used.
-Both types have \cleaninline{channelSync} instances.
-
-The code consists of an \gls{ITASK} part and several \gls{MTASK} parts.
-\Crefrange{lst:example:task1}{lst:example:task2} contains the \gls{ITASK} task that coordinates the \gls{IOT} application.
-First the devices are connected (\crefrange{lst:example:conn1}{lst:example:conn2}) followed by launching a \cleaninline{parallel} task, visualized as a tabbed window, and a shutdown button to terminate the program (\crefrange{lst:example:par1}{lst:example:par2}).
-This parallel task is the controller of the tasks that run on the edge devices.
-It contains one task that allows adding new tasks (using \cleaninline{appendTask}) and all other tasks in the process list will be \gls{MTASK} tasks once they are added by the user.
-The controller task, \cleaninline{chooseTask} as shown in \crefrange{lst:example:ct1}{lst:example:ct2}, allows the user to pick a task, and sending it to the specified device.
-Tasks are picked by index from the \cleaninline{tasks} list (\crefrange{lst:example:tasks1}{lst:example:tasks2}) using \cleaninline{enterChoice}.
-The interface that is generated for this is seen in \cref{fig:example_screenshots1}.
-After selecting the task, a device is selected (see \cref{fig:example_screenshots2,lst:example:selectdev}).
-When both a task and a device are selected, an \gls{ITASK} task is added to the process list using \cleaninline{appendTask}.
-Using the helper function \cleaninline{mkTask}, the actual task is selected from the \cleaninline{tasks} list and executed by providing it the device argument.
-For example, when selecting the \cleaninline{temperature} task, the current temperature is shown to the user (\cref{fig:example_screenshots3}).
-This task just sends a simple temperature monitoring task to the device using \cleaninline{liftmTask} and provides a view on its task value using the \cleaninline{>\&>} \gls{ITASK} combinator.
-This combinator allows the observation of the left-hand side task's value through \pgls{SDS}.
-The light switch task at \crefrange{lst:example:ls1}{lst:example:ls2} is a task that has bidirectional interaction using the definition of \cleaninline{lightswitch} shown in \cref{lst:mtask_liftsds_ex}.
-Using \cleaninline{liftsds}, the status of the light switch is synchronised with the user.
-Finally, a task that calculates the factorial of a user-provided number is shown in the list.
-
- \vspace{4ex}
- \begin{center}
- \begin{subfigure}[b]{.3\linewidth}
- \includegraphics[width=\linewidth]{home_auto1}
- \caption{Select task.}%
- \label{fig:example_screenshots1}
- \end{subfigure}
- \begin{subfigure}[b]{.3\linewidth}
- \includegraphics[width=\linewidth]{home_auto2}
- \caption{Select device.}%
- \label{fig:example_screenshots2}
- \end{subfigure}
- \begin{subfigure}[b]{.3\linewidth}
- \includegraphics[width=\linewidth]{home_auto3}
- \caption{View result.}%
- \label{fig:example_screenshots3}
- \end{subfigure}
- \caption{Screenshots of the home automation example program in action.}%
- \label{fig:example_screenshots}
- \end{center}
- \end{leftfullpage}
-\end{figure}
-
-\begin{figure}[p]
- \begin{fullpage}
- \cleaninputlisting[firstline=12,lastline=50,numbers=left,belowskip=0pt]{lst/example.icl}
- \begin{lstClean}[numbers=left,firstnumber=40,aboveskip=0pt,caption={An example of a home automation program.},label={lst:example_home_automation}]
- , ...][+\label{lst:example:tasks2}+]\end{lstClean}
- \end{fullpage}
-\end{figure}
+%\begin{figure}[p]
+% \begin{leftfullpage}
+% \vspace{\headsep}
+%\section{Home automation}
+%This section presents an interactive home automation program (\cref{lst:example_home_automation}) to illustrate the integration of the \gls{MTASK} language and the \gls{ITASK} system.
+%It consists of a web interface for the user to control which tasks are executed on either one of two connected devices: an \gls{ARDUINO} UNO, connected via a serial port; and an ESP8266 based prototyping board called NodeMCU, connected via \gls{TCP} over \gls{WIFI}.
+%
+%\Crefrange{lst:example:spec1}{lst:example:spec2} show the specification for the devices.
+%The UNO is connected via serial using the unix filepath \path{/dev/ttyACM0} and the default serial port settings.
+%The NodeMCU is connected via \gls{WIFI} and hence the \cleaninline{TCPSettings} record is used.
+%Both types have \cleaninline{channelSync} instances.
+%
+%The code consists of an \gls{ITASK} part and several \gls{MTASK} parts.
+%\Crefrange{lst:example:task1}{lst:example:task2} contains the \gls{ITASK} task that coordinates the \gls{IOT} application.
+%First the devices are connected (\crefrange{lst:example:conn1}{lst:example:conn2}) followed by launching a \cleaninline{parallel} task, visualized as a tabbed window, and a shutdown button to terminate the program (\crefrange{lst:example:par1}{lst:example:par2}).
+%This parallel task is the controller of the tasks that run on the edge devices.
+%It contains one task that allows adding new tasks (using \cleaninline{appendTask}) and all other tasks in the process list will be \gls{MTASK} tasks once they are added by the user.
+%The controller task, \cleaninline{chooseTask} as shown in \crefrange{lst:example:ct1}{lst:example:ct2}, allows the user to pick a task, and sending it to the specified device.
+%Tasks are picked by index from the \cleaninline{tasks} list (\crefrange{lst:example:tasks1}{lst:example:tasks2}) using \cleaninline{enterChoice}.
+%The interface that is generated for this is seen in \cref{fig:example_screenshots1}.
+%After selecting the task, a device is selected (see \cref{fig:example_screenshots2,lst:example:selectdev}).
+%When both a task and a device are selected, an \gls{ITASK} task is added to the process list using \cleaninline{appendTask}.
+%Using the helper function \cleaninline{mkTask}, the actual task is selected from the \cleaninline{tasks} list and executed by providing it the device argument.
+%For example, when selecting the \cleaninline{temperature} task, the current temperature is shown to the user (\cref{fig:example_screenshots3}).
+%This task just sends a simple temperature monitoring task to the device using \cleaninline{liftmTask} and provides a view on its task value using the \cleaninline{>\&>} \gls{ITASK} combinator.
+%This combinator allows the observation of the left-hand side task's value through \pgls{SDS}.
+%The light switch task at \crefrange{lst:example:ls1}{lst:example:ls2} is a task that has bidirectional interaction using the definition of \cleaninline{lightswitch} shown in \cref{lst:mtask_liftsds_ex}.
+%Using \cleaninline{lowerSds}, the status of the light switch is synchronised with the user.
+%Finally, a task that calculates the factorial of a user-provided number is shown in the list.
+%
+% \vspace{4ex}
+% \begin{center}
+% \begin{subfigure}[b]{.3\linewidth}
+% \includegraphics[width=\linewidth]{home_auto1}
+% \caption{Select task.}%
+% \label{fig:example_screenshots1}
+% \end{subfigure}
+% \begin{subfigure}[b]{.3\linewidth}
+% \includegraphics[width=\linewidth]{home_auto2}
+% \caption{Select device.}%
+% \label{fig:example_screenshots2}
+% \end{subfigure}
+% \begin{subfigure}[b]{.3\linewidth}
+% \includegraphics[width=\linewidth]{home_auto3}
+% \caption{View result.}%
+% \label{fig:example_screenshots3}
+% \end{subfigure}
+% \caption{Screenshots of the home automation example program in action.}%
+% \label{fig:example_screenshots}
+% \end{center}
+% \end{leftfullpage}
+%\end{figure}
+%
+%\begin{figure}[p]
+% \begin{fullpage}
+% \cleaninputlisting[firstline=12,lastline=50,numbers=left,belowskip=0pt]{lst/example.icl}
+% \begin{lstClean}[numbers=left,firstnumber=40,aboveskip=0pt,caption={An example of a home automation program.},label={lst:example_home_automation}]
+% , ...][+\label{lst:example:tasks2}+]\end{lstClean}
+% \end{fullpage}
+%\end{figure}
\input{subfilepostamble}
\end{document}
\begin{document}
\input{subfileprefix}
-\chapter{The \texorpdfstring{\gls{MTASK}}{mTask} language}%\texorpdfstring{\glsxtrshort{DSL}}{DSL}}%
+\chapter{The mTask language}%
\label{chp:mtask_dsl}
\begin{chapterabstract}
This chapter introduces the \gls{TOP} language \gls{MTASK} by:
:: Main a = { main :: a }
:: In a b = (In) infix 0 a b
-someTask :: MTask v Int | mtask v & liftsds v & sensor1 v & ...
+someTask :: MTask v Int | mtask v & lowerSds v & sensor1 v & ...
someTask =
sensor1 config1 \sns1->
sensor2 config2 \sns2->
- sds \s1 = initialValue
- In liftsds \s2 = someiTaskSDS
- In fun \fun1= ( \(a0, a1)->... )
- In fun \fun2= ( \a->... )
+ sds \s1 = initialValue
+ In lowerSds \s2 = someiTaskSDS
+ In fun \fun1= ( \(a0, a1)->... )
+ In fun \fun2= ( \a->... )
In { main = mainexpr }
\end{lstClean}
% VimTeX: SynIgnore off
{main = rpeat (readA a1 >>~. writeA a2 >>|. delay (lit 1000))}
\end{lstClean}
-\subsection{\texorpdfstring{\Glsxtrlongpl{SDS}}{Shared data sources}}
+\subsection{Shared data sources}
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 data with other tasks.
\documentclass[tikz]{standalone}
-%\usepackage{listings}
-%\lstset{%
-% basewidth=0.5em,
-% basicstyle=\tt\scriptsize,
-% breakatwhitespace=false,
-% breaklines=true,
-% captionpos=b,
-% columns=[c]fixed,
-% commentstyle=\sl,
-% escapeinside={[+}{+]}, % chktex 9
-% frame=,
-% keepspaces=true,
-% keywordstyle=\bf,
-% showspaces=false,
-% showstringspaces=false,
-% showtabs=false,
-% stringstyle=\it,
-% tabsize=4,
-% numberstyle=\tiny,
-% language=C,
-%}
\usetikzlibrary{arrows.meta,shapes.symbols,matrix,positioning}
\begin{document}
\begin{tikzpicture}[%
\matrix (main) [memory] {
& |[descr]| {\rm high addresses} \\
& || heap\\
- & || $\downarrow$\\
+ & || {\normalsize $\downarrow$}\\
& || \ldots\\
- & || $\uparrow$\\
+ & || {\normalsize $\uparrow$}\\
& || stack\\
- & || $\uparrow$ \\
+ & || {\normalsize $\uparrow$}\\
& || tasks \\
& |[descr]| {\rm low addresses}\\
};
\draw [<->] (T1) -- (S2);
\draw [<->] (T1) -- (Sn);
- \draw [<->] (Tn) -- node [midway,above,fill=white] {\small\texttt{liftmTask}} (D2T1);
- \draw [<->] (Sn) -- node [midway,above,fill=white] {\small\texttt{lowersds}} (D2S1);
+ \draw [<->] (Tn) -- node [midway,above,fill=white] {\texttt{liftmTask}} (D2T1);
+ \draw [<->] (Sn) -- node [midway,above,fill=white] {\texttt{lowerSds}} (D2S1);
\draw [<->] (D1T1) -- (D1S1);
\draw [<->] (D2T1) -- (D2S1);
\draw [<->] (DNT1) -- (DNS1);
- \draw [<->] (D1.north) to [in=180,out=135] node [midway,above,fill=white] {\small\texttt{withDevice}} (TS.west);
+ \draw [<->] (D1.north) to [in=180,out=135] node [midway,above,fill=white] {\texttt{withDevice}} (TS.west);
\end{tikzpicture}
\end{document}
--- /dev/null
+\documentclass[tikz]{standalone}
+\usepackage{stmaryrd}
+\usepackage{listings}
+
+\usepackage{../preamble/lstlangclean}
+\usetikzlibrary{arrows.meta,shapes.symbols,matrix,positioning,calc,fit}
+\begin{document}
+\begin{tikzpicture}
+ \node [draw,label=above:{Clean source code}] (src) {
+\begin{lstlisting}[language=Clean,
+ basewidth=0.5em,
+ basicstyle=\tt\scriptsize,
+ breakatwhitespace=false,
+ breaklines=true,
+ backgroundcolor=,
+ commentstyle=\sl,
+ frame=,
+ keepspaces=true,
+ keywordstyle=\bf,
+ showspaces=false,
+ showstringspaces=false,
+ showtabs=false,
+ stringstyle=\it,
+ tabsize=2]
+someTask :: MTask v Int | ...
+someTask =
+ sensor1 config1 \sns1->
+ sensor2 config2 \sns2->
+ sds \s1 = initialValue
+ In lowerSds \s2 = someiTaskSDS
+ In fun \fun1= ( \(a0, a1)->...)
+ In fun \fun2= ( \a->...)
+ In { main = mainexpr }
+\end{lstlisting}
+ };
+
+ \node (bc) [draw,node distance=4em,right=of src,label=above:{Byte code}] {
+ \scriptsize
+\begin{tabular}{ll}
+ \verb|main:| & \ldots\\
+ & \ldots\\
+ \verb|fun0:| & \ldots\\
+ & \ldots\\
+ \verb|fun1:| & \ldots\\
+ & \ldots\\
+ \verb|sds0:| & \ldots\\
+ \verb|sds1:| & \ldots\\
+ \verb|periph0:| & \ldots\\
+ \verb|periph1:| & \ldots\\
+\end{tabular}
+};
+ \draw [->] (src) to node [midway,above] {compile} (bc);
+
+ \matrix (m) [node distance=4em,right=of bc,matrix of nodes,nodes in empty cells,row sep=1em] {
+ Interpreter & Rewriter\\
+ \verb|main|\\
+ tree & tree\\
+ & \\
+ & tree\\
+ };
+ \draw [->] (m-2-1) -- (m-3-1);
+ \draw [->] (m-3-1) -- (m-3-2);
+ \draw [->] (m-3-2) -- (m-4-2.north) -- (m-4-1.north) -- (m-4-1.south) -- (m-4-2.south) -- (m-5-2);
+ \draw [dashed]($(m-1-1.north)!0.5!(m-1-2.north)$) -- ($(m-5-1.south)!0.5!(m-5-2.south)$);
+ \draw [->] (m-5-2) to [out=0,in=0] (m-3-2);
+
+ \node (dev) [draw,fit=(m),label=above:{Device}] {};
+ \draw [dashed,->] (bc) to node [midway,above] {send} (dev);
+% \node (int) [block,node distance=5em,right=of bc.north] {Interpreter};
+% \node (rew) [block,node distance=1em,right=of int] {Rewrite engine};
+% \node (main) [block,node distance=.5em,below=of int] {\verb|main|};
+% \node (t1) [block,node distance=.5em,below=of main] {tree};
+% \node (t2) [block,node distance=1em,right=of t1] {tree};
+% \node (t3) [block,node distance=.5em,below=of t2] {};
+% \node (t4) [block,node distance=1em,left=of t3] {};
+% \node (t5) [block,node distance=.5em,below=of t4] {};
+% \node (t6) [block,node distance=1em,right=of t5] {};
+% \node (t7) [block,node distance=.5em,below=of t6] {tree};
+%
+% \draw [->] (main) -- (t1);
+% \draw [->] (t1) -- (t2);
+% \draw [->] (t2) -- (t3) -- (t4) -- (t5) -- (t6) -- (t7);
+% %\node (dev) [draw,fit right=of bc,label=above:{Device}] {};
+\end{tikzpicture}
+\end{document}
\begin{document}
\input{subfileprefix}
-\chapter{Could tierless languages reduce \texorpdfstring{\glsxtrshort{IOT}}{IoT} development grief?}%
+\chapter{Could tierless languages reduce IoT development grief?}%
\label{chp:smart_campus}
\begin{chapterabstract}
\section{Background and related work}%
\label{sec_t4t:Background}
-\subsection{\texorpdfstring{\Glsxtrlong{UOG}}{University of Glasgow} smart campus}%
+\subsection{University of Glasgow smart campus}%
\label{sec_t4t:UoGSmartCampus}
% Jeremy
The \gls{UOG} is partway through a ten-year campus
A longitudinal study of sensor accuracy has also been
conducted \citep{harth_predictive_2018}.
-\subsection{\texorpdfstring{\Glsxtrlong{IOT}}{IoT} applications}%
+\subsection{\IOT{} applications}%
\label{sec_t4t:Stacks}
Web applications are necessarily complex distributed systems, with client browsers interacting with a remote webserver and data store. Typical \gls{IOT} applications
\end{figure}
\end{landscape}
-\subsection{The benefits and challenges of developing tiered \texorpdfstring{\glsxtrshort{IOT}}{IoT} stacks}
+\subsection{The benefits and challenges of developing tiered \IOT{} stacks}
Using multiple tiers to
structure complex software is a common software engineering practice that provides significant architectural benefits for \gls{IOT} and other software. The tiered \gls{PYTHON} \gls{PRS} and \gls{PWS} stacks exhibit these benefits.
An example tierless web framework that uses a \gls{DSL} is Haste \citep{10.1145/2775050.2633367}, that embeds the \gls{DSL} in \gls{HASKELL}. Haste programs are compiled multiple times: the server code is generated by the standard \gls{GHC} \gls{HASKELL} compiler \citep{hall1993glasgow}; Javascript for the client is generated by a custom \gls{GHC} compiler backend. The design leverages \gls{HASKELL}'s high-level programming abstractions and strong typing, and benefits from \gls{GHC}: a mature and sophisticated compiler.
-\subsection{Tierless \texorpdfstring{\glsxtrshort{IOT}}{IoT} languages}
+\subsection{Tierless \IOT{} languages}
The use of tierless languages in \gls{IOT} applications is both more recent and less common than for web applications.
Tierless \gls{IOT} programming may extend tierless web programming by adding network and perception layers.
The presentation layer of a tierless \gls{IOT} language, like tierless web languages, benefits from almost invariably executing in a standard browser. The perception layer faces greater challenges, often executing on one of a set of slow and resource-constrained microcontrollers. Hence, tierless \gls{IOT} languages typically compile the perception layer to either \ccpp{} (the lingua franca of microcontrollers), or to some intermediate representation to be interpreted.
-\subsubsection{\texorpdfstring{\Glsxtrlongpl{DSL}}{DSLs} for microcontrollers}
+\subsubsection{DSLs for microcontrollers}
Many \glspl{DSL} provide high-level programming for microcontrollers, for example providing strong typing and memory safety.
For example Copilot \citep{hess_arduino-copilot_2020}
and Ivory \citep{elliott_guilt_2015} are imperative \glspl{DSL} embedded in a functional language that compile to \ccpp{}. In contrast to \cimtask{} such \glspl{DSL} are not tierless \gls{IOT} languages as they have no automatic integration with the server, i.e.\ with the application and presentation layers.
-\subsubsection{\texorpdfstring{\Glsxtrlong{FRP}}{Functional reactive programming}}
+\subsubsection{Functional reactive programming}
\Gls{FRP} is a declarative paradigm often used for implementing the perception layer of an \gls{IOT} stack.
Examples include mfrp \citep{sawada_emfrp:_2016}, CFRP \citep{suzuki_cfrp_2017}, XFRP \citep{10.1145/3281366.3281370}, Juniper \citep{helbling_juniper:_2016}, Hailstorm \citep{sarkar_hailstorm_2020}, and Haski \citep{valliappan_towards_2020}.
None of these languages are tierless \gls{IOT} languages as they have no automatic integration with the server.
TOP allows for more complex collaboration patterns than \gls{FRP} \citep{wang_maintaining_2018}, and in consequence is unable to provide the strong guarantees on memory usage available in a restricted variant of \gls{FRP} such as arrowized \gls{FRP} \citep{nilsson_functional_2002}.
-\subsubsection{Erlang\slash{}Elixir \texorpdfstring{\glsxtrshort{IOT}}{IoT} systems}
+\subsubsection{Erlang\slash{}Elixir \IOT{} systems}
A number of production \gls{IOT} systems are engineered in Erlang or Elixir, and many are mostly tierless.
That is the perception, network and application layers are sets of distributed Erlang processes, although the presentation layer typically uses some conventional web technology.
A resource-rich sensor node may support many Erlang processes on an Erlang VM, or low level code (typically \ccpp{}) on a resource-constrained microcontroller can emulate an Erlang process.
Only a small fraction of these systems are described in the academic literature, example exceptions are \citep{sivieri2012drop,shibanai_distributed_2018}, with many described only in grey literature or not at all.
-\subsection{Characteristics of tierless \texorpdfstring{\glsxtrshort{IOT}}{IoT} languages}%
+\subsection{Characteristics of tierless \IOT{} languages}%
\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.
\Citask{} and \cimtask{} are typical in this respect: little effort has yet been expended on improving their security. Of course as tierless languages they benefit from static type safety and automatically generated communication and placement. Some preliminary work shows that, as the communication between layers is protocol agnostic, more secure alternatives can be used. One example is to run the \gls{ITASK} server behind a reverse proxy implementing TLS\slash{}SSL encryption \citep{wijkhuizen_security_2018}. A second is to add integrity checks or even encryption to the communication protocol for resource-rich sensor nodes \citep{de_boer_secure_2020}.
-\section{Task-oriented and \texorpdfstring{\glsxtrshort{IOT}}{IoT} programming in \texorpdfstring{\glsentrytext{CLEAN}}{Clean}}
+\section{Task-oriented and \IOT{} programming in Clean}
To make this paper self-contained we provide a concise overview of \gls{CLEAN}, \gls{TOP}, and \gls{IOT} programming in \gls{ITASK} and \gls{MTASK}. The minor innovations reported here are the interface to the \gls{IOT} sensors, and the \gls{CLEAN} port for the Raspberry Pi.
In contrast, \gls{CLEAN} has a uniqueness type system to ensure the single-threaded use of stateful objects like files and windows \citep{barendsen_uniqueness_1996}.
Both \gls{CLEAN} and \gls{HASKELL} support fairly similar models of generic programming \citep{ComparingGenericProgramming}, enabling functions to work on many types. As we shall see generic programming is heavily used in task-oriented programming \citep{GenericProgrammingExtensionForClean,HinzeGenericFunctionalProgramming}, for example to construct web editors and communication protocols that work for any user-defined datatype.
-\subsection{\texorpdfstring{\Glsxtrlong{TOP}}{Task-oriented programming}}
+\subsection{Task-oriented programming}
\Gls{TOP} is a declarative programming paradigm for constructing interactive distributed systems \citep{plasmeijer_task-oriented_2012}.
Tasks are the basic blocks of \gls{TOP} and represent work that needs to be done in the broadest sense.
\Glspl{SDS} offer a general abstraction of data shared by different tasks, analogous to variables, persistent values, files, databases and peripherals like sensors. Combinators compose \glspl{SDS} into a larger \gls{SDS}, and
parametric lenses define a specific view on \pgls{SDS}.
-\subsection{The \texorpdfstring{\glsentrytext{ITASK}}{iTask} \texorpdfstring{\glsxtrlong{EDSL}}{eDSL}}%
+\subsection{The iTask eDSL}%
\label{sec_t4t:itasks}
The \gls{ITASK} \gls{EDSL} is designed for constructing multi-user distributed applications, including web \citep{TOP-ICFP07} or \gls{IOT} applications.
Here we present \gls{ITASK} by example, and the first is a complete program to repeatedly read the room temperature from a digital humidity and temperature (DHT) sensor attached to the machine and display it on a web page (\cref{lst_t4t:itaskTemp}).
\Cref{fig_t4t:TempHistory} shows two screenshots of web pages generated by the \cleaninline{TempHistory} program. \Cref{fig_t4t:TempHistoryDiagram} is the deployment diagram showing the addition of the persistent \cleaninline{measurementsSDS} that stores the history of temperature measurements.
-\subsection{Engineering tierless \texorpdfstring{\glsxtrshort{IOT}}{IoT} systems with \texorpdfstring{\glsentrytext{ITASK}}{iTask}}%
+\subsection{Engineering tierless \IOT{} systems with iTask}%
\label{sec_t4t:itaskIOT}
A typical \gls{IOT} system goes beyond a web application by incorporating a distributed set of sensor nodes each with a collection of sensors or actuators. That is, they add the perception and network layers in \cref{fig_t4t:iot_arch}. If the sensor nodes have the computational resources to support an \gls{ITASK} server, as a Raspberry Pi does, then \gls{ITASK} can also be used to implement these layers, and integrate them with the application and presentation layers tierlessly.
\label{fig_t4t:cwtsweb}
\end{figure}
-\subsection{The \texorpdfstring{\glsentrytext{MTASK}}{mTask} \texorpdfstring{\glsxtrlong{EDSL}}{eDSL}}%
+\subsection{The mTask eDSL}%
\label{sec_t4t:mtasks}
In many \gls{IOT} systems the sensor nodes are resource constrained, e.g.\ inexpensive microcontrollers. These are far cheaper, and consume far less power, than a single-board computer like a Raspberry Pi. Microcontrollers also allow the programmer to easily control peripherals like sensors and actuators via the \gls{IO} pins of the processor.
The \gls{MTASK} \gls{OS} is stored in flash memory while the tasks are stored in \gls{RAM} to minimise wear on the flash memory. While sending byte code to a sensor node at runtime greatly increases the amount of communication, this can be mitigated as any tasks known at compile time can be preloaded on the microcontroller.
In contrast, compiled programs, like \ccpp{}, are stored in flash memory and there can only ever be a few thousand programs uploaded during the lifetime of the microcontroller before exhausting the flash memory.
-\subsection{Engineering tierless \texorpdfstring{\glsxtrshort{IOT}}{IoT} systems with \texorpdfstring{\glsentrytext{MTASK}}{mTask}}%
+\subsection{Engineering tierless \IOT{} systems with mTask}%
\label{sec_t4t:mtaskIOT}
A tierless \gls{CLEAN} \gls{IOT} system with microcontroller sensor nodes integrates a set of \gls{ITASK} tasks that specify the application and presentation layers with a set of \gls{MTASK}s that specify the perception and network layers.
The \gls{ITASK} \gls{SDS} \cleaninline{latestTemp} is first transformed to \pgls{SDS} that accepts only temperature values,
the \cleaninline{dateTimeStampedShare} adds the data via a lens.
The \cleaninline{mapRead} adjusts the read type.
-This new \gls{SDS} of type \cleaninline{Real} is lifted to the \gls{MTASK} program with \cleaninline{liftsds}.
+This new \gls{SDS} of type \cleaninline{Real} is lifted to the \gls{MTASK} program with \cleaninline{lowerSds}.
%The \cleaninline{mapRead} ensures that every write to \cleaninline{localSds} is automatically time-stamped when it is written to \cleaninline{latestTemp}.
-The \cleaninline{mainTask} is a simple \gls{ITASK} task that starts the \cleaninline{devTask} \gls{MTASK} task on the device identified by \cleaninline{deviceInfo} (\cref{lst_t4t:mtasktemp:withdevice}). At runtime the \gls{MTASK} slice is compiled to byte code, shipped to the indicated device, and launched. Thereafter, \cleaninline{mainTask} reads temperature values from the \cleaninline{latestTemp} \gls{SDS} that is shared with the \gls{MTASK} device, and displays them on a web page (\cref{fig_t4t:cwtsweb}). The \gls{SDS}---shared with the device using \cleaninline{liftsds}---automatically communicates new temperature values from the microcontroller to the server.
+The \cleaninline{mainTask} is a simple \gls{ITASK} task that starts the \cleaninline{devTask} \gls{MTASK} task on the device identified by \cleaninline{deviceInfo} (\cref{lst_t4t:mtasktemp:withdevice}). At runtime the \gls{MTASK} slice is compiled to byte code, shipped to the indicated device, and launched. Thereafter, \cleaninline{mainTask} reads temperature values from the \cleaninline{latestTemp} \gls{SDS} that is shared with the \gls{MTASK} device, and displays them on a web page (\cref{fig_t4t:cwtsweb}). The \gls{SDS}---shared with the device using \cleaninline{lowerSds}---automatically communicates new temperature values from the microcontroller to the server.
While this simple application makes limited use of the \gls{MTASK} \gls{EDSL}, it illustrates some powerful \gls{MTASK} program abstractions like basic tasks, task combinators, named recursive and parameterized tasks, and \glspl{SDS}.
Function composition (\cref{lst_t4t:mtasktemp:o}) and currying (\cref{lst_t4t:mtasktemp:setSds}) are inherited from the \gls{CLEAN} host language.
latestTemp :: SDSLens () (? (DateTime, Real)) (DateTime, Real)
latestTemp = mapReadWrite (listToMaybe, \x xs -> ?Just [x:xs]) ?None tempSDS[+\label{lst_t4t:mtasktemp:di1}\srcmark{DI}+]
-devTask :: Main (MTask v Real) | mtask, dht, liftsds v[+\label{lst_t4t:mtasktemp:devTask}+]
+devTask :: Main (MTask v Real) | mtask, dht, lowerSds v[+\label{lst_t4t:mtasktemp:devTask}+]
devTask =
DHT (DHT_DHT DHT_pin DHT11) \dht ->[+\label{lst_t4t:mtasktemp:DHT}+][+\label{lst_t4t:mtasktemp:si1}\srcmark{SI}+]
- liftsds \localSds =[+\label{lst_t4t:mtasktemp:liftsds}+][+\label{lst_t4t:mtasktemp:co1}\srcmark{CO}+]
+ lowerSds \localSds =[+\label{lst_t4t:mtasktemp:liftsds}+][+\label{lst_t4t:mtasktemp:co1}\srcmark{CO}+]
mapRead (snd o fromJust) (dateTimeStampedShare latestTemp)[+\label{lst_t4t:mtasktemp:o}+][+\label{lst_t4t:mtasktemp:sn1}\srcmark{SN}+]
In {main = rpeatEvery (ExactSec interval)[+\label{lst_t4t:mtasktemp:rpeatevery}+][+\label{lst_t4t:mtasktemp:sn2}\srcmark{SN}+]
(temperature dht >>~.[+\label{lst_t4t:mtasktemp:temperature}+][+\label{lst_t4t:mtasktemp:si2}\srcmark{SI}+]
\label{fig_t4t:cwtsDiagram}
\end{figure}
-\section{\texorpdfstring{\glsxtrshort{UOG}}{UoG} smart campus case study}%
+\section{UoG smart campus case study}%
\label{sec_t4t:Case}
The basis for our comparison between tiered and tierless technologies are four \gls{IOT} systems that all conform to the \gls{UOG} smart campus specifications (\cref{sec_t4t:OperationalComparison}). There is a small (12 room) deployment of the conventional \gls{PYTHON}-based \gls{PRS} stack that uses Raspberry Pi supersensors, and its direct comparator is the tierless \gls{CRS} implementation: also deployed on Raspberry Pis.
To represent the more common microcontroller sensor nodes we select ESP8266X powered \gls{WEMOS} D1 Mini microcontrollers. To evaluate tierless technologies on microcontrollers we compare the conventional \gls{PYTHON}\slash\gls{MICROPYTHON} \gls{PWS} stack with the tierless \gls{CWS} implementation.
The Raspberry Pi supersensor node used in \gls{CRS} and \gls{PRS} use more power as they have a general purpose ARM processor and run mainstream Linux. With all sensors enabled, they consume \qtyrange{1}{2}{\watt}, depending on ambient load. So a microcontroller sensor node consumes an order of magnitude less power than a supersensor node.
-\section[Is tierless \texorpdfstring{\glsxtrshort{IOT}}{IoT} programming easier than tiered?]{\hspace{-9pt}Is tierless \texorpdfstring{\glsxtrshort{IOT}}{IoT} programming easier than tiered?}%
+\section[Is tierless \IOT{} programming easier than tiered?]{\hspace{-9pt}Is tierless \IOT{} programming easier than tiered?}%
\label{sec_t4t:ProgrammingComparison}
-
This section investigates whether tierless languages make \gls{IOT} programming \emph{easier} by comparing the \gls{UOG} smart campus implementations. The \gls{CRS} and \gls{CWS} implementations allow us to evaluate tierless languages for
resource-rich and for resource-constrained sensor nodes respectively. The \gls{PRS} and \gls{PWS} allow a like-for-like comparison with tiered \gls{PYTHON} implementations.
\Cref{lst_t4t:mtasktemp} illustrates communication in a tierless \gls{IOT} language. That is, the \gls{CWTS} temperature sensor requires just three lines of communication code, and uses just three communication functions. The
\cleaninline{withDevice} function on \cref{lst_t4t:mtasktemp:withdevice} integrates a sensor node with the server, allowing tasks to be sent to it. The
\cleaninline{liftmTask} on \cref{lst_t4t:mtasktemp:liftmtask} integrates an \gls{MTASK} in the \gls{ITASK} runtime by compiling it and sending it for interpretation to the sensor node.
-The \cleaninline{liftsds} on \cref{lst_t4t:mtasktemp:liftsds} integrates \glspl{SDS} from \gls{ITASK} into \gls{MTASK}, allowing \gls{MTASK} tasks to interact with data from the \gls{ITASK} server.
+The \cleaninline{lowerSds} on \cref{lst_t4t:mtasktemp:liftsds} integrates \glspl{SDS} from \gls{ITASK} into \gls{MTASK}, allowing \gls{MTASK} tasks to interact with data from the \gls{ITASK} server.
The exchange of data, user interface, and communication are all automatically generated.
\subsection{High level abstractions}%
As examples, the step combinator \cleaninline{>>*.} allows the task value on the left-hand side to be observed until one of the steps is enabled;
and the \cleaninline{viewSharedInformation} (line 31 of \cref{lst_t4t:mtasktemp}) part of the UI will be automatically updated when the value of the \gls{SDS} changes. Moreover, each \gls{SDS} provides automatic updates to all coupled \glspl{SDS} and associated tasks. Thirdly, the amount of explicit type information is minimised in comparison to other languages, as much is automatically inferred \citep{hughes1989functional}.
-\section{Could tierless \texorpdfstring{\glsxtrshort{IOT}}{IoT} programming be more reliable than tiered?}%
+\section{Could tierless \IOT{} programming be more reliable than tiered?}%
\label{sec_t4t:Discussion}
% Phil: so widely known that a citation is unnecessary \citep{madsen1990strong}.
That said, many distributed system components written in languages that primarily use static typing, like \gls{HASKELL} and Scala, use some dynamic typing, e.g.\ to ensure that the data arriving in a message has the anticipated type \citep{epstein2011towards,gupta2012akka}.
-In a typical tiered multi-language \gls{IOT} system the developer must integrate software in different languages with very different type systems, and potentially executing on different hardware. The challenges of maintaining type safety have long been recognised as a major component of the semantic friction in multi-language systems, e.g.\ \citep{ireland_classification_2009}.
+In a typical tiered multi-language \gls{IOT} system the developer must integrate software in different languages with very different type systems, and potentially executing on different hardware. The challenges of maintaining type safety have long been recognised as a major component of the semantic friction in multi-language systems, e.g.\ \citet{ireland_classification_2009}.
Even if the different languages used in two components are both strongly typed, they may attribute, often quite subtly, different types to a value. Such type errors can lead to runtime errors, or the application silently reporting erroneous data. Such errors can be hard to find. Automatic detection of such errors is sometimes possible, but requires an addition tool like Jinn \citep{Jinn,Furr2005}.
%Such errors can be hard to debug, partly because there is very limited tool support for detecting them