some reorganization
(moved pretty much everything that relates to scope in scope.js, added a module for NodeJS that can be used with require() and exports everything.)
This commit is contained in:
53
lib/scope.js
53
lib/scope.js
@@ -11,6 +11,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(){
|
||||
var labels = {};
|
||||
var tw = new TreeWalker(function(node, descend){
|
||||
if (node instanceof AST_Scope) {
|
||||
node.init_scope_vars();
|
||||
var save_scope = node.parent_scope = scope;
|
||||
scope = node;
|
||||
descend();
|
||||
@@ -31,6 +32,9 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(){
|
||||
delete labels[l.name];
|
||||
return true; // no descend again
|
||||
}
|
||||
if (node instanceof AST_SymbolDeclaration) {
|
||||
node.init_scope_vars();
|
||||
}
|
||||
if (node instanceof AST_SymbolLambda) {
|
||||
scope.def_function(node);
|
||||
}
|
||||
@@ -65,15 +69,27 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(){
|
||||
});
|
||||
this.walk(tw);
|
||||
|
||||
// pass 2: find back references and eval/with
|
||||
var tw = new TreeWalker(function(node){
|
||||
// pass 2: find back references and eval
|
||||
var func = null;
|
||||
var tw = new TreeWalker(function(node, descend){
|
||||
if (node instanceof AST_Lambda) {
|
||||
var prev_func = func;
|
||||
func = node;
|
||||
descend();
|
||||
func = prev_func;
|
||||
return true;
|
||||
}
|
||||
if (node instanceof AST_SymbolRef) {
|
||||
var sym = node.scope.find_variable(node);
|
||||
node.reference(sym);
|
||||
if (!sym) {
|
||||
if (node.name == "eval") {
|
||||
for (var s = node.scope; s; s = s.parent_scope)
|
||||
s.uses_eval = true;
|
||||
for (var s = node.scope;
|
||||
s && !s.uses_eval;
|
||||
s = s.parent_scope) s.uses_eval = true;
|
||||
}
|
||||
if (node.name == "arguments") {
|
||||
func.uses_arguments = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -81,11 +97,31 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(){
|
||||
this.walk(tw);
|
||||
});
|
||||
|
||||
AST_Scope.DEFMETHOD("init_scope_vars", function(){
|
||||
this.variables = {}; // map name to AST_SymbolVar (variables defined in this scope; includes functions)
|
||||
this.functions = {}; // map name to AST_SymbolDefun (functions defined in this scope)
|
||||
this.uses_with = false; // will be set to true if this or some nested scope uses the `with` statement
|
||||
this.uses_eval = false; // will be set to true if this or nested scope uses the global `eval`
|
||||
this.parent_scope = null; // the parent scope
|
||||
this.enclosed = []; // a list of variables from this or outer scope(s) that are referenced from this or inner scopes
|
||||
this.cname = -1; // the current index for mangling functions/variables
|
||||
});
|
||||
|
||||
AST_Lambda.DEFMETHOD("init_scope_vars", function(){
|
||||
AST_Scope.prototype.init_scope_vars.call(this);
|
||||
this.uses_arguments = false;
|
||||
});
|
||||
|
||||
AST_SymbolDeclaration.DEFMETHOD("init_scope_vars", function(){
|
||||
this.references = [];
|
||||
});
|
||||
|
||||
AST_Toplevel.DEFMETHOD("scope_warnings", function(options){
|
||||
options = defaults(options, {
|
||||
undeclared : false, // this makes a lot of noise
|
||||
unreferenced : true,
|
||||
assign_to_global : true,
|
||||
func_arguments : true,
|
||||
eval : true
|
||||
});
|
||||
var tw = new TreeWalker(function(node){
|
||||
@@ -132,6 +168,15 @@ AST_Toplevel.DEFMETHOD("scope_warnings", function(options){
|
||||
col: node.start.col
|
||||
});
|
||||
}
|
||||
if (options.func_arguments
|
||||
&& node instanceof AST_Lambda
|
||||
&& node.uses_arguments) {
|
||||
AST_Node.warn("arguments used in function {name} [{line},{col}]", {
|
||||
name: node.name ? node.name.name : "anonymous",
|
||||
line: node.start.line,
|
||||
col: node.start.col
|
||||
});
|
||||
}
|
||||
});
|
||||
this.walk(tw);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user