Scheme for the browser and Node.js. You can try it right now.
This is still work in progress, the goal is (near) R5RS compliance. Have a look at the TODO to see what's on the agenda. Feedback and contributions welcome, just drop me a line (or a pull request).
If you'd like to see some practical examples, have a look at the GitHub page and the browser REPL.
Just open browser-repl/index.html in a browser.
Node.js and Commander.js are required.
To start an interactive session:
bin/schemejs
To process a file:
bin/schemejs file.scm
You can also install the REPL to /usr/local/bin like this:
make install
Build it like this:
make
This will put dist/scheme.js and dist/scheme.min.js in place. The latter only if you have UglifyJS installed.
If you include dist/scheme.js or dist/scheme.min.js, you can include scheme code via script tags, just like JavaScript code. Like this:
<script src="scheme.min.js"></script>
<script type="text/x-scheme">
((.alert js) "Hello, World!")
</script>
<script type="text/x-scheme" src="hello.scm"></script>
You can also evaluate Scheme from JavaScript:
scheme.evalString('((.log console) "Hello, World!")', new scheme.Environment);
Or load a file:
scheme.load("/hello.scm");
You can execute a scheme file via the REPL:
bin/schemejs hello.scm
Or evaluate Scheme from JavaScript:
var scheme = require("./scheme.min.js");
scheme.evalString('((.log console) "Hello, World!")', new scheme.Environment);
Or load a file from JavaScript:
var scheme = require("./scheme.min.js");
scheme.load("hello.scm");
(.x y)
In JavaScript, this would be:
y.x;
(set! (.x y) "foo")
In JavaScript, this would be:
y.x = "foo";
((.log console) "Hello, World!")
In JavaScript, this would be:
console.log("Hello, World!");
Think of it as retrieving the property log of console and executing it as a function, which is exactly how it works in JavaScript.
js refers to the global object, window in the browser and global in Node.js.
You can create new JavaScript objects from an alist with the make-object, like this:
(make-object '(("hello" "world") ("foo" "bar")))
This will become:
{"hello: "world, "foo": "bar"}
(new (.Date js) 2012 1 19)
In JavaScript, this would be:
new Date(2012, 1, 19);
(try (...) (lambda (e) ...))
In JavaScript, this would be:
try { ... } catch (e) { ... }
You can compile Scheme code to JavaScript that will evaluate itself when loaded.
bin/schemejs -c hello.scm > hello.scm.js
You can include the resulting script file in your page:
<script src="scheme.min.js"></script>
<script src="hello.scm.js"></script>
And like this in Node.js:
var scheme = require("./scheme.min.js");
require("./hello.scm.js");
Note that you have to load scheme.js before the script. If you want a really self-contained JS file, do this:
cp scheme.min.js hello.js
bin/schemejs -c hello.scm >> hello.js
In any event, the code evaluates itself with the environment from the global variable environment. If the variable exists, it uses that, otherwise a fresh environment is created. So if you add several compiled source files they will automatically use the same environment.
This isn't compilation in the proper sense: The result is just the parsed Scheme code in JavaScript data structures, wrapped in an eval call. It is still interpreted at runtime.
Node.js and Node Unit are required.
You can run the tests like this:
nodeunit test