diff --git a/lib/coffee_script/nodes.js b/lib/coffee_script/nodes.js index 5ceaab62..72ebf3e7 100644 --- a/lib/coffee_script/nodes.js +++ b/lib/coffee_script/nodes.js @@ -1,5 +1,5 @@ (function(){ - var AccessorNode, ArrayNode, AssignNode, CallNode, ClosureNode, CodeNode, CommentNode, Expressions, ExtendsNode, IndexNode, LiteralNode, Node, ObjectNode, PushNode, RangeNode, ReturnNode, SliceNode, TAB, TRAILING_WHITESPACE, ThisNode, ValueNode, any, compact, del, dup, flatten, inherit, merge, statement; + var AccessorNode, ArrayNode, AssignNode, CallNode, ClosureNode, CodeNode, CommentNode, Expressions, ExtendsNode, IndexNode, LiteralNode, Node, ObjectNode, PushNode, RangeNode, ReturnNode, SliceNode, SplatNode, TAB, TRAILING_WHITESPACE, ThisNode, ValueNode, any, compact, del, dup, flatten, inherit, merge, statement; var __hasProp = Object.prototype.hasOwnProperty; process.mixin(require('./scope')); // The abstract base class for all CoffeeScript nodes. @@ -980,4 +980,22 @@ return true; } })); + // A splat, either as a parameter to a function, an argument to a call, + // or in a destructuring assignment. + SplatNode = (exports.SplatNode = inherit(Node, { + constructor: function constructor(name) { + this.children = [(this.name = name)]; + return this; + }, + compile_node: function compile_node(o) { + return this.index ? this.compile_param(o) : this.name.compile(o); + }, + compile_param: function compile_param(o) { + o.scope.find(this.name); + return this.name + ' = Array.prototype.slice.call(arguments, ' + this.index + ')'; + }, + compile_value: function compile_value(o, name, index) { + return "Array.prototype.slice.call(" + this.name + ', ' + this.index + ')'; + } + })); })(); \ No newline at end of file diff --git a/lib/coffee_script/parser.js b/lib/coffee_script/parser.js index 203ae22d..92c2db88 100644 --- a/lib/coffee_script/parser.js +++ b/lib/coffee_script/parser.js @@ -196,8 +196,8 @@ // A Parameter (or ParamSplat) in a function definition. Param: [o("PARAM", function() { return yytext; - }), o("PARAM . . .", function() { - return new SplatNode(yytext); + }), o("Param . . .", function() { + return new SplatNode($1); }) ], // A regular splat. diff --git a/src/nodes.coffee b/src/nodes.coffee index cf500eaa..ee022a64 100644 --- a/src/nodes.coffee +++ b/src/nodes.coffee @@ -691,6 +691,25 @@ CodeNode: exports.CodeNode: inherit Node, { } +# A splat, either as a parameter to a function, an argument to a call, +# or in a destructuring assignment. +SplatNode: exports.SplatNode: inherit Node, { + + constructor: (name) -> + @children: [@name: name] + this + + compile_node: (o) -> + if @index then @compile_param(o) else @name.compile(o) + + compile_param: (o) -> + o.scope.find @name + @name + ' = Array.prototype.slice.call(arguments, ' + @index + ')' + + compile_value: (o, name, index) -> + "Array.prototype.slice.call(" + @name + ', ' + @index + ')' + +} diff --git a/src/parser.coffee b/src/parser.coffee index 42d04940..d9fc6554 100644 --- a/src/parser.coffee +++ b/src/parser.coffee @@ -221,7 +221,7 @@ grammar: { # A Parameter (or ParamSplat) in a function definition. Param: [ o "PARAM", -> yytext - o "PARAM . . .", -> new SplatNode(yytext) + o "Param . . .", -> new SplatNode($1) ] # A regular splat.