fixing the extends keyword when the expressions are complex, and should only be run once -- not that it's good style -- ticket #143

This commit is contained in:
Jeremy Ashkenas
2010-02-16 23:23:43 -05:00
parent bedc005d67
commit 0610e20a3c
6 changed files with 39 additions and 11 deletions

View File

@@ -41,7 +41,8 @@
} }
return _a; return _a;
}; };
// The CommandLine handles all of the functionality of the `coffee` utility. // Running `cake` runs the tasks you pass asynchronously (node-style), or
// prints them out, with no arguments.
exports.run = function run() { exports.run = function run() {
return path.exists('Cakefile', function(exists) { return path.exists('Cakefile', function(exists) {
var args; var args;

View File

@@ -249,11 +249,14 @@
}; };
// Matches and consumes non-meaningful whitespace. // Matches and consumes non-meaningful whitespace.
lex.prototype.whitespace_token = function whitespace_token() { lex.prototype.whitespace_token = function whitespace_token() {
var space; var prev, space;
if (!((space = this.match(WHITESPACE, 1)))) { if (!((space = this.match(WHITESPACE, 1)))) {
return false; return false;
} }
this.tokens[this.tokens.length - 1].spaced = true; prev = this.tokens[this.tokens.length - 1];
if (prev) {
prev.spaced = true;
}
this.i += space.length; this.i += space.length;
return true; return true;
}; };
@@ -276,7 +279,7 @@
// Multi-character operators are also literal tokens, so that Racc can assign // Multi-character operators are also literal tokens, so that Racc can assign
// the proper order of operations. // the proper order of operations.
lex.prototype.literal_token = function literal_token() { lex.prototype.literal_token = function literal_token() {
var match, tag, value; var match, prev, tag, value;
match = this.chunk.match(OPERATOR); match = this.chunk.match(OPERATOR);
value = match && match[1]; value = match && match[1];
if (value && value.match(CODE)) { if (value && value.match(CODE)) {
@@ -287,7 +290,8 @@
if (value === ';') { if (value === ';') {
tag = 'TERMINATOR'; tag = 'TERMINATOR';
} }
if (!this.tokens[this.tokens.length - 1].spaced && CALLABLE.indexOf(this.tag()) >= 0) { prev = this.tokens[this.tokens.length - 1];
if (CALLABLE.indexOf(this.tag()) >= 0 && (!prev || !prev.spaced)) {
if (value === '(') { if (value === '(') {
tag = 'CALL_START'; tag = 'CALL_START';
} }

View File

@@ -480,11 +480,22 @@
}, },
// Hooking one constructor into another's prototype chain. // Hooking one constructor into another's prototype chain.
compile_node: function compile_node(o) { compile_node: function compile_node(o) {
var child, construct, parent; var child, child_var, construct, parent, parent_var, prefix;
construct = o.scope.free_variable(); construct = o.scope.free_variable();
child = this.child.compile(o); child = this.child.compile(o);
parent = this.parent.compile(o); parent = this.parent.compile(o);
return this.idt() + construct + ' = function(){};\n' + this.idt() + construct + '.prototype = ' + parent + ".prototype;\n" + this.idt() + child + '.__superClass__ = ' + parent + ".prototype;\n" + this.idt() + child + '.prototype = new ' + construct + "();\n" + this.idt() + child + '.prototype.constructor = ' + child + ';'; prefix = '';
if (!(this.child instanceof ValueNode) || this.child.has_properties() || !(this.child.unwrap() instanceof LiteralNode)) {
child_var = o.scope.free_variable();
prefix += this.idt() + child_var + ' = ' + child + ';\n';
child = child_var;
}
if (!(this.parent instanceof ValueNode) || this.parent.has_properties() || !(this.parent.unwrap() instanceof LiteralNode)) {
parent_var = o.scope.free_variable();
prefix += this.idt() + parent_var + ' = ' + parent + ';\n';
parent = parent_var;
}
return prefix + this.idt() + construct + ' = function(){};\n' + this.idt() + construct + '.prototype = ' + parent + ".prototype;\n" + this.idt() + child + '.__superClass__ = ' + parent + ".prototype;\n" + this.idt() + child + '.prototype = new ' + construct + "();\n" + this.idt() + child + '.prototype.constructor = ' + child + ';';
} }
})); }));
statement(ExtendsNode); statement(ExtendsNode);

View File

@@ -25,7 +25,8 @@ print_tasks: ->
spaces: if spaces > 0 then (' ' for i in [0..spaces]).join('') else '' spaces: if spaces > 0 then (' ' for i in [0..spaces]).join('') else ''
puts "cake " + name + spaces + ' # ' + task.description puts "cake " + name + spaces + ' # ' + task.description
# The CommandLine handles all of the functionality of the `coffee` utility. # Running `cake` runs the tasks you pass asynchronously (node-style), or
# prints them out, with no arguments.
exports.run: -> exports.run: ->
path.exists 'Cakefile', (exists) -> path.exists 'Cakefile', (exists) ->
throw new Error('Cakefile not found in ' + process.cwd()) unless exists throw new Error('Cakefile not found in ' + process.cwd()) unless exists

View File

@@ -209,7 +209,8 @@ lex::outdent_token: (move_out) ->
# Matches and consumes non-meaningful whitespace. # Matches and consumes non-meaningful whitespace.
lex::whitespace_token: -> lex::whitespace_token: ->
return false unless space: @match WHITESPACE, 1 return false unless space: @match WHITESPACE, 1
@tokens[@tokens.length - 1].spaced: true prev: @tokens[@tokens.length - 1]
prev.spaced: true if prev
@i += space.length @i += space.length
true true
@@ -235,7 +236,8 @@ lex::literal_token: ->
tag: if value.match(ASSIGNMENT) then 'ASSIGN' else value tag: if value.match(ASSIGNMENT) then 'ASSIGN' else value
tag: 'TERMINATOR' if value == ';' tag: 'TERMINATOR' if value == ';'
if not @tokens[@tokens.length - 1].spaced and CALLABLE.indexOf(@tag()) >= 0 prev: @tokens[@tokens.length - 1]
if CALLABLE.indexOf(@tag()) >= 0 and (not prev or not prev.spaced)
tag: 'CALL_START' if value is '(' tag: 'CALL_START' if value is '('
tag: 'INDEX_START' if value is '[' tag: 'INDEX_START' if value is '['
@token tag, value @token tag, value

View File

@@ -375,7 +375,16 @@ ExtendsNode: exports.ExtendsNode: inherit Node, {
construct: o.scope.free_variable() construct: o.scope.free_variable()
child: @child.compile(o) child: @child.compile(o)
parent: @parent.compile(o) parent: @parent.compile(o)
@idt() + construct + ' = function(){};\n' + @idt() + prefix: ''
if not (@child instanceof ValueNode) or @child.has_properties() or not (@child.unwrap() instanceof LiteralNode)
child_var: o.scope.free_variable()
prefix += @idt() + child_var + ' = ' + child + ';\n'
child: child_var
if not (@parent instanceof ValueNode) or @parent.has_properties() or not (@parent.unwrap() instanceof LiteralNode)
parent_var: o.scope.free_variable()
prefix += @idt() + parent_var + ' = ' + parent + ';\n'
parent: parent_var
prefix + @idt() + construct + ' = function(){};\n' + @idt() +
construct + '.prototype = ' + parent + ".prototype;\n" + @idt() + construct + '.prototype = ' + parent + ".prototype;\n" + @idt() +
child + '.__superClass__ = ' + parent + ".prototype;\n" + @idt() + child + '.__superClass__ = ' + parent + ".prototype;\n" + @idt() +
child + '.prototype = new ' + construct + "();\n" + @idt() + child + '.prototype = new ' + construct + "();\n" + @idt() +