diff --git a/lib/melbourne/nodes.rb b/lib/melbourne/nodes.rb index 64f1e5494b..a1a09260a3 100644 --- a/lib/melbourne/nodes.rb +++ b/lib/melbourne/nodes.rb @@ -1267,12 +1267,43 @@ def bytecode(g) end class Ensure < Node - def self.from(p, head, ensr) + def self.from(p, body, ensr) node = Ensure.new p.compiler + node.body = body || Nil.from(p) + node.ensure = ensr node end + def children + [@body, @ensure] + end + def bytecode(g) + pos(g) + + ok = g.new_label + g.exceptions :ensure do |ex| + @body.bytecode(g) + ex.escape ok + + ex.handle! + g.push_exception + + @ensure.bytecode(g) + g.pop + + g.pop_exception + + # Re-raise the exception + g.reraise + end + + ok.set! + + # Now, re-emit the code for the ensure which will run if there was no + # exception generated. + @ensure.bytecode(g) + g.pop end end diff --git a/lib/melbourne/processor.rb b/lib/melbourne/processor.rb index 322fea9351..a85b3085fd 100644 --- a/lib/melbourne/processor.rb +++ b/lib/melbourne/processor.rb @@ -186,8 +186,8 @@ def process_dxstr(line, str, array) AST::DynamicExecuteString.from self, str, array end - def process_ensure(line, head, ensr) - AST::Ensure.from self, head, ensr + def process_ensure(line, body, ensr) + AST::Ensure.from self, body, ensr end def process_evstr(line, value)