<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>

    <title>Roopesh Chander</title>
    <link>http://www.roopc.net/</link>
    <description>roopc.net</description>

    <generator>Jekyll</generator>
    <language>en-us</language>
    <copyright>Copyright 2013-2020 Roopesh Chander</copyright>
    <webMaster>roop@roopc.net (Roopesh Chander)</webMaster>
    <lastBuildDate>Tue, 10 Nov 2020 19:00:15 +0530</lastBuildDate>
    <pubDate>Tue, 10 Nov 2020 19:00:15 +0530</pubDate>

    <atom:link href="http://roopc.net/rss.xml" rel="self" type="application/rss+xml" />

    
    <item>
        <title>
        
            A workflow for Swift compiler development
        
        </title>
        <link>http://roopc.net/posts/2020/swift-compiler-dev-workflow/</link>
        <guid>http://roopc.net/posts/2020/swift-compiler-dev-workflow</guid>
        <pubDate>Tue, 21 Jan 2020 00:00:00 +0530</pubDate>
        <description>
        <![CDATA[
        <p>If you’re new to Swift compiler development, it can be helpful to look
at a workflow of how development can happen.</p>

<p>In this post, I’ll be describing the parts of the workflow I use when
working on compiler features. If you work on other parts of Swift (say
the Swift standard library), or on other aspects of the compiler (like
performance), this might not be helpful.</p>

<p>This post assumes that:</p>
<ul>
  <li>The Swift source code repositories are checked out under
<code class="language-plaintext highlighter-rouge">~/swift-source/</code></li>
  <li>The Swift repository is at <code class="language-plaintext highlighter-rouge">~/swift-source/swift</code></li>
  <li>The Swift repository has two remotes, <code class="language-plaintext highlighter-rouge">origin</code> and <code class="language-plaintext highlighter-rouge">fork</code>: <code class="language-plaintext highlighter-rouge">origin</code>
points to Apple’s Swift repository on GitHub, and <code class="language-plaintext highlighter-rouge">fork</code> points to
our fork of that repository on GitHib</li>
  <li>The <code class="language-plaintext highlighter-rouge">SWIFT_BUILD_DIR</code> environment variable is set to a Swift build
directory</li>
</ul>

<p>My <a href="/posts/2020/swift-compiler-dev-on-remote-linux-machine/">previous post</a> talks about one way to get a setup like that.</p>

<p>My workflow uses the following parts. The order of using these parts
varies depending on what I work on.</p>

<ul id="markdown-toc">
  <li><a href="#starting-off" id="markdown-toc-starting-off">Starting off</a></li>
  <li><a href="#debugging" id="markdown-toc-debugging">Debugging</a></li>
  <li><a href="#making-changes" id="markdown-toc-making-changes">Making changes</a></li>
  <li><a href="#syncing-up-with-master" id="markdown-toc-syncing-up-with-master">Syncing up with master</a></li>
  <li><a href="#testing" id="markdown-toc-testing">Testing</a>    <ul>
      <li><a href="#run-the-testsuite" id="markdown-toc-run-the-testsuite">Run the testsuite</a></li>
      <li><a href="#add-to-the-testsuite" id="markdown-toc-add-to-the-testsuite">Add to the testsuite</a></li>
      <li><a href="#more-on-the-testsuite" id="markdown-toc-more-on-the-testsuite">More on the testsuite</a></li>
    </ul>
  </li>
  <li><a href="#open-a-pull-request" id="markdown-toc-open-a-pull-request">Open a pull request</a></li>
  <li><a href="#modify-a-pull-request" id="markdown-toc-modify-a-pull-request">Modify a pull request</a></li>
</ul>

<h3 id="starting-off">Starting off</h3>

<p>When starting to work on a fix or feature, we should create a new branch
off master:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ git checkout -b &lt;feature-branch&gt; master
</code></pre></div></div>

<h3 id="debugging">Debugging</h3>

<p>To debug a compilation of <code class="language-plaintext highlighter-rouge">swiftc file.swift</code>, we can’t just run <code class="language-plaintext highlighter-rouge">lldb
-- swiftc file.swift</code> because <code class="language-plaintext highlighter-rouge">swiftc</code> invokes itself and other
executables as separate processes to do the actual compilation.</p>

<p>To see the underlying commands without running them, we can run:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ swiftc file.swift -###
</code></pre></div></div>

<p>Typically, we want to run the debugger on the first command printed, so
we can say:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ lldb -- `swiftc file.swift -### | head -n 1`
</code></pre></div></div>

<p>The <a href="https://github.com/apple/swift/blob/master/docs/DebuggingTheCompiler.rst">DebuggingTheCompiler.rst</a> document in the Swift repository has some
helpful information on debugging. I’m keeping <a href="https://gist.github.com/roop/94308a77aed665ed666d0d2472d3eec5">some notes</a> as well.</p>

<h3 id="making-changes">Making changes</h3>

<p>When committing, we should follow the Swift <a href="https://swift.org/contributing/#commit-messages">commit message guidelines</a>.</p>

<p>To rebuild Swift after making changes, we can run:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ cd $SWIFT_BUILD_DIR
$ ninja swift
</code></pre></div></div>

<p>If there were no changes to header files, rebuilding Swift would
typically take only a few minutes.</p>

<h3 id="syncing-up-with-master">Syncing up with master</h3>

<p>If we’ve been working on our feature branch for a while (say a
week), and if we have commits as work-in-progress on our feature
branch, it would be a good idea to rebase our feature branch on top
of the latest commits in master.</p>

<p>Assuming we’re on the feature branch:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ git fetch origin master
$ git rebase origin/master
</code></pre></div></div>

<p>If the are conflicts, they would have to be resolved during the
rebase.</p>

<p>After rebasing to master, we’ll have to rebuid Swift again.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ cd $SWIFT_BUILD_DIR
$ ninja swift
</code></pre></div></div>

<p>We’re rebuilding only Swift, while the changes we fetched on master
could have included changes to other parts of the project, like llvm
and the Swift standard library.</p>

<ul>
  <li>
    <p>In case the previously built version of Swift standard library
is out of date, we’ll get an error like this when running
<code class="language-plaintext highlighter-rouge">swift</code> or <code class="language-plaintext highlighter-rouge">swiftc</code>:</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>error: compiled module was created by an older version of the compiler; rebuild 'Swift' and try again
</code></pre></div>    </div>

    <p>Then we should rebuild the standard library as well, like:</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ cd $SWIFT_BUILD_DIR
$ ninja swift swift-stdlib
</code></pre></div>    </div>
  </li>
  <li>
    <p>In case the previously built version of llvm is out of date, we
will get errors referring to llvm header files while compiling
Swift. In that case, we should rerun the build script.</p>

    <p>First, we update all the repositories:</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ cd ~/swift-source/swift
$ git checkout master
$ cd ~/swift-source
$ ./swift/utils/update-checkout
</code></pre></div>    </div>

    <p>If there are commits in our feature branch, we can switch to
that branch now:</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ cd ~/swift-source/swift
$ git checkout &lt;feature-branch&gt; # rebase again onto master if reqd.
</code></pre></div>    </div>

    <p>We can now run <code class="language-plaintext highlighter-rouge">build-script</code> with the same options as the <a href="/posts/2020/swift-compiler-dev-on-remote-linux-machine/#build-it">initial
build</a>. Incremental runs of <code class="language-plaintext highlighter-rouge">build-script</code> take lesser time than clean
runs.</p>
  </li>
</ul>

<h3 id="testing">Testing</h3>

<h4 id="run-the-testsuite">Run the testsuite</h4>

<p>To make sure our changes haven’t affected working parts of the compiler,
we should test our version of Swift against the testsuite. The expected
output is embedded inside the test file, and the output is verified
using llvm’s <a href="https://www.llvm.org/docs/CommandGuide/FileCheck.html">FileCheck</a> utility.</p>

<p>We use the <code class="language-plaintext highlighter-rouge">lit.py</code> script for that. The following commands assume that
<code class="language-plaintext highlighter-rouge">lit.py</code> is available in our <code class="language-plaintext highlighter-rouge">PATH</code>.</p>

<p>By default, <code class="language-plaintext highlighter-rouge">lit.py</code> prints one of “PASS:”, “FAIL:” or “XFAIL:” (which
means expected failure) for every testcase. Passing <code class="language-plaintext highlighter-rouge">-s</code> suppresses
that.</p>

<p>If we pass <code class="language-plaintext highlighter-rouge">-v</code>, <code class="language-plaintext highlighter-rouge">lit.py</code> shall print the commands it invoked for
failing tests, so we can try to run it ourselves.</p>

<p>Typically, we know our changes are likely to affect only certain aspects
of the compiler, so we run only certain tests:</p>

<ul>
  <li>
    <p>To run tests under a certain test directory:</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ lit.py -sv $SWIFT_BUILD_DIR/test-linux-x86_64/&lt;test-directory&gt;
</code></pre></div>    </div>

    <p>where <code class="language-plaintext highlighter-rouge">&lt;test-directory&gt;</code> is a directory path under
<code class="language-plaintext highlighter-rouge">~/swift-source/swift/test/</code>.</p>
  </li>
  <li>
    <p>To run tests matching a filename pattern:</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ lit.py -sv $SWIFT_BUILD_DIR/test-linux-x86_64/&lt;test-directory&gt; --filter=&lt;pattern&gt;
</code></pre></div>    </div>
  </li>
</ul>

<p>If we’re about to open a pull request, we might want to run the full
testsuite:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ lit.py -s $SWIFT_BUILD_DIR/test-linux-x86_64/
</code></pre></div></div>

<h4 id="add-to-the-testsuite">Add to the testsuite</h4>

<p>Most changes to the compiler will require that the change be tested. In
that case, the pull request should include an addition to the testsuite
to verify the change.</p>

<h4 id="more-on-the-testsuite">More on the testsuite</h4>

<ul>
  <li><a href="https://github.com/apple/swift/blob/master/docs/Testing.md">Testing.md</a> in the Swift repository</li>
  <li><a href="https://forums.swift.org/t/need-a-workflow-advice/12536/14">codafi’s post</a> on the Swift forums</li>
</ul>

<h3 id="open-a-pull-request">Open a pull request</h3>

<p>To open a pull request, we should:</p>

<ol>
  <li>
    <p>Push the feature branch to our fork</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ git push fork &lt;feature-branch&gt;
</code></pre></div>    </div>
  </li>
  <li>
    <p>Go to your forked repository on GitHub on a web browser,
where you should see an option to create a pull request</p>
  </li>
  <li>
    <p>When opening the pull request, we should:</p>

    <ul>
      <li>include the bug number resolved by the pull request</li>
      <li>@-mention a potential reviewer, ideally from the Swift team</li>
    </ul>

    <p>If it’s not obvious who should review something, we could look at
<a href="https://github.com/apple/swift/blob/master/CODE_OWNERS.TXT">CODE_OWNERS.TXT</a> in the Swift repository.</p>
  </li>
</ol>

<p>Once we open a pull request, we should wait till a reviewer takes this
up for review. Only those who have commit access can ask
the <a href="https://github.com/apple/swift/blob/master/docs/ContinuousIntegration.md">@swift-ci build bot</a> to invoke automated testing on the pull request.</p>

<h3 id="modify-a-pull-request">Modify a pull request</h3>

<p>We might have to change a pull request for different reasons:</p>

<ul>
  <li>to make corrections in the implementation</li>
  <li>to take a different approach</li>
  <li>to address conflicts with changes in the master branch</li>
</ul>

<p>If we add commits to the same branch and push that to the same branch on
our fork, and they will be added to the pull request automatically.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ git push fork &lt;feature-branch&gt;
</code></pre></div></div>

<p>If we end up with a different set of commits altogether (maybe we used
interactive rebase to edit the commit history, or we rebased to a
different base commit), we can force-push to the same branch on our
fork, and the pull request will be updated automatically.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ git push -f fork &lt;feature-branch&gt;
</code></pre></div></div>

<p>Force-pushing can sometimes cause the @swift-ci build bot to report an
error even when there’s no error. In case the build bot reports an
error, we should take a look at its logs to check if it’s a genuine
error or not.</p>

<p>If you have questions, corrections, or feedback on this workflow, please
<a href="/about/#get-in-touch">let me know</a>.</p>


        
        
        ]]>
        </description>
    </item>
    
    <item>
        <title>
        
            Swift compiler development on a remote Linux machine
        
        </title>
        <link>http://roopc.net/posts/2020/swift-compiler-dev-on-remote-linux-machine/</link>
        <guid>http://roopc.net/posts/2020/swift-compiler-dev-on-remote-linux-machine</guid>
        <pubDate>Tue, 21 Jan 2020 00:00:00 +0530</pubDate>
        <description>
        <![CDATA[
        <p>Building Swift is intensive on CPU, memory, and diskspace. Working on
the compiler in parallel with app development wouldn’t have been
possible on my Macbook Air. So, I’ve been doing my Swift compiler work
on a Linode server instead.</p>

<p>If you’re interested in starting on Swift compiler development, renting
out a remote server like this can be a great way to get your feet wet.</p>

<p>So, let’s get started on setting up a remote server for Swift compiler
development.</p>

<ul id="markdown-toc">
  <li><a href="#choose-a-remote-linux-machine" id="markdown-toc-choose-a-remote-linux-machine">Choose a remote Linux machine</a></li>
  <li><a href="#set-up-the-remote-linux-machine" id="markdown-toc-set-up-the-remote-linux-machine">Set up the remote Linux machine</a>    <ul>
      <li><a href="#set-up-a-user" id="markdown-toc-set-up-a-user">Set up a user</a></li>
      <li><a href="#set-up-ssh-keys" id="markdown-toc-set-up-ssh-keys">Set up SSH keys</a></li>
      <li><a href="#set-up-tmux" id="markdown-toc-set-up-tmux">Set up tmux</a></li>
    </ul>
  </li>
  <li><a href="#set-up-the-local-macos-machine" id="markdown-toc-set-up-the-local-macos-machine">Set up the local macOS machine</a>    <ul>
      <li><a href="#set-up-iterm2" id="markdown-toc-set-up-iterm2">Set up iTerm2</a></li>
      <li><a href="#using-iterm2s-tmux-integration" id="markdown-toc-using-iterm2s-tmux-integration">Using iTerm2’s tmux integration</a></li>
      <li><a href="#configuring-iterm2s-tmux-integration" id="markdown-toc-configuring-iterm2s-tmux-integration">Configuring iTerm2’s tmux integration</a></li>
    </ul>
  </li>
  <li><a href="#build-swift" id="markdown-toc-build-swift">Build Swift</a>    <ul>
      <li><a href="#get-the-dependencies" id="markdown-toc-get-the-dependencies">Get the dependencies</a></li>
      <li><a href="#get-the-code" id="markdown-toc-get-the-code">Get the code</a></li>
      <li><a href="#build-it" id="markdown-toc-build-it">Build it</a></li>
    </ul>
  </li>
  <li><a href="#set-up-the-development-environment" id="markdown-toc-set-up-the-development-environment">Set up the development environment</a>    <ul>
      <li><a href="#git" id="markdown-toc-git">Git</a></li>
      <li><a href="#vim" id="markdown-toc-vim">Vim</a></li>
      <li><a href="#lldb" id="markdown-toc-lldb">lldb</a></li>
    </ul>
  </li>
  <li><a href="#set-up-our-fork-of-swift" id="markdown-toc-set-up-our-fork-of-swift">Set up our fork of Swift</a></li>
</ul>

<h3 id="choose-a-remote-linux-machine">Choose a remote Linux machine</h3>

<p>Choosing a machine configuration depends on the system requirements for
building Swift.</p>

<p>For hacking on Swift compiler features, the Swift repository’s <a href="https://github.com/apple/swift/blob/master/README.md#building-swift">README</a>
recommends building with <code class="language-plaintext highlighter-rouge">--release-debuginfo --debug-swift</code>, which
includes debug information when compiling llvm, the Swift compiler, and
the Swift standard library. A build like this would require at least 8
GB of RAM.</p>

<p>However, we can reduce the RAM required – and thereby adopt a less
expensive server configuration – by building just the compiler part
with debug symbols, with <code class="language-plaintext highlighter-rouge">--release --debug-swift</code>. Doing that would
enable us build Swift on a 4 GB RAM machine. As long as we’re only going
to work on compiler features, this build shall suffice.</p>

<p>In terms of disk space, if we build only Swift with debug symbols, we’ll
need about 30 GB per build; if we build everything with debug symbols,
we’ll need about 80 GB per build.</p>

<p>Apart from memory and diskspace, it’s a good idea to pick a server close
to our location to reduce latency.</p>

<p>Once the Linux server is created and booted, we can start setting it up.</p>

<h3 id="set-up-the-remote-linux-machine">Set up the remote Linux machine</h3>

<h4 id="set-up-a-user">Set up a user</h4>

<p>The freshly created server only has a root login now. We can login to
that machine using the root password specified or obtained while
creating the VPS:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ ssh root@&lt;ip-address&gt; # Enter password
</code></pre></div></div>

<p>Once logged in, create a new user. Specify a password when prompted. You will need
this password later when you use <code class="language-plaintext highlighter-rouge">sudo</code> commands.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># adduser &lt;user&gt; # Specify and remember password. Other info can be empty.
# usermod -aG sudo &lt;user&gt; # Give &lt;user&gt; sudo privileges
# su &lt;user&gt; # Switch to that user
</code></pre></div></div>

<h4 id="set-up-ssh-keys">Set up SSH keys</h4>

<p>Create the <code class="language-plaintext highlighter-rouge">.ssh</code> directory:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ mkdir ~/.ssh
$ chmod 700 ~/.ssh
</code></pre></div></div>

<p>Assuming you have an SSH keypair handy (they should be in ~/.ssh on
your local machine), add your public key as an authorized key on
the remote server.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ cat &gt;&gt; ~/.ssh/authorized_keys # Paste your public key
$ chmod 600 ~/.ssh/authorized_keys
</code></pre></div></div>

<p>This should enable you to <code class="language-plaintext highlighter-rouge">ssh</code> into the remote server without having to
type the server password.</p>

<p>Now, it’s a good idea to disable password-based login:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ sudo vim /etc/ssh/sshd_config # set 'PasswordAuthentication' to 'no'
$ sudo systemctl reload sshd # Reload the SSH daemon
</code></pre></div></div>

<h4 id="set-up-tmux">Set up tmux</h4>

<p>We use tmux to keep terminal sessions alive on the server even when our
SSH connection breaks. tmux is a terminal multiplexer, so one tmux
session can encapsulate multiple terminal sessions.</p>

<p>Install tmux on the server, if it’s not installed already.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ sudo apt-get install tmux
</code></pre></div></div>

<p>Create a new tmux session called “swift” in detatched mode.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ tmux new-session -s swift -d
</code></pre></div></div>

<p>The newly created tmux session will have one tmux window, and therefore
one terminal session. We can list the active tmux sessions by saying:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ tmux list-sessions
</code></pre></div></div>

<p>We’ll see that we have one tmux session with one window. We can create
more tmux windows and thereby, more terminal sessions. There are tmux
commands to do that, but an easier way to work with tmux is through
iTerm2 from your Mac.</p>

<h3 id="set-up-the-local-macos-machine">Set up the local macOS machine</h3>

<h4 id="set-up-iterm2">Set up iTerm2</h4>

<p>If you don’t have iTerm2 on your Mac,
<a href="https://iterm2.com/downloads.html">download</a> and install it. The
following instructions assume iTerm2 version 3.3.7.</p>

<ol>
  <li>
    <p>Open iTerm2</p>
  </li>
  <li>
    <p>Go to <em>iTerm2 &gt; Preferences &gt; Profiles</em> and add a new profile (say
“Swift dev”) using the “+” at the bottom left.</p>
  </li>
  <li>
    <p>Select that profile on the left, then select the <em>General</em> tab on
the right.</p>

    <p>Under the <em>Command</em> section, select <em>Command</em> and enter the
command as:</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ssh -t &lt;user&gt;@&lt;ip-address&gt; "tmux -CC attach -t swift"
</code></pre></div>    </div>

    <p>substituting your remote server username and ip address.</p>
  </li>
</ol>

<h4 id="using-iterm2s-tmux-integration">Using iTerm2’s tmux integration</h4>

<p>Once we’ve created the iTerm2 profile, if we right-click on iTerm2 on
the dock, and click on <em>New Window … &gt; Swift dev</em> (or whatever you named
your profile), iTerm2 will:</p>

<ul>
  <li>Open a new window and run the ssh command</li>
  <li>Once the ssh connection is established, run the tmux attach command
on the server to attach to the tmux session we’d started</li>
  <li>Get the state of the tmux windows in the tmux session and show them
as new tabs or windows in iTerm2</li>
</ul>

<p>The tmux session we had created on the server has just one window. So if
we right-click on iTerm2 and click on <em>New Window … &gt; Swift dev</em>, two
new windows shall open:</p>

<ol>
  <li>First, a window that runs ssh and then the tmux attach command.
This window shall have no command prompt.</li>
  <li>Next, a window that shows the tmux session’s tmux window, with a
command prompt.</li>
</ol>

<p>With the second window selected, iTerm2’s <em>New Window</em> and <em>New Tab</em>
commands will show a prompt asking if we want to create a new tmux tab
or window. If we pick that option, iTerm2 will create a new tmux window in
our tmux session and will open that window in a new tab / window.
When closing such a tab / window, iTerm2 will ask us if we want to
kill that window in the tmux session, or do we want to just hide it. I
prefer killing a tmux window when the corresponsing tab is closed.</p>

<p>If you’re done working on the server, you can close the first window,
which shall close the ssh connection and will then close all the tmux
windows. This can also happen when the ssh connection is broken due to
inactivity or a broken network connection.</p>

<p>To get back to working on the server, you can right-click on iTerm2 and
click on <em>New Window … &gt; Swift dev</em> again, and all our tmux windows will
be back.</p>

<h4 id="configuring-iterm2s-tmux-integration">Configuring iTerm2’s tmux integration</h4>

<p>This is how I like my iTerm2 configured for working on Swift:</p>

<ul>
  <li>
    <p>Make each tab correspond to a tmux window without showing the
prompts mentioned earlier</p>

    <p>Go to <em>iTerm2 &gt; Preferences &gt; Advanced</em>, search for “tmux”.</p>

    <ul>
      <li>
        <p>Under <em>Tmux Integration</em>, turn on <em>Suppress alert asking what
kind of tab to use in tmux integration</em> and <em>Suppress alert
asking what kind of window to open in tmux integration</em>.</p>
      </li>
      <li>
        <p>Under <em>Warnings</em>, turn on <em>Suppress kill/hide dialog when
closing a tmux tab</em> and <em>Suppress kill/hide dialog when closing
a tmux window</em>.</p>
      </li>
    </ul>

    <p>With that, while working on a tmux window, ⌘-T and ⌘-N open new tmux
windows, and closing a tab with a tmux window kills the tmux window.</p>
  </li>
  <li>
    <p>Use different-sized windows</p>

    <p>Previously, tmux required that all tmux windows in a session be
resized to the size of the smallest client viewport. So when we have
tmux windows from one tmux session spread across multiple iTerm2
windows, resizing one of those iTerm2 windows will resize the others
as well.</p>

    <p>If you have tmux version 2.9 or later (to know the tmux version, run
<code class="language-plaintext highlighter-rouge">tmux -V</code> on the server), we can fix this:</p>

    <ul>
      <li>
        <p>Go to <em>iTerm2 &gt; Preferences &gt; Advanced</em>. Under <em>Experimental
Features</em>, turn on <em>Allow variable window sizes in tmux
integration</em>.</p>
      </li>
      <li>
        <p>Go to <em>iTerm2 &gt; Preferences &gt; General</em> and select the <em>tmux</em> tab.
For <em>Open tmux windows as:</em>, select “Native windows”.</p>
      </li>
    </ul>

    <p>I learnt about this option from <a href="https://groups.google.com/forum/#!topic/iterm2-discuss/Etfozb_63Pg">here</a>.</p>

  </li>
  <li>
    <p>Account for many tmux windows in a tmux session</p>

    <p>When connecting to a tmux session, if you have too many tmux windows
(10 tmux windows by default), iTerm2 will show the “tmux dashboard”
instead of opening the windows directly. We can then open the
unopened tmux windows in tabs or windows from the dashboard.</p>

    <p>I find this limit of 10 to be too low, so I set it to 20. This can be
configured in the tmux dashboard itself, by going to <em>Shell &gt; tmux &gt;
Dashboard</em> in the iTerm2 menu.</p>
  </li>
  <li>
    <p>Color scheme</p>

    <p>By default, the tmux windows are created with a profile called “tmux”.
I changed the color scheme for this profile by doing this:</p>

    <ol>
      <li>Go to <em>iTerm2 &gt; Preferences &gt; Profiles</em></li>
      <li>Select <em>tmux</em> on the left, select the <em>Colors</em> tab on the right</li>
      <li>Select a preset in <em>Color Presets</em> (I recommend Solarized Dark)</li>
    </ol>
  </li>
  <li>
    <p>Always show tab bar</p>

    <p>Even if there’s just one tab in a window, I like the tab bar to show
up so that I can easily rearrange tmux windows into iTerm2 windows
as I want. To do that:</p>

    <ol>
      <li>Go to <em>iTerm2 &gt; Preferences &gt; Appearance</em></li>
      <li>Go to the <em>Tabs</em> tab</li>
      <li>Turn on <em>Show tab bar even when there is only one tab</em></li>
    </ol>
  </li>
</ul>

<p>If you want to poke around for more tmux-specific configuration options,
you can try these:</p>

<ul>
  <li>See the <a href="https://gitlab.com/gnachman/iterm2/-/wikis/tmux-Integration-Best-Practices">iTerm2 wiki page</a> on configuring iTerm2’s tmux integration</li>
  <li>Go to <em>iTerm2 &gt; Preferences &gt; General</em> and select the <em>tmux</em> tab</li>
  <li>Go to <em>iTerm2 &gt; Preferences &gt; Advanced</em> and search for “tmux”</li>
</ul>

<h3 id="build-swift">Build Swift</h3>

<h4 id="get-the-dependencies">Get the dependencies</h4>

<p>On the server, install all the required dependancies to build Swift
using the <code class="language-plaintext highlighter-rouge">apt-get</code> command <a href="https://github.com/apple/swift/#linux">from the Swift
repository</a>.</p>

<h4 id="get-the-code">Get the code</h4>

<p>Before building Swift, we need to clone Swift repository, and a
bunch of other repositories as well. We create a directory under
which all these repositories will be placed:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ mkdir ~/swift-source
</code></pre></div></div>

<p>And then clone all the required repositories under that directory:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ cd ~/swift-source
$ git clone https://github.com/apple/swift.git
$ ./swift/utils/update-checkout --clone
</code></pre></div></div>

<h4 id="build-it">Build it</h4>

<p>The Swift project’s build system uses CMake to create Ninja build
files, and Ninja to use those build files to compile and link code.
The Swift repository includes a build script called <code class="language-plaintext highlighter-rouge">build-script</code>
that builds CMake and Ninja from source, and then uses that CMake
and Ninja to build llvm, Swift and the Swift standard library.</p>

<p>By default, <code class="language-plaintext highlighter-rouge">build-script</code> will spawn as many parallel jobs as there
are CPUs in the machine, which is good while compiling. However,
linking uses a lot of memory, so we don’t want to be doing multiple
link jobs at a time.</p>

<s>There's no way I know of to tell the build
system to not use parallel jobs only while linking, so the easy way
out is to ask the build script to run all jobs sequentially (`-j1`).
This will however increase the initial build time quite a bit.</s>

<p><strong>Update:</strong> To tell the build system not to use parallel jobs while
linking, we can set the relevant CMake properties using the
<code class="language-plaintext highlighter-rouge">--llvm-cmake-options</code> and <code class="language-plaintext highlighter-rouge">--swift-cmake-options</code> arguments.</p>

<p>To be able to work on compiler features, we want to build the compiler
in debug mode. If you work on other parts of Swift (say the Swift
standard library), or on other aspects of the compiler (like
performance), the options would be different.</p>

<p>To build only Swift in debug mode and everything else in release mode,
we say:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ cd ~/swift-source
$ ./swift/utils/build-script --release --debug-swift --llvm-cmake-options==-DLLVM_PARALLEL_LINK_JOBS=1 --swift-cmake-options=-DSWIFT_PARALLEL_LINK_JOBS=1
</code></pre></div></div>

<p>This build can take about 3 hours, and will write the build results to
<code class="language-plaintext highlighter-rouge">build/Ninja-ReleaseAssert+swift-DebugAssert</code>.</p>

<p>It helps to set up <code class="language-plaintext highlighter-rouge">SWIFT_BUILD_DIR</code> and <code class="language-plaintext highlighter-rouge">PATH</code> environment variables
like this:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ cat &gt;&gt; ~/.bash_profile
export SWIFT_BUILD_DIR=~/swift-source/build/Ninja-ReleaseAssert+swift-DebugAssert/swift-linux-x86_64
export PATH=${PATH}:${SWIFT_BUILD_DIR}/bin # For swift, swiftc, etc.
export PATH=${PATH}:~/swift-source/llvm-project/utils/lit # For lit.py
$ source ~/.bash_profile
</code></pre></div></div>

<p>Having <code class="language-plaintext highlighter-rouge">swift</code> and <code class="language-plaintext highlighter-rouge">swiftc</code> in our <code class="language-plaintext highlighter-rouge">PATH</code> would help us run the
built Swift from any directory. Having <code class="language-plaintext highlighter-rouge">lit.py</code> in our <code class="language-plaintext highlighter-rouge">PATH</code> would
help us run the Swift testsuite from any directory.</p>

<p>In case you want to build everything with debug information (and your
server has 8 GB RAM or more), you can pass <code class="language-plaintext highlighter-rouge">--release-debuginfo</code> instead
of <code class="language-plaintext highlighter-rouge">--release</code> to <code class="language-plaintext highlighter-rouge">build-script</code>. This build will take longer to
complete, and the build results will be placed in a different directory.</p>

<h3 id="set-up-the-development-environment">Set up the development environment</h3>

<h4 id="git">Git</h4>

<p>Setup username and email for creating commit messages.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git config --global user.name “Roopesh Chander”
git config --global user.email roop@roopc.net
</code></pre></div></div>

<p>Setup the editor for editing commit messages and interactive rebase. I
use vim.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git config --global core.editor vim
</code></pre></div></div>

<h4 id="vim">Vim</h4>

<p>The Swift compiler’s C++ code uses two spaces for indentation, so we can
add these to our <code class="language-plaintext highlighter-rouge">~/.vimrc</code>:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>set expandtab
set tabstop=2
set shiftwidth=2
</code></pre></div></div>

<p>For help in editing Swift, SIL and gyb files, we can use the vim support
files from the Swift repository itself by:</p>

<ul>
  <li>
    <p>adding this line to <code class="language-plaintext highlighter-rouge">~/.vimrc</code>:</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>set runtimepath+=~/swift-source/swift/utils/vim
</code></pre></div>    </div>
  </li>
  <li>
    <p>making the filetype detection files accessible under <code class="language-plaintext highlighter-rouge">~/.vim/ftdetect</code>:</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ mkdir -p ~/.vim/ftdetect
$ cd ~/.vim/ftdetect
$ ln -s ~/swift-source/swift/utils/vim/ftdetect/*.vim .
</code></pre></div>    </div>
  </li>
</ul>

<h4 id="lldb">lldb</h4>

<p>We just need to install lldb:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ sudo apt-get install lldb
</code></pre></div></div>

<h3 id="set-up-our-fork-of-swift">Set up our fork of Swift</h3>

<p>Contributions to the Swift compiler are done through GitHub pull
requests. To create pull requests, we should have a fork of the Swift
repository under our GitHub account. To fork Swift, go to <a href="https://github.com/apple/swift/">Swift’s
GitHub page</a> on a web browser and click
on the “Fork” button.</p>

<p>We already have a clone of the main Swift repository. We want to be able
to push from there to our fork on GitHub. We don’t want to be specifying
our GitHub password every time we push, so we’d like to authenticate to
GitHub automatically using SSH keys. However, if we make our private
keys available on the server, either by copying our private keys or by
using SSH forwarding, it means that in case the server is compromised,
that key can be used to control everything in our GitHub account. So, in
the interest of security, we’re going to create a separate keypair that
we shall use to push to just one repository – our fork of Swift. Since
this key controls just this one repository, we can even afford to make
the key not password-protected.</p>

<ol>
  <li>
    <p>On the server, create a keypair:</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ ssh-keygen
</code></pre></div>    </div>

    <p>and just press enter for the prompts (no password required). This
shall create <code class="language-plaintext highlighter-rouge">~/.ssh/id_rsa</code> and <code class="language-plaintext highlighter-rouge">~/.ssh/id_rsa.pub</code>.</p>
  </li>
  <li>
    <p>Start the SSH agent and add the private key to it:</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ eval `ssh-agent -s`
$ ssh-add ~/.ssh/id_rsa
</code></pre></div>    </div>
  </li>
  <li>
    <p>Copy the public key:</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ cat ~/.ssh/id_rsa.pub # Copy the output
</code></pre></div>    </div>
  </li>
  <li>
    <p>Add this public key as a <em>Deploy key</em> in GitHub:</p>

    <ul>
      <li>Go to your fork’s GitHub page on a web browser (the URL should
be like <code class="language-plaintext highlighter-rouge">https://github.com/&lt;your-github-username&gt;/swift</code>) and
go to <em>Settings &gt; Deploy keys &gt; Add deploy key</em></li>
      <li>Under <em>Title</em>, specify a title so that we can identify the
deploy key’s origin in the future</li>
      <li>Under <em>Key</em>, paste the public key we copied in the previous step</li>
      <li>Tick the checkbox to <em>Allow write access</em></li>
      <li>Click on “Add key”</li>
    </ul>
  </li>
  <li>
    <p>Back on the server, go to our clone of the Swift repository and add
our fork as another remote called <code class="language-plaintext highlighter-rouge">fork</code>:</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ cd ~/swift-source/swift
$ git remote add fork git@github.com:&lt;your-GitHub-username&gt;/swift.git
</code></pre></div>    </div>
  </li>
</ol>

<p>At this point, we have a working setup. If you’re new to Swift compiler
development, now would be a good time to start looking at <a href="https://bugs.swift.org/issues/?jql=project%20%3D%20SR%20AND%20status%20%3D%20Open%20AND%20labels%20%3D%20StarterBug%20AND%20assignee%20in%20(EMPTY)">starter
bugs</a>. In the <a href="/posts/2020/swift-compiler-dev-workflow/">next post</a>, we’ll see how we can work on the
Swift compiler with a setup like this.</p>

<p>If the server reboots, we’ll lose the tmux sessions. In that case, we
have to start a fresh tmux session. We should also restart the SSH agent
and <code class="language-plaintext highlighter-rouge">ssh-add</code> the private key for pushing to <a href="#set-up-our-fork-of-swift">our
fork</a>.</p>

<p>Keep in mind that the server is a recurring cost. So if we know we’re
going to not work on the compiler for a few weeks, it can be a good idea
to delete the server and spawn a new one when we’re ready. Before
deleting, we should take a look at all local branches and the stash,
push anything worth saving to our fork, and file-transfer any uncommitted
unit testcases, so that we can get back to work with minimum disruption.</p>

<p>If you have questions, corrections, or feedback, please <a href="/about/#get-in-touch">get in touch</a>.</p>


        
        
        ]]>
        </description>
    </item>
    
    <item>
        <title>
        
            Introducing Citron
        
        </title>
        <link>http://roopc.net/posts/2017/introducing-citron/</link>
        <guid>http://roopc.net/posts/2017/introducing-citron</guid>
        <pubDate>Sun, 03 Dec 2017 00:00:00 +0530</pubDate>
        <description>
        <![CDATA[
        <p>I’d like to introduce you to <a href="http://roopc.net/citron/">Citron</a>, an LALR parser generator for Swift
that I’ve been working on. For a given input grammar, Citron creates a
reentrant type-safe parser in Swift.</p>

<p>Citron is based on the <a href="https://www.hwaci.com/sw/lemon/lemon.html">Lemon</a> parser generator by <a href="http://www.hwaci.com/drh/">Richard Hipp</a> that’s
used in SQLite. The parser generation engine of Citron is written in C,
as is the case with Lemon, but the output parser code is all Swift.</p>

<h3 id="whats-different">What’s different</h3>

<p>Citron uses the same grammar specification syntax used by Lemon, which
is a little different from what Bison and Yacc use. In addition, Citron
is stricter with code blocks and types than Bison, Yacc or Lemon.</p>

<p>In Citron:</p>

<ul>
  <li>
    <p>All terminals and non-terminals in the grammar must have explicitly
defined types</p>
  </li>
  <li>
    <p>Every grammar rule should be accompanied by an associated code block
that will be invoked when the rule gets used during parsing</p>
  </li>
  <li>
    <p>The code block associated with a rule should take in values of the
correct type as input, and should return a value of the correct
type</p>
  </li>
</ul>

<h3 id="writing-a-rule">Writing a rule</h3>

<p>Let’s say you have a grammar rule for Swift’s <code class="language-plaintext highlighter-rouge">let</code> statement that can
be expressed in <a href="https://en.wikipedia.org/wiki/Backus–Naur_form">BNF</a> like this:</p>

<pre><code class="language-Text">&lt;let-decl&gt; ::= "let" &lt;id&gt; ":" &lt;type-decl&gt;
</code></pre>

<p>An equivalent rule in a Citron grammar file could look like this:</p>

<pre><code class="language-Text">let_decl ::= LET ID COLON type_decl.
</code></pre>

<p>In Citron, terminals (a.k.a. tokens) start with an uppercase letter (like
<code class="language-plaintext highlighter-rouge">LET</code>, <code class="language-plaintext highlighter-rouge">ID</code> and <code class="language-plaintext highlighter-rouge">COLON</code>), and non-terminals start with a lowecase letter (like
<code class="language-plaintext highlighter-rouge">let_decl</code> and <code class="language-plaintext highlighter-rouge">type_decl</code>). “let”, “:” and the identifier are expected to be
recognized at tokenization stage and converted to tokens <code class="language-plaintext highlighter-rouge">LET</code>,
<code class="language-plaintext highlighter-rouge">COLON</code> and <code class="language-plaintext highlighter-rouge">ID</code> respectively, so the parser only sees these tokens.</p>

<p>If one were to create a parse tree from the input, there would be
semantic types representing the terminals and non-terminals present in
the grammar. A <code class="language-plaintext highlighter-rouge">let</code> node of the parse tree could be represented with
something like:</p>

<pre><code class="language-Swift">class LetDeclaration {
    var id: String
    var type: TypeDeclaration
    init(id: String, type: TypeDeclaration) {
        self.id = id
        self.type = type
    }
}
</code></pre>

<p>If that’s the case, you should tell Citron about these backing types.
It’s a good practice to declare the type of the terminals before the
rules, and the declare the types of the non-terminals close to where the
they occur in a rule, like this:</p>

<pre><code class="language-Text">%token_type String // type representing LET, ID and COLON

%nonterminal_type let_decl LetDeclaration
%nonterminal_type type_decl TypeDeclaration

let_decl ::= LET ID COLON type_decl.
</code></pre>

<p>Citron expects a code block immediately after a rule. The code block
should form the body of a function that returns a value representing the
LHS symbol of the rule. The LHS symbol of this rule is <code class="language-plaintext highlighter-rouge">let_decl</code>, so
our code block should return something of type <code class="language-plaintext highlighter-rouge">LetDeclaration</code>.</p>

<p>We can add alias names to the RHS symbols as shown below, and
they will be made available as named function parameters within the code
block with the appropriate type.</p>

<pre><code class="language-Text">%token_type String
%nonterminal_type let_decl LetDeclaration
%nonterminal_type type_decl TypeDeclaration

let_decl ::= LET ID(n) COLON type_decl(t). {
    // 'n' of type String and 't' of type TypeDeclaration
    // are available for use in this code block
    return LetDeclaration(id: n, type: t)
}
</code></pre>

<p>Now we have a valid Citron rule – the rule is immediately followed by a
code block, and the code block takes in and returns values of correct
types.</p>

<p>You can find an example grammar file <a href="https://github.com/roop/citron/blob/master/examples/calc/ArithmeticExpressionParser.y">here</a>, which has a set
of rules that describe simple arithmetic expressions.</p>

<p>In the Citron-generated code, the code block is used as the body of a
function. The type signature of the function is based on the symbol on
the LHS and the aliased symbols on the RHS. For the above code block,
the Citron-generated function would look something like this:</p>

<pre><code class="language-Swift">func codeBlockForRule1(n: String, t: TypeDeclaration) -&gt; LetDeclaration {
    // 'n' of type String and 't' of type TypeDeclaration
    // are available for use in this code block
    return LetDeclaration(name: n, type: t)
}
</code></pre>

<p>Unless the aliased symbols’ types and the return type used in the code
block are consistent with the rule, the generated parser code will not
compile. This type safety helps catch code block errors at build time
rather than at run time.</p>

<h3 id="the-parser-interface">The parser interface</h3>

<p>The Citron-generated code contains a parser class, named <code class="language-plaintext highlighter-rouge">Parser</code> by
default, with two parsing methods:</p>

<ol>
  <li>
    <p><code class="language-plaintext highlighter-rouge">consume(token:code:)</code></p>

    <p>This methods makes the parser consume one token. This should be
called multiple times to pass a sequence of tokens to the parser.
Typically, a separate tokenization stage would generate this
sequence of tokens. As the tokens get generated, they can be passed
to the parser through this method.</p>

    <p>The first argument, <code class="language-plaintext highlighter-rouge">token:</code>, is the semantic value of the token, as
seen by the code blocks in the grammar. The type of this argument
is the <code class="language-plaintext highlighter-rouge">%token_type</code> type specified in the grammar.</p>

    <p>The second argument, <code class="language-plaintext highlighter-rouge">code:</code>, is the token code that Citron knows
this token by. The Citron-generated class contains an enum of all
terminals in the grammar, and this argument should be a value of
that enum.</p>

    <p>For example, the “n” in “let n: Int” would be passed to the
parser like this: <code class="language-plaintext highlighter-rouge">parser.consume(token: "n", code: .ID)</code>.</p>
  </li>
  <li>
    <p><code class="language-plaintext highlighter-rouge">endParsing()</code></p>

    <p>This method tells the parser that there are no more tokens to consume, and
signifies the end of input.</p>

    <p>This method takes no arguments, and returns the parse result. The
parse result is the value returned by the code block of the start
rule (a.k.a. root rule) of the grammar. If we’re building a parse
tree using the code blocks as illustrated above, the parse result
would typically be the parse tree.</p>

    <p>The return type of this method is the <code class="language-plaintext highlighter-rouge">%nonterminal_type</code> of the
start symbol (a.k.a. root symbol) of the grammar.</p>
  </li>
</ol>

<p>The string “let n: Int” could get tokenized into four tokens and passed
to Citron as:</p>

<pre><code class="language-Swift">let parser = Parser()
do {
    ...
    try parser.consume(token: "let", code: .LET)
    try parser.consume(token: "n", code: .ID)
    try parser.consume(token: ":", code: .COLON)
    try parser.consume(token: "Int", code: .BUILTIN_TYPE)
    ...
    let parseTree = try parser.endParsing()
} catch {
    // Handle errors
}
</code></pre>

<h3 id="error-handling">Error handling</h3>

<p>Both <code class="language-plaintext highlighter-rouge">consume(token:code:)</code> and <code class="language-plaintext highlighter-rouge">endParsing()</code> are throwing methods, so
they should be invoked with a preceding <code class="language-plaintext highlighter-rouge">try</code>. They throw when an input
token at a certain position is inconsistent with the grammar, or when the
input ends prematurely.</p>

<p>Moreover, we can throw errors from within a rule’s code block and those
throws would propagate up to one of the two parsing methods.</p>

<p><strong>Update:</strong> In Citron 2.0, you can use <a href="/citron/error-capturing/">error capturing</a> for more
advanced error handling.</p>

<h3 id="the-lexer-interface">The lexer interface</h3>

<p>Citron offers a simple lexer that can tokenize an input string.</p>

<p>We give the lexer a series of rules with either string or regular
expression patterns. The token data that the lexer should output can be
of an arbitrary type, so the lexer is defined as a generic type, with
the token data as a type parameter. For each string pattern, we give it
the token data that should be output, and for each regular expression
pattern, we give it a closure that returns the token data.</p>

<p>For example, you could say:</p>

<pre><code class="language-Swift">
// A tuple with all the data we need for a token
typealias TokenData = (String, Parser.CitronTokenCode)

// A lexer that can output tokens as the tuple we just defined
typealias Lexer = CitronLexer&lt;TokenData&gt;

// Create the lexer with tokenization rules
let lexer = Lexer(rules: [

        // Keywords

        .string("let", ("", .LET)),
        .string("var", ("", .VAR)),
        .string("class", ("", .CLASS)),
        ...

        // Punctuation

        .string("{", ("", .OPEN_FLOWER_BRACKET)),
        .string("}", ("", .CLOSE_FLOWER_BRACKET)),
        .string(":", ("", .COLON)),
        ...

        // Built-in types

        .string("Int", ("", code: .INT)),
        .string("String", ("", code: .STRING)),
        ...

        // Identifiers

        .regexPattern("[A-Za-z][0-9A-Za-z]*", { str in (str, .ID) }),

        // Whitespace

        .regexPattern("\\s", { _ in nil }) // Ignored
    ])
</code></pre>

<p>We can ask the lexer to tokenize a string and give it a closure to run
on each token it identifies. The token data gets passed into the closure
as a parameter. Inside the closure, we can pass on the token data to the
parser.</p>

<pre><code class="language-Swift">do {
    try lexer.tokenize(inputString) { (t, c) in
        try parser.consume(token: t, code: c)
    }
    let parseTree = try parser.endParsing()
    print("\(parseTree)")
} catch {
    print("Error during parsing")
}
</code></pre>

<h3 id="try-it">Try it</h3>

<p>The Citron code is <a href="https://github.com/roop/citron">on Github</a>, along with a few <a href="https://github.com/roop/citron/tree/master/examples/">examples</a>. There’s also
a more <a href="http://roopc.net/citron/">detailed documentation</a>.</p>

<p>I’d be happy to answer questions or take feedback <a href="https://twitter.com/roopeshchander">on Twitter</a> or <a href="mailto:roop@roopc.net">by
email</a>.</p>


        
        
        ]]>
        </description>
    </item>
    
    <item>
        <title>
        
            TRAI’s spat with Apple over app access to messages and call logs
        
        </title>
        <link>http://roopc.net/posts/2017/trai-apple-spat/</link>
        <guid>http://roopc.net/posts/2017/trai-apple-spat</guid>
        <pubDate>Tue, 22 Aug 2017 00:00:00 +0530</pubDate>
        <description>
        <![CDATA[
        <p><a href="http://timesofindia.indiatimes.com/business/india-business/trai-raps-apple-for-colonising-data-in-india-says-its-anti-customer/articleshow/59961674.cms">Pankaj Doval</a>, <em>Times of India</em> (via <a href="https://applesutra.com/2017/08/11/trai-apple-data-fight/">Applesutra</a>):</p>

<blockquote>
  <p>Telecom regulator Trai has accused iPhone maker Apple of engaging in
“data colonisation” in India and being “anti-consumer” by not allowing
customers to pass on details about pesky calls and unwanted messages
to authorities as well as their mobile operators.</p>

  <p>…</p>

  <p>“While Google’s Android supports our Do-Not-Disturb (DND) app, Apple
has just been discussing, discussing, and discussing. They have not
done anything,” Sharma told TOI.</p>
</blockquote>

<p>Sharma is the Chairman of the Telecom Regulatory Authority of India
(<a href="http://www.trai.gov.in/">TRAI</a>), a government organization that, among other things, oversees the
functioning of mobile network carriers in India.</p>

<p>TRAI has published an Android app called <a href="https://play.google.com/store/apps/details?id=trai.gov.in.dnd&amp;hl=en">Do-Not-Disturb</a>
to help curb marketing cold calls and SMS messages. The app is tied to
TRAI’s <a href="http://www.nccptrai.gov.in/">NCPR database</a> of mobile users and their opt-in / opt-out
preferences regarding receiving promotionals calls and SMS messages. A
key feature of the app is helping the user report a promotional call or
SMS they have received that doesn’t comply with their registered
preference.  To implement this feature, the app requires access to the
phone’s call logs and messages. It displays recent calls and messages
that the user can pick from and report a complaint on.</p>

<p>When the Android app was launched last year, TRAI <a href="http://gadgets.ndtv.com/apps/news/trai-launches-dnd-services-app-to-register-pesky-call-complaints-844157">did have plans</a> of
bringing a similar app to iOS as well, but that hasn’t happened so far.
A Public Interest Litigation had been filed in the Delhi High Court
asking for such an app to be made available on the App Store, and was
<a href="http://www.ptinews.com/news/8932791_HC-declines-to-entertain-plea-against-Apple.html">dismissed</a> by the court last month.</p>

<p>There’s no public API in iOS to read call logs or SMS messages. There
are ways to block certain callers and filter certain SMS messages <sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote">1</a></sup>,
but the provided API is restricted because of privacy considerations. To
block callers, apps can provide a block list but have no way to
intercept calls or access the call log. To filter SMS messages, apps can
classify SMS messages from unknown senders as they come, but are not
allowed to keep track of them and use them later on (like showing a list
of messages to choose from).</p>

<h3 id="what-trai-could-do">What TRAI could do</h3>

<p>TRAI could, with the current available API in iOS, write an app that
could be useful in reporting spam calls by including a <a href="https://www.imore.com/sharing-ios-8-explained">share extension</a>
for contacts <sup id="fnref:2" role="doc-noteref"><a href="#fn:2" class="footnote">2</a></sup>.</p>

<p>The user, while viewing the call log on an iPhone, can tap the info
button and then the ‘Share Contact’ button to bring up a share sheet
that could show a TRAI share extension to report complaints.
The share extension would get the phone number from the
shared contact information, but there’s no way to share the date the
spam call was made.  However, there are only three possible options:
‘Today’, ‘Yesterday’ and ‘Two days ago’ (because TRAI requires that the
complaint be filed within 3 days), so it should be okay to ask the user
for that information.</p>

<p>So that would give us a pretty good way to report spam calls.</p>

<p>This share extension method would also work for reporting promotional SMS
messages received from actual phone numbers, but would unfortunately not
work for SMS messages with alphanumeric sender IDs. That means in most
SMS reporting scenarios, this wouldn’t be useful.</p>

<h3 id="what-apple-could-do">What Apple could do</h3>

<p>I think Apple is highly unlikely to create public APIs to access call
logs or messages, but that’s not really needed for an app like this.</p>

<p>Rather, Apple could provide a way to share an SMS through a share sheet,
so a third-party app can get access to all relevant fields of an SMS
message (i.e. body text, sender id and timestamp) that the user
explicitly chose to share with the app. That way, TRAI can create an app
to report errant SMS messages, while Apple can retain their right to not
give apps blanket access to the phone’s SMS data.</p>

<p><strong>Update:</strong> Apple now offers a much more complete solution for reporting
spam calls and SMSes with the <a href="https://developer.apple.com/documentation/sms_and_call_reporting/sms_and_call_spam_reporting">SMS and Call Spam Reporting
API</a>,
which would be perfect for a TRAI iOS app to make use of.</p>

<p>So this is how I think TRAI and Apple can settle this without
compromising either party’s positions, and simultaneously keep Apple’s
privacy-conscious customers happy as well.</p>

<hr />

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1" role="doc-endnote">
      <p>The message filtering capability is part of iOS 11, to be released later this year <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:2" role="doc-endnote">
      <p>With Uniform Type Identifier as “public.vcard” <a href="#fnref:2" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>

        
        
        ]]>
        </description>
    </item>
    
    <item>
        <title>
        
            Apple opens App Accelerator
        
        </title>
        <link>http://roopc.net/posts/2017/apple-opens-app-accelerator/</link>
        <guid>http://roopc.net/posts/2017/apple-opens-app-accelerator</guid>
        <pubDate>Wed, 05 Apr 2017 00:00:00 +0530</pubDate>
        <description>
        <![CDATA[
        <p>Apple has just <a href="http://www.apple.com/in/pr/library/2017/03/Apple-Opens-New-App-Accelerator-Bengaluru.html">opened</a> their <a href="https://developer.apple.com/accelerator/">App Accelerator</a> in Bangalore, a city a
few hours drive away from where I live now. Phil Schiller was in the
city for the occasion.</p>

<p>Foremost, the App Accelerator seems to be a sort of permanent
Apple Tech Talks venue. The first talks started yesterday, and the
schedule for the next few weeks covers mostly introductory topics,
leaning towards iOS (UI Design, Swift, Adaptive UI, Accessibility, i18n,
etc.). All slots for all scheduled presentations were already filled up
when I took a look last Friday (when the news broke). At present, the
talks seem to be only on Tuesdays and Thursdays, so there’s plenty of
room for more. I’d love to see in-depth talks on specific topics (say
Core Data, CloudKit or UIKit Animations). Phil Schiller mentioned that
the App Accelerator is also going to help developers in “learning how
better to market their app on the App Store”, so there could be talks on
that topic as well, which would be very nice.</p>

<p>Apart from the talks, the website says there are going to be hands-on
labs, but no schedule is out yet.</p>

<p>Moreover, the App Accelerator could also serve as a place for Apple to
sit down and talk to some developers of apps it considers important. The
Apple announcement mentions <a href="https://www.practo.com/">Practo</a> and
<a href="http://www.reliancegames.com/">Reliance Games</a>, and it <a href="https://twitter.com/chucksevp/status/847833972491137028">looks
like</a> the <a href="http://www.legendofabhimanyu.com">Legend of
Abhimanyu</a> team visited the App
Accelerator last week.</p>

<p>All in all, this is great news – I’d find the talks and the labs very
useful.</p>

<p>I also think it shows how serious Apple is about a long-term play in the
Indian market. Phil Schiller, when <a href="http://gadgets.ndtv.com/apps/news/phil-schiller-in-india-to-mark-official-opening-of-apples-app-accelerator-in-bengaluru-1675684">talking to NDTV</a> last week, said
“I think what we hope from this accelerator is that we can help the
local market create apps for customers in India that better meet the
needs of our growing customer base here”. There are tons of India
centric apps on Android, but not many on iOS, which is a reflection
of the Indian smartphone market being heavily skewed towards Android.
Getting more India-centric apps would be an important cog in Apple’s
wheel for growing bigger in India.</p>


        
        
        ]]>
        </description>
    </item>
    
 
</channel>
</rss>
