Permalink
Cannot retrieve contributors at this time
Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign up
Fetching contributors…

--- | |
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> |