<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="http://benkonz.github.io//feed.xml" rel="self" type="application/atom+xml" /><link href="http://benkonz.github.io//" rel="alternate" type="text/html" /><updated>2026-05-10T13:47:28+00:00</updated><id>http://benkonz.github.io//feed.xml</id><title type="html">Ben Konz</title><subtitle>(λ x . x Konz) Benjamin</subtitle><author><name>Ben Konz</name></author><entry><title type="html">Using Ratatool to Rank Tennis Players</title><link href="http://benkonz.github.io//using-Ratatool-to-rank-tennis-players/" rel="alternate" type="text/html" title="Using Ratatool to Rank Tennis Players" /><published>2022-06-14T00:00:00+00:00</published><updated>2022-06-14T00:00:00+00:00</updated><id>http://benkonz.github.io//using-Ratatool-to-rank-tennis-players</id><content type="html" xml:base="http://benkonz.github.io//using-Ratatool-to-rank-tennis-players/"><![CDATA[<p><a href="https://github.com/spotify/ratatool">Ratatool</a> is a tooling suite for sampling, generating, and comparing data. It contains several tools worth checking out, but this tutorial be focused on using <a href="https://github.com/spotify/ratatool/tree/master/ratatool-diffy">BigDiffy</a>.</p>

<p>The goal of this tutorial is to create a pipeline that ingests historical WTA Tennis matches and player information, map them to a format <a href="https://github.com/spotify/ratatool/tree/master/ratatool-diffy">BigDiffy</a> can use, run <a href="https://github.com/spotify/ratatool/tree/master/ratatool-diffy">BigDiffy</a>, and analyze the output. We will be creating a simple <a href="https://github.com/spotify/scio">Scio</a> pipeline in order to properly map and store the data. The code should be fairly intuitive, and there will be instructions on how to run the pipeline.</p>

<p>This tutorial will require a GCP environment to run the <a href="https://github.com/spotify/scio">Scio</a> and <a href="https://github.com/spotify/ratatool">Ratatool</a> pipelines.</p>

<h1 id="getting-the-data">Getting the Data</h1>

<p>WTA tennis ranking data can be found <a href="https://github.com/JeffSackmann/tennis_wta">here</a>. The data can be downloaded via <code class="language-plaintext highlighter-rouge">git clone git@github.com:JeffSackmann/tennis_wta.git</code>. The files we will be using for this tutorial are <code class="language-plaintext highlighter-rouge">wta_players.csv</code> and <code class="language-plaintext highlighter-rouge">wta_rankings_10s.csv</code>. <code class="language-plaintext highlighter-rouge">wta_players.csv</code> has the following schema: layer_id, first_name, last_name, hand, birth_date, country_code. <code class="language-plaintext highlighter-rouge">wta_rankings_10s.csv</code> has the schema: ranking_date, rank, player, points, tours.</p>

<p>For convience of the Scio pipeline, we will store the player and ranking data in GCS. Run <code class="language-plaintext highlighter-rouge">gsutil mb -p $PROJECT_ID gs://tennis-wta-csv</code> and copy the files over via <code class="language-plaintext highlighter-rouge">gsutil cp tennis_wta/wta_players.csv gs://tennis-wta-csv/wta_players.csv</code> and <code class="language-plaintext highlighter-rouge">gsutil cp tennis_wta/wta_rankings_10s.csv gs://tennis-wta-csv/wta_rankings_10s.csv</code>.</p>

<h1 id="creating-the-scio-pipeline">Creating the Scio Pipeline</h1>

<p><a href="https://github.com/spotify/scio">Scio</a> is a <a href="https://www.scala-lang.org/">Scala</a> API for <a href="https://beam.apache.org/">Apache Beam</a> and <a href="https://cloud.google.com/dataflow">Google Cloud Dataflow</a>. We will be writing a simple Scio pipeline to map our tennis match data into <a href="https://avro.apache.org/">Avro</a>, which is a file format that BigDiffy understands.</p>

<p>In order to create our Scio pipeline, run <code class="language-plaintext highlighter-rouge">sbt new spotify/scio.g8</code> and enter <code class="language-plaintext highlighter-rouge">yes</code> to the <code class="language-plaintext highlighter-rouge">DataflowRunner [yes/NO]:</code> prompt, all other prompts can be left as default. This will create our pipeline under the <code class="language-plaintext highlighter-rouge">scio-job</code> directory.</p>

<h2 id="pipeline-logic">Pipeline Logic</h2>

<p>Since Scio CSV parsing isn’t included in the template, update the <code class="language-plaintext highlighter-rouge">build.sbt</code> and add</p>
<div class="language-scala highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="s">"com.spotify"</span> <span class="o">%%</span> <span class="s">"scio-extra"</span> <span class="o">%</span> <span class="n">scioVersion</span><span class="o">,</span>
</code></pre></div></div>
<p>to the <code class="language-plaintext highlighter-rouge">libraryDependencies ++= Seq(...)</code> list.</p>

<p>Replace the contents of <code class="language-plaintext highlighter-rouge">WordCount.scala</code> with</p>

<div class="language-scala highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">package</span> <span class="nn">example</span>

<span class="k">import</span> <span class="nn">com.spotify.scio._</span>
<span class="k">import</span> <span class="nn">com.spotify.scio.avro.types.AvroType</span>
<span class="k">import</span> <span class="nn">com.spotify.scio.extra.csv._</span>
<span class="k">import</span> <span class="nn">com.spotify.scio.values.SCollection</span>
<span class="k">import</span> <span class="nn">kantan.csv._</span>

<span class="k">import</span> <span class="nn">scala.util.Try</span>

<span class="c1">// type to represent a row of wta_players.csv</span>
<span class="k">case</span> <span class="k">class</span> <span class="nc">Player</span><span class="o">(</span><span class="n">playerId</span><span class="k">:</span> <span class="kt">String</span><span class="o">,</span> <span class="n">firstName</span><span class="k">:</span> <span class="kt">String</span><span class="o">,</span> <span class="n">lastName</span><span class="k">:</span> <span class="kt">String</span><span class="o">)</span>
<span class="c1">// type to represent a row of wta_rankings_10s.csv</span>
<span class="k">case</span> <span class="k">class</span> <span class="nc">Ranking</span><span class="o">(</span><span class="n">rankingDate</span><span class="k">:</span> <span class="kt">String</span><span class="o">,</span> <span class="n">rank</span><span class="k">:</span> <span class="kt">String</span><span class="o">,</span> <span class="n">playerId</span><span class="k">:</span> <span class="kt">String</span><span class="o">,</span> <span class="n">points</span><span class="k">:</span> <span class="kt">String</span><span class="o">)</span>

<span class="c1">// type to represent a PlayerRank Avro record</span>
<span class="nd">@AvroType</span><span class="o">.</span><span class="py">toSchema</span>
<span class="k">case</span> <span class="k">class</span> <span class="nc">PlayerRankingOutput</span><span class="o">(</span><span class="n">playerId</span><span class="k">:</span> <span class="kt">String</span><span class="o">,</span> <span class="n">firstName</span><span class="k">:</span> <span class="kt">String</span><span class="o">,</span> <span class="n">lastName</span><span class="k">:</span> <span class="kt">String</span><span class="o">,</span>
                               <span class="n">rankingDate</span><span class="k">:</span> <span class="kt">String</span><span class="o">,</span> <span class="n">rank</span><span class="k">:</span> <span class="kt">Long</span><span class="o">,</span> <span class="n">points</span><span class="k">:</span> <span class="kt">Long</span><span class="o">,</span>
                               <span class="n">playerIdMonth</span><span class="k">:</span> <span class="kt">String</span><span class="o">)</span>

