mirror of
https://github.com/jashkenas/coffeescript.git
synced 2022-11-09 12:23:24 -05:00
fixed the while-loop-condition-with-implicit-function-call bug
This commit is contained in:
parent
4ea8be8e0b
commit
fa63288f52
3 changed files with 52 additions and 28 deletions
|
@ -1,5 +1,5 @@
|
|||
(function(){
|
||||
var BALANCED_PAIRS, EXPRESSION_CLOSE, EXPRESSION_START, EXPRESSION_TAIL, IMPLICIT_CALL, IMPLICIT_END, IMPLICIT_FUNC, INVERSES, SINGLE_CLOSERS, SINGLE_LINERS, _1, _2, _3, _4, _5, _6, _7, _8, pair, re;
|
||||
var BALANCED_PAIRS, EXPRESSION_CLOSE, EXPRESSION_START, EXPRESSION_TAIL, IMPLICIT_BLOCK, IMPLICIT_CALL, IMPLICIT_END, IMPLICIT_FUNC, INVERSES, SINGLE_CLOSERS, SINGLE_LINERS, _1, _2, _3, _4, _5, _6, _7, _8, pair, re;
|
||||
var __hasProp = Object.prototype.hasOwnProperty;
|
||||
if (!((typeof process !== "undefined" && process !== null))) {
|
||||
this.exports = this;
|
||||
|
@ -32,7 +32,8 @@
|
|||
EXPRESSION_CLOSE = ['CATCH', 'WHEN', 'ELSE', 'FINALLY'].concat(EXPRESSION_TAIL);
|
||||
// Tokens pairs that, in immediate succession, indicate an implicit call.
|
||||
IMPLICIT_FUNC = ['IDENTIFIER', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END'];
|
||||
IMPLICIT_END = ['IF', 'UNLESS', 'FOR', 'WHILE', 'TERMINATOR', 'OUTDENT'];
|
||||
IMPLICIT_BLOCK = ['->', '=>', '{', '[', ','];
|
||||
IMPLICIT_END = ['IF', 'UNLESS', 'FOR', 'WHILE', 'TERMINATOR', 'INDENT', 'OUTDENT'];
|
||||
IMPLICIT_CALL = ['IDENTIFIER', 'NUMBER', 'STRING', 'JS', 'REGEX', 'NEW', 'PARAM_START', 'TRY', 'DELETE', 'TYPEOF', 'SWITCH', 'TRUE', 'FALSE', 'YES', 'NO', 'ON', 'OFF', '!', '!!', 'NOT', '@', '->', '=>', '[', '(', '{'];
|
||||
// The inverse mappings of token pairs we're trying to fix up.
|
||||
INVERSES = {};
|
||||
|
@ -193,25 +194,32 @@
|
|||
stack = [0];
|
||||
return this.scan_tokens((function(__this) {
|
||||
var __func = function(prev, token, post, i) {
|
||||
var _10, _11, _12, _9, idx, last, size, tmp;
|
||||
if (token[0] === 'INDENT') {
|
||||
var _10, _11, _12, _9, idx, last, size, stack_pointer, tag, tmp;
|
||||
tag = token[0];
|
||||
if (tag === 'INDENT') {
|
||||
stack.push(0);
|
||||
}
|
||||
if (token[0] === 'OUTDENT') {
|
||||
if (tag === 'OUTDENT') {
|
||||
last = stack.pop();
|
||||
stack[stack.length - 1] += last;
|
||||
}
|
||||
if (stack[stack.length - 1] > 0 && (IMPLICIT_END.indexOf(token[0]) >= 0 || !(typeof post !== "undefined" && post !== null))) {
|
||||
idx = token[0] === 'OUTDENT' ? i + 1 : i;
|
||||
_11 = 0; _12 = stack[stack.length - 1];
|
||||
for (_10=0, tmp=_11; (_11 <= _12 ? tmp < _12 : tmp > _12); (_11 <= _12 ? tmp += 1 : tmp -= 1), _10++) {
|
||||
this.tokens.splice(idx, 0, ['CALL_END', ')', token[2]]);
|
||||
if (IMPLICIT_END.indexOf(tag) >= 0 || !(typeof post !== "undefined" && post !== null)) {
|
||||
if (tag === 'INDENT' && prev && IMPLICIT_BLOCK.indexOf(prev[0]) >= 0) {
|
||||
return 1;
|
||||
}
|
||||
if (stack[stack.length - 1] > 0 || tag === 'INDENT') {
|
||||
idx = tag === 'OUTDENT' ? i + 1 : i;
|
||||
stack_pointer = tag === 'INDENT' ? 2 : 1;
|
||||
_11 = 0; _12 = stack[stack.length - stack_pointer];
|
||||
for (_10=0, tmp=_11; (_11 <= _12 ? tmp < _12 : tmp > _12); (_11 <= _12 ? tmp += 1 : tmp -= 1), _10++) {
|
||||
this.tokens.splice(idx, 0, ['CALL_END', ')', token[2]]);
|
||||
}
|
||||
size = stack[stack.length - stack_pointer] + 1;
|
||||
stack[stack.length - stack_pointer] = 0;
|
||||
return size;
|
||||
}
|
||||
size = stack[stack.length - 1] + 1;
|
||||
stack[stack.length - 1] = 0;
|
||||
return size;
|
||||
}
|
||||
if (!(prev && IMPLICIT_FUNC.indexOf(prev[0]) >= 0 && IMPLICIT_CALL.indexOf(token[0]) >= 0)) {
|
||||
if (!(prev && IMPLICIT_FUNC.indexOf(prev[0]) >= 0 && IMPLICIT_CALL.indexOf(tag) >= 0)) {
|
||||
return 1;
|
||||
}
|
||||
this.tokens.splice(i, 0, ['CALL_START', '(', token[2]]);
|
||||
|
@ -306,7 +314,7 @@
|
|||
return _9;
|
||||
}).call(this);
|
||||
if (unclosed.length) {
|
||||
throw "unclosed " + unclosed[0];
|
||||
throw new Error("unclosed " + unclosed[0]);
|
||||
}
|
||||
};
|
||||
// We'd like to support syntax like this:
|
||||
|
|
|
@ -20,7 +20,8 @@ EXPRESSION_CLOSE: ['CATCH', 'WHEN', 'ELSE', 'FINALLY'].concat(EXPRESSION_TAIL)
|
|||
|
||||
# Tokens pairs that, in immediate succession, indicate an implicit call.
|
||||
IMPLICIT_FUNC: ['IDENTIFIER', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END']
|
||||
IMPLICIT_END: ['IF', 'UNLESS', 'FOR', 'WHILE', 'TERMINATOR', 'OUTDENT']
|
||||
IMPLICIT_BLOCK:['->', '=>', '{', '[', ',']
|
||||
IMPLICIT_END: ['IF', 'UNLESS', 'FOR', 'WHILE', 'TERMINATOR', 'INDENT', 'OUTDENT']
|
||||
IMPLICIT_CALL: ['IDENTIFIER', 'NUMBER', 'STRING', 'JS', 'REGEX', 'NEW', 'PARAM_START',
|
||||
'TRY', 'DELETE', 'TYPEOF', 'SWITCH',
|
||||
'TRUE', 'FALSE', 'YES', 'NO', 'ON', 'OFF', '!', '!!', 'NOT',
|
||||
|
@ -140,18 +141,22 @@ re::close_open_calls_and_indexes: ->
|
|||
re::add_implicit_parentheses: ->
|
||||
stack: [0]
|
||||
@scan_tokens (prev, token, post, i) =>
|
||||
stack.push(0) if token[0] is 'INDENT'
|
||||
if token[0] is 'OUTDENT'
|
||||
tag: token[0]
|
||||
stack.push(0) if tag is 'INDENT'
|
||||
if tag is 'OUTDENT'
|
||||
last: stack.pop()
|
||||
stack[stack.length - 1] += last
|
||||
if stack[stack.length - 1] > 0 and (IMPLICIT_END.indexOf(token[0]) >= 0 or !post?)
|
||||
idx: if token[0] is 'OUTDENT' then i + 1 else i
|
||||
for tmp in [0...stack[stack.length - 1]]
|
||||
@tokens.splice(idx, 0, ['CALL_END', ')', token[2]])
|
||||
size: stack[stack.length - 1] + 1
|
||||
stack[stack.length - 1]: 0
|
||||
return size
|
||||
return 1 unless prev and IMPLICIT_FUNC.indexOf(prev[0]) >= 0 and IMPLICIT_CALL.indexOf(token[0]) >= 0
|
||||
if IMPLICIT_END.indexOf(tag) >= 0 or !post?
|
||||
return 1 if tag is 'INDENT' and prev and IMPLICIT_BLOCK.indexOf(prev[0]) >= 0
|
||||
if stack[stack.length - 1] > 0 or tag is 'INDENT'
|
||||
idx: if tag is 'OUTDENT' then i + 1 else i
|
||||
stack_pointer: if tag is 'INDENT' then 2 else 1
|
||||
for tmp in [0...stack[stack.length - stack_pointer]]
|
||||
@tokens.splice(idx, 0, ['CALL_END', ')', token[2]])
|
||||
size: stack[stack.length - stack_pointer] + 1
|
||||
stack[stack.length - stack_pointer]: 0
|
||||
return size
|
||||
return 1 unless prev and IMPLICIT_FUNC.indexOf(prev[0]) >= 0 and IMPLICIT_CALL.indexOf(tag) >= 0
|
||||
@tokens.splice(i, 0, ['CALL_START', '(', token[2]])
|
||||
stack[stack.length - 1] += 1
|
||||
return 2
|
||||
|
@ -196,7 +201,7 @@ re::ensure_balance: (pairs) ->
|
|||
throw "too many " + token[1] if levels[open] < 0
|
||||
return 1
|
||||
unclosed: key for key, value of levels when value > 0
|
||||
throw "unclosed " + unclosed[0] if unclosed.length
|
||||
throw new Error("unclosed " + unclosed[0]) if unclosed.length
|
||||
|
||||
# We'd like to support syntax like this:
|
||||
# el.click((event) ->
|
||||
|
|
13
test/fixtures/execution/test_while.coffee
vendored
13
test/fixtures/execution/test_while.coffee
vendored
|
@ -14,4 +14,15 @@ puts list.join(' ') is "8 6 4 2"
|
|||
i: 5
|
||||
list: (i * 3 while i -= 1)
|
||||
|
||||
puts list.join(' ') is "12 9 6 3"
|
||||
puts list.join(' ') is "12 9 6 3"
|
||||
|
||||
|
||||
i: 5
|
||||
func: (num) -> i -= num
|
||||
assert: -> puts i < 5 > 0
|
||||
|
||||
results: while func 1
|
||||
assert()
|
||||
i
|
||||
|
||||
puts results.join(' ') is '4 3 2 1'
|
Loading…
Reference in a new issue