Permalink
Branch: master
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
233 lines (226 sloc) 8.71 KB
---
layout: post
title: 'ajsone'
subtitle: 'Abusing JSON Esolang'
permalink: '/ajsone/'
tags: ['esolang', 'compiler']
---
<script type="text/javascript" src="/jquery-1.7.1.min.js"></script>
<script type="text/javascript" src="/files/2014/ajsone/ajsone.js"></script>
<script type="text/javascript" src="/files/2014/ajsone/ajsone_utils.js"></script>
<div class="lead">
<p>
Ajsone is an esoteric programming language designed for fun. The language
abuses JSON by using the JSON data format to represent everything: functions, variables, values, etc.
</p>
<p>
If you have never played with esoteric languages, keep in mind that writing even the
most trivial algorithms can be <nobr>mindblowing ( <img style="display: inline; vertical-align: middle;
margin: 0" width="50" height="33" src="/files/2014/ajsone/mindblown.gif"> ).</nobr>
</p>
<p>
Before looking at how the language works, here is a simple piece of code which
computes the factorial of 5:
<pre class="prettyprint linenums lang-json">
{
"fact": {
"=if": {
"cond": {"=<=": {"in1": "=n", "in2": 1}},
"then": 1,
"else": {
"t": {"=-": {"in1": "=n", "in2": 1}},
"=*": {"in1": "=n", "in2": {"=fact": {"n": "=t"}}}}
}
},
"=fact": {"n": 5}
}
</pre>
</p>
<p>
Read on to learn more and try out the interpreter!
</p>
</div>
<section>
<div class="page-header"><h3>Syntax</h3></div>
<p>
Ajsone represents everything as <a class="external" href="http://www.json.org/">JSON</a>. Given that everyone knows
JSON, there is no need to go into the details of the grammar.
</p>
<p>
Tying the grammar to JSON has some disadvantages. <a href="http://en.wikipedia.org/wiki/Sarcasm" class="external">Serious users are therefore encouraged to implement a pre-processor</a>
to support features like comments
or <a href="https://github.com/facebook/hhvm/commit/c1b7da6a4c128af5ddfc75f515c205de9f417a1e" class="external">trailing
commas</a>.
</p>
</section>
<section>
<div class="page-header"><h3>Static Semantics</h3></div>
<p>
Ajsone is a functional (as in functional programming, not to be confused with useful), untyped
, <span style="text-decoration: line-through">lazy</span>, and dynamically scoped programming language.
</p>
<p style="font-style: italic">
I initially tried making the language lazy evaluation based, but I wasn't able to get things to work
in a "reasonable" way. I kept running into weird recursive definitions due to dynamic scope.
<p>
Most JSON values have their usual semantics. Strings which begin with the '=' character and JSON objects get
special treatment.
</p>
<ul>
<li>"hello world" -> the "hello world" string.</li>
<li>12.34 -> a number between 12 and 13.</li>
<li>["foo", "bar", 42] -> an array with 3 elements</li>
<li>true -> a boolean</li>
<li>false -> the other boolean</li>
<li>null -> null</li>
</ul>
<p>
JSON key-value objects represent functions.
</p>
<p>
JSON key-value objects which contain other key-value objects as values are nested functions.
</p>
<p>
The last key of a key-value object is the return value of the function. E.g. the following code assigns <code>1</code>
to <code>x</code> and returns the value of <code>x</code>, i.e. returns <code>1</code>:
</p>
<pre class="prettyprint linenums lang-json">
{
"x": 1
}
</pre>
<p>
Each function creates a new dynamic scope, which continues to live in the nested functions. In the following piece of
code, <code>x</code> is
assigned <code>1</code>, and <code>y</code> is just a temporary variable.
</p>
<p>
There is no explicit variable declaration, so the scope
starts when a variable is first assigned.
</p>
<pre class="prettyprint linenums lang-json">
{
"x": { "y": 1 }
}
</pre>
<p>
Strings which begin with <code>=</code> are evaluated (think of it as
function application or variable de-reference depending of the context).
</p>
<p>
The following piece of code assigns <code>1</code> to <code>x</code> and then
assigns the value of <code>x</code> to <code>y</code>.
</p>
<pre class="prettyprint linenums lang-json">
{
"x": 1,
"y": "=x"
}
</pre>
<p>And is equivalent to:</p>
<pre class="prettyprint linenums lang-json">
{
"x": 1,
"y": {"=x": null}
}
</pre>
<p>
Note: since JSON keys must be unique within an object, Ajsone code feels like
static single assignment (SSA).
</p>
</section>
<section>
<div class="page-header"><h3>Dynamic Semantics</h3></div>
<p>
There is no "main", the JSON tree represents the entire program, and
the last expression is the result of the program.
</p>
<p>
The following program reads the declaration of <code>x</code> and <code>y</code>
and returns the value of <code>z</code>. <code>z</code> overwrites <code>x</code> and
returns the result of <code>y</code>, which ends up being 2.
</p>
<p>The following program returns 2.</p>
<pre class="prettyprint linenums lang-json">
{
"x": 1,
"y": { "foo": "=x"},
"z": {
"x": 2,
"_": {"bar": "=y"}
}
}
</pre>
<p>
Functions don't declare their inputs, they just read variable from the global scope. This imples
parameters can be omitted. The following two pieces of code are (almost) equivalent:
</p>
<pre class="prettyprint linenums lang-json">
{
"arr": [1, 2, 3],
"=arr.len": { "arr": "=arr" }
}
</pre>
and:
<pre class="prettyprint linenums lang-json">
{
"arr": [1, 2, 3],
"=arr.len": {}
}
</pre>
<p>
When using recusion, we need a way to create local variables. The way this is achieved is by pushing the
value part of the key-value function call on a new scope and discarding it when the function returns.
</p>
</section>
<section>
<div class="page-header"><h3>Built-ins</h3></div>
<p>
The language provides the following built-in operators. The argument types for each
of these built-ins is checked at runtime.
</p>
<ul>
<li>if: checks <code>cond</code> and returns <code>=then</code> when true, <code>=else</code> otherwise.</li>
<br/>
<li>+, -, *, /: usual math operators. Numerical parameters are expected in <code>in1</code> and <code>in2</code>.</li>
<li><, <=, >, >=, ==, !=: usual comparator operators. Numerical parameters are expected in <code>in1</code> and <code>in2</code>.</li>
<li>&&, ||: usual boolean operators. Boolean parameters are expected in <code>in1</code> and <code>in2</code>.</li>
<li>&, |, ~: usual binary operators. Numerical parameters are expected in <code>in1</code> and <code>in2</code>.</li>
<br/>
<li>str.len: returns the length of string <code>s</code>.</li>
<li>str.at: returns the <code>offset</code><sup>th</sup> element of string <code>s</code>.</li>
<li>str.append: returns a new strings, which is the result of appending string <code>s1</code> to string <code>s2</code>.</li>
<br/>
<li>arr.len: returns the length of array <code>arr</code>.</li>
<li>arr.at: returns the <code>offset</code><sup>th</sup> element of array <code>arr</code>.</li>
<li>arr.append: returns a new array, which is the result of appending <code>e</code> to array <code>arr</code>.</li>
<li>arr.prepend: returns a new array, which is the result of prepending <code>e</code> to array <code>arr</code>.</li>
</ul>
</section>
<section>
<div class="page-header"><h3>Ajsone Interpreter</h3></div>
<p>
Feel free to try out Ajsone, using the following interpreter. You can try running the following pieces of code:
</p>
<ul>
<li><a href="#" onclick="return load_hello_world()">hello world</a></li>
<li><a href="#" onclick="return load_fact()">fact(5)</a></li>
<li><a href="#" onclick="return load_fib()">fib(6)</a></li>
<li><a href="#" onclick="return load_sort()">sort([2, 1, 3, 4, 6, 8, 7, 5])</a></li>
</ul>
<textarea id="input" style="width: 100%; height: 200px"></textarea>
<div id="output-success"></div>
<div id="output-failure" style="color: red"></div>
<button id="run" onclick="run()">run</button>
</section>
<section>
<h3>Links</h3>
<ul>
<li><a href="http://en.wikipedia.org/wiki/Esoteric_programming_language" class="external">Wikipedia page</a> about Esoteric programming languages.</li>
<li>Esolang page about <a href="http://esolangs.org/wiki/Ajsone" class="external">Ajsone</a>.</li>
<li><a href="http://en.wikipedia.org/wiki/Functional_programming" class="external">Learn more about functional programming</a>.</li>
<li><a href="http://en.wikipedia.org/wiki/Static_single_assignment_form" class="external">Learn more about SSA</a>.</li>
<li><a href="http://www.json.org/" class="external">JSON specification</a></li>
<li><a href="http://en.wikipedia.org/wiki/Homoiconicity" class="external">Homoiconicity</a></li>
</ul>
</section>