summaryrefslogtreecommitdiff
path: root/include/ruby/internal/intern/proc.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/ruby/internal/intern/proc.h')
-rw-r--r--include/ruby/internal/intern/proc.h336
1 files changed, 318 insertions, 18 deletions
diff --git a/include/ruby/internal/intern/proc.h b/include/ruby/internal/intern/proc.h
index d6f77cbd4d..b8c3c5e146 100644
--- a/include/ruby/internal/intern/proc.h
+++ b/include/ruby/internal/intern/proc.h
@@ -17,7 +17,7 @@
* recursively included from extension libraries written in C++.
* Do not expect for instance `__VA_ARGS__` is always available.
* We assume C99 for ruby itself but we don't assume languages of
- * extension libraries. They could be written in C++98.
+ * extension libraries. They could be written in C++98.
* @brief Public APIs related to ::rb_cProc.
*/
#include "ruby/internal/dllexport.h"
@@ -27,26 +27,326 @@
RBIMPL_SYMBOL_EXPORT_BEGIN()
/* proc.c */
+
+/**
+ * Constructs a Proc object from implicitly passed components. When a ruby
+ * method is called with a block, that block is not explicitly passed around
+ * using C level function parameters. This function gathers all the necessary
+ * info to turn them into a Ruby level instance of ::rb_cProc.
+ *
+ * @exception rb_eArgError There is no passed block.
+ * @return An instance of ::rb_cProc.
+ */
VALUE rb_block_proc(void);
+
+/**
+ * Identical to rb_proc_new(), except it returns a lambda.
+ *
+ * @exception rb_eArgError There is no passed block.
+ * @return An instance of ::rb_cProc.
+ */
VALUE rb_block_lambda(void);
-VALUE rb_proc_new(rb_block_call_func_t, VALUE);
-VALUE rb_obj_is_proc(VALUE);
-VALUE rb_proc_call(VALUE, VALUE);
-VALUE rb_proc_call_kw(VALUE, VALUE, int);
-VALUE rb_proc_call_with_block(VALUE, int argc, const VALUE *argv, VALUE);
-VALUE rb_proc_call_with_block_kw(VALUE, int argc, const VALUE *argv, VALUE, int);
-int rb_proc_arity(VALUE);
-VALUE rb_proc_lambda_p(VALUE);
+
+/**
+ * This is an rb_iterate() + rb_block_proc() combo.
+ *
+ * ```CXX
+ * VALUE
+ * my_own_iterator(RB_BLOCK_CALL_FUNC_ARGLIST(y, c))
+ * {
+ * const auto plus = rb_intern("+");
+ * return rb_funcall(c, plus, 1, y);
+ * }
+ *
+ * VALUE
+ * my_own_method(VALUE self)
+ * {
+ * return rb_proc_new(my_own_iterator, self);
+ * }
+ * ```
+ *
+ * @param[in] func A backend function of a proc.
+ * @param[in] callback_arg Passed to `func`'s callback_arg.
+ * @return A C-backended proc object.
+ *
+ */
+VALUE rb_proc_new(rb_block_call_func_t func, VALUE callback_arg);
+
+/**
+ * Queries if the given object is a proc.
+ *
+ * @note This is about the object's data structure, not its class etc.
+ * @param[in] recv Object in question.
+ * @retval RUBY_Qtrue It is a proc.
+ * @retval RUBY_Qfalse Otherwise.
+ */
+VALUE rb_obj_is_proc(VALUE recv);
+
+/**
+ * Evaluates the passed proc with the passed arguments.
+ *
+ * @param[in] recv The proc to call.
+ * @param[in] args An instance of ::RArray which is the arguments.
+ * @exception rb_eException Any exceptions happen inside.
+ * @return What the proc evaluates to.
+ */
+VALUE rb_proc_call(VALUE recv, VALUE args);
+
+/**
+ * Identical to rb_proc_call(), except you can specify how to handle the last
+ * element of the given array.
+ *
+ * @param[in] recv The proc to call.
+ * @param[in] args An instance of ::RArray which is the arguments.
+ * @param[in] kw_splat Handling of keyword parameters:
+ * - RB_NO_KEYWORDS `args`' last is not a keyword argument.
+ * - RB_PASS_KEYWORDS `args`' last is a keyword argument.
+ * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block.
+ * @exception rb_eException Any exceptions happen inside.
+ * @return What the proc evaluates to.
+ */
+VALUE rb_proc_call_kw(VALUE recv, VALUE args, int kw_splat);
+
+/**
+ * Identical to rb_proc_call(), except you can additionally pass another proc
+ * object, as a block. Nowadays procs can take blocks:
+ *
+ * ```ruby
+ * l = -> (positional, optional=nil, *rest, kwarg:, **kwrest, &block) {
+ * # ... how can we pass this `&block`? ^^^^^^
+ * }
+ * ```
+ *
+ * And this function is to pass one to such procs.
+ *
+ * @param[in] recv The proc to call.
+ * @param[in] argc Number of arguments.
+ * @param[in] argv Arbitrary number of proc arguments.
+ * @param[in] proc Proc as a passed block.
+ * @exception rb_eException Any exceptions happen inside.
+ * @return What the proc evaluates to.
+ */
+VALUE rb_proc_call_with_block(VALUE recv, int argc, const VALUE *argv, VALUE proc);
+
+/**
+ * Identical to rb_proc_call_with_block(), except you can specify how to handle
+ * the last element of the given array. It can also be seen as a routine
+ * identical to rb_proc_call_kw(), except you can additionally pass another
+ * proc object as a block.
+ *
+ * @param[in] recv The proc to call.
+ * @param[in] argc Number of arguments.
+ * @param[in] argv Arbitrary number of proc arguments.
+ * @param[in] proc Proc as a passed block.
+ * @param[in] kw_splat Handling of keyword parameters:
+ * - RB_NO_KEYWORDS `args`' last is not a keyword argument.
+ * - RB_PASS_KEYWORDS `args`' last is a keyword argument.
+ * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block.
+ * @exception rb_eException Any exceptions happen inside.
+ * @return What the proc evaluates to.
+ */
+VALUE rb_proc_call_with_block_kw(VALUE recv, int argc, const VALUE *argv, VALUE proc, int kw_splat);
+
+/**
+ * Queries the number of mandatory arguments of the given Proc. If its block
+ * is declared to take no arguments, returns `0`. If the block is known to
+ * take exactly `n` arguments, returns `n`. If the block has optional
+ * arguments, returns `-n-1`, where `n` is the number of mandatory arguments,
+ * with the exception for blocks that are not lambdas and have only a finite
+ * number of optional arguments; in this latter case, returns `n`. Keyword
+ * arguments will be considered as a single additional argument, that argument
+ * being mandatory if any keyword argument is mandatory.
+ *
+ * @param[in] recv Target Proc object.
+ * @retval 0 It takes no arguments.
+ * @retval >0 It takes exactly this number of arguments.
+ * @retval <0 It takes optional arguments.
+ */
+int rb_proc_arity(VALUE recv);
+
+/**
+ * Queries if the given object is a lambda. Instances of ::rb_cProc are either
+ * lambda or proc. They differ in several points. This function can
+ * distinguish them without actually evaluating their contents.
+ *
+ * @param[in] recv Target proc object.
+ * @retval RUBY_Qtrue It is a lambda.
+ * @retval RUBY_Qfalse Otherwise.
+ */
+VALUE rb_proc_lambda_p(VALUE recv);
+
+/**
+ * Snapshots the current execution context and turn it into an instance of
+ * ::rb_cBinding.
+ *
+ * @return An instance of ::rb_cBinding.
+ */
VALUE rb_binding_new(void);
-VALUE rb_obj_method(VALUE, VALUE);
-VALUE rb_obj_is_method(VALUE);
-VALUE rb_method_call(int, const VALUE*, VALUE);
-VALUE rb_method_call_kw(int, const VALUE*, VALUE, int);
-VALUE rb_method_call_with_block(int, const VALUE *, VALUE, VALUE);
-VALUE rb_method_call_with_block_kw(int, const VALUE *, VALUE, VALUE, int);
-int rb_mod_method_arity(VALUE, ID);
-int rb_obj_method_arity(VALUE, ID);
-VALUE rb_protect(VALUE (*)(VALUE), VALUE, int*);
+
+/**
+ * Creates a method object. A method object is a proc-like object that you can
+ * "call". Note that a method object snapshots the method at the time the
+ * object is created:
+ *
+ * ```ruby
+ * class Foo
+ * def foo
+ * return 1
+ * end
+ * end
+ *
+ * obj = Foo.new.method(:foo)
+ *
+ * class Foo
+ * def foo
+ * return 2
+ * end
+ * end
+ *
+ * obj.call # => 1, not 2.
+ * ```
+ *
+ * @param[in] recv Receiver of the method.
+ * @param[in] mid Method name, in either String or Symbol.
+ * @exception rb_eNoMethodError No such method.
+ * @return An instance of ::rb_cMethod.
+ */
+VALUE rb_obj_method(VALUE recv, VALUE mid);
+
+/**
+ * Queries if the given object is a method.
+ *
+ * @note This is about the object's data structure, not its class etc.
+ * @param[in] recv Object in question.
+ * @retval RUBY_Qtrue It is a method.
+ * @retval RUBY_Qfalse Otherwise.
+ */
+VALUE rb_obj_is_method(VALUE recv);
+
+/**
+ * Evaluates the passed method with the passed arguments.
+ *
+ * @param[in] argc Number of objects of `argv`.
+ * @param[in] argv Arbitrary number of method arguments.
+ * @param[in] recv The method object to call.
+ * @exception rb_eTypeError `recv` is not a method.
+ * @exception rb_eException Any exceptions happen inside.
+ * @return What the method returns.
+ */
+VALUE rb_method_call(int argc, const VALUE *argv, VALUE recv);
+
+/**
+ * Identical to rb_method_call(), except you can specify how to handle the last
+ * element of the given array.
+ *
+ * @param[in] argc Number of objects of `argv`.
+ * @param[in] argv Arbitrary number of method arguments.
+ * @param[in] recv The method object to call.
+ * @param[in] kw_splat Handling of keyword parameters:
+ * - RB_NO_KEYWORDS `args`' last is not a keyword argument.
+ * - RB_PASS_KEYWORDS `args`' last is a keyword argument.
+ * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block.
+ * @exception rb_eTypeError `recv` is not a method.
+ * @exception rb_eException Any exceptions happen inside.
+ * @return What the method returns.
+ */
+VALUE rb_method_call_kw(int argc, const VALUE *argv, VALUE recv, int kw_splat);
+
+/**
+ * Identical to rb_proc_call(), except you can additionally pass a proc as a
+ * block.
+ *
+ * @param[in] argc Number of objects of `argv`.
+ * @param[in] argv Arbitrary number of method arguments.
+ * @param[in] recv The method object to call.
+ * @param[in] proc Proc as a passed block.
+ * @exception rb_eTypeError `recv` is not a method.
+ * @exception rb_eException Any exceptions happen inside.
+ * @return What the method returns.
+ */
+VALUE rb_method_call_with_block(int argc, const VALUE *argv, VALUE recv, VALUE proc);
+
+/**
+ * Identical to rb_method_call_with_block(), except you can specify how to
+ * handle the last element of the given array. It can also be seen as a
+ * routine identical to rb_method_call_kw(), except you can additionally pass
+ * another proc object as a block.
+ *
+ * @param[in] argc Number of objects of `argv`.
+ * @param[in] argv Arbitrary number of method arguments.
+ * @param[in] recv The method object to call.
+ * @param[in] proc Proc as a passed block.
+ * @param[in] kw_splat Handling of keyword parameters:
+ * - RB_NO_KEYWORDS `args`' last is not a keyword argument.
+ * - RB_PASS_KEYWORDS `args`' last is a keyword argument.
+ * - RB_PASS_CALLED_KEYWORDS it depends if there is a passed block.
+ * @exception rb_eTypeError `recv` is not a method.
+ * @exception rb_eException Any exceptions happen inside.
+ * @return What the method returns.
+ */
+VALUE rb_method_call_with_block_kw(int argc, const VALUE *argv, VALUE recv, VALUE proc, int kw_splat);
+
+/**
+ * Queries the number of mandatory arguments of the method defined in the given
+ * module. If it is declared to take no arguments, returns `0`. If it takes
+ * exactly `n` arguments, returns `n`. If it has optional arguments, returns
+ * `-n-1`, where `n` is the number of mandatory arguments. Keyword arguments
+ * will be considered as a single additional argument, that argument being
+ * mandatory if any keyword argument is mandatory.
+ *
+ * @param[in] mod Namespace to search a method for.
+ * @param[in] mid Method id.
+ * @retval 0 It takes no arguments.
+ * @retval >0 It takes exactly this number of arguments.
+ * @retval <0 It takes optional arguments.
+ */
+int rb_mod_method_arity(VALUE mod, ID mid);
+
+/**
+ * Identical to rb_mod_method_arity(), except it searches for singleton methods
+ * rather than instance methods.
+ *
+ * @param[in] obj Object to search for a singleton method.
+ * @param[in] mid Method id.
+ * @retval 0 It takes no arguments.
+ * @retval >0 It takes exactly this number of arguments.
+ * @retval <0 It takes optional arguments.
+ */
+int rb_obj_method_arity(VALUE obj, ID mid);
+
+/* eval.c */
+
+RBIMPL_ATTR_NONNULL((1))
+/**
+ * Protects a function call from potential global escapes from the function.
+ * Such global escapes include exceptions, `throw`, `break`, for example.
+ *
+ * It first calls the function func with `args` as the argument. If no global
+ * escape occurred during the function, it returns the result and `*state` is
+ * zero. Otherwise, it returns ::RUBY_Qnil and sets `*state` to nonzero. If
+ * `state` is `NULL`, it is not set in both cases.
+ *
+ * @param[in] func A function that potentially escapes globally.
+ * @param[in] args Passed as-is to `func`.
+ * @param[out] state State of execution.
+ * @return What `func` returns, or an undefined value when it did not
+ * return.
+ * @post `*state` is set to zero if succeeded. Nonzero otherwise.
+ * @warning You have to clear the error info with `rb_set_errinfo(Qnil)` if
+ * you decide to ignore the caught exception.
+ * @see rb_eval_string_protect()
+ * @see rb_load_protect()
+ *
+ * @internal
+ *
+ * The "undefined value" described above is in fact ::RUBY_Qnil for now. But
+ * @shyouhei doesn't think that we would never change that.
+ *
+ * Though not a part of our public API, `state` is in fact an
+ * enum ruby_tag_type. You can see the potential "nonzero" values by looking
+ * at vm_core.h.
+ */
+VALUE rb_protect(VALUE (*func)(VALUE args), VALUE args, int *state);
RBIMPL_SYMBOL_EXPORT_END()