<span class="k">object</span> <span class="nc">WordCount</span> <span class="o">{</span>
  <span class="k">def</span> <span class="nf">main</span><span class="o">(</span><span class="n">cmdlineArgs</span><span class="k">:</span> <span class="kt">Array</span><span class="o">[</span><span class="kt">String</span><span class="o">])</span><span class="k">:</span> <span class="kt">Unit</span> <span class="o">=</span> <span class="o">{</span>
    <span class="c1">// parse CLI arguments</span>
    <span class="nf">val</span> <span class="o">(</span><span class="n">sc</span><span class="o">,</span> <span class="n">args</span><span class="o">)</span> <span class="k">=</span> <span class="nc">ContextAndArgs</span><span class="o">(</span><span class="n">cmdlineArgs</span><span class="o">)</span>
    <span class="k">val</span> <span class="nv">year</span> <span class="k">=</span> <span class="nf">args</span><span class="o">(</span><span class="s">"year"</span><span class="o">)</span>
    <span class="k">val</span> <span class="nv">wtaPlayersInput</span> <span class="k">=</span> <span class="nf">args</span><span class="o">(</span><span class="s">"wtaPlayerInput"</span><span class="o">)</span>
    <span class="k">val</span> <span class="nv">wtaRankingsInput</span> <span class="k">=</span> <span class="nf">args</span><span class="o">(</span><span class="s">"wtaRankingsInput"</span><span class="o">)</span>
    <span class="k">val</span> <span class="nv">output</span> <span class="k">=</span> <span class="nf">args</span><span class="o">(</span><span class="s">"output"</span><span class="o">)</span>

    <span class="c1">// read wta_players.csv and key by playerId</span>
    <span class="k">val</span> <span class="nv">playerCsvs</span><span class="k">:</span> <span class="kt">SCollection</span><span class="o">[(</span><span class="kt">String</span>, <span class="kt">Player</span><span class="o">)]</span> <span class="k">=</span> <span class="o">{</span>
      <span class="k">implicit</span> <span class="k">val</span> <span class="nv">decoder</span><span class="k">:</span> <span class="kt">HeaderDecoder</span><span class="o">[</span><span class="kt">Player</span><span class="o">]</span> <span class="k">=</span>
        <span class="nv">HeaderDecoder</span><span class="o">.</span><span class="py">decoder</span><span class="o">(</span><span class="s">"player_id"</span><span class="o">,</span> <span class="s">"name_first"</span><span class="o">,</span> <span class="s">"name_last"</span><span class="o">)(</span><span class="nv">Player</span><span class="o">.</span><span class="py">apply</span><span class="o">)</span>
      <span class="nv">sc</span><span class="o">.</span><span class="py">csvFile</span><span class="o">(</span><span class="n">wtaPlayersInput</span><span class="o">).</span><span class="py">map</span><span class="o">(</span><span class="n">p</span> <span class="k">=&gt;</span> <span class="o">(</span><span class="nv">p</span><span class="o">.</span><span class="py">playerId</span><span class="o">,</span> <span class="n">p</span><span class="o">))</span>
    <span class="o">}</span>

    <span class="c1">// read wta_rankings_10s.csv and key by playerId</span>
    <span class="k">val</span> <span class="nv">rankingCsvs</span><span class="k">:</span> <span class="kt">SCollection</span><span class="o">[(</span><span class="kt">String</span>, <span class="kt">Ranking</span><span class="o">)]</span> <span class="k">=</span> <span class="o">{</span>
      <span class="k">implicit</span> <span class="k">val</span> <span class="nv">decoder</span><span class="k">:</span> <span class="kt">HeaderDecoder</span><span class="o">[</span><span class="kt">Ranking</span><span class="o">]</span> <span class="k">=</span>
        <span class="nv">HeaderDecoder</span><span class="o">.</span><span class="py">decoder</span><span class="o">(</span><span class="s">"ranking_date"</span><span class="o">,</span> <span class="s">"rank"</span><span class="o">,</span> <span class="s">"player"</span><span class="o">,</span> <span class="s">"points"</span><span class="o">)(</span><span class="nv">Ranking</span><span class="o">.</span><span class="py">apply</span><span class="o">)</span>
      <span class="nv">sc</span><span class="o">.</span><span class="py">csvFile</span><span class="o">(</span><span class="n">wtaRankingsInput</span><span class="o">).</span><span class="py">map</span><span class="o">(</span><span class="n">r</span> <span class="k">=&gt;</span> <span class="o">(</span><span class="nv">r</span><span class="o">.</span><span class="py">playerId</span><span class="o">,</span> <span class="n">r</span><span class="o">))</span>
    <span class="o">}</span>
    <span class="c1">// join on playerId</span>
    <span class="k">val</span> <span class="nv">joined</span><span class="k">:</span> <span class="kt">SCollection</span><span class="o">[(</span><span class="kt">String</span>, <span class="o">(</span><span class="kt">Player</span>, <span class="kt">Ranking</span><span class="o">))]</span> <span class="k">=</span> <span class="n">playerCsvs</span>
      <span class="o">.</span><span class="py">join</span><span class="o">(</span><span class="n">rankingCsvs</span><span class="o">)</span>
    
    <span class="n">joined</span>
      <span class="c1">// map each row to a PlayerRankingOutput avro       </span>
      <span class="o">.</span><span class="py">flatMap</span> <span class="o">{</span>
        <span class="nf">case</span> <span class="o">(</span><span class="n">playerId</span><span class="o">,</span> <span class="o">(</span><span class="n">player</span><span class="o">,</span> <span class="n">ranking</span><span class="o">))</span> <span class="k">=&gt;</span>
          <span class="k">val</span> <span class="nv">month</span> <span class="k">=</span> <span class="nv">ranking</span><span class="o">.</span><span class="py">rankingDate</span><span class="o">.</span><span class="py">substring</span><span class="o">(</span><span class="mi">4</span><span class="o">,</span> <span class="mi">6</span><span class="o">)</span>
          <span class="nc">Try</span><span class="o">(</span><span class="nc">PlayerRankingOutput</span><span class="o">(</span>
            <span class="n">playerId</span><span class="o">,</span>
            <span class="nv">player</span><span class="o">.</span><span class="py">firstName</span><span class="o">,</span>
            <span class="nv">player</span><span class="o">.</span><span class="py">lastName</span><span class="o">,</span>
            <span class="nv">ranking</span><span class="o">.</span><span class="py">rankingDate</span><span class="o">,</span>
            <span class="nv">ranking</span><span class="o">.</span><span class="py">rank</span><span class="o">.</span><span class="py">toLong</span><span class="o">,</span>
            <span class="nv">ranking</span><span class="o">.</span><span class="py">points</span><span class="o">.</span><span class="py">toLong</span><span class="o">,</span>
            <span class="c1">// key by playerId_firstName_lastName_matchMonth</span>
            <span class="c1">// this is the column that BigDiffy will use to find player match</span>
            <span class="c1">// results across two datasets</span>
            <span class="n">s</span><span class="s">"${playerId}_${player.firstName}_${player.lastName}_$month"</span>
          <span class="o">)).</span><span class="py">toOption</span>
      <span class="o">}</span>
      <span class="c1">// filter by the year arg</span>
      <span class="o">.</span><span class="py">filter</span><span class="o">(</span><span class="n">playerRanking</span> <span class="k">=&gt;</span> <span class="nv">playerRanking</span><span class="o">.</span><span class="py">rankingDate</span><span class="o">.</span><span class="py">startsWith</span><span class="o">(</span><span class="n">year</span><span class="o">))</span>
      <span class="c1">// map(...).sampleByKey(...).values.flatten is used to </span>
      <span class="c1">// key by month, then pick a single (arbitrary) match across one month for each month</span>
      <span class="o">.</span><span class="py">map</span><span class="o">(</span><span class="n">playerRanking</span> <span class="k">=&gt;</span> <span class="o">(</span><span class="nv">playerRanking</span><span class="o">.</span><span class="py">playerIdMonth</span><span class="o">,</span> <span class="n">playerRanking</span><span class="o">))</span>
      <span class="o">.</span><span class="py">sampleByKey</span><span class="o">(</span><span class="n">sampleSize</span> <span class="k">=</span> <span class="mi">1</span><span class="o">)</span>
      <span class="o">.</span><span class="py">values</span>
      <span class="o">.</span><span class="py">flatten</span>
      <span class="c1">// save as a PlayerRankingOutput avro record</span>
      <span class="o">.</span><span class="py">saveAsTypedAvroFile</span><span class="o">(</span><span class="n">output</span><span class="o">)</span>

    <span class="nv">sc</span><span class="o">.</span><span class="py">run</span><span class="o">().</span><span class="py">waitUntilDone</span><span class="o">()</span>
  <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<h2 id="running-the-pipeline">Running the pipeline</h2>

<p>Before we run big-diffy, we will need to create a dataset in BigQuery for BigDiffy to create tables and write it’s output to. We can do this through the CLI via <code class="language-plaintext highlighter-rouge">gsutil mb -p $PROJECT_ID gs://tennis-wta-avro</code>.</p>

<p>Additionally, we will need a service account with Dataflow Worker, Service Account User, BigQuery Job User, BigQuery Data Owner, BigQuery User, and Storage Creator + Viewer permissions.</p>

<p>Also, be sure to enable the Dataflow API for your project if you haven’t already.</p>

<p>We can build the JAR with <code class="language-plaintext highlighter-rouge">sbt stage</code> and run it via:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> sbt <span class="s2">"runMain example.WordCount
    --project=[PROJECT] --runner=DataflowRunner --zone=us-east1-b --region=us-east1
    --serviceAccount=[SERVICE_ACCOUNT]
    --wtaPlayerInput=gs://tennis-wta-csv/wta_players.csv --wtaRankingsInput=gs://tennis-wta-csv/wta_rankings_10s.csv
    --year=2010
    --output=gs://tennis-wta-avro/wtaRankingsAvro/2010/"</span>
</code></pre></div></div>

<p>since we need another year to compare the data, run the job again with a different year.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> sbt <span class="s2">"runMain example.WordCount
    --project=[PROJECT] --runner=DataflowRunner --zone=us-east1-b --region=us-east1
    --serviceAccount=[SERVICE_ACCOUNT]
    --wtaPlayerInput=gs://tennis-wta-csv/wta_players.csv --wtaRankingsInput=gs://tennis-wta-csv/wta_rankings_10s.csv
    --year=2011
    --output=gs://tennis-wta-avro/wtaRankingsAvro/2011/"</span>
</code></pre></div></div>

<h2 id="inspecting-the-data">Inspecting the data</h2>

<p>The data should be inspectable via <a href="https://avro.apache.org/docs/current/gettingstartedjava.html">avro-tools</a>. Simply pull down one of the avro files with <code class="language-plaintext highlighter-rouge">gsutil cp gs://tennis-wta-avro/wtaRankingsAvro/2010/part-00000-of-00001.avro .</code> and inspect it with <code class="language-plaintext highlighter-rouge">avro-tools tojson part-00000-of-00001.avro | less</code></p>

<h1 id="installing-ratatool">Installing Ratatool</h1>

<p>Instructions for installing Ratatool can be found <a href="https://github.com/spotify/ratatool#usage">here</a>. If you’re on Mac, there is a Homebrew tap:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>brew tap spotify/public
brew <span class="nb">install </span>ratatool
ratatool
</code></pre></div></div>

<p>Otherwise download the <a href="https://github.com/spotify/ratatool/releases">release</a> jar and run it:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>wget https://github.com/spotify/ratatool/releases/download/v0.3.10/ratatool-cli-0.3.10.tar.gz
<span class="nb">tar </span>xvf ratatool-cli-0.3.10.tar.gz
ratatool-cli-0.3.10/bin/big-diffy
</code></pre></div></div>

<h1 id="running-ratatool">Running Ratatool</h1>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>bq <span class="nt">--project_id</span><span class="o">=[</span>PROJECT] <span class="nt">--location</span><span class="o">=</span>US mk <span class="nt">-d</span> <span class="nt">--default_table_expiration</span> 3600 ratatool_wta_output
</code></pre></div></div>
<p>then we can run BigDiffy via</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ratatool-cli-0.3.10/bin/big-diffy <span class="nt">--input-mode</span><span class="o">=</span>avro <span class="nt">--output-mode</span><span class="o">=</span>bigquery <span class="nt">--key</span><span class="o">=</span>playerIdMonth <span class="nt">--lhs</span><span class="o">=</span>gs://tennis-wta-avro/wtaRankingsAvro/2010/<span class="se">\*</span>.avro <span class="nt">--rhs</span><span class="o">=</span>gs://tennis-wta-avro/wtaRankingsAvro/2011/<span class="se">\*</span>.avro <span class="nt">--output</span><span class="o">=</span>ratatool_wta_output.tennis-wta-bigdiffy <span class="nt">--project</span><span class="o">=[</span>PROJECT] <span class="nt">--runner</span><span class="o">=</span>DataflowRunner <span class="nt">--region</span><span class="o">=[</span>REGION] <span class="nt">--serviceAccount</span><span class="o">=[</span>SERVICE_ACCOUNT]
</code></pre></div></div>

<h1 id="analyzing-the-results">Analyzing the results</h1>

<p>To inspect the Ratatool output, navigate to your BigQuery dataset in the GCP console. In there, you’ll see three tables that Ratatool has created: <code class="language-plaintext highlighter-rouge">tennis-wta-bigdiffy_fields</code>, <code class="language-plaintext highlighter-rouge">tennis-wta-bigdiffy_global</code>, and <code class="language-plaintext highlighter-rouge">tennis-wta-bigdiffy_keys</code>.</p>

<h2 id="tennis-wta-bigdiffy_keys">tennis-wta-bigdiffy_keys</h2>

<p><code class="language-plaintext highlighter-rouge">tennis-wta-bigdiffy_keys</code> contains information on the delta’s for each key in the 2010 and 2011 datasets. The <code class="language-plaintext highlighter-rouge">key</code> column corrosponds to that players WTA ID, first name, last name, and month the match took place (seperated by underscores).</p>

<p>We will see <code class="language-plaintext highlighter-rouge">MISSING_LHS</code> in the <code class="language-plaintext highlighter-rouge">diffType</code> column if a player didn’t play for that month in 2010, but did play for that month in 2010, and vis-versa for <code class="language-plaintext highlighter-rouge">MISSING_RHS</code>. A <code class="language-plaintext highlighter-rouge">diffType</code> of <code class="language-plaintext highlighter-rouge">SAME</code> means that that player had the same score across both years for that month’s match, and a <code class="language-plaintext highlighter-rouge">diffType</code> of <code class="language-plaintext highlighter-rouge">DIFFERENT</code> means that player scored differently for that month’s match in 2010 and 2011.</p>

<p>The <code class="language-plaintext highlighter-rouge">delta.field</code> column corrosponds to the field Ratatool is comparing. In this case, that column will either be <code class="language-plaintext highlighter-rouge">rank</code>, corresponding to that player’s WTA ranking at the time, and <code class="language-plaintext highlighter-rouge">points</code>, corresponding to the number of points that player scored.</p>

<p>The <code class="language-plaintext highlighter-rouge">delta.left</code> and <code class="language-plaintext highlighter-rouge">delta.right</code> correspond to the value for the <code class="language-plaintext highlighter-rouge">delta.field</code> for 2010 (left) and 2011 (right).</p>

<p>The <code class="language-plaintext highlighter-rouge">delta.delta.deltaValue</code> column shows the difference in value from <code class="language-plaintext highlighter-rouge">delta.left</code> and <code class="language-plaintext highlighter-rouge">delta.right</code>, so if the <code class="language-plaintext highlighter-rouge">delta.field</code> is <code class="language-plaintext highlighter-rouge">rank</code>, the id is <code class="language-plaintext highlighter-rouge">200079_Kim_Clijsters_02</code>, <code class="language-plaintext highlighter-rouge">delta.left</code> and <code class="language-plaintext highlighter-rouge">delta.right</code> are <code class="language-plaintext highlighter-rouge">17</code> and <code class="language-plaintext highlighter-rouge">1</code>, and <code class="language-plaintext highlighter-rouge">delta.delta.deltaValue</code> is <code class="language-plaintext highlighter-rouge">-16</code>, then that means that Kim Clijsters rank rose from <code class="language-plaintext highlighter-rouge">17</code> in <code class="language-plaintext highlighter-rouge">2010</code> to <code class="language-plaintext highlighter-rouge">1</code> in <code class="language-plaintext highlighter-rouge">2011</code> in the month of February.</p>

<p>At this point, we can do further analysis in BigQuery by sorting players by the greatest increase in ranking from 2010 and 2011 via:</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="o">*</span> <span class="k">FROM</span> <span class="nv">`[PROJECT].ratatool_wta_output.tennis-wta-bigdiffy_keys`</span> 
<span class="k">WHERE</span> <span class="n">diffType</span> <span class="o">=</span> <span class="s1">'DIFFERENT'</span>
<span class="k">AND</span> <span class="n">delta</span><span class="p">.</span><span class="n">field</span> <span class="o">=</span> <span class="s1">'rank'</span>
<span class="k">ORDER</span> <span class="k">BY</span> <span class="n">delta</span><span class="p">.</span><span class="n">delta</span><span class="p">.</span><span class="n">deltaValue</span> <span class="k">asc</span>
 <span class="k">LIMIT</span> <span class="mi">1000</span>
</code></pre></div></div>

<h2 id="tennis-wta-bigdiffy_global">tennis-wta-bigdiffy_global</h2>

<p><code class="language-plaintext highlighter-rouge">tennis-wta-bigdiffy_global</code> contains global stats such as <code class="language-plaintext highlighter-rouge">numTotal</code>, <code class="language-plaintext highlighter-rouge">numSame</code>, <code class="language-plaintext highlighter-rouge">numDiff</code>, <code class="language-plaintext highlighter-rouge">numMissingLhs</code>, and <code class="language-plaintext highlighter-rouge">numMissingRhs</code>.</p>

<h2 id="tennis-wta-bigdiffy_fields">tennis-wta-bigdiffy_fields</h2>

<p><code class="language-plaintext highlighter-rouge">tennis-wta-bigdiffy_fields</code> contains count, min, max, count, mean, variance, standard deviation, skewness, and kurtosis for the rank, points, and rankingDate fields across both datasets.</p>]]></content><author><name>Ben Konz</name></author><summary type="html"><![CDATA[Ratatool is a tooling suite for sampling, generating, and comparing data. It contains several tools worth checking out, but this tutorial be focused on using BigDiffy.]]></summary></entry><entry><title type="html">Building a Brainf*ck Compiler with Rust and LLVM</title><link href="http://benkonz.github.io//building-a-brainfuck-compiler-with-rust-and-llvm/" rel="alternate" type="text/html" title="Building a Brainf*ck Compiler with Rust and LLVM" /><published>2020-07-28T00:00:00+00:00</published><updated>2020-07-28T00:00:00+00:00</updated><id>http://benkonz.github.io//building-a-brainfuck-compiler-with-rust-and-llvm</id><content type="html" xml:base="http://benkonz.github.io//building-a-brainfuck-compiler-with-rust-and-llvm/"><![CDATA[<p><a href="https://llvm.org/">LLVM</a> is a collection of compiler toolchain technologies  used to compile dynamic and static programming languages. It’s heavly used in programming languages, such as <a href="https://clang.llvm.org/">Clang</a>, <a href="https://emscripten.org/">Emscripten</a>, and <a href="https://www.rust-lang.org/">Rust</a>!</p>

<p>This tutorial is going to go over how to create a simple compiler using LLVM for <a href="https://en.wikipedia.org/wiki/Brainfuck">Brainf*ck</a> in Rust. The completed code can be found here: <a href="https://github.com/benkonz/brainfrick-rust">brainfrick-rust</a></p>

<h1 id="brainfck-introduction">Brainf*ck Introduction</h1>

<p><a href="https://en.wikipedia.org/wiki/Brainfuck">Brainf-ck</a> is a very simple, turing complete, programming language that is made up of 8 commands. Each command is a single character, so parsing out an entire brainf*ck file is easy. Just read every character and match the character with a command. If the character isn’t a command, just skip it and move to the next character.</p>

