diff --git a/lib/nodes.js b/lib/nodes.js index eb9b9b78..2ce5b1e3 100644 --- a/lib/nodes.js +++ b/lib/nodes.js @@ -795,12 +795,21 @@ Slice.__super__.constructor.call(this); } Slice.prototype.compileNode = function(o) { - var compiled, definition, from, fromStr, ref, to, toStr, _ref, _ref2; + var compiled, definition, from, fromStr, ref, reference, to, toStr, _ref, _ref2; _ref = this.range, to = _ref.to, from = _ref.from; fromStr = from ? from.compile(o) : '0'; compiled = to != null ? to.compile(o, LEVEL_PAREN) : void 0; if (to && !(!this.range.exclusive && +compiled === -1)) { - toStr = ', ' + (this.range.exclusive ? to.compile(o) : /^[+-]?\d+$/.test(compiled) ? '' + (+compiled + 1) : ((_ref2 = to.cache(o), definition = _ref2[0], ref = _ref2[1], _ref2), '(' + definition.compile(o, LEVEL_PAREN) + ' + 1) ? ' + ref.compile(o) + ' : 9e9')); + toStr = ', ' + (this.range.exclusive ? to.compile(o) : /^[+-]?\d+$/.test(compiled) ? '' + (+compiled + 1) : ((_ref2 = (function() { + var _i, _len, _ref, _results; + _ref = to.cache(o); + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + ref = _ref[_i]; + _results.push(ref.compile(o, LEVEL_PAREN)); + } + return _results; + }()), definition = _ref2[0], reference = _ref2[1], _ref2), reference === definition ? reference + ' + 1 ? ' + reference + ' + 1 : 9e9' : '(' + definition + ' + 1) ? ' + reference + ' : 9e9')); } return ".slice(" + fromStr + (toStr || '') + ")"; }; diff --git a/src/nodes.coffee b/src/nodes.coffee index a901c9a1..16a30664 100644 --- a/src/nodes.coffee +++ b/src/nodes.coffee @@ -674,10 +674,13 @@ exports.Slice = class Slice extends Base else if /^[+-]?\d+$/.test compiled '' + (+compiled + 1) else - [definition, ref] = to.cache o - # `9e9` used below because not all implementations respect `undefined` or `1/0` + [definition, reference] = (ref.compile(o,LEVEL_PAREN) for ref in to.cache o) + # `9e9` used below because not all implementations respect `undefined` or `1/0` # `9e9` should be safe because `9e9` > `2**32`, the max array length - '(' + definition.compile(o,LEVEL_PAREN) + ' + 1) ? ' + ref.compile(o) + ' : 9e9' + if reference is definition + reference + ' + 1 ? ' + reference + ' + 1 : 9e9' + else + '(' + definition + ' + 1) ? ' + reference + ' : 9e9' ".slice(#{fromStr}#{toStr||''})" #### Obj diff --git a/test/ranges_slices_and_splices.coffee b/test/ranges_slices_and_splices.coffee index aecbfa20..1cc1dc4c 100644 --- a/test/ranges_slices_and_splices.coffee +++ b/test/ranges_slices_and_splices.coffee @@ -7,26 +7,74 @@ shared = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] #### Ranges -test "basic ranges", -> - arrayEqual [2, 3, 4, 5], [2...6] +test "basic inclusive ranges", -> + arrayEqual [1, 2, 3] , [1..3] + arrayEqual [0, 1, 2] , [0..2] + arrayEqual [0, 1] , [0..1] + arrayEqual [0] , [0..0] + arrayEqual [-1] , [-1..-1] + arrayEqual [-1, 0] , [-1..0] + arrayEqual [-1, 0, 1], [-1..1] + +test "basic exclusive ranges", -> + arrayEqual [1, 2, 3] , [1...4] + arrayEqual [0, 1, 2] , [0...3] + arrayEqual [0, 1] , [0...2] + arrayEqual [0] , [0...1] + arrayEqual [-1] , [-1...0] + arrayEqual [-1, 0] , [-1...1] + arrayEqual [-1, 0, 1], [-1...2] + + arrayEqual [], [1...1] + arrayEqual [], [0...0] + arrayEqual [], [-1...-1] test "downward ranges", -> arrayEqual shared, [9..0].reverse() - arrayEqual [5, 4, 3, 2, 1], [5..1] + arrayEqual [5, 4, 3, 2] , [5..2] + arrayEqual [2, 1, 0, -1], [2..-1] + + arrayEqual [3, 2, 1] , [3..1] + arrayEqual [2, 1, 0] , [2..0] + arrayEqual [1, 0] , [1..0] + arrayEqual [0] , [0..0] + arrayEqual [-1] , [-1..-1] + arrayEqual [0, -1] , [0..-1] + arrayEqual [1, 0, -1] , [1..-1] + arrayEqual [0, -1, -2], [0..-2] + + arrayEqual [4, 3, 2], [4...1] + arrayEqual [3, 2, 1], [3...0] + arrayEqual [2, 1] , [2...0] + arrayEqual [1] , [1...0] + arrayEqual [] , [0...0] + arrayEqual [] , [-1...-1] + arrayEqual [0] , [0...-1] + arrayEqual [0, -1] , [0...-2] + arrayEqual [1, 0] , [1...-1] + arrayEqual [2, 1, 0], [2...-1] test "ranges with variables as enpoints", -> - [a, b] = [1, 5] - arrayEqual [1, 2, 3, 4], [a...b] - b = -5 - arrayEqual [1, 0, -1, -2, -3, -4, -5], [a..b] + [a, b] = [1, 3] + arrayEqual [1, 2, 3], [a..b] + arrayEqual [1, 2] , [a...b] + b = -2 + arrayEqual [1, 0, -1, -2], [a..b] + arrayEqual [1, 0, -1] , [a...b] test "ranges with expressions as endpoints", -> - arrayEqual [6, 7, 8, 9, 10], [(1+5)..1+9] + [a, b] = [1, 3] + arrayEqual [2, 3, 4, 5, 6], [(a+1)..2*b] + arrayEqual [2, 3, 4, 5] , [(a+1)...2*b] test "large ranges are generated with looping constructs", -> - ary = [100...0] - ok (len = ary.length) is 100 - ok ary[len - 1] is 1 + down = [99..0] + eq 100, (len = down.length) + eq 0, down[len - 1] + + up = [0...100] + eq 100, (len = up.length) + eq 99, up[len - 1] #### Slices @@ -37,10 +85,14 @@ test "basic slicing", -> arrayEqual [2, 3, 4, 5], shared[2...6] test "slicing with variables as endpoints", -> - [a, b] = [1, 5] - arrayEqual [1, 2, 3, 4], shared[a...b] + [a, b] = [1, 4] + arrayEqual [1, 2, 3, 4], shared[a..b] + arrayEqual [1, 2, 3] , shared[a...b] test "slicing with expressions as endpoints", -> + [a, b] = [1, 3] + arrayEqual [2, 3, 4, 5, 6], shared[(a+1)..2*b] + arrayEqual [2, 3, 4, 5] , shared[a+1...(2*b)] test "unbounded slicing", -> arrayEqual [7, 8, 9] , shared[7..] @@ -48,12 +100,19 @@ test "unbounded slicing", -> arrayEqual [9] , shared[-1...] arrayEqual [0, 1, 2] , shared[...3] arrayEqual [0, 1, 2, 3], shared[..-7] - arrayEqual shared[a..] , shared[a...] for a in [-shared.length..shared.length] + arrayEqual shared , shared[..-1] arrayEqual shared[0..8], shared[...-1] - arrayEqual shared[..a] , shared[...a] for a in [-shared.length..shared.length] when a isnt -1 + + for a in [-shared.length..shared.length] + arrayEqual shared[a..] , shared[a...] + for a in [-shared.length+1...shared.length] + arrayEqual shared[..a][...-1] , shared[...a] test "#930, #835, #831, #746 #624: inclusive slices to -1 should slice to end", -> + arrayEqual shared, shared[0..-1] + arrayEqual shared, shared[..-1] + arrayEqual shared.slice(1,shared.length), shared[1..-1] test "string slicing", -> str = "abcdefghijklmnopqrstuvwxyz" @@ -71,6 +130,10 @@ test "basic splicing", -> ary[5..9] = [0, 0, 0] arrayEqual [0, 1, 2, 3, 4, 0, 0, 0], ary + ary = [0..9] + ary[2...8] = [] + arrayEqual [0, 1, 8, 9], ary + test "unbounded splicing", -> ary = [0..9] ary[3..] = [9, 8, 7] @@ -79,6 +142,21 @@ test "unbounded splicing", -> ary[...3] = [7, 8, 9] arrayEqual [7, 8, 9, 9, 8, 7], ary -# splicing with variables as endpoints +test "splicing with variables as endpoints", -> + [a, b] = [1, 8] -# splicing with expressions as endpoints + ary = [0..9] + ary[a..b] = [2, 3] + arrayEqual [0, 2, 3, 9], ary + + ary = [0..9] + ary[a...b] = [5] + arrayEqual [0, 5, 8, 9], ary + +# currently broken: +# test "splicing with expressions as endpoints", -> +# [a, b] = [1, 3] +# +# ary = [0..9] +# ary[ a+1 .. 2*b+1 ] = [4] +# arrayEqual [0, 1, 4, 7, 8, 9], ary