From 0247b135f8e67afccdd4c9600b7bc81c2abf362b Mon Sep 17 00:00:00 2001 From: Simon Lydell Date: Fri, 10 Jun 2016 08:58:18 +0200 Subject: [PATCH] Improve naming of generated 'i-variables' In for example `for` loops, a variable called `i` is generated (for the loop index). If that name is unavailable, `j` is used instead, then `k`, `l`, etc. all the way to `z`. Then, `aa`, `ab`, `ac` etc. are used. This meant that, eventually, `do` would be used, but that's not a valid variable name since `do` is a JavaScript keyword. This logic was also inefficiently implemented. For example, going from `aa` to `ab` or from `az` to `ba` required lots of loop iterations. This commit changes the variable naming convention. Now, `i`, `j`, `k`, etc. to `z` are used like before. Then comes `i1`, `j1`, `k1`, etc. Then `i2`, `j2`, `k2` and so on. This is simpler, efficient and easier to understand. `i1` is more obvious to be a loop index than `aa`. Fixes #4267. --- lib/coffee-script/scope.js | 11 +++++++++-- src/scope.litcoffee | 10 ++++++++-- test/control_flow.coffee | 9 +++++++++ 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/lib/coffee-script/scope.js b/lib/coffee-script/scope.js index 0f9835a0..fd1cefc7 100644 --- a/lib/coffee-script/scope.js +++ b/lib/coffee-script/scope.js @@ -66,13 +66,20 @@ }; Scope.prototype.temporary = function(name, index, single) { + var diff, endCode, letter, newCode, num, startCode; if (single == null) { single = false; } if (single) { - return (index + parseInt(name, 36)).toString(36).replace(/\d/g, 'a'); + startCode = name.charCodeAt(0); + endCode = 'z'.charCodeAt(0); + diff = endCode - startCode; + newCode = startCode + index % (diff + 1); + letter = String.fromCharCode(newCode); + num = Math.floor(index / (diff + 1)); + return "" + letter + (num || ''); } else { - return name + (index || ''); + return "" + name + (index || ''); } }; diff --git a/src/scope.litcoffee b/src/scope.litcoffee index e983a782..8135cf00 100644 --- a/src/scope.litcoffee +++ b/src/scope.litcoffee @@ -66,9 +66,15 @@ Generate a temporary variable name at the given index. temporary: (name, index, single=false) -> if single - (index + parseInt name, 36).toString(36).replace /\d/g, 'a' + startCode = name.charCodeAt(0) + endCode = 'z'.charCodeAt(0) + diff = endCode - startCode + newCode = startCode + index % (diff + 1) + letter = String.fromCharCode(newCode) + num = index // (diff + 1) + "#{letter}#{num or ''}" else - name + (index or '') + "#{name}#{index or ''}" Gets the type of a variable. diff --git a/test/control_flow.coffee b/test/control_flow.coffee index 9725f445..dc91c099 100644 --- a/test/control_flow.coffee +++ b/test/control_flow.coffee @@ -464,3 +464,12 @@ test "#2367: super in for-loop", -> @sum eq 10, (new Bar).add 2, 3, 5 + +test "#4267: lots of for-loops in the same scope", -> + # This used to include the invalid JavaScript `var do = 0`. + code = """ + do -> + #{Array(200).join('for [0..0] then\n ')} + true + """ + ok CoffeeScript.eval(code)