<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>copton</title>
	<atom:link href="http://blogs.ethz.ch/copton/feed/" rel="self" type="application/rss+xml" />
	<link>http://blogs.ethz.ch/copton</link>
	<description>2.4263102175e-12</description>
	<lastBuildDate>Mon, 20 Feb 2012 08:43:51 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Compiler-Assisted Thread Abstractions for Resource-Constrained Systems</title>
		<link>http://blogs.ethz.ch/copton/2011/09/26/compiler-assisted-thread-abstractions-for-resource-constrained-systems/</link>
		<comments>http://blogs.ethz.ch/copton/2011/09/26/compiler-assisted-thread-abstractions-for-resource-constrained-systems/#comments</comments>
		<pubDate>Mon, 26 Sep 2011 09:58:09 +0000</pubDate>
		<dc:creator>Alexander</dc:creator>
				<category><![CDATA[article]]></category>
		<category><![CDATA[C/C++]]></category>
		<category><![CDATA[code generation]]></category>
		<category><![CDATA[events]]></category>
		<category><![CDATA[threads]]></category>
		<category><![CDATA[wireless sensor networks]]></category>

		<guid isPermaLink="false">http://blogs.ethz.ch/copton/?p=570</guid>
		<description><![CDATA[Summary Major operating systems for wireless sensor networks (WSN) enforce an event-based programming paradigm for efficiency reasons. However, practice has shown that the resulting code complexity is hard to manage for software developers and leads to difficult problems during development, deployment, and operations. Thus, thread libraries for WSN applications have been introduced, but the efficiency [...]]]></description>
			<content:encoded><![CDATA[<h3>Summary</h3>
<p>Major operating systems for wireless sensor networks (WSN) enforce an event-based programming paradigm for efficiency reasons. However, practice has shown that the resulting code complexity is hard to manage for software developers and leads to difficult problems during development, deployment, and operations. Thus, thread libraries for WSN applications have been introduced, but the efficiency constraints of the domain often lead to glaring restrictions of the supported thread semantics.</p>
<p>In contrast, compiler-assisted thread abstractions support threads without actually using threads at runtime. Instead, the thread-based code is automatically translated into equivalent event-based code. Currently, two different systems implement this idea, but both have severe limitations regarding both the thread semantics and the tool support.</p>
<p>Our goal is to demonstrate the potential of compiler-assisted thread abstractions by taking the next step and introducing a comprehensive system of compiler and debugger which supports cooperative threads with minor restrictions and which is also platform independent.</p>
<p>A Haskell-based compiler prototype shows the feasibility of our approach and preliminary results demonstrate that the generated code is efficient enough to be executed on wireless sensor network devices. Furthermore, existing optimization potential suggests that compiler-assisted thread abstractions can indeed outperform runtime-based solutions and compete with hand-written event-based code. We are currently working on completing the implementation of the tools and verifying these points by means of an extensive evaluation.<br />
<span id="more-570"></span></p>
<h3>1. Introduction</h3>
<p>Wireless sensor networks (WSN) aim to provide monitoring of physical phenomena over a spatial region without requiring existing infrastructure. To this end, battery-powered computing systems with sensors and wireless communication capabilities are deployed in the field and continuously deliver measured values via multi-hop routing to a base station.</p>
<p>Examples of existing WSN applications include monitoring of the permafrost in the Swiss Alps [<a href="http://www.permasense.ch/fileadmin/papers/wireless_sensor_network_ahasler_2008.pdf">Hasler2008</a>], adaptive lighting in operational road tunnels [<a href="http://disi.unitn.it/~guna/?cmd=download&amp;file=tunnel.pdf">Ceriotti2011a</a>], and wildlife monitoring [<a href="http://www.cl.cam.ac.uk/~bp296/papers/wildsensing.pdf">Dyo2010</a>]. Such applications typically require a long system lifetime without manual maintenance such as renewal of batteries. As a consequence, energy efficiency is one of the most critical design criteria for WSN applications, which in practice implies resource-constrained devices. A typical example of such a device is the T-Mote Sky, which is equipped with a 16 bit, 8 MHz micro-controller, 48 kB of Flash memory and 10 kB of random access memory (RAM).</p>
<p>Major WSN operating systems such as TinyOS [<a href="http://www.tinyos.net/papers/tos.pdf">Hill2000</a>] and Contiki [<a href="http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.59.2303&amp;rep=rep1&amp;type=pdf">Dunkels2004</a>] account for the scarce resources by enforcing an event-based programming paradigm. The common reasoning behind this is that with event-based programming, a single dispatcher thread and a single stack suffice to execute multiple tasks concurrently.</p>
<p>Although efficient, practice has shown that the implications of this para\-digm often pose significant problems to developers, as it is difficult and cumbersome to manually manage the states and the control flow of event-based applications [<a href="http://www.stanford.edu/class/cs240/readings/usenix2002-fibers.pdf">Adya2002</a>]. Furthermore, deployment environments typically differ strongly from lab environments and debugging is usually very time- and energy-consuming. Therefore, mistakes resulting from the inherent complexity of event-based applications tend to be very expensive to cope with.</p>
<p>To better support developers in programming WSN applications, investigations have been started to provide thread-based programming for WSN applications. On a first branch, common approaches to thread libraries have been adapted, sometimes by introducing restrictions in the supported thread semantics [<a href="http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.86.5201&amp;rep=rep1&amp;type=pdf">McCartney2006</a>, <a href="http://www.springerlink.com/index/g40g5771066h1x70.pdf">Nitta2006</a>, <a href="http://www.eecs.harvard.edu/~mdw/papers/regions-nsdi04.pdf">Welsh2004</a>]. On a second branch, compiler-assisted thread abstractions employ a compiler which takes a thread-based program as input and generates an equivalent event-based program as output. By these means software developers have the comfort of threads while the runtime still performs efficient event dispatching.</p>
<p>The goal of this thesis is to investigate the potential of compiler-assisted thread abstractions for resource-constrained systems. In particular, we aim at demonstrating that compiler-based solutions can not only support almost complete thread semantics to the programmer but also outperform runtime-based solutions in terms of code efficiency. To this end, we are building an accordant compiler called Ocram and will evaluate its performance characteristics on the basis of typical WSN applications. The final outcome of the thesis will thus consists in both a quantitative and a qualitative analysis of the potential and limits of compiler-assisted thread abstractions.</p>
<p>In the next section we will discuss two existing systems that already provide compiler-assisted thread abstractions for WSN applications. Being the first of their kind, though, both systems have sever limitations. Ocram is supposed to overcome these limitations as described in section 3. Section 4 subsequently presents published results, the current state of the work and future plans of it.</p>
<h3>2. State of the Art</h3>
<p>The first system that provided a compiler-assisted thread-abstraction for WSN applications is Protothreads [<a href="http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.143.9245&amp;rep=rep1&amp;type=pdf">Dunkels2006</a>]. It has been specifically designed for Contiki and its usage is deeply embedded in Contiki&#8217;s libraries and runtime system. Technically, Protothreads are a set of C preprocessor macros that enable the syntactical illusion of threads and blocking operations. Instead of waiting for the completion of a blocking operation, though, the runtime memorizes the current code location and returns from the handler function. When resuming the thread, the same function is called again and a <code>switch</code> statement, which is expanded from the Protothreads macros, brings the execution back to the location where the previous blocking operation occurred.</p>
<p>As the C preprocessor can only locally replace language tokens, this approach has a number of limitations. First of all, the state of automatic variables is not preserved across calls of blocking operations. Second, blocking operations can only be called in the topmost thread function, which severely restricts the software architecture of Protothreads-based applications. Last but not least, certain user mistakes are not detected at compile time but have to be indirectly examined by observing unexpected execution behavior. Such mistakes can be as subtle as using additional <code>switch</code> statements that interfere with the expanded ones or relying on the state of an automatic variable after a blocking operation.</p>
<p>In contrast, the first system that employs a dedicated compiler to provide thread abstractions was TinyVT [<a href="http://etd.library.vanderbilt.edu/available/etd-03282008-133712/unrestricted/sallai-dissertation.pdf">Sallai2008</a>]. It has been specifically designed for the TinyOS operating system which is implemented in the nesC programming language [<a href="http://www.tinyos.net/papers/tos.pdf">Hill2000</a>] and enforces a component-based software architecture with event-based interfaces. TinyVT enables software developers to implement single components sequentially as it is possible to inline event handlers in code blocks following a special <code>await</code> statement. Also, the runtime preserves the state of local variables across such operations.</p>
<p>Although TinyVT overcomes many of Protothreads&#8217; drawbacks, the supported thread semantics is still rather restricted. First of all, inlined event handlers may not contain <code>await</code> statements. Additionally, it is not possible to split the implementation of a component into multiple functions, which implies that code can not be shared between multiple threads, which in turn implies that TinyVT has no support for reentrant code.</p>
<p>Besides the above mentioned limitations, both systems provide no support for debugging. The consequence in practice is that software developers use source-level debuggers to step through the generated event-based code. We consider abstractions without debugging support as incomplete because they sometimes fail to hide lower-level details although their primary purpose is to relieve the user from having to deal with them. Even worse, software developers additionally need to understand the implementation details of the abstraction itself in order to perform the necessary back-mapping to identify the cause of the observed error in the abstract program.</p>
<p>In contrast to Protothreads and TinyVT, Ocram translates from and to standard-compliant C code, supports thread semantics comparable to what common thread libraries provide, and is platform independent with respect to the underlying event-driven runtime environment. Furthermore, we want to provide a corresponding source-level debugger that works on the level of the thread abstraction and offers a feature set that is  comparable to those of common source-level debuggers. Finally, we expect that our findings are transferable to other domains where the event-based programming paradigm is prevalent. The next section presents the details of this system.</p>
<h3>3. System Design</h3>
<p>The Ocram compiler translates thread-based code (<em>T-code</em>) to event-based code (<em>E-code</em>) while both T-code and E-code comply with the ISO/IEC 9899 international standard (C99). Section 3.1 describes the semantics of the T-code and the limitations concerning the set of supported language features. Next, section 3.2 illustrates how Ocram translates T-code into E-code. The interoperability with the runtime environment that executes the E-code is discussed in section 3.3, which completes the description of the system basics. Subsequently, section 3.4 enumerates a set of optimizations opportunities that can be exploited to generate more efficient E-code. Finally, section 3.5 describes the design of the T-code source-level debugger and the requirements it poses on the compiler.</p>
<h4>3.1 Thread Semantics and Limitations</h4>
<p>On the T-code side, Ocram supports cooperative threads with shared memory. We assume that the underlying runtime environment defines in its application programming interface (API) the set of blocking functions together with non-blocking functions and required types. Every call to a blocking function is an implicit yield point where control could be passed to a different thread. In addition to that, the runtime environment can support explicit yield points by means of a blocking function that performs no operation.</p>
<p>Every blocking function is called a <em>critical function</em> and every function that calls a critical function, i.e. contains a <em>critical call</em>, is also a critical function. Every thread is started by the call of its <em>thread start function</em>, which usually is a critical function itself. Critical functions are reentrant and can thus be used by different threads. Furthermore, arbitrary non-critical functions can be used to perform additional computations. As threads are not preempted they can easily share memory and thus communicate with each other by means of global variables. In general, T-code is basically just C99 code, which has the additional benefit that existing development environments can be used to write it.</p>
<p>Since the thread semantics are implemented at compiler level, there are some inherent limitations, though [<a href="http://www.vs.inf.ethz.ch/publ/papers/bernauer10_threads2events.pdf">Bernauer2010b</a>]. First, the number of threads must be known at compile time. Second, recursive functions must not invoke critical functions. And third, function pointers must not be used to invoke critical functions. We argue, though, that these limitations do not severely affect programming of WSN applications. In particular, recursive algorithms tend to have an undecidable stack consumption and thus should generally be avoided in embedded systems. Again due to the constrained resources of the employed devices, it is often not sensible to support an arbitrary number of threads. Finally, the use of function pointers is not uncommon, but can be avoided by a case differentiation with moderate overhead. In any case, the compiler can reliably detect any violation of these constraints.</p>
<h4>3.2 Compilation Scheme</h4>
<p>As a first step, the compiler must rewrite the control flow of the program to replace critical calls with non-blocking <em>split-phase operations</em> [<a href="http://www.tinyos.net/papers/tos.pdf">Hill2000</a>]. Additionally, it must rewrite the data flow to preserve the value of automatic variables. Amongst many possibilities, we are currently investigating the following compilation scheme as our preliminary results suggest that it produces efficient E-code in most cases.</p>
<p>For every critical function, the Ocram compiler generates a so-called <em>T-stack structure</em> that holds all automatic variables, all function parameters, the function&#8217;s return value (if existent), the continuation of the current caller, and an instance of the T-stack structure of each critical function that is directly called by the respective function. Furthermore, one instance of the T-stack structure of every thread start function is generated and used by the E-code to access the corresponding variables. We call such an instance a <em>T-stack</em>.</p>
<p>As the scope of a T-stack structure is the execution of the corresponding function and as every instance of a T-stack structure belongs to exactly one thread, all nested T-stacks can share memory and are thus grouped in a C union. In fact, a T-stack represents the overlay of all snapshots of the runtime stack of the corresponding thread if it would actually be executed.</p>
<p>Concerning the control flow, a critical function must only trigger the respective operation and return immediately. The platform abstraction layer, which is covered in section 3.3, implements the blocking functions accordingly. For the other critical functions, the compiler replaces every critical call with the following sequence of statements: First, the callees parameters are written to the T-stack. Second, the continuation information for the callee is written to the T-stack. Third, the actual call is performed. Last, the function returns.</p>
<p>The bodies of all critical functions that are used by a thread are all inlined into one common <em>thread execution function</em> for each thread. Thus, the continuation can simply be the address of a label and a call of a critical, but not blocking, function is just a <code>goto</code> &#8211; Computed <code>gotos</code> are a GNU extension to the C programming language. If it is important to stay standard compliant they can be emulated via less efficient jump tables. &#8211; The first statement of every inlined body, as well as every statement after a critical call, is equipped with a unique label. Furthermore, every <code>return</code> statement in the T-code is replaced by a <code>goto</code> statement that uses the continuation information stored on the T-stack.</p>
<p>As there is a one-to-one mapping between thread execution functions and T-stacks, read and write access to the T-stack involves no indirections. The C compiler that processes the E-code can thus generate efficient memory access code despite the nested structure of the T-stacks.</p>
<h4>3.3 Platform Abstraction Layer</h4>
<p>The above described compilation scheme depends on proper event-based implementations of the blocking functions that are used by an application. Their role is to implement the systematic interface assumed by the code generation by means of the interface of the respective underlying runtime environment. This manual effort is necessary because existing runtime environments have non-systematic interfaces so that the code generation needs some sort of user assistance to be able to use them. Amongst many possible ways of formalizing those interfaces we think that simply implementing them once is justifiable and feasible.</p>
<p>Clearly, this platform abstraction layer (PAL) introduces an overhead in terms of code size, RAM usage and CPU cycles which we have to account for when evaluating the overall system performance. The size of this overhead inherently depends on the semantics of the underlying interfaces. Given a runtime system that actually support Ocram natively this overhead could even disappear.</p>
<p>As the Ocram compiler poses little requirements on the PAL, it is in general not restricted to the WSN domain. In any other domain, where the event-based paradigm is prevalent for efficiency reasons and C99 is used, software developers could benefit from our compiler-assisted thread abstraction.</p>
<h4>3.4 Optimizations</h4>
<p>The compilation scheme of section 3.2 supports the most generic case that can be encountered. In practice, though, many typical recurring patterns exist and allow for shortcuts that can be exploited by a compiler.</p>
<p>First of all, automatic variables that are never written to before a critical call and read afterwards do not need to be preserved, so they do not have to be saved on the T-stack. Instead, they can stay automatic variables in the E-code as well and, thus, be saved on the single runtime stack which saves memory and access time.</p>
<p>As a second example, if a function is only called from one location in the whole program there is no need to save the continuation in memory. Instead, it can be hard-coded into the E-code thus saving memory and lookup time. The callee can additionally access the variables of the caller in case of read-only parameters.</p>
<p>We believe that further investigations will reveal additional potential for optimizations that all sum up to a significant performance benefit of compiler-assisted thread abstractions compared to runtime-only solutions.</p>
<h4>3.5 Debugging Support</h4>
<p>The role of the debugger is to undo the compilation so that the E-code runtime can be presented by means of the T-code abstraction. In general this involves managing the mapping of both the data and the control flow. To this end, the T-code debugger utilizes and controls an E-code debugger which is just a standard C debugger, possibly attached to the execution via JTAG (IEEE 1149.1) or other platform dependent means.</p>
<p>When the user wants to know the value of a T-code variable the T-code debugger only needs to know which E-code variable holds this value and request it from the E-code debugger. Similarly, when the user installs breakpoints or issues step-through commands, the T-code debugger needs to know to which location in the E-code this corresponds to and issue the proper commands to the E-code debugger.</p>
<p>To enable the debugger to perform these tasks, the Ocram compiler must generate corresponding debugging information for all variables and all statements of critical functions. This relatively simple technique is enough to add significant value to the thread abstraction provided by our Ocram compiler as discussed in section 2.</p>
<h3>4. Past, Current, and Future Work</h3>
<p>In <a href="http://www.vs.inf.ethz.ch/publ/papers/bernauer10_ewsn2010.pdf">Bernauer2010</a> and <a href="http://www.vs.inf.ethz.ch/publ/papers/bernauer10_threads2events.pdf">Bernauer2010b</a> we have presented a first compilation scheme that differs from the one described in section \ref{sec:scheme}. Since then we have been working both on finding better compilation schemes and implementing the Ocram compiler.</p>
<p>For the latter, we eventually have decided to use the Haskell programming language, for which the Language.C module provides a comprehensive parser and pretty-printer for the C programming language. The current version of the <a href="http://github.com/copton/ocram">Ocram compiler</a> is a proof-of-concept implementation. Although it supports the translation of basic applications, many C language features are not supported yet. Furthermore, we have implemented a basic PAL for both Contiki and TinyOS and successfully executed generated E-code on a T-Mote Sky device.</p>
<p>As a next step, we plan to implement the T-code debugger and to extend the feature set of Ocram and exploit possible optimizations to achieve higher efficiency. Our goal is to outperform existing threading libraries in an evaluation involving realistic WSN applications.<br />
Finally, past work has shown that the efficiency of the compilation scheme highly depends on application properties such as the number of reentrant functions. On the long term we thus envision a system that measures relevant application properties and chooses the best compilation scheme accordingly, possibly involving user interaction to achieve a proper trade off.</p>
<h3>Meta</h3>
<p>This is a research proposal for my Ph.D. studies. (<a href="http://www.inf.ethz.ch/personal/bernauea/download/bernauer-research_proposal2011.pdf">pdf</a>)</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.ethz.ch/copton/2011/09/26/compiler-assisted-thread-abstractions-for-resource-constrained-systems/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Internal DSLs in Scala</title>
		<link>http://blogs.ethz.ch/copton/2011/04/08/internal-dsls-in-scala/</link>
		<comments>http://blogs.ethz.ch/copton/2011/04/08/internal-dsls-in-scala/#comments</comments>
		<pubDate>Fri, 08 Apr 2011 13:03:49 +0000</pubDate>
		<dc:creator>Alexander</dc:creator>
				<category><![CDATA[article]]></category>
		<category><![CDATA[dsl]]></category>
		<category><![CDATA[scala]]></category>

		<guid isPermaLink="false">http://blogs.ethz.ch/copton/?p=552</guid>
		<description><![CDATA[Quite some time ago I read the Programming in Scala and the Programming Scala book and decided to offer a student lab on a Scala-based implementation of a Reversi tournament framework. One part of this framework is a DSL for the configuration of a tournament. So I went on and investigated the Scala techniques that [...]]]></description>
			<content:encoded><![CDATA[<p>Quite some time ago I read the <a href="http://www.artima.com/shop/programming_in_scala_2ed">Programming in Scala</a> and the <a href="http://programming-scala.labs.oreilly.com/">Programming Scala</a> book and decided to offer a student lab on a Scala-based implementation of a <a href="http://en.wikipedia.org/wiki/Reversi">Reversi</a> tournament framework. One part of this framework is a <a href="http://en.wikipedia.org/wiki/Domain-specific_language">DSL</a> for the configuration of a tournament. So I went on and investigated the Scala techniques that allow for the construction of internal DSLs. Although there is quite some information on the internet and in the books about <a href="http://www.google.com/search?q=scala dsl">Scala DSLs</a> here is what I came up with to get my student started.</p>
<p><span id="more-552"></span></p>
<h3>Example</h3>
<p>So, here is an example DSL for tournaments and the list of the techniques that I encountered and consider essential for building internal DSLs in Scala. I don&#8217;t claim &#8211; and I don&#8217;t think &#8211; that this list is complete, though.</p>
<pre><code>import scala.collection.mutable.ListBuffer

class Setup extends TournamentBuilder {
    "3:2" ==&gt; {
      --&gt; ("butcher" vs "hulk")
      --&gt; ("chaos" vs "crusher")
      --&gt; ("diabola" vs "electra")
    }
}

object Main {
  def main(args: Array[String]) {
    new Setup()
  }
}

class Tournament(val bestof: Int, val winners: Int) {
  def ==&gt; (block: =&gt; TournamentBuilder) : Unit =
  {
    val config = block.list
    run(config)
  }

  def run(config: ListBuffer[(String, String)])
  {
    for (game &lt;- config) {
      Console.print("running best of " + bestof +
	" in " + game._1 + " vs. " + game._2 + "\n")
    }
    Console.print("The best " + winners +
	" players now proceed to the next round\n")
  }
}

class MatchBuilder(p1: String) {
  def vs(p2: String) = (p1, p2)
}

class TournamentBuilder {
  implicit def strToTourn(mode: String): Tournament =
  {
    val parts = mode.split(":")
    new Tournament(parts(0).toInt, parts(1).toInt)
  } 

  implicit def strToMatchB(p1: String): MatchBuilder =
    new MatchBuilder(p1)

  var list = new ListBuffer[(String, String)]()

  def --&gt;(config: (String, String)): TournamentBuilder =
  {
    list += config
    this
  }
}

</code></pre>
<h4>technique 1: method names</h4>
<p>Scala allows to use almost any sequence of Unicode characters as method names. So, especially the ASCII artists can use their creativity and the others can check out the Unicode tables for <a href="http://en.wikipedia.org/wiki/Arrow_(symbol)#Arrows_in_Unicode">arrows</a>, <a href="http://en.wikipedia.org/wiki/Unicode_Mathematical_Operators">mathematical operators</a>, or any other proper symbols.</p>
<p>Be aware though, that the usage of the DSL becomes cumbersome, though, because Unicode symbols are usually not bound directly to some keys on the keyboard. (@Vim users: check out this <a href="http://vim.wikia.com/wiki/Working_with_Unicode">howto</a>). So, for my example I sticked to good old ASCII. And I wasn&#8217;t very creative either. But I can assure you that <code>==&gt;</code> and <code>--&gt;</code> have special semantics for tournament planners <img src='http://blogs.ethz.ch/copton/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<h4>technique 2: infix notation</h4>
<p>In Scala, every method with a single parameter, i.e. any binary function, can be written in infix notation without parantheses. This increases the readability of the DSL because you can write <code>"butcher" vs "hulk"</code> instead of <code>"butcher".vs("hulk")</code> &#8211; which doesn&#8217;t work yet because <code>vs</code> is not a method of <code>String</code>; see the next technique.</p>
<h4>technique 3: implicit convertion</h4>
<p>Scala&#8217;s <code>implicit</code> feature is really powerfull and widely used behind the courtains. In the above example, the <code>strToMatchB</code> method is implicitly called whenever there is a <code>String</code> object but a <code>MatchBuilder</code> object is expected. So, <code>"butcher" vs "hulk"</code> becomes <code>strToMatchB("butcher").vs("hulk")</code>. The trigger for this implicit method call is the method <code>vs</code> which is only defined for <code>MatchBuilder</code> objects.</p>
<h4>technique 4: code blocks</h4>
<p>Code blocks, a.k.a. closures, are first-order citizens in the Scala world. The curly braces allow to denote literals and the type system provides types for them which are essentially simple function types. In the above example, the code block expects no parameters but results in a <code>TournamentBuilder</code> object. With this technique, you can provide grouping and scoping for your DSL.</p>
<h4>technique 5: string processing</h4>
<p>In the above example, <code>"3:2"</code> is supposed to be the tournament mode which reads as &#8220;every match is best of 3 and the best two players enter the next round&#8221;. This is just an example to show that besides all DSL magic you can still use plain old strings and parse them. Either with simple string utility methods, with <a href="http://www.scala-lang.org/node/122">regular expressions</a> or with <a href="http://www.scala-lang.org/api/current/scala/util/parsing/combinator/Parsers.html">parser combinators</a>. Depending on the requirements of the DSL using small sub-grammars can greatly increase the readability of the language.</p>
<h3>Execution</h3>
<p>This program&#8217;s output is:</p>
<pre><code>running best of 3 in butcher vs. hulk
running best of 3 in chaos vs. crusher
running best of 3 in diabola vs. electra
The best 2 players now proceed to the next round
</code></pre>
<p>First, the string <code>"3:2"</code> is converted into a <code>TournamentBuilder</code> by <code>strToTourn</code>. Next, the method <code>==&gt;</code> is invoked which executes the passed code block. There, a chain of <code>--&gt;</code> method calls is executed while each incarnation updates the member <code>list</code> and returns the same <code>TournamentBuilder</code> object. To this end, the <code>--&gt;</code> method expects a tuple which is constructed by means of the <code>MatchBuilder</code> class as explained above. Finally, the <code>Tournament</code> simply takes the <code>MatchBuilder</code>&#8216;s list as its configuration for the holding of the tournament.</p>
<h3>Meta</h3>
<p>I want to thank <a href="http://www.downgra.de/">fire</a> for being my sparring partner on programming languages in general and Scala in particular. Go and check out <a href="http://www.downgra.de/">his blog</a> for more good stuff about Scala.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.ethz.ch/copton/2011/04/08/internal-dsls-in-scala/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Compiling Business Process Models for Sensor Networks</title>
		<link>http://blogs.ethz.ch/copton/2011/04/07/compiling-business-process-models-for-sensor-networks/</link>
		<comments>http://blogs.ethz.ch/copton/2011/04/07/compiling-business-process-models-for-sensor-networks/#comments</comments>
		<pubDate>Thu, 07 Apr 2011 17:57:03 +0000</pubDate>
		<dc:creator>Alexander</dc:creator>
				<category><![CDATA[publication]]></category>
		<category><![CDATA[code generation]]></category>
		<category><![CDATA[embedded]]></category>
		<category><![CDATA[wireless sensor networks]]></category>

		<guid isPermaLink="false">http://blogs.ethz.ch/copton/?p=519</guid>
		<description><![CDATA[Wireless sensor networks are increasingly being used to improve business processes. The behavior of such a process is usually captured in models while its implementation is typically created manually. Besides being expensive, this approach entails deviations between the model and the implementation of a business process, thus rendering it less effective. We aim at closing [...]]]></description>
			<content:encoded><![CDATA[<p>Wireless sensor networks are increasingly being used to improve business processes. The behavior of such a process is usually captured in models while its implementation is typically created manually. Besides being expensive, this approach entails deviations between the model and the implementation of a business process, thus rendering it less effective. We aim at closing this gap by automatically generating applications from the model of the process instead. In our approach, software developers provide building blocks that are used by business analysts to model business processes and hereby effectively control their execution on an abstract level. Furthermore, the model editor integrates a compiler and a simulator so that the business analysts can test and debug the modeled processes on the same level of abstraction. Our evaluation results show that the generated code can be executed on resource-constrained sensor nodes consuming only 1% more energy than the hand-written equivalents. However, the benefits of our approach come at the price of 10% more RAM and 44% more flash space consumption on average.</p>
<p><span id="more-519"></span></p>
<h3>1. Introduction</h3>
<p>Business processes drive the manufacturing of products and the operation of services in today&#8217;s economy. They describe the interactions between humans, IT-systems, and the environment that are necessary to reach the business goals. With increasingly evolving sensor, wireless and distributed systems technologies, more and more business processes use <em>wireless sensor networks (WSN)</em> to gather information about or interact with the entities they control. Examples include safety processes for storing hazardous materials <a href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.123.9487">[1]</a>, securing shipping and handling of containers to comply with government regulations <a href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.83.23">[2]</a>, and automating hospital processes <a href="http://portal.acm.org/citation.cfm?id=1372965">[3]</a>.</p>
<p>Business processes are designed and modeled by business analysts who are domain experts in their field but do not necessarily have a background in IT. Thus, the actual implementation of a business process is typically performed by software developers. This prevalent approach poses two major problems. Firstly, the implementation usually deviates from the intentions and expectations of the business analysts because cross-domain communication is prone to misunderstandings. This deviation typically renders the respective business process less effective the larger it becomes. In order to avoid this, technology implementations should follow the business process and not vice versa <a href="http://ieeexplore.ieee.org/xpls/abs_all.jsp?arnumber=4439077">[4]</a>. Secondly, changing the model of a business process necessitates the adaption or even recreation of parts of the implementation. As this is expensive and time-consuming <a href="http://www.amazon.de/Mythical-Man-Month-Essays-Software-Engineering/dp/0201835959">[5]</a>, business processes tend to adapt slowly to changes of requirements or business facts.</p>
<p>In this paper, we propose to use the standardized <em>Business Process Model and Notation</em> <a href="http://www.bpmn.org">(BPMN2)</a> as the interface language between business analysts and software developers and to apply code generation to turn BPMN models into executable code. BPMN models are refined by additional models while commonly programmed components form the base case of this recursion. These components and the code which is generated from the models constitute the final application. Software developers can decide which levels of abstraction should be modeled and which should be programmed. At the topmost levels, business analysts, which represent our target user group, model the business process in the familiar BPMN while software developers relieve them from mastering distributed computing problems by implementing all models and components below. </p>
<p>In our approach, instead of being just a documentation blueprint, a BPMN model actually defines the execution of the respective business process and can be simulated and debugged directly in the model editor. Additionally, BPMN supports the integration of multiple involved distributed systems into a single top-level model, thus covering the demands of business processes which use WSN. To enable better integration into the environment, reduce power consumption, and decrease production and deployments costs <a href="http://www.ti5.tu-harburg.de/events/fgsn09/proceedings/fgsn_021.pdf">[6]</a>, we focus on the lower-end spectrum of embedded devices such as 8-bit MCUs with 128 kB of non-volatile memory, and 8 kB of volatile memory. To this end, our compiler generates efficient code which runs on such resource-constrained sensor nodes.</p>
<p>The quantification and evaluation of modeling and programming abstractions is notoriously difficult, but we make a series of arguments to support our approach. Firstly, BPMN is an established standard and business analysts already use it to model business processes. Hence, it is an adequate tool for such tasks and the addressed user group is capable of using it. Next, we show that attaching execution semantics to BPMN models is possible. We do this both in theory and in practice. Firstly, by discussing how the code generation works and secondly, by presenting results of a series of case studies for which we used a proof of concept implementation of the required tools. Additionally, we demonstrate that the generated code is efficient enough to be executed on resource-constrained sensor nodes. Last, we argue that simulating and debugging the models of business processes is an intuitive task for business analysts because this functionality is integrated into the model editor. In summary, we enable business analysts to control, simulate, and debug the execution of their business processes on an abstract level.</p>
<p>This paper is organized as follows: Section 2 presents related work and argues how our approach advances the state of the art. Next, Section 3 gives a brief introduction into the BPMN notation and semantics using an example business process. We then outline how BPMN models can capture WSN requirements in Section 4, and show how WSN applications can be generated from BPMN models in Section 5. Our modeling approach requires an integrated tool-set which we describe in Section 6 while in Section 7 we stress the debugging aspect. Subsequently, we evaluate our proof of concept implementation of the tools in Section 8 using a representative set of WSN applications before concluding in Section 9.</p>
<h3>2. Related Work</h3>
<p>Probably the best-known modeling language is the Universal Modeling Language (<a href="http://www.uml.org">UML</a>) which is a generic set of standard graphical notations that capture different system aspects. <a href="http://www.ibm.com/software/awdtools/rhapsody">Rhapsody</a> is an industry solution  for UML-driven development and automatic code generation for embedded systems. Recent work in this area even addresses WSN <a href="http://portal.acm.org/citation.cfm?id=1809111.1809116">[7]</a> using <a href="http://www.sunspotworld.com">Sun SPOTs</a> with a 32-bit ARM core. In comparison, our solution supports sensor nodes with significantly less memory and computation resources. Additionally, for the description of a single business process, UML requires multiple models which cover different aspects and different involved entities of the business process. This reflects the fact that UML is a rather technical notation which does not fit the needs of business analysts.</p>
<p>Other proposed solutions for graphical programming and model-based development of sensor network applications <a href="http://ieeexplore.ieee.org/xpls/abs_all.jsp?arnumber=4027465">[8]</a><a href="http://ieeexplore.ieee.org/xpls/abs_all.jsp?arnumber=4557791">[9]</a> are based on the <a href="http://www.ni.com/labview">LabVIEW</a> and <a href="http://www.mathworks.com/products/simulink">Simulink</a> proprietary standards. Additionally, <a href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.93.7444">Viptos</a>, <a href="http://portal.acm.org/citation.cfm?id=1644106">Flow</a>, and <a href="http://portal.acm.org/citation.cfm?id=1595752">Srijan</a> are modeling environments for wireless sensor networks with custom graphical notations based on data flows. In either case, the intended audience again are scientists, system engineers, and software developers rather than business analysts.</p>
<p>To address the needs of the business domain, the Business Process Model and Notation (<a href="http://www.bpmn.org">BPMN</a>) became an Object Management Group (<a href="http://www.omg.org/">OMG</a>) standard for business processes. Today, this language is widely used by business analysts, consultants, and executives as a lingua franca. BPMN is additionally suitable for transformation to execution languages such as the Business Process Execution Language (<a href="http://www.oasis-open.org/committees/wsbpe">BPEL</a>) where a BPEL engine executes models while communicating with the environment via Web Services. Existing approaches which integrate sensor networks into business processes focus on this approach <a href="http://ieeexplore.ieee.org/xpls/abs_all.jsp?arnumber=4801835">[10]</a><a href="http://portal.acm.org/citation.cfm?id=1658192.1658197">[11]</a><a href="http://portal.acm.org/citation.cfm?id=1586991">[12]</a>. For the resource-constrained sensor nodes which we want to support, a model interpreter like a BPEL engine is not a viable option. Instead, we use a compiler to generate efficient code which executes directly on the targeted sensor node platform. Furthermore, with our approach, different communication channels can use different protocols such as IEEE 802.15.4 or TCP/IP depending on the respective requirements.</p>
<p>In summary, none of the existing solutions bridges the gap between the model description provided by business analysts and the corresponding implementation of a business processes for the resource-constrained sensor networks we are targeting. On the one hand, although some of the modeling solutions may accommodate the resource requirements, they expect the business audience to learn and understand a technical language and the associated tools. On the other hand, solutions targeted particularly at the business domain require too many device resources. We combine the benefits of existing work and use an open industry standard for modeling business processes. Our approach provides a unified view over all involved systems, supports simulation and debugging of business processes directly in the model view, and generates efficient code.</p>
<h3>3. Business Process Example and Background</h3>
<p>This section introduces the reader to a subset of BPMN terms and concepts while we refer to <a href="http://www.bpmn.org">the standard</a> for an exhaustive description. Generally, a BPMN model describes a process with the interactions and behaviors of involved entities which cooperate in order to fulfill required business goals. In BPMN terminology, a <em>pool</em> represents such an involved entity and acts as the topmost container for its model. Its graphical representation is a rectangle which can be collapsed to visually compress a model.</p>
<p><a href="http://blogs.ethz.ch/copton/files/2011/04/figure1.png">Figure 1</a> shows an example BPMN process for parcel delivery with three pools: <code>Headquarters</code>, <code>Truck</code>, and <code>Parcel</code>. Only the <code>Headquarters</code> pool is expanded and shows the details about enclosed tasks, control flows, message flows, and data flows. This is an example of a classical BPMN model as there is no code generation attached but the tasks are performed <em>manually</em> instead.</p>
<p>The actual work performed by a pool is divided into <em>task</em>s which are shown using boxes with round corners. A task may be recursively refined to contain other models in which case a plus-sign annotation is placed in the lower part of the box. Otherwise, the task is a <em>basic task</em> which is implemented directly in the language of the target platform.</p>
<p>Changes in the control flow are described using a <em>gateway</em> rhombus with an enclosed symbol which defines the semantics. A <em>parallel gateway</em> has a plus sign and forks the control flow if there are multiple outgoing sequences and joins the control flow if there are multiple incoming sequences. An <em>if gateway</em> has an X-symbol and represents a conditional decision point where the process follows the respective sequence flow that matches the condition.</p>
<p>During execution, a process may wait for a certain <em>event</em> to occur (<em>catch</em>) or it may trigger (<em>throw</em>) events to notify different tasks or other pools. Examples of possible events include starting and ending a task, receiving or sending a message, and signaling exceptional conditions. </p>
<p>The BPMN representation for events is a circle. To visually distinguish between the different event types and their properties, BPMN uses icons and different styles for the circle line. Catch events have a hollow icon, while throw events have a filled icon.  Furthermore, start events have a thin border and end events have a thick border. A catch event that does not terminate the respective process has a dashed line, e.g. <code>quality breach</code> in <a href="http://blogs.ethz.ch/copton/files/2011/04/figure1.png">Figure 1</a>.  In contrast, other catch events such as <code>damaged</code> in <a href="http://blogs.ethz.ch/copton/files/2011/04/figure2.png">Figure 2</a> do terminate the respective process and are depicted with continuous lines.</p>
<p>The data objects required by a process to fulfill its work can be explicitly represented in BPMN using <em>data items</em> (papers folded on the upper-right corner) and <em>data stores</em> (database cylinders). Both are connected to readers and writer by means of <em>association flow</em> arrows which are depicted as a dotted arrow. The difference between data items and data stores is that the former are volatile while the latter are persistent.</p>
<p>Communication between pools is explicitly modeled using <em>communication flows</em> which are represented as dotted lines with a hollow arrow head on the receiver side and an empty circle at the sender side. An envelope on the communication flow arrow marks the actual definition of the communication and specifies its properties.</p>
<p><a href="http://blogs.ethz.ch/copton/files/2011/04/figure2.png">Figure 2</a> shows the model of the <code>Parcel</code> pool. This process is automatically executed on the WSN nodes and demonstrates one of the major contributions of our work: The business analysts define reactions to business events on an abstract level and hereby control the actual execution of the business process because their model will be used to generate the corresponding application that is executed on the sensor node. </p>
<h3>4. BPMN Models for WSN Applications</h3>
<p>Models for WSN applications should support the distributed, heterogeneous and reactive characteristics of this domain. For energy efficiency considerations, models should also allow control over the protocols used for communication. Additionally, since a WSN is usually connected with other systems, the modeling language should support such integration.</p>
<p>The syntax and semantics of BPMN need neither be extended nor restricted to fulfill these requirements. The reactive nature of WSN applications is captured by BPMN events and the processing of events by BPMN sequence flows. Furthermore, communication only takes place via messages between pools and pools can have multiple instances. Thus, different entities of a distributed system such as various kinds of WSN nodes can be modelled with different pools.</p>
<p>The visual integration of the different entities is provided by the fact that pools can be collapsed and integrated into a system-wide model which shows only the general communication flow between the pools. Moreover, a definition of a communication flow has an envelope component attached to it and the properties of this component defines the details of the employed communication protocol. Thus different transmission modes such as broadcast and unicast, and different communication protocols such as IEEE 802.15.4 and TCP/IP can be chosen for each communication flow separately.</p>
<p>By this means, manually performed and automatically executed business processes can also be integrated into a system-wide model. To this end, base stations could send emails to an operator who sends back commands via HTTP requests, for instance. The communication between the operator and the WSN is simply represented with properly annotated communication flows in a BPMN model and the code generation takes care that the communication routines which are provided by the software developers are invoked.</p>
<p>In BPMN, each pool contains a task which uses sub-tasks. Such a sub-task can be refined by an additional model or can be a <em>basic task</em> which maps to an API function of the <em>target platform</em>. In the end, every sequence flow results in a sequence of basic tasks being called. The set of all basic tasks is part of the <em>platform API</em> which the software developers implement once and reuse for all business processes which involve the given target platform.</p>
<p>While graphical modeling provides a better overview over a process and is more intuitive than programming, it is not a suitable tool for all jobs. In particular, software developers generally prefer writing code when dealing with low-level implementations. Due to the recursive nature of BPMN models, our approach allows to choose the border between modeling and programming at arbitrary levels of abstraction. Hence, the <em>building blocks</em> for the models which are created by the business analysts can contain both basic tasks and tasks which are modeled. As a rule of thumb, general sequence flows of processes should be modeled while algorithms and device drivers should be programmed. </p>
<h3>5. Code Generation</h3>
<p>The core of our approach is a compiler which translates models into executables. In this section, we describe the code generation part of this translation which takes a sound BPMN model as input and yields an <em>intermediate representation</em> which is further processed by later steps. A sound model does not have a lack of synchronization and is deadlock-free as defined in <a href="http://portal.acm.org/citation.cfm?id=1882087">[13]</a>. This basically means that it is not possible that two sequence flows execute the same part of the model at the same time, and that there is always at least one sequence flow executing.</p>
<p>The translation of association flows is straightforward. Data items become variables and access to data stores is mapped to calls of persistence functions provided by the platform API. This translation is correct as long as no task is ever invoked more than once at the same time. We call this the <em>static</em> mode because it provides a one-to-one mapping between tasks and its enclosed data objects. </p>
<p>In contrast, in the <em>dynamic</em> mode there are <em>parallel tasks</em> which are invoked more than once at the same time. Then each invocation of such a task needs its own set of data objects. Thus, in the generated code, the corresponding variables are dynamically instantiated with each invocation and access to them is performed indirectly.</p>
<p>It is undecidable in general if a task is parallel or not. However, it is possible to identify most non-parallel tasks by a simple sequence flow analysis. For the undecidable cases the dynamic mode is always safe but it might be needlessly inefficient. In these cases the user might be able to assist by annotating tasks as non-parallel which is a property that can be checked at runtime by the generated code.</p>
<p>In contrast to the associations flow, the translation of the sequence flow is more complex. To support standard sensor nodes we have to address the fact that major WSN platforms are event-driven due to the efficiency benefits of this paradigm (<a href="http://portal.acm.org/citation.cfm?id=1034117">Contiki</a>, <a href="http://portal.acm.org/citation.cfm?id=356998">TinyOS</a>, <a href="http://www.computer.org/portal/web/csdl/doi/10.1109/SENSORCOMM.2009.27">Mote Runner</a>). Thus, the compiler has to translate the sequential and parallel computation semantics of a BPMN model into equivalent event-based code. </p>
<p>Event-based platforms typically use a single <em>dispatcher</em> which constantly takes the oldest <em>event</em> out of an event queue and calls the corresponding <em>event handler</em>. Event handlers may not block when waiting for something. Instead they only trigger a corresponding <em>split phase operation</em> and delegate the remaining processing to a <em>callback</em> which is a second handler that is registered at the runtime environment.  </p>
<p>By following this pattern the compiler maps each sequence flow to a chain of event handlers which are causally related to each other by the respective events. As long as a split-phase operation has not yet completed, the dispatcher calls handlers which correspond to other sequence flows, thus processing multiple sequence flows virtually in parallel.</p>
<p>We call a basic task with a split-phase interface a <em>critical task</em>. Additionally, all tasks which enclose critical tasks are also called critical. Outgoing sequence flows of critical tasks, catch events, start events, receive events, and outgoing sequence flows of parallel gateways represent all possible start or resume points of sequence flows at runtime. Thus, for each instance of these entities a function is generated which executes the corresponding sequence flow.</p>
<p>If a sequence flow reaches a task, the generated code simply calls the function corresponding to the start event of the invoked task. Furthermore, for every possible continuation &#8211; i.e. catch events at the border of the task or outgoing sequence flows in the case of a critical task &#8211; the pointers of the corresponding functions are saved in extra <em>continuation variables</em>. These variables are managed the same way as data item variables are.</p>
<p>If a sequence flow reaches a throw event, the generated code simply consults the corresponding continuation variable and calls the continuation. If a sequence flow reaches an end event, the generated code simply returns from the function in the case of a non-critical task. Otherwise it consults the continuation variable for the outgoing sequence flow and calls the continuation. Basic critical tasks are manually implemented along these lines, so that the computation can continue after completion of a split-phase operation.</p>
<p>Terminate events require more effort as the BPMN semantics require that all active sequence flows of the enclosing task are canceled. As sequence flows always continue execution until they reach a critical basic task, canceling them simply requires to suppress the invocation of the callbacks. Thus, for every critical task a <em>terminate function</em> is generated which recursively invokes the terminate functions of the enclosed sub-tasks. In the case of critical basic tasks, the terminate function is manually implemented and suppresses the invocation of the callback in a platform-specific way.</p>
<p>The transformation of if gateways simply generates a corresponding if structure. Concerning parallel gateways, the translation exploits the fact that in a sound model there is always a one-to-one mapping between fork and join gateways. Note that for this to be true one has to consider an implicit join gateway in front of all end events. Furthermore, every throw event is implicitly followed by an end event. These model transformations are performed automatically and do not alter the model semantics.</p>
<p>Each pair of join and fork gateways share a common <em>counter variable</em> for the number of active sequence flows between the fork and the join. So, the translation of the fork gateway is code which first increases the counter by the number of outgoing sequence flows and then calls the respective functions of the outgoing flows in turn. Accordingly, a join gateway results in code which decrements the counter by one. If and only if the counter equals zero the function that covers the single outgoing sequence flow is called.</p>
<p><a href="http://blogs.ethz.ch/copton/files/2011/04/listing1.png">Listing 1</a> shows the transformation of the model in <a href="http://blogs.ethz.ch/copton/files/2011/04/figure3.png">Figure 3</a> in static mode. The tasks <code>off</code> and <code>toggle</code> are non-critical sub-tasks because they only invoke the non-critical basic tasks <code>led_setStatus</code> and <code>led_getStatus</code> (line 20, 24 and 26; not shown in the model). In contrast, <code>sleep</code> is a critical basic task. Thus the continuation <code>blink_after_sleep</code> is stored in the continuation variable <code>continue_sleep</code> before the task is invoked (line 7 and 14). Furthermore, the <code>timeout</code> data item is associated with the <code>sleep</code> task, so that its value is passed to the sub-task (line 8 and 15). </p>
<h3>6. Tools</h3>
<p>The realization of our approach requires a set of integrated tools: an editor, a compiler and a simulator.</p>
<p>The compiler transforms a model into an executable in a three-phase translation. In the first phase, the model is checked for consistency and soundness. Next, the compiler performs a pattern-based platform neutral translation as described in Section 5. The third phase then is platform specific and translates the intermediate representation from phase two into suitable code for the target platform. For each entity, the compiler generates one binary using a back-end for the respective target platform. These binaries can be installed on real hardware or executed in the simulator.</p>
<p>There are several constraints on the model which should be checked by the compiler in phase one. For example, unconnected flows, unused data or undefined tasks are not allowed, and all thrown events must also be caught. Furthermore, a type checker should ensure that data which is associated with a basic task has a type which is suitable to what the task expects. Finally, software developers should be able to implement further checks in order to ensure the correct usage of the building blocks they provide. For example, certain basic tasks might only be allowed to be called once or it might be compulsive that other basic tasks are invoked in a certain order.</p>
<p>As mentioned previously, phase three is platform specific. As the concepts of the intermediate representation are very basic, we expect that it is possible to implement them on different target platforms. The standard compiler tool chain of this platform finally processes the output and links it against the implementation of the platform API and other required platform libraries in order to produce the final binaries.</p>
<p>Compilation and simulation are triggered by the business analysts who use the editor as their primary tool. It allows them to create, browse, and manipulate business process models. Furthermore, it offers means to manage, create, and import model libraries. What distinguishes this editor from all other BPMN editors, though, is the seamless integration of the compiler and the simulator. The editor controls these tools by sending commands and receiving resulting information which are visualized in the model. For example, in case of a constraint violation the compiler propagates the information about the constraint and the violating BPMN component back to the editor. And in case of compilation or runtime errors, the compiler or the simulator can infer the causing BPMN component (c.f. Section 7) so that the editor can then highlight this component in the model. </p>
<p>In the overall development cycle, there are different kinds of possible failures. Constraint violations indicate errors in the model which the business analysts have to correct. In contrast, compilation and runtime errors are the responsibility of the software developers. Either by changing the implementation of the platform API or by adding additional constraints, they have to ensure that a model which passes all constraint tests does not cause such failures. This is important because business analysts typically cannot and should not handle compiler error messages and stack traces. Last, runtime exceptions can occur as part of a valid process and are represented as events in BPMN models where they can be caught and handled. In general, we recommend to avoid the usage of exceptional events in higher level models because they introduce a non-sequential control flow which is sometimes difficult to follow for people with little background in IT.</p>
<p>Section 8 presents a proof of concept implementation of the above described tools. Before that, the following section elaborates on the debugging support, which is one of the major contributions of our work.</p>
<h3>7. Debugging</h3>
<p>A major benefit of a modeling or programming abstraction is the concealment of lower-level details. Without being forced to understand and master all those details, a user of the abstraction can create and maintain applications faster and more intuitively. This benefit is undermined if the application contains an error and there is no debugging support on the application&#8217;s level of abstraction. In such a case, the user has to infer the error in the application code from the details of the generated code. Many WSN programming abstractions suffer from the lack of debugging support <a href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.148.2779">[14]</a>, which we believe hinders their adoption in practice.</p>
<p>Consequently, we want to support debugging on the abstraction level of the BPMN models. To this end the compiler generates a <em>symbol table</em> during phase two. This symbol table maps all components of the input model to locations in the generated code. This information can be used by the tools to retrace the translation between the model and the executable in both directions.</p>
<p>Concerning the tools, debugging support means that everything should be integrated into the editor which is the primary tool for the business analysts. They should be able to set breakpoints at arbitrary points of sequence flows either for a single instance or for all instances of an entity. If such a breakpoint is hit during the runtime of the binaries, for each instance the current progress of all sequence flows and the current value of all data objects should be visualized in the editor. Furthermore, it should be possible to alter the value of data objects and to inject events so that different sequence flow paths can be tested.</p>
<p>A simulator which supports these features must be able to simultaneously execute all instances of all entities. If one instance hits a breakpoint, the execution of all instances has to be stopped so that the editor can query the progress of sequence flows and the value of data objects. To this end, the symbol table helps to map between graphical components and points in the generated executables.</p>
<p>Simulating and testing business processes under various possible conditions gives confidence to the business analysts that the created business process will work as intended once it is deployed. For that, it is crucial that the simulation environment matches the real environment of the business process as close as possible. Furthermore, the models and the basic tasks should not contain non-deterministic behavior because this cannot be reliably tested with the described simulation setup. We suggest that the software developers ensure this by creating models and basic tasks accordingly and by adding constraints to the compiler.</p>
<h3>8. Evaluation</h3>
<p>To evaluate our model-driven methodology, we implemented the required tools as described in Section 6. Our proof of concept implementation supports all described requirements except for changing data object values in a stopped simulation. Furthermore, injecting external events is not integrated into the model editor but has to be done by means of command line tools.</p>
<p><a href="http://blogs.ethz.ch/copton/files/2011/04/figure4.png">Figure 4</a> shows our model editor which is a web-based application based on <a href="http://bpt.hpi.uni-potsdam.de/Oryx">Oryx</a>, a BPMN 2.0 editor distributed under the MIT license. We extended the functionality of the Oryx editor to include plugins that integrate the compiler and the simulator into the editor. The communication interface between the web browser, our compiler toolchain, and the sensor network simulation framework uses a RESTful API with data encapsulated in JSON messages.</p>
<p>We use the <a href="http://www.computer.org/portal/web/csdl/doi/10.1109/SENSORCOMM.2009.27">Mote Runner</a> platform as WSN development environment. The platform hides the intricate details of the underlying hardware by using an efficient virtual machine and micro-manages power on behalf of applications. Applications are programmed using high-level languages which are further transformed to optimized byte-codes.  These features relieve our compiler from hardware-specific details so that it can generate portable high-level code.  Mote Runner additionally provides a simulation environment with a source-level debugger interface which our integrated editor exploits to simulate and debug the same application byte-codes that are executed on real sensor nodes.</p>
<p>The compiler plugin calls the compiler tool which generates C# source code for the Mote Runner platform. The simulator plugin creates the corresponding sensor network configuration for the simulator according to the pools and their respective cardinality. With the aid of the symbol table from the compiler, errors and information from all tools are processed and reported back to the modeler in the browser with warning or error indicators overlaid on the graphical symbols.</p>
<p>To show the generality and expressiveness of the approach, we used our editor to model several applications corresponding to several WSN archetypes <a href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.151.4433">[15]</a>. Firstly, we refined the parcel monitoring scenario described in Section 3 using a single-hop star topology with a <em>Truck</em> and several <em>Parcels</em>. Secondly, we modeled a multi-hop tree-based TDMA protocol where the <em>Master</em> root sends beacons which are re-broadcasted in assigned slots by <em>Slave</em> nodes. This shows that we can even express low-level communication and synchronization details. In addition, we modeled <em>Gather</em> which is a high-level data collection application using a decentralized multi-hop library for the communication. Last, we modeled the base case <em>Blink</em> which toggles an LED every 500 ms to clearly expose the systematic overhead of our approach. </p>
<p>To quantify the efficiency of our approach we measure the usage of resources of the generated code against the hand-written equivalents. To this end, we compiled each application once in static and once in dynamic mode with all tasks treated as parallel tasks (c.f. Section 5). This is only possible because in none of our examples we encountered the need of this feature. Nevertheless, we think it is interesting to know the costs of supporting all BPMN features.</p>
<p>The total amount of consumed energy is an important efficiency measurement because the life time of battery-powered sensor nodes depends directly on it. The maximum stack size and the maximum heap size show how efficiently RAM resources are used while the size of the binary does the same for the flash resources. Finally, the code size is a common indicator for code complexity. All measurements were obtained using the simulation environment running for 30 seconds which is enough time to measure and explore both the normal sequence flows as well as the exceptional code paths.</p>
<p>Once a process behaved in the simulation as expected, we used <a href="http://www.memsic.com">Iris</a> sensor nodes which have an 8-bit micro-controller, 128 kB of flash and 8 kB of RAM for a test deployment. We did not measure the resource consumption on the real hardware because the Mote Runner simulator provides accurate measurements by design. Instead, we thereby only verified that the generated code is efficient enough to be executed on such a resource-constrained device.</p>
<p><a href="http://blogs.ethz.ch/copton/files/2011/04/figure5.png">Figure 5</a> shows the results of the evaluation. First, we see that the energy consumption overhead for each compilation mode is only 1%. This is because WSN applications are reactive by nature, where sleeping periods dominate computations.</p>
<p>Second, the overhead for the RAM usage averages at 10% in the static case and 50% in the dynamic mode. In contrast, the size of the binary and the code show that the systematic transformation of the model results in twice more code than a software developer needs for the same task. On average, the overhead for the flash consumption is 44% for the static mode and 3 times more space for the dynamic mode.</p>
<p>In practice, the energy consumption is the most important efficiency characteristic of an application as long as the employed mote provides enough resources to host it. As we could show that the generated code fits on a typical mote and the additional energy consumption is very low, we argue that the benefits of the code generation outweigh the introduced overhead. This is especially true for the static mode for which the overhead is moderate given that flash space is usually not the major limiting resource on motes.</p>
<p>Concerning the dynamic mode, it is currently not clear if parallel tasks are used rather often or rather seldom when modelling WSN applications. All we can say is that the total overhead of the compiled code will fall between the two measured extremes depending on how often parallel tasks are used. Additionally, our proof of concept implementation does not exploit possible optimizations which can reduce the overhead of the translation.</p>
<h3>9. Summary and Conclusion</h3>
<p>In this paper we focus on business processes using wireless sensor networks. Our main contribution is enabling business analysts to control the execution of such a process on the abstract level of its BPMN model. Furthermore, we enable them to test and debug their models on the same level of abstraction. By this means, we close the gap between the specification and the actual implementation of business processes.</p>
<p>We achieve this by introducing a compiler which translates the sequential execution semantics of BPMN models into event-driven code suitable for common sensor network platforms. Software developers provide a set of building blocks which can be reused by different models. These building blocks can be either directly programmed or also modelled in BPMN depending on the desired level of abstraction. </p>
<p>We additionally elaborated on the set of required tools and presented a proof of concept implementation thereof. Our evaluation results on several case studies show that the generated code is only 1% less energy efficient than hand-written equivalents. Concerning RAM and flash usage, though, the overhead is higher. Nevertheless, we could show that the generated applications fit on standard motes.</p>
<p>In summary, we argue that the introduced overhead is worth the benefits of keeping business processes synchronized with their implementations. We argue that the parts of a business process which involve WSN can and should be automatically generated directly from the model specification. Thus, organizations can dynamically adapt their technology implementation according to their business processes and not vice versa.</p>
<h4>Meta</h4>
<ul>
<li>This is a paper published at the <a href="http://www.dcoss.org/">7th IEEE International Conference on Distributed Computing in Sensor Systems (DCOSS 2011)</a>.</li>
<li>This is joint work with Alexandru Caracas from <a href="http://www.zurich.ibm.com/">IBM Research, Zürich</a>.</li>
<li>This work has been partially supported by the National Competence Center in Research on Mobile Information and Communication Systems (<a href="http://www.mics.org/">NCCR-MICS</a>), a center supported by the Swiss National Science Foundation under grant number 5005-67322, and by <a href="http://www.cooperating-objects.eu/">CONET</a>, the Cooperating Objects Network of Excellence, funded by the European Commission under FP7 with contract number FP7-2007-2-224053.</li>
<li>This work has been supported by Thorsten Kramp from <a href="http://www.zurich.ibm.com/">IBM Research, Zürich</a> and the <a href="http://www.zurich.ibm.com/moterunner/">Mote Runner team</a>.</li>
<li><a href="http://www.vs.inf.ethz.ch/publ/papers/caracas-compil-2011.pdf">.pdf</a>, <a href="http://www.vs.inf.ethz.ch/publ/bibtex.html?file=papers/caracas-compil-2011">BibTex</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blogs.ethz.ch/copton/2011/04/07/compiling-business-process-models-for-sensor-networks/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MPS Experience</title>
		<link>http://blogs.ethz.ch/copton/2010/10/23/mps-experience/</link>
		<comments>http://blogs.ethz.ch/copton/2010/10/23/mps-experience/#comments</comments>
		<pubDate>Sat, 23 Oct 2010 17:58:41 +0000</pubDate>
		<dc:creator>Alexander</dc:creator>
				<category><![CDATA[article]]></category>
		<category><![CDATA[code generation]]></category>

		<guid isPermaLink="false">http://blogs.ethz.ch/copton/?p=508</guid>
		<description><![CDATA[I have recently worked quite a bit with the language workbench MPS and I think it&#8217;s about time to note the experiences I have made and the background knowledge I have collected. Language Oriented Programming First of all, in the context of language workbenches, differentiating between programs and models becomes cumbersome and adds no benefit [...]]]></description>
			<content:encoded><![CDATA[<p>I have recently worked quite a bit with the <a href="http://martinfowler.com/articles/languageWorkbench.html">language workbench</a> <a href="http://www.jetbrains.com/mps/">MPS</a> and I think it&#8217;s about time to note the experiences I have made and the background knowledge I have collected.</p>
<p><span id="more-508"></span></p>
<h3>Language Oriented Programming</h3>
<p>First of all, in the context of language workbenches, differentiating between programs and models becomes cumbersome and adds no benefit to solving a given problem. That&#8217;s why some people refer to a program or a model as a &#8220;mogram&#8221;, but I prefer the general term <em>document</em> because in fact it doesn&#8217;t really matter if the generated output has execution semantics or not. So, a document is an instance of a language which is a set of meta-classes, so-called <em>concepts</em>, which can contain other concepts or refer to them. An instance of a concept is called a <em>node</em>, so a document is a tree of nodes which refer to each other.</p>
<p>Given this terminology, the basic idea behind MPS is to create, view and manipulate document trees instead of text files [<a href="http://www.onboard.jetbrains.com/articles/04/10/lop/">Dmitriev</a>]. The major advantage of this approach is that no parsing is necessary, thus the design and the composition of languages is not constrained by technical necessities such as the unambiguity of the grammar or problems with left recursion and so on. In fact, I see a lot of analogies to what makes XML extensible and why Lisp is such a flexible language. In either case, there is a simple syntax for describing document trees while the creation and composition of such trees is unrestricted in large parts. In other words, there is a single parser which is capable of parsing all supported documents.</p>
<p>The document trees in MPS are stored as XML. But the user interface is not a text editor but a composition of tree editors instead. Every concept has an editor attached that provides projections of corresponding nodes. Editors form a hierarchy just like concepts do because an editor of a concept can use the editors of containing concepts. Furthermore, editors can be conditional so that different projections of a given tree are possible under different circumstances. The major benefit of the tree editors is that in contrast to XML and Lisp the contents of a tree can be displayed in a nice and domain-specific way. In most cases, a projection of a tree looks like text but in general graphical projections are also possible.</p>
<p>Generators translate documents into different documents. To this end, there are various kinds of generators that support different transformation techniques such as local search-and-replace of nodes or pattern-based transformations along the lines of XSLT. Document transformations can be chained and the language of the final document is called a <em>base language</em> and has a so-called <code>TextGen</code> aspect attached to each of its concepts. This aspect specifies how a respective node can be translated into text. So, MPS effectively generates text which can be further processed by common compiler tool chains. </p>
<p>In contrast to other code generation techniques, MPS completely knows the target language of a generator. Thus the IDE supports you with context assisting, constraint checking, syntax highlighting and all the other features, which other language workbenches only provide for source languages. However, this also means that if you want to generate code for a certain language there must be an MPS implementation of that language available. Up to now, MPS originally only supports the Java programming language.</p>
<p>Generators and all other aspects of a language are themselves documents of languages provided by MPS and are created by means of the respective tree editors. In other words, MPS consists of a set of domain-specific languages, each for a different aspects of the domain of creating domain-specific languages. This recursion is not only cool but also important because it is possible to extend the language for building generators and thus introduce specialized generators for a given type of a language. In my opinion, this rocks.</p>
<h3>The problems with tree projection</h3>
<p>As outlined above, MPS documents are created and manipulated by means of projection-based tree editing only. Although most projections look like text at first sight, the underlying tree is omnipresent. In fact, what you have to do to create a document is to create its defining tree. Basically, this means that you have to know how the trees of your language are structured, create one node after the other with the help of the context assistant and set their properties by means of the editors. As this is cumbersome and time consuming, MPS supports a bunch of mitigating techniques.</p>
<p>For example, it is possible to define so-called <em>aliases</em> that are strings which when entered into the editor are replaced by a node of a particular concept. Additionally, there are so-called <em>side transformation rules</em> which execute a mini-generator if a given string is entered left or right of a node satisfying a given condition. So, instead of creating a <code>Plus</code> node with two <code>Number</code> children you could type <code>+</code> next to a <code>Number</code> node to get the same effect. As a last example, <em>intentions</em> offer context-specific transformations which can be triggered manually. Such local transformations in various different flavors all help to make creating documents more comfortable and manageable.</p>
<p>Up to my experience, though, the tree nature of the documents never vanishes. If you want to change your document in a way which has not been anticipated by the language creators and thus is not directly supported, you end up in manually manipulating the tree again. For example, when enriching the behavior of concepts with Java-code, you sometimes create an <code>if</code> statement with a rather complex condition. If after creating the statement you realize that in fact you need the negation of that condition, there better is an intention prepared for that. Otherwise, you copy the condition into the clipboard, and paste it back as the child of a newly created node representing a negation expression. If the structure of the language is complicated, sticking nodes together to form the intended tree becomes really difficult.</p>
<p>In case of the MPS languages, things are even worse because there is no way to create the intended document node by node. Instead, you have to use the ways that are predefined by the IDE. A good example in this context is the fact that there is no way to turn a concrete concept into a interface concept or vice versa. As in MPS a concept can inherent from at most one other concept, you need interface concepts to simulate multiple inheritance. In a text-based environment replacing the keyword <code>class</code> with the keyword <code>interface</code> would be all you had to do to change the type of the concept. In the current MPS version, though, you have to remove the concept, create a concept interface, define its properties, children, references, and so on and update all references to the concrete concept to point to the concept interface instead. The upcoming MPS version is supposed to have refactoring support for this case, but still this example demonstrates that in MPS you need tool support for every single possible creation or manipulation task. Things become messy for the user otherwise.</p>
<p>Aside from the above-mentioned cases, the tree nature of MPS documents additionally manifests itself when navigating a document. You have to get used to the fact that moving the cursor or deleting stuff works on nodes instead of characters. If you know the structure of your tree this allows you to navigate your document incredibly fast. But if you don&#8217;t, it can be confusing. And if the focus is on a property of a node, the navigation does work on the granularity of characters. Maybe I didn&#8217;t try hard or long enough, but navigating document trees in MPS never felt like an intuitive task to me.</p>
<p>Finally, the tree editors always show the results of the creation and manipulation of nodes. But they never show, how this result has been achieved. So if you want to figure out how something can be done you can not just look at other examples because they don&#8217;t tell you how to interact with the IDE to get what you see. In contrast, in case of text-based languages, you simply copy the text and you are done.</p>
<p>If you want to create a new language in MPS, you have to complete the following tasks:</p>
<ul>
<li>You have to define the structure of your language, i.e. the concepts and their hierarchy.</li>
<li>You have to define a type system in order to constraint valid documents in ways which can not be expressed by a reasonable set of concepts. </li>
<li>You have to specify constraints for properties, child concepts and references to nodes. For example, this is needed to support scopes in your language.</li>
<li>If you create a base language you have to define the <code>TextGen</code> aspect for all concepts.</li>
<li>If you don&#8217;t create a base language you have to define generators which process documents of your language towards a given target base language.</li>
<li>You have to define and tune the editors for the concepts to get a nice visualization of the documents.</li>
<li>You have to identify common usage patterns and define local transformations and intentions for them.</li>
</ul>
<p>All but the last two tasks have to be done in other language workbenches as well. But the last two tasks are extra work which is necessary to enable of the projection-based tree editing and to compensate for its disadvantages.</p>
<h3>The MPS implementation</h3>
<p>The MPS project is a huge scientific and engineering effort and I really respect the work that has been done by JetBrains. From a user&#8217;s perspective, though, unfortunately it is not enough yet. MPS requires and contains a lot of features which means that a lot of code paths have to be tested and a lot of documentation has to be written. Both things require time and money which might be the reason why they have not been sufficiently done yet. So, if you use MPS, be prepared to encounter bugs. I did so on a daily basis. And if you want to figure out how to do something you better have somebody to ask because the documentation is incomplete and partially inconsistent. Don&#8217;t get me wrong, I don&#8217;t blame anybody. I just want to point out why in my opinion MPS is not yet ready to be used by the public.</p>
<p>The features that do work, though, are really cool. For example, the context assistant is really powerful and it is very easy to use it for your own languages. In fact, all you have to do is derive your concepts from <code>INamedConcept</code> whenever they have a name and use <code>smart references</code> which are concepts with a single reference with granularity one. The context assistant resolves such references and displays the name of the nodes in question in its menu. Furthermore, by means of reference constraint you can limit the set of nodes which are possible as a valid reference and thus offered by the context assistant menu.</p>
<p>Something I find a little bit weird is the language used for the editors. An editor is a set of cells arranged in rows and columns. Each cell has a number of styles and properties which configure the respective projection. Some of these properties are defined directly in the editor of the editor. Other cell properties are only accessible by means of the so-called <em>inspector</em> which is a general property editor for MPS objects. </p>
<p>In my experience, getting the editors right is not trivial. For example, when projecting a do-while-loop the editor could look like <code>[&gt; do %body% while( %condition% ); &lt;]</code> which is a horizontal alignment of the constant strings <code>do</code>, <code>while(</code>, and <code>);</code> and the child nodes named body and condition. If the editor of the body is a block statement and thus uses multiple rows, in the projection of a do-node the while-part follows right of the body but on the same line as the do-part. I know that there should exist a combination of cells with the right properties and styles to get a C-like projection with the while-part following the curly braces of the block statement but I never managed to figure it out.</p>
<h3>Conclusion</h3>
<p>Me experience with MPS comes mainly from my efforts to create a C99 implementation for MPS. The C99 standard is complex and partially weird. So the disadvantages of MPS that I encountered are amplified by the peculiarities of the C99 language. I am sure, that in many cases, DSLs are much simpler and thus the problems of tree-based editing are not so predominant. </p>
<p>In conclusion, I have no final opinion yet, to be honest. It&#8217;s clear that you have to get used to the projection-based tree editing. But as I think people should be willing to learn new paradigms if it pays out, the real question is whether it pays out or not.</p>
<p>Being relieved from parsers really eases the creation and especially the composition of languages. But as discussed above, projection-based tree editing is cumbersome because you basically have to create every single node manually. Maybe, in the future, somebody will come up with a way to create document trees by means of projection-based tree editing which is as fast as writing text which a parser turns into a document tree. Until then, special tool support is required to accelerate the creation of document trees and make it feasible. And providing this tool support is time-consuming because you have to identify all common usage patterns to begin with.</p>
<p>Furthermore, I have the impression that no matter how much tool support you provide your users have to learn the structure of the language. Compared to learning a syntax this seems to be harder to manage. But maybe it&#8217;s just a matter of getting used to it again. I don&#8217;t know yet.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.ethz.ch/copton/2010/10/23/mps-experience/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Did you know? Funny facts about C99</title>
		<link>http://blogs.ethz.ch/copton/2010/10/06/did-you-know-funny-facts-about-c99/</link>
		<comments>http://blogs.ethz.ch/copton/2010/10/06/did-you-know-funny-facts-about-c99/#comments</comments>
		<pubDate>Wed, 06 Oct 2010 16:47:06 +0000</pubDate>
		<dc:creator>Alexander</dc:creator>
				<category><![CDATA[article]]></category>
		<category><![CDATA[C/C++]]></category>

		<guid isPermaLink="false">http://blogs.ethz.ch/copton/?p=467</guid>
		<description><![CDATA[I am currently writing an implementation of the C99 programming language as a basic language for the MPS language workbench. I call this implementation c-base, because it is intended to be used as a target language for code generation, much like MPS&#8217; Java-like base-language. I created the model of this MPS language according to the [...]]]></description>
			<content:encoded><![CDATA[<p>I am currently writing an implementation of the <a href="http://en.wikipedia.org/wiki/C99">C99 programming language</a> as a basic language for the <a href="http://www.jetbrains.com/mps/">MPS</a> <a href="http://www.martinfowler.com/articles/languageWorkbench.html">language workbench</a>. I call this implementation <a href="http://github.com/copton/c-base/">c-base</a>, because it is intended to be used as a target language for code generation, much like MPS&#8217; Java-like base-language.</p>
<p>I created the model of this MPS language according to the C99 standard grammar. Thus, I had to dive into its documentation and I have found a number of surprising features and properties of the C99 programming language. Not all of them are important, but if you want to be nitpicker in the next C discussion, here is your ammo <img src='http://blogs.ethz.ch/copton/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p>So, did you know, that</p>
<p><span id="more-467"></span></p>
<h3>the size of a byte is implementation-defined? (3.6)</h3>
<p>In contrast to an octet, a byte does not always consist of 8 bits. Instead, it is an &#8220;addressable unit of data storage large enough to hold any member of the basic character set of the execution environment&#8221;.</p>
<h3><code>argv[argc]</code> shall be a null pointer? (5.1.2.2.1.2)</h3>
<p>Very convenient indeed. But I haven&#8217;t seen code yet which relies on this.</p>
<h3><code>0</code> is not a decimal constant? (6.4.4.1)</h3>
<p>There are three different types of integer constants, i.e. octal, decimal and hexadecimal integer constants. Octal integers constants are prefixed by <code>0</code>, hexadecimal constants are prefixed by <code>0x</code> and for decimal constants there is no prefix. Thus a single <code>0</code> is an octal integer constant.</p>
<h3>there are hexadecimal floating point constants? (6.4.4.2)</h3>
<p>There are two different types of floating constants, i.e. decimal and hexadecimal floating constants. Octal floating constants are not supported.</p>
<p>As <code>e</code> is a valid hexadecimal digit, the delimiter for the exponent part of a hexadecimal floating constant is <code>p</code>. The base for the exponent is two and the exponent itself is a decimal number. So <code>0xap1</code> equals <code>20</code>, and <code>0xap10</code> equals <code>10240</code>.</p>
<h3>there are two different types of for-loops? (6.8.5)</h3>
<p>We know that the header of a for-loop consists of three optional parts separated by semicolons. But in fact that&#8217;s not true. Instead, only the second and the third header part are always optional expressions. For the first header part, though, things depend on the type of the for-loop.</p>
<p>There are two such types. In case of the first type, the first header part is also an optional expression. As this expression is evaluated once when before starting the first iteration of the loop, it could likewise be moved in front of the loop. What the first part of a for-loop is most used, though, is the declaration of a variable which is scoped by the loop body. As declarations are not expressions, this is not possible with this type of for-loop.</p>
<p>That&#8217;s why there is a second type of for-loop, where the first part is a declaration. The funny thing is, that in this case the first semicolon is not part of the for loop. Instead, it is the delimiter of the declaration. In order to disallow for-loops with only one semicolon, the first header part is not optional in this case. So <code>for(; i&lt;2; i++){}</code> is a for-loop of the first type with an omitted expression as its first header part.</p>
<h3>a <code>typedef</code> declaration does not introduce a new type? (6.7.7)</h3>
<p>Instead, only a synonym for the type is specified. I have seen people ranting about C being not type safe, because the compiler allows to use a <code>foo</code> when a <code>bar</code> is expected, if both identifiers are typedefs of the same type. <em>d&#8217;oh</em></p>
<h3>the <code>typedef</code> specifier is a storage-class specifier? (6.7.1.3)</h3>
<p>The other storage-class specifiers are <code>extern</code>, <code>static</code>, <code>auto</code>, and <code>register</code>. They all deal with how the declared object is stored. <code>typedef</code> is a storage-class specifier, &#8220;for syntactic convenience only&#8221;. </p>
<p>Storage-class specifiers precede declarations which specify &#8220;the interpretation and attributes for a set of identifiers&#8221;. If the storage-class specifier is <code>typedef</code>, these identifiers become synonyms for the respective type. So, <code>typedef int a, (*b)()</code> introduces at one swoop <code>a</code> as a synonym for <code>int</code> and <code>b</code> as a synonym for pointer to function with no parameters and returning <code>int</code>. </p>
<p>From my experience, I have never seen anybody using this feature. So I wonder, how convenient this grammatical hack really is.</p>
<h3>the coupling of <code>switch</code> statements and <code>case</code> labels is rather loose? (6.8.4.2)</h3>
<p>The body of a <code>switch</code> statement is a statement. Most often this is a block statement with <code>case</code> labels and/or a <code>default</code> label. But this is not required. Instead, <code>switch(42) i++;</code> is valid C99 code, where <code>i++</code> is not executed, because there is no matching <code>case</code> constant expression and no <code>default</code> label in the body of the <code>switch</code> statement.</p>
<p>In general, possible jump targets of <code>switch</code> statement are all <code>case</code> labels which are &#8220;in or on the the switch body&#8221;, excluding those which are part of an enclosed <code>switch</code> statement. Apparently, being &#8220;in the switch body&#8221; recursively includes any block statements, enabling things like <a href="http://en.wikipedia.org/wiki/Duffs_device">duff&#8217;s device</a>. As far as I can tell, though, this is not explicitly stated in the standard.</p>
<h3>the grammar defines a rather large superset of the language?</h3>
<p>A grammar describes the building blocks of a language and the rules of combining them. The C99 grammar is very permissive concerning the combination rules. Many things are later disallowed by textually written constraints. But some things are not, although they make no sense.</p>
<p>An example for additional constraints is that the grammar allows an arbitrary list of type qualifiers and type, function and storage-class specifiers preceding a declaration (6.7). Later, 6.7.1.2 states that &#8220;at most one storage-class specifier may be given&#8221; and 6.7.2 requires that &#8220;at least on type specifier shall be given&#8221;. Furthermore, the set of allowed unordered sublists of all type specifiers is enlisted. For example, <code>int static long volatile unsigned i;</code> is a valid declaration, because <code>static</code> is a storage-class specifier, <code>volatile</code> is a type qualifier and <code>unsigned long int</code> is a valid sublist of type specifiers.</p>
<p>An example for &#8211; in my opinion &#8211; forgotten constraints is that a struct definition is a struct specifier which is a type specifier which is a declaration specifier which is part of a parameter declaration (6.7.5). This means, that <code>void f(struct foo { int i; } j);</code> is valid C99 code, although the syntax highlighting of my <a href="http://www.vim.org/">Vim</a> goes crazy about this. <a href="http://gcc.gnu.org/">GCC</a> issues a warning, that &#8220;‘struct foo’ declared inside parameter list&#8221; and &#8220;its scope is only this definition or declaration, which is probably not what you want&#8221;. Indeed, 6.2.1.4 says, that &#8220;if [...] the type specifier [...] appears within the list of parameter declarations [...] the identifier has function prototype scope, which terminates at the end of the function declarator.&#8221; I can hardly imagine a case in which a type definition with function prototype scope is needed. So I wonder, why this isn&#8217;t forbidden.</p>
<h3>there is a clear definition of side effect? (5.1.2.3.2)</h3>
<p>&#8220;Accessing a volatile object, modifying an object, modifying a file, or calling a function that does any of those operations are all side effects&#8221;. It can be so easy.</p>
<h3><code>_Bool</code> is a standard type? (6.2.5.2)</h3>
<p>Before C99 there was no Boolean type. Instead, everybody had its own type synonyms and pre-processor macros. In order to no collide with existing code, C99 introduces the keyword Bool with a underscore prefix. But actually you are not supposed to use it, as there is a macro <code>bool</code> which expands to <code>_Bool</code> in stdbool.h (7.16). Furthermore, there are macros for <code>true</code> and <code>false</code> which expand to the integer constants 1 and 0, unless you redefine them. By the way, &#8220;an object declared as type <code>_Bool</code> is large enough to store the values 0 and 1&#8243;.</p>
<h3><code>_Complex</code> is a keyword? (6.2.5.11)</h3>
<p>Common floating represent real numbers. If you prefix a floating type with <code>_Complex</code> it becomes a complex number and is stored as an array of two elements of the corresponding floating type (6.2.5.13).</p>
<h3><code>_Imaginary</code> is a keyword? (6.4.1)</h3>
<p>But it is only reserved for specifying imaginary types. It is not normative because &#8220;there is little existing practice to validate the design decisions&#8221; (G.1).</p>
<h3>there are different character sets? (5.2.1)</h3>
<p>The <em>basic character set</em> contains the common ASCII upper and lowercase letters, special characters and white spaces. The <em>extended character set</em> contains the basic character set and zero or more implementation defined characters. This is meant to support characteristics of the the various locales. Furthermore, C99 distinguishes between the <em>source character set</em> and the <em>execution character set</em>. The former is the set of characters which form source files. The latter is the set of characters available at execution time. Elements from the execution character set are represented by corresponding elements of the source character set or by escape sequences.</p>
<h3>some special characters can be represented by trigraphs? (5.2.1.1)</h3>
<p>The output of the <code>puts("wtf??!");</code> is &#8220;wtf|&#8221;, because &#8220;??!&#8221; is a trigraph sequence which is replaced by &#8220;|&#8221; &#8220;before any other processing takes place&#8221;. In total, there are nine different trigraph sequences, all starting with &#8220;??&#8221;. So you should escape question marks in string literals. The output of <code>puts("wtf\?\?!");</code> is &#8220;wtf??!&#8221;. </p>
<p>Fortunately, <a href="http://gcc.gnu.org">GCC</a> disables trigraphs by default and issues a warning if the source files contains trigraphs. </p>
<h3>some punctuators can be represented by digraphs? (6.4.6.3)</h3>
<p>In contrast to trigraphs, digraphs are replaced after tokenization. In particular, this means that digraphs within string literals are not replaced. In total, there are six different digraphs, all starting with an opening angle bracket or with a percent sign. The represented punctuators are opening and closing square brackets, opening and closing curly brackets and single or double hash.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.ethz.ch/copton/2010/10/06/did-you-know-funny-facts-about-c99/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Programming Abstractions with Debugging Support for Resource-Constrained Devices</title>
		<link>http://blogs.ethz.ch/copton/2010/10/05/programming-abstractions-with-debugging-support-for-resource-constrained-devices/</link>
		<comments>http://blogs.ethz.ch/copton/2010/10/05/programming-abstractions-with-debugging-support-for-resource-constrained-devices/#comments</comments>
		<pubDate>Tue, 05 Oct 2010 13:09:28 +0000</pubDate>
		<dc:creator>Alexander</dc:creator>
				<category><![CDATA[publication]]></category>
		<category><![CDATA[code generation]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[wireless sensor networks]]></category>

		<guid isPermaLink="false">http://blogs.ethz.ch/copton/?p=454</guid>
		<description><![CDATA[Abstractions are crucial in order to manage complex systems. In pervasive computing, though, common programming abstractions tend to be too expensive for the employed resource-constrained devices. In recent years, the wireless sensor network community has proposed several solutions to this problem. However, little has been done to also support debugging on the level of the [...]]]></description>
			<content:encoded><![CDATA[<p>
Abstractions are crucial in order to manage complex systems. In pervasive computing, though, common programming abstractions tend to be too expensive for the employed resource-constrained devices. In recent years, the wireless sensor network community has proposed several solutions to this problem. However, little has been done to also support debugging on the level of the abstraction. Instead, a developer is forced to understand the lower-level details in order to find and correct defects. This clearly hampers the development of applications. We aim at advancing the state of the art in programming of resource-constrained devices by introducing debugging support for programming abstractions.
</p>
<p><span id="more-454"></span></p>
<h3>Introduction</h3>
<p>
Pervasive computing aims at enriching modern life with IT services which form a smart infrastructure embedded in everyday environments. With increasingly cheaper, smaller, more efficient and in general more capable hardware, more and more pervasive applications are becoming possible. Examples include <a href="http://www.springerlink.com/content/622828mx75508148/">healthcare platforms for diabetes management</a> and <a href="http://sing.stanford.edu/slides/kazandjieva-hotemnets-2010.pdf">measurement platforms for human contact networks and epidemiology research</a>.
</p>
<p>
The unobtrusive integration of pervasive applications into the real world often requires tiny, battery-powered devices to cooperate in a distributed fashion over wireless links. Due to these requirements, pervasive applications tend to be complex and thus difficult to develop, deploy and maintain. In order to make the complexity manageable, suitable programming abstractions which help writing and maintaining code for the devices are required. Unfortunately, programming abstractions offered by high-level programming languages tend to require more CPU and memory resources than a pervasive computing device typically offers. As a consequence, pervasive applications are often implemented in the C programming language which offers only few and rather low-level programming abstractions. Thus, most pervasive applications are notoriously hard to write, deploy and maintain.
</p>
<p>
The need for programming abstractions for resource-constrained devices has since long been recognized by the research community, in particular in the field of <em>wireless sensor network (WSN)</em>. WSNs are a pervasive computing technology which supports monitoring of physical phenomena over a potentially large spatial region. Because the peculiarities of pervasive computing which drive the demand for programming abstractions are especially predominant in WSNs, a number of solutions have been proposed in the past few years [<a href="http://www.sics.se/~luca/papers/mottola10programming.pdf">Mottola</a>].
</p>
<p>
Little has been done, though, to also support debugging on the level of the abstraction [<a href="http://www.sics.se/~luca/papers/mottola10programming.pdf">Mottola</a>]. As a consequence, software developers often have to understand lower-level details such as the syntax and semantics of generated code in order to trace program errors. As hiding lower-level details is one of the main goals of abstractions, we consider programming abstractions without debugging support as incomplete.
</p>
<p>
We thus want to investigate programming abstractions with debugging support for resource-constrained devices. In particular, we focus on WSN because many programming abstractions without debugging support already exist in this field. We furthermore expect our results to be also applicable to other fields of pervasive computing.
</p>
<h3>State of the Art</h3>
<p>
WSN programming abstractions can be classified by two major orthogonal dimensions: <em>node-centric</em> vs. <em>distributed</em> and <em>imperative</em> vs. <em>declarative</em> [<a href="http://www.sics.se/~luca/papers/mottola10programming.pdf">Mottola</a>]. Node-centric abstractions focus on programming single nodes which might or might not form a distributed system. In contrast, abstractions for distributed applications account for the distributed nature of the application and support the programming of groups of nodes such as spatial or logical neighborhoods.
</p>
<p>
Irrespective of the first dimension, with imperative abstractions <q>the intended application processing is expressed through statements that explicitly indicate how to change the program state</q> [<a href="http://www.sics.se/~luca/papers/mottola10programming.pdf">Mottola</a>]. In contrast, for declarative abstractions <q>the application goal is described without specifying how it is accomplished</q> [<a href="http://www.sics.se/~luca/papers/mottola10programming.pdf">Mottola</a>]. Out of the four possible classes of programming abstractions only three are  relevant in practice and we discuss them in the following.
</p>
<p>
Protothreads <a href="http://www.sics.se/~adam/pt/">Protothreads</a> and <a href="http://portal.acm.org/citation.cfm?id=1765579">TinyVT</a> are node-centric, imperative programming abstractions. They offer compiler-based thread abstractions by taking a thread-based program as input and generating a semantically equivalent event-based program for the targeted event-based operating system. While this combines the comfort of thread-based programming with the efficiency of events, both of them have no debugging support. Thus, a developer is forced to step through the generated event-based code in order to identify defects in the thread-based program.
</p>
<p>
A second class of programming abstractions is imperative and distributed programming abstractions which are commonly known as macro-programming in the WSN community. While the existing abstractions like <a href="http://portal.acm.org/citation.cfm?id=1095810.1118600">Kairos</a> and <a href="http://portal.acm.org/citation.cfm?id=1236422">Regiment</a> are powerful, their practical adoption seems to suffer from the lack of debugging support. In this case, besides the knowledge of lower-level details, a software developer additionally needs special tools such as distributed debuggers (<a href="http://portal.acm.org/citation.cfm?id=1322263.1322282">Clairvoyant</a>) because a single macro-program controls the behavior of many distributed devices. Compared to node-centric abstractions, the lack of debugging support on the level of the abstraction is therefore even more severe. To the best of our knowledge, the only macro-programming language with debugging support is <a href="http://portal.acm.org/citation.cfm?id=1460412.1460435">MacroLab</a> which is a dialect of <a href="http://www.mathworks.com/products/matlab/">MATLAB</a> and can be debugged with the <a href="http://portal.acm.org/citation.cfm?id=1644038.1644053">Macrodebugger</a>, a post-mortem debugger specifically crafted for MacroLab. </p>
<p>
Two well-known declarative and distributed programming abstractions are Cougar <a href="http://portal.acm.org/citation.cfm?id=601861">Cougar</a> and <a href="http://portal.acm.org/citation.cfm?id=872817">TinyDB</a>. They model a WSN as a relational database and support SQL-like queries to retrieve information about the monitored physical phenomena. While this is what users presumably want, if an error occurs somewhere in the distributed system, the user has to resort to other means like passive inspection of the network traffic (<a href="http://www.vs.inf.ethz.ch/publ/papers/mringwal-snif-kuvs.pdf">SNIF</a>) in order to find the cause of the problem.
</p>
<p>
Since WSN applications are rather diverse, suitable programming abstractions will have to be specifically crafted for a given application domain. Such programming abstractions are usually implemented by so-called <a href="http://martinfowler.com/dslwip/">domain-specific languages (DSL)</a>. In software engineering there is an ongoing trend towards DSLs in general and DSLs for building DSLs in particular (<a href="http://www.actifsource.com/">actifsource</a>, <a href="http://www.jetbrains.com/mps/">MPS</a>, <a href="http://www.eclipse.org/Xtext/">Xtext</a>, <a href="http://strategoxt.org/Spoofax">Spoofax</a>, <a href="http://www.metacase.com/mep/">MetaEdit+</a>). With the support of these so-called <a href="http://www.martinfowler.com/articles/languageWorkbench.html">language workbenches</a> it is rather easy to quickly introduce DSLs and to implement the corresponding compiler. Again, though, the issue of debugging on the level of the abstraction has not been solved yet.
</p>
<h3>Goals of my Thesis</h3>
<p>
The goal of my thesis is to introduce debugging support of programming abstractions for resource-constrained devices. To this end, we will focus our investigations on two major topics.
</p>
<p>
First, as a concrete example we want to introduce a debuggable, compiler-based thread abstraction for event-based operating systems. The expected outcome is that from a developer&#8217;s perspective there is not much difference from using our compiler to using a thread library. But still, the achieved efficiency is as close as possible to the efficiency of hand-written event-based code. Furthermore, source-level debugging of the thread-based program is possible.
</p>
<p>
Compared to thread libraries there are theoretical limits of what features a compiler-based approach can offer. These limitations stem from the fact that a compiler can only process decidable problems. In order to stay within these theoretical bounds, we can neither commonly support calling blocking operations by function pointers nor calling blocking functions from recursive functions. Furthermore, dynamically starting new threads is not possible. However, as it is advisable to statically ensure that the scarce resources of a given device suffice the demands of a given program, such dynamic features are rarely used for embedded systems. Thus, we don&#8217;t consider these limitations to be severe, especially considering that we expect to be able to get close to the efficiency of the event-based paradigm.
</p>
<p>
Additionally, if the compiler records which thread-based code was translated into which part of the event-based program, it becomes possible to perform source level debugging in the thread-based code. In principle, this technique is very similar to what C tool chains use in order to support source-level debugging of C programs. Thus, we expect to be able to reuse and build upon a large number of existing work such as the <a href="http://dwarfstd.org/">DWARF Debugging Standard</a>.
</p>
<p>
For the second part of the thesis, we want to investigate in more general terms how programming abstractions can be designed and built in a way such that debugging support is included. Therefore we want to identify standard debugging techniques for the various types of programming abstractions encountered in the WSN field. By extending existing language workbenches we enable the design and implementation of various types of DSLs with the respective debugging support integrated. The expected outcome is that software developers will be able to easily create programming abstractions like TinyDB or Kairos with integrated debugging support.
</p>
<p>
For node-centric and imperative DLSs, simple debugging information emitted by the compiler is known to suffice. For distributed DLSs, though, existing debugging tools such as distributed debuggers (<a href="http://portal.acm.org/citation.cfm?id=1322263.1322282">Clairvoyant</a>) or passive distributed assertions (<a href="http://portal.acm.org/citation.cfm?id=1602196">PDA</a>) must be incorporated into the tool chain such that information about an error which is reported from the debugging tool points to the error&#8217;s cause in the program. In the case of declarative programming abstractions, debugging is even harder because there is no one-to-one mapping between the program and the generated code. Thus, more detailed information is necessary in order to be able to map from the generated code back to the program.
</p>
<h3>Meta</h3>
<ul>
<li>This is a paper published at the <a href="http://www.vs.inf.ethz.ch/events/sensys10dc/">Doctoral Colloquium</a> of the <a href="http://sensys.acm.org/2010/">8th ACM Conference on Embedded Networked Sensor Systems (SenSys 2010)</a>.</li>
<li>This work has been partially supported by the National Competence Center in Research on Mobile Information and Communication Systems (<a href="http://www.mics.org/">NCCR-MICS</a>), a center supported by the Swiss National Science Foundation under grant number 5005-67322, and by <a href="http://www.cooperating-objects.eu/">CONET</a>, the Cooperating Objects Network of Excellence, funded by the European Commission under FP7 with contract number FP7-2007-2-224053.</li>
<li>I want to thank <a href="http://www.iti.uni-luebeck.de/index.php?id=roemer&amp;L=1">Prof. Dr. Kay Römer</a> for supporting me with this work.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blogs.ethz.ch/copton/2010/10/05/programming-abstractions-with-debugging-support-for-resource-constrained-devices/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Threads2Events: An Automatic Code Generation Approach</title>
		<link>http://blogs.ethz.ch/copton/2010/05/03/threads2events-an-automatic-code-generation-approach/</link>
		<comments>http://blogs.ethz.ch/copton/2010/05/03/threads2events-an-automatic-code-generation-approach/#comments</comments>
		<pubDate>Mon, 03 May 2010 15:15:45 +0000</pubDate>
		<dc:creator>Alexander</dc:creator>
				<category><![CDATA[publication]]></category>
		<category><![CDATA[code generation]]></category>
		<category><![CDATA[events]]></category>
		<category><![CDATA[threads]]></category>

		<guid isPermaLink="false">http://blogs.ethz.ch/copton/?p=440</guid>
		<description><![CDATA[There is a long-standing dispute on whether and when thread-based programming should be preferred over the event-based paradigm. This dispute has also extended into the wireless sensor networks domain. Many existing operating systems rely on events due to their efficiency, but make code management difficult. Others rely on threads for developer comfort, but at the [...]]]></description>
			<content:encoded><![CDATA[<p>There is a long-standing dispute on whether and when thread-based programming should be preferred over the event-based paradigm. This dispute has also extended into the wireless sensor networks domain. Many existing operating systems rely on events due to their efficiency, but make code management difficult. Others rely on threads for developer comfort, but at the cost of reduced runtime efficiency. In this paper we try to combine the best of both worlds by offering a full-fledged cooperative thread abstraction with blocking I/O to the C programmer that is compiled into efficient event-based code. We present the basic code transformations and investigate their efficiency using a representative application case study. We find that RAM usage of generated code competes with hand-written code, but further optimizations are required to reduce the code size and the number of CPU cycles.</p>
<p><span id="more-440"></span></p>
<h3>Introduction</h3>
<p>Event-driven programming has traditionally been the paradigm of choice to program resource-constrained sensor nodes [<a href="http://doi.ieeecomputersociety.org/10.1109/LCN.2004.38">Contiki</a>, <a href="http://doi.acm.org/10.1145/356989.356998">TinyOS</a>]. The use of events indeed allows to efficiently handle the concurrency-intensive operations such devices must typically deal with [<a href="http://doi.acm.org/10.1145/356989.356998">TinyOS</a>]. In contrast, using threads in such a high-concurrency context induces a significant overhead in terms of memory usage and number of context switches. Therefore, although some thread-based solutions exist [<a href="http://www.springerlink.com/content/k55550108111n450/">Mantis OS</a>, <a href="http://doi.acm.org/10.1145/1460412.1460456">Darjeeling</a>], major operating systems for sensor nodes such as <a href="http://doi.acm.org/10.1145/356989.356998">TinyOS</a> or <a href="http://doi.ieeecomputersociety.org/10.1109/LCN.2004.38">Contiki</a> rely on an event-driven paradigm.</p>
<p>However, event-based programs are notably harder to write, maintain, and debug than their thread-based counterparts [<a href="https://www.usenix.org/events/usenix02/full_papers/adyahowell/adyahowell_html/">Adya2002</a>]. Some authors thus introduced ad-hoc thread libraries to event-based operating systems for sensor nodes in order to facilitate application development [<a href="http://doi.acm.org/10.1145/1278972.1278995">Duffy2007</a>, <a href="http://doi.acm.org/10.1145/1644038.1644052">TOSThreads</a>, <a href="http://doi.acm.org/10.1145/1182807.1182825">TinyThread</a>,<a href="http://www.springerlink.com/content/g40g5771066h1x70/">YThreads</a>]. As an alternative, thread-based programs can be automatically translated into equivalent event-based code using an appropriate compiler. Such compiler-based approaches can apply static code optimizations thus producing potentially more efficient code than library-based solutions. Existing approaches such as <a href="http://doi.acm.org/10.1145/1182807.1182811">Protothreads</a> and <a href="http://www.springerlink.com/content/x15034620476m586/">TinyVT</a> have a number of limitations, though. To the best of our knowledge, our system, which we discuss below, is the only to compile almost arbitrary cooperative-thread-based code written in the C language to event-based code for any event-based runtime environment.</p>
<p>Since the thread semantics are implemented at compiler level, there are the following limitations.  First, the number of threads must be known at compile time. Second, recursive functions must not invoke blocking functions. And third, function pointers must not be used to invoke functions that directly or indirectly invoke blocking functions. We argue, though, that these limitations do not severely affect programming of sensor nodes. In particular, recursive algorithms tend to have an undecidable stack consumption and thus should generally be avoided in embedded systems.  Again due to the constrained resources of sensor nodes, it is often not sensible to support an arbitrary number of threads. Finally, the use of function pointers is not uncommon, but can be avoided by a case differentiation (i.e., if case one, call function A; if case two, call function B; &#8230;) with moderate overhead. What&#8217;s most important about these constraints is the fact that the compiler can reliably detect violations of them.  </p>
<p>The remainder of this paper is organized as follows. After briefly reviewing related work in the section &#8220;Related Work&#8221;, we detail how we can automate the threads-to-events code transformation step in<br />
the section &#8220;From Threads to Events&#8221;. The preliminary evaluation of our system, presented in the section &#8220;Evaluation&#8221;, shows among other things that the generated code can compete with hand-written code in terms of RAM consumption. Finally, we provide our conclusions.</p>
<h3>Related Work</h3>
<p>In the context of wireless sensor networks (WSNs), thread programming on top of event-based systems had first been enabled by the development of ad-hoc thread libraries. For instance, <a href="http://doi.acm.org/10.1145/1182807.1182825">TinyThread</a> provides multi-threading to TinyOS programmers. This library includes a tool to estimate the per-thread stack depth and thus allows to minimize RAM overhead. Similar solutions [<a href="http://doi.acm.org/10.1145/1278972.1278995">Duffy2007</a>, <a href="http://doi.acm.org/10.1145/1644038.1644052">TOSThreads</a>, <a href="http://www.springerlink.com/content/g40g5771066h1x70/">YThreads</a>] also provide cooperative or preemptive thread abstractions on top of TinyOS or other mote operating systems. However, since libraries implement the thread semantics at runtime, their usage does not allow to apply static code optimizations at compile-time. In contrast, compiler-based approaches can exploit this potential for optimization.</p>
<p>The probably best-known compiler-based solution in this context is the Protothreads approach by Dunkels et al. [<a href="http://doi.acm.org/10.1145/1182807.1182811">Protothreads</a>]. Programs written using Protothreads are transformed into event-based code using the C preprocessor. However, while using the C preprocessor guarantees portability across C compilers, it also introduces some limitations. For instance, certain C language constructs such as <code>switch</code> statements may not be used and values of local variables are not retained across context switches [<a href="http://doi.acm.org/10.1145/1182807.1182811">Protothreads</a>]. Furthermore, thread functions are not reentrant, blocking calls may only occur in the top-level thread functions, and debugging is performed in the generated code.</p>
<p>In contrast, we argue for a comprehensive threads-to-events compiler, as introduced by <a href="http://www.springerlink.com/content/x15034620476m586/">TinyVT</a>. This approach extends the event-based nesC programming language by introducing a <code>wait</code> operator that suspends program execution until a certain event occurs. The wait operator also specifies the event handler code that should be executed when the event occurs. In addition, TinyVT provides automatic variables that can be accessed from the event handler code. In contrast to our work, however, TinyVT does not completely hide the event semantics of the underlying system. Furthermore, it was specifically designed for nesC/TinyOS, while our approach supports a wide range of event-based runtime environments. Finally, TinyVT does neither support reentrant calls of functions containing wait operators nor event handlers containing wait operators.</p>
<h3>From Threads to Events</h3>
<p>The main challenges related to the transformation of thread-based code (T-code) into event-based code (E-code) stem from the fact that a call to a blocking function such as <code>read</code> or <code>sleep</code> must be rewritten into triggering the operation and registering the continuation, which is executed by the runtime environment upon completion of a blocking operation. Every function which potentially calls a blocking function, either directly or indirectly, is affected by the transformation. We denominate such functions <em>critical functions</em> and a <em>critical call</em> is a call of a critical function.</p>
<p>The transformation of a critical call into a corresponding split-phase operation has two major implications. First, the code following a critical call must be callable, thus the control flow must be modified appropriately. Second, automatic variables in critical functions that are set before the critical call and read afterwards must be preserved. </p>
<h4>Control Flow</h4>
<p>To be amenable for event-based execution, critical functions have to be split into a part that triggers the critical call, and a part that is invoked upon the completion of the critical call. However, if the critical call is nested in control structures such as loops, the transformation may be more complex and is performed as follows. First, the T-code is transformed into an equivalent GOTO program which is a sequence of commands with labels. It is well known that this transformation is always applicable and actually this is what C compilers do in general. Second, the resulting code is split into basic blocks at all labels and critical calls. Third, each resulting basic block is put into its own E-code sub-function. Then, all GOTO commands and transitions between basic blocks are replaced with calls to the corresponding E-code sub-functions. Furthermore, the call to the critical function is replaced by the call to the corresponding first E-code sub-function. Finally, C code is generated for all those functions.</p>
<p>Consider for example the following function <code>f</code> in which <code>statements_x</code> represents an arbitrary sequence of C language statements and <code>cond</code> is a Boolean expression. The E-code obtained by transforming the GOTO program back into C functions is also shown below.</p>
<p><code></p>
<pre>
// T-code
statements_1;
while(cond) {
    statements_2;
    crit();
    statements_3;
}
statements_4;
</pre>
<p></code></p>
<p><code></p>
<pre>
// GOTO program
      statements_1
loop: IF !cond GOTO end
      statements_2
      CALL crit
      statements_3
      GOTO loop
end:  statements_4
</pre>
<p></code></p>
<p><code></p>
<pre>
// E-code
void f_1() {
    statements_1;
    f_2();
}

void f_2() {
    if (!cond) {
        f_4();
    } else {
        statements_2;
        crit_1();
    }
}

void f_3() {
    statements_3;
    f_2();
}

void f_4() {
    statements_4;
}
</pre>
<p></code></p>
<p>Likewise, <code>crit()</code> is compiled into a set of C functions, such that upon completion <code>f_3</code> is invoked as described in the section &#8220;Returning&#8221;. Furthermore, the value of an automatic variable of <code>f</code> must be retained across calls of the generated functions <code>f_x</code>. This is described in the following section.</p>
<h4>Local Variables</h4>
<p>For every critical function a statically allocated <em>state</em> structure is generated. This structure holds all automatic variables and all parameters that need to be retained across critical calls. Due to the possibility of reentrant function calls, there is one copy of this state structure for each thread. The resulting E-code then accesses those state structures instead of automatic variables. Note that non-critical functions are not affected by this transformation.</p>
<p>To minimize the RAM consumption, we allocate the state structures for certain functions to the same memory location. In particular, if a critical function sequentially calls two other critical functions, so that the local variables of the latter two functions cannot be active simultaneously, we can allocate the state structures of those two functions to the same memory location using a <code>union</code>.  In contrast, the local variables of a function and its calling function are active simultaneously and thus cannot share the same memory location. Using this principle, we can translate the call graph of a critical function directly into a structurally equivalent nested data structure of C <code>struct</code>s (for nested calls) and <code>union</code>s (for sequential calls), holding function state structures as in the following example. Here, <code>state_x</code> denotes the state structure of a function <code>x</code>. <code>run_send</code> is the start method of a thread and <code>sleep</code>, <code>read</code>, and <code>send</code> are blocking functions.</p>
<p><code></p>
<pre>
// T-code
void run_send() {
    while(1) {
    sleep();
    aggr();
    send();
}    

void aggr() {
    read();
    //...
}
</pre>
<p></code></p>
<p><code></p>
<pre>
// corresponding states
struct {
    state_run run;
    union {
        state_sleep sleep;
        struct {
            state_aggr aggr;
            state_read read;
        } struct1;
        state_send send;
    } union1;
} state_send;
</pre>
<p></code></p>
<p>There is one such nested data structure for each thread, representing the call graph starting at the main function of that thread. As multiple threads can make reentrant calls to the same function, there must be a mean to retrieve the structure corresponding to the current thread. To this end, we generate a mapping function that returns a pointer to the proper state structure instance. This mapping is based upon the value of a global variable <code>tid</code>, which holds the identifier of the current thread. For instance, for function <code>aggr</code> in the example above the mapping function would look like:</p>
<p><code></p>
<pre>
state_aggr* map_aggr() {
    switch(tid) {
        case SEND_THREAD:
            return &amp;state_send.union1.struct1.aggr;
        //...
    }
}
</pre>
<p></code></p>
<p>We emphasize again that the above transformation only applies to critical functions. Non-critical functions are just copied from T-code to E-code. In addition, only variables whose values need to be retained across calls of sub-functions are affected by the transformation. These are all variables that are written in one sub-function and read in a subsequent one. All other variables such as iteration variables of <code>for</code> loops not containing critical calls remain automatic stack-based variables.</p>
<h4>Returning</h4>
<p>If a T-code function is only invoked from one place in the code, then the control flow can be hard-coded into the generated E-code. In contrast, if a function may be called from multiple code locations, an explicit return address needs to be saved. In our compilation framework, we include the return address in the state structure of the invoked function much like a local variable while the same optimizations as described in the section &#8220;Local Variables&#8221; apply. The caller has to set the return address before calling the function as in the following code referring to the example from the section &#8220;Control Flow&#8221;.</p>
<p><code></p>
<pre>
void f_2() {
    if (! cond) {
        f_4();
    } else {
        statements_2;
        map_crit()-&gt;cont = f_3;
        crit_1();
    }
}

void f_4() {
    statements_4;
    (*map_f()-&gt;cont)();
}
</pre>
<p></code></p>
<p>Likewise, return values of critical functions are also stored in its state structure. After return, the caller can retrieve it from there. So a complete state structure for a critical function <code>int f(int x)</code> would look like this:</p>
<p><code></p>
<pre>
struct state_f {
    void (*cont)(); // continuation
    int res; // result
    int x; // parameter
    ... // other local variables
}
</pre>
<p></code></p>
<h4>Platform Abstraction Layer</h4>
<p>The so-called <em>platform abstraction layer (PAL)</em> contains event-based implementations of blocking calls in the T-code. The compiler generates E-code skeletons for these functions, but the actual calls to the underlying event-based runtime environment have to be inserted manually. Besides adapting the API of the runtime environment to the generated E-code, the PAL also enables portability.</p>
<p>As an example consider the blocking function <code>sleep</code> in the T-code. There is a hand-written E-code implementation of <code>sleep_1</code> and <code>sleep_2</code> in the PAL. Furthermore, the compiler generates the state structure <code>state_sleep</code> according to the T-code signature of <code>sleep</code>, and the map function <code>map_sleep</code> according to the call graphs of the program.  <code>sleep_1</code> uses the event-based API of the runtime environment to set up a timer and register <code>sleep_2</code> to be called when the timer fires. <code>sleep_2</code> will then call the continuation which was saved in the proper instance of <code>state_sleep</code> by the caller of <code>sleep_1</code>.</p>
<p>While a thread is waiting for the completion of a blocking function, events related to other threads can of course be dispatched. This requires that a (lightweight) context switch is performed by saving the value of the global variable <code>tid</code> holding the current thread ID in <code>sleep_1</code> and restoring it in <code>sleep_2</code>.</p>
<h4>Interfacing the Compiler</h4>
<p>In order to perform the transformation, our compiler needs some additional information besides the T-code. In particular, it must know the set of blocking functions, the total number of threads, and the start functions for each of them.</p>
<p>In the context of this work, we assume the declarations for the blocking calls to be available in a T-code header file. The number of threads and their start functions are specified in the <code>main</code> function of the T-code program. More specifically, each invocation of the built-in function <code>RUN_THREAD</code> causes the global variable <code>tid</code> to be incremented. The pointer to the start function of the thread is passed as an argument to the <code>RUN_THREAD</code> function. This start function will eventually call a blocking function and return. Once all threads have been started in this way, the generated E-code variant of <code>main</code> passes control to the event dispatcher loop of the event-based runtime environment.</p>
<h3>Evaluation</h3>
<p>To verify the feasibility and the practicability of the proposed code transformation, we performed a preliminary experimental study using an application that performs data storage and collection. We started with a <em>hand-written</em> event-based implementation of that application. We then rewrote the same application using cooperative threads with blocking I/O. The purpose of this <em>thread-based</em> implementation was to serve as input to a manually performed code transformation as described in section \ref{sec:transformation}, resulting in a <em>generated</em> event-based version of the application. In the following, we compare the efficiency of the generated event-based code with respect to the hand-written E-code.</p>
<p>The considered test application performs distributed data aggregation with local storage using three main tasks. First, it continuously reads a sensor and stores the values in flash memory (<em>collect</em> task). Second, it periodically receives radio messages from other nodes containing their sensor readings and also stores them on flash memory (<em>receive</em> task). Finally, it regularly reads the flash memory to compute minimum and maximum readings and sends the results over the radio (<em>send</em> task). In the thread-based application, each of these three tasks is performed by a separate thread. Furthermore, the function that writes data to the flash is reentrant since it is invoked by both the receive and the collect threads.</p>
<p>In order to evaluate the correctness of the transformation we first executed both implementations of our test application in our own simulation environment. By analyzing the corresponding API call traces we were able to verify that they behave equivalently. To this end, we choose TinyOS 2.x as a model for the underlaying runtime environment. However, since the transformation applies solely to application code, only the API of the operating system but not its implementation is of significance. Therefore, we simply manually compiled the necessary TinyOS interfaces (e.g., <code>Read</code>, <code>Send</code>) to C code along the lines of the nesC compiler.</p>
<p>Compared to directly working with TinyOS, this approach gave us greater flexibility as we could provide different implementations of the operating system, depending on the needs of the various tests and measurements we performed. The complete source code of the study along with more detailed documentation is <a href="http://github.com/copton/tc-case_study">publicly available</a>.</p>
<p>Besides verifying the feasibility of our approach we also compared hand-written and generated code in terms of consumption of ROM, RAM, and CPU resources on a sensor node equipped with an AVR ATmega128.</p>
<h4>Results</h4>
<p>We cross-compiled the hand-written and the generated event-based application code using avr-gcc version 4.1.2 for the atmega128 microcontroller with optimization option <code>-O2</code>.  We then linked the cross-compiled code against an empty implementation of the operating system. The size of the DATA and the BSS sections of the resulting binaries then allows to directly compare the RAM consumption of the two applications. The following table shows the resulting sums of both sections in bytes and the ratios for different sizes of I/O buffers (see the section &#8220;Discussion&#8221; for a discussion of I/O buffers). Note that the numbers for the generated application include the PAL.</p>
<table cellspacing="10">
<thead>
<tr>
<th>buffer size</th>
<th>hand-written</th>
<th>generated</th>
<th>ratio</th>
</tr>
</thead>
<tbody>
<tr>
<td>30</td>
<td>367</td>
<td>429</td>
<td>1.17</td>
</tr>
<tr>
<td>50</td>
<td>427</td>
<td>469</td>
<td>1.10</td>
</tr>
<tr>
<td>100</td>
<td>577</td>
<td>569</td>
<td>0.99</td>
</tr>
</tbody>
</table>
<p>The size of the TEXT sections of the cross-compiled object files indicate how much flash is needed to store the program in the microcontroller. The results are 3166 bytes for the generated application vs. 1080 bytes for the hand-written one, which is a ratio of 2.93. As the PAL is extra code which does not exist in the hand-written case it influences the estimation of the code transformation. Excluding the PAL, the code size of the generated code reduces to 1684 bytes or a ratio of 1.56.  </p>
<p>We finally measured the consumption of CPU resources by running the applications in the <a href="http://compilers.cs.ucla.edu/avrora/">Avrora</a> simulator. For that purpose we wrote a simple event dispatcher implementation of the operating system. Additionally, we introduced a new main function that after setting up the environment makes each thread perform one iteration of its periodic work.</p>
<p>The results are 4875 CPU cycles for the generated code vs. 1679 cycles for the hand-written code, making for a ratio of 2.78. In order to measure the properties of the code transformation itself we confined the sums on cycles which are executed in the application code, excluding the setup phase and the PAL. Then we measured 1368 vs. 633 cycles, making for a ratio of 2.16.</p>
<h4>Discussion</h4>
<p>The selected application represents a &#8220;stress-test&#8221; for our compilation framework as the code mostly consists of invocations of blocking calls without much &#8220;computations&#8221;. As in our framework overhead results from blocking calls but not from computations, this application can be considered a worst-case scenario.</p>
<p>Another important issue regarding the interpretation of the performance results is the implementation of the PAL. As discussed in the section &#8220;Platform Abstraction Layer&#8221;, the PAL needs to perform a context switch by saving and restoring the current thread ID. Unfortunately, the TinyOS API does not allow to pass parameters to callback functions when triggering the split-phase operation. Such a mechanism would allow a very efficient implementation of context switches. Instead, our PAL implements a rather inefficient mapping from callback handles to thread identifiers.</p>
<p>For RAM consumption, though, the results for the generated code including the PAL are comparable to those for the hand-written code. This is due to memory sharing of state structures holding local variables in the E-code. The measurements for different sizes of the I/O buffers make this apparent. In the hand-written application, each buffer is a separate static variable in a translation unit. In the thread-based application, these buffers are automatic variables and thus become part of the state structures where they share memory. Thus with larger I/O buffers the ratio becomes smaller to a point where the generated code even becomes more efficient than the hand-written one.</p>
<p>The code size overhead can be explained by the very nature of the code transformation, as every critical function results in the generation of several sub-functions and a map function. The bottom line is that the number of functions is roughly doubled. As the application does not do much computation, the administrative overhead of each single function is significant. Thus doubling the number of functions results in roughly twice the code size.</p>
<p>As the ratio of the cycle counts is higher than the ratio of the code size, the generated code must consist of more expensive instructions on average. According to the AVR ATmega128 <a href="http://www.atmel.com/atmel/acrobat/doc2467.pdf">datasheet</a> this is due to the <code>call</code> and <code>ret</code> instructions which have a very high code-size-to-cycles ratio. This affects the generated code because it contains, as we outlined above, many function calls.</p>
<p>We expect realistic applications with more computations to result in better ratios for code size and cycles. However, we also expect the ratios to increase if the number of critical calls per function increases. A more thorough study of those factors is subject of ongoing work.</p>
<p>In general, we need to investigate further optimizations to reduce the number of generated E-code functions. For example, the transformations of the application used in the evaluation resulted in sub-functions which do nothing but call another sub-function. Clearly, this could be avoided. Along these lines we believe that in several cases the transformation could result in more efficient code than in the general case as described in the section &#8220;From Threads to Events&#8221;.</p>
<p>As pointed out in <a href="http://doi.acm.org/10.1145/1460412.1460456">Darjeeling</a>, in the context of WSNs it is often acceptable to trade off lower RAM footprint against a higher execution time. In our case, efficient storage of the state structures has to be paid with the costs of the map functions.</p>
<h3>Conclusions</h3>
<p>We provided the design of a comprehensive compilation framework that automatically generates event-based code from thread-based programs. We tested the feasibility of our approach on a simple but representative case study that can be considered a worst-case scenario. Our preliminary experimental results show that the generated code can compete with hand-written code in terms of RAM usage, while both code size and execution time are larger.  We believe, though, that additional optimizations are possible and will reduce both ratios. Furthermore, we expect the ratios to decrease for applications performing longer and more complex computations.</p>
<h3>Meta</h3>
<ul>
<li>This is a paper published at the <a href="http://www.hotemnets2010.org/">ACM HotEMNETS 2010 Workshop on Hot Topics in Embedded Networked Sensors</a>.</li>
<li>This is joint work with <a href="http://www.inf.ethz.ch/personal/roemer/">Kay Römer</a>, <a href="http://www.inf.ethz.ch/personal/santinis/">Silvia Santini</a> and Junyan Ma.</li>
<li>This work has been partially supported by the National Competence Center in Research on Mobile Information and Communication Systems <a href="http://www.mics.org/">(NCCR-MICS)</a>, a center supported by the Swiss National Science Foundation under grant number 5005-67322, and by <a href="http://www.cooperating-objects.eu/">CONET</a>, the Cooperating Objects Network of Excellence, funded by the European Commission under FP7 with contract number FP7-2007-2-224053.
<li><a href="http://www.vs.inf.ethz.ch/publ/papers/bernauer10_threads2events.pdf">.pdf</a>, <a href="http://www.vs.inf.ethz.ch/publ/bibtex.html?file=papers/bernauer10_threads2events">BibTex</a>.
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blogs.ethz.ch/copton/2010/05/03/threads2events-an-automatic-code-generation-approach/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Meta-Debugging Pervasive Computers</title>
		<link>http://blogs.ethz.ch/copton/2010/04/16/meta-debugging-pervasive-computers/</link>
		<comments>http://blogs.ethz.ch/copton/2010/04/16/meta-debugging-pervasive-computers/#comments</comments>
		<pubDate>Fri, 16 Apr 2010 10:33:09 +0000</pubDate>
		<dc:creator>Alexander</dc:creator>
				<category><![CDATA[publication]]></category>
		<category><![CDATA[code generation]]></category>
		<category><![CDATA[debugging]]></category>

		<guid isPermaLink="false">http://blogs.ethz.ch/copton/?p=431</guid>
		<description><![CDATA[As computers get more complex, the task of programming them gets more complex as well. This is especially true for the &#8220;Pervasive Computer&#8221;, which is a massively distributed system consisting of unreliable embedded devices that communicate with each other over lousy wireless links. A common approach to address the programming problem is to offer programming [...]]]></description>
			<content:encoded><![CDATA[<p>As computers get more complex, the task of programming them gets more complex as well. This is especially true<br />
for the &#8220;Pervasive Computer&#8221;, which is a massively distributed system consisting of unreliable embedded devices that  communicate with each other over lousy wireless links. A common approach to address the programming problem is to offer programming abstractions that hide certain aspects of the complexity from the programmer. While several such abstractions and mappings thereof to low-level target languages have been proposed, there is a glaring lack of debugging support. It is typically impossible to debug at the conceptual level offered by the programming abstractions, instead one has to resort to debugging the generated target code. In this position paper we argue that programming abstractions should be designed in a way that allows debugging at the same conceptual level as programming. We further present requirements for such debugging tools, a taxonomy of programming abstractions and discuss debugging<br />
challenges, existing solutions, and potential approaches in each class.</p>
<p><span id="more-431"></span></p>
<h3>Introduction</h3>
<p>Computer systems tend to get more complex over time. The <em>pervasive computer</em>, for example, consists of many resource-constrained embedded devices that form wireless ad hoc networks to cooperatively solve a task. Programming these systems is difficult.</p>
<p>One common way of addressing this difficulty is to raise the level of abstraction in order to relieve the programmer from lower-level details. Hereby the basic idea is to provide proper programming abstractions by means of a formal meta-language to a software developer in a given application domain.</p>
<p>The benefits of programming abstractions are frequently cited. More abstraction means less code which in turn means fewer possibilities for bugs, be it typos, copy-and-paste errors, inconsistencies, or logical errors. Furthermore, by explicitly representing the concepts of the problem domain in the programming language, a program is easier to create and understand for domain experts. On the long way from an idea in somebodies mind to an executable representation of the same, some steps have to be performed manually and some can be automated. The overall goal of programming abstractions is to reduce the manual part as much as possible.</p>
<p>For the scope of this article, we will adopt the term <em>programming abstraction</em> that is embodied in a meta-language. A program is an instance of a language and forms a solution for a problem in the domain of that language \cite{dmitriev}. A programming abstraction is implemented by mapping it to lower-level abstractions which are themselves embodied as a program in a target language and so on until a program can be directly interpreted or executed by a virtual or physical machine. We focus on programming abstractions in the field of pervasive computing, in particular for applications of wireless sensor networks (WSN).</p>
<p>In this field, several programming abstractions do already exist. For most existing programming abstractions though, debugging cannot be performed at the conceptual level of the programming abstraction, but has to be performed at the level of the target language to which the programming abstraction is mapped [<a href="http://www.sics.se/~luca/papers/mottola10programming.pdf">Mottola2010</a>]. This is a major difficulty, as the developer suddenly has to become aware of the target language, and has to understand its semantics and the semantics of the mapping to the target language.</p>
<p>In this position paper we discuss the problem of debugging abstract programs and we postulate that researches should address the question how such programs can be debugged at the conceptual level of the programming abstraction, thus hiding the very existence of the target language, its semantics, and the mapping &#8212; much like most C programmers are unaware of the syntax and semantics of the assembly target language.</p>
<p>Besides the C programming language and its tool chains, there are various different technologies which raise the level of abstraction in order to mitigate the growing complexity of computer systems. For example, the software engineering community has devised <em>Model Driven Development</em>. Others have proposed <em>Language Oriented Programming</em> [<a href="http://www.onboard.jetbrains.com/is1/articles/04/10/lop/">Dmitriev2004</a>] or <em>Intentional Programming</em> [<a href="http://qconlondon.com/london-2008/presentation/Intentional+Software+-+Domain+Expert+DSLs">Christerson2008</a>]. Additionally, internal and external <em>Domain Specific Languages</em> (DSL) are hot topics in the design of programming languages. While some debugging concepts from those technologies could potentially be applied to the pervasive computing context, pervasive computers differ from other systems in their distributiveness, scale, heterogeneity, resource and energy constraints, as well as their deep embedding into the real world. Hence, we believe that research is required to devise not only tools, but the fundamental concepts of how to debug pervasive computers.</p>
<p>In the remainder of this paper, we present requirements for debugging and a coarse taxonomy of programming abstractions. For each class in the taxonomy, we discuss the challenges involved in debugging, what kind of debugging support is required, and how severe the lack of the latter is.</p>
<h3>Requirements and Taxonomy</h3>
<p>While it would be desirable to build systems that are correct by design or at least to perform a complete static verification of the program code, this is only partially possible for pervasive computers because it would require a complete formal model of the real world. Unlike other computer systems, pervasive computers closely interact with the real world, not only by means of sensing and controlling physical processes, but also through undesirable interactions due to environmental influences. For example, environmental temperature has a strong influence on the frequency and start-up time of crystal oscillators, on received radio signal strength, and on the (dis)charging characteristics of batteries and is thus sometimes causing unpredictable partial node and communication failures. Hence, debugging pervasive computers is a necessity. By debugging we mean finding and removing the causes of incorrect application behavior by examining the its runtime.</p>
<p>In particular, we consider two common types of bugs. Firstly, logical errors in the application code and, secondly, incorrect assumptions in the application code about the semantics of the target language and system to which the application code is mapped. In existing systems, incorrect assumptions concerning the reliability and the timing of message delivery for example are a common cause for failures.</p>
<p>In principle it is possible &#8211; and this is what we are aiming at &#8211; to find the above two types of bugs at the conceptual level of the programming abstraction, i.e., without exposing to the user the target language, its implementation, and the mapping of application code to the target language.</p>
<p>Debugging techniques for pervasive computers have to meet a number of constraints. Firstly, it must be possible to debug large heterogeneous networks of pervasive computers. Secondly, resource and energy constraints of pervasive computers require that resource and energy consumption of debugging techniques is minimized &#8211; otherwise we run the risk of severe probe effects, where the debugger significantly alters the program execution, resulting in (dis)appearance of bug symptoms.</p>
<p>To better understand the problem of <em>debugging abstract programs</em>, we will discuss debugging characteristics of different classes of programming languages for pervasive computers. For this taxonomy, we see two major dimensions: imperative vs. declarative languages and languages for node-centric vs. distributed applications. Actually, those two orthogonal dimensions form a subset of current and common taxonomies for WSN programming models [<a href="http://www.sics.se/~luca/papers/mottola10programming.pdf">Mottola2010</a>] and we consider them crucial for debugging.</p>
<p>With imperative languages the intended application processing is expressed through statements that explicitly indicate how to change the program state [<a href="http://www.sics.se/~luca/papers/mottola10programming.pdf">Mottola2010</a>] while with declarative languages the application goal is described without specifying how it is accomplished [<a href="http://www.sics.se/~luca/papers/mottola10programming.pdf">Mottola2010</a>]. This difference is important because with imperative languages the mapping between source code and target code tends to be one to one. But by raising the level of abstraction towards declarative languages the mapping becomes more complex and even ambiguous, thus making it hard to perform the back-mapping which is required for debugging.</p>
<p>The second dimension of our taxonomy addresses the problem of shared state which is changed concurrently. As opposed to node-centric programs, with distributed programs well-known concepts such as breakpoints need to be reconsidered to make them applicable for distributed applications.</p>
<p>In the following sections we discuss the four classes of programming abstractions which are formed by those two dimensions. While we focus on programming abstractions for pervasive computers, we also look at related application domains that raise similar problems as an inspiration of how one might tackle the problem for pervasive computing.</p>
<h3>Imperative Meta-Languages</h3>
<p>In the WSN community the most famous example of an imperative meta-language is probably TinyOS [<a href="http://doi.acm.org/10.1145/356989.356998">Hill2000</a>]. The programming language of TinyOS is <a href="http://nescc.sourceforge.net/">nesC</a>, which is a DSL for the domain of event-based and component-based applications. The nesC compiler translates nesC code into C code which is then compiled by a platform compiler for an embedded platform such as <a href="http://gcc.gnu.org">avr-gcc</a>.</p>
<p>Imperative programming languages are a list of commands and command abstractions which tell the executing machine what it is supposed to do. So the most natural way of debugging is to observe the sequential execution of these commands by means of a source-level debugger. Programmers are familiar with this concept because most tool chains provide such as debugger. In fact, a C programmer would very likely refuse to use a tool chain which does not offer a debugger that allows to set breakpoints in the source code and to monitor variables during execution. This is because by the lack of a source-level debugger he is forced to trace execution on the assembler level, find the flaw there and infer the location of the bug in the C code. Not only must he know the complete target language but also the details of the transformation performed by the compiler in order to be able to undo it.</p>
<p>In the case of TinyOS this means that a developer must use the debugger of the C tool chain and step through the generated C code. As a consequence she must be familiar with the implementation-specific naming scheme for the generated C symbols [<a href="http://nescc.sourceforge.net/papers/nesc-ref.pdf">nesC reference</a>] and must know how the wiring of nesC components is mapped to C code in order to map back the location of a bug in the generated C code to the corresponding location in the nesC code.</p>
<p>To support source level debugging, C compilers add debugging information to the assembly output, indicating which line in the C source code has been mapped to which lines in the assembly code. A source-code debugger can use this information to map the execution state of a binary program to lines in the source code and to names of variables. As C itself is a programming abstraction, this technique can be adopted to support debugging of imperative meta-languages.</p>
<p>In fact this has been done for the <a href="http://marketplace.eclipse.org/content/yeti-2-tinyos-2x-eclipse-plugin">YETI Eclipse plugin</a> [<a href="http://doi.acm.org/10.1145/1644038.1644068">Burri2009</a>] which is the first source-level debugger for the nesC programming language. It uses the <a href="http://www.eclipse.org/cdt/">Eclipse C/C++ Development Tooling (CDT)</a> to communicate with an underlying instance of the <a href="http://www.gnu.org/software/gdb/">GNU Debugger (GDB)</a> and automatically performs the inverse mapping of the nesC compiler. This is possible because the nesC compiler records which part of the generated C file originates from which part of the various nesC input files by exploiting C preprocessor instructions. To the best of our knowledge, the YETI project is gladly embraced by the TinyOS community because it enables the developer to completely ignore the fact that nesC programs are in fact mapped to C.</p>
<p>Along the lines of YETI, we suggest that programming abstractions should always be designed such that they are amenable to source-level debugging. Probably the most notorious imperative programming abstraction without debugging support are C++ templates. Compiler error messages caused by bugs in C++ template code are so verbose and hard to read that projects like <a href="http://www.bdsoft.com/tools/stlfilt.html">stlfilt</a> try to provide a reverse mapping by means of compiler-specific heuristics. An additional problem with C++ templates is that they are also used to implement declarative languages as opposed to imperative ones, as discussed in the subsequent section.</p>
<h3>Declarative Meta-Languages</h3>
<p>Declarative languages specify a goal, but not how this goal can be achieved. Therefore, a program written in a declarative languages is often called a model. Parser generators are a well known example of tools which process declarative input in order to generate executable implementations of the parser. In the case of <a href="http://boost spirit.com/home/">Boost.Spirit</a>, the intended parser is declared by means of instantiations of C++ templates. Other projects like <a href="http://www.antlr.org/">ANTLR</a> use a dedicated meta-language instead. Another common case of declarative meta-languages are persistence and database abstractions as in the case of the <a href="https://www.hibernate.org/">Hibernate Framework</a> or <a href="http://rubyonrails.org">RubyOnRails</a>.</p>
<p>In general, debugging becomes harder in the case of declarative languages. First, because they tend to be more abstract and second, because the transformation to an imperative target language is not a simple one-to-one mapping any more. As declarative languages are not based on the sequential execution of commands, debugging concepts such as single-stepping and breakpoints are not applicable.</p>
<p>Instead debugging can be supported by providing different views on the model so that the programmer can perform a visual inspection. Visual inspection is only applicable to small models, but fortunately raising the abstraction often leads to reducing the size of the code.  <a href="http://intentsoft.com/">Intentional Software</a> applies this approach and claims to have received positive feedback from their costumers [<a href="http://www.se-radio.net/podcast/2009-12/episode-151-intentional-software-shane-clifford">se-radio151</a>], which in their case are usually domain experts without IT background.</p>
<p>An alternative general concept for debugging models is to simulate or execute example cases. <a href="http://kodos.sourceforge.net/">KODOS</a>, for example, offers such an approach for debugging regular expressions. Given a regular expression and an example string, the application highlights the parts of the string which match and displays the contents of the matching groups. So KODOS basically supports and automates trail-and-error cycles which otherwise would have to be performed manually.</p>
<p>In the worst case without debugging support, the programmer is forced to read or debug the generated code. As the gap between the programming abstraction and the target language is typically rather high, the disadvantages of this approach as described in Sect. \ref{sec:imp} are even more severe.</p>
<h3>Imperative and Distributed</h3>
<p>The pervasive computer is a massively distributed system with unreliable components. As programming such distributed systems is difficult, imperative programming languages have been devised that abstract from certain distribution aspects. One example for such a language is Kairos [<a href="http://doi.acm.org/10.1145/1095810.1118600">Millstein2005</a>], which allows computations involving different nodes without explicit network communication. This is very convenient but yet it is completely unclear how to debug Kairos programs. Traditional single-node source-level debuggers cannot be applied here, as single stepping or breakpointing one node may violate timing assumptions in the remaining network which can itself lead to failures. Clairvoyant [<a href="http://doi.acm.org/10.1145/1322263.1322282">Yang2007</a>] addresses this issues by adding WSN specific features to the GDB, i.e. global stop and continue commands. The downside still remains, though, which is that interactive debugging sessions on deployed networks deplete the batteries due to heavy usage of the energy consuming radios thus reducing the overall network lifetime.</p>
<p>A promising imperative meta-language for WSNs is <a href="http://www.cs.virginia.edu/~whitehouse/research/macrolab/">MacroLab</a> [<a>Hnat2008</a>] which is a vector-based meta language and framework inspired by Matlab. MacroLab programs are composed of computations on vectors containing data on nodes such as sensor values, internal state, and parameters for actuators. Hereby the communication of the vectors among the nodes is hidden from the programmer. Though, the most important fact is that there is a debugger (MDB) [<a href="http://doi.acm.org/10.1145/1644038.1644053">Soocor2010</a>] for MacroLab. MDB is a post-mortem debugger which synchronizes and analyzes log files written by the individual nodes. It supports common debugging concepts such as breakpoints and stepping for both temporally and logically synchronous views. Because MDB does not operate at runtime, it can and does support time travel and rendering effects of hypothetical changes. Furthermore there is a deployment mode in which no logging is done but the timing of the debugging mode is preserved thus avoiding probe effects.</p>
<p>Apart from MacroLab and MDB, few approaches exist to assist in debugging networks of pervasive computers at the conceptual level of the programming language. One such approach is to annotate the program with distributed assertions [<a href="http://doi.acm.org/10.1145/1435473.1435484">Römer2008</a>] that formulate hypothesis about distributed variables which are checked by a a runtime system.  When placed carefully in the code, failed assertions can help debug. However, this is largely decoupled from the programming abstractions offered by the meta language. As in this example, today one typically has to resort to distributed debugging techniques that are independent of the actual programming abstractions. Dustminer [<a href="http://portal.acm.org/citation.cfm?id=1460412.1460423">Khan2008</a>], for example, applies data mining techniques to event traces obtained from nodes to find bug symptoms. Other tools [<a href="http://doi.acm.org/10.1145/1098918.1098946">Ramanathan2005</a>, <a href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.120.3346">Chen2008</a>,<a href="http://www.vs.inf.ethz.ch/publ/papers/snif-techreport.pdf">Ringwald2006</a>,<a href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.110.1717">Rost2006</a>] can detect certain predefined problems such as node reboots, routing loops, or network partitions. But there is no easy way to relate these symptoms to possible causes in the program.</p>
<h3>Declarative and Distributed</h3>
<p>Languages in this class offer declarative programming of a distributed system as a whole. One well-known example in the context of WSNs is TinyDB [<a href="http://doi.acm.org/10.1145/1061318.1061322">Maden2005</a>] which provides a database abstraction. The outputs of distributed sensors form a virtual database table, over which the user can issue SQL queries. Hereby the user is largely unaware of the fact that he is actually programming a distributed system.</p>
<p>With respect to debugging, the difficulties of declarative and distributed languages multiply in this class of our taxonomy. It is already unclear which debugging concepts should be applied to declarative queries, let alone the adoption of such concepts to a distributed setting. To the best of our knowledge no solution exists to support debugging in this class.</p>
<h3>Conclusion</h3>
<p>We postulate that programming abstractions should be designed in a way that allows debugging at the same conceptual level as programming.  The goal should be that developers can work on the abstract level without having to think about lower-level implementation issues. In the case of debugging pervasive applications, though, this goal is hardly achieved as there are only a few good examples such as YETI or MDB.</p>
<p>We believe that the reason for this is that augmenting programming abstractions with debugging capabilities is not merely an engineering issue. Research is required to devise fundamental debugging concepts for declarative and distributed languages. Known source-level debugging concepts such as single-stepping or breakpoints are neither applicable to declarative languages nor to distributed settings. Once we have devised such concepts, we can investigate the implications on the design of debuggable programming abstractions.</p>
<h3>Meta</h3>
<ul>
<li>This is a position paper, published at the <a href="http://www.stevens.edu/compsci/PMMPS/">The International Workshop on Programming Methods for Mobile and Pervasive Systems 2010</a></li>
<li>This is joint work with <a href="http://www.inf.ethz.ch/personal/roemer/">Kay Römer</a>.</li>
<li>This work has been partially supported by the National Competence Center in Research on Mobile Information and Communication Systems <a href="http://www.mics.org/">(NCCR-MICS)</a>, a center supported by the Swiss National Science Foundation under grant number 5005-67322, and by <a href="http://www.cooperating-objects.eu/">CONET</a>, the Cooperating Objects Network of Excellence, funded by the European Commission under FP7 with contract number FP7-2007-2-224053.</li>
<li><a href="http://www.vs.inf.ethz.ch/publ/papers/bernauer_pmmps2010.pdf">.pdf</a>, <a href="http://www.vs.inf.ethz.ch/publ/bibtex.html?file=papers/bernauer_pmmps2010">BibTex</a>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blogs.ethz.ch/copton/2010/04/16/meta-debugging-pervasive-computers/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Trust your tools&#8230;</title>
		<link>http://blogs.ethz.ch/copton/2010/02/21/trust-your-tools/</link>
		<comments>http://blogs.ethz.ch/copton/2010/02/21/trust-your-tools/#comments</comments>
		<pubDate>Sun, 21 Feb 2010 15:23:24 +0000</pubDate>
		<dc:creator>Alexander</dc:creator>
				<category><![CDATA[article]]></category>
		<category><![CDATA[C/C++]]></category>
		<category><![CDATA[wireless sensor networks]]></category>

		<guid isPermaLink="false">http://blogs.ethz.ch/copton/?p=424</guid>
		<description><![CDATA[For my current work I need to show how efficient the generated code is. Fortunately the binutils include a tool called size which &#8220;lists the section sizes of an object or archive file&#8221;. In order to have representative results I should compile for a platform which is typical for the WSN community. I have chosen [...]]]></description>
			<content:encoded><![CDATA[<p>For my current work I need to show how efficient the generated code is. Fortunately the <a href="http://www.gnu.org/software/binutils/">binutils </a> include a tool called <code>size</code> which &#8220;lists the section sizes of an object or archive file&#8221;.</p>
<p>In order to have representative results I should compile for a platform which is typical for the <a href="http://en.wikipedia.org/wiki/Wsn">WSN</a> community. I have chosen the <a href="http://en.wikipedia.org/wiki/TI_MSP430">MSP430</a> because there is a package of a <a href="http://gcc.gnu.org/">GCC</a> cross compiler for that target in the <a href="http://www.tinyos.net/">TinyOS</a> <a href="http://tinyos.stanford.edu/tinyos/dists/ubuntu">Ubuntu repository</a>.</p>
<p>At first, the numbers looked promising. But at a closer look something was wrong. Investigating the problem emerges something weird. </p>
<p><span id="more-424"></span></p>
<p>The function <code>ec_sub6_collect_run</code> from <a href="http://github.com/copton/tc-case_study/blob/7ffdb657f0d5b6baea0a21623254fc58f5322647/src/application/collect_and_forward/generated/app.c">the generated application</a> is defined as:</p>
<p><code></p>
<blockquote><p>
static void ec_sub6_collect_run()<br />
{<br />
    ec_struct_collect_run*const ec_p_collect_run = ec_map_collect_run();<br />
    ec_p_collect_run-&gt;ec_continuation();<br />
}
</p></blockquote>
<p></code></p>
<p>It is merely an artefact of the code generation and will most probably be target of optimization soon. Nevertheless the generated assembler code should not harm too much. But here is the surprise. In the assembler code this function consists of 196 bytes of code! How can this be?</p>
<p>Disassembling the binary reveals this:<br />
<code></p>
<blockquote><p>
00000436 :<br />
 436:   92 12 00 00     call    &amp;0x0000         ;<br />
 43a:   30 41           ret<br />
 43c:   2f 74           subc    @r4,    r15     ;<br />
 43e:   6d 70           subc.b  @r0,    r13     ;<br />
 440:   2f 74           subc    @r4,    r15     ;<br />
 442:   63 2f           jc      $-312           ;abs 0x30a<br />
 444:   72 65           addc.b  @r5+,   r2      ;<br />
 446:   63 65           .word   0x6563; ????<br />
 448:   69 76           subc.b  @r6,    r9      ;<br />
 44a:   65 2e           jc      $-820           ;abs 0x116<br />
 44c:   73 6f           .word   0x6f73; ????<br />
 44e:   63 6b           .word   0x6b63; ????<br />
 450:   00 2f           jc      $-510           ;abs 0x252<br />
 452:   74 6d           addc.b  @r13+,  r4      ;<br />
 454:   70 2f           jc      $-286           ;abs 0x336<br />
 456:   74 63           addc.b  #-1,    r4      ;r3 As==11<br />
 458:   2f 73           subc    #2,     r15     ;r3 As==10<br />
 45a:   65 6e           addc.b  @r14,   r5      ;<br />
[...]<br />
 4f2:   73 69           .word   0x6973; ????<br />
 4f4:   6e 6b           addc.b  @r11,   r14     ;<br />
 4f6:   2e 73           subc    #2,     r14     ;r3 As==10<br />
 4f8:   6f 63           addc.b  #2,     r15     ;r3 As==10<br />
 4fa:   6b 00           .word   0x006b; ????
</p></blockquote>
<p></code></p>
<p>WTF?!? The second command is a <code>ret</code>. This ends the function. There is no jump before that. So everything below is unreachable code. And anyways, it does not seem to do something meaningful. As long as I haven&#8217;t completely misunderstood something, I think this is a bug.</p>
<p>If I would not have had a closer look I would have trusted the output of the tools and used it as an argument for or against my hypothesis. Because, as we all know, you can trust your tools. Ouch!</p>
<p>Well, could be a known issue and maybe its even fixed. So I checked the compiler version. Turns out, it&#8217;s GCC version 3.2.3! According to the <a href="http://gcc.gnu.org/releases.html">GCC release documentation</a> this release is from October 2003. It is over six years old. Double-checking <a href="http://www.tinyos.net/tinyos-2.x/doc/html/install-tinyos.html">other distribution channels</a> makes clear, that this is really what the TinyOS community uses.</p>
<p>I mean, maybe we should use recent tools before we complain that deploying motes is hard. Maybe it&#8217;s due to compiler bugs that motes tend to inexplicably reboot now and then.</p>
<p>How can I measure the properties of the generated code now anyway? Do I really have to build a cross compiler from source? So much for unexpected problems&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.ethz.ch/copton/2010/02/21/trust-your-tools/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>xtc, meta-models and static typing</title>
		<link>http://blogs.ethz.ch/copton/2010/01/22/xtc-meta-models-and-static-typing/</link>
		<comments>http://blogs.ethz.ch/copton/2010/01/22/xtc-meta-models-and-static-typing/#comments</comments>
		<pubDate>Fri, 22 Jan 2010 09:33:29 +0000</pubDate>
		<dc:creator>Alexander</dc:creator>
				<category><![CDATA[article]]></category>
		<category><![CDATA[C/C++]]></category>
		<category><![CDATA[parser]]></category>

		<guid isPermaLink="false">http://blogs.ethz.ch/copton/?p=406</guid>
		<description><![CDATA[For my current work I want to implement a C* to C compiler, where * stands for a yet unknown set of extensions and restrictions. In my opinion, parsing expression grammars are the tool of choice for growing a grammars. Among the existing PEG tools, the Rats! parser generator of the eXTensible C framework offers [...]]]></description>
			<content:encoded><![CDATA[<p>For my <a href="http://blogs.ethz.ch/copton/2010/01/20/threads-for-the-programmer-events-for-the-machine/">current work</a> I want to implement a C* to C compiler, where * stands for a yet unknown set of extensions and restrictions.</p>
<p>In my opinion, <a href="http://blogs.ethz.ch/copton/2009/07/08/parsing-expression-grammars/"> parsing expression grammars</a> are the tool of choice for growing a grammars. Among the existing PEG tools, the <a href="http://blogs.ethz.ch/copton/2009/09/16/rats/">Rats! parser generator</a> of the <a href="http://www.cs.nyu.edu/rgrimm/xtc/">eXTensible C framework</a> offers the most. Besides many handy features there is a complete C grammar and a pretty printer. Ready to take off!</p>
<p><span id="more-406"></span></p>
<p>Because my compiler does more than simple search-and-replace transformations, I won&#8217;t get along with <a href="http://cs.nyu.edu/~soule/doc/xtc/xform/package-summary.html">xform</a>, which is a domain specific language for AST transformations of the xtc framework. Instead, I think I will need full turing-completeness. So I just want to use the AST from the xtc parser and plug my transformation engine there. For the implemenation of the latter I have chosen <a href="http://www.scala-lang.org/">Scala</a>, because it integrates well with Java and offers many features like functional programming and pattern matching, which should serve well for compiler tasks.</p>
<p>Parsers generated by Rats! produce ASTs which are composed of <a href="http://cs.nyu.edu/~soule/doc/xtc/tree/GNode.html">GNodes</a>. A GNode basically is a tuple of a name and a list of children, which often are GNodes again and sometimes are Strings or other leafe objects. A compiler which works on such an AST must repeatedly compare strings and address child nodes by their index in the children&#8217;s list. This makes the compiler&#8217;s code hard to write, read and maintain. Furthermore the toolchain is unable to assist me as it has no information about what I am doing.</p>
<p>In principle, though, Scala could help me as it is a strongly typed programming language. In order to take full advantage of this I need to transform the GNode-based AST into Scala objects. Every name of a GNode corresponds to a case class with the types and the names of the members set according to the children&#8217;s list of that node. In other words, I specify the meta-model of the C AST in terms of Scala types. Then I can use Scala&#8217;s pattern matching to find nodes of the AST, use functional programming to do the transformation and use the Scala AST classes to construct the result. And for all those tasks the Scala compiler will assit me with type checking. Sound&#8217;s good.</p>
<p>But here is the the problem: There are approx 140 different names of GNodes in the C AST of xtc. Writing all corresponding Scala classes plus the transformation code for both directions is a cumbersome and time-consuming way. Writing tests for all possible cases is even worse. And maintaining all this code for later modifications of the source language&#8217;s grammar is hell.</p>
<p>Instead, I would like to generate that code. What I need therefore is a machine-readable form of the meta-model, which basically is specified by the Rats! grammar of the language. But there are a number of Rats! rules such as lifting and desugaring, which make the meta-model of the resulting AST slightly different from the grammar.</p>
<p>But fortunatelly xtc includes <a href="http://cs.nyu.edu/~soule/doc/xtc/typical/package-summary.html">Typical</a>, &#8220;a language and compiler for specification and generation of type checkers&#8221;. Among other things Rats! support to dump the meta-model of any grammar in Typical notation, and there is a Rats! grammar for the Typical format. So, I could use this chain of tools and plug in a code generator at the end, which produces the meta-model in Scala type system notation.</p>
<p>At a closer look, though, some information is missing in the Typical format, which in particular is the name of child nodes if they are not GNodes. Without that information the generated Scala classes would end up with names such as <code>string1</code>, <code>string2</code>, etc, instead of <code>structureTag</code> or alike. This is not very nice.</p>
<p>That&#8217;s why I though about introducing a backend next to Typical which is capable of dumping the meta-model as a <a href="http://www.omg.org/spec/UML/2.2/">UML class diagram</a> in the <a href="http://www.omg.org/technology/documents/formal/xmi.htm">XMI</a> format. Unfortunatelly xtc seems to be not prepared for such extensions. The code which does the printing in Typical format is part of the <a href="http://cs.nyu.edu/~soule/doc/xtc/type/AST.html">AST class</a>, which is the father of the <a href="http://cs.nyu.edu/~soule/doc/xtc/type/JavaAST.html">JavaAST</a> class. An instance of the latter is created by the <a href="http://cs.nyu.edu/~soule/doc/xtc/parser/Rats.html">Rats class</a> and passed to a <a href="http://cs.nyu.edu/~soule/doc/xtc/parser/TreeTyper.html">TreeTyper</a> instance, which invokes the printing. So, it would need some hacking to integrate an alternative dump format into this code.</p>
<p>But the real show stopper is something else. Rats! parser have no problem with producing two GNodes with the same name but with different types of children.</p>
<pre><code>
$ cat example.rats
module example;

public generic Foo = Bar \ Baz;
generic Bar = "bar";
generic Baz = "baz";

$ java xtc.parser.Rats -ast -variant example.rats
[...]
mltype foo = Foo of [
    | `SomeBar of bar
    | `SomeBaz of baz
  ] ;
mltype bar = Bar of string ;
mltype baz = Baz of string ;
</code></pre>
<p>I don&#8217;t fully understand the Typical format, but as far as I can see this means, that the child of a <code>Foo</code> is either a <code>Bar</code> or a <code>Baz</code>, but there is no common base class of them. Looking into the generated parser code confirms this:</p>
<pre><code>
$ java xtc.parser.Rats example.rats
$ cat example.java
[...]
  public Result pFoo(final int yyStart) throws IOException {
  [...]
    // Alternative 1.
    yyResult = pBar(yyStart);
  [...]
      Node v$g$1 = yyResult.semanticValue();
      yyValue = GNode.create("Foo", v$g$1);
  [...]
    // Alternative 2.
    yyResult = pBaz(yyStart);
  [...]
      Node v$g$2 = yyResult.semanticValue();
      yyValue = GNode.create("Foo", v$g$2);
[...]
</pre>
<p></code></p>
<p>So it seems to me, that Rats! and static type systems do not fit together in general. But there might be a way out.</p>
<pre>
$ cat example2.rats
module example2;

public generic Foo = Bar @Bar / Baz @Baz;
generic Bar = "bar";
generic Baz = "baz";

$ java xtc.parser.Rats -ast -variant example2.rats
[...]
mltype foo =
  | Bar of foo
  | Baz of foo ;
</pre>
<p>By using node markers we can force the names of the generated GNodes to a specific value. For the meta-model this means that <code>Foo</code> is an abstract class and <code>Bar</code> and <code>Baz</code> inherit from it.</p>
<p>So I will have to find out, how I can rewrite the C grammar in a way that the language is not changed but the resulting meta-model can be statically typed. And then I will have to hack an XMI backend and finally write the code generator for the Scala classes. So much for unexpected problems...</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.ethz.ch/copton/2010/01/22/xtc-meta-models-and-static-typing/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

