From dbccc1fa4f8e4463e96fff8aa9906693031af8e6 Mon Sep 17 00:00:00 2001 From: tlrobinson Date: Thu, 24 Dec 2009 14:41:35 -0800 Subject: [PATCH] Narwhal support for CoffeeScript --- lib-js/coffee-script.js | 91 ++++++++++++++++++++++++++++++++++ lib-js/coffee-script/loader.js | 23 +++++++++ package.json | 9 ++++ 3 files changed, 123 insertions(+) create mode 100644 lib-js/coffee-script.js create mode 100644 lib-js/coffee-script/loader.js create mode 100644 package.json diff --git a/lib-js/coffee-script.js b/lib-js/coffee-script.js new file mode 100644 index 00000000..266f1309 --- /dev/null +++ b/lib-js/coffee-script.js @@ -0,0 +1,91 @@ +var FILE = require("file"); +var OS = require("os"); + +exports.run = function(args) { + // TODO: non-REPL + + args.shift(); + + if (args.length) { + require(FILE.absolute(args[0])); + return; + } + + while (true) + { + try { + system.stdout.write("cs> ").flush(); + + var result = exports.cs_eval(require("readline").readline()); + + if (result !== undefined) + print(result); + + } catch (e) { + print(e); + } + } +} + +// executes the coffee-script Ruby program to convert from CoffeeScript to Objective-J. +// eventually this will hopefully be replaced by a JavaScript program. +var coffeePath = FILE.path(module.path).dirname().dirname().join("bin", "coffee-script"); + +exports.compileFile = function(path) { + var coffee = OS.popen([coffeePath, "--print", path]); + + if (coffee.wait() !== 0) + throw new Error("coffee compiler error"); + + return coffee.stdout.read(); +} + +exports.compile = function(source) { + var coffee = OS.popen([coffeePath, "-"]); + + coffee.stdin.write(source).flush().close(); + + if (coffee.wait() !== 0) + throw new Error("coffee compiler error"); + + return coffee.stdout.read(); +} + +// these two functions are equivalent to objective-j's objj_eval/make_narwhal_factory. +// implemented as a call to coffee and objj_eval/make_narwhal_factory +exports.cs_eval = function(source) { + init(); + + var code = exports.compile(source); + + // strip the function wrapper, we add our own. + // TODO: this is very fragile + code = code.split("\n").slice(1,-2).join("\n"); + + return eval(code); +} + +exports.make_narwhal_factory = function(path) { + init(); + + var code = exports.compileFile(path); + + // strip the function wrapper, we add our own. + // TODO: this is very fragile + code = code.split("\n").slice(1,-2).join("\n"); + + var factoryText = "function(require,exports,module,system,print){" + code + "/**/\n}"; + + if (system.engine === "rhino") + return Packages.org.mozilla.javascript.Context.getCurrentContext().compileFunction(global, factoryText, path, 0, null); + + // eval requires parenthesis, but parenthesis break compileFunction. + else + return eval("(" + factoryText + ")"); +} + + +var init = function() { + // make sure it's only done once + init = function(){} +} \ No newline at end of file diff --git a/lib-js/coffee-script/loader.js b/lib-js/coffee-script/loader.js new file mode 100644 index 00000000..9dfba971 --- /dev/null +++ b/lib-js/coffee-script/loader.js @@ -0,0 +1,23 @@ +var coffeescript = null; + +function CoffeeScriptLoader() { + var loader = {}; + var factories = {}; + + loader.reload = function(topId, path) { + if (!coffeescript) coffeescript = require("coffee-script"); + + //print("loading objective-j: " + topId + " (" + path + ")"); + factories[topId] = coffeescript.make_narwhal_factory(path); + } + + loader.load = function(topId, path) { + if (!factories.hasOwnProperty(topId)) + loader.reload(topId, path); + return factories[topId]; + } + + return loader; +}; + +require.loader.loaders.unshift([".cs", CoffeeScriptLoader()]); diff --git a/package.json b/package.json new file mode 100644 index 00000000..ead29983 --- /dev/null +++ b/package.json @@ -0,0 +1,9 @@ +{ + "name": "coffee-script", + "lib": "lib-js", + "preload": ["coffee-script/loader"], + "description": "Unfancy JavaScript", + "keywords": ["javascript", "language"], + "author": "Jeremy Ashkenas", + "version": "0.1.1" +}