<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>dmytrish</title>
    <link>https://dmytrish.net</link>
    <description>source of some good bits</description>
    <pubDate>Sat, 20 Oct 2018 17:30:00 +0200</pubDate>
    <language>en</language>
    <atom:link href="https://dmytrish.net/rssfeed.xml" rel="self" type="application/rss+xml" />
    
     
    <item>
      <title>pywiki: a Python web app without frameworks</title>
      <link>https://dmytrish.net/en/pywebapp-without-frameworks</link>
      <pubDate>Sat, 20 Oct 2018 17:30:00 +0200</pubDate>
      <guid isPermaLink="true">https://dmytrish.net/en/pywebapp-without-frameworks</guid>
      <category>
        <![CDATA[en]]>
      </category>
      <description>
        <![CDATA[
          <p>A couple of weeks ago I went through <a href="https://golang.org/doc/articles/wiki/">Writing Web Applications in Go</a> and my mind was blown away: I used to think that you need a web framework (at least a very minimal one like Flask) to make web applications (possibly because of my Python background). So I set out to do something similar in Python3 to figure out why its standard library is not enough.</p>

<h2 id="gowiki">gowiki</h2>

<p>Gowiki is an example of a very tiny web application that is already useful: it can show text files (<code class="language-plaintext highlighter-rouge">GET /view/&lt;PAGE&gt;</code>) from <code class="language-plaintext highlighter-rouge">./pages/</code>, edit them using a <code class="language-plaintext highlighter-rouge">&lt;textarea&gt;</code> (<code class="language-plaintext highlighter-rouge">GET /edit/&lt;page&gt;</code>) and save them back (<code class="language-plaintext highlighter-rouge">POST /save/&lt;PAGE&gt;</code>).</p>

<h2 id="httpserver-the-basics">http.server: the basics</h2>

<p>First of all, we need a web server. I use <code class="language-plaintext highlighter-rouge">python3 -m http.server</code> pretty often to serve a directory over http quickly, which looks promising to extend.</p>

<p>The <a href="https://docs.python.org/3/library/http.server.html">documentation page for http.server</a> greets us with a warning:</p>

<blockquote>
  <p>http.server is meant for demo purposes and does not implement the stringent security checks needed of real HTTP server. We do not recommend using this module directly in production.</p>
</blockquote>

<p>Fine, that must be one of the reasons why nobody uses it. Let’s proceed at our own risk.</p>

<p>Let’s run the initial example:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="n">http.server</span> <span class="k">as</span> <span class="n">http</span>

<span class="n">address</span> <span class="o">=</span> <span class="p">(</span><span class="sh">''</span><span class="p">,</span> <span class="mi">8000</span><span class="p">)</span>
<span class="k">with</span> <span class="n">http</span><span class="p">.</span><span class="nc">HTTPServer</span><span class="p">(</span><span class="n">address</span><span class="p">,</span> <span class="n">SimpleHTTPRequestHandler</span><span class="p">)</span> <span class="k">as</span> <span class="n">httpd</span><span class="p">:</span>
    <span class="nf">print</span><span class="p">(</span><span class="sh">'</span><span class="s">Listening on %s:%d</span><span class="sh">'</span> <span class="o">%</span> <span class="n">address</span><span class="p">)</span>
    <span class="k">try</span><span class="p">:</span>
        <span class="n">httpd</span><span class="p">.</span><span class="nf">serve_forever</span><span class="p">()</span>
    <span class="k">except</span> <span class="nb">KeyboardInterrupt</span><span class="p">:</span>
        <span class="k">pass</span>
</code></pre></div></div>

<h2 id="extending-the-httpserver">Extending the http.server</h2>

<p>The documentation looked pretty massive and intimidating at first, and after some initial reading I had a lot of questions:</p>

<ul>
  <li>should I extend <code class="language-plaintext highlighter-rouge">HTTPServer</code>, <code class="language-plaintext highlighter-rouge">BaseHTTPRequestHandler</code>, one of its subclasses? Turns out that <code class="language-plaintext highlighter-rouge">HTTPServer</code> is the “transport” part of the application (a subclass of <code class="language-plaintext highlighter-rouge">TCPServer</code>) and it takes a request handler (subclassed from <code class="language-plaintext highlighter-rouge">BaseHTTPRequestHandler</code>) as a mix-in to actually handle the requests; <code class="language-plaintext highlighter-rouge">SimpleHTTPRequestHandler</code> is a subclass of <code class="language-plaintext highlighter-rouge">BaseHTTPRequestHandler</code> that maps requests to files under the current directory; <code class="language-plaintext highlighter-rouge">CGIHTTPRequestHandler</code> extends <code class="language-plaintext highlighter-rouge">SimpleHTTPRequestHandler</code> with the ability to run CGI scripts from <code class="language-plaintext highlighter-rouge">./cgi-bin</code> (in the very primitive CGI way: running a process for each request).</li>
  <li>are there any request routing mechanism in the standard library? Nope, none: you need to handle routing manually, unlike Go;</li>
  <li>where do I get the requested path (do I get any parameters to <code class="language-plaintext highlighter-rouge">do_GET</code>)? I needed to check with the source code and debug it to understand that <code class="language-plaintext highlighter-rouge">do_GET</code> relies on the state of its object;</li>
  <li>what is <code class="language-plaintext highlighter-rouge">send_response()</code>, <code class="language-plaintext highlighter-rouge">send_response_only()</code>, <code class="language-plaintext highlighter-rouge">send_error()</code>, <code class="language-plaintext highlighter-rouge">end_headers()</code>, what is the protocol to call them? Which of those are internal methods and which can I call? I needed to read the <a href="https://github.com/python/cpython/blob/3.7/Lib/http/server.py">source code of <code class="language-plaintext highlighter-rouge">http.server</code></a> to understand what they do exactly;</li>
  <li>how do I write the response? I wrote some Python FastCGI script some time ago, so I knew about <code class="language-plaintext highlighter-rouge">wfile</code> file descriptors that can be used for this: indeed, there’s <code class="language-plaintext highlighter-rouge">self.rfile</code>and <code class="language-plaintext highlighter-rouge">self.wfile</code>;</li>
</ul>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="n">shutil</span>
<span class="kn">from</span> <span class="n">pathlib</span> <span class="kn">import</span> <span class="n">Path</span>
<span class="kn">from</span> <span class="n">http</span> <span class="kn">import</span> <span class="n">HTTPStatus</span> <span class="k">as</span> <span class="n">status</span>

<span class="n">pages_dir</span> <span class="o">=</span> <span class="nc">Path</span><span class="p">(</span><span class="sh">'</span><span class="s">./pages/</span><span class="sh">'</span><span class="p">)</span>

<span class="k">class</span> <span class="nc">RequestHandlers</span><span class="p">(</span><span class="n">http</span><span class="p">.</span><span class="n">BaseHTTPRequestHandler</span><span class="p">):</span>
    <span class="k">def</span> <span class="nf">do_GET</span><span class="p">(</span><span class="n">self</span><span class="p">):</span>
        <span class="k">if</span> <span class="n">self</span><span class="p">.</span><span class="n">path</span><span class="p">.</span><span class="nf">startswith</span><span class="p">(</span><span class="sh">'</span><span class="s">/view/</span><span class="sh">'</span><span class="p">):</span>
            <span class="k">return</span> <span class="n">self</span><span class="p">.</span><span class="nf">get_view</span><span class="p">()</span>
        <span class="k">return</span> <span class="n">self</span><span class="p">.</span><span class="nf">send_error</span><span class="p">(</span><span class="n">status</span><span class="p">.</span><span class="n">NOT_FOUND</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">respond_ok</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="n">body</span><span class="p">):</span>
        <span class="n">self</span><span class="p">.</span><span class="nf">send_response</span><span class="p">(</span><span class="n">status</span><span class="p">.</span><span class="n">OK</span><span class="p">)</span>
        <span class="n">self</span><span class="p">.</span><span class="nf">end_headers</span><span class="p">()</span>

        <span class="n">shutil</span><span class="p">.</span><span class="nf">copyfileobj</span><span class="p">(</span><span class="n">body</span><span class="p">,</span> <span class="n">self</span><span class="p">.</span><span class="n">wfile</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">get_view</span><span class="p">(</span><span class="n">self</span><span class="p">):</span>
        <span class="n">title</span> <span class="o">=</span> <span class="n">self</span><span class="p">.</span><span class="n">path</span><span class="p">[</span><span class="nf">len</span><span class="p">(</span><span class="sh">'</span><span class="s">/view/</span><span class="sh">'</span><span class="p">):]</span>

        <span class="n">p</span> <span class="o">=</span> <span class="n">pages_dir</span> <span class="o">/</span> <span class="p">(</span><span class="n">title</span> <span class="o">+</span> <span class="sh">'</span><span class="s">.txt</span><span class="sh">'</span><span class="p">)</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="n">p</span><span class="p">.</span><span class="nf">exists</span><span class="p">():</span>
            <span class="k">return</span> <span class="n">self</span><span class="p">.</span><span class="nf">send_error</span><span class="p">(</span><span class="n">status</span><span class="p">.</span><span class="n">NOT_FOUND</span><span class="p">)</span>

        <span class="k">with</span> <span class="n">p</span><span class="p">.</span><span class="nf">open</span><span class="p">(</span><span class="sh">'</span><span class="s">rb</span><span class="sh">'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
            <span class="n">self</span><span class="p">.</span><span class="nf">respond_ok</span><span class="p">(</span><span class="n">f</span><span class="p">)</span>
</code></pre></div></div>

<p>Plug it in <code class="language-plaintext highlighter-rouge">http.HTTPServer(address, RequestHandlers)</code> and we are ready to go.</p>

<h2 id="serving-html">Serving HTML</h2>

<p>Now let’s serve html instead of plain text. At first, I had hard-coded html snippets in the source code using multi-line string literals and inserting values using formatting, but soon I needed to move templates into separate files and to do more advanced templating using <code class="language-plaintext highlighter-rouge">string.Template</code>:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="bp">...</span>
<span class="kn">import</span> <span class="n">io</span>
<span class="kn">import</span> <span class="n">string</span>

<span class="n">templ_dir</span> <span class="o">=</span> <span class="nc">Path</span><span class="p">(</span><span class="sh">'</span><span class="s">./tmpl/</span><span class="sh">'</span><span class="p">)</span>

<span class="k">class</span> <span class="nc">RequestHandlers</span><span class="p">(</span><span class="n">http</span><span class="p">.</span><span class="n">BaseHTTPRequestHandler</span><span class="p">):</span>
<span class="c1">#   ...
</span>    <span class="k">def</span> <span class="nf">respond_ok</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="n">body</span><span class="p">,</span> <span class="n">mime</span><span class="o">=</span><span class="sh">'</span><span class="s">plain</span><span class="sh">'</span><span class="p">):</span>
        <span class="k">if</span> <span class="nf">isinstance</span><span class="p">(</span><span class="n">body</span><span class="p">,</span> <span class="nb">str</span><span class="p">):</span>
            <span class="n">body</span> <span class="o">=</span> <span class="n">body</span><span class="p">.</span><span class="nf">encode</span><span class="p">(</span><span class="sh">'</span><span class="s">utf8</span><span class="sh">'</span><span class="p">)</span>
        <span class="k">if</span> <span class="nf">isinstance</span><span class="p">(</span><span class="n">body</span><span class="p">,</span> <span class="nb">bytes</span><span class="p">):</span>
            <span class="n">body</span> <span class="o">=</span> <span class="n">io</span><span class="p">.</span><span class="nc">BytesIO</span><span class="p">(</span><span class="n">body</span><span class="p">)</span>

        <span class="n">self</span><span class="p">.</span><span class="nf">send_response</span><span class="p">(</span><span class="n">status</span><span class="p">.</span><span class="n">OK</span><span class="p">)</span>
        <span class="n">self</span><span class="p">.</span><span class="nf">send_header</span><span class="p">(</span><span class="sh">'</span><span class="s">Content-Type</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">text/%s; charset=utf8</span><span class="sh">'</span> <span class="o">%</span> <span class="n">mime</span><span class="p">)</span>
        <span class="n">self</span><span class="p">.</span><span class="nf">end_headers</span><span class="p">()</span>
        
        <span class="n">shutil</span><span class="p">.</span><span class="nf">copyfileobj</span><span class="p">(</span><span class="n">body</span><span class="p">,</span> <span class="n">self</span><span class="p">.</span><span class="n">wfile</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">format_tmpl</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="n">page</span><span class="p">,</span> <span class="o">**</span><span class="n">values</span><span class="p">):</span>
        <span class="n">template</span> <span class="o">=</span> <span class="nf">open</span><span class="p">(</span><span class="n">templ_dir</span> <span class="o">/</span> <span class="n">tmpl</span><span class="p">).</span><span class="nf">read</span><span class="p">()</span>
        <span class="n">t</span> <span class="o">=</span> <span class="n">string</span><span class="p">.</span><span class="nc">Template</span><span class="p">(</span><span class="n">template</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">t</span><span class="p">.</span><span class="nf">substitute</span><span class="p">(</span><span class="o">**</span><span class="n">values</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">get_view</span><span class="p">(</span><span class="n">self</span><span class="p">):</span>
        <span class="n">title</span> <span class="o">=</span> <span class="n">self</span><span class="p">.</span><span class="n">path</span><span class="p">[</span><span class="nf">len</span><span class="p">(</span><span class="sh">'</span><span class="s">/view/</span><span class="sh">'</span><span class="p">):]</span>

        <span class="n">p</span> <span class="o">=</span> <span class="n">pages_dir</span> <span class="o">/</span> <span class="p">(</span><span class="n">title</span> <span class="o">+</span> <span class="sh">'</span><span class="s">.txt</span><span class="sh">'</span><span class="p">)</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="n">p</span><span class="p">.</span><span class="nf">exists</span><span class="p">():</span>
            <span class="k">return</span> <span class="n">self</span><span class="p">.</span><span class="nf">send_error</span><span class="p">(</span><span class="n">status</span><span class="p">.</span><span class="n">NOT_FOUND</span><span class="p">)</span>

        <span class="k">with</span> <span class="n">p</span><span class="p">.</span><span class="nf">open</span><span class="p">(</span><span class="sh">'</span><span class="s">rb</span><span class="sh">'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
            <span class="n">body</span> <span class="o">=</span> <span class="n">f</span><span class="p">.</span><span class="nf">read</span><span class="p">().</span><span class="nf">decode</span><span class="p">(</span><span class="sh">'</span><span class="s">utf8</span><span class="sh">'</span><span class="p">)</span>
            <span class="n">page</span> <span class="o">=</span> <span class="n">self</span><span class="p">.</span><span class="nf">format_tmpl</span><span class="p">(</span><span class="sh">'</span><span class="s">view.html</span><span class="sh">'</span><span class="p">,</span> <span class="n">title</span><span class="o">=</span><span class="n">title</span><span class="p">,</span> <span class="n">body</span><span class="o">=</span><span class="n">body</span><span class="p">)</span>

            <span class="n">self</span><span class="p">.</span><span class="nf">respond_ok</span><span class="p">(</span><span class="n">page</span><span class="p">,</span> <span class="n">text</span><span class="o">=</span><span class="sh">'</span><span class="s">html</span><span class="sh">'</span><span class="p">)</span>
</code></pre></div></div>

<p>and now we have a new file, <code class="language-plaintext highlighter-rouge">tmpl/view.html</code>:</p>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;h1&gt;</span>${title}<span class="nt">&lt;/h1&gt;</span>
<span class="nt">&lt;ul</span> <span class="na">id=</span><span class="s">"menu"</span><span class="nt">&gt;</span>
<span class="nt">&lt;li&gt;</span>[<span class="nt">&lt;a</span> <span class="na">href=</span><span class="s">"/"</span><span class="nt">&gt;</span>main<span class="nt">&lt;/a&gt;</span>]<span class="nt">&lt;/li&gt;</span>
<span class="nt">&lt;li&gt;</span>[<span class="nt">&lt;a</span> <span class="na">href=</span><span class="s">"/edit/${title}"</span><span class="nt">&gt;</span>edit<span class="nt">&lt;/a&gt;</span>]<span class="nt">&lt;/li&gt;</span>
<span class="nt">&lt;/ul&gt;</span>
<span class="nt">&lt;hr&gt;</span>
<span class="nt">&lt;div&gt;&lt;pre&gt;</span>${body}<span class="nt">&lt;/pre&gt;&lt;/div&gt;</span>
<span class="nt">&lt;link</span> <span class="na">rel=</span><span class="s">"stylesheet"</span> <span class="na">href=</span><span class="s">"/file/style.css"</span><span class="nt">&gt;</span>
</code></pre></div></div>

<p>Wow, that’s a rather low-level trickery going on now in <code class="language-plaintext highlighter-rouge">respond_ok()</code>, but it will pay off later, when we need to serve files.</p>

<h2 id="editing">Editing…</h2>

<p>The frontend part is a matter of a simple html page, <code class="language-plaintext highlighter-rouge">tmpl/edit.html</code>:</p>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;h1&gt;</span>${title}<span class="nt">&lt;h1&gt;</span>
<span class="nt">&lt;ul</span> <span class="na">id=</span><span class="s">"menu"</span><span class="nt">&gt;&lt;/ul&gt;</span>
<span class="nt">&lt;hr&gt;</span>
<span class="nt">&lt;div&gt;</span>
<span class="nt">&lt;form</span> <span class="na">action=</span><span class="s">"/save/${title}"</span> <span class="na">method=</span><span class="s">"POST"</span><span class="nt">&gt;</span>
<span class="nt">&lt;textarea</span> <span class="na">cols=</span><span class="s">"80"</span> <span class="na">rows=</span><span class="s">"20"</span> <span class="na">autofocus</span> <span class="na">name=</span><span class="s">"body"</span><span class="nt">&gt;</span>${body}<span class="nt">&lt;/textarea&gt;&lt;br&gt;</span>
<span class="nt">&lt;input</span> <span class="na">type=</span><span class="s">"submit"</span> <span class="na">value=</span><span class="s">"Save"</span><span class="nt">&gt;</span>
<span class="nt">&lt;/form&gt;</span>
<span class="nt">&lt;/div&gt;</span>
</code></pre></div></div>

<p>and serving it is easy:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">RequestHandlers</span><span class="p">(</span><span class="n">http</span><span class="p">.</span><span class="n">BaseHTTPRequestHandler</span><span class="p">):</span>
<span class="c1">#   ...
</span>    <span class="k">def</span> <span class="nf">do_GET</span><span class="p">(</span><span class="n">self</span><span class="p">):</span>
        <span class="k">if</span> <span class="n">self</span><span class="p">.</span><span class="n">path</span><span class="p">.</span><span class="nf">startswith</span><span class="p">(</span><span class="sh">'</span><span class="s">/view/</span><span class="sh">'</span><span class="p">):</span>
            <span class="k">return</span> <span class="n">self</span><span class="p">.</span><span class="nf">get_view</span><span class="p">()</span>
        <span class="k">if</span> <span class="n">self</span><span class="p">.</span><span class="n">path</span><span class="p">.</span><span class="nf">startswith</span><span class="p">(</span><span class="sh">'</span><span class="s">/edit/</span><span class="sh">'</span><span class="p">):</span>
            <span class="k">return</span> <span class="n">self</span><span class="p">.</span><span class="nf">get_edit</span><span class="p">()</span>
        <span class="k">return</span> <span class="n">self</span><span class="p">.</span><span class="nf">send_error</span><span class="p">(</span><span class="n">status</span><span class="p">.</span><span class="n">NOT_FOUND</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">get_edit</span><span class="p">(</span><span class="n">self</span><span class="p">):</span>
        <span class="n">title</span> <span class="o">=</span> <span class="n">self</span><span class="p">.</span><span class="n">path</span><span class="p">[</span><span class="nf">len</span><span class="p">(</span><span class="sh">"</span><span class="s">/edit/</span><span class="sh">"</span><span class="p">):]</span>

        <span class="n">body</span> <span class="o">=</span> <span class="sh">''</span>
        <span class="n">p</span> <span class="o">=</span> <span class="n">pages_dir</span> <span class="o">/</span> <span class="p">(</span><span class="n">title</span> <span class="o">+</span> <span class="sh">'</span><span class="s">.txt</span><span class="sh">'</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">p</span><span class="p">.</span><span class="nf">exists</span><span class="p">():</span>
            <span class="n">body</span> <span class="o">=</span> <span class="n">p</span><span class="p">.</span><span class="nf">open</span><span class="p">().</span><span class="nf">read</span><span class="p">()</span>

        <span class="n">page</span> <span class="o">=</span> <span class="n">self</span><span class="p">.</span><span class="nf">format_tmpl</span><span class="p">(</span><span class="sh">'</span><span class="s">edit.html</span><span class="sh">'</span><span class="p">,</span> <span class="n">title</span><span class="o">=</span><span class="n">title</span><span class="p">,</span> <span class="n">body</span><span class="o">=</span><span class="n">body</span><span class="p">)</span>

        <span class="n">self</span><span class="p">.</span><span class="nf">respond_ok</span><span class="p">(</span><span class="n">page</span><span class="p">,</span> <span class="n">text</span><span class="o">=</span><span class="sh">'</span><span class="s">html</span><span class="sh">'</span><span class="p">)</span>
</code></pre></div></div>

<h2 id="and-posting">…and POSTing</h2>

<p>Now, how do I do <code class="language-plaintext highlighter-rouge">POST</code> requests? The shocking answer is that <code class="language-plaintext highlighter-rouge">http.server</code> only provides <code class="language-plaintext highlighter-rouge">do_POST</code> and leaves you on your own. You need to read the sent form yourself, parse it (thanks to the standard library, there’s <code class="language-plaintext highlighter-rouge">urllib.parse.parse_qs</code>) and save it.</p>

<p>I spent some time debugging why <code class="language-plaintext highlighter-rouge">self.rfile.read()</code> just hangs the app: turns out, you need to read <code class="language-plaintext highlighter-rouge">Content-Length</code> and only read it from <code class="language-plaintext highlighter-rouge">self.rfile</code> (HTTP/1.1 can reuse connections for new requests).</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">RequestHandlers</span><span class="p">(</span><span class="n">http</span><span class="p">.</span><span class="n">BaseHTTPRequestHandler</span><span class="p">):</span>
<span class="c1">#   ...
</span>    <span class="k">def</span> <span class="nf">_is_form</span><span class="p">(</span><span class="n">self</span><span class="p">):</span>
        <span class="sh">"""</span><span class="s"> checks is the request is a form sent from a page </span><span class="sh">"""</span>
        <span class="n">formmime</span> <span class="o">=</span> <span class="sh">'</span><span class="s">application/x-www-form-urlencoded</span><span class="sh">'</span>
        <span class="k">return</span> <span class="n">self</span><span class="p">.</span><span class="n">headers</span><span class="p">.</span><span class="nf">get</span><span class="p">(</span><span class="sh">'</span><span class="s">content-type</span><span class="sh">'</span><span class="p">)</span> <span class="o">==</span> <span class="n">formmime</span>

    <span class="k">def</span> <span class="nf">_parse_form</span><span class="p">(</span><span class="n">self</span><span class="p">):</span>
        <span class="sh">"""</span><span class="s"> parse and save form into `self.form` </span><span class="sh">"""</span>
        <span class="n">size</span> <span class="o">=</span> <span class="nf">int</span><span class="p">(</span><span class="n">self</span><span class="p">.</span><span class="n">headers</span><span class="p">[</span><span class="sh">'</span><span class="s">content-length</span><span class="sh">'</span><span class="p">])</span>
        <span class="n">form</span> <span class="o">=</span> <span class="n">self</span><span class="p">.</span><span class="n">rfile</span><span class="p">.</span><span class="nf">read</span><span class="p">(</span><span class="n">size</span><span class="p">)</span>
        <span class="n">form</span> <span class="o">=</span> <span class="n">form</span><span class="p">.</span><span class="nf">decode</span><span class="p">(</span><span class="sh">'</span><span class="s">ascii</span><span class="sh">'</span><span class="p">)</span>
        <span class="n">form</span> <span class="o">=</span> <span class="nf">parse_qs</span><span class="p">(</span><span class="n">form</span><span class="p">)</span>
        <span class="n">self</span><span class="p">.</span><span class="n">form</span> <span class="o">=</span> <span class="n">form</span>

    <span class="k">def</span> <span class="nf">form_value</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="n">key</span><span class="p">):</span>
        <span class="sh">"""</span><span class="s"> get a form parameter by key or None </span><span class="sh">"""</span>
        <span class="k">return</span> <span class="n">self</span><span class="p">.</span><span class="n">form</span><span class="p">.</span><span class="nf">get</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="p">[</span><span class="bp">None</span><span class="p">])[</span><span class="mi">0</span><span class="p">]</span>
</code></pre></div></div>

<p>– and now we are ready to read form parameters!</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    <span class="k">def</span> <span class="nf">do_POST</span><span class="p">(</span><span class="n">self</span><span class="p">):</span>
        <span class="k">if</span> <span class="n">self</span><span class="p">.</span><span class="nf">_is_form</span><span class="p">():</span>
            <span class="n">self</span><span class="p">.</span><span class="nf">_parse_form</span><span class="p">()</span>

        <span class="k">if</span> <span class="n">self</span><span class="p">.</span><span class="n">path</span><span class="p">.</span><span class="nf">startswith</span><span class="p">(</span><span class="sh">'</span><span class="s">/save/</span><span class="sh">'</span><span class="p">):</span>
            <span class="k">return</span> <span class="n">self</span><span class="p">.</span><span class="nf">post_save</span><span class="p">()</span>

        <span class="k">return</span> <span class="n">self</span><span class="p">.</span><span class="nf">send_error</span><span class="p">(</span><span class="n">status</span><span class="p">.</span><span class="n">NOT_FOUND</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">post_save</span><span class="p">(</span><span class="n">self</span><span class="p">):</span>
        <span class="n">title</span> <span class="o">=</span> <span class="n">self</span><span class="p">.</span><span class="n">path</span><span class="p">[</span><span class="nf">len</span><span class="p">(</span><span class="sh">"</span><span class="s">/save/</span><span class="sh">"</span><span class="p">):]</span>
        <span class="n">body</span> <span class="o">=</span> <span class="n">self</span><span class="p">.</span><span class="nf">form_value</span><span class="p">(</span><span class="sh">'</span><span class="s">body</span><span class="sh">'</span><span class="p">)</span>

        <span class="n">p</span> <span class="o">=</span> <span class="n">pages_dir</span> <span class="o">/</span> <span class="p">(</span><span class="n">title</span> <span class="o">+</span> <span class="sh">'</span><span class="s">.txt</span><span class="sh">'</span><span class="p">)</span>
        <span class="k">with</span> <span class="n">p</span><span class="p">.</span><span class="nf">open</span><span class="p">(</span><span class="sh">'</span><span class="s">w</span><span class="sh">'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
            <span class="n">f</span><span class="p">.</span><span class="nf">write</span><span class="p">(</span><span class="n">body</span><span class="p">)</span>

        <span class="n">self</span><span class="p">.</span><span class="nf">respond_redirect</span><span class="p">(</span><span class="sh">'</span><span class="s">/view/</span><span class="sh">'</span> <span class="o">+</span> <span class="n">title</span><span class="p">)</span>
</code></pre></div></div>

<p>Redirecting requires reinventing the wheel again:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    <span class="k">def</span> <span class="nf">respond_redirect</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="n">url</span><span class="p">):</span>
        <span class="n">self</span><span class="p">.</span><span class="nf">send_response</span><span class="p">(</span><span class="n">status</span><span class="p">.</span><span class="n">FOUND</span><span class="p">)</span>
        <span class="n">self</span><span class="p">.</span><span class="nf">send_header</span><span class="p">(</span><span class="sh">'</span><span class="s">Location</span><span class="sh">'</span><span class="p">,</span> <span class="n">url</span><span class="p">)</span>
        <span class="n">self</span><span class="p">.</span><span class="nf">end_headers</span><span class="p">()</span>
</code></pre></div></div>

<p>Now we can view, create and edit pages.</p>

<h2 id="main-page">Main page</h2>

<p>Adding the index page is very straightforward now. The only small problem is that there are no loops in <code class="language-plaintext highlighter-rouge">string.Template</code>, so the html representation for the list of pages must be built in Python:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    <span class="k">def</span> <span class="nf">get_main</span><span class="p">(</span><span class="n">self</span><span class="p">):</span>
        <span class="n">pages</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">pages_dir</span><span class="p">.</span><span class="nf">iterdir</span><span class="p">():</span>
            <span class="k">if</span> <span class="n">p</span><span class="p">.</span><span class="n">suffix</span> <span class="o">==</span> <span class="sh">'</span><span class="s">.txt</span><span class="sh">'</span><span class="p">:</span>
                <span class="n">pages</span><span class="p">.</span><span class="nf">append</span><span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="n">stem</span><span class="p">)</span>

        <span class="n">pagelist</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="k">for</span> <span class="n">page</span> <span class="ow">in</span> <span class="n">pages</span><span class="p">:</span>
            <span class="n">pagelist</span><span class="p">.</span><span class="nf">append</span><span class="p">(</span><span class="sa">f</span><span class="sh">'</span><span class="s">&lt;li&gt;&lt;a href=</span><span class="sh">"</span><span class="s">/view/</span><span class="si">{</span><span class="n">page</span><span class="si">}</span><span class="sh">"</span><span class="s">&gt;</span><span class="si">{</span><span class="n">page</span><span class="si">}</span><span class="s">&lt;/a&gt;&lt;/li&gt;</span><span class="sh">'</span><span class="p">)</span>
        <span class="n">pagelist</span> <span class="o">=</span> <span class="sh">'</span><span class="se">\n</span><span class="sh">'</span><span class="p">.</span><span class="nf">join</span><span class="p">(</span><span class="n">pagelist</span><span class="p">)</span>

        <span class="n">body</span> <span class="o">=</span> <span class="n">self</span><span class="p">.</span><span class="nf">format_tmpl</span><span class="p">(</span><span class="sh">'</span><span class="s">main.html</span><span class="sh">'</span><span class="p">,</span> <span class="n">pagelist</span><span class="o">=</span><span class="n">pagelist</span><span class="p">)</span>
        <span class="n">self</span><span class="p">.</span><span class="nf">respond_ok</span><span class="p">(</span><span class="n">body</span><span class="p">,</span> <span class="n">text</span><span class="o">=</span><span class="sh">'</span><span class="s">html</span><span class="sh">'</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">post_goto</span><span class="p">(</span><span class="n">self</span><span class="p">):</span>
        <span class="n">page</span> <span class="o">=</span> <span class="n">self</span><span class="p">.</span><span class="nf">form_value</span><span class="p">(</span><span class="sh">'</span><span class="s">page</span><span class="sh">'</span><span class="p">)</span>
        <span class="n">self</span><span class="p">.</span><span class="nf">respond_redirect</span><span class="p">(</span><span class="sh">"</span><span class="s">/edit/</span><span class="sh">"</span> <span class="o">+</span> <span class="n">page</span><span class="p">)</span>
</code></pre></div></div>

<p>– and don’t forget to add <code class="language-plaintext highlighter-rouge">get_main</code> to <code class="language-plaintext highlighter-rouge">do_GET</code> and <code class="language-plaintext highlighter-rouge">post_goto</code> to <code class="language-plaintext highlighter-rouge">do_POST</code>! This definitely could be automated using <code class="language-plaintext highlighter-rouge">getattr</code> and dynamic method calls, but I am a little wary of calling code dynamically based on external requests.</p>

<p><code class="language-plaintext highlighter-rouge">main.html</code> is:</p>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;h1&gt;</span>pywiki<span class="nt">&lt;/h1&gt;</span>
<span class="nt">&lt;hr&gt;</span>
<span class="nt">&lt;form</span> <span class="na">action=</span><span class="s">"/goto"</span> <span class="na">method=</span><span class="s">"POST"</span><span class="nt">&gt;</span>
<span class="nt">&lt;input</span> <span class="na">type=</span><span class="s">"text"</span> <span class="na">name=</span><span class="s">"page"</span> <span class="na">required</span> <span class="na">autofocus</span><span class="nt">&gt;</span>
<span class="nt">&lt;input</span> <span class="na">type=</span><span class="s">"submit"</span> <span class="na">value=</span><span class="s">"Go"</span><span class="nt">&gt;</span>
<span class="nt">&lt;/form&gt;</span>
<span class="nt">&lt;ul&gt;</span>
${pagelist}
<span class="nt">&lt;/ul&gt;</span>
</code></pre></div></div>

<h2 id="serving-files">Serving files</h2>

<p>What about serving files, e.g. adding a bit of CSS through <code class="language-plaintext highlighter-rouge">/file/style.css</code>? I could just fall back onto <code class="language-plaintext highlighter-rouge">SimpleHTTPRequestHandler</code> and use its <code class="language-plaintext highlighter-rouge">do_GET</code>, but let’s reinvent this too:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">files_dir</span> <span class="o">=</span> <span class="nc">Path</span><span class="p">(</span><span class="sh">'</span><span class="s">./file/</span><span class="sh">'</span><span class="p">)</span>

<span class="k">class</span> <span class="nc">RequestHandlers</span><span class="p">(</span><span class="n">http</span><span class="p">.</span><span class="n">BaseHTTPRequestHandler</span><span class="p">):</span>
<span class="c1">#   ...
</span>
    <span class="k">def</span> <span class="nf">get_file</span><span class="p">(</span><span class="n">self</span><span class="p">):</span>
        <span class="sh">"""</span><span class="s"> just serve files from ./file/ </span><span class="sh">"""</span>
        <span class="n">fname</span> <span class="o">=</span> <span class="n">self</span><span class="p">.</span><span class="n">path</span><span class="p">[</span><span class="nf">len</span><span class="p">(</span><span class="sh">"</span><span class="s">/file/</span><span class="sh">"</span><span class="p">):]</span>
        <span class="k">if</span> <span class="sh">'</span><span class="s">/</span><span class="sh">'</span> <span class="ow">in</span> <span class="n">fname</span><span class="p">:</span>
            <span class="k">return</span> <span class="n">self</span><span class="p">.</span><span class="nf">send_error</span><span class="p">(</span><span class="n">status</span><span class="p">.</span><span class="n">BAD_REQUEST</span><span class="p">)</span>

        <span class="n">fpath</span> <span class="o">=</span> <span class="n">files_dir</span> <span class="o">/</span> <span class="n">fname</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="n">fpath</span><span class="p">.</span><span class="nf">exists</span><span class="p">():</span>
            <span class="k">return</span> <span class="n">self</span><span class="p">.</span><span class="nf">send_error</span><span class="p">(</span><span class="n">status</span><span class="p">.</span><span class="n">NOT_FOUND</span><span class="p">)</span>

        <span class="k">with</span> <span class="n">fpath</span><span class="p">.</span><span class="nf">open</span><span class="p">(</span><span class="sh">'</span><span class="s">rb</span><span class="sh">'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
            <span class="n">contenttype</span> <span class="o">=</span> <span class="sh">'</span><span class="s">application/octet-stream</span><span class="sh">'</span>
            <span class="k">if</span> <span class="n">fname</span><span class="p">.</span><span class="nf">endswith</span><span class="p">(</span><span class="sh">'</span><span class="s">.css</span><span class="sh">'</span><span class="p">):</span>
                <span class="n">contenttype</span> <span class="o">=</span> <span class="sh">'</span><span class="s">text/css</span><span class="sh">'</span>

            <span class="n">self</span><span class="p">.</span><span class="nf">respond_ok</span><span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="p">{</span><span class="sh">'</span><span class="s">Content-Type</span><span class="sh">'</span><span class="p">:</span> <span class="n">contenttype</span><span class="p">})</span>
</code></pre></div></div>

<p>A nice side-effect here is that it’s not necessary to read file to memory at all, <code class="language-plaintext highlighter-rouge">shutil.copyfileobj()</code> can take care of this through <a href="http://man7.org/linux/man-pages/man2/sendfile.2.html">sendfile(2)</a>.</p>

<h2 id="general-ergonomics-compared-to-go">General ergonomics compared to Go</h2>

<ul>
  <li>absence of any complex examples in the documentation. This might be intentional: to discourage production usage, which is assumed by default in Go.</li>
  <li>massive documentation with several big classes with directly accessible state; you need to read through and consult the source code to understand what is going on: what methods to call, in what sequence, what methods are low-level and high-level, it was not clear immediately how to read the request body and write the response (which is immediately obvious in Go: <code class="language-plaintext highlighter-rouge">http.Request</code> and <code class="language-plaintext highlighter-rouge">http.ResponseWriter</code> as parameters to a handler);</li>
  <li>not a very complex, but non-trivial hierarchy of classes which are used to access complex state and run custom methods (instead of clean and isolated callbacks in Go with clear inputs and outputs);</li>
  <li>a very bare HTTP implementation, without essentials like parsing form fields (Go’s <code class="language-plaintext highlighter-rouge">http.Request.FormValue()</code>) and redirects (just <code class="language-plaintext highlighter-rouge">http.Redirect()</code> in Go);</li>
  <li>no html templating with loops, no html character escaping, compared to <code class="language-plaintext highlighter-rouge">http/template</code> in Go;</li>
</ul>

<h2 id="conclusion">Conclusion</h2>

<p>The source code of pywiki may be found here: <a href="https://git.dmytrish.net/lang-learn/pywiki">https://git.dmytrish.net/lang-learn/pywiki</a>.</p>

<p>I feel like I have written my <strong>own buggy and incomplete micro webframework</strong> at this point: low-level http manipulation, absence of good url routing, manual parsing, etc; <code class="language-plaintext highlighter-rouge">http.server</code> is clearly not supposed to be extended further and should be a finished demo of what can be done using other parts of the standard library.</p>

<p>There is <strong>no concurrency</strong> here: everything is blocking (although e.g. Flask works the same way); even though Python has <code class="language-plaintext highlighter-rouge">asyncio</code> now, the standard library does not ship an asyncio http server, which is a shame. Go gives you production-grade concurrency for free.</p>

<p>I haven’t built any <strong>security</strong> checks into my code, which might be disastrous.</p>

<p>So: you <em>can</em> write primitive web-applications using only the Python standard library. <em>Should</em> you do it? Judge for yourself.</p>

        ]]>
      </description>
    </item>
    
     
    <item>
      <title>My Elisp.js is v0.1.0 now!</title>
      <link>https://dmytrish.net/en/elispjs-010</link>
      <pubDate>Sun, 19 Aug 2018 21:50:00 +0200</pubDate>
      <guid isPermaLink="true">https://dmytrish.net/en/elispjs-010</guid>
      <category>
        <![CDATA[en]]>
      </category>
      <description>
        <![CDATA[
          <p>Recently my <a href="https://github.com/EarlGray/elisp.js">new hobby project, elisp.js,</a> reached version <code class="language-plaintext highlighter-rouge">0.1.0</code>! It is a basic Elisp environment that runs of top of Javascript and runs code through transpiling it into Javascript dynamically and <code class="language-plaintext highlighter-rouge">eval</code>uating the intermediate JS code.</p>

<p>I consider the core of the implementation reasonably self-sufficient by now: lambdas and macros work reasonably well (with proper dynamic scoping and Lisp-2 namespace separation, unlike <a href="https://github.com/samsonjs/elisp.js/">Samsonjs’s elisp.js</a> from 2009!), code may be <code class="language-plaintext highlighter-rouge">eval</code>ed, the most used types are implemented (symbols, lists, strings, numbers, bools, vectors).</p>

<p>On the other hand, the implementation is still very bare, lacks many essential types (e.g. hashtables) and even language-level functionality (e.g. <code class="language-plaintext highlighter-rouge">&amp;optional</code> and <code class="language-plaintext highlighter-rouge">&amp;rest</code> arguments in functions), still wants for proper error handling and debugging and it completely lacks any chrome around the core primitives (even <code class="language-plaintext highlighter-rouge">defmacro</code> and <code class="language-plaintext highlighter-rouge">defun</code> are very recent additions).</p>

<p>Also, my implementation is not a transpiler in the strict sense of “code in, code out”: Lisp is still too dynamic and fluid in runtime to map into some static Javascript. Macros make a full transpiler necessary even in runtime. I’d rather call it a “Just-In-Time Transpiler”.</p>

<p>If you are still keen to try it and are fine with using its <a href="https://github.com/EarlGray/elisp.js/blob/e8f3b24044d960d4a60e6ceba49e44f81c81ca9a/elisp/subr.js">source</a> <a href="https://github.com/EarlGray/elisp.js/blob/e8f3b24044d960d4a60e6ceba49e44f81c81ca9a/test/subr.js">code</a> as a reference, you can find a basic online demo here: <a href="https://dmytrish.net/elisp">https://dmytrish.net/elisp</a>.</p>

<h3 id="why">Why?</h3>
<p>My first and the most moon-shot reason has been the dream of seeing <code class="language-plaintext highlighter-rouge">org-mode</code> in the browser. I still hope that I might be able to write just enough functionality to support significant chunk of <code class="language-plaintext highlighter-rouge">org-mode</code> on top of, say, <a href="http://www.ymacs.org/">Ymacs</a>.</p>

<p>Also, I’ve been curious to learn more about Javascript/v8/node.js and v8’s performance. This goal has definitely paid off: I gained some insight into speeding up Javascript code and inner workings of v8, even though I am still very far from an expert in this.</p>

<h3 id="development-notes">Development notes</h3>

<p><strong>Test-Driven Development is cool</strong>–when you have a clear specification/reference implementation like the Elisp reference manual and Emacs (just look at <a href="https://github.com/EarlGray/elisp.js/blob/e8f3b24044d960d4a60e6ceba49e44f81c81ca9a/test/parser.js#L63">this</a> for example!). The right amount of end-to-end tests makes writing Javascript almost not scary, Mocha is pretty fast and provides with nice guardrails to structure lots of tests. Hopefully, extensive testing will make the project at least a bit more maintainable and evolvable.</p>

<p><strong>Dynamic scoping</strong>. With lexical scoping (i.e. almost any other kind of Lisp) translation to Javascript would be a lot easier (at least leaving out macros), but Elisp is the only surviving dinosaur of dynamic scoping, so I had to map dynamic bindings into Javascript carefully. This hinders v8 from many optimizations (obscuring the intent) and produces ugly JS code like this:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>elisp&gt; (defun sqr (x) (* x x))
(lambda (x) (* x x))

elisp&gt; (jscode (symbol-function 'sqr))
"(() =&gt; {
  let f1 = global.env.fun('*');
  let v2 = global.env.var_('x');
  return f1.get().fcall([v2.get(), v2.get()], global.env);
})"
</code></pre></div></div>

<p><strong>Pain of macros</strong>. Before I started working on macros in Elisp, the source code organization was straightforward and dependencies were unidirectional: I had <code class="language-plaintext highlighter-rouge">types.js</code> describing Lisp types, <code class="language-plaintext highlighter-rouge">parser.js</code> was turning an input string to a Lisp object, <code class="language-plaintext highlighter-rouge">translate.js</code> was taking a Lisp object and producing ephemeral JS code from it; <code class="language-plaintext highlighter-rouge">elisp.js</code> nicely packed everything into a high-level wrapper.</p>

<p>Once I’d added macros, the architecture became a mess: now even <code class="language-plaintext highlighter-rouge">types.js</code> requires <code class="language-plaintext highlighter-rouge">elisp.eval_lisp()</code>, creating circular references and lazy-loading in <code class="language-plaintext highlighter-rouge">parser.js</code> and <code class="language-plaintext highlighter-rouge">translate.js</code>. Maybe, I will be able to abstract the runtime parts from these files later, but macros really made the interpreter source code tightly coupled and intertwined. Just look at <a href="https://github.com/EarlGray/elisp.js/blob/e8f3b24044d960d4a60e6ceba49e44f81c81ca9a/elisp/types.js#L359">this pearl</a> (yes, <a href="https://github.com/EarlGray/elisp.js/blob/e8f3b24044d960d4a60e6ceba49e44f81c81ca9a/test/elisp.js#L283">every function call might require a recompilation</a> in Elisp):</p>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">LispFun</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">fcall</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">args</span><span class="p">,</span> <span class="nx">env</span><span class="p">)</span> <span class="p">{</span>
  <span class="k">try</span> <span class="p">{</span>
    <span class="k">return</span> <span class="nx">elisp</span><span class="p">.</span><span class="nx">fcall</span><span class="p">.</span><span class="nf">call</span><span class="p">(</span><span class="k">this</span><span class="p">,</span> <span class="nx">args</span><span class="p">,</span> <span class="nx">env</span><span class="p">);</span>
  <span class="p">}</span> <span class="k">catch </span><span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if </span><span class="p">(</span><span class="nx">e</span><span class="p">.</span><span class="nx">message</span> <span class="o">!==</span> <span class="dl">'</span><span class="s1">Macro accessed as a function</span><span class="dl">'</span><span class="p">)</span>
      <span class="k">throw</span> <span class="nx">e</span><span class="p">;</span>
    <span class="cm">/* trigger recompilation */</span>
    <span class="k">this</span><span class="p">.</span><span class="nx">func</span> <span class="o">=</span> <span class="kc">undefined</span><span class="p">;</span>
    <span class="k">return</span> <span class="nx">elisp</span><span class="p">.</span><span class="nx">fcall</span><span class="p">.</span><span class="nf">call</span><span class="p">(</span><span class="k">this</span><span class="p">,</span> <span class="nx">args</span><span class="p">,</span> <span class="nx">env</span><span class="p">);</span>
  <span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>

<p><strong>Repl tab completion is easy and surprisingly useful</strong>. <a href="https://github.com/EarlGray/elisp.js/blob/e8f3b24044d960d4a60e6ceba49e44f81c81ca9a/repl.js#L99">My heuristic for tab completion</a> is very crude and dumb at the moment: just looking back until the start of the current symbol and if there’s a <code class="language-plaintext highlighter-rouge">(</code>, complete the symbol as a function, otherwise complete it as a variable. Still, it works pretty reliably and saves a lot of typing. Also, this gave me a little insight why on earth anybody would prefer Lisp-2 (an ugly, ugly idea compared to Lisp-1!): now I understand that Lisp-2 might be slightly easier for tooling.</p>

<h3 id="profiling-and-benchmarking">Profiling and benchmarking</h3>

<blockquote>
  <p>v8 is fast!</p>
</blockquote>

<p>Still, my first naive version that could run <a href="https://github.com/EarlGray/elisp.js/blob/e8f3b24044d960d4a60e6ceba49e44f81c81ca9a/bench/silly-loop.el">silly-loops</a> made even v8 stumble compared to the slow Emacs interpreter. I had to learn about v8 profiling and it took several significant optimizations for it to become competitive with Emacs (this shows execution time in seconds):</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ npm run bench

&gt; elisp.js@0.1.0 bench /home/mitra/code/elisp.js
&gt; ./bench/bench

funcall
     now: 0,285
   emacs: 0,255
silly-loop
     now: 0,834
   emacs: 1,845
</code></pre></div></div>

<p>There is no free lunch, a slow implementation is still a slow implementation even on a fast engine. Profiling can guide to faster code though, so it’s better to say “v8 can be fast”.</p>

<p>Still, I find the results pretty satisfying for my limited resources.</p>

<h3 id="what-exactly-is-done-in-010">What exactly is done in 0.1.0</h3>

<p>Citing the CHANGELOG,</p>

<blockquote>
  <ul>
    <li>language types: integer, symbol, nil, cons, string, vector; LispFun
and LispMacro as invisible “upgrades” to lists when appropriate;</li>
    <li>language special forms: <code class="language-plaintext highlighter-rouge">let</code>, <code class="language-plaintext highlighter-rouge">lambda</code>, <code class="language-plaintext highlighter-rouge">quote</code>, <code class="language-plaintext highlighter-rouge">setq</code>, <code class="language-plaintext highlighter-rouge">if</code>, <code class="language-plaintext highlighter-rouge">progn</code>,
<code class="language-plaintext highlighter-rouge">while</code>;</li>
    <li>language subrs (builtin functions): <code class="language-plaintext highlighter-rouge">subrp</code>, <code class="language-plaintext highlighter-rouge">functionp</code>, <code class="language-plaintext highlighter-rouge">macrop</code>, <code class="language-plaintext highlighter-rouge">listp</code>,
<code class="language-plaintext highlighter-rouge">numberp</code>, <code class="language-plaintext highlighter-rouge">booleanp</code>, <code class="language-plaintext highlighter-rouge">read</code>, <code class="language-plaintext highlighter-rouge">eval</code>, <code class="language-plaintext highlighter-rouge">macroexpand-1</code>, <code class="language-plaintext highlighter-rouge">jscode</code>,
<code class="language-plaintext highlighter-rouge">jseval</code>, <code class="language-plaintext highlighter-rouge">+</code>, <code class="language-plaintext highlighter-rouge">-</code>, <code class="language-plaintext highlighter-rouge">*</code>, <code class="language-plaintext highlighter-rouge">&lt;</code>, <code class="language-plaintext highlighter-rouge">car</code>, <code class="language-plaintext highlighter-rouge">cdr</code>, <code class="language-plaintext highlighter-rouge">cons</code>, <code class="language-plaintext highlighter-rouge">list</code>, <code class="language-plaintext highlighter-rouge">fset</code>,
<code class="language-plaintext highlighter-rouge">symbol-function</code>, <code class="language-plaintext highlighter-rouge">error</code>, <code class="language-plaintext highlighter-rouge">print</code>, <code class="language-plaintext highlighter-rouge">float-time</code>.</li>
    <li>functions: positional arguments only, dynamic scoping;</li>
    <li>UI: repl.js with <code class="language-plaintext highlighter-rouge">defmacro</code>, <code class="language-plaintext highlighter-rouge">defun</code>, <code class="language-plaintext highlighter-rouge">defvar</code>; tab-completion of
functions and variables;</li>
    <li>UI: a <a href="https://dmytrish.net/elisp">browser demo</a> using webpack;</li>
    <li>benchmarked and optimized, in the ballpark of Emacs interpreter or
faster.</li>
  </ul>
</blockquote>

<h3 id="things-to-do-before-020">Things to do before 0.2.0</h3>

<p>The main goals for 0.2.0 at the moment are:</p>

<ul>
  <li>Make it parse and interpret non-trivial amount of source code from <code class="language-plaintext highlighter-rouge">lisp/emacs-lisp/</code> of Emacs;</li>
  <li>Add meaningful robust error handling with stacktraces, pluggable debuggers and references to source code;</li>
  <li>Extend the standard library of subrs on the go as needed;</li>
  <li>Give more thought to Emacs-specific types like buffers, cursors, charmaps, etc;</li>
  <li>Starting at least some form of documentation.</li>
</ul>

        ]]>
      </description>
    </item>
    
     
    <item>
      <title>How I stopped worrying and learned how to fix QML applets</title>
      <link>https://dmytrish.net/en/kde-dict</link>
      <pubDate>Sat, 28 Jul 2018 16:15:00 +0200</pubDate>
      <guid isPermaLink="true">https://dmytrish.net/en/kde-dict</guid>
      <category>
        <![CDATA[en]]>
      </category>
      <description>
        <![CDATA[
          <p>I am used to the Mac OS dictionary widget. When I moved to KDE, I was glad to add a dictionary widget to the system tray. A global key shortcut (<kbd>Shift</kbd>+<kbd>Win</kbd>+<kbd>D</kbd>) made it even better and faster to use.</p>

<p>Still, a small problem needed a fix: the input field did not focus automatically and I had to use touchpad to click it, which is quite distracting. My ideal dictionary applet workflow is: reading a text, spotting an unknown/unclear word, pressing <kbd>Shift</kbd>+<kbd>Win</kbd>+<kbd>D</kbd>, typing the word in (typing is good for remembering!), getting results on <kbd>Enter</kbd>, <kbd>Esc</kbd>, get back to the text.</p>

<p>Hey, it’s the Linux tinkering time again!</p>

<p><em>Disclaimer</em>: I am not an expert in KDE by any means, take the recipes with a grain of salt; if you are, please point out what can be done better.</p>

<h3 id="finding-the-source-for-the-widget">Finding the source for the widget</h3>

<p>I worked with Qt a little, a long time ago, so I knew about QML: it’s a fun little declarative language on top of Qt used to describe interfaces and UI actions. Turns out, you can write whole widgets in it!</p>

<p>Let’s find the source of the dictionary widget then.</p>

<p>After a few guesses (<code class="language-plaintext highlighter-rouge">plasmoid</code>? <code class="language-plaintext highlighter-rouge">widget</code>? <code class="language-plaintext highlighter-rouge">dict</code>?), <code class="language-plaintext highlighter-rouge">dpkg --list | grep</code> (I am using Kubuntu) gave me this:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ dpkg --list | grep plasma
...
ii  plasma-widgets-addons   4:5.12.6-0ubuntu0.1    amd64    additional widgets for Plasma 5
...
</code></pre></div></div>

<p>Looks like the dictionary applet might be in there:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ dpkg -L plasma-widgets-addons | grep dict
...
/usr/share/plasma/plasmoids/org.kde.plasma_applet_dict
...
</code></pre></div></div>

<p>Right. Examining the source showed that the applet UI is described here: <code class="language-plaintext highlighter-rouge">/usr/share/plasma/plasmoids/org.kde.plasma_dict_applet/contents/ui/main.qml</code>.</p>

<h3 id="looking-for-the-focus-event">Looking for the focus event</h3>

<p>Now it was time to actually fix the problem: get the text field (<code class="language-plaintext highlighter-rouge">input</code>) to focus every time the plasmoid is shown.</p>

<p>First, I tried to do it the right way: reading the documentation, understanding QML events and layouts, etc.</p>

<p>Googling “QML widget events” led me to the official QML documentation, which looks pretty solid and systematic. Sadly, I had spent a couple of hours trying to find anything relevant in the dump of definitions of methods and properties (scattered over super- and supersuperclasses of TextField and ColumnLayout), trying to grep through tutorials and StackOverflow – before giving up.</p>

<p>Then I had a better idea: installing and running QtCreator, opening the <code class="language-plaintext highlighter-rouge">main.qml</code> file and just stupidly trying a few completions here and there. This proved to be surprisingly effective and trying a few <code class="language-plaintext highlighter-rouge">on</code> completions found the <code class="language-plaintext highlighter-rouge">onActiveFocusChanged</code> callback and <code class="language-plaintext highlighter-rouge">.focus</code> property of the <code class="language-plaintext highlighter-rouge">input</code> element:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ColumnLayout {
    onActiveFocusChanged: input.focus = true
    
    ...
}
</code></pre></div></div>

<p>Now, let’s test the changes:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ pkill plasmashell ; kstart5 plasmashell
</code></pre></div></div>

<p>Nice, <kbd>Shift</kbd>+<kbd>Win</kbd>+<kbd>D</kbd> now showed the dictionary widget with the search field focused.</p>

<p>A note: it’s better to keep the modified <code class="language-plaintext highlighter-rouge">main.qml</code> in a safe place and copy it in <code class="language-plaintext highlighter-rouge">/usr/share/...</code>, because it might be rewritten by a new system update. I omitted copying it for simplicity.</p>

<h2 id="making-the-previous-search-selected">Making the previous search selected</h2>

<p>Another annoying usability problem remained: now the search field was focused, but contained the previous search in it, unselected, so I had to be careful: if there was a word in the search field, I had to erase it first (<kbd>Shift</kbd>+<kbd>Backspace</kbd>) or I would just append a new word to its end. It was not a big deal, but it introduced some state I needed to track every time and any state is distracting (Vim is still a holy cow that is above any whining about modes)!</p>

<p>The problem could be solved by clearing the field every time the widget was hidden, but sometimes you just want to see the previous word, not to look up a new one. Selecting the previous search when the widget is shown solves this: the previous search is here, but typing anything replaces it.</p>

<p>This time the documentation was more helpful:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ColumnLayout {
    onActiveFocusChanged: {
        input.selectAll()
        input.focus = true
    }
    
    ...
}
</code></pre></div></div>

<h3 id="linux-is-still-diy-design-it-yourself-sometimes">Linux is still DIY (Design It Yourself) sometimes!</h3>

<p>While we’re at it, why not fix the annoying font and background color choice with my <em>crazy design skills</em>? I find it annoying and not as streamlined as the Mac widget, don’t you (let the flame war begin!)?</p>

<p><img src="../sta/kdedict-before.png" alt="" /></p>

<p>Trying to tinker with QML <code class="language-plaintext highlighter-rouge">Font</code> property was not successful. <code class="language-plaintext highlighter-rouge">WebEngineView</code> is obviously a piece of web that listens only to CSS. <a href="https://stackoverflow.com/questions/41931172/webengineview-set-custom-font-to-html-content">Quick googling</a> shows that there is no easy way to style <code class="language-plaintext highlighter-rouge">WebEngineView</code> other than running some Javascript (I will be glad to be proved wrong here!):</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ColumnLayout {
    ...
    WebEngineView: {
        id: web
        ...
        onLoadingChanged: {
            web.runJavaScript(
                "document.body.style['font-family'] = 'Lato, monospace'; " +
                "document.body.style['line-height'] = '1.5'; " +
                "document.body.style['background-color'] = '#f9f7e0'; "
            )
        }
    }
}
</code></pre></div></div>

<p>Now it was much more palatable to me:</p>

<p><img src="../sta/kdedict-after.png" alt="" /></p>

<h3 id="conclusions">Conclusions</h3>

<ul>
  <li>
    <p>The KDE dictionary widget is very basic, quick and dirty, and could use some love and usability testing. On the other hand, I am satisfied with my tweaks and resulting usability (should I contribute that upstream?).</p>
  </li>
  <li>
    <p>KDE widgets are small, fun and flexible (for a programmer) and fixing them does not require to recompile half of KDE.</p>
  </li>
  <li>
    <p>QtCreator was more helpful than the docs, the QML documentation is a OOP mess.</p>
  </li>
</ul>


        ]]>
      </description>
    </item>
    
     
    <item>
      <title>Network programming in Bash</title>
      <link>https://dmytrish.net/en/bash-tcp</link>
      <pubDate>Thu, 05 Jul 2018 20:15:00 +0200</pubDate>
      <guid isPermaLink="true">https://dmytrish.net/en/bash-tcp</guid>
      <category>
        <![CDATA[en]]>
      </category>
      <description>
        <![CDATA[
          <p>Did you know that bash can connect to TCP/UDP servers on its own, without using <code class="language-plaintext highlighter-rouge">nc</code>/<code class="language-plaintext highlighter-rouge">telnet</code> (or even <a href="https://www.gnu.org/software/gawk/manual/html_node/TCP_002fIP-Networking.html">awk</a>!)?</p>

<p>I learned this in the abyss of <code class="language-plaintext highlighter-rouge">info bash</code>: it mentions that redirects like <code class="language-plaintext highlighter-rouge">/dev/stdin</code>, <code class="language-plaintext highlighter-rouge">/dev/fd/FD</code>, etc, are treated specially. One of redirections on the list was <code class="language-plaintext highlighter-rouge">/dev/tcp/HOST/PORT</code>—I could not believe my eyes!</p>

<p>After figuring out how to use the same file descriptor for reading and writing, I was able to make a simple HTTP request to Google:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ (exec 3&lt;&gt;/dev/tcp/www.google.com/80 ; 
echo "GET /search?q=bash+madness HTTP/1.0" &gt;&amp;3; 
echo &gt;&amp;3; 
cat &lt;&amp;3 ) | less
</code></pre></div></div>

<p>Yes, it’s that simple.</p>

        ]]>
      </description>
    </item>
    
     
    <item>
      <title>A small annoyance of Linux modifier keys</title>
      <link>https://dmytrish.net/en/xwindow-modifiers</link>
      <pubDate>Sat, 16 Jun 2018 17:15:00 +0200</pubDate>
      <guid isPermaLink="true">https://dmytrish.net/en/xwindow-modifiers</guid>
      <category>
        <![CDATA[en]]>
      </category>
      <description>
        <![CDATA[
          <p>I switched back to Linux recently, trading an aging MacBook Air—it was wonderful in its days!—for Dell XPS 13. It’s been a hardware upgrade in every sense (well, except for the weird camera location and crappier sound speakers).</p>

<p>I am greatly satisfied with my non-orthodox KDE setup with a few tweaks, except for one little thing I can’t even properly google (I get a lot of results for keyboard customization).</p>

<p>I noticed a weird thing: MacOS never gets multi-modifier shortcuts (<kbd>Ctrl-Shift</kbd>, <kbd>Alt-Cmd</kbd>, etc) wrong: I never get <kbd>Ctrl-D</kbd>/<kbd>Shift-D</kbd> instead of <kbd>Ctrl-Shift-D</kbd>, which happens pretty often on my new Linux system.</p>

<p>This could be explained by the hypothesis that the MacOS input layer has a special delay to account for this: when <kbd>Ctrl</kbd>, <kbd>D</kbd> are pressed in a short time, it waits an instant for another modifier key to follow (e.g. <kbd>Shift</kbd>) and produces <kbd>Ctrl-Shift-D</kbd>. The XWindow (xinput?) behavior seems more straightforward: it generates an event for <kbd>Ctrl-D</kbd> the instant when <kbd>D</kbd> is down, disregarding any modifier keys after that.</p>

<p>It’s a small thing, but quite annoying already.</p>

        ]]>
      </description>
    </item>
    
     
    <item>
      <title>Why does Telegram use camera while in background?</title>
      <link>https://dmytrish.net/en/is-telegram-watching-me</link>
      <pubDate>Sat, 05 May 2018 21:22:39 +0200</pubDate>
      <guid isPermaLink="true">https://dmytrish.net/en/is-telegram-watching-me</guid>
      <category>
        <![CDATA[en]]>
      </category>
      <description>
        <![CDATA[
          <h3 id="tuesday-telegram-caught-using-my-camera-while-in-the-background">Tuesday:<br /> Telegram caught using my camera while in the background</h3>

<p>It was a nice spring evening when this happened. At 19:41, I came home, pulled my phone out of my pocket and saw this:</p>

<p><img src="../sta/telegram-caught.jpg" alt="" /></p>

<p>For some surprising and possibly alarming reason, the official Telegram app for Android needed access to camera while in the background! Was it Telegram itself watching me for no reason, was it a bug in the app, was it a bug in the Android permission monitoring?</p>

<p>I was perfectly sure that I did not use the phone at the time (I knew the exact minute I used it last time before this happened: a picture was taken at 19:25) and that Telegram was in the background.</p>

<p>I took the screenshot above and started thinking about the situation and what I can do to figure this out. Good ideas come slowly, and when I tried to get the phone logs with <code class="language-plaintext highlighter-rouge">adb logcat</code>, it was already too late: logs for that moment were gone.</p>

<p>So, I noted that I would need to logcat the logs later when a suspicious activity happens again and waited.</p>

<h3 id="next-monday-telegram-blinks-with-the-camera-torchlight-when-opened">Next Monday:<br /> Telegram blinks with the camera torchlight when opened</h3>

<p>Next time this happened in the morning when I was checking my phone: this time Telegram blinked with the frontal camera right after I opened it. I was ready this time and pulled <a href="../sta/telegram.logcat">full logs from the phone</a>.</p>

<p>Here it was, caught with a smoking gun:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>04-30 12:10:01.032   429 20402 I CameraService: CameraService::connect call (PID -1 "org.telegram.messenger", camera ID 1) for HAL version default and Camera API version 1
</code></pre></div></div>

<p>This proved that Telegram used my cameras on its own, without asking/warning me, and this time it appeared smarter than before: it did not try accessing a camera from background this time, it waited until I opened the app instead.</p>

<p>Why the app would do that? Digging further revealed that Telegram accessed both rear and frontal camera for a moment, changing torchlight status (this is a clean excerpt, the full log is very verbose and often low-level):</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>04-30 12:10:01.738   429 20402 I CameraService: torch_mode_status_change: cameraId=1, TorchStatus=1
04-30 12:10:01.738   429 20402 I CameraService: onTorchStatusChangedLocked: Torch status changed for cameraId=1, newTorchStatus=1
04-30 12:10:01.739  2081 16047 I CameraManagerGlobal: postSingleTorchUpdate : Camera id 1 has torch status changed to 0x1
04-30 12:10:01.739   701  6521 I CameraManagerGlobal: postSingleTorchUpdate : Camera id 1 has torch status changed to 0x1
04-30 12:10:01.741   429   740 W QCamera2Factory: getCameraInfo: E, camera_id = 1
04-30 12:10:01.741   429   740 I QCamera2HWI: getFlashInfo cameraId:0 hasFlash:1
04-30 12:10:01.741   429   740 I QCamera2HWI: getCapabilities id:0 hasFlash:1
04-30 12:10:01.741   429   740 W QCamera2HWI: __dbg: info-&gt;orientation : 90 rc = 0
04-30 12:10:01.741   429   740 I QCamera2HWI: getFlashInfo cameraId:1 hasFlash:1
04-30 12:10:01.741   429   740 I QCamera2HWI: getCapabilities id:1 hasFlash:1
04-30 12:10:01.741   429   740 W QCamera2HWI: __dbg: info-&gt;orientation : 270 rc = 0
04-30 12:10:01.741   429   740 W QCamera2Factory: getCameraInfo: X
04-30 12:10:01.744   429 20402 I CameraService: CameraService::connect call (PID -1 "org.telegram.messenger", camera ID 1) for HAL version default and Camera API version 1

04-30 12:10:01.750   429 20402 E CameraService: checkTemperature (0)
04-30 12:10:01.750   429 20402 I CameraService: CameraService::validateConnectLocked is ok : calling pid 30732, calling uid 10137, cameraservice pid=429, device user 0, currently allowed device users: 0
04-30 12:10:01.750   429 20402 I CameraFlashlight: prepareDeviceOpen: prepare for device open(cameraId=1, package=org.telegram.messenger)
04-30 12:10:01.750   429 20402 I CameraService: torch_mode_status_change: cameraId=0, TorchStatus=0
04-30 12:10:01.750   429 20402 I CameraService: onTorchStatusChangedLocked: Torch status changed for cameraId=0, newTorchStatus=0
04-30 12:10:01.750   429 20402 I CameraService: torch_mode_status_change: cameraId=1, TorchStatus=0
04-30 12:10:01.750   429 20402 I CameraService: onTorchStatusChangedLocked: Torch status changed for cameraId=1, newTorchStatus=0
04-30 12:10:01.751   429 20402 W QCamera2Factory: getCameraInfo: E, camera_id = 1
04-30 12:10:01.751   429 20402 I QCamera2HWI: getFlashInfo cameraId:0 hasFlash:1
04-30 12:10:01.752   429 20402 I QCamera2HWI: getCapabilities id:0 hasFlash:1
04-30 12:10:01.752   429 20402 W QCamera2HWI: __dbg: info-&gt;orientation : 90 rc = 0
04-30 12:10:01.752   429 20402 I QCamera2HWI: getFlashInfo cameraId:1 hasFlash:1
04-30 12:10:01.752   429 20402 I QCamera2HWI: getCapabilities id:1 hasFlash:1
04-30 12:10:01.752   429 20402 W QCamera2HWI: __dbg: info-&gt;orientation : 270 rc = 0
04-30 12:10:01.752   429 20402 W QCamera2Factory: getCameraInfo: X

04-30 12:10:01.765   429 20402 I CameraService: torch_mode_status_change: cameraId=1, TorchStatus=0
04-30 12:10:01.765   429 20402 I CameraService: onTorchStatusChangedLocked: Torch status changed for cameraId=1, newTorchStatus=0
</code></pre></div></div>

<p>This log is cherry-picked and omits activation of <code class="language-plaintext highlighter-rouge">AudioSink</code>, <code class="language-plaintext highlighter-rouge">MediaPlayerServer</code>, <code class="language-plaintext highlighter-rouge">OggExtractor</code>, and lots of other low-level things, but I suppose that this activity is automatic when opening a camera; I could not find any explicit signs of a picture/video being taken, please feel free <a href="../sta/telegram.logcat">to examine the full log</a> and tell me I am wrong.</p>

<h3 id="conclusion">Conclusion</h3>

<p>It seems rather innocent: as far as I see, this looks like a instantaneous activation of camera torchlight without clear signs of a picture being taken. It does not look like a sneaky operation: it blinked the camera light, obviously drawing my attention. On the other hand, I do not have extensive knowledge of low-level details of camera operation on Android and I could have missed something.</p>

<p>The most probable benign explanation sounds like this: Telegram has been experimenting with blinking camera torchlight on new messages for phones that do not have a LED above the screen dedicated to notifications (like in many Sony smartphones). The first time they were releasing this feature, Permission Manager was raising warnings about the app using camera from the background. This explains the first time: I was coming home, my phone connected to home Wi-Fi from the street, Telegram detected new messages and tried to blink about this with the torchlight from the background. The second time they fixed the background access and restricted blinking to foreground mode.</p>

<p>Still, I do not feel comfortable with Telegram accessing my camera without my intent. The blinking feature (as I guess it) sounds dubious and unnecessary to me (I try to restrict notifications on my phone as much as I can) and it’s easy to sneak any malicious activity later, covering camera activity with innocent explanations.</p>

        ]]>
      </description>
    </item>
    
     
    <item>
      <title>More C++ fun, explained</title>
      <link>https://dmytrish.net/en/cpp-more-fun</link>
      <pubDate>Sun, 22 Apr 2018 19:39:00 +0200</pubDate>
      <guid isPermaLink="true">https://dmytrish.net/en/cpp-more-fun</guid>
      <category>
        <![CDATA[en]]>
      </category>
      <description>
        <![CDATA[
          <p>In <a href="http://rachelbythebay.com/w/2018/04/19/map/">a recent post</a>, <a href="http://rachelbythebay.com/w">rachelbythebay</a> showed this example of a very surprising C++ behavior (graceously leaving the explanation as an exercise to the reader):</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp">
</span> 
<span class="cp">#include</span> <span class="cpf">&lt;map&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;string&gt;</span><span class="cp">
</span> 
<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
  <span class="n">std</span><span class="o">::</span><span class="n">map</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&gt;</span> <span class="n">x</span><span class="p">;</span>
  <span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mh">0x5001</span><span class="p">;</span>
  <span class="n">x</span><span class="p">[</span><span class="s">"foo"</span><span class="p">]</span> <span class="o">=</span> <span class="n">i</span><span class="p">;</span>
 
  <span class="n">printf</span><span class="p">(</span><span class="s">"%s"</span><span class="p">,</span> <span class="n">x</span><span class="p">[</span><span class="s">"foo"</span><span class="p">].</span><span class="n">c_str</span><span class="p">());</span>
 
  <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>So, what is happening here? Compilation does not give any warnings and it runs without segfaults, and more, without any visible output!</p>

<p>What happened to type safety?! How on earth is this possible?! Is it a compiler bug? No, it turns out that it’s perfectly valid C++ (C++98, to be pedantic!).</p>

<h2 id="what-is-xfoo-exactly">What is x[“foo”], exactly?</h2>

<p>My first reflex was to look at the assembly:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ clang++ -Wall -Wextra -g strmap.cc
$ otool -tv ./a.out | c++filt
</code></pre></div></div>

<p>and oops, trying to wade through C++ heavily templated symbol names was an exercise in futility (unlike plain C).</p>

<p>Ok, let’s fire up a debugger, which is by definition more human-friendly, and set a breakpoint after the mysterious assignment statement and see what we got:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ lldb ./a.out
Current executable set to './a.out' (x86_64).
(lldb) b 11
Breakpoint 1: where = a.out`main + 354 at strmap.cc:11, address = 0x0000000100000bc2
(lldb) r
Process 25081 launched: './a.out' (x86_64)
Process 25081 stopped
* thread #1: tid = 0x45b804, 0x0000000100000bc2 a.out`main + 354 at strmap.cc:11, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
    frame #0: 0x0000000100000bc2 a.out`main + 354 at strmap.cc:11
   8      int i = 0x5001;
   9      x["foo"] = i;
   10    
-&gt; 11     printf("%s", x["foo"].c_str());
   12    
   13     return 0;
   14   }
(lldb) p x
(std::__1::map&lt;std::__1::basic_string&lt;char, std::__1::char_traits&lt;char&gt;, std::__1::allocator&lt;char&gt; &gt;, std::__1::basic_string&lt;char, std::__1::char_traits&lt;char&gt;, std::__1::allocator&lt;char&gt; &gt;, std::__1::less&lt;std::__1::basic_string&lt;char, std::__1::char_traits&lt;char&gt;, std::__1::allocator&lt;char&gt; &gt; &gt;, std::__1::allocator&lt;std::__1::pair&lt;const std::__1::basic_string&lt;char, std::__1::char_traits&lt;char&gt;, std::__1::allocator&lt;char&gt; &gt;, std::__1::basic_string&lt;char, std::__1::char_traits&lt;char&gt;, std::__1::allocator&lt;char&gt; &gt; &gt; &gt; &gt;) $0 = size=1 {
  [0] = (first = "foo", second = "\x01")
}
(lldb) 
</code></pre></div></div>

<p>Whoa, the string <code class="language-plaintext highlighter-rouge">"\x01"</code> is inserted silently! Is this some kind of integer-pointer conversion that creates a C string from the integer? If it is, why there are no segfaults (<code class="language-plaintext highlighter-rouge">0x5001</code> does not look like a memory address usually used in Unix-like OSes). If it a pointer conversion, let’s try to produce a segfault by changing <code class="language-plaintext highlighter-rouge">0x5001</code> to something else, like <code class="language-plaintext highlighter-rouge">0x6001</code>. Still no segfaults, and the string is still <code class="language-plaintext highlighter-rouge">"\x01"</code>. So, it’s not a pointer, it’s the integer value that is changed into <code class="language-plaintext highlighter-rouge">"\x01"</code> somehow. Now it’s clear that <code class="language-plaintext highlighter-rouge">int</code> is silently converted to <code class="language-plaintext highlighter-rouge">char</code>, leaving us with the least significant byte.</p>

<p>Let’s make the source code a little less obscure:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>x["foo"] = 'a';
</code></pre></div></div>

<h2 id="string-constructors">String constructors?</h2>

<p>Now we have a new mystery: how can you put a <code class="language-plaintext highlighter-rouge">char</code> into <code class="language-plaintext highlighter-rouge">map&lt;string, string&gt;</code>?</p>

<p>The usual suspects in such investigations are usually constructors that can kick in silently and make everything into everything. Is it a <code class="language-plaintext highlighter-rouge">std::string</code> constructor that would take a <code class="language-plaintext highlighter-rouge">char</code> (business as usual in the C++ land, why not)?</p>

<p>Let’s read <a href="http://en.cppreference.com/w/cpp/string/basic_string/basic_string">the docs on <code class="language-plaintext highlighter-rouge">basic_string</code> constructors</a>. Still, there is no sign of a constructor that would take a bare <code class="language-plaintext highlighter-rouge">CharT</code> value as an argument.</p>

<p>Is it an <code class="language-plaintext highlighter-rouge">initializer_list</code> somewhere that could be made with one <code class="language-plaintext highlighter-rouge">char</code>? No, <code class="language-plaintext highlighter-rouge">clang++ -std=c++98 strmap.cc</code> is happy to produce the same result.</p>

<p>Another twenty minutes are fruitlessly spent on trying to guess what other constructor could be hidden here, until an experiment proves me wrong:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>x["foo"] = std::string('a');
</code></pre></div></div>

<p>spews two screens of compilation errors that can be summarized as “no such constructor”.</p>

<h2 id="who-else-was-there">Who else was there?</h2>

<p>Now the investigation turns to every witness of the crime, one of which is <code class="language-plaintext highlighter-rouge">std::map</code>. How does <code class="language-plaintext highlighter-rouge">std::map::operator[]</code> work? Reading <a href="http://en.cppreference.com/w/cpp/container/map/operator_at">the docs</a> clears this up a bit:</p>

<blockquote>
  <p>1) Inserts <code class="language-plaintext highlighter-rouge">value_type(key, T())</code> if the key does not exist. This function is equivalent to <code class="language-plaintext highlighter-rouge">return insert(std::make_pair(key, T())).first-&gt;second</code>;</p>

  <ul>
    <li><code class="language-plaintext highlighter-rouge">key_type</code> must meet the requirements of <code class="language-plaintext highlighter-rouge">CopyConstructible</code>.</li>
    <li><code class="language-plaintext highlighter-rouge">mapped_type</code> must meet the requirements of <code class="language-plaintext highlighter-rouge">CopyConstructible</code> and <code class="language-plaintext highlighter-rouge">DefaultConstructible</code>.</li>
  </ul>

  <p>If an insertion is performed, the mapped value is value-initialized (default-constructed for class types, zero-initialized otherwise) and a reference to it is returned.</p>
</blockquote>

<p>So that’s how the string <code class="language-plaintext highlighter-rouge">"\x01"</code> is created: it emerges as an empty string in <code class="language-plaintext highlighter-rouge">x["foo"]</code> and gets its content later. Now it’s clear that the default constructor is called and the content is assigned later through <code class="language-plaintext highlighter-rouge">std::string::operator=</code>.</p>

<p><a href="http://en.cppreference.com/w/cpp/string/basic_string/operator%3D">std::string::operator=</a> in its fourth (sic) form is the last piece of the puzzle:</p>

<blockquote>
  <p>4) Replaces the contents with character <code class="language-plaintext highlighter-rouge">ch</code> as if by <code class="language-plaintext highlighter-rouge">*this = basic_string(1,c)</code></p>
</blockquote>

<p>That’s what really happens:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>int i = 0x5001;
x["foo"] = std::string();  // in-place creation
x["foo"] = (char)i;        // the string content is replaced with (char)i
</code></pre></div></div>

<h2 id="conclusion">Conclusion</h2>

<p>We have a nice <a href="https://en.wikipedia.org/wiki/Rube_Goldberg_machine">Rube-Goldberg machine</a> here:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">int</code> is silently converted into <code class="language-plaintext highlighter-rouge">char</code>;</li>
  <li><code class="language-plaintext highlighter-rouge">std::map</code> creates an empty string for a key that does not exist;</li>
  <li><code class="language-plaintext highlighter-rouge">std::string::operator=</code> is heavily overloaded, so one of its forms takes a <code class="language-plaintext highlighter-rouge">char</code>.</li>
</ul>

<p>The lesson to learn here is that C++ compilers could waste less time and CPU cycles trying to guess the programmer intent and could benefit from Rust-like explicitness and strictness.</p>

        ]]>
      </description>
    </item>
    
     
    <item>
      <title>Validating a self-hosted web server</title>
      <link>https://dmytrish.net/en/web-observatories</link>
      <pubDate>Sat, 21 Apr 2018 17:24:56 +0200</pubDate>
      <guid isPermaLink="true">https://dmytrish.net/en/web-observatories</guid>
      <category>
        <![CDATA[en]]>
      </category>
      <description>
        <![CDATA[
          <p>I have some simple self-hosted services running on a small Linode VPS (mostly as a useful hobby). If you are in a similar boat (one-person hobby sysadmin), I’d like to share some useful web tools I have discovered during my dabbling with my web server setup.</p>

<h2 id="https">HTTPS</h2>

<p>It is a good idea to serve your web-site over HTTPS as soon as you have any kind of authorization/server-side logic (and even if it’s a completely static site, it’s still a good practice to provide users with confidence in the page integrity: plain unencrypted HTTP can be messed up by any intermediate host/proxy/cache). Nowadays, HTTPS is very simple to set up using <a href="https://letsencrypt.org/">Let’s Encrypt</a>: it’s <a href="https://certbot.eff.org/">a one-off setup procedure</a> with automated renewal of certificates later and no beaurocracy whatsoever (compared to free, but manual and rather beaurocratic procedure of getting StartSSL certificates which I used before).</p>

<p>On the other hand, TLS (the base of HTTPS security) is a complicated protocol with a lot of subtleties to get right: e.g. the server should send the full chain of authority certificates (ideally excluding the root certficate authority which is installed in the OS/browser anyway, to optimize performance), the server should use reliable, modern ciphers and key exchange methods without known vulnerabilites. There are also higher-level attacks like downgrading TLS version by a middleman.</p>

<p><a href="https://www.ssllabs.com/ssltest/analyze.html">SSLLabs HTTPS test</a> provides a good starting point for learning about these intricacies and vulnerabilities and gives helpful advice for improving the HTTPS setup.</p>

<p><img src="../sta/observ-ssllabs.png" alt="" /></p>

<h2 id="web-security">Web security</h2>

<p>Even a simple web-service with a couple of forms and actions might provide a surprisingly big attack surface: <a href="https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)">CSRF</a>, <a href="https://www.owasp.org/index.php/Clickjacking">clickjacking</a>, <a href="https://www.owasp.org/index.php/XSS">XSS</a>, <a href="https://en.wikipedia.org/wiki/POODLE">downgrading SSL/TLS to older versions</a>, <a href="https://www.owasp.org/index.php/3rd_Party_Javascript_Management_Cheat_Sheet">third-party Javascript risks</a> (e.g. even if you trust the third-party—which is usually the case!—loading script over plain HTTP might be risky).</p>

<p>A good place to start learning the theory is <a href="https://wiki.mozilla.org/WebAppSec">https://wiki.mozilla.org/WebAppSec</a> and <a href="https://www.owasp.org/index.php/Cheat_Sheets">https://www.owasp.org/index.php/Cheat_Sheets</a>.</p>

<p><a href="https://observatory.mozilla.org/analyze">Mozilla HTTP Observatory</a> is a very helpful tool to check how well your HTTP server setup is equipped against common security hazards: does it send security-relevant HTTP headers, does it have HTTPS redirections from HTTP, etc.</p>

<p><img src="../sta/observ-mozilla.png" alt="" /></p>

<h2 id="rssxmlhtml5-validators">RSS/XML/HTML5 validators</h2>

<p>If you have RSS feeds, it’s a good idea to verify it for compliance to standards: <a href="https://validator.w3.org/feed/">https://validator.w3.org/feed/</a>.</p>

<p><img src="../sta/observ-rss.png" alt="" /></p>

<h2 id="user-experience">User experience</h2>

<p>If you want your site to have modern look and good performance, particularly on mobile (which are essential for e.g. good ranking in search results), Google has a helpful tool: <a href="https://developers.google.com/speed/pagespeed/insights/">PageSpeed Insights</a>.</p>

<p>PageSpeed Insights provides advice about page/assets size (minification of HTML/CSS/JS/images), server response time, page rendering delays, caching and compression setup of the web server and other useful things.</p>

<p><img src="../sta/observ-pagespeed.png" alt="" /></p>


        ]]>
      </description>
    </item>
    
     
    <item>
      <title>Idris: хай код пишеться сам</title>
      <link>https://dmytrish.net/uk/idris-self-coding</link>
      <pubDate>Sat, 08 Oct 2016 13:34:56 +0200</pubDate>
      <guid isPermaLink="true">https://dmytrish.net/uk/idris-self-coding</guid>
      <category>
        <![CDATA[uk]]>
      </category>
      <description>
        <![CDATA[
          <p>Idris — це просто мрія ледачого програміста, із idris-vim код пишеться буквально сам собою.</p>

<p>Наприклад, хочемо ми відсортувати список певної довжини insertion sort’ом. Гаразд, пишемо</p>

<div class="language-idris highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">ins_sort :</span> <span class="nc">Ord </span><span class="n">el</span> <span class="o">=&gt;</span> <span class="kt">Vect</span> <span class="n">n</span> <span class="n">el</span> <span class="o">-&gt;</span> <span class="kt">Vect</span> <span class="n">n</span> <span class="n">el</span>
</code></pre></div></div>

<p>і говоримо Віму <code class="language-plaintext highlighter-rouge">\d</code> (<em>define</em>). Він зв’язується із repl Ідріса і дописує внизу:</p>

<div class="language-idris highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">ins_sort</span> <span class="n">xs</span> <span class="o">=</span> <span class="o">?</span><span class="n">ins_sort_rhs</span>
</code></pre></div></div>

<p>де <code class="language-plaintext highlighter-rouge">?ins_sort_rhs</code> це дірка, функціональність, уже правильно типізована, тільки ще не написана.</p>

<p>Ясно, що після цього нам хочеться розкласти <code class="language-plaintext highlighter-rouge">xs</code> на можливі клози pattern matching. Наводимо курсор на <code class="language-plaintext highlighter-rouge">xs</code>, говоримо <code class="language-plaintext highlighter-rouge">\c</code> (<em>clauses</em>), Вім переписує визначення в</p>

<div class="language-idris highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">ins_sort</span> <span class="kt">[]</span> <span class="o">=</span> <span class="o">?</span><span class="n">ins_sort_rhs_1</span>
<span class="n">ins_sort</span> <span class="p">(</span><span class="n">x</span> <span class="o">::</span> <span class="n">xs</span><span class="p">)</span> <span class="o">=</span> <span class="o">?</span><span class="n">ins_sort_rhs_2</span>
</code></pre></div></div>

<p>Заміняти <code class="language-plaintext highlighter-rouge">?ins_sort_rhs_1</code> на <code class="language-plaintext highlighter-rouge">[]</code> нижче нашої гідності (ми ж наче розумні люди, хай цим займаються інструменти), тому знову можна навести курсор на нього і сказати <code class="language-plaintext highlighter-rouge">\o</code>  (<em>prOOf search</em>) — і <code class="language-plaintext highlighter-rouge">?ins_sort_rhs_1</code> сам перепишеться в <code class="language-plaintext highlighter-rouge">[]</code></p>

<p>Із <code class="language-plaintext highlighter-rouge">?ins_sort_rhs_2</code> інструмент уже почувається не таким розумним і доводиться писати код вручну:</p>

<div class="language-idris highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">ins_sort</span> <span class="p">(</span><span class="n">x</span> <span class="o">::</span> <span class="n">xs</span><span class="p">)</span> <span class="o">=</span> 
   <span class="kr">let</span> <span class="n">xs_sorted</span> <span class="o">=</span> <span class="n">ins_sort</span> <span class="n">xs</span>
   <span class="kr">in</span> <span class="o">?</span><span class="n">sorted_insert</span>
</code></pre></div></div>

<p>— зате тепер можна навести курсор на <code class="language-plaintext highlighter-rouge">?sorted_insert</code> і зробити із нього нову проблему^W лемму^W функцію за допомогою <code class="language-plaintext highlighter-rouge">\l</code> (<em>make Lemma</em>). Вім вставляє нову функцію, якій передає як параметри всі локальні змінні:</p>

<div class="language-idris highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">sorted_insert :</span> <span class="nc">Ord </span><span class="n">el</span> <span class="o">=&gt;</span> 
                 <span class="p">(</span><span class="n">x</span> <span class="o">:</span> <span class="n">el</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="p">(</span><span class="n">xs</span> <span class="o">:</span> <span class="kt">Vect</span> <span class="n">k</span> <span class="n">el</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="p">(</span><span class="n">xs_sorted</span> <span class="o">:</span> <span class="kt">Vect</span> <span class="n">k</span> <span class="n">el</span><span class="p">)</span>
                 <span class="o">-&gt;</span> <span class="kt">Vect</span> <span class="p">(</span><span class="kt">S</span> <span class="n">k</span><span class="p">)</span> <span class="n">el</span>
</code></pre></div></div>

<p>Ясно, що старі xs нам тепер не потрібні, доводиться підправляти цей код у</p>

<div class="language-idris highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">sorted_insert :</span> <span class="nc">Ord </span><span class="n">el</span> <span class="o">=&gt;</span> <span class="p">(</span><span class="n">x</span> <span class="o">:</span> <span class="n">el</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="p">(</span><span class="n">xs</span> <span class="o">:</span> <span class="kt">Vect</span> <span class="n">k</span> <span class="n">el</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kt">Vect</span> <span class="p">(</span><span class="kt">S</span> <span class="n">k</span><span class="p">)</span> <span class="n">el</span>
</code></pre></div></div>

<p>(де <code class="language-plaintext highlighter-rouge">xs</code> — це коротше ім’я для <code class="language-plaintext highlighter-rouge">xs_sorted</code>). Знову робимо <code class="language-plaintext highlighter-rouge">\d</code>, автоматично пишеться</p>

<div class="language-idris highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">sorted_insert</span> <span class="n">x</span> <span class="n">xs</span> <span class="o">=</span> <span class="o">?</span><span class="n">sorted_insert_rhs</span>
</code></pre></div></div>

<p>Наводимо курсор на <code class="language-plaintext highlighter-rouge">xs</code>, тиснемо <code class="language-plaintext highlighter-rouge">\c</code>, створюються клози:</p>

<div class="language-idris highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">sorted_insert</span> <span class="n">x</span> <span class="kt">[]</span> <span class="o">=</span> <span class="o">?</span><span class="n">sorted_insert_rhs_1</span>
<span class="n">sorted_insert</span> <span class="n">x</span> <span class="p">(</span><span class="n">y</span> <span class="o">::</span> <span class="n">xs</span><span class="p">)</span> <span class="o">=</span> <span class="o">?</span><span class="n">sorted_insert_rhs_2</span>
</code></pre></div></div>

<p>(зверніть увагу на автоматичне перейменування в <code class="language-plaintext highlighter-rouge">y :: xs</code>!).</p>

<p>За допомогою <code class="language-plaintext highlighter-rouge">\o</code> <code class="language-plaintext highlighter-rouge">?sorted_insert_rhs_1</code> автоматично переписується в <code class="language-plaintext highlighter-rouge">[x]</code>. Тепер можна зайнятись <code class="language-plaintext highlighter-rouge">?sorted_insert_rhs_2</code>, тепер уже вручну:</p>

<div class="language-idris highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">sorted_insert</span> <span class="n">x</span> <span class="p">(</span><span class="n">y</span> <span class="o">::</span> <span class="n">xs</span><span class="p">)</span> <span class="o">=</span> 
     <span class="kr">if</span> <span class="n">x</span> <span class="o">&lt;</span> <span class="n">y</span> <span class="kr">then</span> <span class="p">(</span><span class="n">x</span> <span class="o">::</span> <span class="n">y</span> <span class="o">::</span> <span class="n">xs</span><span class="p">)</span> <span class="kr">else</span> <span class="n">y</span> <span class="o">::</span> <span class="n">sorted_insert</span> <span class="n">x</span> <span class="n">xs</span>
</code></pre></div></div>

<p>І вуаля, <code class="language-plaintext highlighter-rouge">\r</code> (<em>reload</em>) перевіряє типи в модулі, все нормально. Прямо з Віма пробуємо <code class="language-plaintext highlighter-rouge">\e</code> (<em>expression/evaluate</em>?), вводимо <code class="language-plaintext highlighter-rouge">ins_sort [5,1,4,3,2]</code> і в вікні Віма (яке з’являється по <code class="language-plaintext highlighter-rouge">\i</code>, <em>interactive</em>?) бачимо відповідь:</p>

<div class="language-idris highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">=</span> <span class="p">[</span><span class="mf">1</span><span class="p">,</span> <span class="mf">2</span><span class="p">,</span> <span class="mf">3</span><span class="p">,</span> <span class="mf">4</span><span class="p">,</span> <span class="mf">5</span><span class="p">]</span> <span class="o">:</span> <span class="kt">Vect</span> <span class="mf">5</span> <span class="kt">Integer</span>
</code></pre></div></div>

        ]]>
      </description>
    </item>
    
     
    <item>
      <title>Coq: when general is simpler</title>
      <link>https://dmytrish.net/en/coq-simpler-general</link>
      <pubDate>Mon, 01 Aug 2016 11:34:56 +0200</pubDate>
      <guid isPermaLink="true">https://dmytrish.net/en/coq-simpler-general</guid>
      <category>
        <![CDATA[en]]>
      </category>
      <description>
        <![CDATA[
          <p>Today I learned a thing about generalization: sometimes it is the only way to solve a problem even though it may be quite non-obvious.</p>

<p>At the moment I am reading “Software Foundations” by B. Pierce and currently I’m making my way through <code class="language-plaintext highlighter-rouge">Imp.v</code>. It shows a tiny language of arithmetical expressions (pure and halting!):</p>

<div class="language-coq highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">(** Syntax *)</span><span class="w">
</span><span class="k">Inductive</span><span class="w"> </span><span class="no">aexp</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="kr">Type</span><span class="w"> </span><span class="p">:=</span><span class="w">
  </span><span class="p">|</span><span class="w"> </span><span class="no">ANum</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">nat</span><span class="w"> </span><span class="o">-&gt;</span><span class="w"> </span><span class="no">aexp</span><span class="w">
  </span><span class="p">|</span><span class="w"> </span><span class="no">AId</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">id</span><span class="w"> </span><span class="o">-&gt;</span><span class="w"> </span><span class="no">aexp</span><span class="w">  
  </span><span class="p">|</span><span class="w"> </span><span class="no">APlus</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">aexp</span><span class="w"> </span><span class="o">-&gt;</span><span class="w"> </span><span class="no">aexp</span><span class="w"> </span><span class="o">-&gt;</span><span class="w"> </span><span class="no">aexp</span><span class="w">
  </span><span class="p">|</span><span class="w"> </span><span class="no">AMinus</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">aexp</span><span class="w"> </span><span class="o">-&gt;</span><span class="w"> </span><span class="no">aexp</span><span class="w"> </span><span class="o">-&gt;</span><span class="w"> </span><span class="no">aexp</span><span class="w">
  </span><span class="p">|</span><span class="w"> </span><span class="no">AMult</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">aexp</span><span class="w"> </span><span class="o">-&gt;</span><span class="w"> </span><span class="no">aexp</span><span class="w"> </span><span class="o">-&gt;</span><span class="w"> </span><span class="no">aexp</span><span class="pi">.</span><span class="w"> 
</span><span class="c">(** Evaluation *)</span><span class="w">
</span><span class="k">Fixpoint</span><span class="w"> </span><span class="no">aeval</span><span class="w"> </span><span class="p">(</span><span class="no">st</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">state</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="no">a</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">aexp</span><span class="p">)</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">nat</span><span class="w"> </span><span class="p">:=</span><span class="w">
  </span><span class="kr">match</span><span class="w"> </span><span class="no">a</span><span class="w"> </span><span class="kp">with</span><span class="w">
  </span><span class="p">|</span><span class="w"> </span><span class="no">ANum</span><span class="w"> </span><span class="no">n</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="no">n</span><span class="w">
  </span><span class="p">|</span><span class="w"> </span><span class="no">AId</span><span class="w"> </span><span class="no">x</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="no">st</span><span class="w"> </span><span class="no">x</span><span class="w">
  </span><span class="p">|</span><span class="w"> </span><span class="no">APlus</span><span class="w"> </span><span class="no">a1</span><span class="w"> </span><span class="no">a2</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">(</span><span class="no">aeval</span><span class="w"> </span><span class="no">st</span><span class="w"> </span><span class="no">a1</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="p">(</span><span class="no">aeval</span><span class="w"> </span><span class="no">st</span><span class="w"> </span><span class="no">a2</span><span class="p">)</span><span class="w">
  </span><span class="p">|</span><span class="w"> </span><span class="no">AMinus</span><span class="w"> </span><span class="no">a1</span><span class="w"> </span><span class="no">a2</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">(</span><span class="no">aeval</span><span class="w"> </span><span class="no">st</span><span class="w"> </span><span class="no">a1</span><span class="p">)</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="p">(</span><span class="no">aeval</span><span class="w"> </span><span class="no">st</span><span class="w"> </span><span class="no">a2</span><span class="p">)</span><span class="w">
  </span><span class="p">|</span><span class="w"> </span><span class="no">AMult</span><span class="w"> </span><span class="no">a1</span><span class="w"> </span><span class="no">a2</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">(</span><span class="no">aeval</span><span class="w"> </span><span class="no">st</span><span class="w"> </span><span class="no">a1</span><span class="p">)</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="p">(</span><span class="no">aeval</span><span class="w"> </span><span class="no">st</span><span class="w"> </span><span class="no">a2</span><span class="p">)</span><span class="w">
  </span><span class="kr">end</span><span class="pi">.</span><span class="w">
</span></code></pre></div></div>

<p>and a tiny virtual machine for evaluating expressions in this language:</p>

<figure class="highlight"><pre><code class="language-coq" data-lang="coq"><span class="k">Inductive</span><span class="w"> </span><span class="no">id</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="kr">Type</span><span class="w"> </span><span class="p">:=</span><span class="w"> </span><span class="no">Id</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">nat</span><span class="w"> </span><span class="o">-&gt;</span><span class="w"> </span><span class="no">id</span><span class="pi">.</span><span class="w">

</span><span class="k">Inductive</span><span class="w"> </span><span class="no">sinstr</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="kr">Type</span><span class="w"> </span><span class="p">:=</span><span class="w">
  </span><span class="p">|</span><span class="w"> </span><span class="no">SPush</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">nat</span><span class="w"> </span><span class="o">-&gt;</span><span class="w"> </span><span class="no">sinstr</span><span class="w">  </span><span class="c">(* load a constant on the stack *)</span><span class="w">
  </span><span class="p">|</span><span class="w"> </span><span class="no">SLoad</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">id</span><span class="w"> </span><span class="o">-&gt;</span><span class="w"> </span><span class="no">sinstr</span><span class="w">   </span><span class="c">(* load a value from the environment on the stack *)</span><span class="w">
  </span><span class="p">|</span><span class="w"> </span><span class="no">SPlus</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">sinstr</span><span class="w">    </span><span class="c">(* take two values from the stack, push their sum back *)</span><span class="w">
  </span><span class="p">|</span><span class="w"> </span><span class="no">SMinus</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">sinstr</span><span class="w">
  </span><span class="p">|</span><span class="w"> </span><span class="no">SMult</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">sinstr</span><span class="pi">.</span><span class="w"> </span></code></pre></figure>

<p>It is stack-based (it loads constants or values from an environment on stack and leaves its result there):</p>

<div class="language-coq highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">Fixpoint</span><span class="w"> </span><span class="no">s_execute</span><span class="w"> </span><span class="p">(</span><span class="no">st</span><span class="p">:</span><span class="w"> </span><span class="no">state</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="no">stack</span><span class="p">:</span><span class="w"> </span><span class="no">list</span><span class="w"> </span><span class="no">nat</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="no">prog</span><span class="p">:</span><span class="w"> </span><span class="no">list</span><span class="w"> </span><span class="no">sinstr</span><span class="p">)</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">list</span><span class="w"> </span><span class="no">nat</span><span class="w"> 
</span><span class="c">(**
  I will not post the body of this function to fulfil 
  the request of the book author to avoid posting solutions 
  to exercises in public; the only thing I say about it is
  that my version ignores stack underflow: the stack is 
  not changed by [SPlus]/[SMult]/[SMinus] if there are
  less than two values on it 
**)</span><span class="w">
</span></code></pre></div></div>

<p>The next necessity is a compiler from <code class="language-plaintext highlighter-rouge">aexp</code> to <code class="language-plaintext highlighter-rouge">list sinst</code>:</p>

<div class="language-coq highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">Fixpoint</span><span class="w"> </span><span class="no">s_compile</span><span class="w"> </span><span class="p">(</span><span class="no">e</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">aexp</span><span class="p">)</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">list</span><span class="w"> </span><span class="no">sinstr</span><span class="w"> </span><span class="p">:=</span><span class="w"> </span><span class="c">(* censored *)</span><span class="w">
</span></code></pre></div></div>

<p>The climax of this exercise is proving <code class="language-plaintext highlighter-rouge">s_compile</code> correct, i.e.</p>

<div class="language-coq highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">Theorem</span><span class="w"> </span><span class="no">s_compile_correct</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="kr">forall</span><span class="w"> </span><span class="p">(</span><span class="no">st</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">state</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="no">e</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">aexp</span><span class="p">),</span><span class="w">
   </span><span class="no">s_execute</span><span class="w"> </span><span class="no">st</span><span class="w"> </span><span class="p">[]</span><span class="w"> </span><span class="p">(</span><span class="no">s_compile</span><span class="w"> </span><span class="no">e</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="no">aeval</span><span class="w"> </span><span class="no">st</span><span class="w"> </span><span class="no">e</span><span class="w"> </span><span class="p">]</span><span class="pi">.</span><span class="w">
</span></code></pre></div></div>

<p>(I hope that the following text does not count as a ready solution, rather as a hint).</p>

<p>After some fiddling with the assertion, it became obvious that it would be useful to define small-step lemmas:</p>

<div class="language-coq highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">Lemma</span><span class="w"> </span><span class="no">s_execute_step</span><span class="w"> </span><span class="p">:</span><span class="w">
  </span><span class="kr">forall</span><span class="w"> </span><span class="p">(</span><span class="no">st</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">state</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="no">s</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">list</span><span class="w"> </span><span class="no">nat</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="no">i</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">sinstr</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="no">p</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">list</span><span class="w"> </span><span class="no">sinstr</span><span class="p">),</span><span class="w">
    </span><span class="no">s_execute</span><span class="w"> </span><span class="no">st</span><span class="w"> </span><span class="no">s</span><span class="w"> </span><span class="p">(</span><span class="no">i</span><span class="w"> </span><span class="p">::</span><span class="w"> </span><span class="no">p</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="no">s_execute</span><span class="w"> </span><span class="no">st</span><span class="w"> </span><span class="p">(</span><span class="no">s_execute</span><span class="w"> </span><span class="no">st</span><span class="w"> </span><span class="no">s</span><span class="w"> </span><span class="p">[</span><span class="no">i</span><span class="p">])</span><span class="w"> </span><span class="no">p</span><span class="pi">.</span><span class="w">

</span><span class="k">Lemma</span><span class="w"> </span><span class="no">s_execute_map</span><span class="w"> </span><span class="p">:</span><span class="w">
  </span><span class="kr">forall</span><span class="w"> </span><span class="p">(</span><span class="no">st</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">state</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="no">s</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">list</span><span class="w"> </span><span class="no">nat</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="no">p1</span><span class="w"> </span><span class="no">p2</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">list</span><span class="w"> </span><span class="no">sinstr</span><span class="p">),</span><span class="w">
    </span><span class="no">s_execute</span><span class="w"> </span><span class="no">st</span><span class="w"> </span><span class="no">s</span><span class="w"> </span><span class="p">(</span><span class="no">p1</span><span class="w"> </span><span class="o">++</span><span class="w"> </span><span class="no">p2</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="no">s_execute</span><span class="w"> </span><span class="no">st</span><span class="w"> </span><span class="p">(</span><span class="no">s_execute</span><span class="w"> </span><span class="no">st</span><span class="w"> </span><span class="no">s</span><span class="w"> </span><span class="no">p1</span><span class="p">)</span><span class="w"> </span><span class="no">p2</span><span class="pi">.</span><span class="w">
</span></code></pre></div></div>

<p>Having been armed with this lemmas, I started tackling the theorem. Quite quickly I decided to assert that the language of aexp cannot modify the stack below its expression (<code class="language-plaintext highlighter-rouge">s_compile</code> never produces a <code class="language-plaintext highlighter-rouge">list sinstr</code> that underflows the stack):</p>

<div class="language-coq highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">Lemma</span><span class="w"> </span><span class="no">aexp_never_underflows</span><span class="p">:</span><span class="w">
  </span><span class="kr">forall</span><span class="w"> </span><span class="p">(</span><span class="no">st</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">state</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="no">s</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">list</span><span class="w"> </span><span class="no">nat</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="no">e</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">aexp</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="no">v</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">nat</span><span class="p">),</span><span class="w">
   </span><span class="no">s_execute</span><span class="w"> </span><span class="no">st</span><span class="w"> </span><span class="p">[]</span><span class="w"> </span><span class="p">(</span><span class="no">s_compile</span><span class="w"> </span><span class="no">e</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="no">v</span><span class="p">]</span><span class="w"> </span><span class="o">-&gt;</span><span class="w"> </span><span class="no">s_execute</span><span class="w"> </span><span class="no">st</span><span class="w"> </span><span class="no">s</span><span class="w"> </span><span class="p">(</span><span class="no">s_compile</span><span class="w"> </span><span class="no">e</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="no">v</span><span class="w"> </span><span class="p">::</span><span class="w"> </span><span class="no">s</span><span class="pi">.</span><span class="w">
</span></code></pre></div></div>

<p>and tried to prove this lemma. The funny thing was that this lemma seemed to be dependent on <code class="language-plaintext highlighter-rouge">s_compile_correct</code> and vice versa! After some time (I am omitting the related emotional rollercoaster) I realized that it’s not going to work and tried to step back to get the big picture. The lucky idea was to combine the lemmas into one (why not?):</p>

<div class="language-coq highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">Lemma</span><span class="w"> </span><span class="no">s_compile_correct_s</span><span class="w"> </span><span class="p">:</span><span class="w"> 
  </span><span class="kr">forall</span><span class="w"> </span><span class="p">(</span><span class="no">st</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">state</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="no">e</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">aexp</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="no">s</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">list</span><span class="w"> </span><span class="no">nat</span><span class="p">),</span><span class="w">
    </span><span class="no">s_execute</span><span class="w"> </span><span class="no">st</span><span class="w"> </span><span class="no">s</span><span class="w"> </span><span class="p">(</span><span class="no">s_compile</span><span class="w"> </span><span class="no">e</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="no">aeval</span><span class="w"> </span><span class="no">st</span><span class="w"> </span><span class="no">e</span><span class="w"> </span><span class="p">::</span><span class="w"> </span><span class="no">s</span><span class="p">)</span><span class="pi">.</span><span class="w">
</span></code></pre></div></div>

<p>As soon as I had it written down, I realized that it’s not a lemma, it’s the theorem I am going after! It’s a more general version of <code class="language-plaintext highlighter-rouge">s_compile_correct</code> that I’ve been told to prove! To save your time scrolling back, here is <code class="language-plaintext highlighter-rouge">s_compile_correct</code>:</p>

<div class="language-coq highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">Theorem</span><span class="w"> </span><span class="no">s_compile_correct</span><span class="w"> </span><span class="p">:</span><span class="w">
  </span><span class="kr">forall</span><span class="w"> </span><span class="p">(</span><span class="no">st</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">state</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="no">e</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="no">aexp</span><span class="p">),</span><span class="w">
    </span><span class="no">s_execute</span><span class="w"> </span><span class="no">st</span><span class="w"> </span><span class="p">[]</span><span class="w"> </span><span class="p">(</span><span class="no">s_compile</span><span class="w"> </span><span class="no">e</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="no">aeval</span><span class="w"> </span><span class="no">st</span><span class="w"> </span><span class="no">e</span><span class="w"> </span><span class="p">]</span><span class="pi">.</span><span class="w">
</span><span class="k">Proof</span><span class="pi">.</span><span class="w">
  </span><span class="kp">intros</span><span class="pi">.</span><span class="w"> </span><span class="kp">apply</span><span class="w"> </span><span class="no">s_compile_correct_s</span><span class="pi">.</span><span class="w">
  </span><span class="c">(* I hope this solution is trivial enough to publish it *)</span><span class="w">
</span><span class="k">Qed</span><span class="pi">.</span><span class="w">
</span></code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">s_compile_correct_s</code> was not the easiest thing to prove, but it was doable and straightforward, compared to my previous roundabout wandering in the maze of special cases.</p>

<p><strong>Conclusion</strong>: Even though I knew the concept that some problems are much easier in a generalized form, this exercise was a real eye-opener: sometimes it takes a lot of time and effort to recognize a subtle need for generalization.</p>

        ]]>
      </description>
    </item>
    
     
    <item>
      <title>SMT solvers for fun and profit</title>
      <link>https://dmytrish.net/uk/smt-fun-profit</link>
      <pubDate>Mon, 01 Feb 2016 11:34:56 +0100</pubDate>
      <guid isPermaLink="true">https://dmytrish.net/uk/smt-fun-profit</guid>
      <category>
        <![CDATA[uk]]>
      </category>
      <description>
        <![CDATA[
          <p>Дивлюсь початок курсу із логіки на Курсері, і там давали квіз на перевірку формул, зокрема такої:</p>

<p><code class="language-plaintext highlighter-rouge">((¬r ⇒ ¬p ∧ ¬q) ∨ s) ⇔ (p ∨ q ⇒ r ∨ s)</code></p>

<p>Виписувати таблицю істиності на 16 комбінацій мені стало страшно.
Я схитрив і побачив, що для <code class="language-plaintext highlighter-rouge">s=1</code> ця формула тавтологічна, а от для <code class="language-plaintext highlighter-rouge">s=0</code> довелось попереписувати:</p>

<p><code class="language-plaintext highlighter-rouge">(¬r ⇒ ¬p ∧ ¬q) ⇔ (p ∨ q ⇒ r)</code></p>

<p>помітити, що <code class="language-plaintext highlighter-rouge">¬p ∧ ¬q ⇔ ¬(p ∨ q)</code>  за де Морганом, отже</p>

<p><code class="language-plaintext highlighter-rouge">(¬r ⇒ ¬(p ∨ q)) ⇔ (p ∨ q ⇒ r)</code></p>

<p>довелось ще помітити, що, оскільки <code class="language-plaintext highlighter-rouge">(¬x ⇒ ¬y) ⇔ (y ⇒ x)</code>, то формула при s=0 також вироджується в тавтологію.</p>

<p>А потім згадав, що є такі чудові штуки, як SMT-солвери, і, розчехливши цю гармату, таки вистрілив по горобцях:</p>

<figure class="highlight"><pre><code class="language-lisp" data-lang="lisp"><span class="nv">$</span> <span class="nv">rlwrap</span> <span class="nv">z3</span> <span class="nv">-smt2</span> <span class="nv">-in</span>
<span class="c1">;; описуємо наші змінні:</span>
<span class="p">(</span><span class="nv">declare-const</span> <span class="nv">p</span> <span class="nv">Bool</span><span class="p">)</span>
<span class="p">(</span><span class="nv">declare-const</span> <span class="nv">q</span> <span class="nv">Bool</span><span class="p">)</span>
<span class="p">(</span><span class="nv">declare-const</span> <span class="nv">r</span> <span class="nv">Bool</span><span class="p">)</span>
<span class="p">(</span><span class="nv">declare-const</span> <span class="nv">s</span> <span class="nv">Bool</span><span class="p">)</span> 

<span class="c1">;; ((¬r ⇒ ¬p ∧ ¬q) ∨ s) ⇔ (p ∨ q ⇒ r ∨ s)</span>
<span class="p">(</span><span class="nv">define-fun</span> <span class="nv">lhs</span> <span class="p">()</span> <span class="nv">Bool</span>
  <span class="p">(</span><span class="nb">or</span> <span class="p">(</span><span class="nv">=&gt;</span> <span class="p">(</span><span class="nb">not</span> <span class="nv">r</span><span class="p">)</span> <span class="p">(</span><span class="nb">and</span> <span class="p">(</span><span class="nb">not</span> <span class="nv">p</span><span class="p">)</span> <span class="p">(</span><span class="nb">not</span> <span class="nv">q</span><span class="p">)))</span> <span class="nv">s</span><span class="p">))</span>
<span class="p">(</span><span class="nv">define-fun</span> <span class="nv">rhs</span> <span class="p">()</span> <span class="nv">Bool</span>
  <span class="p">(</span><span class="nv">=&gt;</span> <span class="p">(</span><span class="nb">or</span> <span class="nv">p</span> <span class="nv">q</span><span class="p">)</span> <span class="p">(</span><span class="nb">or</span> <span class="nv">r</span> <span class="nv">s</span><span class="p">)))</span>
<span class="p">(</span><span class="nv">define-fun</span> <span class="nv">conjecture</span> <span class="p">()</span> <span class="nv">Bool</span>
  <span class="p">(</span><span class="nb">=</span> <span class="nv">lhs</span> <span class="nv">rhs</span><span class="p">))</span>

<span class="p">(</span><span class="nb">push</span><span class="p">)</span> <span class="c1">;; зберігаємо стан без припущень</span>
<span class="p">(</span><span class="nb">assert</span> <span class="nv">conjecture</span><span class="p">)</span>  <span class="c1">;; робимо припущення, що формула conjecture задовольняється</span>
<span class="p">(</span><span class="nv">check-sat</span><span class="p">)</span> <span class="c1">;sat    ;; так, існують truth assignments, за яких це так</span>

<span class="p">(</span><span class="nb">pop</span><span class="p">)</span> <span class="c1">;; позбавляємось припущення істинності conjecture</span>
<span class="p">(</span><span class="nb">assert</span> <span class="p">(</span><span class="nb">not</span> <span class="nv">conjecture</span><span class="p">))</span>
<span class="p">(</span><span class="nv">check-sat</span><span class="p">)</span> <span class="c1">;unsat   ;; не існує truth assignment, за яких формула заперечується </span>

<span class="c1">;; `conjecture` is satisfiable and its negation is not,</span>
<span class="c1">;; so it's valid.(exit)</span></code></pre></figure>

<p>Спробувати це онлайн можна тут: <a href="http://rise4fun.com/z3">http://rise4fun.com/z3</a>.</p>


        ]]>
      </description>
    </item>
    
     
    <item>
      <title>Thoughts on Brainfuck decompilation</title>
      <link>https://dmytrish.net/en/brainfuck-decompiler</link>
      <pubDate>Mon, 22 Jun 2015 11:34:56 +0200</pubDate>
      <guid isPermaLink="true">https://dmytrish.net/en/brainfuck-decompiler</guid>
      <category>
        <![CDATA[en]]>
      </category>
      <description>
        <![CDATA[
          <p>Yesterday I wrote a <a href="https://github.com/EarlGray/language-snippets/commit/a13617a70cf09ee586014a65d3db4c0461d24219">primitive Brainfuck decompiler</a>. At the moment the only useful thing it does is that it eliminates <code class="language-plaintext highlighter-rouge">&gt;</code>, <code class="language-plaintext highlighter-rouge">&lt;</code>, rewrites <code class="language-plaintext highlighter-rouge">[</code> and <code class="language-plaintext highlighter-rouge">]</code> into labels and compresses <code class="language-plaintext highlighter-rouge">+</code>,<code class="language-plaintext highlighter-rouge">-</code> into <code class="language-plaintext highlighter-rouge">"add [0], 4"</code>-like commands. For example:</p>

<figure class="highlight"><pre><code class="language-asm" data-lang="asm">$ cat bf/hello2.bf 

++++++++++[&gt;+++++++&gt;++++++++++&gt;+++&gt;+&lt;&lt;&lt;&lt;-]
 &gt;++.&gt;+.+++++++..+++.&gt;++.&lt;&lt;+++++++++++++++.
 &gt;.+++.------.--------.&gt;+.&gt;.

$ runhaskell bfdecomp.hs &lt; bf/hello2.bf 
  add [0] 10
  bz  [0] f1
b1:
  add [1] 7
  add [2] 10
  add [3] 3
  add [4] 1
  sub [0] 1
  bnz [0] b1
f1:
  add [1] 2
  put [1]
  add [2] 1
  put [2]
  add [2] 7
  put [2]
  put [2]
  add [2] 3
  put [2]
  add [3] 2
  put [3]
  add [1] 15
  put [1]
  put [2]
  add [2] 3
  put [2]
  sub [2] 6
  put [2]
  sub [2] 8
  put [2]
  add [3] 1
  put [3]
  put [4]</code></pre></figure>

<p>I thought that I could recover some patterns pretty easily, for example, <code class="language-plaintext highlighter-rouge">[-]</code> is equvalent to setting the current cell to 0. But why it does it? How to determine whether the cycle terminates? What tools are helpful there?</p>

<p>First of all, I don’t want to make Brainfuck programs completely static, my goal here is to recover as many facts about the program as possible and to do maximum partial evaluation. In general, if a progam does not depend on input, it’s even safe to “replay” it and to emulate its behavior with <code class="language-plaintext highlighter-rouge">put $val1; put $val2; ...</code>. But here is the first hurdle: what if it is an endless loop? First we have to prove that the loop terminates. That part in general is undecidable (it is basically the halting problem), but some partial evaluations are quite possible.</p>

<p>Recently I had a look at <a href="http://fbinfer.com/">Facebook Infer</a>, a fast static analyser for Java/C programs that infers pre/postconditions of functions on its own. It’s a pretty neat idea and the separation logic behind it looks attractive, so I wanted to apply some of it to the primitiveness of BrainFck.</p>

<p>Let’s apply Hoare triples here. First of all, we have to infer effects of primitive operations (let <code class="language-plaintext highlighter-rouge">p</code> be the data pointer, <code class="language-plaintext highlighter-rouge">[p]</code> - the contents of the current cell) like that:</p>

<p><code>add [p] n</code>
\(p_{post} = p_{pre}, [p]_{post} = [p]_{pre} + n;\)</p>

<p>Then we need our program to understand arithmetics: for example, it must know that <code class="language-plaintext highlighter-rouge">add [p] n</code>, applied to <code class="language-plaintext highlighter-rouge">[p]</code> <code class="language-plaintext highlighter-rouge">m</code> times, is equal to <code class="language-plaintext highlighter-rouge">add [p] n*m</code>. Then we need to be able to reason about variables: e.g. <code class="language-plaintext highlighter-rouge">&gt;++++&lt;-</code> does not move the data pointer, or, in other words, we must be able to figure out that \(a_{pre} = a_{0}\), \(a_1 = a_0 + 1\), \(a_2 = a_1 - 1 = a_0 + 1 - 1 = a_0\), so \(a_{pre}=a_{post}\); the contents of cells must obey rules: \([a_0]_{post} = [a_0]_{pre} - 1\), \([a_1]_{post} = [a_1]_{pre} + 4\)</p>

<p><code class="language-plaintext highlighter-rouge">get</code>/<code class="language-plaintext highlighter-rouge">put</code> are not like other operations: we have to preserve their effects. Any value introduced by get must be “poisoned”, we only know that it may be in range from 0 to 255 and is determined at run-time. When multiplied with another value, it must “poison” the result.</p>

<p>When I had a look at <a href="https://github.com/EarlGray/language-snippets/blob/master/bf/bf/bfi.bf">BF self-interpreter</a>, I was a little shocked: I thought that people are not that smart to smash runtime pointers so freely with constructs like <code class="language-plaintext highlighter-rouge">[&lt;]</code> (“move left until a cell with zero in it found”) and <code class="language-plaintext highlighter-rouge">[-[-&gt;]]</code>. Now I have to think how to handle such situations without going crazy and how to recover facts about non-zero data regions. But it looks like here I will fight the concrete wall of Turing completeness</p>


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

