summaryrefslogtreecommitdiff
path: root/include/ruby/internal/intern/variable.h
blob: 479c3950c1e3733dfd2bbd8c62c2a561fd2246a1 (plain)
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
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
#ifndef RBIMPL_INTERN_VARIABLE_H                     /*-*-C++-*-vi:se ft=cpp:*/
#define RBIMPL_INTERN_VARIABLE_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 names inside of a Ruby program.
 */
#include "ruby/internal/attr/nonnull.h"
#include "ruby/internal/attr/noreturn.h"
#include "ruby/internal/dllexport.h"
#include "ruby/internal/value.h"
#include "ruby/st.h"

RBIMPL_SYMBOL_EXPORT_BEGIN()

/* variable.c */

/**
 * Queries the name of a module.
 *
 * @param[in]  mod        An instance of ::rb_cModule.
 * @retval     RUBY_Qnil  `mod` is anonymous.
 * @retval     otherwise  `mod` is onymous.
 */
VALUE rb_mod_name(VALUE mod);

/**
 * Identical  to  rb_mod_name(),  except   it  returns  `#<Class:  ...>`  style
 * inspection for anonymous modules.
 *
 * @param[in]  mod        An instance of ::rb_cModule.
 * @return     An instance of ::rb_cString representing `mod`'s path.
 */
VALUE rb_class_path(VALUE mod);

/**
 * @alias{rb_mod_name}
 *
 * @internal
 *
 * Am I missing something?  Why we have the same thing in different names?
 */
VALUE rb_class_path_cached(VALUE mod);

RBIMPL_ATTR_NONNULL(())
/**
 * Names a class.
 *
 * @param[out]  klass  Target module to name.
 * @param[out]  space  Namespace that `klass` shall reside.
 * @param[in]   name   Name of `klass`.
 * @post        `klass` has `space::klass` name.
 */
void rb_set_class_path(VALUE klass, VALUE space, const char *name);

/**
 * Identical  to rb_set_class_path(),  except  it accepts  the  name as  Ruby's
 * string instead of C's.
 *
 * @param[out]  klass  Target module to name.
 * @param[out]  space  Namespace that `klass` shall reside.
 * @param[in]   name   Name of `klass`.
 * @post        `klass` has `space::klass` name.
 */
void rb_set_class_path_string(VALUE klass, VALUE space, VALUE name);

/**
 * Identical to  rb_path2class(), except it  accepts the path as  Ruby's string
 * instead of C's.
 *
 * @param[in]  path           Path to query.
 * @exception  rb_eArgError   No such constant.
 * @exception  rb_eTypeError  The path resolved to a non-module.
 * @return     Resolved class.
 */
VALUE rb_path_to_class(VALUE path);

RBIMPL_ATTR_NONNULL(())
/**
 * Resolves a `Q::W::E::R`-style path string to the actual class it points.
 *
 * @param[in]  path           Path to query.
 * @exception  rb_eArgError   No such constant.
 * @exception  rb_eTypeError  The path resolved to a non-module.
 * @return     Resolved class.
 */
VALUE rb_path2class(const char *path);

/**
 * Queries the name of the given object's class.
 *
 * @param[in]  obj  Arbitrary object.
 * @return     An instance of ::rb_cString representing `obj`'s class' path.
 */
VALUE rb_class_name(VALUE obj);

/**
 * Kicks the autoload procedure as if it was "touched".
 *
 * @param[out]  space        Namespace where autoload is defined.
 * @param[in]   name         Name of the autoloaded constant.
 * @retval      RUBY_Qfalse  No such autoload.
 * @retval      RUBY_Qtrue   Autoload successfully initiated.
 * @note        As an  autoloaded library is expected  to define `space::name`,
 *              it is  a nature  of this function  to have  process-global side
 *              effects.
 * @note        Multiple threads  can simultaneously call this  API.  It blocks
 *              then.  That must not last indefinitely but can take longer than
 *              you expect.
 *
 * @internal
 *
 * @shyouhei has no idea why extension libraries should use this API.
 */
VALUE rb_autoload_load(VALUE space, ID name);

/**
 * Queries if an autoload is defined at a point.
 *
 * @param[in]  space      Namespace where autoload is defined.
 * @param[in]  name       Name of the autoloaded constant.
 * @retval     RUBY_Qnil  No such autoload.
 * @retval     otherwise  The feature (path) registered at `space::name`.
 */
