Skip to content

aconchillo/guilescript

Repository files navigation

What is GuileScript?

https://github.com/aconchillo/guilescript/actions/workflows/guile3.0.yml/badge.svg

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.

Why?

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.

How does it work?

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.

How do I try it out?

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))));
};

What’s missing?

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.

What’s supported?

Types

GuileScriptJavaScript
#nilnull
“guile”“guile”
‘guileguile
#ttrue
#ffalse
234234
0.50.5
1/20.5
#(1 2 3)[1,2,3]

Strings

GuileScriptJavaScript
(string-length s)s.length
(string-ref s i)s[i]

Vectors

GuileScriptJavaScript
(vector-length v)v.length
(vector-ref v i)v[i]
(vector-set! v i m)v[i] = m

Objects

GuileScriptJavaScript
(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).

Operators

GuileScriptJavaScript
+ - * / < > <= >=+ - * / < > <= >=
equal?===

Math

GuileScriptJavaScript
absMath.abs
ceilingMath.ceil
floorMath.floor
maxMath.max
minMath.min
roundMath.round

Logging (just simple strings)

GuileScriptJavaScript
console-logconsole.log
console-debugconsole.debug
console-errorconsole.error
console-warnconsole.warn

Basic constructs

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

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.

License

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