2 ** variable.c - mruby variables
4 ** See Copyright Notice in mruby.h
8 #include <mruby/array.h>
9 #include <mruby/class.h>
10 #include <mruby/proc.h>
11 #include <mruby/string.h>
12 #include <mruby/variable.h>
13 #include <mruby/internal.h>
14 #include <mruby/presym.h>
16 /* Instance variable table structure */
17 typedef struct iv_tbl
{
23 #define IV_DELETED (1UL<<31)
24 #define IV_KEY_P(k) (((k)&~((uint32_t)IV_DELETED))!=0)
26 /* Creates the instance variable table. */
28 iv_new(mrb_state
*mrb
)
32 t
= (iv_tbl
*)mrb_malloc(mrb
, sizeof(iv_tbl
));
40 static void iv_put(mrb_state
*mrb
, iv_tbl
*t
, mrb_sym sym
, mrb_value val
);
43 iv_rehash(mrb_state
*mrb
, iv_tbl
*t
)
45 int old_alloc
= t
->alloc
;
46 int new_alloc
= old_alloc
> 0 ? old_alloc
<< 1 : 4;
47 mrb_value
*old_ptr
= t
->ptr
;
49 t
->ptr
= (mrb_value
*)mrb_calloc(mrb
, sizeof(mrb_value
)+sizeof(mrb_sym
), new_alloc
);
52 if (old_alloc
== 0) return;
54 mrb_sym
*keys
= (mrb_sym
*)&old_ptr
[old_alloc
];
55 mrb_value
*vals
= old_ptr
;
56 for (int i
= 0; i
< old_alloc
; i
++) {
57 if (IV_KEY_P(keys
[i
])) {
58 iv_put(mrb
, t
, keys
[i
], vals
[i
]);
61 mrb_free(mrb
, old_ptr
);
64 /* Set the value for the symbol in the instance variable table. */
66 iv_put(mrb_state
*mrb
, iv_tbl
*t
, mrb_sym sym
, mrb_value val
)
68 int hash
, pos
, start
, dpos
= -1;
74 mrb_sym
*keys
= (mrb_sym
*)&t
->ptr
[t
->alloc
];
75 mrb_value
*vals
= t
->ptr
;
76 hash
= mrb_int_hash_func(mrb
, sym
);
77 start
= pos
= hash
& (t
->alloc
-1);
79 mrb_sym key
= keys
[pos
];
84 else if (key
== IV_EMPTY
) {
90 else if (key
== IV_DELETED
&& dpos
< 0) {
93 pos
= (pos
+1) & (t
->alloc
-1);
94 if (pos
== start
) { /* not found */
103 keys
= (mrb_sym
*)&t
->ptr
[t
->alloc
];
105 start
= pos
= hash
& (t
->alloc
-1);
110 /* Get a value for a symbol from the instance variable table. */
112 iv_get(mrb_state
*mrb
, iv_tbl
*t
, mrb_sym sym
, mrb_value
*vp
)
114 int hash
, pos
, start
;
116 if (t
== NULL
) return FALSE
;
117 if (t
->alloc
== 0) return FALSE
;
118 if (t
->size
== 0) return FALSE
;
120 mrb_sym
*keys
= (mrb_sym
*)&t
->ptr
[t
->alloc
];
121 mrb_value
*vals
= t
->ptr
;
122 hash
= mrb_int_hash_func(mrb
, sym
);
123 start
= pos
= hash
& (t
->alloc
-1);
125 mrb_sym key
= keys
[pos
];
127 if (vp
) *vp
= vals
[pos
];
130 else if (key
== IV_EMPTY
) {
133 pos
= (pos
+1) & (t
->alloc
-1);
134 if (pos
== start
) { /* not found */
140 /* Deletes the value for the symbol from the instance variable table. */
142 iv_del(mrb_state
*mrb
, iv_tbl
*t
, mrb_sym sym
, mrb_value
*vp
)
144 int hash
, pos
, start
;
146 if (t
== NULL
) return FALSE
;
147 if (t
->alloc
== 0) return FALSE
;
148 if (t
->size
== 0) return FALSE
;
150 mrb_sym
*keys
= (mrb_sym
*)&t
->ptr
[t
->alloc
];
151 mrb_value
*vals
= t
->ptr
;
152 hash
= mrb_int_hash_func(mrb
, sym
);
153 start
= pos
= hash
& (t
->alloc
-1);
155 mrb_sym key
= keys
[pos
];
157 if (vp
) *vp
= vals
[pos
];
159 keys
[pos
] = IV_DELETED
;
162 else if (key
== IV_EMPTY
) {
165 pos
= (pos
+1) & (t
->alloc
-1);
166 if (pos
== start
) { /* not found */
172 /* Iterates over the instance variable table. */
174 iv_foreach(mrb_state
*mrb
, iv_tbl
*t
, mrb_iv_foreach_func
*func
, void *p
)
176 if (t
== NULL
) return;
177 if (t
->alloc
== 0) return;
178 if (t
->size
== 0) return;
180 mrb_sym
*keys
= (mrb_sym
*)&t
->ptr
[t
->alloc
];
181 mrb_value
*vals
= t
->ptr
;
182 for (int i
=0; i
<t
->alloc
; i
++) {
183 if (IV_KEY_P(keys
[i
])) {
184 if ((*func
)(mrb
, keys
[i
], vals
[i
], p
) != 0) {
192 /* Get the size of the instance variable table. */
193 /* Size is approximated by the allocated table size. */
195 iv_size(mrb_state
*mrb
, iv_tbl
*t
)
197 if (t
== NULL
) return 0;
198 return (size_t)t
->size
;
201 /* Copy the instance variable table. */
203 iv_copy(mrb_state
*mrb
, iv_tbl
*t
)
207 if (t
== NULL
) return NULL
;
208 if (t
->alloc
== 0) return NULL
;
209 if (t
->size
== 0) return NULL
;
211 mrb_sym
*keys
= (mrb_sym
*)&t
->ptr
[t
->alloc
];
212 mrb_value
*vals
= t
->ptr
;
214 for (int i
=0; i
<t
->alloc
; i
++) {
215 if (IV_KEY_P(keys
[i
])) {
216 iv_put(mrb
, t2
, keys
[i
], vals
[i
]);
222 /* Free memory of the instance variable table. */
224 iv_free(mrb_state
*mrb
, iv_tbl
*t
)
226 mrb_free(mrb
, t
->ptr
);
231 iv_mark_i(mrb_state
*mrb
, mrb_sym sym
, mrb_value v
, void *p
)
233 mrb_gc_mark_value(mrb
, v
);
238 mark_tbl(mrb_state
*mrb
, iv_tbl
*t
)
240 iv_foreach(mrb
, t
, iv_mark_i
, 0);
244 mrb_gc_mark_gv(mrb_state
*mrb
)
246 mark_tbl(mrb
, mrb
->globals
);
250 mrb_gc_free_gv(mrb_state
*mrb
)
253 iv_free(mrb
, mrb
->globals
);
257 mrb_gc_mark_iv(mrb_state
*mrb
, struct RObject
*obj
)
259 mark_tbl(mrb
, obj
->iv
);
260 return iv_size(mrb
, obj
->iv
);
264 mrb_gc_free_iv(mrb_state
*mrb
, struct RObject
*obj
)
267 iv_free(mrb
, obj
->iv
);
272 mrb_vm_special_get(mrb_state
*mrb
, mrb_sym i
)
274 return mrb_fixnum_value(0);
278 mrb_vm_special_set(mrb_state
*mrb
, mrb_sym i
, mrb_value v
)
283 obj_iv_p(mrb_value obj
)
285 switch (mrb_type(obj
)) {
292 case MRB_TT_EXCEPTION
:
300 class_iv_ptr(struct RClass
*c
)
302 return c
->tt
== MRB_TT_ICLASS
? c
->c
->iv
: c
->iv
;
306 mrb_obj_iv_get(mrb_state
*mrb
, struct RObject
*obj
, mrb_sym sym
)
310 if (obj
->iv
&& iv_get(mrb
, obj
->iv
, sym
, &v
))
312 return mrb_nil_value();
316 mrb_iv_get(mrb_state
*mrb
, mrb_value obj
, mrb_sym sym
)
319 return mrb_obj_iv_get(mrb
, mrb_obj_ptr(obj
), sym
);
321 return mrb_nil_value();
324 static inline mrb_bool
325 namespace_p(enum mrb_vtype tt
)
327 return tt
== MRB_TT_CLASS
|| tt
== MRB_TT_MODULE
? TRUE
: FALSE
;
331 assign_class_name(mrb_state
*mrb
, struct RObject
*obj
, mrb_sym sym
, mrb_value v
)
333 if (namespace_p(mrb_type(v
))) {
334 struct RObject
*c
= mrb_obj_ptr(v
);
335 if (obj
!= c
&& ISUPPER(mrb_sym_name_len(mrb
, sym
, NULL
)[0])) {
336 mrb_sym id_classname
= MRB_SYM(__classname__
);
337 mrb_value o
= mrb_obj_iv_get(mrb
, c
, id_classname
);
340 mrb_sym id_outer
= MRB_SYM(__outer__
);
341 o
= mrb_obj_iv_get(mrb
, c
, id_outer
);
344 if ((struct RClass
*)obj
== mrb
->object_class
) {
345 mrb_obj_iv_set_force(mrb
, c
, id_classname
, mrb_symbol_value(sym
));
348 mrb_obj_iv_set_force(mrb
, c
, id_outer
, mrb_obj_value(obj
));
357 mrb_obj_iv_set_force(mrb_state
*mrb
, struct RObject
*obj
, mrb_sym sym
, mrb_value v
)
359 if (namespace_p(obj
->tt
)) {
360 assign_class_name(mrb
, obj
, sym
, v
);
363 obj
->iv
= iv_new(mrb
);
365 iv_put(mrb
, obj
->iv
, sym
, v
);
366 mrb_field_write_barrier_value(mrb
, (struct RBasic
*)obj
, v
);
370 mrb_obj_iv_set(mrb_state
*mrb
, struct RObject
*obj
, mrb_sym sym
, mrb_value v
)
372 mrb_check_frozen(mrb
, obj
);
373 mrb_obj_iv_set_force(mrb
, obj
, sym
, v
);
376 /* Iterates over the instance variable table. */
378 mrb_iv_foreach(mrb_state
*mrb
, mrb_value obj
, mrb_iv_foreach_func
*func
, void *p
)
380 if (!obj_iv_p(obj
)) return;
381 iv_foreach(mrb
, mrb_obj_ptr(obj
)->iv
, func
, p
);
385 mrb_iv_set(mrb_state
*mrb
, mrb_value obj
, mrb_sym sym
, mrb_value v
)
388 mrb_obj_iv_set(mrb
, mrb_obj_ptr(obj
), sym
, v
);
391 mrb_raise(mrb
, E_ARGUMENT_ERROR
, "cannot set instance variable");
396 mrb_obj_iv_defined(mrb_state
*mrb
, struct RObject
*obj
, mrb_sym sym
)
401 if (t
&& iv_get(mrb
, t
, sym
, NULL
)) return TRUE
;
406 mrb_iv_defined(mrb_state
*mrb
, mrb_value obj
, mrb_sym sym
)
408 if (!obj_iv_p(obj
)) return FALSE
;
409 return mrb_obj_iv_defined(mrb
, mrb_obj_ptr(obj
), sym
);
413 mrb_iv_name_sym_p(mrb_state
*mrb
, mrb_sym iv_name
)
418 s
= mrb_sym_name_len(mrb
, iv_name
, &len
);
419 if (len
< 2) return FALSE
;
420 if (s
[0] != '@') return FALSE
;
421 if (ISDIGIT(s
[1])) return FALSE
;
422 return mrb_ident_p(s
+1, len
-1);
426 mrb_iv_name_sym_check(mrb_state
*mrb
, mrb_sym iv_name
)
428 if (!mrb_iv_name_sym_p(mrb
, iv_name
)) {
429 mrb_name_error(mrb
, iv_name
, "'%n' is not allowed as an instance variable name", iv_name
);
434 mrb_iv_copy(mrb_state
*mrb
, mrb_value dest
, mrb_value src
)
436 struct RObject
*d
= mrb_obj_ptr(dest
);
437 struct RObject
*s
= mrb_obj_ptr(src
);
444 mrb_write_barrier(mrb
, (struct RBasic
*)d
);
445 d
->iv
= iv_copy(mrb
, s
->iv
);
450 inspect_i(mrb_state
*mrb
, mrb_sym sym
, mrb_value v
, void *p
)
452 mrb_value str
= *(mrb_value
*)p
;
456 char *sp
= RSTRING_PTR(str
);
458 /* need not to show internal data */
459 if (sp
[0] == '-') { /* first element */
461 mrb_str_cat_lit(mrb
, str
, " ");
464 mrb_str_cat_lit(mrb
, str
, ", ");
466 s
= mrb_sym_name_len(mrb
, sym
, &len
);
467 mrb_str_cat(mrb
, str
, s
, len
);
468 mrb_str_cat_lit(mrb
, str
, "=");
469 ins
= mrb_inspect(mrb
, v
);
470 mrb_str_cat_str(mrb
, str
, ins
);
475 mrb_obj_iv_inspect(mrb_state
*mrb
, struct RObject
*obj
)
478 size_t len
= iv_size(mrb
, t
);
481 const char *cn
= mrb_obj_classname(mrb
, mrb_obj_value(obj
));
482 mrb_value str
= mrb_str_new_capa(mrb
, 30);
484 mrb_str_cat_lit(mrb
, str
, "-<");
485 mrb_str_cat_cstr(mrb
, str
, cn
);
486 mrb_str_cat_lit(mrb
, str
, ":");
487 mrb_str_cat_str(mrb
, str
, mrb_ptr_to_str(mrb
, obj
));
489 if (mrb_inspect_recursive_p(mrb
, mrb_obj_value(obj
))) {
490 mrb_str_cat_lit(mrb
, str
, " ...>");
493 iv_foreach(mrb
, t
, inspect_i
, &str
);
494 mrb_str_cat_lit(mrb
, str
, ">");
497 return mrb_any_to_s(mrb
, mrb_obj_value(obj
));
501 mrb_iv_remove(mrb_state
*mrb
, mrb_value obj
, mrb_sym sym
)
504 struct RObject
*o
= mrb_obj_ptr(obj
);
508 mrb_check_frozen(mrb
, o
);
509 if (iv_del(mrb
, t
, sym
, &val
)) {
513 return mrb_undef_value();
517 iv_i(mrb_state
*mrb
, mrb_sym sym
, mrb_value v
, void *p
)
523 ary
= *(mrb_value
*)p
;
524 s
= mrb_sym_name_len(mrb
, sym
, &len
);
525 if (len
> 1 && s
[0] == '@' && s
[1] != '@') {
526 mrb_ary_push(mrb
, ary
, mrb_symbol_value(sym
));
534 * obj.instance_variables -> array
536 * Returns an array of instance variable names for the receiver. Note
537 * that simply defining an accessor does not create the corresponding
546 * Fred.new.instance_variables #=> [:@iv]
549 mrb_obj_instance_variables(mrb_state
*mrb
, mrb_value self
)
553 ary
= mrb_ary_new(mrb
);
554 if (obj_iv_p(self
)) {
555 iv_foreach(mrb
, mrb_obj_ptr(self
)->iv
, iv_i
, &ary
);
561 cv_i(mrb_state
*mrb
, mrb_sym sym
, mrb_value v
, void *p
)
567 ary
= *(mrb_value
*)p
;
568 s
= mrb_sym_name_len(mrb
, sym
, &len
);
569 if (len
> 2 && s
[0] == '@' && s
[1] == '@') {
570 mrb_ary_push(mrb
, ary
, mrb_symbol_value(sym
));
578 * mod.class_variables(inherit=true) -> array
580 * Returns an array of the names of class variables in <i>mod</i>.
588 * One.class_variables #=> [:@@var1]
589 * Two.class_variables #=> [:@@var2]
592 mrb_mod_class_variables(mrb_state
*mrb
, mrb_value mod
)
596 mrb_bool inherit
= TRUE
;
598 mrb_get_args(mrb
, "|b", &inherit
);
599 ary
= mrb_ary_new(mrb
);
600 c
= mrb_class_ptr(mod
);
602 iv_foreach(mrb
, class_iv_ptr(c
), cv_i
, &ary
);
610 mrb_mod_cv_get(mrb_state
*mrb
, struct RClass
*c
, mrb_sym sym
)
612 struct RClass
* cls
= c
;
617 if (iv_get(mrb
, class_iv_ptr(c
), sym
, &v
)) {
623 if (cls
&& cls
->tt
== MRB_TT_SCLASS
) {
626 klass
= mrb_obj_iv_get(mrb
, (struct RObject
*)cls
, MRB_SYM(__attached__
));
627 c
= mrb_class_ptr(klass
);
628 if (c
->tt
== MRB_TT_CLASS
|| c
->tt
== MRB_TT_MODULE
) {
631 if (iv_get(mrb
, class_iv_ptr(c
), sym
, &v
)) {
639 mrb_name_error(mrb
, sym
, "uninitialized class variable %n in %C", sym
, cls
);
641 return mrb_nil_value();
645 mrb_cv_get(mrb_state
*mrb
, mrb_value mod
, mrb_sym sym
)
647 return mrb_mod_cv_get(mrb
, mrb_class_ptr(mod
), sym
);
651 mrb_mod_cv_set(mrb_state
*mrb
, struct RClass
*c
, mrb_sym sym
, mrb_value v
)
653 struct RClass
* cls
= c
;
656 iv_tbl
*t
= class_iv_ptr(c
);
657 int pos
= iv_get(mrb
, t
, sym
, NULL
);
660 mrb_check_frozen(mrb
, c
);
661 t
->ptr
[pos
-1] = v
; /* iv_get returns pos+1 to put */
662 mrb_field_write_barrier_value(mrb
, (struct RBasic
*)c
, v
);
668 if (cls
&& cls
->tt
== MRB_TT_SCLASS
) {
671 klass
= mrb_obj_iv_get(mrb
, (struct RObject
*)cls
, MRB_SYM(__attached__
));
672 switch (mrb_type(klass
)) {
676 c
= mrb_class_ptr(klass
);
683 else if (cls
&& cls
->tt
== MRB_TT_ICLASS
) {
690 mrb_check_frozen(mrb
, c
);
695 iv_put(mrb
, c
->iv
, sym
, v
);
696 mrb_field_write_barrier_value(mrb
, (struct RBasic
*)c
, v
);
700 mrb_cv_set(mrb_state
*mrb
, mrb_value mod
, mrb_sym sym
, mrb_value v
)
702 mrb_mod_cv_set(mrb
, mrb_class_ptr(mod
), sym
, v
);
706 mrb_mod_cv_defined(mrb_state
*mrb
, struct RClass
* c
, mrb_sym sym
)
709 iv_tbl
*t
= class_iv_ptr(c
);
710 if (iv_get(mrb
, t
, sym
, NULL
)) return TRUE
;
718 mrb_cv_defined(mrb_state
*mrb
, mrb_value mod
, mrb_sym sym
)
720 return mrb_mod_cv_defined(mrb
, mrb_class_ptr(mod
), sym
);
724 mrb_vm_cv_get(mrb_state
*mrb
, mrb_sym sym
)
728 const struct RProc
*p
= mrb
->c
->ci
->proc
;
731 c
= MRB_PROC_TARGET_CLASS(p
);
732 if (c
&& c
->tt
!= MRB_TT_SCLASS
) break;
735 return mrb_mod_cv_get(mrb
, c
, sym
);
739 mrb_vm_cv_set(mrb_state
*mrb
, mrb_sym sym
, mrb_value v
)
742 const struct RProc
*p
= mrb
->c
->ci
->proc
;
745 c
= MRB_PROC_TARGET_CLASS(p
);
746 if (c
&& c
->tt
!= MRB_TT_SCLASS
) break;
749 mrb_mod_cv_set(mrb
, c
, sym
, v
);
753 mod_const_check(mrb_state
*mrb
, mrb_value mod
)
755 switch (mrb_type(mod
)) {
761 mrb_raise(mrb
, E_TYPE_ERROR
, "constant look-up for non class/module");
767 const_get(mrb_state
*mrb
, struct RClass
*base
, mrb_sym sym
, mrb_bool skip
)
769 struct RClass
*c
= base
;
771 mrb_bool retry
= FALSE
;
773 /* if skip then skip the current class (already searched) */
774 if (skip
) c
= c
->super
;
777 if (!MRB_FLAG_TEST(c
, MRB_FL_CLASS_IS_PREPENDED
) && iv_get(mrb
, class_iv_ptr(c
), sym
, &v
)) {
781 if (!skip
&& c
== mrb
->object_class
) break;
783 if (!retry
&& base
->tt
== MRB_TT_MODULE
&& skip
) {
784 c
= mrb
->object_class
;
788 mrb_value mod
= mrb_obj_value(base
);
789 if (mrb_func_basic_p(mrb
, mod
, MRB_SYM(const_missing
), mrb_mod_const_missing
)) {
790 return mrb_const_missing(mrb
, mod
, sym
);
792 mrb_value name
= mrb_symbol_value(sym
);
793 return mrb_funcall_argv(mrb
, mod
, MRB_SYM(const_missing
), 1, &name
);
797 mrb_const_get(mrb_state
*mrb
, mrb_value mod
, mrb_sym sym
)
799 mod_const_check(mrb
, mod
);
800 return const_get(mrb
, mrb_class_ptr(mod
), sym
, FALSE
);
804 mrb_vm_const_get(mrb_state
*mrb
, mrb_sym sym
)
809 const struct RProc
*proc
= mrb
->c
->ci
->proc
;
811 c
= MRB_PROC_TARGET_CLASS(proc
);
812 if (!c
) c
= mrb
->object_class
;
813 if (iv_get(mrb
, class_iv_ptr(c
), sym
, &v
)) {
817 while (c2
&& c2
->tt
== MRB_TT_SCLASS
) {
820 if (!iv_get(mrb
, class_iv_ptr(c2
), MRB_SYM(__attached__
), &klass
)) {
824 c2
= mrb_class_ptr(klass
);
826 if (c2
&& (c2
->tt
== MRB_TT_CLASS
|| c2
->tt
== MRB_TT_MODULE
)) c
= c2
;
829 c2
= MRB_PROC_TARGET_CLASS(proc
);
830 if (!c2
) c2
= mrb
->object_class
;
831 if (c2
&& iv_get(mrb
, class_iv_ptr(c2
), sym
, &v
)) {
836 return const_get(mrb
, c
, sym
, TRUE
);
840 mrb_const_set(mrb_state
*mrb
, mrb_value mod
, mrb_sym sym
, mrb_value v
)
842 mod_const_check(mrb
, mod
);
843 if (mrb_type(v
) == MRB_TT_CLASS
|| mrb_type(v
) == MRB_TT_MODULE
) {
844 mrb_class_name_class(mrb
, mrb_class_ptr(mod
), mrb_class_ptr(v
), sym
);
846 mrb_iv_set(mrb
, mod
, sym
, v
);
850 mrb_vm_const_set(mrb_state
*mrb
, mrb_sym sym
, mrb_value v
)
854 c
= MRB_PROC_TARGET_CLASS(mrb
->c
->ci
->proc
);
855 if (!c
) c
= mrb
->object_class
;
856 mrb_obj_iv_set(mrb
, (struct RObject
*)c
, sym
, v
);
860 mrb_const_remove(mrb_state
*mrb
, mrb_value mod
, mrb_sym sym
)
862 mod_const_check(mrb
, mod
);
863 mrb_iv_remove(mrb
, mod
, sym
);
867 mrb_define_const_id(mrb_state
*mrb
, struct RClass
*mod
, mrb_sym name
, mrb_value v
)
869 mrb_obj_iv_set(mrb
, (struct RObject
*)mod
, name
, v
);
873 mrb_define_const(mrb_state
*mrb
, struct RClass
*mod
, const char *name
, mrb_value v
)
875 mrb_obj_iv_set(mrb
, (struct RObject
*)mod
, mrb_intern_cstr(mrb
, name
), v
);
879 mrb_define_global_const(mrb_state
*mrb
, const char *name
, mrb_value val
)
881 mrb_define_const(mrb
, mrb
->object_class
, name
, val
);
885 const_i(mrb_state
*mrb
, mrb_sym sym
, mrb_value v
, void *p
)
891 ary
= *(mrb_value
*)p
;
892 s
= mrb_sym_name_len(mrb
, sym
, &len
);
893 if (len
>= 1 && ISUPPER(s
[0])) {
894 mrb_int i
, alen
= RARRAY_LEN(ary
);
896 for (i
=0; i
<alen
; i
++) {
897 if (mrb_symbol(RARRAY_PTR(ary
)[i
]) == sym
)
901 mrb_ary_push(mrb
, ary
, mrb_symbol_value(sym
));
910 * mod.constants -> array
912 * Returns an array of all names of constants defined in the receiver.
915 mrb_mod_constants(mrb_state
*mrb
, mrb_value mod
)
918 mrb_bool inherit
= TRUE
;
919 struct RClass
*c
= mrb_class_ptr(mod
);
921 mrb_get_args(mrb
, "|b", &inherit
);
922 ary
= mrb_ary_new(mrb
);
924 iv_foreach(mrb
, class_iv_ptr(c
), const_i
, &ary
);
927 if (c
== mrb
->object_class
) break;
933 mrb_gv_get(mrb_state
*mrb
, mrb_sym sym
)
937 if (iv_get(mrb
, mrb
->globals
, sym
, &v
))
939 return mrb_nil_value();
943 mrb_gv_set(mrb_state
*mrb
, mrb_sym sym
, mrb_value v
)
948 mrb
->globals
= iv_new(mrb
);
951 iv_put(mrb
, t
, sym
, v
);
955 mrb_gv_remove(mrb_state
*mrb
, mrb_sym sym
)
957 iv_del(mrb
, mrb
->globals
, sym
, NULL
);
961 gv_i(mrb_state
*mrb
, mrb_sym sym
, mrb_value v
, void *p
)
965 ary
= *(mrb_value
*)p
;
966 mrb_ary_push(mrb
, ary
, mrb_symbol_value(sym
));
974 * global_variables -> array
976 * Returns an array of the names of global variables.
978 * global_variables.grep /std/ #=> [:$stdin, :$stdout, :$stderr]
981 mrb_f_global_variables(mrb_state
*mrb
, mrb_value self
)
983 iv_tbl
*t
= mrb
->globals
;
984 mrb_value ary
= mrb_ary_new(mrb
);
986 iv_foreach(mrb
, t
, gv_i
, &ary
);
991 const_defined_0(mrb_state
*mrb
, mrb_value mod
, mrb_sym id
, mrb_bool exclude
, mrb_bool recurse
)
993 struct RClass
*klass
= mrb_class_ptr(mod
);
995 mrb_bool mod_retry
= FALSE
;
1000 if (iv_get(mrb
, class_iv_ptr(tmp
), id
, NULL
)) {
1003 if (!recurse
&& (klass
!= mrb
->object_class
)) break;
1006 if (!exclude
&& !mod_retry
&& (klass
->tt
== MRB_TT_MODULE
)) {
1008 tmp
= mrb
->object_class
;
1015 mrb_const_defined(mrb_state
*mrb
, mrb_value mod
, mrb_sym id
)
1017 return const_defined_0(mrb
, mod
, id
, TRUE
, TRUE
);
1021 mrb_const_defined_at(mrb_state
*mrb
, mrb_value mod
, mrb_sym id
)
1023 return const_defined_0(mrb
, mod
, id
, TRUE
, FALSE
);
1027 mrb_attr_get(mrb_state
*mrb
, mrb_value obj
, mrb_sym id
)
1029 return mrb_iv_get(mrb
, obj
, id
);
1038 csym_i(mrb_state
*mrb
, mrb_sym sym
, mrb_value v
, void *p
)
1040 struct csym_arg
*a
= (struct csym_arg
*)p
;
1041 struct RClass
*c
= a
->c
;
1043 if (mrb_type(v
) == c
->tt
&& mrb_class_ptr(v
) == c
) {
1045 return 1; /* stop iteration */
1051 find_class_sym(mrb_state
*mrb
, struct RClass
*outer
, struct RClass
*c
)
1053 struct csym_arg arg
;
1055 if (!outer
) return 0;
1056 if (outer
== c
) return 0;
1059 iv_foreach(mrb
, class_iv_ptr(outer
), csym_i
, &arg
);
1063 static struct RClass
*
1064 outer_class(mrb_state
*mrb
, struct RClass
*c
)
1068 ov
= mrb_obj_iv_get(mrb
, (struct RObject
*)c
, MRB_SYM(__outer__
));
1069 if (mrb_nil_p(ov
)) return NULL
;
1070 switch (mrb_type(ov
)) {
1073 return mrb_class_ptr(ov
);
1081 detect_outer_loop(mrb_state
*mrb
, struct RClass
*c
)
1083 struct RClass
*t
= c
; /* tortoise */
1084 struct RClass
*h
= c
; /* hare */
1087 if (h
== NULL
) return FALSE
;
1088 h
= outer_class(mrb
, h
);
1089 if (h
== NULL
) return FALSE
;
1090 h
= outer_class(mrb
, h
);
1091 t
= outer_class(mrb
, t
);
1092 if (t
== h
) return TRUE
;
1097 mrb_class_find_path(mrb_state
*mrb
, struct RClass
*c
)
1099 struct RClass
*outer
;
1105 if (detect_outer_loop(mrb
, c
)) return mrb_nil_value();
1106 outer
= outer_class(mrb
, c
);
1107 if (outer
== NULL
) return mrb_nil_value();
1108 name
= find_class_sym(mrb
, outer
, c
);
1109 if (name
== 0) return mrb_nil_value();
1110 path
= mrb_str_new_capa(mrb
, 40);
1111 str
= mrb_class_name(mrb
, outer
);
1112 mrb_str_cat_cstr(mrb
, path
, str
);
1113 mrb_str_cat_cstr(mrb
, path
, "::");
1115 str
= mrb_sym_name_len(mrb
, name
, &len
);
1116 mrb_str_cat(mrb
, path
, str
, len
);
1117 if (RSTRING_PTR(path
)[0] != '#') {
1118 iv_del(mrb
, c
->iv
, MRB_SYM(__outer__
), NULL
);
1119 iv_put(mrb
, c
->iv
, MRB_SYM(__classname__
), path
);
1120 mrb_field_write_barrier_value(mrb
, (struct RBasic
*)c
, path
);
1121 path
= mrb_str_dup(mrb
, path
);
1127 mrb_obj_iv_tbl_memsize(mrb_value obj
)
1129 iv_tbl
*t
= mrb_obj_ptr(obj
)->iv
;
1130 if (t
== NULL
) return 0;
1131 return sizeof(iv_tbl
) + t
->alloc
*(sizeof(mrb_value
)+sizeof(mrb_sym
));
1134 #define identchar(c) (ISALNUM(c) || (c) == '_' || !ISASCII(c))
1137 mrb_ident_p(const char *s
, mrb_int len
)
1139 for (mrb_int i
= 0; i
< len
; i
++) {
1140 if (!identchar(s
[i
])) return FALSE
;