aboutsummaryrefslogtreecommitdiff
path: root/lib/scope.js
diff options
context:
space:
mode:
authorMihai Bazon <mihai@bazon.net>2012-08-21 12:55:56 +0300
committerMihai Bazon <mihai@bazon.net>2012-08-21 13:53:16 +0300
commit7ae1c600a24e2f43feb839c5fd1625f6261751b5 (patch)
treeabe06f041accc5dc0a4d277ae29612f2ee5af080 /lib/scope.js
parent92bd53b513c6cf030d96ed627efc50dd1875ba85 (diff)
downloadtracifyjs-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.js53
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);
});