summaryrefslogtreecommitdiffstats
path: root/articles/xerl-0.5-intermediate-module/index.html
diff options
context:
space:
mode:
Diffstat (limited to 'articles/xerl-0.5-intermediate-module/index.html')
-rw-r--r--articles/xerl-0.5-intermediate-module/index.html364
1 files changed, 208 insertions, 156 deletions
diff --git a/articles/xerl-0.5-intermediate-module/index.html b/articles/xerl-0.5-intermediate-module/index.html
index dc9f2a2a..38627277 100644
--- a/articles/xerl-0.5-intermediate-module/index.html
+++ b/articles/xerl-0.5-intermediate-module/index.html
@@ -7,7 +7,7 @@
<meta name="description" content="">
<meta name="author" content="Loïc Hoguin based on a design from (Soft10) Pol Cámara">
- <meta name="generator" content="Hugo 0.17" />
+ <meta name="generator" content="Hugo 0.26" />
<title>Nine Nines: Xerl: intermediate module</title>
@@ -74,136 +74,136 @@
</p>
</header>
-<div class="paragraph"><p>Today we will start the work on the intermediate module
-that will be used to run the code for the expressions found
-in our file&#8217;s body, replacing our interpreter.</p></div>
-<div class="paragraph"><p>This is what we want to have when all the work is done:</p></div>
-<div class="listingblock">
-<div class="content">
-<pre><code>xerl -&gt; tokens -&gt; AST -&gt; intermediate -&gt; cerl</code></pre>
-</div></div>
-<div class="paragraph"><p>Today we will perform this work only on the atomic integer
-expression however, so we will not build any module at the end.
-We have a few more things to take care of before getting there.
-This does mean that we completely break compilation of modules
-though, so hopefully we can resolve that soon.</p></div>
-<div class="paragraph"><p>This intermediate representation is in the form of a module
-which contains a single function: <code>run/0</code>. This function
-contains all the expressions from our Xerl source file.</p></div>
-<div class="paragraph"><p>In the case of a Xerl source file only containing the integer
-<code>42</code>, we will obtain the following module ready to
-be executed:</p></div>
-<div class="listingblock">
-<div class="content"><!-- Generator: GNU source-highlight 3.1.8
-by Lorenzo Bettini
-http://www.lorenzobettini.it
-http://www.gnu.org/software/src-highlite -->
-<pre><tt><span style="font-weight: bold"><span style="color: #000080">-module</span></span>(<span style="color: #FF6600">'$xerl_intermediate'</span>)<span style="color: #990000">.</span>
-<span style="font-weight: bold"><span style="color: #000080">-export</span></span>([<span style="font-weight: bold"><span style="color: #000000">run</span></span><span style="color: #990000">/</span><span style="color: #993399">0</span>])<span style="color: #990000">.</span>
-
-<span style="font-weight: bold"><span style="color: #000000">run</span></span>() <span style="color: #990000">-&gt;</span>
- <span style="color: #993399">42</span><span style="color: #990000">.</span></tt></pre></div></div>
-<div class="paragraph"><p>Running it will of course give us a result of <code>42</code>,
-the same we had when interpreting expressions.</p></div>
-<div class="paragraph"><p>The resulting Core Erlang code looks like this:</p></div>
-<div class="listingblock">
-<div class="content"><!-- Generator: GNU source-highlight 3.1.8
-by Lorenzo Bettini
-http://www.lorenzobettini.it
-http://www.gnu.org/software/src-highlite -->
-<pre><tt><span style="color: #FF6600">module</span> <span style="color: #FF6600">'$xerl_intermediate'</span> [<span style="color: #FF6600">'run'</span><span style="color: #990000">/</span><span style="color: #993399">0</span>]
- <span style="color: #FF6600">attributes</span> []
-<span style="color: #FF6600">'run'</span><span style="color: #990000">/</span><span style="color: #993399">0</span> <span style="color: #990000">=</span>
- <span style="font-weight: bold"><span style="color: #0000FF">fun</span></span> () <span style="color: #990000">-&gt;</span>
- <span style="color: #993399">42</span>
-<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
-<div class="paragraph"><p>The nice thing about doing it like this is that other than the
-definition of the intermediate module and its <code>run/0</code>
-function, we can use the same code we are using for generating
-the final Beam file. It may also be faster than interpreting
-if you have complex modules.</p></div>
-<div class="paragraph"><p>Of course this here only works for the simplest cases, as you
-cannot declare a module or a function inside another Erlang function.
-We will need to wrap these into function calls to the Xerl compiler
-that will take care of compiling them, making them available for
-any subsequent expression. We will also need to pass the environment
-to the <code>run</code> function to keep track of all this.</p></div>
-<div class="paragraph"><p>This does mean that we will have different code for compiling
-<code>fun</code> and <code>mod</code> expressions when creating
-the intermediate module. But the many other expressions don&#8217;t need
-any special care.</p></div>
-<div class="paragraph"><p>Right now we&#8217;ve used the <code>'$xerl_intermediate'</code> atom
-for the intermediate module name because we only have one, but we
-will need to have a more random name later on when we&#8217;ll implement
-modules this way.</p></div>
-<div class="paragraph"><p>The attentive mind will know by now that when compiling a Xerl
-file containing one module, we will need to compile two intermediate
-modules: one for the file body, and one for the module&#8217;s body. Worry
-not though, if we only detect <code>mod</code> instructions in the file
-body, we can just skip this phase.</p></div>
-<div class="paragraph"><p>While we&#8217;re at it, we&#8217;ll modify our code generator to handle lists
-of expressions, which didn&#8217;t actually work with integer literals
-before.</p></div>
-<div class="paragraph"><p>We&#8217;re going to use Core Erlang sequences for running the many
-expressions. Sequences work like <code>let</code>, except no value
-is actually bound. Perfect for our case, since we don&#8217;t support
-binding values at this time anyway.</p></div>
-<div class="paragraph"><p>Sequences have an argument and a body, both being Core Erlang
-expressions. The simplest way to have many expressions is to use
-a simple expression for the argument and a sequence for the rest
-of the expressions. When we encounter the last expression in the
-list, we do not create a sequence.</p></div>
-<div class="paragraph"><p>The result is this very simple function:</p></div>
-<div class="listingblock">
-<div class="content"><!-- Generator: GNU source-highlight 3.1.8
-by Lorenzo Bettini
-http://www.lorenzobettini.it
-http://www.gnu.org/software/src-highlite -->
-<pre><tt><span style="font-weight: bold"><span style="color: #000000">comp_body</span></span>([<span style="color: #009900">Expr</span>]) <span style="color: #990000">-&gt;</span>
- <span style="font-weight: bold"><span style="color: #000000">expr</span></span>(<span style="color: #009900">Expr</span>);
-<span style="font-weight: bold"><span style="color: #000000">comp_body</span></span>([<span style="color: #009900">Expr</span>|<span style="color: #009900">Exprs</span>]) <span style="color: #990000">-&gt;</span>
- <span style="color: #009900">Arg</span> <span style="color: #990000">=</span> <span style="font-weight: bold"><span style="color: #000000">expr</span></span>(<span style="color: #009900">Expr</span>),
- <span style="color: #009900">Body</span> <span style="color: #990000">=</span> <span style="font-weight: bold"><span style="color: #000000">comp_body</span></span>(<span style="color: #009900">Exprs</span>),
- <span style="font-weight: bold"><span style="color: #000000">cerl:c_seq</span></span>(<span style="color: #009900">Arg</span>, <span style="color: #009900">Body</span>)<span style="color: #990000">.</span></tt></pre></div></div>
-<div class="paragraph"><p>In the case of our example above, a sequence will not be created,
-we only have one expression. If we were to have <code>42, 43, 44</code>
-in our Xerl source file, we would have a result equivalent to the
-following before optimization:</p></div>
-<div class="listingblock">
-<div class="content"><!-- Generator: GNU source-highlight 3.1.8
-by Lorenzo Bettini
-http://www.lorenzobettini.it
-http://www.gnu.org/software/src-highlite -->
-<pre><tt><span style="font-weight: bold"><span style="color: #000080">-module</span></span>(<span style="color: #FF6600">'$xerl_intermediate'</span>)<span style="color: #990000">.</span>
-<span style="font-weight: bold"><span style="color: #000080">-export</span></span>([<span style="font-weight: bold"><span style="color: #000000">run</span></span><span style="color: #990000">/</span><span style="color: #993399">0</span>])<span style="color: #990000">.</span>
-
-<span style="font-weight: bold"><span style="color: #000000">run</span></span>() <span style="color: #990000">-&gt;</span>
- <span style="color: #993399">42</span>,
- <span style="color: #993399">43</span>,
- <span style="color: #993399">44</span><span style="color: #990000">.</span></tt></pre></div></div>
-<div class="paragraph"><p>And the result is of course <code>44</code>.</p></div>
-<div class="paragraph"><p>The resulting Core Erlang code looks like this:</p></div>
-<div class="listingblock">
-<div class="content"><!-- Generator: GNU source-highlight 3.1.8
-by Lorenzo Bettini
-http://www.lorenzobettini.it
-http://www.gnu.org/software/src-highlite -->
-<pre><tt><span style="color: #FF6600">module</span> <span style="color: #FF6600">'$xerl_intermediate'</span> [<span style="color: #FF6600">'run'</span><span style="color: #990000">/</span><span style="color: #993399">0</span>]
- <span style="color: #FF6600">attributes</span> []
-<span style="color: #FF6600">'run'</span><span style="color: #990000">/</span><span style="color: #993399">0</span> <span style="color: #990000">=</span>
- <span style="font-weight: bold"><span style="color: #0000FF">fun</span></span> () <span style="color: #990000">-&gt;</span>
- <span style="color: #FF6600">do</span> <span style="color: #993399">42</span>
- <span style="color: #FF6600">do</span> <span style="color: #993399">43</span>
- <span style="color: #993399">44</span>
-<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
-<div class="paragraph"><p>Feels very lisp-y, right? Yep.</p></div>
-<div class="ulist"><ul>
-<li>
-<p>
-<a href="https://github.com/extend/xerl/blob/0.5/">View the source</a>
-</p>
-</li>
-</ul></div>
+<div class="paragraph"><p>Today we will start the work on the intermediate module
+that will be used to run the code for the expressions found
+in our file&#8217;s body, replacing our interpreter.</p></div>
+<div class="paragraph"><p>This is what we want to have when all the work is done:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>xerl -&gt; tokens -&gt; AST -&gt; intermediate -&gt; cerl</code></pre>
+</div></div>
+<div class="paragraph"><p>Today we will perform this work only on the atomic integer
+expression however, so we will not build any module at the end.
+We have a few more things to take care of before getting there.
+This does mean that we completely break compilation of modules
+though, so hopefully we can resolve that soon.</p></div>
+<div class="paragraph"><p>This intermediate representation is in the form of a module
+which contains a single function: <code>run/0</code>. This function
+contains all the expressions from our Xerl source file.</p></div>
+<div class="paragraph"><p>In the case of a Xerl source file only containing the integer
+<code>42</code>, we will obtain the following module ready to
+be executed:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.8
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #000080">-module</span></span>(<span style="color: #FF6600">'$xerl_intermediate'</span>)<span style="color: #990000">.</span>
+<span style="font-weight: bold"><span style="color: #000080">-export</span></span>([<span style="font-weight: bold"><span style="color: #000000">run</span></span><span style="color: #990000">/</span><span style="color: #993399">0</span>])<span style="color: #990000">.</span>
+
+<span style="font-weight: bold"><span style="color: #000000">run</span></span>() <span style="color: #990000">-&gt;</span>
+ <span style="color: #993399">42</span><span style="color: #990000">.</span></tt></pre></div></div>
+<div class="paragraph"><p>Running it will of course give us a result of <code>42</code>,
+the same we had when interpreting expressions.</p></div>
+<div class="paragraph"><p>The resulting Core Erlang code looks like this:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.8
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #FF6600">module</span> <span style="color: #FF6600">'$xerl_intermediate'</span> [<span style="color: #FF6600">'run'</span><span style="color: #990000">/</span><span style="color: #993399">0</span>]
+ <span style="color: #FF6600">attributes</span> []
+<span style="color: #FF6600">'run'</span><span style="color: #990000">/</span><span style="color: #993399">0</span> <span style="color: #990000">=</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">fun</span></span> () <span style="color: #990000">-&gt;</span>
+ <span style="color: #993399">42</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
+<div class="paragraph"><p>The nice thing about doing it like this is that other than the
+definition of the intermediate module and its <code>run/0</code>
+function, we can use the same code we are using for generating
+the final Beam file. It may also be faster than interpreting
+if you have complex modules.</p></div>
+<div class="paragraph"><p>Of course this here only works for the simplest cases, as you
+cannot declare a module or a function inside another Erlang function.
+We will need to wrap these into function calls to the Xerl compiler
+that will take care of compiling them, making them available for
+any subsequent expression. We will also need to pass the environment
+to the <code>run</code> function to keep track of all this.</p></div>
+<div class="paragraph"><p>This does mean that we will have different code for compiling
+<code>fun</code> and <code>mod</code> expressions when creating
+the intermediate module. But the many other expressions don&#8217;t need
+any special care.</p></div>
+<div class="paragraph"><p>Right now we&#8217;ve used the <code>'$xerl_intermediate'</code> atom
+for the intermediate module name because we only have one, but we
+will need to have a more random name later on when we&#8217;ll implement
+modules this way.</p></div>
+<div class="paragraph"><p>The attentive mind will know by now that when compiling a Xerl
+file containing one module, we will need to compile two intermediate
+modules: one for the file body, and one for the module&#8217;s body. Worry
+not though, if we only detect <code>mod</code> instructions in the file
+body, we can just skip this phase.</p></div>
+<div class="paragraph"><p>While we&#8217;re at it, we&#8217;ll modify our code generator to handle lists
+of expressions, which didn&#8217;t actually work with integer literals
+before.</p></div>
+<div class="paragraph"><p>We&#8217;re going to use Core Erlang sequences for running the many
+expressions. Sequences work like <code>let</code>, except no value
+is actually bound. Perfect for our case, since we don&#8217;t support
+binding values at this time anyway.</p></div>
+<div class="paragraph"><p>Sequences have an argument and a body, both being Core Erlang
+expressions. The simplest way to have many expressions is to use
+a simple expression for the argument and a sequence for the rest
+of the expressions. When we encounter the last expression in the
+list, we do not create a sequence.</p></div>
+<div class="paragraph"><p>The result is this very simple function:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.8
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #000000">comp_body</span></span>([<span style="color: #009900">Expr</span>]) <span style="color: #990000">-&gt;</span>
+ <span style="font-weight: bold"><span style="color: #000000">expr</span></span>(<span style="color: #009900">Expr</span>);
+<span style="font-weight: bold"><span style="color: #000000">comp_body</span></span>([<span style="color: #009900">Expr</span>|<span style="color: #009900">Exprs</span>]) <span style="color: #990000">-&gt;</span>
+ <span style="color: #009900">Arg</span> <span style="color: #990000">=</span> <span style="font-weight: bold"><span style="color: #000000">expr</span></span>(<span style="color: #009900">Expr</span>),
+ <span style="color: #009900">Body</span> <span style="color: #990000">=</span> <span style="font-weight: bold"><span style="color: #000000">comp_body</span></span>(<span style="color: #009900">Exprs</span>),
+ <span style="font-weight: bold"><span style="color: #000000">cerl:c_seq</span></span>(<span style="color: #009900">Arg</span>, <span style="color: #009900">Body</span>)<span style="color: #990000">.</span></tt></pre></div></div>
+<div class="paragraph"><p>In the case of our example above, a sequence will not be created,
+we only have one expression. If we were to have <code>42, 43, 44</code>
+in our Xerl source file, we would have a result equivalent to the
+following before optimization:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.8
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #000080">-module</span></span>(<span style="color: #FF6600">'$xerl_intermediate'</span>)<span style="color: #990000">.</span>
+<span style="font-weight: bold"><span style="color: #000080">-export</span></span>([<span style="font-weight: bold"><span style="color: #000000">run</span></span><span style="color: #990000">/</span><span style="color: #993399">0</span>])<span style="color: #990000">.</span>
+
+<span style="font-weight: bold"><span style="color: #000000">run</span></span>() <span style="color: #990000">-&gt;</span>
+ <span style="color: #993399">42</span>,
+ <span style="color: #993399">43</span>,
+ <span style="color: #993399">44</span><span style="color: #990000">.</span></tt></pre></div></div>
+<div class="paragraph"><p>And the result is of course <code>44</code>.</p></div>
+<div class="paragraph"><p>The resulting Core Erlang code looks like this:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.8
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="color: #FF6600">module</span> <span style="color: #FF6600">'$xerl_intermediate'</span> [<span style="color: #FF6600">'run'</span><span style="color: #990000">/</span><span style="color: #993399">0</span>]
+ <span style="color: #FF6600">attributes</span> []
+<span style="color: #FF6600">'run'</span><span style="color: #990000">/</span><span style="color: #993399">0</span> <span style="color: #990000">=</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">fun</span></span> () <span style="color: #990000">-&gt;</span>
+ <span style="color: #FF6600">do</span> <span style="color: #993399">42</span>
+ <span style="color: #FF6600">do</span> <span style="color: #993399">43</span>
+ <span style="color: #993399">44</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
+<div class="paragraph"><p>Feels very lisp-y, right? Yep.</p></div>
+<div class="ulist"><ul>
+<li>
+<p>
+<a href="https://github.com/extend/xerl/blob/0.5/">View the source</a>
+</p>
+</li>
+</ul></div>
</article>
</div>
@@ -212,55 +212,107 @@ http://www.gnu.org/software/src-highlite -->
<h3>More articles</h3>
<ul id="articles-nav" class="extra_margin">
- <li><a href="https://ninenines.eu/articles/cowboy-2.0.0-rc.2/">Cowboy 2.0 release candidate 2</a></li>
+
+ <li><a href="https://ninenines.eu/articles/cowboy-2.0.0-rc.2/">Cowboy 2.0 release candidate 2</a></li>
+
+
+
+ <li><a href="https://ninenines.eu/articles/cowboy-2.0.0-rc.1/">Cowboy 2.0 release candidate 1</a></li>
+
- <li><a href="https://ninenines.eu/articles/cowboy-2.0.0-rc.1/">Cowboy 2.0 release candidate 1</a></li>
+
+ <li><a href="https://ninenines.eu/articles/the-elephant-in-the-room/">The elephant in the room</a></li>
+
- <li><a href="https://ninenines.eu/articles/the-elephant-in-the-room/">The elephant in the room</a></li>
+
+ <li><a href="https://ninenines.eu/articles/dont-let-it-crash/">Don&#39;t let it crash</a></li>
+
- <li><a href="https://ninenines.eu/articles/dont-let-it-crash/">Don&#39;t let it crash</a></li>
+
+ <li><a href="https://ninenines.eu/articles/cowboy-2.0.0-pre.4/">Cowboy 2.0 pre-release 4</a></li>
+
- <li><a href="https://ninenines.eu/articles/cowboy-2.0.0-pre.4/">Cowboy 2.0 pre-release 4</a></li>
+
+ <li><a href="https://ninenines.eu/articles/ranch-1.3/">Ranch 1.3</a></li>
+
- <li><a href="https://ninenines.eu/articles/ranch-1.3/">Ranch 1.3</a></li>
+
+ <li><a href="https://ninenines.eu/articles/ml-archives/">Mailing list archived</a></li>
+
- <li><a href="https://ninenines.eu/articles/ml-archives/">Mailing list archived</a></li>
+
+ <li><a href="https://ninenines.eu/articles/website-update/">Website update</a></li>
+
- <li><a href="https://ninenines.eu/articles/website-update/">Website update</a></li>
+
+ <li><a href="https://ninenines.eu/articles/erlanger-playbook-september-2015-update/">The Erlanger Playbook September 2015 Update</a></li>
+
- <li><a href="https://ninenines.eu/articles/erlanger-playbook-september-2015-update/">The Erlanger Playbook September 2015 Update</a></li>
+
+ <li><a href="https://ninenines.eu/articles/erlanger-playbook/">The Erlanger Playbook</a></li>
+
- <li><a href="https://ninenines.eu/articles/erlanger-playbook/">The Erlanger Playbook</a></li>
+
+ <li><a href="https://ninenines.eu/articles/erlang-validate-utf8/">Validating UTF-8 binaries with Erlang</a></li>
+
- <li><a href="https://ninenines.eu/articles/erlang-validate-utf8/">Validating UTF-8 binaries with Erlang</a></li>
+
+ <li><a href="https://ninenines.eu/articles/on-open-source/">On open source</a></li>
+
- <li><a href="https://ninenines.eu/articles/on-open-source/">On open source</a></li>
+
+ <li><a href="https://ninenines.eu/articles/the-story-so-far/">The story so far</a></li>
+
- <li><a href="https://ninenines.eu/articles/the-story-so-far/">The story so far</a></li>
+
+ <li><a href="https://ninenines.eu/articles/cowboy2-qs/">Cowboy 2.0 and query strings</a></li>
+
- <li><a href="https://ninenines.eu/articles/cowboy2-qs/">Cowboy 2.0 and query strings</a></li>
+
+ <li><a href="https://ninenines.eu/articles/january-2014-status/">January 2014 status</a></li>
+
- <li><a href="https://ninenines.eu/articles/january-2014-status/">January 2014 status</a></li>
+
+ <li><a href="https://ninenines.eu/articles/farwest-funded/">Farwest got funded!</a></li>
+
- <li><a href="https://ninenines.eu/articles/farwest-funded/">Farwest got funded!</a></li>
+
+ <li><a href="https://ninenines.eu/articles/erlang.mk-and-relx/">Build Erlang releases with Erlang.mk and Relx</a></li>
+
- <li><a href="https://ninenines.eu/articles/erlang.mk-and-relx/">Build Erlang releases with Erlang.mk and Relx</a></li>
+
+ <li><a href="https://ninenines.eu/articles/xerl-0.5-intermediate-module/">Xerl: intermediate module</a></li>
+
- <li><a href="https://ninenines.eu/articles/xerl-0.5-intermediate-module/">Xerl: intermediate module</a></li>
+
+ <li><a href="https://ninenines.eu/articles/xerl-0.4-expression-separator/">Xerl: expression separator</a></li>
+
- <li><a href="https://ninenines.eu/articles/xerl-0.4-expression-separator/">Xerl: expression separator</a></li>
+
+ <li><a href="https://ninenines.eu/articles/erlang-scalability/">Erlang Scalability</a></li>
+
- <li><a href="https://ninenines.eu/articles/erlang-scalability/">Erlang Scalability</a></li>
+
+ <li><a href="https://ninenines.eu/articles/xerl-0.3-atomic-expressions/">Xerl: atomic expressions</a></li>
+
- <li><a href="https://ninenines.eu/articles/xerl-0.3-atomic-expressions/">Xerl: atomic expressions</a></li>
+
+ <li><a href="https://ninenines.eu/articles/xerl-0.2-two-modules/">Xerl: two modules</a></li>
+
- <li><a href="https://ninenines.eu/articles/xerl-0.2-two-modules/">Xerl: two modules</a></li>
+
+ <li><a href="https://ninenines.eu/articles/xerl-0.1-empty-modules/">Xerl: empty modules</a></li>
+
- <li><a href="https://ninenines.eu/articles/xerl-0.1-empty-modules/">Xerl: empty modules</a></li>
+
+ <li><a href="https://ninenines.eu/articles/ranch-ftp/">Build an FTP Server with Ranch in 30 Minutes</a></li>
+
- <li><a href="https://ninenines.eu/articles/ranch-ftp/">Build an FTP Server with Ranch in 30 Minutes</a></li>
+
+ <li><a href="https://ninenines.eu/articles/tictactoe/">Erlang Tic Tac Toe</a></li>
+
- <li><a href="https://ninenines.eu/articles/tictactoe/">Erlang Tic Tac Toe</a></li>
+
</ul>