VALUE rb_autoload_p(VALUE space, ID name);

/**
 * Traces a global variable.
 *
 * @param[in]  argc        Either 1 or 2.
 * @param[in]  argv        Variable name, optionally a Proc.
 * @retval     RUBY_Qnil   No previous tracers.
 * @retval     otherwise   Previous tracers.
 *
 * @internal
 *
 * @shyouhei has no idea why extension libraries should use this API.
 */
VALUE rb_f_trace_var(int argc, const VALUE *argv);

/**
 * Deletes the  passed tracer from the  passed global variable, or  if omitted,
 * deletes everything.
 *
 * @param[in]  argc        Either 1 or 2.
 * @param[in]  argv        Variable name, optionally a Proc.
 * @retval     RUBY_Qnil   No previous tracers.
 * @retval     otherwise   Deleted tracers.
 *
 * @internal
 *
 * @shyouhei has no idea why extension libraries should use this API.
 */
VALUE rb_f_untrace_var(int argc, const VALUE *argv);

/**
 * Queries the list of global variables.
 *
 * @return  The list of the name of the global variables.
 *
 * @internal
 *
 * Above description is in fact inaccurate.  This API interfaces with Ractors.
 */
VALUE rb_f_global_variables(void);

/**
 * Aliases  a global  variable.   Did you  know  that you  can  alias a  global
 * variable?  It is like aliasing methods:
 *
 * ```ruby
 * alias $dst $src
 * ```
 *
 * This C function does the same thing.
 *
 * @param[in]  dst  Destination name.
 * @param[in]  src  Source name.
 * @post       A global  variable named `dst`  is defined to  be an alias  of a
 *             global variable named `src`.
 *
 * @internal
 *
 * Above description is in fact inaccurate.  This API interfaces with Ractors.
 */
void rb_alias_variable(ID dst, ID src);

/**
 * Frees the list of instance variables.   3rd parties need not know, but there
 * are several ways  to store an object's instance variables,  depending on its
 * internal structure.   This function makes  sense when the passed  objects is
 * using so-called "generic" backend storage.  People need not be aware of this
 * working behind-the-scenes.
 *
 * @param[out]  obj  The object in question.
 *
 * @internal
 *
 * This just  destroys the given object.   @shyouhei has no idea  why extension
 * libraries should use this API.
 */
void rb_free_generic_ivar(VALUE obj);

/**
 * Identical to rb_iv_get(), except it accepts the name as an ::ID instead of a
 * C string.
 *
 * @param[in]  obj        Target object.
 * @param[in]  name       Target instance variable to query.
 * @retval     RUBY_nil   No such instance variable.
 * @retval     otherwise  The value assigned to the instance variable.
 */
VALUE rb_ivar_get(VALUE obj, ID name);

/**
 * Identical to rb_iv_set(), except it accepts the name as an ::ID instead of a
 * C string.
 *
 * @param[out]  obj              Target object.
 * @param[in]   name             Target instance variable.
 * @param[in]   val              Value to assign.
 * @exception   rb_eFrozenError  Can't modify `obj`.
 * @exception   rb_eArgError     `obj` has too many instance variables.
 * @return      Passed value.
 * @post        An  instance variable  named  `name` is  defined  if absent  on
 *              `obj`, whose value is set to `val`.
 */
VALUE rb_ivar_set(VALUE obj, ID name, VALUE val);

/**
 * Queries if  the instance variable  is defined  at the object.   This roughly
 * resembles `defined?(@name)` in `obj`'s context.
 *
 * @param[in]  obj          Target object.
 * @param[in]  name         Target instance variable to query.
 * @retval     RUBY_Qtrue   There is an instance variable.
 * @retval     RUBY_Qfalse  No such instance variable.
 */
VALUE rb_ivar_defined(VALUE obj, ID name);

/**
 * Iterates over an object's instance variables.
 *
 * @param[in]  obj   Target object.
 * @param[in]  func  Callback function.
 * @param[in]  arg   Passed as-is to the last argument of `func`.
 */
void rb_ivar_foreach(VALUE obj, int (*func)(ID name, VALUE val, st_data_t arg), st_data_t arg);