<h2 id="commands">Commands</h2>

<table>
  <thead>
    <tr>
      <th>Character</th>
      <th>Meaning</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">&gt;</code></td>
      <td>increment data pointer</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">&lt;</code></td>
      <td>decrement data pointer</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">+</code></td>
      <td>increment the byte at the data pointer</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">-</code></td>
      <td>decrement the byte at the data pointer</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">.</code></td>
      <td>output the byte at the data pointer to <code class="language-plaintext highlighter-rouge">stdout</code></td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">,</code></td>
      <td>accept one byte of input from <code class="language-plaintext highlighter-rouge">stdin</code>, storing it’s value in the byte at the data pointer</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">[</code></td>
      <td>if the byte at the data pointer is zero, then move the program counter to instruction after the matching <code class="language-plaintext highlighter-rouge">]</code>, otherwise move to the next instruction</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">]</code></td>
      <td>if the byte at the data pointer is nonzero, then move the program counter to the instruction after the matching <code class="language-plaintext highlighter-rouge">[</code>, otherwise move to the next instruction</td>
    </tr>
  </tbody>
</table>

<h2 id="sample-program">Sample Program</h2>

<p>This simple program is going to add the current cell’s value to the next cell</p>

<div class="language-brainfuck highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cm">[-&gt;+&lt;]</span>
</code></pre></div></div>

<p>Think of <code class="language-plaintext highlighter-rouge">[</code> and <code class="language-plaintext highlighter-rouge">]</code> as <code class="language-plaintext highlighter-rouge">while (*data_ptr) {</code> and <code class="language-plaintext highlighter-rouge">}</code>, respectivly.
We decrement the current cell’s value with <code class="language-plaintext highlighter-rouge">-</code>, then increment the <code class="language-plaintext highlighter-rouge">data_ptr</code> with <code class="language-plaintext highlighter-rouge">&gt;</code>, then increment the new value at our data pointer with <code class="language-plaintext highlighter-rouge">+</code>, then decrement the <code class="language-plaintext highlighter-rouge">data_ptr</code> back to where it was at the start of the loop with <code class="language-plaintext highlighter-rouge">-</code>.</p>

<p>Since this is surrounded in a <code class="language-plaintext highlighter-rouge">[</code> <code class="language-plaintext highlighter-rouge">]</code>, we are going to do this until the value at the <code class="language-plaintext highlighter-rouge">data_ptr</code> is <code class="language-plaintext highlighter-rouge">0</code>, effectivly adding the value at the <code class="language-plaintext highlighter-rouge">data_ptr</code> to the next value in memory.</p>

<h1 id="project-setup">Project Setup</h1>

<p>This project uses <a href="https://releases.llvm.org/10.0.0/docs/ReleaseNotes.html">LLVM-10</a>, as well as <a href="https://crates.io/">Cargo</a>.</p>

<p>Start with:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cargo new --bin brainfrick-rust
</code></pre></div></div>

<p>then edit the <code class="language-plaintext highlighter-rouge">Cargo.toml</code> file and add this to the dependencies:</p>

<div class="language-toml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nn">inkwell</span> <span class="o">=</span> <span class="p">{</span> <span class="py">git</span> <span class="p">=</span> <span class="s">"https://github.com/TheDan64/inkwell"</span><span class="p">,</span> <span class="py">branch</span> <span class="p">=</span> <span class="s">"llvm10-0"</span> <span class="p">}</span>
<span class="py">clap</span> <span class="p">=</span> <span class="s">"2.33"</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">clap</code> is used to make parsing command line args easier</p>

<p>Verify that everything works by running:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cargo build
</code></pre></div></div>

<p>Unless you’ve already installed the LLVM-10 development files on your machine, you will probably get an error message complaining about being unable to find LLVM-10. If that’s the case, just follow the “Compiling LLVM” instructions <a href="https://crates.io/crates/llvm-sys">here</a>.</p>

<h1 id="your-first-executable">Your First Executable</h1>

<p>We’re going to start by making a simple executable that just returns <code class="language-plaintext highlighter-rouge">0</code>.</p>

<p>To start, we’ll parse out the command line args. The first argument will be our input file and the <code class="language-plaintext highlighter-rouge">-o OUTPUT</code> will be our output file.</p>

<div class="language-rust highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">#[macro_use]</span>
<span class="k">extern</span> <span class="k">crate</span> <span class="n">clap</span><span class="p">;</span>

<span class="k">use</span> <span class="nn">clap</span><span class="p">::{</span><span class="n">App</span><span class="p">,</span> <span class="n">Arg</span><span class="p">};</span>

<span class="k">fn</span> <span class="nf">main</span><span class="p">()</span> <span class="k">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="p">(),</span> <span class="nb">String</span><span class="o">&gt;</span> <span class="p">{</span>
     <span class="k">let</span> <span class="n">matches</span> <span class="o">=</span> <span class="nn">App</span><span class="p">::</span><span class="nf">new</span><span class="p">(</span><span class="nd">crate_name!</span><span class="p">())</span>
        <span class="nf">.version</span><span class="p">(</span><span class="nd">crate_version!</span><span class="p">())</span>
        <span class="nf">.author</span><span class="p">(</span><span class="nd">crate_authors!</span><span class="p">())</span>
        <span class="nf">.about</span><span class="p">(</span><span class="nd">crate_description!</span><span class="p">())</span>
        <span class="nf">.arg</span><span class="p">(</span>
            <span class="nn">Arg</span><span class="p">::</span><span class="nf">with_name</span><span class="p">(</span><span class="s">"INPUT"</span><span class="p">)</span>
                <span class="nf">.help</span><span class="p">(</span><span class="s">"source bf file to compile"</span><span class="p">)</span>
                <span class="nf">.required</span><span class="p">(</span><span class="k">true</span><span class="p">)</span>
                <span class="nf">.index</span><span class="p">(</span><span class="mi">1</span><span class="p">),</span>
        <span class="p">)</span>
        <span class="nf">.arg</span><span class="p">(</span>
            <span class="nn">Arg</span><span class="p">::</span><span class="nf">with_name</span><span class="p">(</span><span class="s">"output"</span><span class="p">)</span>
                <span class="nf">.short</span><span class="p">(</span><span class="s">"o"</span><span class="p">)</span>
                <span class="nf">.help</span><span class="p">(</span><span class="s">"output filename"</span><span class="p">)</span>
                <span class="nf">.takes_value</span><span class="p">(</span><span class="k">true</span><span class="p">)</span>
                <span class="nf">.required</span><span class="p">(</span><span class="k">true</span><span class="p">),</span>
        <span class="p">)</span>
        <span class="nf">.get_matches</span><span class="p">();</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Next, we’ll create our <code class="language-plaintext highlighter-rouge">context</code>, <code class="language-plaintext highlighter-rouge">module</code>, and <code class="language-plaintext highlighter-rouge">builder</code></p>

<div class="language-rust highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">use</span> <span class="nn">inkwell</span><span class="p">::</span><span class="nn">context</span><span class="p">::</span><span class="n">Context</span><span class="p">;</span>

<span class="k">let</span> <span class="n">context</span> <span class="o">=</span> <span class="nn">Context</span><span class="p">::</span><span class="nf">create</span><span class="p">();</span>
<span class="k">let</span> <span class="n">module</span> <span class="o">=</span> <span class="n">context</span><span class="nf">.create_module</span><span class="p">(</span><span class="s">"brainfrick_rust"</span><span class="p">);</span>
<span class="k">let</span> <span class="n">builder</span> <span class="o">=</span> <span class="n">context</span><span class="nf">.create_builder</span><span class="p">();</span>
</code></pre></div></div>

<p>After that, we’ll create a main function type, which takes no arguments and returns an <code class="language-plaintext highlighter-rouge">i32</code> and add it to our module</p>

<div class="language-rust highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">use</span> <span class="nn">inkwell</span><span class="p">::</span><span class="nn">module</span><span class="p">::</span><span class="n">Linkage</span><span class="p">;</span>

<span class="k">let</span> <span class="n">i32_type</span> <span class="o">=</span> <span class="n">context</span><span class="nf">.i32_type</span><span class="p">();</span>
<span class="k">let</span> <span class="n">main_fn_type</span> <span class="o">=</span> <span class="n">i32_type</span><span class="nf">.fn_type</span><span class="p">(</span><span class="o">&amp;</span><span class="p">[],</span> <span class="k">false</span><span class="p">);</span>
<span class="k">let</span> <span class="n">main_fn</span> <span class="o">=</span> <span class="n">module</span>
                <span class="nf">.add_function</span><span class="p">(</span><span class="s">"main"</span><span class="p">,</span> <span class="n">main_fn_type</span><span class="p">,</span> <span class="nf">Some</span><span class="p">(</span><span class="nn">Linkage</span><span class="p">::</span><span class="n">External</span><span class="p">));</span>
</code></pre></div></div>

<p>Next, we’ll set the builder’s instruction pointer to the main function and use it to build a return instruction</p>

<div class="language-rust highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">let</span> <span class="n">basic_block</span> <span class="o">=</span> <span class="n">context</span><span class="nf">.append_basic_block</span><span class="p">(</span><span class="n">main_fn</span><span class="p">,</span> <span class="s">"entry"</span><span class="p">);</span>
<span class="n">builder</span><span class="nf">.position_at_end</span><span class="p">(</span><span class="n">basic_block</span><span class="p">);</span>

<span class="c1">// our compiler will go here</span>

<span class="k">let</span> <span class="n">i32_zero</span> <span class="o">=</span> <span class="n">i32_type</span><span class="nf">.const_int</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="k">false</span><span class="p">);</span>
<span class="n">builder</span><span class="nf">.build_return</span><span class="p">(</span><span class="nf">Some</span><span class="p">(</span><span class="o">&amp;</span><span class="n">i32_zero</span><span class="p">));</span>
</code></pre></div></div>

<p>Finally, we’ll have to setup LLVM to convert the builder to machine code and write that result to a file</p>

<div class="language-rust highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">use</span> <span class="nn">inkwell</span><span class="p">::</span><span class="nn">targets</span><span class="p">::{</span>
    <span class="n">CodeModel</span><span class="p">,</span> <span class="n">FileType</span><span class="p">,</span> <span class="n">InitializationConfig</span><span class="p">,</span> <span class="n">RelocMode</span><span class="p">,</span> <span class="n">Target</span><span class="p">,</span> <span class="n">TargetMachine</span><span class="p">,</span>
<span class="p">};</span>
<span class="k">use</span> <span class="nn">inkwell</span><span class="p">::</span><span class="n">OptimizationLevel</span><span class="p">;</span>

<span class="nn">Target</span><span class="p">::</span><span class="nf">initialize_all</span><span class="p">(</span><span class="o">&amp;</span><span class="nn">InitializationConfig</span><span class="p">::</span><span class="nf">default</span><span class="p">());</span>
<span class="c1">// use the host machine as the compilation target</span>
<span class="k">let</span> <span class="n">target_triple</span> <span class="o">=</span> <span class="nn">TargetMachine</span><span class="p">::</span><span class="nf">get_default_triple</span><span class="p">();</span>
<span class="k">let</span> <span class="n">cpu</span> <span class="o">=</span> <span class="nn">TargetMachine</span><span class="p">::</span><span class="nf">get_host_cpu_name</span><span class="p">()</span><span class="nf">.to_string</span><span class="p">();</span>
<span class="k">let</span> <span class="n">features</span> <span class="o">=</span> <span class="nn">TargetMachine</span><span class="p">::</span><span class="nf">get_host_cpu_features</span><span class="p">()</span><span class="nf">.to_string</span><span class="p">();</span>

<span class="c1">// make a target from the triple</span>
<span class="k">let</span> <span class="n">target</span> <span class="o">=</span> <span class="nn">Target</span><span class="p">::</span><span class="nf">from_triple</span><span class="p">(</span><span class="o">&amp;</span><span class="n">target_triple</span><span class="p">)</span>
<span class="nf">.map_err</span><span class="p">(|</span><span class="n">e</span><span class="p">|</span> <span class="nd">format!</span><span class="p">(</span><span class="s">"{:?}"</span><span class="p">,</span> <span class="n">e</span><span class="p">))</span><span class="o">?</span><span class="p">;</span>

<span class="c1">// make a machine from the target</span>
<span class="k">let</span> <span class="n">target_machine</span> <span class="o">=</span> <span class="n">target</span>
    <span class="nf">.create_target_machine</span><span class="p">(</span>
        <span class="o">&amp;</span><span class="n">target_triple</span><span class="p">,</span>
        <span class="o">&amp;</span><span class="n">cpu</span><span class="p">,</span>
        <span class="o">&amp;</span><span class="n">features</span><span class="p">,</span>
        <span class="nn">OptimizationLevel</span><span class="p">::</span><span class="nb">Default</span><span class="p">,</span>
        <span class="nn">RelocMode</span><span class="p">::</span><span class="nb">Default</span><span class="p">,</span>
        <span class="nn">CodeModel</span><span class="p">::</span><span class="nb">Default</span><span class="p">,</span>
    <span class="p">)</span>
    <span class="nf">.ok_or_else</span><span class="p">(||</span> <span class="s">"Unable to create target machine!"</span><span class="nf">.to_string</span><span class="p">())</span><span class="o">?</span><span class="p">;</span>

<span class="c1">// use the machine to convert our module to machine code and write the result to a file</span>
<span class="k">let</span> <span class="n">output_filename</span> <span class="o">=</span> <span class="n">matches</span><span class="nf">.value_of</span><span class="p">(</span><span class="s">"output"</span><span class="p">)</span><span class="nf">.unwrap</span><span class="p">();</span>
<span class="n">target_machine</span>
    <span class="nf">.write_to_file</span><span class="p">(</span><span class="o">&amp;</span><span class="n">module</span><span class="p">,</span> <span class="nn">FileType</span><span class="p">::</span><span class="n">Object</span><span class="p">,</span> <span class="n">output_filename</span><span class="nf">.as_ref</span><span class="p">())</span>
    <span class="nf">.map_err</span><span class="p">(|</span><span class="n">e</span><span class="p">|</span> <span class="nd">format!</span><span class="p">(</span><span class="s">"{:?}"</span><span class="p">,</span> <span class="n">e</span><span class="p">))</span><span class="o">?</span><span class="p">;</span>
</code></pre></div></div>

<p>The <code class="language-plaintext highlighter-rouge">FileType::Object</code> can be changed to <code class="language-plaintext highlighter-rouge">FileType::Assembly</code> to write human-readable machine instructions, which is very useful for debugging your compiler</p>

<h2 id="running-the-executable">Running the executable</h2>

<p>By setting the file type to <code class="language-plaintext highlighter-rouge">FileType::Object</code>, LLVM will produce an <a href="https://en.wikipedia.org/wiki/Object_file">Object File</a>. That file cannot be run by itself, and needs to be linked togeather by a linker. Typically, this is ued by <a href="https://linux.die.net/man/1/ld">ld</a>, but the right arguments to <code class="language-plaintext highlighter-rouge">ld</code> varies based on Linux disro. The easier way to link your object file is with <a href="https://gcc.gnu.org/">gcc</a>, which, internally, calls <code class="language-plaintext highlighter-rouge">ld</code> with the right args.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cargo run INPUT_FILE -o OUTPUT_FILE
gcc OUTPUT_FILE -o OUTPUT_FILE.exe
./OUTPUT_FILE.exe
echo $?
0
</code></pre></div></div>

<p>The <code class="language-plaintext highlighter-rouge">echo $?</code> should print out the status code of the last program. You can modify the <code class="language-plaintext highlighter-rouge">let i32_zero = i32_type.const_int(0, false);</code> line to return any integer.</p>

<h1 id="standard-library-functions">Standard Library Functions</h1>

<p>Before we start compiling our source program, we need to initialize the memory that our brainf*ck programs will use. This means calling the <a href="https://en.cppreference.com/w/c/memory/calloc">calloc</a> libc call.</p>

<p>After we’ve initialized our <code class="language-plaintext highlighter-rouge">builder</code>, we’re going to add this code</p>

<div class="language-rust highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">use</span> <span class="nn">inkwell</span><span class="p">::</span><span class="n">AddressSpace</span><span class="p">;</span>

<span class="k">let</span> <span class="n">i64_type</span> <span class="o">=</span> <span class="n">context</span><span class="nf">.i64_type</span><span class="p">();</span>
<span class="k">let</span> <span class="n">i8_type</span> <span class="o">=</span> <span class="n">context</span><span class="nf">.i8_type</span><span class="p">();</span>
<span class="k">let</span> <span class="n">i8_ptr_type</span> <span class="o">=</span> <span class="n">i8_type</span><span class="nf">.ptr_type</span><span class="p">(</span><span class="nn">AddressSpace</span><span class="p">::</span><span class="n">Generic</span><span class="p">);</span>

<span class="k">let</span> <span class="n">calloc_fn_type</span> <span class="o">=</span> <span class="n">i8_ptr_type</span><span class="nf">.fn_type</span><span class="p">(</span><span class="o">&amp;</span><span class="p">[</span><span class="n">i64_type</span><span class="nf">.into</span><span class="p">(),</span> <span class="n">i64_type</span><span class="nf">.into</span><span class="p">()],</span> <span class="k">false</span><span class="p">);</span>
<span class="k">let</span> <span class="n">calloc_fn</span> <span class="o">=</span> <span class="n">module</span>
    <span class="nf">.add_function</span><span class="p">(</span><span class="s">"calloc"</span><span class="p">,</span> <span class="n">calloc_fn_type</span><span class="p">,</span> <span class="nf">Some</span><span class="p">(</span><span class="nn">Linkage</span><span class="p">::</span><span class="n">External</span><span class="p">));</span>

</code></pre></div></div>

<p>We’re also going to want to add the <code class="language-plaintext highlighter-rouge">getchar</code> and <code class="language-plaintext highlighter-rouge">putchar</code> functions, which are going to get used by the <code class="language-plaintext highlighter-rouge">.</code> and  <code class="language-plaintext highlighter-rouge">,</code> commands.</p>

<div class="language-rust highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">let</span> <span class="n">getchar_fn_type</span> <span class="o">=</span> <span class="n">i32_type</span><span class="nf">.fn_type</span><span class="p">(</span><span class="o">&amp;</span><span class="p">[],</span> <span class="k">false</span><span class="p">);</span>
<span class="k">let</span> <span class="n">getchar_fn</span> <span class="o">=</span><span class="n">module</span>
    <span class="nf">.add_function</span><span class="p">(</span><span class="s">"getchar"</span><span class="p">,</span> <span class="n">getchar_fn_type</span><span class="p">,</span> <span class="nf">Some</span><span class="p">(</span><span class="nn">Linkage</span><span class="p">::</span><span class="n">External</span><span class="p">));</span>

<span class="k">let</span> <span class="n">putchar_fn_type</span> <span class="o">=</span> <span class="n">i32_type</span><span class="nf">.fn_type</span><span class="p">(</span><span class="o">&amp;</span><span class="p">[</span><span class="n">i32_type</span><span class="nf">.into</span><span class="p">()],</span> <span class="k">false</span><span class="p">);</span>
<span class="k">let</span> <span class="n">putchar_fn</span> <span class="o">=</span><span class="n">module</span>
    <span class="nf">.add_function</span><span class="p">(</span><span class="s">"putchar"</span><span class="p">,</span> <span class="n">putchar_fn_type</span><span class="p">,</span> <span class="nf">Some</span><span class="p">(</span><span class="nn">Linkage</span><span class="p">::</span><span class="n">External</span><span class="p">));</span>
</code></pre></div></div>

<p>Next, we’re going to call <code class="language-plaintext highlighter-rouge">calloc</code> and initialize our <code class="language-plaintext highlighter-rouge">data</code> and <code class="language-plaintext highlighter-rouge">ptr</code> variables, which will both point to the result of our <code class="language-plaintext highlighter-rouge">calloc</code> call. After the <code class="language-plaintext highlighter-rouge">builder.position_at_end(basic_block);</code> line, we’re going to add this code:</p>

<div class="language-rust highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">let</span> <span class="n">i8_type</span> <span class="o">=</span> <span class="n">context</span><span class="nf">.i8_type</span><span class="p">();</span>
<span class="k">let</span> <span class="n">i8_ptr_type</span> <span class="o">=</span> <span class="n">i8_type</span><span class="nf">.ptr_type</span><span class="p">(</span><span class="nn">AddressSpace</span><span class="p">::</span><span class="n">Generic</span><span class="p">);</span>

<span class="k">let</span> <span class="n">data</span> <span class="o">=</span> <span class="n">builder</span><span class="nf">.build_alloca</span><span class="p">(</span><span class="n">i8_ptr_type</span><span class="p">,</span> <span class="s">"data"</span><span class="p">);</span>
<span class="k">let</span> <span class="n">ptr</span> <span class="o">=</span> <span class="n">builder</span><span class="nf">.build_alloca</span><span class="p">(</span><span class="n">i8_ptr_type</span><span class="p">,</span> <span class="s">"ptr"</span><span class="p">);</span>

<span class="k">let</span> <span class="n">i64_type</span> <span class="o">=</span> <span class="n">context</span><span class="nf">.i64_type</span><span class="p">();</span>
<span class="k">let</span> <span class="n">i64_memory_size</span> <span class="o">=</span> <span class="n">i64_type</span><span class="nf">.const_int</span><span class="p">(</span><span class="mi">30_000</span><span class="p">,</span> <span class="k">false</span><span class="p">);</span>
<span class="k">let</span> <span class="n">i64_element_size</span> <span class="o">=</span> <span class="n">i64_type</span><span class="nf">.const_int</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="k">false</span><span class="p">);</span>

