diff options
author | Mihai Bazon <mihai@bazon.net> | 2012-08-21 12:55:56 +0300 |
---|---|---|
committer | Mihai Bazon <mihai@bazon.net> | 2012-08-21 13:53:16 +0300 |
commit | 7ae1c600a24e2f43feb839c5fd1625f6261751b5 (patch) | |
tree | abe06f041accc5dc0a4d277ae29612f2ee5af080 /lib/scope.js | |
parent | 92bd53b513c6cf030d96ed627efc50dd1875ba85 (diff) | |
download | tracifyjs-7ae1c600a24e2f43feb839c5fd1625f6261751b5.tar.gz tracifyjs-7ae1c600a24e2f43feb839c5fd1625f6261751b5.zip |
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.)
Diffstat (limited to 'lib/scope.js')
-rw-r--r-- | lib/scope.js | 53 |
1 files changed, 49 insertions, 4 deletions
diff --git a/lib/scope.js b/lib/scope.js index a5719bf3..0ac797e0 100644 --- a/lib/scope.js +++ b/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); }); |