Class: Opal::Rewriters::ThrowerFinder

Inherits:
Base
  • Object
show all
Defined in:
opal/lib/opal/rewriters/thrower_finder.rb

Overview

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.

Constant Summary

Constants inherited from Base

Base::DUMMY_LOCATION

Instance Attribute Summary

Attributes inherited from Base

#current_node

Instance Method Summary collapse

Methods inherited from Base

#append_to_body, #begin_with_stmts, #dynamic!, #error, #on_top, #prepend_to_body, #process, s, #s, #stmts_of

Constructor Details

#initializeThrowerFinder

Returns a new instance of ThrowerFinder.



12
13
14
15
16
17
# File 'opal/lib/opal/rewriters/thrower_finder.rb', line 12

def initialize
  @break_stack = []
  @redo_stack = []
  @retry_stack = []
  @rescue_else_stack = []
end

Instance Method Details

#on_break(node) ⇒ Object



19
20
21
22
# File 'opal/lib/opal/rewriters/thrower_finder.rb', line 19

def on_break(node)
  tracking(:break, @break_stack)
  super
end

#on_defined(node) ⇒ Object

ignore throwers inside defined



49
50
51
52
53
54
55
# File 'opal/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) ⇒ Object

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.



63
64
65
# File 'opal/lib/opal/rewriters/thrower_finder.rb', line 63

def on_ensure(node)
  pushing([@rescue_else_stack, node]) { super }
end

#on_for(node) ⇒ Object



42
# File 'opal/lib/opal/rewriters/thrower_finder.rb', line 42

def on_for(node);        on_loop(node) { super }; end

#on_iter(node) ⇒ Object



34
35
36
# File 'opal/lib/opal/rewriters/thrower_finder.rb', line 34

def on_iter(node)
  pushing([@break_stack, node]) { super }
end

#on_loop(node, &block) ⇒ Object



38
39
40
# File 'opal/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) ⇒ Object



24
25
26
27
# File 'opal/lib/opal/rewriters/thrower_finder.rb', line 24

def on_redo(node)
  tracking(:redo, @redo_stack)
  super
end

#on_rescue(node) ⇒ Object



67
68
69
70
71
72
73
# File 'opal/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) ⇒ Object



29
30
31
32
# File 'opal/lib/opal/rewriters/thrower_finder.rb', line 29

def on_retry(node)
  tracking(:retry, @retry_stack)
  super
end

#on_until(node) ⇒ Object



45
# File 'opal/lib/opal/rewriters/thrower_finder.rb', line 45

def on_until(node);      on_loop(node) { super }; end

#on_until_post(node) ⇒ Object



46
# File 'opal/lib/opal/rewriters/thrower_finder.rb', line 46

def on_until_post(node); on_loop(node) { super }; end

#on_while(node) ⇒ Object



43
# File 'opal/lib/opal/rewriters/thrower_finder.rb', line 43

def on_while(node);      on_loop(node) { super }; end

#on_while_post(node) ⇒ Object



44
# File 'opal/lib/opal/rewriters/thrower_finder.rb', line 44

def on_while_post(node); on_loop(node) { super }; end