summaryrefslogtreecommitdiff
path: root/spec/ruby/language/fixtures/return.rb
blob: 0414c356e8737bd8dc5cb4ba58a5936f9807a556 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
module ReturnSpecs
  class Blocks
    def yielding_method
      yield
      ScratchPad.record :after_yield
    end

    def enclosing_method
      yielding_method do
        ScratchPad.record :before_return
        return :return_value
        ScratchPad.record :after_return
      end

      ScratchPad.record :after_call
    end
  end

  class NestedCalls < Blocks
    def invoking_method(&b)
      yielding_method(&b)
      ScratchPad.record :after_invoke
    end

    def enclosing_method
      invoking_method do
        ScratchPad.record :before_return
        return :return_value
        ScratchPad.record :after_return
      end
      ScratchPad.record :after_invoke
    end
  end

  class NestedBlocks < Blocks
    def enclosing_method
      yielding_method do
        yielding_method do
          ScratchPad.record :before_return
          return :return_value
          ScratchPad.record :after_return
        end
        ScratchPad.record :after_invoke1
      end
      ScratchPad.record :after_invoke2
    end
  end

  class SavedInnerBlock
    def add(&b)
      @block = b
    end

    def outer
      yield
      @block.call
    end

    def inner
      yield
    end

    def start
      outer do
        inner do
          add do
            ScratchPad.record :before_return
            return :return_value
          end
        end
      end

      ScratchPad.record :bottom_of_start

      return false
    end
  end

  class ThroughDefineMethod
    lamb = proc { |x| x.call }
    define_method :foo, lamb

    def mp(&b); b; end

    def outer
      pr = mp { return :good }

      foo(pr)
      return :bad
    end
  end

  class DefineMethod
    lamb = proc { return :good }
    define_method :foo, lamb

    def outer
      val = :bad

      # This is tricky, but works. If lamb properly returns, then the
      # return value will go into val before we run the ensure.
      #
      # If lamb's return keeps unwinding incorrectly, val will still
      # have it's old value.
      #
      # We can therefore use val to figure out what happened.
      begin
        val = foo()
      ensure
        if val != :good
          return :bad
        end
      end

      return val
    end
  end

  class MethodWithBlock
    def method1
      return [2, 3].inject 0 do |a, b|
        a + b
      end
      nil
    end

    def get_ary(count, &blk)
      count.times.to_a do |i|
        blk.call(i) if blk
      end
    end

    def method2
      return get_ary 3 do |i|
      end
      nil
    end
  end
end