CodeTools::AST << {
Quest < Node { node_type quest field receiver, field questable setter questable: |given| { given.receiver = FakeReceiver.new(line: self.line) given } bytecode: |g| { pos(g) ## # unless Rubinius::Type.object_respond_to?(self.receiver, self.questable.name).false? # execute_statement self.questable # else # return void # end else_label = g.new_label end_label = g.new_label self.receiver.bytecode(g) g.dup_top # dup the receiver to save it for later g.push_type; g.swap g.push_literal(self.questable.name) g.send(:"object_respond_to?", 2) g.send(:"false?", 0) g.goto_if_true(else_label) # The duped receiver is still at the top of the stack, # and self.questable.receiver has been set to an instance of FakeReceiver # to let the true receiver pass through instead. self.questable.bytecode(g) g.goto(end_label) else_label.set! g.pop # pop the duped receiver - it won't be used after all g.push_void end_label.set! } FakeReceiver < Node { node_type qrcvr # Do nothing here - this would normally be ill-advised, # because Nodes are expected to push an item onto the stack, # but here we are intentionally not doing so because # the real receiver should already at the top of the stack bytecode: |g| pos(g) } }
}