1
0
Fork 0
mirror of https://github.com/jashkenas/coffeescript.git synced 2022-11-09 12:23:24 -05:00

Allow @ values as indices in for expressions

This loosens the compilation of `for` expressions to allow the index
variable to be an `@` value, e.g.

    do @visit for @node, @index in nodes

Within `@visit`, the index of the current node (`@node`) would be
available as `@index`.

Fixes #4411.
This commit is contained in:
Chris Connelly 2016-12-29 18:55:33 +00:00
parent 0a6aeef0c9
commit 1143ac0268
4 changed files with 21 additions and 4 deletions

View file

@ -3415,7 +3415,7 @@
if (this.object) {
ref3 = [this.index, this.name], this.name = ref3[0], this.index = ref3[1];
}
if (this.index instanceof Value) {
if (this.index instanceof Value && !this.index.isAssignable()) {
this.index.error('index cannot be a pattern matching expression');
}
this.range = this.source instanceof Value && this.source.base instanceof Range && !this.source.properties.length && !this.from;
@ -3447,7 +3447,7 @@
if (name && !this.pattern) {
scope.find(name);
}
if (index) {
if (index && !(this.index instanceof Value)) {
scope.find(index);
}
if (this.returns) {

View file

@ -2312,7 +2312,7 @@ exports.For = class For extends While
@index.error 'cannot use index with for-from' if @from and @index
source.ownTag.error "cannot use own with for-#{if @from then 'from' else 'in'}" if @own and not @object
[@name, @index] = [@index, @name] if @object
@index.error 'index cannot be a pattern matching expression' if @index instanceof Value
@index.error 'index cannot be a pattern matching expression' if @index instanceof Value and not @index.isAssignable()
@range = @source instanceof Value and @source.base instanceof Range and not @source.properties.length and not @from
@pattern = @name instanceof Value
@index.error 'indexes do not apply to range loops' if @range and @index
@ -2334,7 +2334,7 @@ exports.For = class For extends While
name = @name and (@name.compile o, LEVEL_LIST) if not @pattern
index = @index and (@index.compile o, LEVEL_LIST)
scope.find(name) if name and not @pattern
scope.find(index) if index
scope.find(index) if index and @index not instanceof Value
rvar = scope.freeVariable 'results' if @returns
if @from
ivar = scope.freeVariable 'x', single: true if @pattern

View file

@ -515,6 +515,16 @@ test "#2274: Allow @values as loop variables", ->
obj.method()
eq obj.item, 3
test "#4411: Allow @values as loop indices", ->
obj =
index: null
get: -> @index
method: ->
@get() for _, @index in [1, 2, 3]
eq obj.index, null
arrayEq obj.method(), [0, 1, 2]
eq obj.index, 3
test "#2525, #1187, #1208, #1758, looping over an array forwards", ->
list = [0, 1, 2, 3, 4]

View file

@ -1179,3 +1179,10 @@ test "tagged template literals must be called by an identifier", ->
1"""#{b}"""
^
'''
test "can't use pattern matches for loop indices", ->
assertErrorFormat 'a for b, {c} in d', '''
[stdin]:1:10: error: index cannot be a pattern matching expression
a for b, {c} in d
^^^
'''