GuileScript is currently a toy compiler that aims to compile Guile to JavaScript. It currently doesn’t do much, but it might in the future.
Because, why not? Guile is actually a lot of fun and I just got jealous that people could do these sort of cool things with ClojureScript and I couldn’t with Guile. But thanks to GuileScript it is now with gas.
GuileScript leverages Guile’s Compiler Tower. It compiles Guile code into Tree-IL and then compiles Tree-IL into JavaScript.
Tree-IL is the first intermediate language (the main one actually being CPS) that Guile code is actually converted to, so the only thing that I needed to do is figure out how Tree-IL works plus get some inspiration from ClojureScript first commit.
Clone the repository and run:
$ autoreconf -vif $ ./configure $ make $ sudo make install
If you are on macOS you can actually install GuileScript through Guile Homebrew:
$ brew install aconchillo/guile/guilescript
If everything builds and installs fine you can try to compile one of the
provided examples (e.g. examples/fibonacci.gs
):
(define (fib n)
(if (<= n 1)
1
(+ (fib (- n 2)) (fib (- n 1)))))
$ guilescript examples/fibonacci.gs
which in this case would generate something like:
var fib = function fib(n) {
return ((n<=1) ? 1 : (fib((n-2))+fib((n-1))));
};
Too many things, but just to name a few:
- More types: maps, sets…
- More vector and string functions.
- Support formatting in logging functions.
- Integration with Google’s Closure Compiler.
And even long term:
- Modules.
- NodeJS integration.
GuileScript | JavaScript |
---|---|
#nil | null |
“guile” | “guile” |
‘guile | guile |
#t | true |
#f | false |
234 | 234 |
0.5 | 0.5 |
1/2 | 0.5 |
#(1 2 3) | [1,2,3] |
GuileScript | JavaScript |
---|---|
(string-length s) | s.length |
(string-ref s i) | s[i] |
GuileScript | JavaScript |
---|---|
(vector-length v) | v.length |
(vector-ref v i) | v[i] |
(vector-set! v i m) | v[i] = m |
GuileScript | JavaScript |
---|---|
(js-invoke obj ‘method arg1 … argN) | obj.method(arg1,…,argN) |
(js-new “type” arg1 … argN) | new type(arg1,…,argN) |
(js-ref obj ‘prop) | obj.prop |
(js-set! obj ‘prop value) | obj.prop = value |
Note that (js-set! obj prop value)
is just a shortcut to (set! (js-ref obj
prop) value)
.
GuileScript | JavaScript |
---|---|
+ - * / < > <= >= | + - * / < > <= >= |
equal? | === |
GuileScript | JavaScript |
---|---|
abs | Math.abs |
ceiling | Math.ceil |
floor | Math.floor |
max | Math.max |
min | Math.min |
round | Math.round |
GuileScript | JavaScript |
---|---|
console-log | console.log |
console-debug | console.debug |
console-error | console.error |
console-warn | console.warn |
GuileScript | JavaScript |
---|---|
(define a 23) | var a = 23; |
(set! a 45) | a = 45; |
(begin e1 e2 … eN) | (function () { e1; e2; … return eN; })() |
(if test then else) | (test ? then : else) |
(cond ((t1 e1) (t2 e2) (else e3)) | With simple e1, e2, e3: (function () { return (t1 ? e1 : (t2 ? e2 : e3)) })() |
(when test e1 e2 … eN) | (function () { if (test) { e1; e2; … return eN; } })() |
(let ((x 0) …) e1 … eN) | (function () { var x = 0; var …; e1; … return eN; })() |
(let lp ((x 0) (y 0)) e1 … eN) | (function () { var lp = function(x,y) { … return eN; }; return lp(0, 0); })() |
(lambda (x y) … eN) | (function (x, y) { … return eN; }) |
(define (f x y) … eN) | var f = function f(x, y) { … return eN; }; |
Macros (define-syntax, syntax-rules, syntax-case) just work out of the box. This is because the Scheme-To-Tree-IL compiler performs macro expansion at the same time it analyzes the code, producing expanded Tree-IL expressions which is what GuileScript actually needs.
Copyright (C) 2022 Aleix Conchillo Flaque <[email protected]>
GuileScript is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
GuileScript is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with GuileScript. If not, see https://www.gnu.org/licenses/.