figure out label targets
authorMihai Bazon <mihai@bazon.net>
Sat, 15 Sep 2012 13:05:01 +0000 (16:05 +0300)
committerMihai Bazon <mihai@bazon.net>
Sat, 15 Sep 2012 13:05:17 +0000 (16:05 +0300)
lib/ast.js
lib/scope.js

index 1a79286..55e9503 100644 (file)
@@ -287,7 +287,7 @@ var AST_Throw = DEFNODE("Throw", null, {
     $documentation: "A `throw` statement"
 }, AST_Exit);
 
-var AST_LoopControl = DEFNODE("LoopControl", "label", {
+var AST_LoopControl = DEFNODE("LoopControl", "label loopcontrol_target", {
     $documentation: "Base class for loop control statements (`break` and `continue`)",
     _walk: function(visitor) {
         return visitor._visit(this, this.label && function(){
@@ -614,7 +614,7 @@ var AST_SymbolCatch = DEFNODE("SymbolCatch", null, {
     $documentation: "Symbol naming the exception in catch",
 }, AST_SymbolDeclaration);
 
-var AST_Label = DEFNODE("Label", null, {
+var AST_Label = DEFNODE("Label", "label_target", {
     $documentation: "Symbol naming a label (declaration)",
 }, AST_SymbolDeclaration);
 
index ef0ac6e..79d6e91 100644 (file)
@@ -101,8 +101,28 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(){
         }
         if (node instanceof AST_Label) {
             node.init_scope_vars();
+            var p = tw.parent(); // AST_LabeledStatement
+            var block = p.body;
+            if (block instanceof AST_StatementWithBody)
+                block = block.body;
+            node.label_target = block;
         }
-        if (node instanceof AST_SymbolLambda) {
+        if (node instanceof AST_LoopControl) {
+            if (!node.label) {
+                var a = tw.stack, i = a.length - 1;
+                while (--i >= 0) {
+                    var p = a[i];
+                    if (p instanceof AST_For
+                        || p instanceof AST_ForIn
+                        || p instanceof AST_DWLoop
+                        || p instanceof AST_Switch) {
+                        node.loopcontrol_target = p.body;
+                        break;
+                    }
+                }
+            }
+        }
+        else if (node instanceof AST_SymbolLambda) {
             scope.def_function(node);
         }
         else if (node instanceof AST_SymbolDefun) {
@@ -272,6 +292,11 @@ AST_Symbol.DEFMETHOD("global", function(){
     return this.definition().global;
 });
 
+AST_LoopControl.DEFMETHOD("target", function(){
+    if (this.label) return this.label.definition().label_target;
+    return this.loopcontrol_target;
+});
+
 AST_Toplevel.DEFMETHOD("mangle_names", function(){
     // We only need to mangle declaration nodes.  Special logic wired
     // into the code generator will display the mangled name if it's