mirror of
https://github.com/jashkenas/coffeescript.git
synced 2026-02-18 11:31:20 -05:00
Implement @-prefixed parameters.
This commit is contained in:
@@ -139,8 +139,12 @@
|
|||||||
Param: [
|
Param: [
|
||||||
o("PARAM", function() {
|
o("PARAM", function() {
|
||||||
return new LiteralNode($1);
|
return new LiteralNode($1);
|
||||||
}), o("Param . . .", function() {
|
}), o("@ PARAM", function() {
|
||||||
return new SplatNode($1);
|
return new ParamNode($2, true);
|
||||||
|
}), o("PARAM . . .", function() {
|
||||||
|
return new ParamNode($1, false, true);
|
||||||
|
}), o("@ PARAM . . .", function() {
|
||||||
|
return new ParamNode($2, true, true);
|
||||||
})
|
})
|
||||||
],
|
],
|
||||||
Splat: [
|
Splat: [
|
||||||
|
|||||||
80
lib/nodes.js
80
lib/nodes.js
@@ -1,5 +1,5 @@
|
|||||||
(function() {
|
(function() {
|
||||||
var AccessorNode, ArrayNode, AssignNode, BaseNode, CallNode, ClassNode, ClosureNode, CodeNode, CommentNode, DOUBLE_PARENS, ExistenceNode, Expressions, ExtendsNode, ForNode, IDENTIFIER, IS_STRING, IfNode, InNode, IndexNode, LiteralNode, NUMBER, ObjectNode, OpNode, ParentheticalNode, PushNode, RangeNode, ReturnNode, SIMPLENUM, Scope, SliceNode, SplatNode, TAB, TRAILING_WHITESPACE, ThrowNode, TryNode, UTILITIES, ValueNode, WhileNode, _a, compact, del, ends, flatten, helpers, include, indexOf, literal, merge, starts, utility;
|
var AccessorNode, ArrayNode, AssignNode, BaseNode, CallNode, ClassNode, ClosureNode, CodeNode, CommentNode, DOUBLE_PARENS, ExistenceNode, Expressions, ExtendsNode, ForNode, IDENTIFIER, IS_STRING, IfNode, InNode, IndexNode, LiteralNode, NUMBER, ObjectNode, OpNode, ParamNode, ParentheticalNode, PushNode, RangeNode, ReturnNode, SIMPLENUM, Scope, SliceNode, SplatNode, TAB, TRAILING_WHITESPACE, ThrowNode, TryNode, UTILITIES, ValueNode, WhileNode, _a, compact, del, ends, flatten, helpers, include, indexOf, literal, merge, starts, utility;
|
||||||
var __extends = function(child, parent) {
|
var __extends = function(child, parent) {
|
||||||
var ctor = function(){};
|
var ctor = function(){};
|
||||||
ctor.prototype = parent.prototype;
|
ctor.prototype = parent.prototype;
|
||||||
@@ -958,7 +958,7 @@
|
|||||||
CodeNode.prototype['class'] = 'CodeNode';
|
CodeNode.prototype['class'] = 'CodeNode';
|
||||||
CodeNode.prototype.children = ['params', 'body'];
|
CodeNode.prototype.children = ['params', 'body'];
|
||||||
CodeNode.prototype.compileNode = function(o) {
|
CodeNode.prototype.compileNode = function(o) {
|
||||||
var _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, code, func, i, param, params, sharedScope, splat, top;
|
var _b, _c, _d, _e, _f, _g, _h, _i, _j, code, func, i, name, param, params, sharedScope, splat, top;
|
||||||
sharedScope = del(o, 'sharedScope');
|
sharedScope = del(o, 'sharedScope');
|
||||||
top = del(o, 'top');
|
top = del(o, 'top');
|
||||||
o.scope = sharedScope || new Scope(o.scope, this.body, this);
|
o.scope = sharedScope || new Scope(o.scope, this.body, this);
|
||||||
@@ -966,37 +966,46 @@
|
|||||||
o.indent = this.idt(1);
|
o.indent = this.idt(1);
|
||||||
del(o, 'noWrap');
|
del(o, 'noWrap');
|
||||||
del(o, 'globals');
|
del(o, 'globals');
|
||||||
i = 0;
|
|
||||||
splat = undefined;
|
splat = undefined;
|
||||||
params = [];
|
params = [];
|
||||||
_c = this.params;
|
_b = this.params;
|
||||||
for (_b = 0, _d = _c.length; _b < _d; _b++) {
|
for (i = 0, _c = _b.length; i < _c; i++) {
|
||||||
param = _c[_b];
|
param = _b[i];
|
||||||
if (param instanceof SplatNode && !(typeof splat !== "undefined" && splat !== null)) {
|
if (typeof splat !== "undefined" && splat !== null) {
|
||||||
splat = param;
|
if (param.attach) {
|
||||||
splat.index = i;
|
param.assign = new AssignNode(new ValueNode(literal('this'), [new AccessorNode(param.name)]));
|
||||||
splat.trailings = [];
|
this.body.expressions.splice(splat.index + 1, 0, param.assign);
|
||||||
splat.arglength = this.params.length;
|
}
|
||||||
this.body.unshift(splat);
|
|
||||||
} else if (typeof splat !== "undefined" && splat !== null) {
|
|
||||||
splat.trailings.push(param);
|
splat.trailings.push(param);
|
||||||
} else {
|
} else {
|
||||||
params.push(param);
|
if (param.attach) {
|
||||||
|
name = param.name;
|
||||||
|
param = literal(o.scope.freeVariable());
|
||||||
|
this.body.unshift(new AssignNode(new ValueNode(literal('this'), [new AccessorNode(name)]), param));
|
||||||
|
}
|
||||||
|
if (param.splat) {
|
||||||
|
splat = new SplatNode(param.name);
|
||||||
|
splat.index = i;
|
||||||
|
splat.trailings = [];
|
||||||
|
splat.arglength = this.params.length;
|
||||||
|
this.body.unshift(splat);
|
||||||
|
} else {
|
||||||
|
params.push(param);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
i += 1;
|
|
||||||
}
|
}
|
||||||
params = (function() {
|
params = (function() {
|
||||||
_e = []; _g = params;
|
_d = []; _f = params;
|
||||||
for (_f = 0, _h = _g.length; _f < _h; _f++) {
|
for (_e = 0, _g = _f.length; _e < _g; _e++) {
|
||||||
param = _g[_f];
|
param = _f[_e];
|
||||||
_e.push(param.compile(o));
|
_d.push(param.compile(o));
|
||||||
}
|
}
|
||||||
return _e;
|
return _d;
|
||||||
})();
|
})();
|
||||||
this.body.makeReturn();
|
this.body.makeReturn();
|
||||||
_j = params;
|
_i = params;
|
||||||
for (_i = 0, _k = _j.length; _i < _k; _i++) {
|
for (_h = 0, _j = _i.length; _h < _j; _h++) {
|
||||||
param = _j[_i];
|
param = _i[_h];
|
||||||
(o.scope.parameter(param));
|
(o.scope.parameter(param));
|
||||||
}
|
}
|
||||||
code = this.body.expressions.length ? ("\n" + (this.body.compileWithDeclarations(o)) + "\n") : '';
|
code = this.body.expressions.length ? ("\n" + (this.body.compileWithDeclarations(o)) + "\n") : '';
|
||||||
@@ -1029,6 +1038,24 @@
|
|||||||
};
|
};
|
||||||
return CodeNode;
|
return CodeNode;
|
||||||
})();
|
})();
|
||||||
|
exports.ParamNode = (function() {
|
||||||
|
ParamNode = function(name, attach, splat) {
|
||||||
|
this.name = literal(name);
|
||||||
|
this.attach = attach;
|
||||||
|
this.splat = splat;
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
__extends(ParamNode, BaseNode);
|
||||||
|
ParamNode.prototype['class'] = 'ParamNode';
|
||||||
|
ParamNode.prototype.children = ['name'];
|
||||||
|
ParamNode.prototype.compileNode = function(o) {
|
||||||
|
return this.name.compile(o);
|
||||||
|
};
|
||||||
|
ParamNode.prototype.toString = function(idt) {
|
||||||
|
return this.type === 'this' ? (literal("@" + name)).toString(idt) : this.name.toString(idt);
|
||||||
|
};
|
||||||
|
return ParamNode;
|
||||||
|
})();
|
||||||
exports.SplatNode = (function() {
|
exports.SplatNode = (function() {
|
||||||
SplatNode = function(name) {
|
SplatNode = function(name) {
|
||||||
if (!(name.compile)) {
|
if (!(name.compile)) {
|
||||||
@@ -1045,7 +1072,7 @@
|
|||||||
return (typeof (_b = this.index) !== "undefined" && _b !== null) ? this.compileParam(o) : this.name.compile(o);
|
return (typeof (_b = this.index) !== "undefined" && _b !== null) ? this.compileParam(o) : this.name.compile(o);
|
||||||
};
|
};
|
||||||
SplatNode.prototype.compileParam = function(o) {
|
SplatNode.prototype.compileParam = function(o) {
|
||||||
var _b, _c, end, idx, len, name, pos, trailing, variadic;
|
var _b, _c, assign, end, idx, len, name, pos, trailing, variadic;
|
||||||
name = this.name.compile(o);
|
name = this.name.compile(o);
|
||||||
o.scope.find(name);
|
o.scope.find(name);
|
||||||
end = '';
|
end = '';
|
||||||
@@ -1058,6 +1085,11 @@
|
|||||||
_b = this.trailings;
|
_b = this.trailings;
|
||||||
for (idx = 0, _c = _b.length; idx < _c; idx++) {
|
for (idx = 0, _c = _b.length; idx < _c; idx++) {
|
||||||
trailing = _b[idx];
|
trailing = _b[idx];
|
||||||
|
if (trailing.attach) {
|
||||||
|
assign = trailing.assign;
|
||||||
|
trailing = literal(o.scope.freeVariable());
|
||||||
|
assign.value = trailing;
|
||||||
|
}
|
||||||
pos = this.trailings.length - idx;
|
pos = this.trailings.length - idx;
|
||||||
o.scope.assign(trailing.compile(o), ("arguments[" + variadic + " ? " + len + " - " + pos + " : " + (this.index + idx) + "]"));
|
o.scope.assign(trailing.compile(o), ("arguments[" + variadic + " ? " + len + " - " + pos + " : " + (this.index + idx) + "]"));
|
||||||
}
|
}
|
||||||
|
|||||||
360
lib/parser.js
360
lib/parser.js
File diff suppressed because one or more lines are too long
@@ -203,7 +203,9 @@ grammar =
|
|||||||
# that hoovers up the remaining arguments.
|
# that hoovers up the remaining arguments.
|
||||||
Param: [
|
Param: [
|
||||||
o "PARAM", -> new LiteralNode $1
|
o "PARAM", -> new LiteralNode $1
|
||||||
o "Param . . .", -> new SplatNode $1
|
o "@ PARAM", -> new ParamNode $2, true
|
||||||
|
o "PARAM . . .", -> new ParamNode $1, false, true
|
||||||
|
o "@ PARAM . . .", -> new ParamNode $2, true, true
|
||||||
]
|
]
|
||||||
|
|
||||||
# A splat that occurs outside of a parameter list.
|
# A splat that occurs outside of a parameter list.
|
||||||
|
|||||||
@@ -871,21 +871,27 @@ exports.CodeNode = class CodeNode extends BaseNode
|
|||||||
o.indent = @idt(1)
|
o.indent = @idt(1)
|
||||||
del o, 'noWrap'
|
del o, 'noWrap'
|
||||||
del o, 'globals'
|
del o, 'globals'
|
||||||
i = 0
|
|
||||||
splat = undefined
|
splat = undefined
|
||||||
params = []
|
params = []
|
||||||
for param in @params
|
for param, i in @params
|
||||||
if param instanceof SplatNode and not splat?
|
if splat?
|
||||||
splat = param
|
if param.attach
|
||||||
splat.index = i
|
param.assign = new AssignNode new ValueNode literal('this'), [new AccessorNode param.name]
|
||||||
splat.trailings = []
|
@body.expressions.splice splat.index + 1, 0, param.assign
|
||||||
splat.arglength = @params.length
|
splat.trailings.push param
|
||||||
@body.unshift(splat)
|
|
||||||
else if splat?
|
|
||||||
splat.trailings.push(param)
|
|
||||||
else
|
else
|
||||||
params.push(param)
|
if param.attach
|
||||||
i += 1
|
name = param.name
|
||||||
|
param = literal o.scope.freeVariable()
|
||||||
|
@body.unshift new AssignNode new ValueNode(literal('this'), [new AccessorNode name]), param
|
||||||
|
if param.splat
|
||||||
|
splat = new SplatNode param.name
|
||||||
|
splat.index = i
|
||||||
|
splat.trailings = []
|
||||||
|
splat.arglength = @params.length
|
||||||
|
@body.unshift(splat)
|
||||||
|
else
|
||||||
|
params.push(param)
|
||||||
params = (param.compile(o) for param in params)
|
params = (param.compile(o) for param in params)
|
||||||
@body.makeReturn()
|
@body.makeReturn()
|
||||||
(o.scope.parameter(param)) for param in params
|
(o.scope.parameter(param)) for param in params
|
||||||
@@ -906,6 +912,26 @@ exports.CodeNode = class CodeNode extends BaseNode
|
|||||||
children = (child.toString(idt + TAB) for child in @collectChildren()).join('')
|
children = (child.toString(idt + TAB) for child in @collectChildren()).join('')
|
||||||
"\n#idt#children"
|
"\n#idt#children"
|
||||||
|
|
||||||
|
#### ParamNode
|
||||||
|
|
||||||
|
# A parameter in a function definition. Special parameters have a particular
|
||||||
|
# type - either 'this', meaning it assigns straight to the current context, or
|
||||||
|
# 'splat', where it gathers up a block of the parameters into an array.
|
||||||
|
exports.ParamNode = class ParamNode extends BaseNode
|
||||||
|
|
||||||
|
class: 'ParamNode'
|
||||||
|
children: ['name']
|
||||||
|
|
||||||
|
constructor: (name, attach, splat) ->
|
||||||
|
@name = literal name
|
||||||
|
@attach = attach
|
||||||
|
@splat = splat
|
||||||
|
|
||||||
|
compileNode: (o) -> @name.compile o
|
||||||
|
|
||||||
|
toString: (idt) ->
|
||||||
|
if @type is 'this' then (literal "@#name").toString idt else @name.toString idt
|
||||||
|
|
||||||
#### SplatNode
|
#### SplatNode
|
||||||
|
|
||||||
# A splat, either as a parameter to a function, an argument to a call,
|
# A splat, either as a parameter to a function, an argument to a call,
|
||||||
@@ -935,6 +961,10 @@ exports.SplatNode = class SplatNode extends BaseNode
|
|||||||
o.scope.assign variadic, "#len >= #@arglength"
|
o.scope.assign variadic, "#len >= #@arglength"
|
||||||
end = if @trailings.length then ", #len - #{@trailings.length}"
|
end = if @trailings.length then ", #len - #{@trailings.length}"
|
||||||
for trailing, idx in @trailings
|
for trailing, idx in @trailings
|
||||||
|
if trailing.attach
|
||||||
|
assign = trailing.assign
|
||||||
|
trailing = literal o.scope.freeVariable()
|
||||||
|
assign.value = trailing
|
||||||
pos = @trailings.length - idx
|
pos = @trailings.length - idx
|
||||||
o.scope.assign(trailing.compile(o), "arguments[#variadic ? #len - #pos : #{@index + idx}]")
|
o.scope.assign(trailing.compile(o), "arguments[#variadic ? #len - #pos : #{@index + idx}]")
|
||||||
"#name = #{utility('slice')}.call(arguments, #@index#end)"
|
"#name = #{utility('slice')}.call(arguments, #@index#end)"
|
||||||
|
|||||||
@@ -23,3 +23,10 @@ sumOfArgs = ->
|
|||||||
sum
|
sum
|
||||||
|
|
||||||
ok sumOfArgs(1, 2, 3, 4, 5) is 15
|
ok sumOfArgs(1, 2, 3, 4, 5) is 15
|
||||||
|
|
||||||
|
|
||||||
|
((@arg) ->).call context = {}, 1
|
||||||
|
ok context.arg is 1
|
||||||
|
|
||||||
|
((splat..., @arg) ->).call context, 1, 2, 3
|
||||||
|
ok context.arg is 3
|
||||||
Reference in New Issue
Block a user