Ethpretho is a small, lisp-inspired language that compiles to readable, standard javascript. It is in the vein of coffeescript and, more so, in that of sibilant.
The approach:
- retain normal javascript semantics
- .. except provide implicit return
- any non-javascript semantics should be implemented with macros
- use terse syntax where appropriate
Currently, the base compiler is done and is written in itself (and can compile itself). The macro system, which I intend to make pattern-based and hygenic, will follow.
The tooling / packaging is also pending.
cd src
node compile ./somefile.eth
This will place the new .js file next to the .eth file
js equivalent shown below each line of ethpretho
Numbers, atoms, and regexes are that same as in js.
Strings are enclosed in double-quotes only.
(:= x 1)
var x = 1;
(= x 2)
x = 2;
(-> (x y) (* x y))
function (x, y) { return (x * y); }
[1 2 3]
[1,2,3]
{a 1 "b" 2}
{a:1, "b":2}
Comments are not retained in the js output
; somecomment
(. x y)
x.y
(. x [y])
x[y]
(. x 0)
x[0]
(. x (y 1) (z 2 3))
x.y(1).z(2,3)
(. x [(y z)])
x[y(z)]
(. x ([(y z)] a))
x[y(z)](a)
'if' encompasses 'else' and 'else if' when necessary:
(if x (y))
if (x) {
y();
}
(if (< x y) (a 2)
(< x z) (a 3)
(a 4))
if (x < y) {
a(2);
} else if (x < z) {
a(3);
} else {
a(4);
}
Note: If you want more than one expression in a result block, you need to expand the block by use of the sequence form, ',':
(if x (y)
(, (y)
(z)))
if (x) {
y();
} else {
y();
z();
}
Only 'for' and 'while' are provided. These map directly to the normal js 'for' and 'while'. Later, more convienient looping constructs will be added as macros that compile to these:
(for ((= i 0) (< i len) (++ i))
(y i)
(z i))
for (i = 0; i < len; i++) {
y(i);
z(i);
}
(while (!== i 0)
(y i)
(-- i))
while (i !== 0) {
y(i);
i--;
}
(try e
(, (x) (y))
(throw (new Error (+ "The world is ending: " e)))
(y))
try {
x();
y();
} catch (e) {
throw new Error("The world is ending: " + e);
} finally {
y();
}
Almost everything is an expression. Try/catch, loops, and conditionals will be wrapped in self-calling functions if a value is expected of them:
(+ 1 (for ((in i j)) (* i 2)))
(1 + (function () {
res_ = [];
for (i in j) {
res_.push(i * 2);
}
return res_;
})())
The last expression of a function will be returned. If it is a conditional, the 'return' will propagate to the last position in all its branches:
(-> (x) (y)
(z)
(x))
function (x) {
y();
z();
return x();
}
(-> (x) (if (< x y) 2
(< x z) 3
4))
function (x) {
if (x < y) {
return 2;
} else if (x < z) {
return 3;
} else {
return 4;
}
}
(+ "a" "b" "c")
("a" + "b" + "c")
(< x y z)
((x < y) && (y < z))