Groonga 3.0.9 Source Code Document
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
variable.c
Go to the documentation of this file.
1 /*
2 ** variable.c - mruby variables
3 **
4 ** See Copyright Notice in mruby.h
5 */
6 
7 #include "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 "error.h"
14 #include <ctype.h>
15 
17 
18 #ifdef MRB_USE_IV_SEGLIST
19 
20 #ifndef MRB_SEGMENT_SIZE
21 #define MRB_SEGMENT_SIZE 4
22 #endif
23 
24 typedef struct segment {
25  mrb_sym key[MRB_SEGMENT_SIZE];
26  mrb_value val[MRB_SEGMENT_SIZE];
27  struct segment *next;
28 } segment;
29 
30 /* Instance variable table structure */
31 typedef struct iv_tbl {
32  segment *rootseg;
33  size_t size;
34  size_t last_len;
35 } iv_tbl;
36 
37 /*
38  * Creates the instance variable table.
39  *
40  * Parameters
41  * mrb
42  * Returns
43  * the instance variable table.
44  */
45 static iv_tbl*
46 iv_new(mrb_state *mrb)
47 {
48  iv_tbl *t;
49 
50  t = mrb_malloc(mrb, sizeof(iv_tbl));
51  if (t) {
52  t->size = 0;
53  t->rootseg = NULL;
54  t->last_len = 0;
55  }
56  return t;
57 }
58 
59 /*
60  * Set the value for the symbol in the instance variable table.
61  *
62  * Parameters
63  * mrb
64  * t the instance variable table to be set in.
65  * sym the symbol to be used as the key.
66  * val the value to be set.
67  */
68 static void
69 iv_put(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value val)
70 {
71  segment *seg = t->rootseg;
72  segment *prev = NULL;
73  segment *matched_seg = NULL;
74  size_t matched_idx = 0;
75  size_t i;
76 
77  while (seg) {
78  for (i=0; i<MRB_SEGMENT_SIZE; i++) {
79  mrb_sym key = seg->key[i];
80  /* Found room in last segment after last_len */
81  if (!seg->next && i >= t->last_len) {
82  seg->key[i] = sym;
83  seg->val[i] = val;
84  t->last_len = i+1;
85  t->size++;
86  return;
87  }
88  if (!matched_seg && key == 0) {
89  matched_seg = seg;
90  matched_idx = i;
91  }
92  else if (key == sym) {
93  seg->val[i] = val;
94  return;
95  }
96  }
97  prev = seg;
98  seg = seg->next;
99  }
100 
101  /* Not found */
102  t->size++;
103  if (matched_seg) {
104  matched_seg->key[matched_idx] = sym;
105  matched_seg->val[matched_idx] = val;
106  return;
107  }
108 
109  seg = mrb_malloc(mrb, sizeof(segment));
110  if (!seg) return;
111  seg->next = NULL;
112  seg->key[0] = sym;
113  seg->val[0] = val;
114  t->last_len = 1;
115  if (prev) {
116  prev->next = seg;
117  }
118  else {
119  t->rootseg = seg;
120  }
121 }
122 
123 /*
124  * Get a value for a symbol from the instance the variable table.
125  *
126  * Parameters
127  * mrb
128  * t the variable table to be searched.
129  * sym the symbol to be used as the key.
130  * vp the value pointer. Recieves the value if the specified symbol contains
131  * in the instance variable table.
132  * Returns
133  * true if the specfiyed symbol contains in the instance variable table.
134  */
135 static mrb_bool
136 iv_get(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp)
137 {
138  segment *seg;
139  size_t i;
140 
141  seg = t->rootseg;
142  while (seg) {
143  for (i=0; i<MRB_SEGMENT_SIZE; i++) {
144  mrb_sym key = seg->key[i];
145 
146  if (!seg->next && i >= t->last_len) {
147  return FALSE;
148  }
149  if (key == sym) {
150  if (vp) *vp = seg->val[i];
151  return TRUE;
152  }
153  }
154  seg = seg->next;
155  }
156  return FALSE;
157 }
158 
159 /*
160  * Deletes the value for the symbol from the instance variable table.
161  *
162  * Parameters
163  * t the variable table to be searched.
164  * sym the symbol to be used as the key.
165  * vp the value pointer. Recieve the deleted value if the symbol contans
166  * in the instance varible table.
167  * Returns
168  * true if the specfied symbol contains in the instance variable table.
169  */
170 static mrb_bool
171 iv_del(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp)
172 {
173  segment *seg;
174  size_t i;
175 
176  seg = t->rootseg;
177  while (seg) {
178  for (i=0; i<MRB_SEGMENT_SIZE; i++) {
179  mrb_sym key = seg->key[i];
180 
181  if (!seg->next && i >= t->last_len) {
182  return FALSE;
183  }
184  if (key == sym) {
185  t->size--;
186  seg->key[i] = 0;
187  if (vp) *vp = seg->val[i];
188  return TRUE;
189  }
190  }
191  seg = seg->next;
192  }
193  return FALSE;
194 }
195 
196 static mrb_bool
197 iv_foreach(mrb_state *mrb, iv_tbl *t, iv_foreach_func *func, void *p)
198 {
199  segment *seg;
200  size_t i;
201  int n;
202 
203  seg = t->rootseg;
204  while (seg) {
205  for (i=0; i<MRB_SEGMENT_SIZE; i++) {
206  mrb_sym key = seg->key[i];
207 
208  /* no value in last segment after last_len */
209  if (!seg->next && i >= t->last_len) {
210  return FALSE;
211  }
212  if (key != 0) {
213  n =(*func)(mrb, key, seg->val[i], p);
214  if (n > 0) return FALSE;
215  if (n < 0) {
216  t->size--;
217  seg->key[i] = 0;
218  }
219  }
220  }
221  seg = seg->next;
222  }
223  return TRUE;
224 }
225 
226 static size_t
227 iv_size(mrb_state *mrb, iv_tbl *t)
228 {
229  segment *seg;
230  size_t size = 0;
231 
232  if (!t) return 0;
233  if (t->size > 0) return t->size;
234  seg = t->rootseg;
235  while (seg) {
236  if (seg->next == NULL) {
237  size += t->last_len;
238  return size;
239  }
240  seg = seg->next;
241  size += MRB_SEGMENT_SIZE;
242  }
243  /* empty iv_tbl */
244  return 0;
245 }
246 
247 static iv_tbl*
248 iv_copy(mrb_state *mrb, iv_tbl *t)
249 {
250  segment *seg;
251  iv_tbl *t2;
252 
253  size_t i;
254 
255  seg = t->rootseg;
256  t2 = iv_new(mrb);
257 
258  while (seg != NULL) {
259  for (i=0; i<MRB_SEGMENT_SIZE; i++) {
260  mrb_sym key = seg->key[i];
261  mrb_value val = seg->val[i];
262 
263  if ((seg->next == NULL) && (i >= t->last_len)) {
264  return t2;
265  }
266  iv_put(mrb, t2, key, val);
267  }
268  seg = seg->next;
269  }
270  return t2;
271 }
272 
273 static void
274 iv_free(mrb_state *mrb, iv_tbl *t)
275 {
276  segment *seg;
277 
278  seg = t->rootseg;
279  while (seg) {
280  segment *p = seg;
281  seg = seg->next;
282  mrb_free(mrb, p);
283  }
284  mrb_free(mrb, t);
285 }
286 
287 #else
288 
289 #include "mruby/khash.h"
290 
291 #ifndef MRB_IVHASH_INIT_SIZE
292 #define MRB_IVHASH_INIT_SIZE 8
293 #endif
294 
297 
298 typedef struct iv_tbl {
299  khash_t(iv) h;
300 } iv_tbl;
301 
302 static iv_tbl*
303 iv_new(mrb_state *mrb)
304 {
305  return (iv_tbl*)kh_init_size(iv, mrb, MRB_IVHASH_INIT_SIZE);
306 }
307 
308 static void
309 iv_put(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value val)
310 {
311  khash_t(iv) *h = &t->h;
312  khiter_t k;
313 
314  k = kh_put(iv, h, sym);
315  kh_value(h, k) = val;
316 }
317 
318 static mrb_bool
319 iv_get(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp)
320 {
321  khash_t(iv) *h = &t->h;
322  khiter_t k;
323 
324  k = kh_get(iv, h, sym);
325  if (k != kh_end(h)) {
326  if (vp) *vp = kh_value(h, k);
327  return TRUE;
328  }
329  return FALSE;
330 }
331 
332 static mrb_bool
333 iv_del(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp)
334 {
335  khash_t(iv) *h = &t->h;
336  khiter_t k;
337 
338  if (h) {
339  k = kh_get(iv, h, sym);
340  if (k != kh_end(h)) {
341  mrb_value val = kh_value(h, k);
342  kh_del(iv, h, k);
343  if (vp) *vp = val;
344  return TRUE;
345  }
346  }
347  return FALSE;
348 }
349 
350 static mrb_bool
351 iv_foreach(mrb_state *mrb, iv_tbl *t, iv_foreach_func *func, void *p)
352 {
353  khash_t(iv) *h = &t->h;
354  khiter_t k;
355  int n;
356 
357  if (h) {
358  for (k = kh_begin(h); k != kh_end(h); k++) {
359  if (kh_exist(h, k)){
360  n = (*func)(mrb, kh_key(h, k), kh_value(h, k), p);
361  if (n > 0) return FALSE;
362  if (n < 0) {
363  kh_del(iv, h, k);
364  }
365  }
366  }
367  }
368  return TRUE;
369 }
370 
371 static size_t
372 iv_size(mrb_state *mrb, iv_tbl *t)
373 {
374  khash_t(iv) *h = &t->h;
375 
376  if (!h) return 0;
377  return kh_size(h);
378 }
379 
380 static iv_tbl*
381 iv_copy(mrb_state *mrb, iv_tbl *t)
382 {
383  return (iv_tbl*)kh_copy(iv, mrb, &t->h);
384 }
385 
386 static void
387 iv_free(mrb_state *mrb, iv_tbl *t)
388 {
389  kh_destroy(iv, &t->h);
390 }
391 
392 #endif
393 
394 static int
395 iv_mark_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p)
396 {
397  mrb_gc_mark_value(mrb, v);
398  return 0;
399 }
400 
401 static void
402 mark_tbl(mrb_state *mrb, iv_tbl *t)
403 {
404  if (t) {
405  iv_foreach(mrb, t, iv_mark_i, 0);
406  }
407 }
408 
409 void
411 {
412  mark_tbl(mrb, mrb->globals);
413 }
414 
415 void
417 {
418  if (mrb->globals)
419  iv_free(mrb, mrb->globals);
420 }
421 
422 void
423 mrb_gc_mark_iv(mrb_state *mrb, struct RObject *obj)
424 {
425  mark_tbl(mrb, obj->iv);
426 }
427 
428 size_t
430 {
431  return iv_size(mrb, obj->iv);
432 }
433 
434 void
435 mrb_gc_free_iv(mrb_state *mrb, struct RObject *obj)
436 {
437  if (obj->iv) {
438  iv_free(mrb, obj->iv);
439  }
440 }
441 
442 mrb_value
444 {
445  return mrb_fixnum_value(0);
446 }
447 
448 void
450 {
451 }
452 
453 static mrb_bool
454 obj_iv_p(mrb_value obj)
455 {
456  switch (mrb_type(obj)) {
457  case MRB_TT_OBJECT:
458  case MRB_TT_CLASS:
459  case MRB_TT_MODULE:
460  case MRB_TT_SCLASS:
461  case MRB_TT_HASH:
462  case MRB_TT_DATA:
463  return TRUE;
464  default:
465  return FALSE;
466  }
467 }
468 
469 mrb_value
470 mrb_obj_iv_get(mrb_state *mrb, struct RObject *obj, mrb_sym sym)
471 {
472  mrb_value v;
473 
474  if (obj->iv && iv_get(mrb, obj->iv, sym, &v))
475  return v;
476  return mrb_nil_value();
477 }
478 
479 mrb_value
481 {
482  if (obj_iv_p(obj)) {
483  return mrb_obj_iv_get(mrb, mrb_obj_ptr(obj), sym);
484  }
485  return mrb_nil_value();
486 }
487 
488 void
490 {
491  iv_tbl *t = obj->iv;
492 
493  if (!t) {
494  t = obj->iv = iv_new(mrb);
495  }
496  mrb_write_barrier(mrb, (struct RBasic*)obj);
497  iv_put(mrb, t, sym, v);
498 }
499 
500 void
502 {
503  iv_tbl *t = obj->iv;
504 
505  if (!t) {
506  t = obj->iv = iv_new(mrb);
507  }
508  else if (iv_get(mrb, t, sym, &v)) {
509  return;
510  }
511  mrb_write_barrier(mrb, (struct RBasic*)obj);
512  iv_put(mrb, t, sym, v);
513 }
514 
515 void
517 {
518  if (obj_iv_p(obj)) {
519  mrb_obj_iv_set(mrb, mrb_obj_ptr(obj), sym, v);
520  }
521  else {
522  mrb_raise(mrb, E_ARGUMENT_ERROR, "cannot set instance variable");
523  }
524 }
525 
526 mrb_bool
528 {
529  iv_tbl *t;
530 
531  t = obj->iv;
532  if (t) {
533  return iv_get(mrb, t, sym, NULL);
534  }
535  return FALSE;
536 }
537 
538 mrb_bool
540 {
541  if (!obj_iv_p(obj)) return FALSE;
542  return mrb_obj_iv_defined(mrb, mrb_obj_ptr(obj), sym);
543 }
544 
545 void
547 {
548  struct RObject *d = mrb_obj_ptr(dest);
549  struct RObject *s = mrb_obj_ptr(src);
550 
551  if (d->iv) {
552  iv_free(mrb, d->iv);
553  d->iv = 0;
554  }
555  if (s->iv) {
556  d->iv = iv_copy(mrb, s->iv);
557  }
558 }
559 
560 static int
561 inspect_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p)
562 {
563  mrb_value str = *(mrb_value*)p;
564  const char *s;
565  size_t len;
566 
567  /* need not to show internal data */
568  if (RSTRING_PTR(str)[0] == '-') { /* first element */
569  RSTRING_PTR(str)[0] = '#';
570  mrb_str_cat(mrb, str, " ", 1);
571  }
572  else {
573  mrb_str_cat(mrb, str, ", ", 2);
574  }
575  s = mrb_sym2name_len(mrb, sym, &len);
576  mrb_str_cat(mrb, str, s, len);
577  mrb_str_cat(mrb, str, "=", 1);
578  mrb_str_append(mrb, str, mrb_inspect(mrb, v));
579  return 0;
580 }
581 
582 mrb_value
584 {
585  iv_tbl *t = obj->iv;
586  size_t len = iv_size(mrb, t);
587 
588  if (len > 0) {
589  const char *cn = mrb_obj_classname(mrb, mrb_obj_value(obj));
590  mrb_value str = mrb_str_buf_new(mrb, 30);
591 
592  mrb_str_buf_cat(mrb, str, "-<", 2);
593  mrb_str_cat2(mrb, str, cn);
594  mrb_str_cat(mrb, str, ":", 1);
595  mrb_str_concat(mrb, str, mrb_ptr_to_str(mrb, obj));
596 
597  iv_foreach(mrb, t, inspect_i, &str);
598  mrb_str_cat(mrb, str, ">", 1);
599  return str;
600  }
601  return mrb_any_to_s(mrb, mrb_obj_value(obj));
602 }
603 
604 mrb_value
606 {
607  if (obj_iv_p(obj)) {
608  iv_tbl *t = mrb_obj_ptr(obj)->iv;
609  mrb_value val;
610 
611  if (t && iv_del(mrb, t, sym, &val)) {
612  return val;
613  }
614  }
615  return mrb_undef_value();
616 }
617 
618 mrb_value
620 {
621  /* get self */
622  return mrb_iv_get(mrb, mrb->c->stack[0], sym);
623 }
624 
625 void
627 {
628  /* get self */
629  mrb_iv_set(mrb, mrb->c->stack[0], sym, v);
630 }
631 
632 static int
633 iv_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p)
634 {
635  mrb_value ary;
636  const char* s;
637  size_t len;
638 
639  ary = *(mrb_value*)p;
640  s = mrb_sym2name_len(mrb, sym, &len);
641  if (len > 1 && s[0] == '@' && s[1] != '@') {
642  mrb_ary_push(mrb, ary, mrb_symbol_value(sym));
643  }
644  return 0;
645 }
646 
647 /* 15.3.1.3.23 */
648 /*
649  * call-seq:
650  * obj.instance_variables -> array
651  *
652  * Returns an array of instance variable names for the receiver. Note
653  * that simply defining an accessor does not create the corresponding
654  * instance variable.
655  *
656  * class Fred
657  * attr_accessor :a1
658  * def initialize
659  * @iv = 3
660  * end
661  * end
662  * Fred.new.instance_variables #=> [:@iv]
663  */
664 mrb_value
666 {
667  mrb_value ary;
668 
669  ary = mrb_ary_new(mrb);
670  if (obj_iv_p(self) && mrb_obj_ptr(self)->iv) {
671  iv_foreach(mrb, mrb_obj_ptr(self)->iv, iv_i, &ary);
672  }
673  return ary;
674 }
675 
676 static int
677 cv_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p)
678 {
679  mrb_value ary;
680  const char* s;
681  size_t len;
682 
683  ary = *(mrb_value*)p;
684  s = mrb_sym2name_len(mrb, sym, &len);
685  if (len > 2 && s[0] == '@' && s[1] == '@') {
686  mrb_ary_push(mrb, ary, mrb_symbol_value(sym));
687  }
688  return 0;
689 }
690 
691 /* 15.2.2.4.19 */
692 /*
693  * call-seq:
694  * mod.class_variables -> array
695  *
696  * Returns an array of the names of class variables in <i>mod</i>.
697  *
698  * class One
699  * @@var1 = 1
700  * end
701  * class Two < One
702  * @@var2 = 2
703  * end
704  * One.class_variables #=> [:@@var1]
705  * Two.class_variables #=> [:@@var2]
706  */
707 mrb_value
709 {
710  mrb_value ary;
711  struct RClass *c;
712 
713  ary = mrb_ary_new(mrb);
714  c = mrb_class_ptr(mod);
715  while (c) {
716  if (c->iv) {
717  iv_foreach(mrb, c->iv, cv_i, &ary);
718  }
719  c = c->super;
720  }
721  return ary;
722 }
723 
724 mrb_value
725 mrb_mod_cv_get(mrb_state *mrb, struct RClass * c, mrb_sym sym)
726 {
727  struct RClass * cls = c;
728 
729  while (c) {
730  if (c->iv) {
731  iv_tbl *t = c->iv;
732  mrb_value v;
733 
734  if (iv_get(mrb, t, sym, &v))
735  return v;
736  }
737  c = c->super;
738  }
739  mrb_name_error(mrb, sym, "uninitialized class variable %S in %S",
740  mrb_sym2str(mrb, sym), mrb_obj_value(cls));
741  /* not reached */
742  return mrb_nil_value();
743 }
744 
745 mrb_value
747 {
748  return mrb_mod_cv_get(mrb, mrb_class_ptr(mod), sym);
749 }
750 
751 void
753 {
754  struct RClass * cls = c;
755 
756  while (c) {
757  if (c->iv) {
758  iv_tbl *t = c->iv;
759 
760  if (iv_get(mrb, t, sym, NULL)) {
761  mrb_write_barrier(mrb, (struct RBasic*)c);
762  iv_put(mrb, t, sym, v);
763  return;
764  }
765  }
766  c = c->super;
767  }
768 
769  if (!cls->iv) {
770  cls->iv = iv_new(mrb);
771  }
772 
773  mrb_write_barrier(mrb, (struct RBasic*)cls);
774  iv_put(mrb, cls->iv, sym, v);
775 }
776 
777 void
779 {
780  mrb_mod_cv_set(mrb, mrb_class_ptr(mod), sym, v);
781 }
782 
783 mrb_bool
785 {
786  while (c) {
787  if (c->iv) {
788  iv_tbl *t = c->iv;
789  if (iv_get(mrb, t, sym, NULL)) return TRUE;
790  }
791  c = c->super;
792  }
793 
794  return FALSE;
795 }
796 
797 mrb_bool
799 {
800  return mrb_mod_cv_defined(mrb, mrb_class_ptr(mod), sym);
801 }
802 
803 mrb_value
805 {
806  struct RClass *c = mrb->c->ci->proc->target_class;
807 
808  if (!c) c = mrb->c->ci->target_class;
809 
810  return mrb_mod_cv_get(mrb, c, sym);
811 }
812 
813 void
815 {
816  struct RClass *c = mrb->c->ci->proc->target_class;
817 
818  if (!c) c = mrb->c->ci->target_class;
819  while (c) {
820  if (c->iv) {
821  iv_tbl *t = c->iv;
822 
823  if (iv_get(mrb, t, sym, NULL)) {
824  mrb_write_barrier(mrb, (struct RBasic*)c);
825  iv_put(mrb, t, sym, v);
826  return;
827  }
828  }
829  c = c->super;
830  }
831  c = mrb->c->ci->target_class;
832  if (!c->iv) {
833  c->iv = iv_new(mrb);
834  }
835  mrb_write_barrier(mrb, (struct RBasic*)c);
836  iv_put(mrb, c->iv, sym, v);
837 }
838 
839 mrb_bool
841 {
842  struct RClass *m = mrb_class_ptr(mod);
843  iv_tbl *t = m->iv;
844 
845  if (!t) return FALSE;
846  return iv_get(mrb, t, sym, NULL);
847 }
848 
849 static void
850 mod_const_check(mrb_state *mrb, mrb_value mod)
851 {
852  switch (mrb_type(mod)) {
853  case MRB_TT_CLASS:
854  case MRB_TT_MODULE:
855  case MRB_TT_SCLASS:
856  break;
857  default:
858  mrb_raise(mrb, E_TYPE_ERROR, "constant look-up for non class/module");
859  break;
860  }
861 }
862 
863 static mrb_value
864 const_get(mrb_state *mrb, struct RClass *base, mrb_sym sym)
865 {
866  struct RClass *c = base;
867  mrb_value v;
868  iv_tbl *t;
869  mrb_bool retry = 0;
870  mrb_sym cm;
871 
872 L_RETRY:
873  while (c) {
874  if (c->iv) {
875  t = c->iv;
876  if (iv_get(mrb, t, sym, &v))
877  return v;
878  }
879  c = c->super;
880  }
881  if (!retry && base && base->tt == MRB_TT_MODULE) {
882  c = mrb->object_class;
883  retry = 1;
884  goto L_RETRY;
885  }
886  c = base;
887  cm = mrb_intern2(mrb, "const_missing", 13);
888  while (c) {
889  if (mrb_respond_to(mrb, mrb_obj_value(c), cm)) {
890  mrb_value name = mrb_symbol_value(sym);
891  return mrb_funcall_argv(mrb, mrb_obj_value(c), cm, 1, &name);
892  }
893  c = c->super;
894  }
895  mrb_name_error(mrb, sym, "uninitialized constant %S",
896  mrb_sym2str(mrb, sym));
897  /* not reached */
898  return mrb_nil_value();
899 }
900 
901 mrb_value
903 {
904  mod_const_check(mrb, mod);
905  return const_get(mrb, mrb_class_ptr(mod), sym);
906 }
907 
908 mrb_value
910 {
911  struct RClass *c = mrb->c->ci->proc->target_class;
912 
913  if (!c) c = mrb->c->ci->target_class;
914  if (c) {
915  struct RClass *c2;
916  mrb_value v;
917 
918  if (c->iv && iv_get(mrb, c->iv, sym, &v)) {
919  return v;
920  }
921  c2 = c;
922  for (;;) {
923  c2 = mrb_class_outer_module(mrb, c2);
924  if (!c2) break;
925  if (c2->iv && iv_get(mrb, c2->iv, sym, &v)) {
926  return v;
927  }
928  }
929  }
930  return const_get(mrb, c, sym);
931 }
932 
933 void
935 {
936  mod_const_check(mrb, mod);
937  mrb_iv_set(mrb, mod, sym, v);
938 }
939 
940  void
942 {
943  struct RClass *c = mrb->c->ci->proc->target_class;
944 
945  if (!c) c = mrb->c->ci->target_class;
946  mrb_obj_iv_set(mrb, (struct RObject*)c, sym, v);
947 }
948 
949 void
951 {
952  mod_const_check(mrb, mod);
953  mrb_iv_remove(mrb, mod, sym);
954 }
955 
956 void
957 mrb_define_const(mrb_state *mrb, struct RClass *mod, const char *name, mrb_value v)
958 {
959  mrb_obj_iv_set(mrb, (struct RObject*)mod, mrb_intern_cstr(mrb, name), v);
960 }
961 
962 void
963 mrb_define_global_const(mrb_state *mrb, const char *name, mrb_value val)
964 {
965  mrb_define_const(mrb, mrb->object_class, name, val);
966 }
967 
968 static int
969 const_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p)
970 {
971  mrb_value ary;
972  const char* s;
973  size_t len;
974 
975  ary = *(mrb_value*)p;
976  s = mrb_sym2name_len(mrb, sym, &len);
977  if (len > 1 && ISUPPER(s[0])) {
978  mrb_ary_push(mrb, ary, mrb_symbol_value(sym));
979  }
980  return 0;
981 }
982 
983 /* 15.2.2.4.24 */
984 /*
985  * call-seq:
986  * mod.constants -> array
987  *
988  * Returns an array of all names of contants defined in the receiver.
989  */
990 mrb_value
992 {
993  mrb_value ary;
994  struct RClass *c = mrb_class_ptr(mod);
995 
996  ary = mrb_ary_new(mrb);
997  while (c) {
998  if (c->iv) {
999  iv_foreach(mrb, c->iv, const_i, &ary);
1000  }
1001  c = c->super;
1002  if (c == mrb->object_class) break;
1003  }
1004  return ary;
1005 }
1006 
1007 mrb_value
1009 {
1010  mrb_value v;
1011 
1012  if (!mrb->globals) {
1013  return mrb_nil_value();
1014  }
1015  if (iv_get(mrb, mrb->globals, sym, &v))
1016  return v;
1017  return mrb_nil_value();
1018 }
1019 
1020 void
1022 {
1023  iv_tbl *t;
1024 
1025  if (!mrb->globals) {
1026  t = mrb->globals = iv_new(mrb);
1027  }
1028  else {
1029  t = mrb->globals;
1030  }
1031  iv_put(mrb, t, sym, v);
1032 }
1033 
1034 static int
1035 gv_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p)
1036 {
1037  mrb_value ary;
1038 
1039  ary = *(mrb_value*)p;
1040  mrb_ary_push(mrb, ary, mrb_symbol_value(sym));
1041  return 0;
1042 }
1043 
1044 /* 15.3.1.2.4 */
1045 /* 15.3.1.3.14 */
1046 /*
1047  * call-seq:
1048  * global_variables -> array
1049  *
1050  * Returns an array of the names of global variables.
1051  *
1052  * global_variables.grep /std/ #=> [:$stdin, :$stdout, :$stderr]
1053  */
1054 mrb_value
1056 {
1057  iv_tbl *t = mrb->globals;
1058  mrb_value ary = mrb_ary_new(mrb);
1059  size_t i;
1060  char buf[3];
1061 
1062  if (t) {
1063  iv_foreach(mrb, t, gv_i, &ary);
1064  }
1065  buf[0] = '$';
1066  buf[2] = 0;
1067  for (i = 1; i <= 9; ++i) {
1068  buf[1] = (char)(i + '0');
1069  mrb_ary_push(mrb, ary, mrb_symbol_value(mrb_intern2(mrb, buf, 2)));
1070  }
1071  return ary;
1072 }
1073 
1074 static mrb_bool
1075 mrb_const_defined_0(mrb_state *mrb, struct RClass *klass, mrb_sym id, mrb_bool exclude, mrb_bool recurse)
1076 {
1077  struct RClass * tmp;
1078  mrb_bool mod_retry = 0;
1079 
1080  tmp = klass;
1081 retry:
1082  while (tmp) {
1083  if (tmp->iv && iv_get(mrb, tmp->iv, id, NULL)) {
1084  return TRUE;
1085  }
1086  if (!recurse && (klass != mrb->object_class)) break;
1087  tmp = tmp->super;
1088  }
1089  if (!exclude && !mod_retry && (klass->tt == MRB_TT_MODULE)) {
1090  mod_retry = 1;
1091  tmp = mrb->object_class;
1092  goto retry;
1093  }
1094  return FALSE;
1095 }
1096 
1097 int
1099 {
1100  return mrb_const_defined_0(mrb, klass, id, TRUE, FALSE);
1101 }
1102 
1103 mrb_value
1105 {
1106  return mrb_iv_get(mrb, obj, id);
1107 }
1108 
1109 struct csym_arg {
1110  struct RClass *c;
1112 };
1113 
1114 static int
1115 csym_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p)
1116 {
1117  struct csym_arg *a = (struct csym_arg*)p;
1118  struct RClass *c = a->c;
1119 
1120  if (mrb_type(v) == c->tt && mrb_class_ptr(v) == c) {
1121  a->sym = sym;
1122  return 1; /* stop iteration */
1123  }
1124  return 0;
1125 }
1126 
1127 mrb_sym
1128 mrb_class_sym(mrb_state *mrb, struct RClass *c, struct RClass *outer)
1129 {
1130  mrb_value name;
1131 
1132  name = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern2(mrb, "__classid__", 11));
1133  if (mrb_nil_p(name)) {
1134 
1135  if (!outer) return 0;
1136  else {
1137  struct csym_arg arg;
1138 
1139  arg.c = c;
1140  arg.sym = 0;
1141  iv_foreach(mrb, outer->iv, csym_i, &arg);
1142  return arg.sym;
1143  }
1144  }
1145  return mrb_symbol(name);
1146 }