class Opal::Rewriters::ThrowerFinder
ThrowerFinder
attempts to track the presence of throwers, like break, redo, so we can make an informed guess in the early compilation phase before traversing other nodes whether we want to track a closure. Tracking a closure is often a deoptimizing step, so we want to get that knowledge earlier.
Public Class Methods
new()
click to toggle source
# File lib/opal/rewriters/thrower_finder.rb, line 12 def initialize @break_stack = [] @redo_stack = [] @retry_stack = [] @rescue_else_stack = [] end
Public Instance Methods
on_break(node)
click to toggle source
Calls superclass method
# File lib/opal/rewriters/thrower_finder.rb, line 19 def on_break(node) tracking(:break, @break_stack) super end
on_defined(node)
click to toggle source
ignore throwers inside defined
Calls superclass method
# File lib/opal/rewriters/thrower_finder.rb, line 49 def on_defined(node) pushing( [@redo_stack, nil], [@break_stack, nil], [@retry_stack, nil] ) { super } end
on_ensure(node)
click to toggle source
In Opal
we handle rescue-else either in ensure or in rescue. If ensure is present, we handle it in ensure. Otherwise we handle it in rescue. ensure is always above a rescue. This logic is about tracking if a given ensure node should expect a rescue-else inside a rescue node.
Calls superclass method
# File lib/opal/rewriters/thrower_finder.rb, line 63 def on_ensure(node) pushing([@rescue_else_stack, node]) { super } end
on_for(node)
click to toggle source
Calls superclass method
# File lib/opal/rewriters/thrower_finder.rb, line 42 def on_for(node); on_loop(node) { super }; end
on_iter(node)
click to toggle source
Calls superclass method
# File lib/opal/rewriters/thrower_finder.rb, line 34 def on_iter(node) pushing([@break_stack, node]) { super } end
on_loop(node, &block)
click to toggle source
# File lib/opal/rewriters/thrower_finder.rb, line 38 def on_loop(node, &block) pushing([@redo_stack, node], [@break_stack, nil], &block) end
on_redo(node)
click to toggle source
Calls superclass method
# File lib/opal/rewriters/thrower_finder.rb, line 24 def on_redo(node) tracking(:redo, @redo_stack) super end
on_rescue(node)
click to toggle source
Calls superclass method
# File lib/opal/rewriters/thrower_finder.rb, line 67 def on_rescue(node) if node.children[1..-1].detect { |sexp| sexp && sexp.type != :resbody } tracking(:rescue_else, @rescue_else_stack) end pushing([@rescue_else_stack, nil], [@retry_stack, node]) { super } end
on_retry(node)
click to toggle source
Calls superclass method
# File lib/opal/rewriters/thrower_finder.rb, line 29 def on_retry(node) tracking(:retry, @retry_stack) super end
on_until(node)
click to toggle source
Calls superclass method
# File lib/opal/rewriters/thrower_finder.rb, line 45 def on_until(node); on_loop(node) { super }; end
on_until_post(node)
click to toggle source
Calls superclass method
# File lib/opal/rewriters/thrower_finder.rb, line 46 def on_until_post(node); on_loop(node) { super }; end
on_while(node)
click to toggle source
Calls superclass method
# File lib/opal/rewriters/thrower_finder.rb, line 43 def on_while(node); on_loop(node) { super }; end
on_while_post(node)
click to toggle source
Calls superclass method
# File lib/opal/rewriters/thrower_finder.rb, line 44 def on_while_post(node); on_loop(node) { super }; end
Private Instance Methods
pushing(*stacks) { || ... }
click to toggle source
# File lib/opal/rewriters/thrower_finder.rb, line 77 def pushing(*stacks) stacks.each { |stack, node| stack.push(node) } result = yield stacks.map(&:first).each(&:pop) result end
tracking(breaker, stack)
click to toggle source
# File lib/opal/rewriters/thrower_finder.rb, line 84 def tracking(breaker, stack) stack.last.meta[:"has_#{breaker}"] = true if stack.last end