<span class="k">let</span> <span class="n">data_ptr</span> <span class="o">=</span> <span class="n">builder</span><span class="nf">.build_call</span><span class="p">(</span>
    <span class="n">calloc_fn</span><span class="p">,</span>
    <span class="o">&amp;</span><span class="p">[</span><span class="n">i64_memory_size</span><span class="nf">.into</span><span class="p">(),</span> <span class="n">i64_element_size</span><span class="nf">.into</span><span class="p">()],</span>
    <span class="s">"calloc_call"</span><span class="p">,</span>
<span class="p">);</span>
<span class="k">let</span> <span class="n">data_ptr_result</span><span class="p">:</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="n">_</span><span class="p">,</span> <span class="n">_</span><span class="o">&gt;</span> <span class="o">=</span> <span class="n">data_ptr</span><span class="nf">.try_as_basic_value</span><span class="p">()</span><span class="nf">.flip</span><span class="p">()</span><span class="nf">.into</span><span class="p">();</span>
<span class="k">let</span> <span class="n">data_ptr_basic_val</span> <span class="o">=</span>
    <span class="n">data_ptr_result</span><span class="nf">.map_err</span><span class="p">(|</span><span class="n">_</span><span class="p">|</span> <span class="s">"calloc returned void for some reason!"</span><span class="p">)</span><span class="o">?</span><span class="p">;</span>

<span class="n">builder</span><span class="nf">.build_store</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="n">data_ptr_basic_val</span><span class="p">);</span>
<span class="n">builder</span><span class="nf">.build_store</span><span class="p">(</span><span class="n">ptr</span><span class="p">,</span> <span class="n">data_ptr_basic_val</span><span class="p">);</span>
</code></pre></div></div>

<p>Finally, we’re going to call <a href="https://en.cppreference.com/w/c/memory/free">free</a> on our <code class="language-plaintext highlighter-rouge">data</code> pointer. This isn’t really necessary, since the program ends right after, but it is good practice. LLVM has a convience function called <code class="language-plaintext highlighter-rouge">build_free</code>, so we don’t need to add the free function to our module.</p>

<div class="language-rust highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="n">builder</span>
    <span class="nf">.build_free</span><span class="p">(</span><span class="n">builder</span><span class="nf">.build_load</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="s">"load"</span><span class="p">)</span><span class="nf">.into_pointer_value</span><span class="p">());</span>

</code></pre></div></div>

<p>Let’s verify that everything is working correctly. Recompile our code and make another executable with <code class="language-plaintext highlighter-rouge">cargo run</code>. Re-link it with <code class="language-plaintext highlighter-rouge">gcc</code>, then run <code class="language-plaintext highlighter-rouge">ltrace ./OUTPUT_FILE.exe</code>. You should see something like this:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>calloc(30000, 1)        = 0x55a9ec9482a0
free(0x55a9ec9482a0)    = &lt;void&gt;
+++ exited (status 0) +++
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">ltrace</code> traces all of the library calls of an executable, so we should see a call to <code class="language-plaintext highlighter-rouge">calloc</code> and a call to <code class="language-plaintext highlighter-rouge">free</code>.</p>

<p>We’ll need to setup some boilerplate code to read in our input file and iterate through all of the characters. After <code class="language-plaintext highlighter-rouge">builder.build_store(ptr, data_ptr_basic_val);</code>, add</p>

<div class="language-rust highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">use</span> <span class="nn">std</span><span class="p">::</span><span class="nn">fs</span><span class="p">::</span><span class="n">File</span><span class="p">;</span>
<span class="k">use</span> <span class="nn">std</span><span class="p">::</span><span class="nn">io</span><span class="p">::</span><span class="nn">prelude</span><span class="p">::</span><span class="o">*</span><span class="p">;</span>
<span class="k">use</span> <span class="nn">std</span><span class="p">::</span><span class="nn">collections</span><span class="p">::</span><span class="n">VecDeque</span><span class="p">;</span>
<span class="k">use</span> <span class="nn">inkwell</span><span class="p">::</span><span class="nn">basic_block</span><span class="p">::</span><span class="n">BasicBlock</span><span class="p">;</span>

<span class="k">let</span> <span class="n">source_filename</span> <span class="o">=</span> <span class="n">matches</span><span class="nf">.value_of</span><span class="p">(</span><span class="s">"INPUT"</span><span class="p">)</span><span class="nf">.unwrap</span><span class="p">();</span>
<span class="k">let</span> <span class="k">mut</span> <span class="n">f</span> <span class="o">=</span> <span class="nn">File</span><span class="p">::</span><span class="nf">open</span><span class="p">(</span><span class="n">source_filename</span><span class="p">)</span><span class="nf">.map_err</span><span class="p">(|</span><span class="n">e</span><span class="p">|</span> <span class="nd">format!</span><span class="p">(</span><span class="s">"{:?}"</span><span class="p">,</span> <span class="n">e</span><span class="p">))</span><span class="o">?</span><span class="p">;</span>
<span class="k">let</span> <span class="k">mut</span> <span class="n">program</span> <span class="o">=</span> <span class="nn">String</span><span class="p">::</span><span class="nf">new</span><span class="p">();</span>
<span class="n">f</span><span class="nf">.read_to_string</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span> <span class="n">program</span><span class="p">)</span>
    <span class="nf">.map_err</span><span class="p">(|</span><span class="n">e</span><span class="p">|</span> <span class="nd">format!</span><span class="p">(</span><span class="s">"{:?}"</span><span class="p">,</span> <span class="n">e</span><span class="p">))</span><span class="o">?</span><span class="p">;</span>

<span class="k">let</span> <span class="k">mut</span> <span class="n">while_blocks</span> <span class="o">=</span> <span class="nn">VecDeque</span><span class="p">::</span><span class="nf">new</span><span class="p">();</span>

