aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMihai Bazon <mihai.bazon@gmail.com>2015-11-12 11:48:06 +0200
committerMihai Bazon <mihai.bazon@gmail.com>2015-11-12 11:48:06 +0200
commitc898a26117c2687d5707a4e80d6058d5c8601165 (patch)
tree17eaad010d2a8d6823e7894d50a307449469efe4
parent619adb0308dbc794e9c3b77185e886443e03df9e (diff)
downloadtracifyjs-c898a26117c2687d5707a4e80d6058d5c8601165.tar.gz
tracifyjs-c898a26117c2687d5707a4e80d6058d5c8601165.zip
Build label def/refs info when figuring out scope
Fix #862
-rw-r--r--lib/scope.js31
1 files changed, 31 insertions, 0 deletions
diff --git a/lib/scope.js b/lib/scope.js
index 4a3739c4..1f0986c4 100644
--- a/lib/scope.js
+++ b/lib/scope.js
@@ -92,6 +92,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
// pass 1: setup scope chaining and handle definitions
var self = this;
var scope = self.parent_scope = null;
+ var labels = new Dictionary();
var defun = null;
var nesting = 0;
var tw = new TreeWalker(function(node, descend){
@@ -108,12 +109,25 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
node.init_scope_vars(nesting);
var save_scope = node.parent_scope = scope;
var save_defun = defun;
+ var save_labels = labels;
defun = scope = node;
+ labels = new Dictionary();
++nesting; descend(); --nesting;
scope = save_scope;
defun = save_defun;
+ labels = save_labels;
return true; // don't descend again in TreeWalker
}
+ if (node instanceof AST_LabeledStatement) {
+ var l = node.label;
+ if (labels.has(l.name)) {
+ throw new Error(string_template("Label {name} defined twice", l));
+ }
+ labels.set(l.name, l);
+ descend();
+ labels.del(l.name);
+ return true; // no descend again
+ }
if (node instanceof AST_With) {
for (var s = scope; s; s = s.parent_scope)
s.uses_with = true;
@@ -122,6 +136,10 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
if (node instanceof AST_Symbol) {
node.scope = scope;
}
+ if (node instanceof AST_Label) {
+ node.thedef = node;
+ node.references = [];
+ }
if (node instanceof AST_SymbolLambda) {
defun.def_function(node);
}
@@ -143,6 +161,15 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
(options.screw_ie8 ? scope : defun)
.def_variable(node);
}
+ else if (node instanceof AST_LabelRef) {
+ var sym = labels.get(node.name);
+ if (!sym) throw new Error(string_template("Undefined label {name} [{line},{col}]", {
+ name: node.name,
+ line: node.start.line,
+ col: node.start.col
+ }));
+ node.thedef = sym;
+ }
});
self.walk(tw);
@@ -157,6 +184,10 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
func = prev_func;
return true;
}
+ if (node instanceof AST_LoopControl && node.label) {
+ node.label.thedef.references.push(node);
+ return true;
+ }
if (node instanceof AST_SymbolRef) {
var name = node.name;
var sym = node.scope.find_variable(name);