Temporary tag for this failure. Updated CI spec coming.
[rbx.git] / kernel / core / throw_catch.rb
blobc56c163cba33979a38ec576d9f9fdf3d785fe569
1 # depends on: class.rb
3 ##
4 # Emulates the interface of Exception, but isn't one.
6 class ThrownValue
7   def initialize(name, value, ctx)
8     @name = name
9     @value = value
10     @context = ctx
11   end
12   
13   attr_reader :name
14   attr_reader :value
15   
16   def message
17     "A thrown value from Kernel#throw"
18   end
19   
20   def backtrace
21     if @context.kind_of? MethodContext
22       @context = Backtrace.backtrace(@context)
23     end
24     
25     return @context
26   end
27   
28   def set_backtrace(obj)
29     @context = obj
30   end
31   
32   def exception(msg)
33     true
34   end
35   
36   def self.register(sym)
37     cur = Thread.current[:__catches__]
38     if cur.nil?
39       cur = []
40       Thread.current[:__catches__] = cur
41     end
42     
43     cur << sym
44     
45     begin
46       yield
47     ensure
48       cur.pop
49     end
50   end
51   
52   def self.available?(sym)
53     cur = Thread.current[:__catches__]
54     return false if cur.nil?
55     cur.include? sym
56   end
57 end
59 module Kernel
60   def catch(sym)
61     begin
62       ThrownValue.register(sym) do
63         yield
64       end
65     rescue ThrownValue => val
66       return val.value if val.name == sym
67       Rubinius.asm(val) do |v|
68         v.bytecode(self)
69         raise_exc
70       end
71     end
72   end
73   module_function :catch
75   def throw(sym, value = nil)
76     unless ThrownValue.available? sym
77       raise NameError.new("uncaught throw `#{sym}'", sym.to_sym)
78     end
79     
80     exc = ThrownValue.new(sym, value, MethodContext.current.sender)
81     Rubinius.asm(exc) do |v|
82       v.bytecode(self)
83       raise_exc
84     end
85   end
86   module_function :throw
87 end