simplifying the lookup of the top-level scope object

This commit is contained in:
Jeremy Ashkenas 2010-03-30 19:21:14 -04:00
parent 1e1146d61d
commit f3a60edc5d
3 changed files with 26 additions and 24 deletions

View File

@ -20,21 +20,20 @@
this.expressions = _a[1];
this.method = _a[2];
this.variables = {};
this.temp_var = this.parent ? this.parent.temp_var : '_a';
if (this.parent) {
this.temp_var = this.parent.temp_var;
} else {
Scope.root = this;
this.temp_var = '_a';
}
return this;
};
// The top-level **Scope** object.
Scope.root = null;
// Initialize a scope with its parent, for lookups up the chain,
// as well as a reference to the **Expressions** node is belongs to, which is
// where it should declare its variables, and a reference to the function that
// it wraps.
// Find the top-most scope object, used for defined global variables
Scope.prototype.topmost = function topmost() {
if (this.parent) {
return this.parent.topmost();
} else {
return this;
}
};
// Look up a variable name in lexical scope, and declare it if it does not
// already exist.
Scope.prototype.find = function find(name) {
@ -84,7 +83,7 @@
// (or at the top-level scope, if requested).
Scope.prototype.assign = function assign(name, value, top_level) {
if (top_level) {
return this.topmost().assign(name, value);
return Scope.root.assign(name, value);
}
this.variables[name] = {
value: value,
@ -97,7 +96,7 @@
Scope.prototype.utility = function utility(name) {
var _a, _b, _c, _d, dep;
if (this.parent) {
return this.topmost().utility(name);
return Scope.root.utility(name);
}
if ((typeof (_d = utilities.functions[name]) !== "undefined" && _d !== null)) {
this.utilities = this.utilities || {};

View File

@ -11,6 +11,9 @@ utilities: if process? then require('./utilities').utilities else this.utilities
exports.Scope: class Scope
# The top-level **Scope** object.
@root: null
# Initialize a scope with its parent, for lookups up the chain,
# as well as a reference to the **Expressions** node is belongs to, which is
# where it should declare its variables, and a reference to the function that
@ -18,11 +21,11 @@ exports.Scope: class Scope
constructor: (parent, expressions, method) ->
[@parent, @expressions, @method]: [parent, expressions, method]
@variables: {}
@temp_var: if @parent then @parent.temp_var else '_a'
# Find the top-most scope object, used for defined global variables
topmost: ->
if @parent then @parent.topmost() else @
if @parent
@temp_var: @parent.temp_var
else
Scope.root: this
@temp_var: '_a'
# Look up a variable name in lexical scope, and declare it if it does not
# already exist.
@ -59,13 +62,13 @@ exports.Scope: class Scope
# Ensure that an assignment is made at the top of this scope
# (or at the top-level scope, if requested).
assign: (name, value, top_level) ->
return @topmost().assign(name, value) if top_level
return Scope.root.assign(name, value) if top_level
@variables[name]: {value: value, assigned: true}
# Ensure the CoffeeScript utility object is included in the top level
# then return a CallNode curried constructor bound to the utility function
utility: (name) ->
return @topmost().utility(name) if @parent
return Scope.root.utility(name) if @parent
if utilities.functions[name]?
@utilities: or {}
@utilities[name]: utilities.functions[name]

View File

@ -8,7 +8,7 @@ exports.utilities: {
functions: {
extend: """
extend: """
function(child, parent) {
var ctor = function(){ };
ctor.prototype = parent.prototype;
@ -16,24 +16,24 @@ exports.utilities: {
child.prototype = new ctor();
child.prototype.constructor = child;
}
"""
"""
bind: """
bind: """
function(func, obj, args) {
return function() {
return func.apply(obj || {}, args ? args.concat(__slice.call(arguments, 0)) : arguments);
};
}
"""
"""
range: """
range: """
function(array, from, to, exclusive) {
return [
(from < 0 ? from + array.length : from || 0),
(to < 0 ? to + array.length : to || array.length) + (exclusive ? 0 : 1)
];
}
"""
"""
hasProp: 'Object.prototype.hasOwnProperty'