<span class="k">for</span> <span class="n">command</span> <span class="k">in</span> <span class="n">program</span><span class="nf">.chars</span><span class="p">()</span> <span class="p">{</span>
    <span class="k">match</span> <span class="n">command</span> <span class="p">{</span>
        <span class="sc">'&gt;'</span> <span class="k">=&gt;</span> <span class="nf">build_add_ptr</span><span class="p">(</span><span class="o">&amp;</span><span class="n">context</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">builder</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">ptr</span><span class="p">),</span>
        <span class="sc">'&lt;'</span> <span class="k">=&gt;</span> <span class="nf">build_add_ptr</span><span class="p">(</span><span class="o">&amp;</span><span class="n">context</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">builder</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">ptr</span><span class="p">),</span>
        <span class="sc">'+'</span> <span class="k">=&gt;</span> <span class="nf">build_add</span><span class="p">(</span><span class="o">&amp;</span><span class="n">context</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">builder</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">ptr</span><span class="p">),</span>
        <span class="sc">'-'</span> <span class="k">=&gt;</span> <span class="nf">build_add</span><span class="p">(</span><span class="o">&amp;</span><span class="n">context</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">builder</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">ptr</span><span class="p">),</span>
        <span class="sc">'.'</span> <span class="k">=&gt;</span> <span class="nf">build_put</span><span class="p">(</span><span class="o">&amp;</span><span class="n">context</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">builder</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">putchar_fn</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">ptr</span><span class="p">),</span>
        <span class="sc">','</span> <span class="k">=&gt;</span> <span class="nf">build_get</span><span class="p">(</span><span class="o">&amp;</span><span class="n">context</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">builder</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">getchar_fn</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">ptr</span><span class="p">)</span><span class="o">?</span><span class="p">,</span>
        <span class="sc">'['</span> <span class="k">=&gt;</span> <span class="nf">build_while_start</span><span class="p">(</span><span class="o">&amp;</span><span class="n">context</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">builder</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">main_fn</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">ptr</span><span class="p">,</span> <span class="o">&amp;</span><span class="k">mut</span> <span class="n">while_blocks</span><span class="p">),</span>
        <span class="sc">']'</span> <span class="k">=&gt;</span> <span class="nf">build_while_end</span><span class="p">(</span><span class="o">&amp;</span><span class="n">context</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">builder</span><span class="p">,</span> <span class="o">&amp;</span><span class="k">mut</span> <span class="n">while_blocks</span><span class="p">)</span><span class="o">?</span><span class="p">,</span>
        <span class="n">_</span> <span class="k">=&gt;</span> <span class="p">(),</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>we will fill out these functions in the next sections</p>

<h1 id="compiling--and-">Compiling ‘&gt;’ and ‘&lt;’</h1>

<p>The <code class="language-plaintext highlighter-rouge">&gt;</code> and <code class="language-plaintext highlighter-rouge">&lt;</code> operations are similar enough that we can make a function that moves the <code class="language-plaintext highlighter-rouge">ptr</code> by an <code class="language-plaintext highlighter-rouge">amount</code> parameter.</p>

<p>To move the pointer around, we’ll use the <code class="language-plaintext highlighter-rouge">build_in_bounds_gep</code>, which takes a pointer and a list of ordered indexes. The function is marked as <code class="language-plaintext highlighter-rouge">unsafe</code> because it is very likely to SEGFAULT if we index outside the bounds of the array. This code doesn’t do any size checks, so it is likely that indexing outside the <code class="language-plaintext highlighter-rouge">30_000</code> bytes of memory from our <code class="language-plaintext highlighter-rouge">calloc</code> call will SEGFAULT.</p>

<div class="language-rust highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">use</span> <span class="nn">inkwell</span><span class="p">::</span><span class="nn">builder</span><span class="p">::</span><span class="n">Builder</span><span class="p">;</span>
<span class="k">use</span> <span class="nn">inkwell</span><span class="p">::</span><span class="nn">values</span><span class="p">::</span><span class="n">PointerValue</span><span class="p">;</span>

<span class="k">fn</span> <span class="nf">build_add_ptr</span><span class="p">(</span>
        <span class="n">context</span><span class="p">:</span> <span class="o">&amp;</span><span class="n">Context</span><span class="p">,</span> 
        <span class="n">builder</span><span class="p">:</span> <span class="o">&amp;</span><span class="n">Builder</span><span class="p">,</span> 
        <span class="n">amount</span><span class="p">:</span> <span class="nb">i32</span><span class="p">,</span> 
        <span class="n">ptr</span><span class="p">:</span> <span class="o">&amp;</span><span class="n">PointerValue</span>
    <span class="p">)</span> <span class="p">{</span>
    <span class="k">let</span> <span class="n">i32_type</span> <span class="o">=</span> <span class="n">context</span><span class="nf">.i32_type</span><span class="p">();</span>
    <span class="k">let</span> <span class="n">i32_amount</span> <span class="o">=</span> <span class="n">i32_type</span><span class="nf">.const_int</span><span class="p">(</span><span class="n">amount</span> <span class="k">as</span> <span class="nb">u64</span><span class="p">,</span> <span class="k">false</span><span class="p">);</span>
    <span class="k">let</span> <span class="n">ptr_load</span> <span class="o">=</span> <span class="n">builder</span>
        <span class="nf">.build_load</span><span class="p">(</span><span class="o">*</span><span class="n">ptr</span><span class="p">,</span> <span class="s">"load ptr"</span><span class="p">)</span>
        <span class="nf">.into_pointer_value</span><span class="p">();</span>
    <span class="c1">// unsafe because we are calling an unsafe function, since we could index out of bounds of the calloc</span>
    <span class="k">let</span> <span class="n">result</span> <span class="o">=</span> <span class="k">unsafe</span> <span class="p">{</span>
        <span class="n">builder</span>
            <span class="nf">.build_in_bounds_gep</span><span class="p">(</span><span class="n">ptr_load</span><span class="p">,</span> <span class="o">&amp;</span><span class="p">[</span><span class="n">i32_amount</span><span class="p">],</span> <span class="s">"add to pointer"</span><span class="p">)</span>
    <span class="p">};</span>
    <span class="n">builder</span><span class="nf">.build_store</span><span class="p">(</span><span class="o">*</span><span class="n">ptr</span><span class="p">,</span> <span class="n">result</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<h1 id="compiling--and--">Compiling ‘+’ and ‘-‘</h1>

<p>The <code class="language-plaintext highlighter-rouge">+</code> and <code class="language-plaintext highlighter-rouge">-</code> operations are similar enough that we can make a function that adds the value that <code class="language-plaintext highlighter-rouge">ptr</code> is pointing to by an <code class="language-plaintext highlighter-rouge">amount</code> parameter.</p>

<p>First, we’ll load the pointer variable, then we’ll load the value at that that pointer points to. Then, we use <code class="language-plaintext highlighter-rouge">build_int_add</code> to add that value to <code class="language-plaintext highlighter-rouge">amount</code>.</p>

<div class="language-rust highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">fn</span> <span class="nf">build_add</span><span class="p">(</span>
        <span class="n">context</span><span class="p">:</span> <span class="o">&amp;</span><span class="n">Context</span><span class="p">,</span> 
        <span class="n">builder</span><span class="p">:</span> <span class="o">&amp;</span><span class="n">Builder</span><span class="p">,</span> 
        <span class="n">amount</span><span class="p">:</span> <span class="nb">i32</span><span class="p">,</span> 
        <span class="n">ptr</span><span class="p">:</span> <span class="o">&amp;</span><span class="n">PointerValue</span>
    <span class="p">)</span> <span class="p">{</span>
    <span class="k">let</span> <span class="n">i8_type</span> <span class="o">=</span> <span class="n">context</span><span class="nf">.i8_type</span><span class="p">();</span>
    <span class="k">let</span> <span class="n">i8_amount</span> <span class="o">=</span> <span class="n">i8_type</span><span class="nf">.const_int</span><span class="p">(</span><span class="n">amount</span> <span class="k">as</span> <span class="nb">u64</span><span class="p">,</span> <span class="k">false</span><span class="p">);</span>
    <span class="k">let</span> <span class="n">ptr_load</span> <span class="o">=</span> <span class="n">builder</span>
        <span class="nf">.build_load</span><span class="p">(</span><span class="o">*</span><span class="n">ptr</span><span class="p">,</span> <span class="s">"load ptr"</span><span class="p">)</span>
        <span class="nf">.into_pointer_value</span><span class="p">();</span>
    <span class="k">let</span> <span class="n">ptr_val</span> <span class="o">=</span> <span class="n">builder</span><span class="nf">.build_load</span><span class="p">(</span><span class="n">ptr_load</span><span class="p">,</span> <span class="s">"load ptr value"</span><span class="p">);</span>
    <span class="k">let</span> <span class="n">result</span> <span class="o">=</span> <span class="n">builder</span>
            <span class="nf">.build_int_add</span><span class="p">(</span><span class="n">ptr_val</span><span class="nf">.into_int_value</span><span class="p">(),</span> <span class="n">i8_amount</span><span class="p">,</span> <span class="s">"add to data ptr"</span><span class="p">);</span>
    <span class="n">builder</span><span class="nf">.build_store</span><span class="p">(</span><span class="n">ptr_load</span><span class="p">,</span> <span class="n">result</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<h1 id="compiling--and--1">Compiling ‘.’ and ‘,’</h1>

<p>Here, we’ll make use of the <code class="language-plaintext highlighter-rouge">getchar_fn</code> and <code class="language-plaintext highlighter-rouge">putchar_fn</code> functions.</p>

<h2 id="compiling-">Compiling ‘.’</h2>

<div class="language-rust highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">use</span> <span class="nn">inkwell</span><span class="p">::</span><span class="nn">values</span><span class="p">::</span><span class="n">FunctionValue</span><span class="p">;</span>

<span class="k">fn</span> <span class="nf">build_get</span><span class="p">(</span>
        <span class="n">context</span><span class="p">:</span> <span class="o">&amp;</span><span class="n">Context</span><span class="p">,</span> 
        <span class="n">builder</span><span class="p">:</span> <span class="o">&amp;</span><span class="n">Builder</span><span class="p">,</span> 
        <span class="n">getchar_fn</span><span class="p">:</span> <span class="o">&amp;</span><span class="n">FunctionValue</span><span class="p">,</span> 
        <span class="n">ptr</span><span class="p">:</span> <span class="o">&amp;</span><span class="n">PointerValue</span>
    <span class="p">)</span> <span class="k">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="p">(),</span> <span class="nb">String</span><span class="o">&gt;</span> <span class="p">{</span>
    <span class="c1">// call getchar</span>
    <span class="k">let</span> <span class="n">getchar_call</span> <span class="o">=</span> <span class="n">builder</span>
        <span class="nf">.build_call</span><span class="p">(</span><span class="o">*</span><span class="n">getchar_fn</span><span class="p">,</span> <span class="o">&amp;</span><span class="p">[],</span> <span class="s">"getchar call"</span><span class="p">);</span>

    <span class="c1">// get the result of getchar and store it in our pointer's value</span>
    <span class="k">let</span> <span class="n">getchar_result</span><span class="p">:</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="n">_</span><span class="p">,</span> <span class="n">_</span><span class="o">&gt;</span> <span class="o">=</span> <span class="n">getchar_call</span><span class="nf">.try_as_basic_value</span><span class="p">()</span><span class="nf">.flip</span><span class="p">()</span><span class="nf">.into</span><span class="p">();</span>
    <span class="k">let</span> <span class="n">getchar_basicvalue</span> <span class="o">=</span>
        <span class="n">getchar_result</span><span class="nf">.map_err</span><span class="p">(|</span><span class="n">_</span><span class="p">|</span> <span class="s">"getchar returned void for some reason!"</span><span class="p">)</span><span class="o">?</span><span class="p">;</span>
    <span class="k">let</span> <span class="n">i8_type</span> <span class="o">=</span> <span class="n">context</span><span class="nf">.i8_type</span><span class="p">();</span>
    <span class="c1">// truncate since we are converting i8's to i32's</span>
    <span class="k">let</span> <span class="n">truncated</span> <span class="o">=</span> <span class="n">builder</span><span class="nf">.build_int_truncate</span><span class="p">(</span>
        <span class="n">getchar_basicvalue</span><span class="nf">.into_int_value</span><span class="p">(),</span>
        <span class="n">i8_type</span><span class="p">,</span>
        <span class="s">"getchar truncate result"</span><span class="p">,</span>
    <span class="p">);</span>
    <span class="k">let</span> <span class="n">ptr_value</span> <span class="o">=</span> <span class="n">builder</span>
        <span class="nf">.build_load</span><span class="p">(</span><span class="o">*</span><span class="n">ptr</span><span class="p">,</span> <span class="s">"load ptr value"</span><span class="p">)</span>
        <span class="nf">.into_pointer_value</span><span class="p">();</span>
    <span class="n">builder</span><span class="nf">.build_store</span><span class="p">(</span><span class="n">ptr_value</span><span class="p">,</span> <span class="n">truncated</span><span class="p">);</span>

    <span class="nf">Ok</span><span class="p">(())</span>
<span class="p">}</span>
</code></pre></div></div>

<h2 id="compiling--1">Compiling ‘,’</h2>

<div class="language-rust highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">fn</span> <span class="nf">build_put</span><span class="p">(</span>
        <span class="n">context</span><span class="p">:</span> <span class="o">&amp;</span><span class="n">Context</span><span class="p">,</span> 
        <span class="n">builder</span><span class="p">:</span> <span class="o">&amp;</span><span class="n">Builder</span><span class="p">,</span> 
        <span class="n">putchar_fn</span><span class="p">:</span> <span class="o">&amp;</span><span class="n">FunctionValue</span><span class="p">,</span> 
        <span class="n">ptr</span><span class="p">:</span> <span class="o">&amp;</span><span class="n">PointerValue</span>
    <span class="p">)</span> <span class="p">{</span>
    <span class="c1">// call putchar</span>
    <span class="k">let</span> <span class="n">char_to_put</span> <span class="o">=</span> <span class="n">builder</span><span class="nf">.build_load</span><span class="p">(</span>
    <span class="n">builder</span>
        <span class="nf">.build_load</span><span class="p">(</span><span class="o">*</span><span class="n">ptr</span><span class="p">,</span> <span class="s">"load ptr value"</span><span class="p">)</span>
        <span class="nf">.into_pointer_value</span><span class="p">(),</span>
        <span class="s">"load ptr ptr value"</span><span class="p">,</span>
    <span class="p">);</span>
    <span class="c1">// sign-extend, since we are conveting from i8's to i32's</span>
    <span class="k">let</span> <span class="n">s_ext</span> <span class="o">=</span> <span class="n">builder</span><span class="nf">.build_int_s_extend</span><span class="p">(</span>
        <span class="n">char_to_put</span><span class="nf">.into_int_value</span><span class="p">(),</span>
        <span class="n">context</span><span class="nf">.i32_type</span><span class="p">(),</span>
        <span class="s">"putchar sign extend"</span><span class="p">,</span>
    <span class="p">);</span>
    <span class="n">builder</span>
        <span class="nf">.build_call</span><span class="p">(</span><span class="o">*</span><span class="n">putchar_fn</span><span class="p">,</span> <span class="o">&amp;</span><span class="p">[</span><span class="n">s_ext</span><span class="nf">.into</span><span class="p">()],</span> <span class="s">"putchar call"</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<h1 id="compiling--and--2">Compiling ‘[’ and ‘]’</h1>

<p>For our <code class="language-plaintext highlighter-rouge">[</code> and <code class="language-plaintext highlighter-rouge">]</code>, we’re going to add this struct to <code class="language-plaintext highlighter-rouge">main.rs</code>:</p>

<div class="language-rust highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">struct</span> <span class="n">WhileBlock</span><span class="o">&lt;</span><span class="nv">'ctx</span><span class="o">&gt;</span> <span class="p">{</span>
    <span class="n">while_start</span><span class="p">:</span> <span class="n">BasicBlock</span><span class="o">&lt;</span><span class="nv">'ctx</span><span class="o">&gt;</span><span class="p">,</span>
    <span class="n">while_body</span><span class="p">:</span> <span class="n">BasicBlock</span><span class="o">&lt;</span><span class="nv">'ctx</span><span class="o">&gt;</span><span class="p">,</span>
    <span class="n">while_end</span><span class="p">:</span> <span class="n">BasicBlock</span><span class="o">&lt;</span><span class="nv">'ctx</span><span class="o">&gt;</span><span class="p">,</span>
<span class="p">}</span>
</code></pre></div></div>

<h2 id="compiling--2">Compiling ‘[’</h2>

<p>We’re going to use a <code class="language-plaintext highlighter-rouge">VecDeq&lt;WhileBlock&gt;</code> to keep track of which <code class="language-plaintext highlighter-rouge">]</code> corresponds to which <code class="language-plaintext highlighter-rouge">[</code>. Each <code class="language-plaintext highlighter-rouge">[</code>, we will push to the <code class="language-plaintext highlighter-rouge">VecDeq</code>, and each <code class="language-plaintext highlighter-rouge">]</code>, we will pop from the top of our <code class="language-plaintext highlighter-rouge">VecDeq</code>.</p>

<p>A <code class="language-plaintext highlighter-rouge">WhileBlock</code> is composed of three basic blocks.</p>

<ul>
  <li>
    <p><code class="language-plaintext highlighter-rouge">while_start</code> corresponds to the zero check. If the value at the data pointer is zero, we will jump to the end of the while block, otherwise, we will continue to the <code class="language-plaintext highlighter-rouge">while_body</code> block.</p>
  </li>
  <li>
    <p><code class="language-plaintext highlighter-rouge">while_body</code> block corresponds to the instructions between <code class="language-plaintext highlighter-rouge">[</code> and <code class="language-plaintext highlighter-rouge">]</code>.</p>
  </li>
  <li>
    <p><code class="language-plaintext highlighter-rouge">while_end</code> is all of the instructions after the <code class="language-plaintext highlighter-rouge">]</code>.</p>
  </li>
</ul>

<div class="language-rust highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">use</span> <span class="nn">inkwell</span><span class="p">::</span><span class="n">IntPredicate</span><span class="p">;</span>

 <span class="k">fn</span> <span class="n">build_while_start</span><span class="o">&lt;</span><span class="nv">'ctx</span><span class="o">&gt;</span><span class="p">(</span>
        <span class="n">context</span><span class="p">:</span> <span class="o">&amp;</span><span class="nv">'ctx</span> <span class="n">Context</span><span class="p">,</span>
        <span class="n">builder</span><span class="p">:</span> <span class="o">&amp;</span><span class="n">Builder</span><span class="p">,</span>
        <span class="n">main_fn</span><span class="p">:</span> <span class="o">&amp;</span><span class="n">FunctionValue</span><span class="p">,</span>
        <span class="n">ptr</span><span class="p">:</span> <span class="o">&amp;</span><span class="n">PointerValue</span><span class="p">,</span>
        <span class="n">while_blocks</span><span class="p">:</span> <span class="o">&amp;</span><span class="k">mut</span> <span class="n">VecDeque</span><span class="o">&lt;</span><span class="n">WhileBlock</span><span class="o">&lt;</span><span class="nv">'ctx</span><span class="o">&gt;&gt;</span><span class="p">,</span>
    <span class="p">)</span> <span class="p">{</span>
        <span class="c1">// create the while block</span>
        <span class="k">let</span> <span class="n">num_while_blocks</span> <span class="o">=</span> <span class="n">while_blocks</span><span class="nf">.len</span><span class="p">()</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
        <span class="k">let</span> <span class="n">while_block</span> <span class="o">=</span> <span class="n">WhileBlock</span> <span class="p">{</span>
            <span class="n">while_start</span><span class="p">:</span> <span class="n">context</span><span class="nf">.append_basic_block</span><span class="p">(</span>
                <span class="o">*</span><span class="n">main_fn</span><span class="p">,</span> <span class="nd">format!</span><span class="p">(</span><span class="s">"while_start {}"</span><span class="p">,</span> <span class="n">num_while_blocks</span><span class="p">)</span><span class="nf">.as_str</span><span class="p">(),</span>
            <span class="p">),</span>
            <span class="n">while_body</span><span class="p">:</span> <span class="n">context</span><span class="nf">.append_basic_block</span><span class="p">(</span>
                <span class="o">*</span><span class="n">main_fn</span><span class="p">,</span> <span class="nd">format!</span><span class="p">(</span><span class="s">"while_body {}"</span><span class="p">,</span> <span class="n">num_while_blocks</span><span class="p">)</span><span class="nf">.as_str</span><span class="p">(),</span>
            <span class="p">),</span>
            <span class="n">while_end</span><span class="p">:</span> <span class="n">context</span><span class="nf">.append_basic_block</span><span class="p">(</span>
                <span class="o">*</span><span class="n">main_fn</span><span class="p">,</span> <span class="nd">format!</span><span class="p">(</span><span class="s">"while_end {}"</span><span class="p">,</span> <span class="n">num_while_blocks</span><span class="p">)</span><span class="nf">.as_str</span><span class="p">(),</span>
            <span class="p">),</span>
        <span class="p">};</span>
        <span class="n">while_blocks</span><span class="nf">.push_front</span><span class="p">(</span><span class="n">while_block</span><span class="p">);</span>
        <span class="k">let</span> <span class="n">while_block</span> <span class="o">=</span> <span class="n">while_blocks</span><span class="nf">.front</span><span class="p">()</span><span class="nf">.unwrap</span><span class="p">();</span>

        <span class="n">builder</span>
            <span class="nf">.build_unconditional_branch</span><span class="p">(</span><span class="n">while_block</span><span class="py">.while_start</span><span class="p">);</span>
        <span class="n">builder</span><span class="nf">.position_at_end</span><span class="p">(</span><span class="n">while_block</span><span class="py">.while_start</span><span class="p">);</span>

        <span class="c1">// compare the value at ptr with zero</span>
        <span class="k">let</span> <span class="n">i8_type</span> <span class="o">=</span> <span class="n">context</span><span class="nf">.i8_type</span><span class="p">();</span>
        <span class="k">let</span> <span class="n">i8_zero</span> <span class="o">=</span> <span class="n">i8_type</span><span class="nf">.const_int</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="k">false</span><span class="p">);</span>
        <span class="k">let</span> <span class="n">ptr_load</span> <span class="o">=</span> <span class="n">builder</span>
            <span class="nf">.build_load</span><span class="p">(</span><span class="o">*</span><span class="n">ptr</span><span class="p">,</span> <span class="s">"load ptr"</span><span class="p">)</span>
            <span class="nf">.into_pointer_value</span><span class="p">();</span>
        <span class="k">let</span> <span class="n">ptr_value</span> <span class="o">=</span> <span class="n">builder</span>
            <span class="nf">.build_load</span><span class="p">(</span><span class="n">ptr_load</span><span class="p">,</span> <span class="s">"load ptr value"</span><span class="p">)</span>
            <span class="nf">.into_int_value</span><span class="p">();</span>
        <span class="k">let</span> <span class="n">cmp</span> <span class="o">=</span> <span class="n">builder</span><span class="nf">.build_int_compare</span><span class="p">(</span>
            <span class="nn">IntPredicate</span><span class="p">::</span><span class="n">NE</span><span class="p">,</span>
            <span class="n">ptr_value</span><span class="p">,</span>
            <span class="n">i8_zero</span><span class="p">,</span>
            <span class="s">"compare value at pointer to zero"</span><span class="p">,</span>
        <span class="p">);</span>

        <span class="c1">// jump to the while_end if the data at ptr was zero</span>
        <span class="n">builder</span>
            <span class="nf">.build_conditional_branch</span><span class="p">(</span><span class="n">cmp</span><span class="p">,</span> <span class="n">while_block</span><span class="py">.while_body</span><span class="p">,</span> <span class="n">while_block</span><span class="py">.while_end</span><span class="p">);</span>
        <span class="n">builder</span><span class="nf">.position_at_end</span><span class="p">(</span><span class="n">while_block</span><span class="py">.while_body</span><span class="p">);</span>
    <span class="p">}</span>
</code></pre></div></div>

<h2 id="compiling--3">Compiling ‘]’</h2>

<p>This function is fairly streightforward. We are just jumping back to the <code class="language-plaintext highlighter-rouge">start_block</code> of the matching <code class="language-plaintext highlighter-rouge">[</code>. The <code class="language-plaintext highlighter-rouge">start_block</code> will then re-compare the value at our <code class="language-plaintext highlighter-rouge">ptr</code>, and jump to the instruction after the <code class="language-plaintext highlighter-rouge">]</code> if it is zero.</p>

<div class="language-rust highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    <span class="k">fn</span> <span class="n">build_while_end</span><span class="o">&lt;</span><span class="nv">'ctx</span><span class="o">&gt;</span><span class="p">(</span>
        <span class="n">builder</span><span class="p">:</span> <span class="o">&amp;</span><span class="n">Builder</span><span class="p">,</span>
        <span class="n">while_blocks</span><span class="p">:</span> <span class="o">&amp;</span><span class="k">mut</span> <span class="n">VecDeque</span><span class="o">&lt;</span><span class="n">WhileBlock</span><span class="o">&lt;</span><span class="nv">'ctx</span><span class="o">&gt;&gt;</span>
        <span class="p">)</span> <span class="k">-&gt;</span> <span class="nb">Result</span><span class="o">&lt;</span><span class="p">(),</span> <span class="nb">String</span><span class="o">&gt;</span> <span class="p">{</span>
        <span class="k">if</span> <span class="k">let</span> <span class="nf">Some</span><span class="p">(</span><span class="n">while_block</span><span class="p">)</span> <span class="o">=</span> <span class="n">while_blocks</span><span class="nf">.pop_front</span><span class="p">()</span> <span class="p">{</span>
            <span class="n">builder</span>
                <span class="nf">.build_unconditional_branch</span><span class="p">(</span><span class="n">while_block</span><span class="py">.while_start</span><span class="p">);</span>
            <span class="n">builder</span><span class="nf">.position_at_end</span><span class="p">(</span><span class="n">while_block</span><span class="py">.while_end</span><span class="p">);</span>
            <span class="nf">Ok</span><span class="p">(())</span>
        <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
            <span class="nf">Err</span><span class="p">(</span><span class="s">"error: unmatched `]`"</span><span class="nf">.to_string</span><span class="p">())</span>
        <span class="p">}</span>
    <span class="p">}</span>

</code></pre></div></div>

<h1 id="wrap-up">Wrap Up</h1>

<p>That’s it! You should now have a functioning brainf*ck compiler using LLVM written in Rust!</p>

<p>Verify everything is working by testing the examples on <a href="https://en.wikipedia.org/wiki/Brainfuck#Examples">wikipedia</a></p>

<h2 id="addition">Addition</h2>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cargo run addition.bf -o output.o
gcc output.o
./a.out
7
</code></pre></div></div>

<h2 id="hello-world">Hello, World!</h2>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cargo run hello.bf -o output.o
gcc output.o
./a.out
Hello World!
</code></pre></div></div>

<h2 id="rot13-cipher">ROT13 Cipher</h2>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cargo run ROT13.bf -o output.o
gcc output.o
./a.out
asdf
nfqs
wrwer
jejre
^C⏎ 
</code></pre></div></div>

<h2 id="other-examples">Other Examples</h2>

<p>There are loads of other cool Brainf*ck programs that people have written, such as: <a href="http://esoteric.sange.fi/brainfuck/utils/mandelbrot/mandelbrot.b">mandelbrot.b</a>, <a href="http://www.clifford.at/bfcpu/hanoi.bf">hanoi.bf</a>, and <a href="http://www.linusakesson.net/programming/brainfuck/">Conway’s Game of Life</a>!</p>]]></content><author><name>Ben Konz</name></author><summary type="html"><![CDATA[LLVM is a collection of compiler toolchain technologies used to compile dynamic and static programming languages. It’s heavly used in programming languages, such as Clang, Emscripten, and Rust!]]></summary></entry><entry><title type="html">Pullquotes</title><link href="http://benkonz.github.io//pullquotes/" rel="alternate" type="text/html" title="Pullquotes" /><published>2019-12-11T00:00:00+00:00</published><updated>2019-12-11T00:00:00+00:00</updated><id>http://benkonz.github.io//pullquotes</id><content type="html" xml:base="http://benkonz.github.io//pullquotes/"><![CDATA[<p>In graphic design, a pull quote (also known as a lift-out pull quote) is a key phrase, quotation, or excerpt that has been pulled from an article and used as a page layout graphic element, serving to entice readers into the article or to highlight a key topic. It is typically placed in a larger or distinctive typeface and on the same page.<span data-pullquote="It is typically placed in a larger or distinctive typeface and on the same page."></span> Pull quotes are often used in magazine and newspaper articles, annual reports, and brochures, as well as on the web. They can add visual interest to text-heavy pages with few images or illustrations.</p>

<p>Placement of a pull quote on a page may be defined in a publication’s or website’s style guide. Such a typographic device may or may not be aligned with a column on the page. Some designers, for example, choose not to align the quote. In that case, the quotation cuts into two or more columns, as in the example shown. Because the pull quote invites the reader to read about the highlighted material, the pull quote should appear before the text it cites and, generally, fairly close to it.</p>

<p>Pull quotes need not be a verbatim copy of the text being quoted; depending on a publication’s house style, pull quotes may be abbreviated for space or paraphrased for clarity, with or without indication.</p>

<p>A disadvantage of pull quotes as a design element is that they can disrupt the reading process of readers invested in reading the text sequentially by drawing attention to ghost fragments out of context. At the other extreme, when pull quotes are used to break up what would otherwise be a formless wall of text, pull quote can serve as visual landmarks to help the reader maintain a sense of sequence and place.</p>]]></content><author><name>Ben Konz</name></author><category term="HTML" /><category term="Code" /><summary type="html"><![CDATA[In graphic design, a pull quote (also known as a lift-out pull quote) is a key phrase, quotation, or excerpt that has been pulled from an article and used as a page layout graphic element, serving to entice readers into the article or to highlight a key topic.]]></summary></entry><entry><title type="html">The Subtle Ergonomics of the Python Parser</title><link href="http://benkonz.github.io//the-sudtle-ergonomics-of-the-python-parser/" rel="alternate" type="text/html" title="The Subtle Ergonomics of the Python Parser" /><published>2019-09-28T00:00:00+00:00</published><updated>2019-09-28T00:00:00+00:00</updated><id>http://benkonz.github.io//the-sudtle-ergonomics-of-the-python-parser</id><content type="html" xml:base="http://benkonz.github.io//the-sudtle-ergonomics-of-the-python-parser/"><![CDATA[<p><a href="https://www.python.org/">Python</a> has established itself as a popular programming language for both
programming newcomers and veterans. This is due to how easy the language is to
both read and write. While writing a Python parser for
<a href="https://jeroo.org/beta">Jeroo</a>, I discovered many subtle things that the Parser and
Lexer do that make the language very ergonomic to use.</p>

<h1 id="dynamic-indentation-levels">Dynamic Indentation Levels</h1>

<p>Code blocks in Python have to start with a new indentation level and end with a dedentation level.
For example:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="bp">True</span><span class="p">:</span>
    <span class="k">print</span><span class="p">(</span><span class="s">"true"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">"always"</span><span class="p">)</span>
</code></pre></div></div>

<p>The indentation level can be of any length, so long as that it is more
whitespace than the previously seen indentation level. Additionally, tabs count
as 8 spaces, so it is possible to parse a file with both tabs and spaces.</p>

<h1 id="auto-closing-dedentation-tokens">Auto-Closing Dedentation Tokens</h1>

<p><a href="https://docs.python.org/3/reference/lexical_analysis.html#indentation">The Python language spec</a>
specifies that all indentation levels should be automatically be closed before 
the lexer emits an EOF token.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
    <span class="k">print</span><span class="p">(</span><span class="s">"loop"</span><span class="p">)</span>

</code></pre></div></div>

<p>This is quite useful, otherwise it would be very difficult to write programs
with multiple code blocks.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="bp">True</span><span class="p">:</span>
    <span class="k">if</span> <span class="bp">True</span><span class="p">:</span>
        <span class="k">if</span> <span class="bp">True</span><span class="p">:</span>
            <span class="k">if</span> <span class="bp">True</span><span class="p">:</span>
</code></pre></div></div>

<p>The programmer would have to make 4 newlines, all with one less whitespace
character than the previous.</p>

<h1 id="logical-newlines">Logical Newlines</h1>

<p><a href="https://docs.python.org/3/reference/lexical_analysis.html#logical-lines">The Python language spec</a>
also describes logical newlines. They are defined by this regular expression
<code class="language-plaintext highlighter-rouge">((whitespace* comment? newline)* whitespace* comment?) newline</code>, which says 
that logical newlines are whitespace, comments, and at least one newline.</p>

<p>Without this property, newlines would need to be handled in the parser, which
could lead to ambiguities.</p>

<h1 id="eof-as-a-valid-newline">EOF as a Valid Newline</h1>

<p>Python programs consider an EOF token as a valid end to a statement. 
As a result, not every program needs to end with a newline character, 
which also makes programs easier to write. For example, this:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
    <span class="k">print</span><span class="p">(</span><span class="s">"loop"</span><span class="p">)</span>
</code></pre></div></div>

<p>is a valid program, even though it doesn’t have a newline at the end of the
print statement.</p>]]></content><author><name>Ben Konz</name></author><summary type="html"><![CDATA[Python has established itself as a popular programming language for both programming newcomers and veterans. This is due to how easy the language is to both read and write. While writing a Python parser for Jeroo, I discovered many subtle things that the Parser and Lexer do that make the language very ergonomic to use.]]></summary></entry><entry><title type="html">Code snippets in a blog post</title><link href="http://benkonz.github.io//code-snippets/" rel="alternate" type="text/html" title="Code snippets in a blog post" /><published>2019-08-12T00:00:00+00:00</published><updated>2019-08-12T00:00:00+00:00</updated><id>http://benkonz.github.io//code-snippets</id><content type="html" xml:base="http://benkonz.github.io//code-snippets/"><![CDATA[<p>This post demonstrate the use of code snippets in the theme. The code snippets are powered by <a href="http://pygments.org/">Pygments</a> and the code theme that is been used in Reverie is called <a href="https://draculatheme.com/">Dracula</a>.</p>

<p>This is a raw snippet:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>hello world
123
This is a text snippet
</code></pre></div></div>

<p>This is a PHP snippet:</p>

<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">&lt;?php</span>
    <span class="k">echo</span> <span class="s1">'Hello, World!'</span><span class="p">;</span>
<span class="cp">?&gt;</span>
</code></pre></div></div>

<p>This is a JavaScript snippet:</p>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">add</span> <span class="o">=</span> <span class="p">(</span><span class="nx">a</span><span class="p">,</span> <span class="nx">b</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="nx">a</span> <span class="o">+</span> <span class="nx">b</span>
<span class="kd">const</span> <span class="nx">minus</span> <span class="o">=</span> <span class="p">(</span><span class="nx">a</span><span class="p">,</span> <span class="nx">b</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="nx">a</span> <span class="o">-</span> <span class="nx">b</span>

<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">add</span><span class="p">(</span><span class="mi">100</span><span class="p">,</span><span class="mi">200</span><span class="p">))</span>  <span class="c1">// 300</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">minus</span><span class="p">(</span><span class="mi">100</span><span class="p">,</span><span class="mi">200</span><span class="p">))</span>  <span class="c1">// -100</span>
</code></pre></div></div>

<p>This is a Python snippet:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">say_hello</span><span class="p">():</span>
    <span class="k">print</span><span class="p">(</span><span class="s">"hello world!"</span><span class="p">)</span>

<span class="n">say_hello</span><span class="p">()</span>   <span class="o">//</span> <span class="s">"hello world!"</span>
</code></pre></div></div>]]></content><author><name>Ben Konz</name></author><category term="HTML" /><category term="Code" /><summary type="html"><![CDATA[This post demonstrate the use of code snippets in the theme. The code snippets are powered by Pygments and the code theme that is been used in Reverie is called Dracula.]]></summary></entry><entry><title type="html"></title><link href="http://benkonz.github.io//no-title-posts/" rel="alternate" type="text/html" title="" /><published>2019-08-08T00:00:00+00:00</published><updated>2019-08-08T00:00:00+00:00</updated><id>http://benkonz.github.io//no-title-posts</id><content type="html" xml:base="http://benkonz.github.io//no-title-posts/"><![CDATA[<p>Sometimes, your post just stands for itself and doesn’t need a title. And that’s fine, too!</p>]]></content><author><name>Ben Konz</name></author><category term="Miscellaneous" /><summary type="html"><![CDATA[Sometimes, your post just stands for itself and doesn’t need a title. And that’s fine, too!]]></summary></entry><entry><title type="html">Some articles are just so short that we’ve to make the footer stick</title><link href="http://benkonz.github.io//super-short-article/" rel="alternate" type="text/html" title="Some articles are just so short that we’ve to make the footer stick" /><published>2019-07-28T00:00:00+00:00</published><updated>2019-07-28T00:00:00+00:00</updated><id>http://benkonz.github.io//super-short-article</id><content type="html" xml:base="http://benkonz.github.io//super-short-article/"><![CDATA[<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>]]></content><author><name>Ben Konz</name></author><category term="Miscellaneous" /><summary type="html"><![CDATA[Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.]]></summary></entry><entry><title type="html">Some articles are just so long they deserve a really long title to see if things will break well</title><link href="http://benkonz.github.io//super-long-article/" rel="alternate" type="text/html" title="Some articles are just so long they deserve a really long title to see if things will break well" /><published>2019-07-27T00:00:00+00:00</published><updated>2019-07-27T00:00:00+00:00</updated><id>http://benkonz.github.io//super-long-article</id><content type="html" xml:base="http://benkonz.github.io//super-long-article/"><![CDATA[<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce bibendum neque eget nunc mattis eu sollicitudin enim tincidunt. Vestibulum lacus tortor, ultricies id dignissim ac, bibendum in velit. Proin convallis mi ac felis pharetra aliquam. Curabitur dignissim accumsan rutrum. In arcu magna, aliquet vel pretium et, molestie et arcu. Mauris lobortis nulla et felis ullamcorper bibendum. Phasellus et hendrerit mauris. Proin eget nibh a massa vestibulum pretium. Suspendisse eu nisl a ante aliquet bibendum quis a nunc. Praesent varius interdum vehicula. Aenean risus libero, placerat at vestibulum eget, ultricies eu enim. Praesent nulla tortor, malesuada adipiscing adipiscing sollicitudin, adipiscing eget est.</p>

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce bibendum neque eget nunc mattis eu sollicitudin enim tincidunt. Vestibulum lacus tortor, ultricies id dignissim ac, bibendum in velit. Proin convallis mi ac felis pharetra aliquam. Curabitur dignissim accumsan rutrum. In arcu magna, aliquet vel pretium et, molestie et arcu. Mauris lobortis nulla et felis ullamcorper bibendum. Phasellus et hendrerit mauris. Proin eget nibh a massa vestibulum pretium. Suspendisse eu nisl a ante aliquet bibendum quis a nunc. Praesent varius interdum vehicula. Aenean risus libero, placerat at vestibulum eget, ultricies eu enim. Praesent nulla tortor, malesuada adipiscing adipiscing sollicitudin, adipiscing eget est.</p>

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce bibendum neque eget nunc mattis eu sollicitudin enim tincidunt. Vestibulum lacus tortor, ultricies id dignissim ac, bibendum in velit. Proin convallis mi ac felis pharetra aliquam. Curabitur dignissim accumsan rutrum. In arcu magna, aliquet vel pretium et, molestie et arcu. Mauris lobortis nulla et felis ullamcorper bibendum. Phasellus et hendrerit mauris. Proin eget nibh a massa vestibulum pretium. Suspendisse eu nisl a ante aliquet bibendum quis a nunc. Praesent varius interdum vehicula. Aenean risus libero, placerat at vestibulum eget, ultricies eu enim. Praesent nulla tortor, malesuada adipiscing adipiscing sollicitudin, adipiscing eget est.</p>]]></content><author><name>Ben Konz</name></author><category term="Miscellaneous" /><summary type="html"><![CDATA[Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce bibendum neque eget nunc mattis eu sollicitudin enim tincidunt. Vestibulum lacus tortor, ultricies id dignissim ac, bibendum in velit. Proin convallis mi ac felis pharetra aliquam. Curabitur dignissim accumsan rutrum. In arcu magna, aliquet vel pretium et, molestie et arcu. Mauris lobortis nulla et felis ullamcorper bibendum. Phasellus et hendrerit mauris. Proin eget nibh a massa vestibulum pretium. Suspendisse eu nisl a ante aliquet bibendum quis a nunc. Praesent varius interdum vehicula. Aenean risus libero, placerat at vestibulum eget, ultricies eu enim. Praesent nulla tortor, malesuada adipiscing adipiscing sollicitudin, adipiscing eget est.]]></summary></entry><entry><title type="html">This post demonstrates post content styles</title><link href="http://benkonz.github.io//this-post-demonstrates-post-content-styles/" rel="alternate" type="text/html" title="This post demonstrates post content styles" /><published>2019-07-27T00:00:00+00:00</published><updated>2019-07-27T00:00:00+00:00</updated><id>http://benkonz.github.io//this-post-demonstrates-post-content-styles</id><content type="html" xml:base="http://benkonz.github.io//this-post-demonstrates-post-content-styles/"><![CDATA[<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce bibendum neque eget nunc mattis eu sollicitudin enim tincidunt. Vestibulum lacus tortor, ultricies id dignissim ac, bibendum in velit. Praesent varius interdum vehicula. Aenean risus libero, placerat at vestibulum eget, ultricies eu enim. Praesent nulla tortor, malesuada adipiscing adipiscing sollicitudin, adipiscing eget est.</p>

