1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
|
#ifndef RBIMPL_INTERN_PROC_H /*-*-C++-*-vi:se ft=cpp:*/
#define RBIMPL_INTERN_PROC_H
/**
* @file
* @author Ruby developers <ruby-core@ruby-lang.org>
* @copyright This file is a part of the programming language Ruby.
* Permission is hereby granted, to either redistribute and/or
* modify this file, provided that the conditions mentioned in the
* file COPYING are met. Consult the file for details.
* @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are
* implementation details. Don't take them as canon. They could
* rapidly appear then vanish. The name (path) of this header file
* is also an implementation detail. Do not expect it to persist
* at the place it is now. Developers are free to move it anywhere
* anytime at will.
* @note To ruby-core: remember that this header can be possibly
* 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.
* @brief Public APIs related to ::rb_cProc.
*/
#include "ruby/internal/dllexport.h"
#include "ruby/internal/iterator.h"
#include "ruby/internal/value.h"
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);
/**
* 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);
/**
* 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()
#endif /* RBIMPL_INTERN_PROC_H */
|