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

Pulling in variable declarations closer to inner scope (after Coco).

This commit is contained in:
Jeremy Ashkenas 2010-12-13 21:24:32 -05:00
parent b5bd58b2b6
commit 466cd43277
8 changed files with 56 additions and 47 deletions

View file

@ -211,8 +211,9 @@
return jsl.stdin.end(); return jsl.stdin.end();
}; };
printTokens = function(tokens) { printTokens = function(tokens) {
var strings, tag, token, value, _i, _len, _ref, _results; var strings, tag, token, value;
strings = function() { strings = function() {
var _i, _len, _ref, _results;
_results = []; _results = [];
for (_i = 0, _len = tokens.length; _i < _len; _i++) { for (_i = 0, _len = tokens.length; _i < _len; _i++) {
token = tokens[_i]; token = tokens[_i];

View file

@ -1,5 +1,5 @@
(function() { (function() {
var Parser, alt, alternatives, grammar, name, o, operators, token, tokens, unwrap, _i, _j, _len, _len2, _ref, _results; var Parser, alt, alternatives, grammar, name, o, operators, token, tokens, unwrap;
Parser = require('jison').Parser; Parser = require('jison').Parser;
unwrap = /^function\s*\(\)\s*\{\s*return\s*([\s\S]*);\s*\}/; unwrap = /^function\s*\(\)\s*\{\s*return\s*([\s\S]*);\s*\}/;
o = function(patternString, action, options) { o = function(patternString, action, options) {
@ -561,6 +561,7 @@
for (name in grammar) { for (name in grammar) {
alternatives = grammar[name]; alternatives = grammar[name];
grammar[name] = function() { grammar[name] = function() {
var _i, _j, _len, _len2, _ref, _results;
_results = []; _results = [];
for (_i = 0, _len = alternatives.length; _i < _len; _i++) { for (_i = 0, _len = alternatives.length; _i < _len; _i++) {
alt = alternatives[_i]; alt = alternatives[_i];

View file

@ -44,7 +44,7 @@
if (this.containsPureStatement()) { if (this.containsPureStatement()) {
throw SyntaxError('cannot include a pure statement in an expression.'); throw SyntaxError('cannot include a pure statement in an expression.');
} }
o.sharedScope = o.scope; o.sharedScope = true;
return Closure.wrap(this).compileNode(o); return Closure.wrap(this).compileNode(o);
}; };
Base.prototype.cache = function(o, level, reused) { Base.prototype.cache = function(o, level, reused) {
@ -597,7 +597,7 @@
return ifn; return ifn;
}; };
Call.prototype.compileNode = function(o) { Call.prototype.compileNode = function(o) {
var arg, args, code, _i, _len, _ref, _ref2, _results; var arg, args, code, _ref;
if ((_ref = this.variable) != null) { if ((_ref = this.variable) != null) {
_ref.front = this.front; _ref.front = this.front;
} }
@ -605,10 +605,11 @@
return this.compileSplat(o, code); return this.compileSplat(o, code);
} }
args = (function() { args = (function() {
_ref2 = this.args; var _i, _len, _ref, _results;
_ref = this.args;
_results = []; _results = [];
for (_i = 0, _len = _ref2.length; _i < _len; _i++) { for (_i = 0, _len = _ref.length; _i < _len; _i++) {
arg = _ref2[_i]; arg = _ref[_i];
_results.push(arg.compile(o, LEVEL_LIST)); _results.push(arg.compile(o, LEVEL_LIST));
} }
return _results; return _results;
@ -803,7 +804,7 @@
} }
Obj.prototype.children = ['properties']; Obj.prototype.children = ['properties'];
Obj.prototype.compileNode = function(o) { Obj.prototype.compileNode = function(o) {
var i, idt, indent, join, lastNoncom, nonComments, obj, prop, props, _i, _len, _len2, _ref, _results, _results2; var i, idt, indent, join, lastNoncom, nonComments, obj, prop, props;
props = this.properties; props = this.properties;
if (!props.length) { if (!props.length) {
if (this.front) { if (this.front) {
@ -814,6 +815,7 @@
} }
idt = o.indent += TAB; idt = o.indent += TAB;
nonComments = (function() { nonComments = (function() {
var _i, _len, _ref, _results;
_ref = this.properties; _ref = this.properties;
_results = []; _results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) { for (_i = 0, _len = _ref.length; _i < _len; _i++) {
@ -826,8 +828,9 @@
}.call(this)); }.call(this));
lastNoncom = last(nonComments); lastNoncom = last(nonComments);
props = function() { props = function() {
_results2 = []; var _len, _results;
for (i = 0, _len2 = props.length; i < _len2; i++) { _results = [];
for (i = 0, _len = props.length; i < _len; i++) {
prop = props[i]; prop = props[i];
join = i === props.length - 1 ? '' : prop === lastNoncom || prop instanceof Comment ? '\n' : ',\n'; join = i === props.length - 1 ? '' : prop === lastNoncom || prop instanceof Comment ? '\n' : ',\n';
indent = prop instanceof Comment ? '' : idt; indent = prop instanceof Comment ? '' : idt;
@ -836,9 +839,9 @@
} else if (!(prop instanceof Assign) && !(prop instanceof Comment)) { } else if (!(prop instanceof Assign) && !(prop instanceof Comment)) {
prop = new Assign(prop, prop, 'object'); prop = new Assign(prop, prop, 'object');
} }
_results2.push(indent + prop.compile(o, LEVEL_TOP) + join); _results.push(indent + prop.compile(o, LEVEL_TOP) + join);
} }
return _results2; return _results;
}(); }();
props = props.join(''); props = props.join('');
obj = "{" + (props && '\n' + props + '\n' + this.tab) + "}"; obj = "{" + (props && '\n' + props + '\n' + this.tab) + "}";
@ -868,7 +871,7 @@
} }
Arr.prototype.children = ['objects']; Arr.prototype.children = ['objects'];
Arr.prototype.compileNode = function(o) { Arr.prototype.compileNode = function(o) {
var code, obj, _i, _len, _ref, _results; var code, obj;
if (!this.objects.length) { if (!this.objects.length) {
return '[]'; return '[]';
} }
@ -877,6 +880,7 @@
return code; return code;
} }
code = (function() { code = (function() {
var _i, _len, _ref, _results;
_ref = this.objects; _ref = this.objects;
_results = []; _results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) { for (_i = 0, _len = _ref.length; _i < _len; _i++) {
@ -1218,12 +1222,9 @@
return !!this.ctor; return !!this.ctor;
}; };
Code.prototype.compileNode = function(o) { Code.prototype.compileNode = function(o) {
var code, exprs, i, idt, lit, p, param, ref, sharedScope, splats, v, val, vars, wasEmpty, _i, _j, _k, _len, _len2, _len3, _len4, _ref, _ref2, _ref3, _ref4, _results; var code, exprs, i, idt, lit, p, param, ref, splats, v, val, vars, wasEmpty, _i, _j, _len, _len2, _len3, _ref, _ref2, _ref3;
sharedScope = del(o, 'sharedScope'); o.scope = new Scope(o.scope, this.body, this);
o.scope = sharedScope || new Scope(o.scope, this.body, this); o.scope.shared = del(o, 'sharedScope');
if (sharedScope) {
o.scope.shared = true;
}
o.indent += TAB; o.indent += TAB;
delete o.bare; delete o.bare;
delete o.globals; delete o.globals;
@ -1234,10 +1235,11 @@
param = _ref[_i]; param = _ref[_i];
if (param.splat) { if (param.splat) {
splats = new Assign(new Value(new Arr(function() { splats = new Assign(new Value(new Arr(function() {
_ref2 = this.params; var _i, _len, _ref, _results;
_ref = this.params;
_results = []; _results = [];
for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) { for (_i = 0, _len = _ref.length; _i < _len; _i++) {
p = _ref2[_j]; p = _ref[_i];
_results.push(p.asReference(o)); _results.push(p.asReference(o));
} }
return _results; return _results;
@ -1245,9 +1247,9 @@
break; break;
} }
} }
_ref3 = this.params; _ref2 = this.params;
for (_k = 0, _len3 = _ref3.length; _k < _len3; _k++) { for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) {
param = _ref3[_k]; param = _ref2[_j];
if (param.isComplex()) { if (param.isComplex()) {
val = ref = param.asReference(o); val = ref = param.asReference(o);
if (param.value) { if (param.value) {
@ -1273,10 +1275,10 @@
exprs.unshift(splats); exprs.unshift(splats);
} }
if (exprs.length) { if (exprs.length) {
(_ref4 = this.body.expressions).unshift.apply(_ref4, exprs); (_ref3 = this.body.expressions).unshift.apply(_ref3, exprs);
} }
if (!splats) { if (!splats) {
for (i = 0, _len4 = vars.length; i < _len4; i++) { for (i = 0, _len3 = vars.length; i < _len3; i++) {
v = vars[i]; v = vars[i];
o.scope.parameter(vars[i] = v.compile(o)); o.scope.parameter(vars[i] = v.compile(o));
} }
@ -1367,7 +1369,7 @@
} }
}; };
Splat.compileSplattedArray = function(o, list, apply) { Splat.compileSplattedArray = function(o, list, apply) {
var args, base, code, i, index, node, _i, _len, _len2, _ref, _results; var args, base, code, i, index, node, _len;
index = -1; index = -1;
while ((node = list[++index]) && !(node instanceof Splat)) { while ((node = list[++index]) && !(node instanceof Splat)) {
continue; continue;
@ -1392,9 +1394,10 @@
return args[0] + (".concat(" + (args.slice(1).join(', ')) + ")"); return args[0] + (".concat(" + (args.slice(1).join(', ')) + ")");
} }
base = (function() { base = (function() {
var _i, _len, _ref, _results;
_ref = list.slice(0, index); _ref = list.slice(0, index);
_results = []; _results = [];
for (_i = 0, _len2 = _ref.length; _i < _len2; _i++) { for (_i = 0, _len = _ref.length; _i < _len; _i++) {
node = _ref[_i]; node = _ref[_i];
_results.push(node.compile(o, LEVEL_LIST)); _results.push(node.compile(o, LEVEL_LIST));
} }
@ -1611,14 +1614,15 @@
} }
}; };
In.prototype.compileOrTest = function(o) { In.prototype.compileOrTest = function(o) {
var cmp, cnj, i, item, ref, sub, tests, _len, _ref, _ref2, _ref3, _results; var cmp, cnj, i, item, ref, sub, tests, _ref, _ref2;
_ref = this.object.cache(o, LEVEL_OP), sub = _ref[0], ref = _ref[1]; _ref = this.object.cache(o, LEVEL_OP), sub = _ref[0], ref = _ref[1];
_ref2 = this.negated ? [' !== ', ' && '] : [' === ', ' || '], cmp = _ref2[0], cnj = _ref2[1]; _ref2 = this.negated ? [' !== ', ' && '] : [' === ', ' || '], cmp = _ref2[0], cnj = _ref2[1];
tests = function() { tests = function() {
_ref3 = this.array.base.objects; var _len, _ref, _results;
_ref = this.array.base.objects;
_results = []; _results = [];
for (i = 0, _len = _ref3.length; i < _len; i++) { for (i = 0, _len = _ref.length; i < _len; i++) {
item = _ref3[i]; item = _ref[i];
_results.push((i ? ref : sub) + cmp + item.compile(o, LEVEL_OP)); _results.push((i ? ref : sub) + cmp + item.compile(o, LEVEL_OP));
} }
return _results; return _results;
@ -1882,7 +1886,7 @@
args.unshift(new Literal('this')); args.unshift(new Literal('this'));
} }
body.expressions[idx] = new Call(base, args); body.expressions[idx] = new Call(base, args);
o.sharedScope = o.scope; o.sharedScope = true;
defs += this.tab + new Assign(ref, fn).compile(o, LEVEL_TOP) + ';\n'; defs += this.tab + new Assign(ref, fn).compile(o, LEVEL_TOP) + ';\n';
} }
return defs; return defs;

View file

@ -18,8 +18,11 @@
Scope.root = this; Scope.root = this;
} }
} }
Scope.prototype.add = function(name, type) { Scope.prototype.add = function(name, type, immediate) {
var pos; var pos;
if (this.shared && !immediate) {
return this.parent.add(name, type, immediate);
}
if (typeof (pos = this.positions[name]) === 'number') { if (typeof (pos = this.positions[name]) === 'number') {
return this.variables[pos].type = type; return this.variables[pos].type = type;
} else { } else {
@ -37,7 +40,7 @@
return false; return false;
}; };
Scope.prototype.parameter = function(name) { Scope.prototype.parameter = function(name) {
if (this.shared && this.check(name, true)) { if (this.shared && this.parent.check(name, true)) {
return; return;
} }
return this.add(name, 'param'); return this.add(name, 'param');
@ -74,7 +77,7 @@
while (this.check((temp = this.temporary(type, index)), true)) { while (this.check((temp = this.temporary(type, index)), true)) {
index++; index++;
} }
this.add(temp, 'var'); this.add(temp, 'var', true);
return temp; return temp;
}; };
Scope.prototype.assign = function(name, value) { Scope.prototype.assign = function(name, value) {

View file

@ -50,7 +50,7 @@ exports.Base = class Base
compileClosure: (o) -> compileClosure: (o) ->
if @containsPureStatement() if @containsPureStatement()
throw SyntaxError 'cannot include a pure statement in an expression.' throw SyntaxError 'cannot include a pure statement in an expression.'
o.sharedScope = o.scope o.sharedScope = yes
Closure.wrap(this).compileNode o Closure.wrap(this).compileNode o
# If the code generation wishes to use the result of a complex expression # If the code generation wishes to use the result of a complex expression
@ -988,9 +988,8 @@ exports.Code = class Code extends Base
# arrow, generates a wrapper that saves the current value of `this` through # arrow, generates a wrapper that saves the current value of `this` through
# a closure. # a closure.
compileNode: (o) -> compileNode: (o) ->
sharedScope = del o, 'sharedScope' o.scope = new Scope o.scope, @body, this
o.scope = sharedScope or new Scope o.scope, @body, this o.scope.shared = del o, 'sharedScope'
o.scope.shared = yes if sharedScope
o.indent += TAB o.indent += TAB
delete o.bare delete o.bare
delete o.globals delete o.globals
@ -1495,7 +1494,7 @@ exports.For = class For extends Base
[val.base, base] = [base, val] [val.base, base] = [base, val]
args.unshift new Literal 'this' args.unshift new Literal 'this'
body.expressions[idx] = new Call base, args body.expressions[idx] = new Call base, args
o.sharedScope = o.scope o.sharedScope = yes
defs += @tab + new Assign(ref, fn).compile(o, LEVEL_TOP) + ';\n' defs += @tab + new Assign(ref, fn).compile(o, LEVEL_TOP) + ';\n'
defs defs

View file

@ -23,7 +23,8 @@ exports.Scope = class Scope
Scope.root = this unless @parent Scope.root = this unless @parent
# Adds a new variable or overrides an existing one. # Adds a new variable or overrides an existing one.
add: (name, type) -> add: (name, type, immediate) ->
return @parent.add name, type, immediate if @shared and not immediate
if typeof (pos = @positions[name]) is 'number' if typeof (pos = @positions[name]) is 'number'
@variables[pos].type = type @variables[pos].type = type
else else
@ -39,7 +40,7 @@ exports.Scope = class Scope
# Reserve a variable name as originating from a function parameter for this # Reserve a variable name as originating from a function parameter for this
# scope. No `var` required for internal references. # scope. No `var` required for internal references.
parameter: (name) -> parameter: (name) ->
return if @shared and @check name, yes return if @shared and @parent.check name, yes
@add name, 'param' @add name, 'param'
# Just check to see if a variable has already been declared, without reserving, # Just check to see if a variable has already been declared, without reserving,
@ -66,7 +67,7 @@ exports.Scope = class Scope
freeVariable: (type) -> freeVariable: (type) ->
index = 0 index = 0
index++ while @check((temp = @temporary type, index), true) index++ while @check((temp = @temporary type, index), true)
@add temp, 'var' @add temp, 'var', yes
temp temp
# Ensure that an assignment is made at the top of this scope # Ensure that an assignment is made at the top of this scope

View file

@ -1,7 +1,7 @@
# Importing # Importing
# --------- # ---------
unless window? or testingBrowser unless window? or testingBrowser?
test "coffeescript modules can be imported and executed", -> test "coffeescript modules can be imported and executed", ->
magicKey = __filename magicKey = __filename

View file

@ -236,7 +236,7 @@ list = ['one', 'two']
(-> (->
for entity in list for entity in list
facets[entity] = -> entity facets[entity] = -> entity
)() )()
eq typeof entity, 'undefined' eq typeof entity, 'undefined'