From 2d57ee693bbdae0ce890378e514ebccd990b9888 Mon Sep 17 00:00:00 2001 From: Jeremy Ashkenas Date: Thu, 24 Dec 2009 23:09:24 -0800 Subject: [PATCH] the narwhal integration written in JavaScript has been replaced with CoffeeScript, and compiler-generated variable names now start with '__' --- Rakefile | 16 ++- lib-js/coffee-script.js | 113 ++++++++------------- lib-js/coffee-script/loader.js | 40 ++++---- lib/coffee_script/narwhal/coffee-script.cs | 63 ++++++++++++ lib/coffee_script/narwhal/loader.cs | 20 ++++ lib/coffee_script/nodes.rb | 1 + lib/coffee_script/scope.rb | 2 +- test/fixtures/each.js | 14 +-- test/fixtures/each_no_wrap.js | 14 +-- 9 files changed, 177 insertions(+), 106 deletions(-) create mode 100644 lib/coffee_script/narwhal/coffee-script.cs create mode 100644 lib/coffee_script/narwhal/loader.cs diff --git a/Rakefile b/Rakefile index 87c11bee..553194a9 100644 --- a/Rakefile +++ b/Rakefile @@ -10,9 +10,19 @@ task :test do Dir['test/*/**/test_*.rb'].each {|test| require test } end -desc "Recompile the Racc parser (pass -v and -g for verbose debugging)" -task :build, :extra_args do |t, args| - sh "racc #{args[:extra_args]} -o lib/coffee_script/parser.rb lib/coffee_script/grammar.y" +namespace :build do + + desc "Recompile the Racc parser (pass -v and -g for verbose debugging)" + task :parser, :extra_args do |t, args| + sh "racc #{args[:extra_args]} -o lib/coffee_script/parser.rb lib/coffee_script/grammar.y" + end + + desc "Compile the Narwhal interface for bin/cs" + task :narwhal do + sh "bin/coffee-script lib/coffee_script/narwhal/coffee-script.cs --print > lib-js/coffee-script.js" + sh "bin/coffee-script lib/coffee_script/narwhal/loader.cs --print > lib-js/coffee-script/loader.js" + end + end desc "Build the documentation page" diff --git a/lib-js/coffee-script.js b/lib-js/coffee-script.js index 7a2f307b..99889dd8 100644 --- a/lib-js/coffee-script.js +++ b/lib-js/coffee-script.js @@ -1,87 +1,64 @@ -var FILE = require("file"); -var OS = require("os"); - -exports.run = function(args) { - // TODO: non-REPL - +(function(){ + var File = require('file'); + var OS = require('os'); + exports.run = function(args) { args.shift(); - if (args.length) { - require(FILE.absolute(args[0])); - return; + return require(File.absolute(args[0])); } - - 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); + 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) { + }; + // 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", "--no-wrap", path]); - if (coffee.wait() !== 0) { - system.stderr.print(coffee.stderr.read()); - throw new Error("coffee-script compile error"); + system.stderr.print(coffee.stderr.read()); + throw new Error("coffee-script compile error"); } - return coffee.stdout.read(); -} - -exports.compile = function(source) { + }; + exports.compile = function(source) { var coffee = OS.popen([coffeePath, "--eval", "--no-wrap"]); - coffee.stdin.write(source).flush().close(); - if (coffee.wait() !== 0) { - system.stderr.print(coffee.stderr.read()); - throw new Error("coffee-script compile error"); + system.stderr.print(coffee.stderr.read()); + throw new Error("coffee-script compile 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) { + }; + // 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); - - return eval(code); -} - -exports.make_narwhal_factory = function(path) { + return eval(exports.compile(source)); + }; + exports.make_narwhal_factory = function(path) { init(); - var code = exports.compileFile(path); - 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() { + if (system.engine === "rhino") { + return Packages.org.mozilla.javascript.Context.getCurrentContext().compileFunction(global, factoryText, path, 0, null); + } else { + // eval requires parenthesis, but parenthesis break compileFunction. + return eval("(" + factoryText + ")"); + } + }; + var init = function() { // make sure it's only done once - init = function(){} -} \ No newline at end of file + init = function() { + }; + return init; + }; +})(); diff --git a/lib-js/coffee-script/loader.js b/lib-js/coffee-script/loader.js index 9dfba971..e0ec9d9d 100644 --- a/lib-js/coffee-script/loader.js +++ b/lib-js/coffee-script/loader.js @@ -1,23 +1,23 @@ -var coffeescript = null; - -function CoffeeScriptLoader() { - var loader = {}; - var factories = {}; - +(function(){ + var coffeescript = null; + var CoffeeScriptLoader = function() { + 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); - } - + coffeescript = coffeescript || require('coffee-script'); + // print("loading objective-j: " + topId + " (" + path + ")"); + factories[topId] = coffeescript.make_narwhal_factory(path); + return factories[topId]; + }; loader.load = function(topId, path) { - if (!factories.hasOwnProperty(topId)) - loader.reload(topId, path); - return factories[topId]; - } - + if (!(factories.hasOwnProperty(topId))) { + loader.reload(topId, path); + } + return factories[topId]; + }; return loader; -}; - -require.loader.loaders.unshift([".cs", CoffeeScriptLoader()]); + }; + require.loader.loaders.unshift([".cs", CoffeeScriptLoader()]); +})(); diff --git a/lib/coffee_script/narwhal/coffee-script.cs b/lib/coffee_script/narwhal/coffee-script.cs new file mode 100644 index 00000000..ca868779 --- /dev/null +++ b/lib/coffee_script/narwhal/coffee-script.cs @@ -0,0 +1,63 @@ +# This (javascript) file is generated from lib/coffee_script/narwhal/coffee-script.cs + +File: require('file') +OS: require('os') + +exports.run: args => + args.shift() + return require(File.absolute(args[0])) if args.length + + while true + try + system.stdout.write('cs> ').flush() + result: exports.cs_eval(require('readline').readline()) + print(result) if result isnt undefined + 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. +coffeePath: File.path(module.path).dirname().dirname().join('bin', 'coffee-script') + +exports.compileFile: path => + coffee: OS.popen([coffeePath, "--print", "--no-wrap", path]) + + if coffee.wait() isnt 0 + system.stderr.print(coffee.stderr.read()) + throw new Error("coffee-script compile error"). + + coffee.stdout.read(). + +exports.compile: source => + coffee: OS.popen([coffeePath, "--eval", "--no-wrap"]) + + coffee.stdin.write(source).flush().close() + + if coffee.wait() isnt 0 + system.stderr.print(coffee.stderr.read()) + throw new Error("coffee-script compile error"). + + 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: source => + init() + eval(exports.compile(source)). + +exports.make_narwhal_factory: path => + init() + code: exports.compileFile(path) + + factoryText: "function(require,exports,module,system,print){" + code + "/**/\n}" + + if system.engine is "rhino" + Packages.org.mozilla.javascript.Context.getCurrentContext().compileFunction(global, factoryText, path, 0, null) + else + # eval requires parenthesis, but parenthesis break compileFunction. + eval("(" + factoryText + ")").. + + +init: => + # make sure it's only done once + init: => .. \ No newline at end of file diff --git a/lib/coffee_script/narwhal/loader.cs b/lib/coffee_script/narwhal/loader.cs new file mode 100644 index 00000000..8928ed1c --- /dev/null +++ b/lib/coffee_script/narwhal/loader.cs @@ -0,0 +1,20 @@ +# This (javascript) file is generated from lib/coffee_script/narwhal/loader.cs + +coffeescript: null + +CoffeeScriptLoader: => + loader: {} + factories: {} + + loader.reload: topId, path => + coffeescript ||: require('coffee-script') + # print("loading objective-j: " + topId + " (" + path + ")"); + factories[topId]: coffeescript.make_narwhal_factory(path). + + loader.load: topId, path => + loader.reload(topId, path) unless factories.hasOwnProperty(topId) + factories[topId]. + + loader. + +require.loader.loaders.unshift([".cs", CoffeeScriptLoader()]) diff --git a/lib/coffee_script/nodes.rb b/lib/coffee_script/nodes.rb index 16b20b75..dcfcd096 100644 --- a/lib/coffee_script/nodes.rb +++ b/lib/coffee_script/nodes.rb @@ -479,6 +479,7 @@ module CoffeeScript def compile(o={}) o = super(o) + o.delete(:return) indent = o[:indent] + TAB cond = @condition.compile(o.merge(:no_paren => true)) write("while (#{cond}) {\n#{@body.compile(o.merge(:indent => indent))}\n#{o[:indent]}}") diff --git a/lib/coffee_script/scope.rb b/lib/coffee_script/scope.rb index 743552ea..8c07785b 100644 --- a/lib/coffee_script/scope.rb +++ b/lib/coffee_script/scope.rb @@ -11,7 +11,7 @@ module CoffeeScript def initialize(parent=nil) @parent = parent @variables = {} - @temp_variable = @parent ? @parent.temp_variable : 'a' + @temp_variable = @parent ? @parent.temp_variable : '__a' end # Look up a variable in lexical scope, or declare it if not found. diff --git a/test/fixtures/each.js b/test/fixtures/each.js index 9ee1dcea..58778639 100644 --- a/test/fixtures/each.js +++ b/test/fixtures/each.js @@ -8,16 +8,16 @@ if (obj.forEach) { obj.forEach(iterator, context); } else if (_.isArray(obj) || _.isArguments(obj)) { - var a = obj; - for (var b=0, c=a.length; b