People keep saying that html is a markup language, not a programing language. While this is true, it kinds of ignores the expressiveness of the html language. The tree structure of a DOM suits very well to the job of representing an astract syntax tree.
The div Programing Languange is an experiment which aims to illustrate the expressiveness of html. The so called div language is just a piece of js code which works as an interpreter. When you add this piece of code to an html5 file, it totally changes the semantics of all elements in the document, and turns the html file to a functional, lisp-like language.
To use Div, all you need to do is to add div.js
to the <head>
part of your html file, for example, if you download div.js
file to the same level of the html file, then just add this line:
<script src="./div.js"></script>
And now you can write programs directly with the html <div>
s.
Here is the hello world example:
<!DOCTYPE html>
<html>
<head>
<title>hello world</title>
<script src="./div.js"></script>
</head>
<body>
<div class="out">
<div class="value">"hello world"</div>
</div>
</body>
</html>
This program will display 'hello world'
on the screen when you open it with a browser
You can also use other tags than <div>
s, as a short cut. For example, the <body>
part of the hello world example could also be written as:
<main><i>"hello world"</i></main>
This is much simpler.
Here is another example. It computes the greatest common divisor of two user inputs (only shows the <body>
part for simpliciy):
<body>
<cite id="a">Please input the first number:</cite>
<cite id="b">Please input the second number:</cite>
<main><i>"The gcd is: "</i></main>
<main>
<div class="call">
<div class="function" id="gcd">
<article>
<section id="first"><div class="operator" title="car"><label></label></div></section>
<section id="second"><div class="operator" title="cdr"><label></label></div></section>
<nav>
<div class="operator" title="equal?"><a>second</a><i>0</i></div>
<a>first</a>
<div class="call">
<a>gcd</a>
<aside><a>second</a><div class="operator" title="modulus"><a>first</a><a>second</a></div></aside>
</div>
</nav>
</article>
</div>
<aside><a>a</a><a>b</a></aside>
</div>
</main>
</body>
A div program is written inside the <body>
element in a html5 file. A program is composed of a series of statements. These statements are excuted in order.
There are only two statements in the div language. These are in statement
and out statement
. They deal with IO. Everything else is an expression.
The in statement
is in the following format:
<div class="in" id="[identifier]"> [prompt] </div>
or
<cite id="[identifier]"> [prompt] </cite>
Here [prompt]
is a string to display to the user, [identifier]
is a variable identifier. A variable identifier can be anything acceptible as the value of id
attribute in html. Variables with the same identifier is not allowed in div (even in different scopes), because the id
attribute could not have repeated value throughout the document.
The in statement
displays the prompt message to the user, and an <input>
element. Once the user input something into the <input>
, it creates a top-level variable binding to the identifier provided.
Anything other than the user input goes inside the out statement
. The out statement
is in the format:
<div class="out"> [expression] </div>
or
<main> [expression] </main>
The out statement
first evaluates the expression inside of it, and then displays its result on the screen. One out statement
can only hold one expression. For multple output, you may use multiple out statement
.
The expressions are explained next.
There are 10 expressions in div.
The literal expression
is in the format:
<div class="value"> [literal] </div>
or
<i> [literal] </i>
The literal
expression represent a literal. The [literal]
must be a number literal (64-bit floating point, not including NaN
), boolean literal (true
or false
), null
, or a string (wrapped in ""). If the value given is not in "", and not true
, false
, or null
, and cannot be converted to a number, then it will be treated as a string.
The scope expression
is in the format:
<div class="scope">
[variable binding expression]*
[expression]
</div>
or
<article>
[variable binding expression]*
[expression]
</article>
The scope expression
opens a scope. It takes 0 or more [variable binding expression]
s, add those into the current environment to create a new environment, and evaluate the [expression]
under this new environment. The value is the value of the last [expression]
.
The variable binding expression
is in the format:
<div class="define" id="[identifier]"> [expression] </div>
or
<section id="[identifier]"> [expression] </section>
The variable binding expression
binds the evaluation result of [expression]
to the [identifier]
in the current scope. The [identifier]
does not allow repeated value throughout the file. So there are no re-binding, assignment, mutation, or shadowing in the div languange.
The variable use expression
is in the format:
<div class="variable"> [identifier] </div>
or
<a> [identifier] </a>
The variable use expression
looks up the [identifier]
in the current environment. The [identifier]
is not wrapped in "".
The function expression
is in the format:
<div class="function" id="[identifier]"?> [expression] </div>
This expression does not have short hand tag.
The function expression
defines a function. Every function in div only takes one argument, so there is no need to give a name to this only argument. The [expression]
represents the function body. In the body, use a argument expression
as a placeholder for where the argument is used.
The function expression
also binds the function itself to the [identifier]
and adds it to the environment. This allows recursion. The [identifier]
part is optional, but if it is missing, you cannot call this function in itself.
The argument expression
is in the format:
<div class="argument"></div>
or
<label></label>
The argument expression
is a placeholder in the function body for the argument. It contains nothing, all contained elements or text will be ignored.
The condition expression
is in the format:
<div class="condition"> [expression] [expression] [expression]? </div>
or
<nav> [expression] [expression] [expression]? </nav>
The condition expression
takes two or three [expression]
s. It first evaluates the first one. This one must evaluates to a literal expression
. If the value is convertible to true according to js rules, the value of the condition expression
is the value of the second [expression]
. Otherwise the value is the value of the third [expression]
.
Only one of the second and third [expression]
s is evaluated.
The third [expression]
is optional. If the third [expression]
is not given but the first [expression]
evaluates to false, a literal expression
with value null
is the evaluating result.
The pair expression
is in the format:
<div class="pair"> [expression] [expression] </div>
or
<aside> [expression] [expression] </aside>
The pair expression
takes two [expression]
s, and make a pair of them. The pair is the only compound data structure in div. It can be nested.
The function call expression
is in the format:
<div class="call"> [function expression] [expression] </div>
or This expression does not have a short hand tag.
The function call expression
takes two [expression]
s. The first must evaluate to a function. Evaluting a function call expression
will first evalute the [function expression]
to a function, and then evaluate the [expression]
to a value. Then it will evaluate the function's body, in which where an argument expression
is encountered, it will be evaluated to the value of the [expression]
.
The operator expression
is in the format:
<div class="operator" title="[operator name]"> [expression] [expression]? </div>
This expression does not have a short hand tag.
The operator expression
represents the usage of an operator. The name of the operator is given as the title attribute. There are 8 unary operators and 13 binary operators. Where a unary operator is given, the operator expression
must take exactly 1 [expression]
; where a binary operator is given, it must take two.
Evaluating an operator expression
will evaluate the [expression]
(s) in order, and perform the operation
Unary operators:
name | result on a value v |
---|---|
positive |
+v |
negative |
-v |
not |
!v |
increment |
v + 1 |
decrement |
v - 1 |
pair? |
true if v is a pair, false otherwise |
car |
the first element of a pair |
cdr |
the second element of a pair |
Binary operators
name | result on values a and b |
---|---|
add |
a + b |
minus |
a - b |
multiply |
a * b |
divide |
a / b (as floating point numebrs) |
intdivide |
a / b (as integers) |
modulus |
a % b |
and |
a && b |
or |
a || b |
equal? |
a === b |
larger? |
a > b |
smaller? |
a < b |
notlarger? |
a <= b |
notsmaller? |
a >= b |
Is it possible to program when there are no loops at all?
Yes, you can, as long as you can use recursions. This example displays 'Love you x' 365 times on the screen (i.e. Love you 1 Love you 2 ... Love you 365). The plan was to write a loveyou3000, but doing so will exceed the limitation of recursions of the browser. Sadly, tail recursion has not been implemented.
What can I use when I need some data structure like an array, given that the only data structure is simply a pair?
You can use nested pairs. Here is an example displaying the first nth elements of the Fibonacci sequence onto the screen.
What can I do if I want to let the functions take multiple arguments, instead of only one?
Say if you want to pass two arguments, you can either wrap the arguments into a pair, and use the operators car
and cdr
to extract the elements of the pair inside the function body, or curry the function.
Here is a comprehensive example which displays the first nth prime numbers in the form of nested pairs. It uses both pairing and currying to deal with multi-argument functions.
As the div program can be extremely hard to read, here is a js version which adopts the same logic:
// suppose the user input is bound to the variable count
const count = 20
const from = n => [n, () => from(n + 1)]
const take = (list, n) => n == 0 ? [] : [list[0], ...take(list[1](), n - 1)]
const sift = p => list => list[0] % p
? [list[0], () => sift(p)(list[1]())]
: sift(p)(list[1]())
const sieve = list => [list[0], () => sieve(sift(list[0])(list[1]()))]
console.log(take(sieve(from(2)), count))