slightly nicer implementation of SplatNode.compileSplattedArray

This commit is contained in:
Jeremy Ashkenas
2010-07-13 22:16:19 -04:00
parent 8c34aff1c5
commit 0b87387fab
5 changed files with 43 additions and 28 deletions

View File

@@ -1,5 +1,5 @@
(function(){ (function(){
var compact, count, del, extend, flatten, helpers, include, indexOf, merge, starts; var compact, count, del, ends, extend, flatten, helpers, include, indexOf, merge, starts;
var __hasProp = Object.prototype.hasOwnProperty; var __hasProp = Object.prototype.hasOwnProperty;
if (!(typeof process !== "undefined" && process !== null)) { if (!(typeof process !== "undefined" && process !== null)) {
this.exports = this; this.exports = this;
@@ -25,6 +25,11 @@
helpers.starts = (starts = function(string, literal, start) { helpers.starts = (starts = function(string, literal, start) {
return string.substring(start, (start || 0) + literal.length) === literal; return string.substring(start, (start || 0) + literal.length) === literal;
}); });
helpers.ends = (ends = function(string, literal, back) {
var start;
start = string.length - literal.length - ((typeof back !== "undefined" && back !== null) ? back : 0);
return string.substring(start, start + literal.length) === literal;
});
helpers.compact = (compact = function(array) { helpers.compact = (compact = function(array) {
var _a, _b, _c, _d, item; var _a, _b, _c, _d, item;
_a = []; _c = array; _a = []; _c = array;

View File

@@ -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, Scope, SliceNode, SplatNode, TAB, TRAILING_WHITESPACE, ThrowNode, TryNode, UTILITIES, ValueNode, WhileNode, _a, compact, del, 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, ParentheticalNode, PushNode, RangeNode, ReturnNode, 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;
@@ -23,6 +23,7 @@
include = _a.include; include = _a.include;
indexOf = _a.indexOf; indexOf = _a.indexOf;
starts = _a.starts; starts = _a.starts;
ends = _a.ends;
exports.BaseNode = (function() { exports.BaseNode = (function() {
BaseNode = function() { }; BaseNode = function() { };
BaseNode.prototype.compile = function(o) { BaseNode.prototype.compile = function(o) {
@@ -419,7 +420,7 @@
this.variable = this.isSuper ? null : variable; this.variable = this.isSuper ? null : variable;
this.args = (args || []); this.args = (args || []);
this.compileSplatArguments = function(o) { this.compileSplatArguments = function(o) {
return SplatNode.compileMixedArray.call(this, this.args, o); return SplatNode.compileSplattedArray.call(this, this.args, o);
}; };
return this; return this;
}; };
@@ -670,7 +671,7 @@
ArrayNode = function(objects) { ArrayNode = function(objects) {
this.objects = objects || []; this.objects = objects || [];
this.compileSplatLiteral = function(o) { this.compileSplatLiteral = function(o) {
return SplatNode.compileMixedArray.call(this, this.objects, o); return SplatNode.compileSplattedArray.call(this, this.objects, o);
}; };
return this; return this;
}; };
@@ -1015,28 +1016,26 @@
trail = trailings ? (", " + (name) + ".length - " + trailings) : ''; trail = trailings ? (", " + (name) + ".length - " + trailings) : '';
return "" + (utility('slice')) + ".call(" + name + ", " + index + trail + ")"; return "" + (utility('slice')) + ".call(" + name + ", " + index + trail + ")";
}; };
SplatNode.compileMixedArray = function(list, o) { SplatNode.compileSplattedArray = function(list, o) {
var _b, _c, _d, arg, args, code, i, prev; var _b, _c, arg, args, code, i, last, prev;
args = []; args = [];
i = 0; _b = list;
_c = list; for (i = 0, _c = _b.length; i < _c; i++) {
for (_b = 0, _d = _c.length; _b < _d; _b++) { arg = _b[i];
arg = _c[_b];
code = arg.compile(o); code = arg.compile(o);
prev = args[(last = args.length - 1)];
if (!(arg instanceof SplatNode)) { if (!(arg instanceof SplatNode)) {
prev = args[i - 1]; if (prev && starts(prev, '[') && ends(prev, ']')) {
if (i === 1 && prev.substr(0, 1) === '[' && prev.substr(prev.length - 1, 1) === ']') { args[last] = ("" + (prev.substr(0, prev.length - 1)) + ", " + code + "]");
args[i - 1] = ("" + (prev.substr(0, prev.length - 1)) + ", " + code + "]");
continue; continue;
} else if (i > 1 && prev.substr(0, 9) === '.concat([' && prev.substr(prev.length - 2, 2) === '])') { } else if (prev && starts(prev, '.concat([') && ends(prev, '])')) {
args[i - 1] = ("" + (prev.substr(0, prev.length - 2)) + ", " + code + "])"); args[last] = ("" + (prev.substr(0, prev.length - 2)) + ", " + code + "])");
continue; continue;
} else { } else {
code = ("[" + code + "]"); code = ("[" + code + "]");
} }
} }
args.push(i === 0 ? code : (".concat(" + code + ")")); args.push(i === 0 ? code : (".concat(" + code + ")"));
i += 1;
} }
return args.join(''); return args.join('');
}; };

View File

@@ -22,6 +22,11 @@ helpers.include: include: (list, value) ->
helpers.starts: starts: (string, literal, start) -> helpers.starts: starts: (string, literal, start) ->
string.substring(start, (start or 0) + literal.length) is literal string.substring(start, (start or 0) + literal.length) is literal
# Peek at the end of a given string to see if it matches a sequence.
helpers.ends: ends: (string, literal, back) ->
start: string.length - literal.length - (back ? 0)
string.substring(start, start + literal.length) is literal
# Trim out all falsy values from an array. # Trim out all falsy values from an array.
helpers.compact: compact: (array) -> item for item in array when item helpers.compact: compact: (array) -> item for item in array when item

View File

@@ -14,7 +14,7 @@ else
Scope: this.Scope Scope: this.Scope
# Import the helpers we plan to use. # Import the helpers we plan to use.
{compact, flatten, merge, del, include, indexOf, starts}: helpers {compact, flatten, merge, del, include, indexOf, starts, ends}: helpers
#### BaseNode #### BaseNode
@@ -403,7 +403,7 @@ exports.CallNode: class CallNode extends BaseNode
@variable: if @isSuper then null else variable @variable: if @isSuper then null else variable
@args: (args or []) @args: (args or [])
@compileSplatArguments: (o) -> @compileSplatArguments: (o) ->
SplatNode.compileMixedArray.call(this, @args, o) SplatNode.compileSplattedArray.call(this, @args, o)
# Tag this invocation as creating a new instance. # Tag this invocation as creating a new instance.
newInstance: -> newInstance: ->
@@ -625,7 +625,7 @@ exports.ArrayNode: class ArrayNode extends BaseNode
constructor: (objects) -> constructor: (objects) ->
@objects: objects or [] @objects: objects or []
@compileSplatLiteral: (o) -> @compileSplatLiteral: (o) ->
SplatNode.compileMixedArray.call(this, @objects, o) SplatNode.compileSplattedArray.call(this, @objects, o)
compileNode: (o) -> compileNode: (o) ->
o.indent: @idt 1 o.indent: @idt 1
@@ -921,23 +921,21 @@ exports.SplatNode: class SplatNode extends BaseNode
# Utility function that converts arbitrary number of elements, mixed with # Utility function that converts arbitrary number of elements, mixed with
# splats, to a proper array # splats, to a proper array
@compileMixedArray: (list, o) -> @compileSplattedArray: (list, o) ->
args: [] args: []
i: 0 for arg, i in list
for arg in list
code: arg.compile o code: arg.compile o
prev: args[last: args.length - 1]
if not (arg instanceof SplatNode) if not (arg instanceof SplatNode)
prev: args[i - 1] if prev and starts(prev, '[') and ends(prev, ']')
if i is 1 and prev.substr(0, 1) is '[' and prev.substr(prev.length - 1, 1) is ']' args[last]: "${prev.substr(0, prev.length - 1)}, $code]"
args[i - 1]: "${prev.substr(0, prev.length - 1)}, $code]"
continue continue
else if i > 1 and prev.substr(0, 9) is '.concat([' and prev.substr(prev.length - 2, 2) is '])' else if prev and starts(prev, '.concat([') and ends(prev, '])')
args[i - 1]: "${prev.substr(0, prev.length - 2)}, $code])" args[last]: "${prev.substr(0, prev.length - 2)}, $code])"
continue continue
else else
code: "[$code]" code: "[$code]"
args.push(if i is 0 then code else ".concat($code)") args.push(if i is 0 then code else ".concat($code)")
i: + 1
args.join('') args.join('')
#### WhileNode #### WhileNode

View File

@@ -105,3 +105,11 @@ ok pen is 2
method 1, 2 method 1, 2
ok pen is 2 ok pen is 2
# Array splat expansions with assigns.
nums: [1, 2, 3]
list: [a: 0, nums..., b: 4]
ok a is 0
ok b is 4
ok list.join(' ') is '0 1 2 3 4'