Ruby 2.7.0p0(2019-12-25revision647ee6f091eafcce70ffb75ddf7e121e192ab217)

struct.c
Go to the documentation of this file.
1 /**********************************************************************
2
3 struct.c -
4
5 $Author$
6 created at: Tue Mar 22 18:44:30 JST 1995
7
8 Copyright (C) 1993-2007 Yukihiro Matsumoto
9
10 **********************************************************************/
11
12 #include "internal.h"
13 #include "vm_core.h"
14 #include "id.h"
15 #include "transient_heap.h"
16
17 /* only for struct[:field] access */
18 enum {
19 AREF_HASH_UNIT = 5,
20 AREF_HASH_THRESHOLD = 10
21 };
22
23 const rb_iseq_t *rb_method_for_self_aref(VALUE name, VALUE arg, rb_insn_func_t func);
24 const rb_iseq_t *rb_method_for_self_aset(VALUE name, VALUE arg, rb_insn_func_t func);
25
26 VALUE rb_cStruct;
27 static ID id_members, id_back_members, id_keyword_init;
28
29 static VALUE struct_alloc(VALUE);
30
31 static inline VALUE
32 struct_ivar_get(VALUE c, ID id)
33 {
34 VALUE orig = c;
35 VALUE ivar = rb_attr_get(c, id);
36
37 if (!NIL_P(ivar))
38 return ivar;
39
40 for (;;) {
41 c = RCLASS_SUPER(c);
42 if (c == 0 || c == rb_cStruct)
43 return Qnil;
44 ivar = rb_attr_get(c, id);
45 if (!NIL_P(ivar)) {
46 return rb_ivar_set(orig, id, ivar);
47 }
48 }
49 }
50
51 VALUE
52 rb_struct_s_keyword_init(VALUE klass)
53 {
54 return struct_ivar_get(klass, id_keyword_init);
55 }
56
57 VALUE
58 rb_struct_s_members(VALUE klass)
59 {
60 VALUE members = struct_ivar_get(klass, id_members);
61
62 if (NIL_P(members)) {
63 rb_raise(rb_eTypeError, "uninitialized struct");
64 }
65 if (!RB_TYPE_P(members, T_ARRAY)) {
66 rb_raise(rb_eTypeError, "corrupted struct");
67 }
68 return members;
69 }
70
71 VALUE
72 rb_struct_members(VALUE s)
73 {
74 VALUE members = rb_struct_s_members(rb_obj_class(s));
75
76 if (RSTRUCT_LEN(s) != RARRAY_LEN(members)) {
77 rb_raise(rb_eTypeError, "struct size differs (%ld required %ld given)",
78 RARRAY_LEN(members), RSTRUCT_LEN(s));
79 }
80 return members;
81 }
82
83 static long
84 struct_member_pos_ideal(VALUE name, long mask)
85 {
86 /* (id & (mask/2)) * 2 */
87 return (SYM2ID(name) >> (ID_SCOPE_SHIFT - 1)) & mask;
88 }
89
90 static long
91 struct_member_pos_probe(long prev, long mask)
92 {
93 /* (((prev/2) * AREF_HASH_UNIT + 1) & (mask/2)) * 2 */
94 return (prev * AREF_HASH_UNIT + 2) & mask;
95 }
96
97 static VALUE
98 struct_set_members(VALUE klass, VALUE /* frozen hidden array */ members)
99 {
100 VALUE back;
101 const long members_length = RARRAY_LEN(members);
102
103 if (members_length <= AREF_HASH_THRESHOLD) {
104 back = members;
105 }
106 else {
107 long i, j, mask = 64;
108 VALUE name;
109
110 while (mask < members_length * AREF_HASH_UNIT) mask *= 2;
111
112 back = rb_ary_tmp_new(mask + 1);
113 rb_ary_store(back, mask, INT2FIX(members_length));
114 mask -= 2; /* mask = (2**k-1)*2 */
115
116 for (i=0; i < members_length; i++) {
117 name = RARRAY_AREF(members, i);
118
119 j = struct_member_pos_ideal(name, mask);
120
121 for (;;) {
122 if (!RTEST(RARRAY_AREF(back, j))) {
123 rb_ary_store(back, j, name);
124 rb_ary_store(back, j + 1, INT2FIX(i));
125 break;
126 }
127 j = struct_member_pos_probe(j, mask);
128 }
129 }
130 OBJ_FREEZE_RAW(back);
131 }
132 rb_ivar_set(klass, id_members, members);
133 rb_ivar_set(klass, id_back_members, back);
134
135 return members;
136 }
137
138 static inline int
139 struct_member_pos(VALUE s, VALUE name)
140 {
141 VALUE back = struct_ivar_get(rb_obj_class(s), id_back_members);
142 long j, mask;
143
144 if (UNLIKELY(NIL_P(back))) {
145 rb_raise(rb_eTypeError, "uninitialized struct");
146 }
147 if (UNLIKELY(!RB_TYPE_P(back, T_ARRAY))) {
148 rb_raise(rb_eTypeError, "corrupted struct");
149 }
150
151 mask = RARRAY_LEN(back);
152
153 if (mask <= AREF_HASH_THRESHOLD) {
154 if (UNLIKELY(RSTRUCT_LEN(s) != mask)) {
155 rb_raise(rb_eTypeError,
156 "struct size differs (%ld required %ld given)",
157 mask, RSTRUCT_LEN(s));
158 }
159 for (j = 0; j < mask; j++) {
160 if (RARRAY_AREF(back, j) == name)
161 return (int)j;
162 }
163 return -1;
164 }
165
166 if (UNLIKELY(RSTRUCT_LEN(s) != FIX2INT(RARRAY_AREF(back, mask-1)))) {
167 rb_raise(rb_eTypeError, "struct size differs (%d required %ld given)",
168 FIX2INT(RARRAY_AREF(back, mask-1)), RSTRUCT_LEN(s));
169 }
170
171 mask -= 3;
172 j = struct_member_pos_ideal(name, mask);
173
174 for (;;) {
175 VALUE e = RARRAY_AREF(back, j);
176 if (e == name)
177 return FIX2INT(RARRAY_AREF(back, j + 1));
178 if (!RTEST(e)) {
179 return -1;
180 }
181 j = struct_member_pos_probe(j, mask);
182 }
183 }
184
185 static VALUE
186 rb_struct_s_members_m(VALUE klass)
187 {
188 VALUE members = rb_struct_s_members(klass);
189
190 return rb_ary_dup(members);
191 }
192
193 /*
194 * call-seq:
195 * struct.members -> array
196 *
197 * Returns the struct members as an array of symbols:
198 *
199 * Customer = Struct.new(:name, :address, :zip)
200 * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
201 * joe.members #=> [:name, :address, :zip]
202 */
203
204 static VALUE
205 rb_struct_members_m(VALUE obj)
206 {
207 return rb_struct_s_members_m(rb_obj_class(obj));
208 }
209
210 VALUE
211 rb_struct_getmember(VALUE obj, ID id)
212 {
213 VALUE slot = ID2SYM(id);
214 int i = struct_member_pos(obj, slot);
215 if (i != -1) {
216 return RSTRUCT_GET(obj, i);
217 }
218 rb_name_err_raise("`%1$s' is not a struct member", obj, ID2SYM(id));
219
220 UNREACHABLE_RETURN(Qnil);
221 }
222
223 static VALUE rb_struct_ref0(VALUE obj) {return RSTRUCT_GET(obj, 0);}
224 static VALUE rb_struct_ref1(VALUE obj) {return RSTRUCT_GET(obj, 1);}
225 static VALUE rb_struct_ref2(VALUE obj) {return RSTRUCT_GET(obj, 2);}
226 static VALUE rb_struct_ref3(VALUE obj) {return RSTRUCT_GET(obj, 3);}
227 static VALUE rb_struct_ref4(VALUE obj) {return RSTRUCT_GET(obj, 4);}
228 static VALUE rb_struct_ref5(VALUE obj) {return RSTRUCT_GET(obj, 5);}
229 static VALUE rb_struct_ref6(VALUE obj) {return RSTRUCT_GET(obj, 6);}
230 static VALUE rb_struct_ref7(VALUE obj) {return RSTRUCT_GET(obj, 7);}
231 static VALUE rb_struct_ref8(VALUE obj) {return RSTRUCT_GET(obj, 8);}
232 static VALUE rb_struct_ref9(VALUE obj) {return RSTRUCT_GET(obj, 9);}
233
234 #define N_REF_FUNC numberof(ref_func)
235
236 static VALUE (*const ref_func[])(VALUE) = {
237 rb_struct_ref0,
238 rb_struct_ref1,
239 rb_struct_ref2,
240 rb_struct_ref3,
241 rb_struct_ref4,
242 rb_struct_ref5,
243 rb_struct_ref6,
244 rb_struct_ref7,
245 rb_struct_ref8,
246 rb_struct_ref9,
247 };
248
249 static void
250 rb_struct_modify(VALUE s)
251 {
252 rb_check_frozen(s);
253 }
254
255 static VALUE
256 anonymous_struct(VALUE klass)
257 {
258 VALUE nstr;
259
260 nstr = rb_class_new(klass);
261 rb_make_metaclass(nstr, RBASIC(klass)->klass);
262 rb_class_inherited(klass, nstr);
263 return nstr;
264 }
265
266 static VALUE
267 new_struct(VALUE name, VALUE super)
268 {
269 /* old style: should we warn? */
270 ID id;
271 name = rb_str_to_str(name);
272 if (!rb_is_const_name(name)) {
273 rb_name_err_raise("identifier %1$s needs to be constant",
274 super, name);
275 }
276 id = rb_to_id(name);
277 if (rb_const_defined_at(super, id)) {
278 rb_warn("redefining constant %"PRIsVALUE"::%"PRIsVALUE, super, name);
279 rb_mod_remove_const(super, ID2SYM(id));
280 }
281 return rb_define_class_id_under(super, id, super);
282 }
283
284 static void
285 define_aref_method(VALUE nstr, VALUE name, VALUE off)
286 {
287 rb_control_frame_t *FUNC_FASTCALL(rb_vm_opt_struct_aref)(rb_execution_context_t *, rb_control_frame_t *);
288 const rb_iseq_t *iseq = rb_method_for_self_aref(name, off, rb_vm_opt_struct_aref);
289
290 rb_add_method_iseq(nstr, SYM2ID(name), iseq, NULL, METHOD_VISI_PUBLIC);
291 }
292
293 static void
294 define_aset_method(VALUE nstr, VALUE name, VALUE off)
295 {
296 rb_control_frame_t *FUNC_FASTCALL(rb_vm_opt_struct_aset)(rb_execution_context_t *, rb_control_frame_t *);
297 const rb_iseq_t *iseq = rb_method_for_self_aset(name, off, rb_vm_opt_struct_aset);
298
299 rb_add_method_iseq(nstr, SYM2ID(name), iseq, NULL, METHOD_VISI_PUBLIC);
300 }
301
302 static VALUE
303 rb_struct_s_inspect(VALUE klass)
304 {
305 VALUE inspect = rb_class_name(klass);
306 if (RTEST(rb_struct_s_keyword_init(klass))) {
307 rb_str_cat_cstr(inspect, "(keyword_init: true)");
308 }
309 return inspect;
310 }
311
312 static VALUE
313 struct_new_kw(int argc, const VALUE *argv, VALUE klass)
314 {
315 return rb_class_new_instance_kw(argc, argv, klass, RB_PASS_CALLED_KEYWORDS);
316 }
317
318 static VALUE
319 setup_struct(VALUE nstr, VALUE members, int keyword_init)
320 {
321 long i, len;
322 VALUE (*new_func)(int, const VALUE *, VALUE) = rb_class_new_instance;
323
324 if (keyword_init) new_func = struct_new_kw;
325
326 members = struct_set_members(nstr, members);
327
328 rb_define_alloc_func(nstr, struct_alloc);
329 rb_define_singleton_method(nstr, "new", new_func, -1);
330 rb_define_singleton_method(nstr, "[]", new_func, -1);
331 rb_define_singleton_method(nstr, "members", rb_struct_s_members_m, 0);
332 rb_define_singleton_method(nstr, "inspect", rb_struct_s_inspect, 0);
333 len = RARRAY_LEN(members);
334 for (i=0; i< len; i++) {
335 VALUE sym = RARRAY_AREF(members, i);
336 ID id = SYM2ID(sym);
337 VALUE off = LONG2NUM(i);
338
339 if (i < N_REF_FUNC) {
340 rb_define_method_id(nstr, id, ref_func[i], 0);
341 }
342 else {
343 define_aref_method(nstr, sym, off);
344 }
345 define_aset_method(nstr, ID2SYM(rb_id_attrset(id)), off);
346 }
347
348 return nstr;
349 }
350
351 VALUE
352 rb_struct_alloc_noinit(VALUE klass)
353 {
354 return struct_alloc(klass);
355 }
356
357 static VALUE
358 struct_make_members_list(va_list ar)
359 {
360 char *mem;
361 VALUE ary, list = rb_ident_hash_new();
362 st_table *tbl = RHASH_TBL(list);
363
364 RBASIC_CLEAR_CLASS(list);
365 while ((mem = va_arg(ar, char*)) != 0) {
366 VALUE sym = rb_sym_intern_ascii_cstr(mem);
367 if (st_insert(tbl, sym, Qtrue)) {
368 rb_raise(rb_eArgError, "duplicate member: %s", mem);
369 }
370 }
371 ary = rb_hash_keys(list);
372 st_clear(tbl);
373 RBASIC_CLEAR_CLASS(ary);
374 OBJ_FREEZE_RAW(ary);
375 return ary;
376 }
377
378 static VALUE
379 struct_define_without_accessor(VALUE outer, const char *class_name, VALUE super, rb_alloc_func_t alloc, VALUE members)
380 {
381 VALUE klass;
382
383 if (class_name) {
384 if (outer) {
385 klass = rb_define_class_under(outer, class_name, super);
386 }
387 else {
388 klass = rb_define_class(class_name, super);
389 }
390 }
391 else {
392 klass = anonymous_struct(super);
393 }
394
395 struct_set_members(klass, members);
396
397 if (alloc) {
398 rb_define_alloc_func(klass, alloc);
399 }
400 else {
401 rb_define_alloc_func(klass, struct_alloc);
402 }
403
404 return klass;
405 }
406
407 VALUE
408 rb_struct_define_without_accessor_under(VALUE outer, const char *class_name, VALUE super, rb_alloc_func_t alloc, ...)
409 {
410 va_list ar;
411 VALUE members;
412
413 va_start(ar, alloc);
414 members = struct_make_members_list(ar);
415 va_end(ar);
416
417 return struct_define_without_accessor(outer, class_name, super, alloc, members);
418 }
419
420 VALUE
421 rb_struct_define_without_accessor(const char *class_name, VALUE super, rb_alloc_func_t alloc, ...)
422 {
423 va_list ar;
424 VALUE members;
425
426 va_start(ar, alloc);
427 members = struct_make_members_list(ar);
428 va_end(ar);
429
430 return struct_define_without_accessor(0, class_name, super, alloc, members);
431 }
432
433 VALUE
434 rb_struct_define(const char *name, ...)
435 {
436 va_list ar;
437 VALUE st, ary;
438
439 va_start(ar, name);
440 ary = struct_make_members_list(ar);
441 va_end(ar);
442
443 if (!name) st = anonymous_struct(rb_cStruct);
444 else st = new_struct(rb_str_new2(name), rb_cStruct);
445 return setup_struct(st, ary, 0);
446 }
447
448 VALUE
449 rb_struct_define_under(VALUE outer, const char *name, ...)
450 {
451 va_list ar;
452 VALUE ary;
453
454 va_start(ar, name);
455 ary = struct_make_members_list(ar);
456 va_end(ar);
457
458 return setup_struct(rb_define_class_under(outer, name, rb_cStruct), ary, 0);
459 }
460
461 /*
462 * call-seq:
463 * Struct.new([class_name] [, member_name]+) -> StructClass
464 * Struct.new([class_name] [, member_name]+, keyword_init: true) -> StructClass
465 * Struct.new([class_name] [, member_name]+) {|StructClass| block } -> StructClass
466 * StructClass.new(value, ...) -> object
467 * StructClass[value, ...] -> object
468 *
469 * The first two forms are used to create a new Struct subclass +class_name+
470 * that can contain a value for each +member_name+. This subclass can be
471 * used to create instances of the structure like any other Class.
472 *
473 * If the +class_name+ is omitted an anonymous structure class will be
474 * created. Otherwise, the name of this struct will appear as a constant in
475 * class Struct, so it must be unique for all Structs in the system and
476 * must start with a capital letter. Assigning a structure class to a
477 * constant also gives the class the name of the constant.
478 *
479 * # Create a structure with a name under Struct
480 * Struct.new("Customer", :name, :address)
481 * #=> Struct::Customer
482 * Struct::Customer.new("Dave", "123 Main")
483 * #=> #<struct Struct::Customer name="Dave", address="123 Main">
484 *
485 * # Create a structure named by its constant
486 * Customer = Struct.new(:name, :address)
487 * #=> Customer
488 * Customer.new("Dave", "123 Main")
489 * #=> #<struct Customer name="Dave", address="123 Main">
490 *
491 * If the optional +keyword_init+ keyword argument is set to +true+,
492 * .new takes keyword arguments instead of normal arguments.
493 *
494 * Customer = Struct.new(:name, :address, keyword_init: true)
495 * Customer.new(name: "Dave", address: "123 Main")
496 * #=> #<struct Customer name="Dave", address="123 Main">
497 *
498 * If a block is given it will be evaluated in the context of
499 * +StructClass+, passing the created class as a parameter:
500 *
501 * Customer = Struct.new(:name, :address) do
502 * def greeting
503 * "Hello #{name}!"
504 * end
505 * end
506 * Customer.new("Dave", "123 Main").greeting #=> "Hello Dave!"
507 *
508 * This is the recommended way to customize a struct. Subclassing an
509 * anonymous struct creates an extra anonymous class that will never be used.
510 *
511 * The last two forms create a new instance of a struct subclass. The number
512 * of +value+ parameters must be less than or equal to the number of
513 * attributes defined for the structure. Unset parameters default to +nil+.
514 * Passing more parameters than number of attributes will raise
515 * an ArgumentError.
516 *
517 * Customer = Struct.new(:name, :address)
518 * Customer.new("Dave", "123 Main")
519 * #=> #<struct Customer name="Dave", address="123 Main">
520 * Customer["Dave"]
521 * #=> #<struct Customer name="Dave", address=nil>
522 */
523
524 static VALUE
525 rb_struct_s_def(int argc, VALUE *argv, VALUE klass)
526 {
527 VALUE name, rest, keyword_init = Qfalse;
528 long i;
529 VALUE st;
530 st_table *tbl;
531
532 rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
533 name = argv[0];
534 if (SYMBOL_P(name)) {
535 name = Qnil;
536 }
537 else {
538 --argc;
539 ++argv;
540 }
541
542 if (RB_TYPE_P(argv[argc-1], T_HASH)) {
543 static ID keyword_ids[1];
544
545 if (!keyword_ids[0]) {
546 keyword_ids[0] = rb_intern("keyword_init");
547 }
548 rb_get_kwargs(argv[argc-1], keyword_ids, 0, 1, &keyword_init);
549 if (keyword_init == Qundef) {
550 keyword_init = Qfalse;
551 }
552 --argc;
553 }
554
555 rest = rb_ident_hash_new();
556 RBASIC_CLEAR_CLASS(rest);
557 tbl = RHASH_TBL(rest);
558 for (i=0; i<argc; i++) {
559 VALUE mem = rb_to_symbol(argv[i]);
560 if (rb_is_attrset_sym(mem)) {
561 rb_raise(rb_eArgError, "invalid struct member: %"PRIsVALUE, mem);
562 }
563 if (st_insert(tbl, mem, Qtrue)) {
564 rb_raise(rb_eArgError, "duplicate member: %"PRIsVALUE, mem);
565 }
566 }
567 rest = rb_hash_keys(rest);
568 st_clear(tbl);
569 RBASIC_CLEAR_CLASS(rest);
570 OBJ_FREEZE_RAW(rest);
571 if (NIL_P(name)) {
572 st = anonymous_struct(klass);
573 }
574 else {
575 st = new_struct(name, klass);
576 }
577 setup_struct(st, rest, (int)keyword_init);
578 rb_ivar_set(st, id_keyword_init, keyword_init);
579 if (rb_block_given_p()) {
580 rb_mod_module_eval(0, 0, st);
581 }
582
583 return st;
584 }
585
586 static long
587 num_members(VALUE klass)
588 {
589 VALUE members;
590 members = struct_ivar_get(klass, id_members);
591 if (!RB_TYPE_P(members, T_ARRAY)) {
592 rb_raise(rb_eTypeError, "broken members");
593 }
594 return RARRAY_LEN(members);
595 }
596
597 /*
598 */
599
600 struct struct_hash_set_arg {
601 VALUE self;
602 VALUE unknown_keywords;
603 };
604
605 static int rb_struct_pos(VALUE s, VALUE *name);
606
607 static int
608 struct_hash_set_i(VALUE key, VALUE val, VALUE arg)
609 {
610 struct struct_hash_set_arg *args = (struct struct_hash_set_arg *)arg;
611 int i = rb_struct_pos(args->self, &key);
612 if (i < 0) {
613 if (args->unknown_keywords == Qnil) {
614 args->unknown_keywords = rb_ary_new();
615 }
616 rb_ary_push(args->unknown_keywords, key);
617 }
618 else {
619 rb_struct_modify(args->self);
620 RSTRUCT_SET(args->self, i, val);
621 }
622 return ST_CONTINUE;
623 }
624
625 static VALUE
626 rb_struct_initialize_m(int argc, const VALUE *argv, VALUE self)
627 {
628 VALUE klass = rb_obj_class(self);
629 long i, n;
630
631 rb_struct_modify(self);
632 n = num_members(klass);
633 if (argc > 0 && RTEST(rb_struct_s_keyword_init(klass))) {
634 struct struct_hash_set_arg arg;
635 if (argc > 1 || !RB_TYPE_P(argv[0], T_HASH)) {
636 rb_raise(rb_eArgError, "wrong number of arguments (given %d, expected 0)", argc);
637 }
638 rb_mem_clear((VALUE *)RSTRUCT_CONST_PTR(self), n);
639 arg.self = self;
640 arg.unknown_keywords = Qnil;
641 rb_hash_foreach(argv[0], struct_hash_set_i, (VALUE)&arg);
642 if (arg.unknown_keywords != Qnil) {
643 rb_raise(rb_eArgError, "unknown keywords: %s",
644 RSTRING_PTR(rb_ary_join(arg.unknown_keywords, rb_str_new2(", "))));
645 }
646 }
647 else {
648 if (n < argc) {
649 rb_raise(rb_eArgError, "struct size differs");
650 }
651 for (i=0; i<argc; i++) {
652 RSTRUCT_SET(self, i, argv[i]);
653 }
654 if (n > argc) {
655 rb_mem_clear((VALUE *)RSTRUCT_CONST_PTR(self)+argc, n-argc);
656 }
657 }
658 return Qnil;
659 }
660
661 VALUE
662 rb_struct_initialize(VALUE self, VALUE values)
663 {
664 return rb_struct_initialize_m(RARRAY_LENINT(values), RARRAY_CONST_PTR(values), self);
665 }
666
667 static VALUE *
668 struct_heap_alloc(VALUE st, size_t len)
669 {
670 VALUE *ptr = rb_transient_heap_alloc((VALUE)st, sizeof(VALUE) * len);
671
672 if (ptr) {
673 RSTRUCT_TRANSIENT_SET(st);
674 return ptr;
675 }
676 else {
677 RSTRUCT_TRANSIENT_UNSET(st);
678 return ALLOC_N(VALUE, len);
679 }
680 }
681
682 #if USE_TRANSIENT_HEAP
683 void
684 rb_struct_transient_heap_evacuate(VALUE obj, int promote)
685 {
686 if (RSTRUCT_TRANSIENT_P(obj)) {
687 const VALUE *old_ptr = rb_struct_const_heap_ptr(obj);
688 VALUE *new_ptr;
689 long len = RSTRUCT_LEN(obj);
690
691 if (promote) {
692 new_ptr = ALLOC_N(VALUE, len);
693 FL_UNSET_RAW(obj, RSTRUCT_TRANSIENT_FLAG);
694 }
695 else {
696 new_ptr = struct_heap_alloc(obj, len);
697 }
698 MEMCPY(new_ptr, old_ptr, VALUE, len);
699 RSTRUCT(obj)->as.heap.ptr = new_ptr;
700 }
701 }
702 #endif
703
704 static VALUE
705 struct_alloc(VALUE klass)
706 {
707 long n;
708 NEWOBJ_OF(st, struct RStruct, klass, T_STRUCT | (RGENGC_WB_PROTECTED_STRUCT ? FL_WB_PROTECTED : 0));
709
710 n = num_members(klass);
711
712 if (0 < n && n <= RSTRUCT_EMBED_LEN_MAX) {
713 RBASIC(st)->flags &= ~RSTRUCT_EMBED_LEN_MASK;
714 RBASIC(st)->flags |= n << RSTRUCT_EMBED_LEN_SHIFT;
715 rb_mem_clear((VALUE *)st->as.ary, n);
716 }
717 else {
718 st->as.heap.ptr = struct_heap_alloc((VALUE)st, n);
719 rb_mem_clear((VALUE *)st->as.heap.ptr, n);
720 st->as.heap.len = n;
721 }
722
723 return (VALUE)st;
724 }
725
726 VALUE
727 rb_struct_alloc(VALUE klass, VALUE values)
728 {
729 return rb_class_new_instance(RARRAY_LENINT(values), RARRAY_CONST_PTR(values), klass);
730 }
731
732 VALUE
733 rb_struct_new(VALUE klass, ...)
734 {
735 VALUE tmpargs[N_REF_FUNC], *mem = tmpargs;
736 int size, i;
737 va_list args;
738
739 size = rb_long2int(num_members(klass));
740 if (size > numberof(tmpargs)) {
741 tmpargs[0] = rb_ary_tmp_new(size);
742 mem = RARRAY_PTR(tmpargs[0]);
743 }
744 va_start(args, klass);
745 for (i=0; i<size; i++) {
746 mem[i] = va_arg(args, VALUE);
747 }
748 va_end(args);
749
750 return rb_class_new_instance(size, mem, klass);
751 }
752
753 static VALUE
754 struct_enum_size(VALUE s, VALUE args, VALUE eobj)
755 {
756 return rb_struct_size(s);
757 }
758
759 /*
760 * call-seq:
761 * struct.each {|obj| block } -> struct
762 * struct.each -> enumerator
763 *
764 * Yields the value of each struct member in order. If no block is given an
765 * enumerator is returned.
766 *
767 * Customer = Struct.new(:name, :address, :zip)
768 * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
769 * joe.each {|x| puts(x) }
770 *
771 * Produces:
772 *
773 * Joe Smith
774 * 123 Maple, Anytown NC
775 * 12345
776 */
777
778 static VALUE
779 rb_struct_each(VALUE s)
780 {
781 long i;
782
783 RETURN_SIZED_ENUMERATOR(s, 0, 0, struct_enum_size);
784 for (i=0; i<RSTRUCT_LEN(s); i++) {
785 rb_yield(RSTRUCT_GET(s, i));
786 }
787 return s;
788 }
789
790 /*
791 * call-seq:
792 * struct.each_pair {|sym, obj| block } -> struct
793 * struct.each_pair -> enumerator
794 *
795 * Yields the name and value of each struct member in order. If no block is
796 * given an enumerator is returned.
797 *
798 * Customer = Struct.new(:name, :address, :zip)
799 * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
800 * joe.each_pair {|name, value| puts("#{name} => #{value}") }
801 *
802 * Produces:
803 *
804 * name => Joe Smith
805 * address => 123 Maple, Anytown NC
806 * zip => 12345
807 */
808
809 static VALUE
810 rb_struct_each_pair(VALUE s)
811 {
812 VALUE members;
813 long i;
814
815 RETURN_SIZED_ENUMERATOR(s, 0, 0, struct_enum_size);
816 members = rb_struct_members(s);
817 if (rb_block_arity() > 1) {
818 for (i=0; i<RSTRUCT_LEN(s); i++) {
819 VALUE key = rb_ary_entry(members, i);
820 VALUE value = RSTRUCT_GET(s, i);
821 rb_yield_values(2, key, value);
822 }
823 }
824 else {
825 for (i=0; i<RSTRUCT_LEN(s); i++) {
826 VALUE key = rb_ary_entry(members, i);
827 VALUE value = RSTRUCT_GET(s, i);
828 rb_yield(rb_assoc_new(key, value));
829 }
830 }
831 return s;
832 }
833
834 static VALUE
835 inspect_struct(VALUE s, VALUE dummy, int recur)
836 {
837 VALUE cname = rb_class_path(rb_obj_class(s));
838 VALUE members, str = rb_str_new2("#<struct ");
839 long i, len;
840 char first = RSTRING_PTR(cname)[0];
841
842 if (recur || first != '#') {
843 rb_str_append(str, cname);
844 }
845 if (recur) {
846 return rb_str_cat2(str, ":...>");
847 }
848
849 members = rb_struct_members(s);
850 len = RSTRUCT_LEN(s);
851
852 for (i=0; i<len; i++) {
853 VALUE slot;
854 ID id;
855
856 if (i > 0) {
857 rb_str_cat2(str, ", ");
858 }
859 else if (first != '#') {
860 rb_str_cat2(str, " ");
861 }
862 slot = RARRAY_AREF(members, i);
863 id = SYM2ID(slot);
864 if (rb_is_local_id(id) || rb_is_const_id(id)) {
865 rb_str_append(str, rb_id2str(id));
866 }
867 else {
868 rb_str_append(str, rb_inspect(slot));
869 }
870 rb_str_cat2(str, "=");
871 rb_str_append(str, rb_inspect(RSTRUCT_GET(s, i)));
872 }
873 rb_str_cat2(str, ">");
874
875 return str;
876 }
877
878 /*
879 * call-seq:
880 * struct.to_s -> string
881 * struct.inspect -> string
882 *
883 * Returns a description of this struct as a string.
884 */
885
886 static VALUE
887 rb_struct_inspect(VALUE s)
888 {
889 return rb_exec_recursive(inspect_struct, s, 0);
890 }
891
892 /*
893 * call-seq:
894 * struct.to_a -> array
895 * struct.values -> array
896 *
897 * Returns the values for this struct as an Array.
898 *
899 * Customer = Struct.new(:name, :address, :zip)
900 * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
901 * joe.to_a[1] #=> "123 Maple, Anytown NC"
902 */
903
904 static VALUE
905 rb_struct_to_a(VALUE s)
906 {
907 return rb_ary_new4(RSTRUCT_LEN(s), RSTRUCT_CONST_PTR(s));
908 }
909
910 /*
911 * call-seq:
912 * struct.to_h -> hash
913 * struct.to_h {|name, value| block } -> hash
914 *
915 * Returns a Hash containing the names and values for the struct's members.
916 *
917 * If a block is given, the results of the block on each pair of the receiver
918 * will be used as pairs.
919 *
920 * Customer = Struct.new(:name, :address, :zip)
921 * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
922 * joe.to_h[:address] #=> "123 Maple, Anytown NC"
923 * joe.to_h{|name, value| [name.upcase, value.to_s.upcase]}[:ADDRESS]
924 * #=> "123 MAPLE, ANYTOWN NC"
925 */
926
927 static VALUE
928 rb_struct_to_h(VALUE s)
929 {
930 VALUE h = rb_hash_new_with_size(RSTRUCT_LEN(s));
931 VALUE members = rb_struct_members(s);
932 long i;
933 int block_given = rb_block_given_p();
934
935 for (i=0; i<RSTRUCT_LEN(s); i++) {
936 VALUE k = rb_ary_entry(members, i), v = RSTRUCT_GET(s, i);
937 if (block_given)
938 rb_hash_set_pair(h, rb_yield_values(2, k, v));
939 else
940 rb_hash_aset(h, k, v);
941 }
942 return h;
943 }
944
945 static VALUE
946 rb_struct_deconstruct_keys(VALUE s, VALUE keys)
947 {
948 VALUE h;
949 long i;
950
951 if (NIL_P(keys)) {
952 return rb_struct_to_h(s);
953 }
954 if (UNLIKELY(!RB_TYPE_P(keys, T_ARRAY))) {
955 rb_raise(rb_eTypeError,
956 "wrong argument type %"PRIsVALUE" (expected Array or nil)",
957 rb_obj_class(keys));
958
959 }
960 if (RSTRUCT_LEN(s) < RARRAY_LEN(keys)) {
961 return rb_hash_new_with_size(0);
962 }
963 h = rb_hash_new_with_size(RARRAY_LEN(keys));
964 for (i=0; i<RARRAY_LEN(keys); i++) {
965 VALUE key = RARRAY_AREF(keys, i);
966 int i = rb_struct_pos(s, &key);
967 if (i < 0) {
968 return h;
969 }
970 rb_hash_aset(h, key, RSTRUCT_GET(s, i));
971 }
972 return h;
973 }
974
975 /* :nodoc: */
976 VALUE
977 rb_struct_init_copy(VALUE copy, VALUE s)
978 {
979 long i, len;
980
981 if (!OBJ_INIT_COPY(copy, s)) return copy;
982 if (RSTRUCT_LEN(copy) != RSTRUCT_LEN(s)) {
983 rb_raise(rb_eTypeError, "struct size mismatch");
984 }
985
986 for (i=0, len=RSTRUCT_LEN(copy); i<len; i++) {
987 RSTRUCT_SET(copy, i, RSTRUCT_GET(s, i));
988 }
989
990 return copy;
991 }
992
993 static int
994 rb_struct_pos(VALUE s, VALUE *name)
995 {
996 long i;
997 VALUE idx = *name;
998
999 if (RB_TYPE_P(idx, T_SYMBOL)) {
1000 return struct_member_pos(s, idx);
1001 }
1002 else if (RB_TYPE_P(idx, T_STRING)) {
1003 idx = rb_check_symbol(name);
1004 if (NIL_P(idx)) return -1;
1005 return struct_member_pos(s, idx);
1006 }
1007 else {
1008 long len;
1009 i = NUM2LONG(idx);
1010 len = RSTRUCT_LEN(s);
1011 if (i < 0) {
1012 if (i + len < 0) {
1013 *name = LONG2FIX(i);
1014 return -1;
1015 }
1016 i += len;
1017 }
1018 else if (len <= i) {
1019 *name = LONG2FIX(i);
1020 return -1;
1021 }
1022 return (int)i;
1023 }
1024 }
1025
1026 NORETURN(static void invalid_struct_pos(VALUE s, VALUE idx));
1027 static void
1028 invalid_struct_pos(VALUE s, VALUE idx)
1029 {
1030 if (FIXNUM_P(idx)) {
1031 long i = FIX2INT(idx), len = RSTRUCT_LEN(s);
1032 if (i < 0) {
1033 rb_raise(rb_eIndexError, "offset %ld too small for struct(size:%ld)",
1034 i, len);
1035 }
1036 else {
1037 rb_raise(rb_eIndexError, "offset %ld too large for struct(size:%ld)",
1038 i, len);
1039 }
1040 }
1041 else {
1042 rb_name_err_raise("no member '%1$s' in struct", s, idx);
1043 }
1044 }
1045
1046 /*
1047 * call-seq:
1048 * struct[member] -> object
1049 * struct[index] -> object
1050 *
1051 * Attribute Reference---Returns the value of the given struct +member+ or
1052 * the member at the given +index+. Raises NameError if the +member+ does
1053 * not exist and IndexError if the +index+ is out of range.
1054 *
1055 * Customer = Struct.new(:name, :address, :zip)
1056 * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
1057 *
1058 * joe["name"] #=> "Joe Smith"
1059 * joe[:name] #=> "Joe Smith"
1060 * joe[0] #=> "Joe Smith"
1061 */
1062
1063 VALUE
1064 rb_struct_aref(VALUE s, VALUE idx)
1065 {
1066 int i = rb_struct_pos(s, &idx);
1067 if (i < 0) invalid_struct_pos(s, idx);
1068 return RSTRUCT_GET(s, i);
1069 }
1070
1071 /*
1072 * call-seq:
1073 * struct[member] = obj -> obj
1074 * struct[index] = obj -> obj
1075 *
1076 * Attribute Assignment---Sets the value of the given struct +member+ or
1077 * the member at the given +index+. Raises NameError if the +member+ does not
1078 * exist and IndexError if the +index+ is out of range.
1079 *
1080 * Customer = Struct.new(:name, :address, :zip)
1081 * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
1082 *
1083 * joe["name"] = "Luke"
1084 * joe[:zip] = "90210"
1085 *
1086 * joe.name #=> "Luke"
1087 * joe.zip #=> "90210"
1088 */
1089
1090 VALUE
1091 rb_struct_aset(VALUE s, VALUE idx, VALUE val)
1092 {
1093 int i = rb_struct_pos(s, &idx);
1094 if (i < 0) invalid_struct_pos(s, idx);
1095 rb_struct_modify(s);
1096 RSTRUCT_SET(s, i, val);
1097 return val;
1098 }
1099
1100 FUNC_MINIMIZED(VALUE rb_struct_lookup(VALUE s, VALUE idx));
1101 NOINLINE(static VALUE rb_struct_lookup_default(VALUE s, VALUE idx, VALUE notfound));
1102
1103 VALUE
1104 rb_struct_lookup(VALUE s, VALUE idx)
1105 {
1106 return rb_struct_lookup_default(s, idx, Qnil);
1107 }
1108
1109 static VALUE
1110 rb_struct_lookup_default(VALUE s, VALUE idx, VALUE notfound)
1111 {
1112 int i = rb_struct_pos(s, &idx);
1113 if (i < 0) return notfound;
1114 return RSTRUCT_GET(s, i);
1115 }
1116
1117 static VALUE
1118 struct_entry(VALUE s, long n)
1119 {
1120 return rb_struct_aref(s, LONG2NUM(n));
1121 }
1122
1123 /*
1124 * call-seq:
1125 * struct.values_at(selector, ...) -> array
1126 *
1127 * Returns the struct member values for each +selector+ as an Array. A
1128 * +selector+ may be either an Integer offset or a Range of offsets (as in
1129 * Array#values_at).
1130 *
1131 * Customer = Struct.new(:name, :address, :zip)
1132 * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
1133 * joe.values_at(0, 2) #=> ["Joe Smith", 12345]
1134 *
1135 */
1136
1137 static VALUE
1138 rb_struct_values_at(int argc, VALUE *argv, VALUE s)
1139 {
1140 return rb_get_values_at(s, RSTRUCT_LEN(s), argc, argv, struct_entry);
1141 }
1142
1143 /*
1144 * call-seq:
1145 * struct.select {|obj| block } -> array
1146 * struct.select -> enumerator
1147 * struct.filter {|obj| block } -> array
1148 * struct.filter -> enumerator
1149 *
1150 * Yields each member value from the struct to the block and returns an Array
1151 * containing the member values from the +struct+ for which the given block
1152 * returns a true value (equivalent to Enumerable#select).
1153 *
1154 * Lots = Struct.new(:a, :b, :c, :d, :e, :f)
1155 * l = Lots.new(11, 22, 33, 44, 55, 66)
1156 * l.select {|v| v.even? } #=> [22, 44, 66]
1157 *
1158 * Struct#filter is an alias for Struct#select.
1159 */
1160
1161 static VALUE
1162 rb_struct_select(int argc, VALUE *argv, VALUE s)
1163 {
1164 VALUE result;
1165 long i;
1166
1167 rb_check_arity(argc, 0, 0);
1168 RETURN_SIZED_ENUMERATOR(s, 0, 0, struct_enum_size);
1169 result = rb_ary_new();
1170 for (i = 0; i < RSTRUCT_LEN(s); i++) {
1171 if (RTEST(rb_yield(RSTRUCT_GET(s, i)))) {
1172 rb_ary_push(result, RSTRUCT_GET(s, i));
1173 }
1174 }
1175
1176 return result;
1177 }
1178
1179 static VALUE
1180 recursive_equal(VALUE s, VALUE s2, int recur)
1181 {
1182 long i, len;
1183
1184 if (recur) return Qtrue; /* Subtle! */
1185 len = RSTRUCT_LEN(s);
1186 for (i=0; i<len; i++) {
1187 if (!rb_equal(RSTRUCT_GET(s, i), RSTRUCT_GET(s2, i))) return Qfalse;
1188 }
1189 return Qtrue;
1190 }
1191
1192 /*
1193 * call-seq:
1194 * struct == other -> true or false
1195 *
1196 * Equality---Returns +true+ if +other+ has the same struct subclass and has
1197 * equal member values (according to Object#==).
1198 *
1199 * Customer = Struct.new(:name, :address, :zip)
1200 * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
1201 * joejr = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
1202 * jane = Customer.new("Jane Doe", "456 Elm, Anytown NC", 12345)
1203 * joe == joejr #=> true
1204 * joe == jane #=> false
1205 */
1206
1207 static VALUE
1208 rb_struct_equal(VALUE s, VALUE s2)
1209 {
1210 if (s == s2) return Qtrue;
1211 if (!RB_TYPE_P(s2, T_STRUCT)) return Qfalse;
1212 if (rb_obj_class(s) != rb_obj_class(s2)) return Qfalse;
1213 if (RSTRUCT_LEN(s) != RSTRUCT_LEN(s2)) {
1214 rb_bug("inconsistent struct"); /* should never happen */
1215 }
1216
1217 return rb_exec_recursive_paired(recursive_equal, s, s2, s2);
1218 }
1219
1220 /*
1221 * call-seq:
1222 * struct.hash -> integer
1223 *
1224 * Returns a hash value based on this struct's contents.
1225 *
1226 * See also Object#hash.
1227 */
1228
1229 static VALUE
1230 rb_struct_hash(VALUE s)
1231 {
1232 long i, len;
1233 st_index_t h;
1234 VALUE n;
1235
1236 h = rb_hash_start(rb_hash(rb_obj_class(s)));
1237 len = RSTRUCT_LEN(s);
1238 for (i = 0; i < len; i++) {
1239 n = rb_hash(RSTRUCT_GET(s, i));
1240 h = rb_hash_uint(h, NUM2LONG(n));
1241 }
1242 h = rb_hash_end(h);
1243 return ST2FIX(h);
1244 }
1245
1246 static VALUE
1247 recursive_eql(VALUE s, VALUE s2, int recur)
1248 {
1249 long i, len;
1250
1251 if (recur) return Qtrue; /* Subtle! */
1252 len = RSTRUCT_LEN(s);
1253 for (i=0; i<len; i++) {
1254 if (!rb_eql(RSTRUCT_GET(s, i), RSTRUCT_GET(s2, i))) return Qfalse;
1255 }
1256 return Qtrue;
1257 }
1258
1259 /*
1260 * call-seq:
1261 * struct.eql?(other) -> true or false
1262 *
1263 * Hash equality---+other+ and +struct+ refer to the same hash key if they
1264 * have the same struct subclass and have equal member values (according to
1265 * Object#eql?).
1266 */
1267
1268 static VALUE
1269 rb_struct_eql(VALUE s, VALUE s2)
1270 {
1271 if (s == s2) return Qtrue;
1272 if (!RB_TYPE_P(s2, T_STRUCT)) return Qfalse;
1273 if (rb_obj_class(s) != rb_obj_class(s2)) return Qfalse;
1274 if (RSTRUCT_LEN(s) != RSTRUCT_LEN(s2)) {
1275 rb_bug("inconsistent struct"); /* should never happen */
1276 }
1277
1278 return rb_exec_recursive_paired(recursive_eql, s, s2, s2);
1279 }
1280
1281 /*
1282 * call-seq:
1283 * struct.length -> integer
1284 * struct.size -> integer
1285 *
1286 * Returns the number of struct members.
1287 *
1288 * Customer = Struct.new(:name, :address, :zip)
1289 * joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
1290 * joe.length #=> 3
1291 */
1292
1293 VALUE
1294 rb_struct_size(VALUE s)
1295 {
1296 return LONG2FIX(RSTRUCT_LEN(s));
1297 }
1298
1299 /*
1300 * call-seq:
1301 * struct.dig(key, ...) -> object
1302 *
1303 * Extracts the nested value specified by the sequence of +key+
1304 * objects by calling +dig+ at each step, returning +nil+ if any
1305 * intermediate step is +nil+.
1306 *
1307 * Foo = Struct.new(:a)
1308 * f = Foo.new(Foo.new({b: [1, 2, 3]}))
1309 *
1310 * f.dig(:a, :a, :b, 0) # => 1
1311 * f.dig(:b, 0) # => nil
1312 * f.dig(:a, :a, :b, :c) # TypeError: no implicit conversion of Symbol into Integer
1313 */
1314
1315 static VALUE
1316 rb_struct_dig(int argc, VALUE *argv, VALUE self)
1317 {
1318 rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
1319 self = rb_struct_lookup(self, *argv);
1320 if (!--argc) return self;
1321 ++argv;
1322 return rb_obj_dig(argc, argv, self, Qnil);
1323 }
1324
1325 /*
1326 * Document-class: Struct
1327 *
1328 * A Struct is a convenient way to bundle a number of attributes together,
1329 * using accessor methods, without having to write an explicit class.
1330 *
1331 * The Struct class generates new subclasses that hold a set of members and
1332 * their values. For each member a reader and writer method is created
1333 * similar to Module#attr_accessor.
1334 *
1335 * Customer = Struct.new(:name, :address) do
1336 * def greeting
1337 * "Hello #{name}!"
1338 * end
1339 * end
1340 *
1341 * dave = Customer.new("Dave", "123 Main")
1342 * dave.name #=> "Dave"
1343 * dave.greeting #=> "Hello Dave!"
1344 *
1345 * See Struct::new for further examples of creating struct subclasses and
1346 * instances.
1347 *
1348 * In the method descriptions that follow, a "member" parameter refers to a
1349 * struct member which is either a quoted string (<code>"name"</code>) or a
1350 * Symbol (<code>:name</code>).
1351 */
1352 void
1353 InitVM_Struct(void)
1354 {
1355 rb_cStruct = rb_define_class("Struct", rb_cObject);
1356 rb_include_module(rb_cStruct, rb_mEnumerable);
1357
1358 rb_undef_alloc_func(rb_cStruct);
1359 rb_define_singleton_method(rb_cStruct, "new", rb_struct_s_def, -1);
1360
1361 rb_define_method(rb_cStruct, "initialize", rb_struct_initialize_m, -1);
1362 rb_define_method(rb_cStruct, "initialize_copy", rb_struct_init_copy, 1);
1363
1364 rb_define_method(rb_cStruct, "==", rb_struct_equal, 1);
1365 rb_define_method(rb_cStruct, "eql?", rb_struct_eql, 1);
1366 rb_define_method(rb_cStruct, "hash", rb_struct_hash, 0);
1367
1368 rb_define_method(rb_cStruct, "inspect", rb_struct_inspect, 0);
1369 rb_define_alias(rb_cStruct, "to_s", "inspect");
1370 rb_define_method(rb_cStruct, "to_a", rb_struct_to_a, 0);
1371 rb_define_method(rb_cStruct, "to_h", rb_struct_to_h, 0);
1372 rb_define_method(rb_cStruct, "values", rb_struct_to_a, 0);
1373 rb_define_method(rb_cStruct, "size", rb_struct_size, 0);
1374 rb_define_method(rb_cStruct, "length", rb_struct_size, 0);
1375
1376 rb_define_method(rb_cStruct, "each", rb_struct_each, 0);
1377 rb_define_method(rb_cStruct, "each_pair", rb_struct_each_pair, 0);
1378 rb_define_method(rb_cStruct, "[]", rb_struct_aref, 1);
1379 rb_define_method(rb_cStruct, "[]=", rb_struct_aset, 2);
1380 rb_define_method(rb_cStruct, "select", rb_struct_select, -1);
1381 rb_define_method(rb_cStruct, "filter", rb_struct_select, -1);
1382 rb_define_method(rb_cStruct, "values_at", rb_struct_values_at, -1);
1383
1384 rb_define_method(rb_cStruct, "members", rb_struct_members_m, 0);
1385 rb_define_method(rb_cStruct, "dig", rb_struct_dig, -1);
1386
1387 rb_define_method(rb_cStruct, "deconstruct", rb_struct_to_a, 0);
1388 rb_define_method(rb_cStruct, "deconstruct_keys", rb_struct_deconstruct_keys, 1);
1389 }
1390
1391 #undef rb_intern
1392 void
1393 Init_Struct(void)
1394 {
1395 id_members = rb_intern("__members__");
1396 id_back_members = rb_intern("__members_back__");
1397 id_keyword_init = rb_intern("__keyword_init__");
1398
1399 InitVM(Struct);
1400 }
rb_yield_values
#define rb_yield_values(argc,...)
Definition: rb_mjit_min_header-2.7.0.h:6584
rb_is_const_name
int rb_is_const_name(VALUE name)
Definition: symbol.c:1050
rb_check_symbol
VALUE rb_check_symbol(volatile VALUE *namep)
Definition: symbol.c:952
rb_get_kwargs
int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *values)
Definition: class.c:1886
UNLIKELY
#define UNLIKELY(x)
Definition: ffi_common.h:126
ID
unsigned long ID
Definition: ruby.h:103
rb_define_class
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:649
Init_Struct
void Init_Struct(void)
Definition: struct.c:1393
rb_define_method_id
void rb_define_method_id(VALUE klass, ID mid, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1542
rb_is_const_id
int rb_is_const_id(ID id)
Definition: symbol.c:854
rb_method_for_self_aref
const rb_iseq_t * rb_method_for_self_aref(VALUE name, VALUE arg, rb_insn_func_t func)
Definition: compile.c:9476
rb_block_arity
int rb_block_arity(void)
Definition: proc.c:1144
rb_include_module
void rb_include_module(VALUE klass, VALUE module)
Definition: class.c:869
rb_struct_init_copy
VALUE rb_struct_init_copy(VALUE copy, VALUE s)
Definition: struct.c:977
rb_mod_remove_const
VALUE rb_mod_remove_const(VALUE, VALUE)
Definition: variable.c:2479
rb_assoc_new
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Definition: array.c:896
rb_str_new2
#define rb_str_new2
Definition: intern.h:903
rb_class_inherited
MJIT_FUNC_EXPORTED VALUE rb_class_inherited(VALUE super, VALUE klass)
Calls Class::inherited.
Definition: class.c:623
AREF_HASH_UNIT
@ AREF_HASH_UNIT
Definition: struct.c:28
FUNC_MINIMIZED
FUNC_MINIMIZED(VALUE rb_struct_lookup(VALUE s, VALUE idx))
id
const int id
Definition: nkf.c:209
RB_PASS_CALLED_KEYWORDS
#define RB_PASS_CALLED_KEYWORDS
Definition: ruby.h:1980
FIX2INT
#define FIX2INT(x)
Definition: ruby.h:717
rb_iseq_struct
Definition: vm_core.h:456
va_arg
#define va_arg(v, l)
Definition: rb_mjit_min_header-2.7.0.h:3980
rb_ident_hash_new
VALUE rb_ident_hash_new(void)
Definition: hash.c:4203
rb_struct_alloc
VALUE rb_struct_alloc(VALUE klass, VALUE values)
Definition: struct.c:727
rb_struct_members
VALUE rb_struct_members(VALUE s)
Definition: struct.c:72
rb_warn
void rb_warn(const char *fmt,...)
Definition: error.c:313
rb_struct_aset
VALUE rb_struct_aset(VALUE s, VALUE idx, VALUE val)
Definition: struct.c:1091
rb_block_given_p
int rb_block_given_p(void)
Determines if the current method is given a block.
Definition: eval.c:897
rb_add_method_iseq
void rb_add_method_iseq(VALUE klass, ID mid, const rb_iseq_t *iseq, rb_cref_t *cref, rb_method_visibility_t visi)
Definition: vm_method.c:684
RBASIC_CLEAR_CLASS
#define RBASIC_CLEAR_CLASS(obj)
Definition: internal.h:1981
rb_struct_lookup
VALUE rb_struct_lookup(VALUE s, VALUE idx)
Definition: struct.c:1104
INT2FIX
#define INT2FIX(i)
Definition: ruby.h:263
rb_to_symbol
VALUE rb_to_symbol(VALUE name)
Definition: string.c:11156
rb_vm_opt_struct_aset
rb_control_frame_t *FUNC_FASTCALL() rb_vm_opt_struct_aset(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp)
Definition: vm_insnhelper.c:3474
RSTRING_PTR
#define RSTRING_PTR(str)
Definition: ruby.h:1009
NUM2LONG
#define NUM2LONG(x)
Definition: ruby.h:679
rb_struct_new
VALUE rb_struct_new(VALUE klass,...)
Definition: struct.c:733
rb_attr_get
VALUE rb_attr_get(VALUE, ID)
Definition: variable.c:1084
rb_class_new_instance_kw
VALUE rb_class_new_instance_kw(int, const VALUE *, VALUE, int)
Definition: object.c:1931
rb_equal
VALUE rb_equal(VALUE, VALUE)
Same as Object#===, case equality.
Definition: object.c:124
VALUE
unsigned long VALUE
Definition: ruby.h:102
rb_id_attrset
ID rb_id_attrset(ID)
Definition: symbol.c:98
rb_eArgError
VALUE rb_eArgError
Definition: error.c:923
rb_intern
#define rb_intern(str)
rb_ary_store
void rb_ary_store(VALUE ary, long idx, VALUE val)
Definition: array.c:1079
RB_TYPE_P
#define RB_TYPE_P(obj, type)
Definition: ruby.h:560
RARRAY_PTR
#define RARRAY_PTR(a)
Definition: ruby.h:1110
int
__inline__ int
Definition: rb_mjit_min_header-2.7.0.h:2839
id.h
rb_inspect
VALUE rb_inspect(VALUE)
Convenient wrapper of Object::inspect.
Definition: object.c:551
rb_eIndexError
VALUE rb_eIndexError
Definition: error.c:924
rb_str_cat2
#define rb_str_cat2
Definition: intern.h:912
rb_get_values_at
VALUE rb_get_values_at(VALUE obj, long olen, int argc, const VALUE *argv, VALUE(*func)(VALUE, long))
Definition: array.c:3106
rb_is_attrset_sym
int rb_is_attrset_sym(VALUE sym)
Definition: symbol.c:902
Qundef
#define Qundef
Definition: ruby.h:470
rb_define_singleton_method
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
Definition: class.c:1755
struct_hash_set_arg
Definition: struct.c:600
rb_define_method
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1551
rb_long2int
#define rb_long2int(n)
Definition: ruby.h:350
rb_hash_keys
MJIT_FUNC_EXPORTED VALUE rb_hash_keys(VALUE hash)
Definition: hash.c:3334
ptr
struct RIMemo * ptr
Definition: debug.c:74
RSTRUCT_TRANSIENT_SET
#define RSTRUCT_TRANSIENT_SET(st)
Definition: internal.h:934
Qfalse
#define Qfalse
Definition: ruby.h:467
rb_struct_s_keyword_init
VALUE rb_struct_s_keyword_init(VALUE klass)
Definition: struct.c:52
RETURN_SIZED_ENUMERATOR
#define RETURN_SIZED_ENUMERATOR(obj, argc, argv, size_fn)
Definition: intern.h:271
rb_id2str
#define rb_id2str(id)
Definition: vm_backtrace.c:30
NULL
#define NULL
Definition: _sdbm.c:101
FL_WB_PROTECTED
#define FL_WB_PROTECTED
Definition: ruby.h:1279
rb_struct_define
VALUE rb_struct_define(const char *name,...)
Definition: struct.c:434
PRIsVALUE
#define PRIsVALUE
Definition: ruby.h:166
RSTRUCT_EMBED_LEN_MAX
#define RSTRUCT_EMBED_LEN_MAX
Definition: internal.h:919
st_insert
int st_insert(st_table *tab, st_data_t key, st_data_t value)
Definition: st.c:1171
ID2SYM
#define ID2SYM(x)
Definition: ruby.h:414
T_SYMBOL
#define T_SYMBOL
Definition: ruby.h:540
struct_hash_set_arg::unknown_keywords
VALUE unknown_keywords
Definition: struct.c:602
RString::ary
char ary[RSTRING_EMBED_LEN_MAX+1]
Definition: ruby.h:999
rb_define_alias
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
Definition: class.c:1800
rb_check_arity
#define rb_check_arity
Definition: intern.h:347
rb_eql
int rb_eql(VALUE, VALUE)
Determines if obj1 and obj2 are equal in terms of Object::eql?.
Definition: object.c:147
rb_struct_define_without_accessor_under
VALUE rb_struct_define_without_accessor_under(VALUE outer, const char *class_name, VALUE super, rb_alloc_func_t alloc,...)
Definition: struct.c:408
InitVM
#define InitVM(ext)
Definition: ruby.h:2329
rb_hash_new_with_size
MJIT_FUNC_EXPORTED VALUE rb_hash_new_with_size(st_index_t size)
Definition: hash.c:1507
struct_hash_set_arg::self
VALUE self
Definition: struct.c:601
RARRAY_LENINT
#define RARRAY_LENINT(ary)
Definition: ruby.h:1071
v
int VALUE v
Definition: rb_mjit_min_header-2.7.0.h:12332
ALLOC_N
#define ALLOC_N(type, n)
Definition: ruby.h:1663
UNLIMITED_ARGUMENTS
#define UNLIMITED_ARGUMENTS
Definition: intern.h:57
rb_raise
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2669
rb_ary_entry
VALUE rb_ary_entry(VALUE ary, long offset)
Definition: array.c:1512
LONG2NUM
#define LONG2NUM(x)
Definition: ruby.h:1644
obj
const VALUE VALUE obj
Definition: rb_mjit_min_header-2.7.0.h:5742
NORETURN
NORETURN(static void invalid_struct_pos(VALUE s, VALUE idx))
rb_obj_class
VALUE rb_obj_class(VALUE)
Equivalent to Object#class in Ruby.
Definition: object.c:217
st_clear
void st_clear(st_table *tab)
Definition: st.c:698
rb_check_frozen
#define rb_check_frozen(obj)
Definition: intern.h:319
RSTRUCT_TRANSIENT_P
#define RSTRUCT_TRANSIENT_P(st)
Definition: internal.h:933
rb_obj_dig
VALUE rb_obj_dig(int argc, VALUE *argv, VALUE self, VALUE notfound)
Definition: object.c:3791
rb_insn_func_t
rb_control_frame_t *FUNC_FASTCALL rb_insn_func_t(rb_execution_context_t *, rb_control_frame_t *)
Definition: vm_core.h:1143
RGENGC_WB_PROTECTED_STRUCT
#define RGENGC_WB_PROTECTED_STRUCT
Definition: ruby.h:808
RSTRUCT_EMBED_LEN_MASK
#define RSTRUCT_EMBED_LEN_MASK
Definition: internal.h:920
rb_ary_tmp_new
VALUE rb_ary_tmp_new(long capa)
Definition: array.c:768
i
uint32_t i
Definition: rb_mjit_min_header-2.7.0.h:5464
sym
#define sym(x)
Definition: date_core.c:3716
mask
enum @11::@13::@14 mask
rb_to_id
ID rb_to_id(VALUE)
Definition: string.c:11146
rb_struct_transient_heap_evacuate
void rb_struct_transient_heap_evacuate(VALUE obj, int promote)
Definition: struct.c:684
rb_struct_aref
VALUE rb_struct_aref(VALUE s, VALUE idx)
Definition: struct.c:1064
rb_ary_push
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:1195
st_index_t
st_data_t st_index_t
Definition: st.h:50
rb_struct_alloc_noinit
VALUE rb_struct_alloc_noinit(VALUE klass)
Definition: struct.c:352
va_end
#define va_end(v)
Definition: rb_mjit_min_header-2.7.0.h:3979
rb_hash_start
st_index_t rb_hash_start(st_index_t)
Definition: random.c:1434
transient_heap.h
vm_core.h
rb_eTypeError
VALUE rb_eTypeError
Definition: error.c:922
RSTRUCT_EMBED_LEN_SHIFT
#define RSTRUCT_EMBED_LEN_SHIFT
Definition: internal.h:921
RSTRUCT_TRANSIENT_FLAG
@ RSTRUCT_TRANSIENT_FLAG
Definition: internal.h:927
RARRAY_AREF
#define RARRAY_AREF(a, i)
Definition: ruby.h:1101
rb_control_frame_struct
Definition: vm_core.h:760
rb_transient_heap_alloc
void * rb_transient_heap_alloc(VALUE obj, size_t req_size)
Definition: transient_heap.c:359
rb_struct_getmember
VALUE rb_struct_getmember(VALUE obj, ID id)
Definition: struct.c:211
rb_mem_clear
void rb_mem_clear(VALUE *mem, long size)
Definition: array.c:243
size
int size
Definition: encoding.c:58
FIXNUM_P
#define FIXNUM_P(f)
Definition: ruby.h:396
RCLASS_SUPER
#define RCLASS_SUPER(c)
Definition: classext.h:16
rb_struct_size
VALUE rb_struct_size(VALUE s)
Definition: struct.c:1294
METHOD_VISI_PUBLIC
@ METHOD_VISI_PUBLIC
Definition: method.h:28
rb_hash_foreach
void rb_hash_foreach(VALUE hash, rb_foreach_func *func, VALUE farg)
Definition: hash.c:1461
list
struct rb_encoding_entry * list
Definition: encoding.c:56
ID_SCOPE_SHIFT
#define ID_SCOPE_SHIFT
Definition: id.h:31
key
key
Definition: openssl_missing.h:181
T_HASH
#define T_HASH
Definition: ruby.h:531
rb_method_for_self_aset
const rb_iseq_t * rb_method_for_self_aset(VALUE name, VALUE arg, rb_insn_func_t func)
Definition: compile.c:9485
RSTRUCT_SET
#define RSTRUCT_SET(st, idx, v)
Definition: ruby.h:1257
RARRAY_CONST_PTR
#define RARRAY_CONST_PTR(a)
Definition: ruby.h:1072
rb_hash_set_pair
VALUE rb_hash_set_pair(VALUE hash, VALUE arg)
Definition: hash.c:3257
rb_struct_define_under
VALUE rb_struct_define_under(VALUE outer, const char *name,...)
Definition: struct.c:449
rb_str_to_str
VALUE rb_str_to_str(VALUE)
Definition: string.c:1382
rb_class_new
VALUE rb_class_new(VALUE super)
Creates a new class.
Definition: class.c:241
RARRAY_LEN
#define RARRAY_LEN(a)
Definition: ruby.h:1070
rb_sym_intern_ascii_cstr
#define rb_sym_intern_ascii_cstr(ptr)
Definition: rb_mjit_min_header-2.7.0.h:7758
RSTRUCT_LEN
#define RSTRUCT_LEN(st)
Definition: ruby.h:1255
rb_ary_new4
#define rb_ary_new4
Definition: intern.h:105
rb_cObject
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:2010
n
const char size_t n
Definition: rb_mjit_min_header-2.7.0.h:5456
rb_str_cat_cstr
#define rb_str_cat_cstr(str, ptr)
Definition: rb_mjit_min_header-2.7.0.h:6126
FL_UNSET_RAW
#define FL_UNSET_RAW(x, f)
Definition: ruby.h:1360
rb_str_append
VALUE rb_str_append(VALUE, VALUE)
Definition: string.c:2965
rb_bug
void rb_bug(const char *fmt,...)
Definition: error.c:634
internal.h
OBJ_INIT_COPY
#define OBJ_INIT_COPY(obj, orig)
Definition: intern.h:331
T_ARRAY
#define T_ARRAY
Definition: ruby.h:530
arg
VALUE arg
Definition: rb_mjit_min_header-2.7.0.h:5601
argv
char ** argv
Definition: ruby.c:223
ST_CONTINUE
@ ST_CONTINUE
Definition: st.h:99
RSTRUCT_TRANSIENT_UNSET
#define RSTRUCT_TRANSIENT_UNSET(st)
Definition: internal.h:935
rb_hash_uint
#define rb_hash_uint(h, i)
Definition: intern.h:815
klass
VALUE klass
Definition: rb_mjit_min_header-2.7.0.h:13254
rb_ary_join
VALUE rb_ary_join(VALUE ary, VALUE sep)
Definition: array.c:2347
rb_struct_define_without_accessor
VALUE rb_struct_define_without_accessor(const char *class_name, VALUE super, rb_alloc_func_t alloc,...)
Definition: struct.c:421
rb_hash
VALUE rb_hash(VALUE obj)
Definition: hash.c:129
str
char str[HTML_ESCAPE_MAX_LEN+1]
Definition: escape.c:18
rb_hash_end
#define rb_hash_end(h)
Definition: intern.h:816
FUNC_FASTCALL
#define FUNC_FASTCALL(x)
Definition: vm_core.h:1139
keys
const rb_iseq_t const char const VALUE keys
Definition: rb_mjit_min_header-2.7.0.h:13506
MEMCPY
#define MEMCPY(p1, p2, type, n)
Definition: ruby.h:1753
rb_hash_aset
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
Definition: hash.c:2779
rb_alloc_func_t
VALUE(* rb_alloc_func_t)(VALUE)
Definition: intern.h:427
NIL_P
#define NIL_P(v)
Definition: ruby.h:482
OBJ_FREEZE_RAW
#define OBJ_FREEZE_RAW(x)
Definition: ruby.h:1376
argc
int argc
Definition: ruby.c:222
st
enum ruby_tag_type st
Definition: rb_mjit_min_header-2.7.0.h:11111
rb_exec_recursive
VALUE rb_exec_recursive(VALUE(*)(VALUE, VALUE, int), VALUE, VALUE)
Definition: thread.c:5075
recur
#define recur(fmt)
Definition: date_strptime.c:152
rb_is_local_id
int rb_is_local_id(ID id)
Definition: symbol.c:884
rb_make_metaclass
VALUE rb_make_metaclass(VALUE obj, VALUE unused)
Definition: class.c:580
s2
const char * s2
Definition: rb_mjit_min_header-2.7.0.h:5454
RSTRUCT_GET
#define RSTRUCT_GET(st, idx)
Definition: ruby.h:1258
RBASIC
#define RBASIC(obj)
Definition: ruby.h:1267
Qtrue
#define Qtrue
Definition: ruby.h:468
rb_class_name
VALUE rb_class_name(VALUE)
Definition: variable.c:274
len
uint8_t len
Definition: escape.c:17
rb_class_path
VALUE rb_class_path(VALUE)
Definition: variable.c:153
SYMBOL_P
#define SYMBOL_P(x)
Definition: ruby.h:413
RStruct
Definition: internal.h:942
rb_class_new_instance
VALUE rb_class_new_instance(int, const VALUE *, VALUE)
Allocates and initializes an instance of klass.
Definition: object.c:1955
rb_ary_dup
VALUE rb_ary_dup(VALUE ary)
Definition: array.c:2238
rb_struct_initialize
VALUE rb_struct_initialize(VALUE self, VALUE values)
Definition: struct.c:662
rb_exec_recursive_paired
VALUE rb_exec_recursive_paired(VALUE(*)(VALUE, VALUE, int), VALUE, VALUE, VALUE)
Definition: thread.c:5086
LONG2FIX
#define LONG2FIX(i)
Definition: ruby.h:265
va_start
#define va_start(v, l)
Definition: rb_mjit_min_header-2.7.0.h:3978
rb_ivar_set
VALUE rb_ivar_set(VALUE, ID, VALUE)
Definition: variable.c:1300
T_STRING
#define T_STRING
Definition: ruby.h:528
rb_define_class_under
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:698
va_list
__gnuc_va_list va_list
Definition: rb_mjit_min_header-2.7.0.h:836
rb_const_defined_at
int rb_const_defined_at(VALUE, ID)
Definition: variable.c:2688
rb_cStruct
VALUE rb_cStruct
Definition: struct.c:26
RHASH_TBL
#define RHASH_TBL(h)
Definition: ruby.h:1127
iseq
const rb_iseq_t * iseq
Definition: rb_mjit_min_header-2.7.0.h:13504
rb_yield
VALUE rb_yield(VALUE)
Definition: vm_eval.c:1237
ST2FIX
#define ST2FIX(h)
Definition: ruby_missing.h:21
rb_struct_s_members
VALUE rb_struct_s_members(VALUE klass)
Definition: struct.c:58
rb_ary_new
VALUE rb_ary_new(void)
Definition: array.c:723
N_REF_FUNC
#define N_REF_FUNC
Definition: struct.c:234
NEWOBJ_OF
#define NEWOBJ_OF(obj, type, klass, flags)
Definition: ruby.h:785
T_STRUCT
#define T_STRUCT
Definition: ruby.h:532
Qnil
#define Qnil
Definition: ruby.h:469
rb_define_class_id_under
VALUE rb_define_class_id_under(VALUE outer, ID id, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:721
rb_mEnumerable
VALUE rb_mEnumerable
Definition: enum.c:20
h
size_t st_index_t h
Definition: rb_mjit_min_header-2.7.0.h:5462
rb_name_err_raise
#define rb_name_err_raise(mesg, recv, name)
Definition: internal.h:1574
rb_undef_alloc_func
void rb_undef_alloc_func(VALUE)
Definition: vm_method.c:722
numberof
#define numberof(array)
Definition: etc.c:618
UNREACHABLE_RETURN
#define UNREACHABLE_RETURN(val)
Definition: ruby.h:59
st_table
Definition: st.h:79
rb_mod_module_eval
VALUE rb_mod_module_eval(int, const VALUE *, VALUE)
Definition: vm_eval.c:2067
rb_define_alloc_func
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
RTEST
#define RTEST(v)
Definition: ruby.h:481
SYM2ID
#define SYM2ID(x)
Definition: ruby.h:415
rb_vm_opt_struct_aref
rb_control_frame_t *FUNC_FASTCALL() rb_vm_opt_struct_aref(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp)
Definition: vm_insnhelper.c:3467
RSTRUCT_CONST_PTR
#define RSTRUCT_CONST_PTR(st)
Definition: internal.h:962
RSTRUCT
#define RSTRUCT(obj)
Definition: internal.h:966
InitVM_Struct
void InitVM_Struct(void)
Definition: struct.c:1353
AREF_HASH_THRESHOLD
@ AREF_HASH_THRESHOLD
Definition: struct.c:29
NOINLINE
NOINLINE(static VALUE rb_struct_lookup_default(VALUE s, VALUE idx, VALUE notfound))
name
const char * name
Definition: nkf.c:208
rb_execution_context_struct
Definition: vm_core.h:843