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

refactoring Scope.

This commit is contained in:
Jeremy Ashkenas 2010-12-06 23:32:32 -05:00
parent 3eac6aeb99
commit 2fb269a938
4 changed files with 30 additions and 71 deletions

View file

@ -281,11 +281,13 @@
}
post = this.compileNode(o);
scope = o.scope;
if (!o.globals && o.scope.hasDeclarations(this)) {
code += "" + this.tab + "var " + (scope.compiledDeclarations()) + ";\n";
}
if (scope.hasAssignments(this)) {
code += "" + this.tab + "var " + (multident(scope.compiledAssignments(), this.tab)) + ";\n";
if (scope.expressions === this) {
if (!o.globals && o.scope.hasDeclarations) {
code += "" + this.tab + "var " + (scope.declaredVariables().join(', ')) + ";\n";
}
if (scope.hasAssignments) {
code += "" + this.tab + "var " + (multident(scope.assignedVariables().join(', '), this.tab)) + ";\n";
}
}
return code + post;
};

View file

@ -34,17 +34,7 @@
return true;
}
this.add(name, 'var');
return false;
};
Scope.prototype.any = function(fn) {
var v, _i, _len, _ref;
_ref = this.variables;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
v = _ref[_i];
if (fn(v)) {
return true;
}
}
this.hasDeclarations = true;
return false;
};
Scope.prototype.parameter = function(name) {
@ -86,36 +76,28 @@
index++;
}
this.add(temp, 'var');
this.hasDeclarations = true;
return temp;
};
Scope.prototype.assign = function(name, value) {
return this.add(name, {
this.add(name, {
value: value,
assigned: true
});
};
Scope.prototype.hasDeclarations = function(body) {
return body === this.expressions && this.any(function(v) {
return v.type === 'var';
});
};
Scope.prototype.hasAssignments = function(body) {
return body === this.expressions && this.any(function(v) {
return v.type.assigned;
});
return this.hasAssignments = true;
};
Scope.prototype.declaredVariables = function() {
var tmp, usr, v, _i, _len, _ref;
usr = [];
tmp = [];
var realVars, tempVars, v, _i, _len, _ref;
realVars = [];
tempVars = [];
_ref = this.variables;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
v = _ref[_i];
if (v.type === 'var') {
(v.name.charAt(0) === '_' ? tmp : usr).push(v.name);
(v.name.charAt(0) === '_' ? tempVars : realVars).push(v.name);
}
}
return usr.sort().concat(tmp.sort());
return realVars.sort().concat(tempVars.sort());
};
Scope.prototype.assignedVariables = function() {
var v, _i, _len, _ref, _results;
@ -129,12 +111,6 @@
}
return _results;
};
Scope.prototype.compiledDeclarations = function() {
return this.declaredVariables().join(', ');
};
Scope.prototype.compiledAssignments = function() {
return this.assignedVariables().join(', ');
};
return Scope;
}();
}).call(this);

View file

@ -244,10 +244,11 @@ exports.Expressions = class Expressions extends Base
@expressions = rest
post = @compileNode o
{scope} = o
if not o.globals and o.scope.hasDeclarations this
code += "#{@tab}var #{ scope.compiledDeclarations() };\n"
if scope.hasAssignments this
code += "#{@tab}var #{ multident scope.compiledAssignments(), @tab };\n"
if scope.expressions is this
if not o.globals and o.scope.hasDeclarations
code += "#{@tab}var #{ scope.declaredVariables().join(', ') };\n"
if scope.hasAssignments
code += "#{@tab}var #{ multident scope.assignedVariables().join(', '), @tab };\n"
code + post
# Wrap up the given nodes as an **Expressions**, unless it already happens

View file

@ -32,13 +32,9 @@ exports.Scope = class Scope
# Look up a variable name in lexical scope, and declare it if it does not
# already exist.
find: (name, options) ->
return true if @check name, options
return yes if @check name, options
@add name, 'var'
false
# Test variables and return `true` the first time `fn(v)` returns `true`
any: (fn) ->
return yes for v in @variables when fn v
@hasDeclarations = yes
no
# Reserve a variable name as originating from a function parameter for this
@ -72,40 +68,24 @@ exports.Scope = class Scope
index = 0
index++ while @check((temp = @temporary type, index), true)
@add temp, 'var'
@hasDeclarations = yes
temp
# Ensure that an assignment is made at the top of this scope
# (or at the top-level scope, if requested).
assign: (name, value) ->
@add name, value: value, assigned: true
# Does this scope reference any variables that need to be declared in the
# given function body?
hasDeclarations: (body) ->
body is @expressions and @any (v) -> v.type is 'var'
# Does this scope reference any assignments that need to be declared at the
# top of the given function body?
hasAssignments: (body) ->
body is @expressions and @any (v) -> v.type.assigned
@hasAssignments = yes
# Return the list of variables first declared in this scope.
declaredVariables: ->
usr = []
tmp = []
realVars = []
tempVars = []
for v in @variables when v.type is 'var'
(if v.name.charAt(0) is '_' then tmp else usr).push v.name
usr.sort().concat tmp.sort()
(if v.name.charAt(0) is '_' then tempVars else realVars).push v.name
realVars.sort().concat tempVars.sort()
# Return the list of assignments that are supposed to be made at the top
# of this scope.
assignedVariables: ->
("#{v.name} = #{v.type.value}" for v in @variables when v.type.assigned)
# Compile the JavaScript for all of the variable declarations in this scope.
compiledDeclarations: ->
@declaredVariables().join ', '
# Compile the JavaScript for all of the variable assignments in this scope.
compiledAssignments: ->
@assignedVariables().join ', '
"#{v.name} = #{v.type.value}" for v in @variables when v.type.assigned