mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
d0892f1ba9
Added complete call-seq documentation for catch/throw functionality across both Ruby and C implementations: - Class documentation: explains exception raised for unmatched throws - initialize: constructor with tag and value parameters, creates error message with proper tag inspection and stores thrown values for debugging - throw: transfers control to matching catch block with optional return value, raises UncaughtThrowError if no matching catch found, supports both single tag and tag+value forms with comprehensive usage examples - find_catcher: searches call stack for matching catch block by comparing tags using mrb_obj_eq, returns call stack index or 0 if not found - catch_syms: pre-defined symbols (Object, new, call) used by catch bytecode implementation for efficient symbol lookup - catch_iseq: bytecode instruction sequence implementing catch method logic, handles default tag creation (Object.new) and block parameter passing - catch_irep: instruction representation containing bytecode metadata for catch method execution - catch_proc: procedure object used to identify catch blocks in call stack during throw operations, marked with proper GC and scope flags - mrb_mruby_catch_gem_init: defines catch and throw as private methods in Kernel module, initializes symbols and sets up bytecode procedure - mrb_mruby_catch_gem_final: cleanup function (currently no-op as implementation uses static data structures) Co-authored-by: Atlassian Rovo Dev
mruby-catch
This mrbgem provides catch and throw functionality similar to what is available in standard Ruby. It allows for non-local exits from blocks of code.
catch
The catch method is used to establish a block that can be exited prematurely using throw.
catch(tag) do |current_tag|
# ... code ...
if some_condition
throw(tag, return_value)
end
# ... more code ...
end
- With a tag: When
catchis called with atag(any Ruby object), it executes the block. Ifthrowis called with the sametagfrom within this block (or any method called from within it), thecatchblock immediately exits and returns the value provided tothrow. - Block completion: If the block executes to completion without
throwbeing called with a matching tag, thecatchblock returns the result of the last expression evaluated in the block. - No tag: If
catchis called without a tag, a new uniqueObjectis created and used as the tag. This tag is passed as an argument to the block.
catch do |generated_tag|
# generated_tag is a new Object
throw(generated_tag, "hello")
end # => "hello"
throw
The throw method is used to initiate a non-local exit to a corresponding catch block.
throw(tag)
throw(tag, value)
- With a tag and value:
throw(tag, value)jumps to the innermost activecatchblock that is waiting fortag. Thecatchblock then returnsvalue. - With only a tag:
throw(tag)is equivalent tothrow(tag, nil). - Uncaught throw: If
throwis called with atagfor which there is no matchingcatchblock in the current call stack, anUncaughtThrowErroris raised.
UncaughtThrowError
This is a custom error class that inherits from ArgumentError. It is raised when throw is called for a tag that is not currently being caught.
It has two attributes:
tag: The tag that was thrown.value: The value that was thrown with the tag.
Example
def check_value(val)
puts "Checking: #{val}"
if val < 0
throw(:negative_value, val)
elsif val == 0
throw(:zero_value) # value will be nil
end
puts "#{val} is positive"
val * 2
end
result = catch(:negative_value) do
puts catch(:zero_value) do
puts check_value(10)
puts check_value(-5) # This will throw to :negative_value
puts check_value(0) # This would throw to :zero_value, but it's not reached
end
puts "This line is skipped if :zero_value is thrown."
end
puts "Result: #{result}"
# Output:
# Checking: 10
# 10 is positive
# 20
# Checking: -5
# Result: -5
puts "--- Next example --- "
result2 = catch do |tag_a|
catch do |tag_b|
puts "In tag_b block"
throw(tag_a, "Exited from A via B")
puts "This is not printed"
end
puts "This is not printed either"
end
puts result2 # => Exited from A via B