<h2 id="some-great-heading-h2">Some great heading (h2)</h2>

<p>Proin convallis mi ac felis pharetra aliquam. Curabitur dignissim accumsan rutrum. In arcu magna, aliquet vel pretium et, molestie et arcu.</p>

<p>Mauris lobortis nulla et felis ullamcorper bibendum. Phasellus et hendrerit mauris. Proin eget nibh a massa vestibulum pretium. Suspendisse eu nisl a ante aliquet bibendum quis a nunc. Praesent varius interdum vehicula. Aenean risus libero, placerat at vestibulum eget, ultricies eu enim. Praesent nulla tortor, malesuada adipiscing adipiscing sollicitudin, adipiscing eget est.</p>

<h2 id="another-great-heading-h2">Another great heading (h2)</h2>

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce bibendum neque eget nunc mattis eu sollicitudin enim tincidunt. Vestibulum lacus tortor, ultricies id dignissim ac, bibendum in velit.</p>

<h3 id="some-great-subheading-h3">Some great subheading (h3)</h3>

<p>Proin convallis mi ac felis pharetra aliquam. Curabitur dignissim accumsan rutrum. In arcu magna, aliquet vel pretium et, molestie et arcu. Mauris lobortis nulla et felis ullamcorper bibendum.</p>

