Report abuse

diff --git a/kernel/compiler/bytecode.rb b/kernel/compiler/bytecode.rb
index 6f321d3..95a02a9 100644
--- a/kernel/compiler/bytecode.rb
+++ b/kernel/compiler/bytecode.rb
@@ -1420,22 +1420,39 @@ class Compiler

     class Loop
       def bytecode(g)
-        g.push_modifiers
+        pos(g)

-        g.break = g.new_label
-        g.next = g.redo = top = g.new_label
-        top.set!
+        desc = MethodDescription.new @compiler.generator_class, @locals
+        desc.name = :__block__
+        desc.for_block = true
+        sub = desc.generator

-        if @body then
-          @body.bytecode(g)
-          g.pop
-        end
+        # Push line info down.
+        sub.set_line g.line, g.file

-        g.check_interrupts
-        g.goto top
+        show_errors(sub) do
+          sub.push_modifiers
+          sub.break = sub.new_label
+          top = sub.next = sub.redo = sub.new_label
+          top.set!

-        g.break.set!
-        g.pop_modifiers
+          if @body then
+            @body.bytecode(sub)
+            sub.pop
+          end
+
+          sub.check_interrupts
+          sub.goto top
+
+          sub.break.set!
+          sub.pop_modifiers
+
+          sub.ret
+          sub.close
+        end
+
+        g.create_block desc
+        g.send :call, 0
       end
     end

diff --git a/kernel/compiler/local.rb b/kernel/compiler/local.rb
index 5fb6394..87d29d0 100644
--- a/kernel/compiler/local.rb
+++ b/kernel/compiler/local.rb
@@ -11,6 +11,7 @@ class Compiler
       @names = []
       @locals = Hash.new { |h,k| h[k] = Local.new(@scope, k) }
       @from_eval = false
+      @skip = false
     end

     attr_accessor :from_eval
@@ -45,6 +46,14 @@ class Compiler
       @names.size
     end

+    def skip?
+      @skip
+    end
+
+    def skip!
+      @skip = true
+    end
+
     def encoded_order
        # figure out the size
        size = 0
diff --git a/kernel/compiler/nodes.rb b/kernel/compiler/nodes.rb
index 05a72bc..cecbef9 100644
--- a/kernel/compiler/nodes.rb
+++ b/kernel/compiler/nodes.rb
@@ -593,6 +593,10 @@ raise "no"
         end
       end

+      def skip!
+        @block_scope.last.skip!
+      end
+
       def depth
         @block_scope.size
       end
@@ -634,7 +638,7 @@ raise "no"
         dep = 0

         @block_scope.reverse_each do |scope|
-          if scope.key?(name)
+          if !scope.skip? && scope.key?(name)
             if scope.from_eval
               depth = dep + 1
             else
@@ -655,14 +659,20 @@ raise "no"
             return nil
           else
             # This not found. create it.
-            in_scope = @block_scope.last
+            depth = 0
+            in_scope = @top_scope
+            @block_scope.reverse_each do |scope|
+              if !scope.skip?
+                in_scope = scope
+                break
+              end
+              depth += 1
+            end
             idx = in_scope.size
             lcl = in_scope[name]
             lcl.created_in_block!(idx)
             if in_scope.from_eval
-              depth = 1
-            else
-              depth = 0
+              depth += 1
             end
           end
         end
@@ -1170,6 +1180,8 @@ raise "no"

         set(:iter) do
           @locals = get(:scope).new_block_scope do
+            get(:scope).skip!
+
             set(:iter_args) do
              sexp[1] = convert(s(:iter_args, sexp[1])) # local var assignment
             end
@@ -1307,9 +1319,13 @@ raise "no"
         end

         if c.is? Call and c.method == :loop
-          sexp[1] = convert(sexp[1])
-          set(:pop_unwind, false) do
-            sexp[2] = convert(sexp[2])
+          set(:iter) do
+            @locals = get(:scope).new_block_scope do
+              sexp[1] = convert(sexp[1])
+              set(:pop_unwind, false) do
+                sexp[2] = convert(sexp[2])
+              end
+            end
           end
           return sexp
         end
@@ -1334,7 +1350,7 @@ raise "no"

         if c.is? Call and c.method == :loop
           n = Loop.new(@compiler)
-          n.args(b)
+          n.args(b, @locals)
           return n
         end

@@ -1575,7 +1591,8 @@ raise "no"
     end

     class Loop < Node
-      def args(body)
+      def args(body, locals)
+        @locals = locals
         @body = body
       end
     end
diff --git a/spec/tags/frozen/language/for_tags.txt b/spec/tags/frozen/language/for_tags.txt
index 060b4f9..c033480 100644
--- a/spec/tags/frozen/language/for_tags.txt
+++ b/spec/tags/frozen/language/for_tags.txt
@@ -1,3 +1 @@
-fails:The for expression executes code in containing variable scope
-fails:The for expression executes code in containing variable scope with 'do'
 fails:The for expression repeats the loop from the beginning with 'retry'
diff --git a/spec/tags/frozen/language/loop_tags.txt b/spec/tags/frozen/language/loop_tags.txt
deleted file mode 100644
index 4131550..0000000
--- a/spec/tags/frozen/language/loop_tags.txt
+++ /dev/null
@@ -1 +0,0 @@
-fails:The loop expression executes code in its own scope