},
}, AST_Statement);
-var AST_BlockScope = DEFNODE("BlockScope", "enclosed functions make_def parent_scope variables", {
+var AST_BlockScope = DEFNODE("BlockScope", "cname enclosed functions make_def parent_scope variables", {
$documentation: "Base class for all statements introducing a lexical scope",
$propdoc: {
+ cname: "[integer/S] current index for mangling variables (used internally by the mangler)",
enclosed: "[SymbolDef*/S] a list of all symbol definitions that are accessed from this scope or any subscopes",
functions: "[Object/S] like `variables`, but only lists function declarations",
parent_scope: "[AST_Scope?/S] link to the parent scope",
/* -----[ scope and functions ]----- */
-var AST_Scope = DEFNODE("Scope", "cname uses_eval uses_with", {
+var AST_Scope = DEFNODE("Scope", "uses_eval uses_with", {
$documentation: "Base class for all statements introducing a lexical scope",
$propdoc: {
- cname: "[integer/S] current index for mangling variables (used internally by the mangler)",
uses_eval: "[boolean/S] tells whether this scope contains a direct call to the global `eval`",
uses_with: "[boolean/S] tells whether this scope uses the `with` statement",
},
if (self.args.length == 0) return make_node(AST_Function, self, {
argnames: [],
body: []
- }).init_scope_vars(exp.scope);
+ }).init_vars(exp.scope);
if (all(self.args, function(x) {
return x instanceof AST_String;
})) {
self.expression = make_node(AST_Function, self.expression, {
argnames: [],
body: []
- }).init_scope_vars(exp.scope);
+ }).init_vars(exp.scope);
break;
case "Number":
self.expression = make_node(AST_Number, self.expression, {
return true;
}
if (node instanceof AST_With) {
- for (var s = scope; s; s = s.parent_scope) s.uses_with = true;
+ var s = scope;
+ do {
+ s = s.resolve();
+ if (s.uses_with) break;
+ s.uses_with = true;
+ } while (s = s.parent_scope);
return;
}
if (node instanceof AST_Symbol) {
}
function walk_scope(descend) {
- node.init_scope_vars(scope);
+ node.init_vars(scope);
var save_defun = defun;
var save_scope = scope;
if (node instanceof AST_Scope) defun = node;
if (name == "eval") {
var parent = tw.parent();
if (parent.TYPE == "Call" && parent.expression === node) {
- for (var s = node.scope; s && !s.uses_eval; s = s.parent_scope) {
+ var s = node.scope;
+ do {
+ s = s.resolve();
+ if (s.uses_eval) break;
s.uses_eval = true;
- }
+ } while (s = s.parent_scope);
} else if (sym.undeclared) {
self.uses_eval = true;
}
}
});
-function init_scope_vars(scope, parent) {
+function init_block_vars(scope, parent) {
scope.cname = -1; // the current index for mangling functions/variables
scope.enclosed = []; // variables from this or outer scope(s) that are referenced from this or inner scopes
- scope.uses_eval = false; // will be set to true if this or nested scope uses the global `eval`
- scope.uses_with = false; // will be set to true if this or some nested scope uses the `with` statement
scope.parent_scope = parent; // the parent scope (null if this is the top level)
scope.functions = new Dictionary(); // map name to AST_SymbolDefun (functions defined in this scope)
scope.variables = new Dictionary(); // map name to AST_SymbolVar (variables defined in this scope; includes functions)
if (parent) scope.make_def = parent.make_def; // top-level tracking of SymbolDef instances
}
-AST_BlockScope.DEFMETHOD("init_scope_vars", function(parent_scope) {
+function init_scope_vars(scope, parent) {
+ init_block_vars(scope, parent);
+ scope.uses_eval = false; // will be set to true if this or nested scope uses the global `eval`
+ scope.uses_with = false; // will be set to true if this or some nested scope uses the `with` statement
+}
+
+AST_BlockScope.DEFMETHOD("init_vars", function(parent_scope) {
+ init_block_vars(this, parent_scope);
+});
+AST_Scope.DEFMETHOD("init_vars", function(parent_scope) {
init_scope_vars(this, parent_scope);
});
-
-AST_Lambda.DEFMETHOD("init_scope_vars", function(parent_scope) {
+AST_Lambda.DEFMETHOD("init_vars", function(parent_scope) {
init_scope_vars(this, parent_scope);
this.uses_arguments = false;
this.def_variable(new AST_SymbolFunarg({