<p>Phasellus et hendrerit mauris. Proin eget nibh a massa vestibulum pretium. Suspendisse eu nisl a ante aliquet bibendum quis a nunc.</p>

<h3 id="some-great-subheading-h3-1">Some great subheading (h3)</h3>

<p>Praesent varius interdum vehicula. Aenean risus libero, placerat at vestibulum eget, ultricies eu enim. Praesent nulla tortor, malesuada adipiscing adipiscing sollicitudin, adipiscing eget est.</p>

<blockquote>
  <p>This quote will change your life. It will reveal the secrets of the universe, and all the wonders of humanity. Don’t misuse it.</p>
</blockquote>

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce bibendum neque eget nunc mattis eu sollicitudin enim tincidunt.</p>

<h3 id="some-great-subheading-h3-2">Some great subheading (h3)</h3>

<p>Vestibulum lacus tortor, ultricies id dignissim ac, bibendum in velit. Proin convallis mi ac felis pharetra aliquam. Curabitur dignissim accumsan rutrum.</p>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;html&gt;</span>
  <span class="nt">&lt;head&gt;</span>
  <span class="nt">&lt;/head&gt;</span>
  <span class="nt">&lt;body&gt;</span>
    <span class="nt">&lt;p&gt;</span>Hello, World!<span class="nt">&lt;/p&gt;</span>
  <span class="nt">&lt;/body&gt;</span>