/**
 * Number of instance variables defined on an object.
 *
 * @param[in]  obj   Target object.
 * @return     Number of instance variables defined on `obj`.
 */
st_index_t rb_ivar_count(VALUE obj);

/**
 * Identical to rb_ivar_get()
 *
 * @param[in]  obj        Target object.
 * @param[in]  name       Target instance variable to query.
 * @retval     RUBY_nil   No such instance variable.
 * @retval     otherwise  The value assigned to the instance variable.
 *
 * @internal
 *
 * Am I missing something?  Why we have the same thing in different names?
 */
VALUE rb_attr_get(VALUE obj, ID name);

/**
 * Resembles `Object#instance_variables`.
 *
 * @param[in]  obj  Target object to query.
 * @return     An array of instance variable names for the receiver.
 * @note       Simply defining  an accessor  does not create  the corresponding
 *             instance variable.
 */
VALUE rb_obj_instance_variables(VALUE obj);

/**
 * Resembles `Object#remove_instance_variable`.
 *
 * @param[out]  obj   Target object.
 * @param[in]   name  Variable name to remove, either in Symbol or String.
 * @return      What was removed.
 * @pre         Instance variable named `name` is deleted from `obj`.
 */
VALUE rb_obj_remove_instance_variable(VALUE obj, VALUE name);

/**
 * This API is  mysterious.  It has been there since  the initial revision.  No
 * single bits of  documents has ever been written.  The  function name doesn't
 * describe anything.  What should be passed to the argument, or what should be
 * the  return value,  are not  obvious.  Yet  it has  evolved over  time.  The
 * source code is written in counter-intuitive way (as of 3.0).
 *
 * Simply put, don't try to understand this API.
 */
void *rb_mod_const_at(VALUE, void*);

/**
 * This is a variant of rb_mod_const_at().  As a result, it is also mysterious.
 * It _seems_ it iterates over the ancestry  tree of the module.  But what that
 * means is beyond a human brain.
 */
void *rb_mod_const_of(VALUE, void*);

/**
 * This is  another mysterious  API that  comes with no  documents at  all.  It
 * seems it expects  some specific data structure for the  passed pointer.  But
 * the details has  never been made explicit.  It seems  nobody should use this
 * API.
 */
VALUE rb_const_list(void*);

/**
 * Resembles  `Module#constants`.   List  up   the  constants  defined  at  the
 * receiver.  This  includes the  names of constants  in any  included modules,
 * unless `argv[0]` is ::RUBY_Qfalse.
 *
 * The  implementation  makes  no  guarantees  about the  order  in  which  the
 * constants are yielded.
 *
 * @param[in]  argc  Either 0 or 1.
 * @param[in]  argv  Pointer to ::RUBY_Qfalse, if `argc == 1`.
 * @param[in]  recv  Target namespace.
 * @return     An array of symbols, which are constant names under `recv`.
 */
VALUE rb_mod_constants(int argc, const VALUE *argv, VALUE recv);

/**
 * Resembles `Module#remove_const`.
 *
 * @param[out]  space  Target namespace.
 * @param[in]   name   Variable name to remove, either in Symbol or String.
 * @return      What was removed.
 * @pre         Constant named `space::name` is deleted.
 * @note        In case what was removed was in  fact a module or a class, this
 *              operation does  not affect its  name.  Which means  when people
 *              for instance  look at  it using `p`  etc., it  still introduces
 *              itself using the deleted name.  Can confuse people.
 */
VALUE rb_mod_remove_const(VALUE space, VALUE name);

/**
 * Queries if the constant is defined at the namespace.
 *
 * @param[in]  space        Target namespace.
 * @param[in]  name         Target name to query.
 * @retval     RUBY_Qtrue   There is a constant.
 * @retval     RUBY_Qfalse  No such constant.
 *
 * @internal
 *
 * The return values are not typo!  This function returns ruby values casted to
 * `int`.  Completely brain-damaged design.
 */
int rb_const_defined(VALUE space, ID name);

/**
 * Identical to rb_const_defined(), except it  doesn't look for parent classes.
 * For  instance  `Array`  is  a  toplevel  constant,  which  is  visible  from
 * everywhere.  But this  function does not take such things  into account.  It
 * concerns only what is directly defined inside of the given namespace.
 *
 * @param[in]  space        Target namespace.
 * @param[in]  name         Target name to query.
 * @retval     RUBY_Qtrue   There is a constant.
 * @retval     RUBY_Qfalse  No such constant.
 *
 * @internal
 *
 * The return values are not typo!  This function returns ruby values casted to
 * `int`.  Completely brain-damaged design.
 */
