(This post is part of a series, all with the same title)

Executable examples of the SICMechanics book within an HTML page

Our little Scheme syntax to JS compiler (developed in the last few blog posts) is now in a state to run all 109 examples of the first part of the SICMechanics book.

The according html-file with the original Scheme examples is embedded below as an IFrame.

<iframe id="book-part1" sandbox="allow-same-origin" src="/blog/html/sicmutils-as-js-book-part1.html" width="600" height="100" scrolling="no"></iframe>

Click here to see the full html page with the examples executed online. We also mention that they can be viewed as a visual version in clj-tiles.

The html file is not only meant to be changed on-line, but also to be read as source code for both the Scheme examples and their tailor-made syntax compiler. This blog post helps with that reading, giving an outline of the technical implementation of that file. However, it is not the goal of this post to explain Theoretical Physics, which is the specific topic of SICM (and its showcase being the purpose of the html-file).

Every example in that html file is a Klipse snippet. To give a simple preview, we import a small JavaScript snippet from the source.


   

   

You can modify every piece of code directly in the page to immediate effect, maybe change 3 to 4 directly above and see what happens.

We already mention here that even the Scheme syntax compiler is just such a JavaScript snippet. In fact, the compiler does exist only as Klipse snippet within an html file. There is no other source file for it.

Header of the HTML file

Lets start with the file content. In the header we do four things: (1) prepare for mobile devices (2) load the stylesheet for Codemirror, (3) configure Klipse to allow execution of JavaScript (4) set the Klipse+Codemirror mode to Scheme-Language code formatting.

Note that these are all just settings and no JavaScript code is executed just yet. In fact, Klipse+Codemirror is only executed in the footer of the html file.

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="stylesheet" type="text/css" href="https://storage.googleapis.com/app.klipse.tech/css/codemirror.css">

        <script>
     window.klipse_settings = {
         selector_eval_js: '.language-klipse-eval-js',
         selector_eval_scheme: '.language-klipse-scheme, .language-eval-scheme',
         codemirror_options_in: {
             mode: 'scheme'
         }
     };
        </script>
    </head>
<body>

Then Sicmutils is loaded as a JavaScript library.

<script src="https://kloimhardt.github.io/blog/js/main.js"></script>

This specific library was compiled according to the instructions found here[1].

Next comes a helper function for loading variables from the Sicmutils environment.

<script>
    var loadEnv = (name) => {
    window[name] = sicmutils.env[name];
    return name;
    }
</script>

The rest of the HTML file

Next comes a speciality: in order to activate the Scheme-Language formatting of Codemirror, we need to execute once some code using Klipse's very own Scheme interpreter (yes, it also has one, albeit of no further use). Consequently, class="language-klipse-scheme" is never used again afterwards in the file.

    <pre id="klipse-scheme"><code class="language-klipse-scheme">
#t
    </code></pre>

    

    

Then our little Scheme syntax compiler is added, it is just another Klipse JavaScript snippet. Here we show the first lines, it has in total about 160 lines of code only. It is tailor-made (e.g. no if-then clause) and depends heavily on Sicmutils' functionality.

    <pre id="compiler"><code class="language-klipse-eval-js">
["pi", "_pi", "state__GT_t"].map(loadEnv);

var symbol = cljs.core.symbol;
var _COLON_pi = pi;
...
    </code></pre>

    

    

The code just loaded exposes the function expressionToJs. We patch the JavaScript eval function to invoke expressionToJs whenever some code starts with a round bracket (.

<script>
     var _2_eval = window.eval;
     var _3_eval = (txt) =>
         txt[0] === "("
         ? _2_eval(expressionToJs(txt))
         : _2_eval(txt);
     window.eval = _3_eval;
</script>

Finally, we want to try out our brand new Scheme compiler.

    <pre id="prefix-123"><code class="language-klipse-eval-js">
(+ 1 2 3) 
    </code></pre>

    

    

Also this Scheme code can be changed to immediate effect. Maybe change the 3 to 4. Make sure that the blank character is at the end of a Scheme code snippet (omitting it is a feature that turns off compilation).

Next, let's calculate the cosine of pi, which results in minus one.


    

    

Now, modify the compiler itself. Go up and change _COLON_pi = pi; to _COLON_pi = 3.0;. Then come back and add another blank to the snippet(cos :pi) to see that the result indeed changes (to a wrong value).

As noted above, we do not use Klipse in its own Scheme mode, but in (eval-patched) JavaScript mode. You could easily write some JavaScript in the above (or any) box, just make sure not to start with a (. Remember, the ( triggers our syntax compiler -- the one that you just put a pi bug into (fortunatelly only locally and until you browser-reload this blog).

What follows is a bit more of an interesting example. The code is not manually written. Like the Scheme compiler itself, it is automatically imported from the IFRame of the source html above. The addSnippet command used to import code is demonstrated in the previous blog.


    

    

To finish up, we execute another example of the SICMechanics book, an even juicier one.


    

    

    


    

    

    

The footer of the html file finally loads Klipse.

<script src="https://storage.googleapis.com/app.klipse.tech/plugin_prod/js/klipse_plugin.min.js"></script>
</body>
</html>

This ends the exposition.

[1] To build sicmutils as JavaScript library, follow the instrunctions of its demo directory. The command shadow-cljs release sicm-browser is used. There is one additonal thing to do before you use this command: you need to change the compiler-options in shadow-cljs.edn from :advanced to :simple. The resulting js-file size is 6MB, which means it can take up some downlload time in our html-file.