<span class="nt">&lt;/html&gt;</span>
</code></pre></div></div>

<p>In arcu magna, aliquet vel pretium et, molestie et arcu. Mauris lobortis nulla et felis ullamcorper bibendum. Phasellus et hendrerit mauris.</p>

<h4 id="you-might-want-a-sub-subheading-h4">You might want a sub-subheading (h4)</h4>

<p>In arcu magna, aliquet vel pretium et, molestie et arcu. Mauris lobortis nulla et felis ullamcorper bibendum. Phasellus et hendrerit mauris.</p>

<p>In arcu magna, aliquet vel pretium et, molestie et arcu. Mauris lobortis nulla et felis ullamcorper bibendum. Phasellus et hendrerit mauris.</p>

<h4 id="but-its-probably-overkill-h4">But it’s probably overkill (h4)</h4>

<p>In arcu magna, aliquet vel pretium et, molestie et arcu. Mauris lobortis nulla et felis ullamcorper bibendum. Phasellus et hendrerit mauris.</p>

<h3 id="oh-hai-an-unordered-list">Oh hai, an unordered list!!</h3>

<p>In arcu magna, aliquet vel pretium et, molestie et arcu. Mauris lobortis nulla et felis ullamcorper bibendum. Phasellus et hendrerit mauris.</p>

<ul>
  <li>First item, yo</li>
  <li>Second item, dawg</li>
  <li>Third item, what what?!</li>
  <li>Fourth item, fo sheezy my neezy</li>
</ul>

<h3 id="oh-hai-an-ordered-list">Oh hai, an ordered list!!</h3>

<p>In arcu magna, aliquet vel pretium et, molestie et arcu. Mauris lobortis nulla et felis ullamcorper bibendum. Phasellus et hendrerit mauris.</p>

<ol>
  <li>First item, yo</li>
  <li>Second item, dawg</li>
  <li>Third item, what what?!</li>
  <li>Fourth item, fo sheezy my neezy</li>
</ol>

<h2 id="headings-are-cool-h2">Headings are cool! (h2)</h2>

<p>Proin eget nibh a massa vestibulum pretium. Suspendisse eu nisl a ante aliquet bibendum quis a nunc. Praesent varius interdum vehicula. Aenean risus libero, placerat at vestibulum eget, ultricies eu enim. Praesent nulla tortor, malesuada adipiscing adipiscing sollicitudin, adipiscing eget est.</p>

<p>Praesent nulla tortor, malesuada adipiscing adipiscing sollicitudin, adipiscing eget est.</p>

<p>Proin eget nibh a massa vestibulum pretium. Suspendisse eu nisl a ante aliquet bibendum quis a nunc.</p>

<h3 id="tables">Tables</h3>

<table>
  <thead>
    <tr>
      <th>Title 1</th>
      <th>Title 2</th>
      <th>Title 3</th>
      <th>Title 4</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>lorem</td>
      <td>lorem ipsum</td>
      <td>lorem ipsum dolor</td>
      <td>lorem ipsum dolor sit</td>
    </tr>
    <tr>
      <td>lorem ipsum dolor sit</td>
      <td>lorem ipsum dolor sit</td>
      <td>lorem ipsum dolor sit</td>
      <td>lorem ipsum dolor sit</td>
    </tr>
    <tr>
      <td>lorem ipsum dolor sit</td>
      <td>lorem ipsum dolor sit</td>
      <td>lorem ipsum dolor sit</td>
      <td>lorem ipsum dolor sit</td>
    </tr>
    <tr>
      <td>lorem ipsum dolor sit</td>
      <td>lorem ipsum dolor sit</td>
      <td>lorem ipsum dolor sit</td>
      <td>lorem ipsum dolor sit</td>
    </tr>
  </tbody>
</table>]]></content><author><name>Ben Konz</name></author><category term="Miscellaneous" /><summary type="html"><![CDATA[Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce bibendum neque eget nunc mattis eu sollicitudin enim tincidunt. Vestibulum lacus tortor, ultricies id dignissim ac, bibendum in velit. Praesent varius interdum vehicula. Aenean risus libero, placerat at vestibulum eget, ultricies eu enim. Praesent nulla tortor, malesuada adipiscing adipiscing sollicitudin, adipiscing eget est.]]></summary></entry><entry><title type="html">Introducing Reverie - A ridiculously elegant Jekyll theme</title><link href="http://benkonz.github.io//introducing-reverie-jekyll-theme/" rel="alternate" type="text/html" title="Introducing Reverie - A ridiculously elegant Jekyll theme" /><published>2019-02-13T00:00:00+00:00</published><updated>2019-02-13T00:00:00+00:00</updated><id>http://benkonz.github.io//introducing-reverie-jekyll-theme</id><content type="html" xml:base="http://benkonz.github.io//introducing-reverie-jekyll-theme/"><![CDATA[<p><a href="https://github.com/amitmerchant1990/reverie">Reverie</a> is a <a href="https://jekyllrb.com/">Jekyll</a>-powered theme which is simple and opinionated. It’s actually a fork of <a href="https://github.com/barryclark/jekyll-now">jekyll-now</a> with some additional features and personal touches which I’ve implemented to suit my needs for my blog.</p>

<p>This is a plug-and-play Jekyll theme which you can use on GitHub Pages without even setting up a local environment.</p>

<p><img src="/images/reverie-demo.png" alt="" /></p>

<h2 id="features-overview">Features overview</h2>

<ul>
  <li>Command-line free fork-first workflow, using GitHub.com to create, customize and post to your blog</li>
  <li>Fully responsive and mobile optimized base theme</li>
  <li>Sass/Coffeescript support using Jekyll 2.0</li>
  <li>Free hosting on your GitHub Pages user site</li>
  <li>All the SEO goodies comes in-built</li>
  <li>Markdown blogging</li>
  <li>Syntax highlighting using Pygments
    <ul>
      <li><a href="https://draculatheme.com/">Dracula syntax theme</a> included</li>
    </ul>
  </li>
  <li>Disqus commenting</li>
  <li>Google Analytics integration</li>
  <li>Fuzzy search across blog posts</li>
  <li>Pagination of posts works out-of-the-box.</li>
  <li>Categorize posts out-of-the box</li>
  <li>RSS Feed</li>
  <li>In-built sitemap</li>
</ul>

<div style="text-align: center;">
 <script async="" type="text/javascript" src="//cdn.carbonads.com/carbon.js?serve=CE7D6KJY&amp;placement=wwwamitmerchantcom" id="_carbonads_js"></script>
</div>

<h2 id="using-reverie-on-github-pages">Using Reverie on GitHub Pages</h2>

<h3 id="step-1-fork-reverie-to-your-user-repository">Step 1) Fork Reverie to your User Repository</h3>

<p>Fork <a href="https://github.com/amitmerchant1990/reverie">this repository</a>, then rename the repository to <code class="language-plaintext highlighter-rouge">yourgithubusername.github.io</code>.</p>

<p>Alternatively, you can use <a href="https://github.com/amitmerchant1990/reverie/generate">Use this template</a> button if you want to create a repository with a clean commit history which will use Reverie as a template.</p>

<p>Your Jekyll blog will often be viewable immediately at <a href="https://yourgithubusername.github.io">https://yourgithubusername.github.io</a> (if it’s not, you can often force it to build by completing step 2)</p>

<h3 id="step-2-customize-and-view-your-site">Step 2) Customize and view your site</h3>

<p>Enter your site name, description, avatar and many other options by editing the <code class="language-plaintext highlighter-rouge">_config.yml</code> file. You can easily turn on Google Analytics tracking, Disqus commenting and social icons here.</p>

<p>Making a change to <code class="language-plaintext highlighter-rouge">_config.yml</code> (or any file in your repository) will force GitHub Pages to rebuild your site with jekyll. Your rebuilt site will be viewable a few seconds later at <a href="https://yourgithubusername.github.io">https://yourgithubusername.github.io</a> - if not, give it ten minutes as GitHub suggests and it’ll appear soon.</p>

<h3 id="step-3-publish-your-first-blog-post">Step 3) Publish your first blog post</h3>

<p>Create a new file called <code class="language-plaintext highlighter-rouge">/_posts/2019-2-13-Hello-World.md</code> to publish your first blog post. That’s all you need to do to publish your first blog post! This <a href="https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet">Markdown Cheatsheet</a> might come in handy while writing the posts.</p>

<blockquote>
  <p>You can add additional posts in the browser on GitHub.com too! Just hit the <kbd>Create new file</kbd> button in <code class="language-plaintext highlighter-rouge">/_posts/</code> to create new content. Just make sure to include the <a href="http://jekyllrb.com/docs/frontmatter/">front-matter</a> block at the top of each new blog post and make sure the post’s filename is in this format: year-month-day-title.md</p>
</blockquote>

<h2 id="using-categories-in-reverie">Using Categories in Reverie</h2>

<p>You can categorize your content based on <code class="language-plaintext highlighter-rouge">categories</code> in Reverie. For this, you just need to add <code class="language-plaintext highlighter-rouge">categories</code> in front matter like below:</p>

<p>For adding single category:</p>

<div class="language-md highlighter-rouge"><div class="highlight"><pre class="highlight"><code>categories: JavaScript
</code></pre></div></div>

<p>For adding multiple categories:</p>

<div class="language-md highlighter-rouge"><div class="highlight"><pre class="highlight"><code>categories: [PHP, Laravel]
</code></pre></div></div>

<p>The contegorized content can be shown over this URL: <a href="https://yourgithubusername.github.io/categories/">https://yourgithubusername.github.io/categories/</a></p>

<h2 id="rss">RSS</h2>

<p>The generated <a href="https://en.wikipedia.org/wiki/RSS">RSS feed</a> of your blog can be found at <a href="https://yourgithubusername.github.io/feed">https://yourgithubusername.github.io/feed</a>. You can see the example RSS feed over <a href="https://www.amitmerchant.com/reverie/feed">here</a>.</p>

<h2 id="sitemap">Sitemap</h2>

<p>The generated sitemap of your blog can be found at <a href="https://yourgithubusername.github.io/sitemap">https://yourgithubusername.github.io/sitemap</a>. You can see the example sitemap feed over <a href="https://www.amitmerchant.com/reverie/sitemap">here</a>.</p>

<h2 id="license">License</h2>

<p>MIT</p>]]></content><author><name>Ben Konz</name></author><category term="Miscellaneous" /><category term="Jekyll" /><summary type="html"><![CDATA[Reverie is a Jekyll-powered theme which is simple and opinionated. It’s actually a fork of jekyll-now with some additional features and personal touches which I’ve implemented to suit my needs for my blog.]]></summary></entry></feed>