int rb_const_defined_at(VALUE space, ID name);

/**
 * Identical  to  rb_const_defined(),  except  it  returns  false  for  private
 * constants.
 *
 * @param[in]  space        Target namespace.
 * @param[in]  name         Target name to query.
 * @retval     RUBY_Qtrue   There is a constant.
 * @retval     RUBY_Qfalse  No such constant.
 *
 * @internal
 *
 * What does "from" mean?  The name sounds quite cryptic.
 *
 * The return values are not typo!  This function returns ruby values casted to
 * `int`.  Completely brain-damaged design.
 */
int rb_const_defined_from(VALUE space, ID name);

/**
 * Identical to rb_const_defined(), except it returns the actual defined value.
 *
 * @param[in]  space          Target namespace.
 * @param[in]  name           Target name to query.
 * @exception  rb_eNameError  No such constant.
 * @return     The defined constant.
 *
 * @internal
 *
 * Above description is in fact inaccurate.  This API interfaces with Ractors.
 */
VALUE rb_const_get(VALUE space, ID name);

/**
 * Identical  to rb_const_defined_at(),  except it  returns the  actual defined
 * value.  It can also be seen as a routine identical to rb_const_get(), except
 * it doesn't look for parent classes.
 *
 * @param[in]  space          Target namespace.
 * @param[in]  name           Target name to query.
 * @exception  rb_eNameError  No such constant.
 * @return     The defined constant.
 *
 * @internal
 *
 * Above description is in fact inaccurate.  This API interfaces with Ractors.
 */
VALUE rb_const_get_at(VALUE space, ID name);

/**
 * Identical  to rb_const_defined_at(),  except it  returns the  actual defined
 * value.  It can also be seen as a routine identical to rb_const_get(), except
 * it doesn't return a private constant.
 *
 * @param[in]  space          Target namespace.
 * @param[in]  name           Target name to query.
 * @exception  rb_eNameError  No such constant.
 * @return     The defined constant.
 *
 * @internal
 *
 * Above description is in fact inaccurate.  This API interfaces with Ractors.
 */
VALUE rb_const_get_from(VALUE space, ID name);

/**
 * Names a constant.
 *
 * @param[out]  space          Target namespace.
 * @param[in]   name           Target name to query.
 * @param[in]   val            Value to define.
 * @exception   rb_eTypeError  `space` is not a module.
 * @post        `name` is a constant under `space`, whose value is `val`.
 * @note        You can reassign.
 *
 * @internal
 *
 * Above description is in fact inaccurate.  This API interfaces with Ractors.
 */
void rb_const_set(VALUE space, ID name, VALUE val);

/**
 * Identical to rb_mod_remove_const(), except it takes the name as ::ID instead
 * of ::VALUE.
 *
 * @param[out]  space  Target namespace.
 * @param[in]   name   Variable name to remove, either in Symbol or String.
 * @return      What was removed.
 * @pre         Constant named `space::name` is deleted.
 * @note        In case what was removed was in  fact a module or a class, this
 *              operation does  not affect its  name.  Which means  when people
 *              for instance  look at  it using `p`  etc., it  still introduces
 *              itself using the deleted name.  Can confuse people.
 */
VALUE rb_const_remove(VALUE space, ID name);

#if 0 /* EXPERIMENTAL: remove if no problem */
RBIMPL_ATTR_NORETURN()
/**
 * This is the default implementation of `Module#const_missing`.
 *
 * @param[in]  space          Target namespace.
 * @param[in]  name           Target name that is nonexistent.
 * @exception  rb_eNameError  Always.
 */
VALUE rb_mod_const_missing(VALUE space, VALUE name);
#endif

/**
 * Queries if the given class has the given class variable.
 *
 * @param[in]  klass        Target class.
 * @param[in]  name         Name to query.
 * @return     RUBY_Qtrue   Yes there is.
 * @return     RUBY_Qfalse  No there isn't.
 * @pre        `klass` must be an instance of rb_cModule.
 *
 * @internal
 *
 * Above description is in fact inaccurate.  This API interfaces with Ractors.
 */
