diff --git a/lib/coffee_script/nodes.js b/lib/coffee_script/nodes.js index 6ac79ad4..199c0ecd 100644 --- a/lib/coffee_script/nodes.js +++ b/lib/coffee_script/nodes.js @@ -1,5 +1,5 @@ (function(){ - var CallNode, CommentNode, Expressions, LiteralNode, Node, ReturnNode, TAB, TRAILING_WHITESPACE, ValueNode, any, compact, del, dup, flatten, inherit, merge, statement; + var CallNode, CommentNode, Expressions, ExtendsNode, LiteralNode, Node, ReturnNode, TAB, TRAILING_WHITESPACE, 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. @@ -257,17 +257,14 @@ }; // Merge objects. merge = function merge(src, dest) { - var __a, __b, key, val; - dest[key] = (function() { - __a = []; __b = src; - for (key in __b) { - val = __b[key]; - if (__hasProp.call(__b, key)) { - __a.push(val); - } + var __a, key, val; + __a = src; + for (key in __a) { + val = __a[key]; + if (__hasProp.call(__a, key)) { + ((dest[key] = val)); } - return __a; - }).call(this); + } return dest; }; // Do any of the elements in the list pass a truth test? @@ -361,7 +358,7 @@ var __a, __b, __c, __d, i, idt; idt = (this.indent || ''); __c = 0; __d = (tabs || 0); - for (__b=0, i=__c; (__c <= __d ? i <= __d : i >= __d); (__c <= __d ? i += 1 : i -= 1), __b++) { + for (__b=0, i=__c; (__c <= __d ? i < __d : i > __d); (__c <= __d ? i += 1 : i -= 1), __b++) { idt += TAB; } return idt; @@ -702,4 +699,23 @@ return [call, reference]; } })); + // Node to extend an object's prototype with an ancestor object. + // After goog.inherits from the Closure Library. + ExtendsNode = (exports.ExtendsNode = inherit(Node, { + constructor: function constructor(child, parent) { + this.child = child; + this.parent = parent; + this.children = [child, parent]; + return this; + }, + // Hooking one constructor into another's prototype chain. + compile_node: function compile_node(o) { + var child, constructor, parent; + constructor = o.scope.free_variable(); + child = this.child.compile(o); + parent = this.parent.compile(o); + return this.idt() + constructor + ' = function(){};\n' + this.idt() + constructor + '.prototype = ' + parent + ".prototype;\n" + this.idt() + child + '.__superClass__ = ' + parent + ".prototype;\n" + this.idt() + child + '.prototype = new ' + constructor + "();\n" + this.idt() + child + '.prototype.constructor = ' + child + ';'; + } + })); + statement(ExtendsNode); })(); \ No newline at end of file diff --git a/lib/coffee_script/scope.js b/lib/coffee_script/scope.js index 172afbd4..5935b0e9 100644 --- a/lib/coffee_script/scope.js +++ b/lib/coffee_script/scope.js @@ -47,7 +47,7 @@ }; // Find an available, short, name for a compiler-generated variable. Scope.prototype.free_variable = function free_variable() { - while (check(this.temp_variable)) { + while (this.check(this.temp_variable)) { ((this.temp_variable = succ(this.temp_variable))); } this.variables[this.temp_variable] = 'var'; diff --git a/src/nodes.coffee b/src/nodes.coffee index c27ae1c3..be65e3af 100644 --- a/src/nodes.coffee +++ b/src/nodes.coffee @@ -69,7 +69,7 @@ dup: (input) -> # Merge objects. merge: (src, dest) -> - dest[key]: val for key, val of src + (dest[key]: val) for key, val of src dest # Do any of the elements in the list pass a truth test? @@ -134,7 +134,7 @@ Node::compile_closure: (o) -> # Quick short method for the current indentation level, plus tabbing in. Node::idt: (tabs) -> idt: (@indent || '') - idt += TAB for i in [0..(tabs or 0)] + idt += TAB for i in [0...(tabs or 0)] idt # Does this node, or any of its children, contain a node of a certain kind? @@ -415,6 +415,32 @@ CallNode: exports.CallNode: inherit Node, { } +# Node to extend an object's prototype with an ancestor object. +# After goog.inherits from the Closure Library. +ExtendsNode: exports.ExtendsNode: inherit Node, { + + constructor: (child, parent) -> + @child: child + @parent: parent + @children: [child, parent] + this + + # Hooking one constructor into another's prototype chain. + compile_node: (o) -> + constructor: o.scope.free_variable() + child: @child.compile(o) + parent: @parent.compile(o) + @idt() + constructor + ' = function(){};\n' + @idt() + + constructor + '.prototype = ' + parent + ".prototype;\n" + @idt() + + child + '.__superClass__ = ' + parent + ".prototype;\n" + @idt() + + child + '.prototype = new ' + constructor + "();\n" + @idt() + + child + '.prototype.constructor = ' + child + ';' + +} + +statement ExtendsNode + + diff --git a/src/scope.coffee b/src/scope.coffee index 09cc550d..85b932fe 100644 --- a/src/scope.coffee +++ b/src/scope.coffee @@ -36,7 +36,7 @@ Scope::reset: (name) -> # Find an available, short, name for a compiler-generated variable. Scope::free_variable: -> - (@temp_variable: succ(@temp_variable)) while check @temp_variable + (@temp_variable: succ(@temp_variable)) while @check @temp_variable @variables[@temp_variable]: 'var' @temp_variable