VALUE rb_cvar_defined(VALUE klass, ID name);

/**
 * Assigns a value to a class variable.
 *
 * @param[out]  klass  Target class.
 * @param[in]   name   Variable name.
 * @param[in]   val    Value to be assigned.
 * @post        `klass` has a class variable named `name` whose value is `val`.
 *
 * @internal
 *
 * Above description is in fact inaccurate.  This API interfaces with Ractors.
 */
void rb_cvar_set(VALUE klass, ID name, VALUE val);

/**
 * Obtains a value from a class variable.
 *
 * @param[in]  klass             Target class.
 * @param[in]  name              Variable name.
 * @exception  rb_eNameError     Uninitialised class variable.
 * @exception  rb_eRuntimeError  `[Bug#14541]` situation.
 * @return     Class variable named `name` under `klass`.
 *
 * @internal
 *
 * Above description is in fact inaccurate.  This API interfaces with Ractors.
 */
VALUE rb_cvar_get(VALUE klass, ID name);

RBIMPL_ATTR_NONNULL(())
/**
 * Identical  to rb_cvar_get(),  except  it takes  additional "front"  pointer.
 * This  extra parameter  is a  buffer,  which will  have the  class where  the
 * queried class variable actually resides.
 *
 * @param[in]   klass             Target class.
 * @param[in]   name              Variable name.
 * @param[out]  front             Return buffer.
 * @exception   rb_eNameError     Uninitialised class variable.
 * @exception   rb_eRuntimeError  `[Bug#14541]` situation.
 * @return      Class variable named `name` under `klass`.
 * @post        `front` has the class object,  which is an ancestor of `klass`,
 *              where the queried class variable actually resides.
 *
 * @internal
 *
 * Above description is in fact inaccurate.  This API interfaces with Ractors.
 */
VALUE rb_cvar_find(VALUE klass, ID name, VALUE *front);

RBIMPL_ATTR_NONNULL(())
/**
 * Identical to rb_cvar_set(), except it accepts C's string instead of ::ID.
 *
 * @param[out]  klass  Target class.
 * @param[in]   name   Variable name.
 * @param[in]   val    Value to be assigned.
 * @post        `klass` has a class variable named `name` whose value is `val`.
 */
void rb_cv_set(VALUE klass, const char *name, VALUE val);

RBIMPL_ATTR_NONNULL(())
/**
 * Identical to rb_cvar_get(), except it accepts C's string instead of ::ID.
 *
 * @param[in]  klass             Target class.
 * @param[in]  name              Variable name.
 * @exception  rb_eNameError     Uninitialised class variable.
 * @exception  rb_eRuntimeError  `[Bug#14541]` situation.
 * @return     Class variable named `name` under `klass`.
 */
VALUE rb_cv_get(VALUE klass, const char *name);

RBIMPL_ATTR_NONNULL(())
/**
 * @alias{rb_cv_set}
 *
 * @internal
 *
 * Am I missing something?  Why we have the same thing in different names?
 */
void rb_define_class_variable(VALUE, const char*, VALUE);

/**
 * Resembles `Module#class_variables`.   List up  the variables defined  at the
 * receiver.  This  includes the  names of constants  in any  included modules,
 * unless `argv[0]` is ::RUBY_Qfalse.
 *
 * The  implementation  makes  no  guarantees  about the  order  in  which  the
 * constants are yielded.
 *
 * @param[in]  argc  Either 0 or 1.
 * @param[in]  argv  Pointer to ::RUBY_Qfalse, if `argc == 1`.
 * @param[in]  recv  Target class.
 * @return     An  array  of symbols,  which  are  class variable  names  under
 *             `recv`.
 */
VALUE rb_mod_class_variables(int argc, const VALUE *argv, VALUE recv);

/**
 * Resembles `Module#remove_class_variable`.
 *
 * @param[out]  mod   Target class.
 * @param[in]   name  Variable name to remove, either in Symbol or String.
 * @return      What was removed.
 * @pre         Instance variable named `name` is deleted from `obj`.
 */
VALUE rb_mod_remove_cvar(VALUE mod, VALUE name);

RBIMPL_SYMBOL_EXPORT_END()

#endif /* RBIMPL_INTERN_VARIABLE_H */