Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 914 lines (789 sloc) 16.776 kB
8354436 @mimaki add file header
mimaki authored
1 /*
2 ** variable.c - mruby variables
4ec6d41 rm whitespace
roco authored
3 **
8354436 @mimaki add file header
mimaki authored
4 ** See Copyright Notice in mruby.h
5 */
6
e0d6430 @mimaki add mruby sources
mimaki authored
7 #include "mruby.h"
8 #include "mruby/class.h"
2fc1b8a @matz mv variable.h to mruby/variable.h
matz authored
9 #include "mruby/variable.h"
e0d6430 @mimaki add mruby sources
mimaki authored
10 #include "error.h"
11 #include "mruby/array.h"
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
12 #include "mruby/string.h"
08213e3 @matz const reference from instance_eval should not cause SEGV
matz authored
13 #include "mruby/proc.h"
e0d6430 @mimaki add mruby sources
mimaki authored
14
76f7aec @matz use ENABLE/DISABLE instead of INCLUDE for configuration macro names
matz authored
15 #ifdef ENABLE_REGEXP
e0d6430 @mimaki add mruby sources
mimaki authored
16 #include "re.h"
17 #endif
18
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
19 typedef int (iv_foreach_func)(mrb_state*,mrb_sym,mrb_value,void*);
20
21 #ifdef MRB_USE_IV_SEGLIST
22
23 #ifndef MRB_SEGMENT_SIZE
24 #define MRB_SEGMENT_SIZE 4
25 #endif
26
27 typedef struct segment
28 {
29 mrb_sym key[MRB_SEGMENT_SIZE];
30 mrb_value val[MRB_SEGMENT_SIZE];
31 struct segment *next;
32 } segment;
33
34 typedef struct iv_tbl {
35 segment *rootseg;
36 int size;
37 int last_len;
38 } iv_tbl;
39
40 static iv_tbl*
41 iv_new(mrb_state *mrb)
42 {
43 iv_tbl *t;
44
45 t = mrb_malloc(mrb, sizeof(iv_tbl));
46 if (t) {
47 t->size = 0;
48 t->rootseg = NULL;
49 t->last_len = 0;
50 }
51 return t;
52 }
53
54 static void
55 iv_put(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value val)
56 {
57 segment *seg = t->rootseg;
58 segment *prev = NULL;
59 segment *matched_seg = NULL;
60 int matched_idx = 0;
61 int i;
62
63 while (seg) {
64 for (i=0; i<MRB_SEGMENT_SIZE; i++) {
65 mrb_sym key = seg->key[i];
66 /* found room in last segment after last_len */
67 if (!seg->next && i >= t->last_len) {
68 seg->key[i] = sym;
69 seg->val[i] = val;
70 t->last_len = i+1;
71 t->size++;
72 return;
73 }
74 if (key == 0 && !matched_seg) {
75 matched_seg = seg;
76 matched_idx = i;
77 }
78 else if (key == sym) {
79 seg->val[i] = val;
80 return;
81 }
82 }
83 prev = seg;
84 seg = seg->next;
85 }
86
87 /* not found */
88 t->size++;
89 if (matched_seg) {
90 matched_seg->key[matched_idx] = sym;
91 matched_seg->val[matched_idx] = val;
92 return;
93 }
94
95 seg = mrb_malloc(mrb, sizeof(segment));
96 if (!seg) return;
97 seg->next = NULL;
98 seg->key[0] = sym;
99 seg->val[0] = val;
100 t->last_len = 1;
101 if (prev) {
102 prev->next = seg;
103 }
104 else {
105 t->rootseg = seg;
106 }
107 return;
108 }
109
110 static int
111 iv_get(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp)
112 {
113 segment *seg;
114 int i;
115
116 seg = t->rootseg;
117 while (seg) {
118 for (i=0; i<MRB_SEGMENT_SIZE; i++) {
119 mrb_sym key = seg->key[i];
120
121 if (!seg->next && i >= t->last_len) {
1ed39d5 @matz use TRUE/FALSE instead of 1/0
matz authored
122 return FALSE;
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
123 }
124 if (key == sym) {
125 if (vp) *vp = seg->val[i];
1ed39d5 @matz use TRUE/FALSE instead of 1/0
matz authored
126 return TRUE;
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
127 }
128 }
129 seg = seg->next;
130 }
1ed39d5 @matz use TRUE/FALSE instead of 1/0
matz authored
131 return FALSE;
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
132 }
133
134 static int
135 iv_del(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp)
136 {
137 segment *seg;
138 int i;
139
140 seg = t->rootseg;
141 while (seg) {
142 for (i=0; i<MRB_SEGMENT_SIZE; i++) {
143 mrb_sym key = seg->key[i];
144
145 if (!seg->next && i >= t->last_len) {
1ed39d5 @matz use TRUE/FALSE instead of 1/0
matz authored
146 return FALSE;
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
147 }
148 if (key == sym) {
149 t->size--;
150 seg->key[i] = 0;
151 if (vp) *vp = seg->val[i];
1ed39d5 @matz use TRUE/FALSE instead of 1/0
matz authored
152 return TRUE;
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
153 }
154 }
155 seg = seg->next;
156 }
1ed39d5 @matz use TRUE/FALSE instead of 1/0
matz authored
157 return FALSE;
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
158 }
159
160 static int
161 iv_foreach(mrb_state *mrb, iv_tbl *t, iv_foreach_func *func, void *p)
162 {
163 segment *seg;
164 int i, n;
165
166 seg = t->rootseg;
167 while (seg) {
168 for (i=0; i<MRB_SEGMENT_SIZE; i++) {
169 mrb_sym key = seg->key[i];
170
171 /* no value in last segment after last_len */
172 if (!seg->next && i >= t->last_len) {
1ed39d5 @matz use TRUE/FALSE instead of 1/0
matz authored
173 return FALSE;
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
174 }
175 if (key != 0) {
176 n =(*func)(mrb, key, seg->val[i], p);
1ed39d5 @matz use TRUE/FALSE instead of 1/0
matz authored
177 if (n > 0) return FALSE;
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
178 if (n < 0) {
179 t->size--;
180 seg->key[i] = 0;
181 }
182 }
183 }
184 seg = seg->next;
185 }
1ed39d5 @matz use TRUE/FALSE instead of 1/0
matz authored
186 return TRUE;
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
187 }
188
189 static int
190 iv_size(mrb_state *mrb, iv_tbl *t)
191 {
192 segment *seg;
193 int size = 0;
194
195 if (!t) return 0;
196 if (t->size > 0) return t->size;
197 seg = t->rootseg;
198 while (seg) {
199 if (seg->next == NULL) {
200 size += t->last_len;
201 return size;
202 }
203 seg = seg->next;
204 size += MRB_SEGMENT_SIZE;
205 }
206 /* empty iv_tbl */
207 return 0;
208 }
209
210 static iv_tbl*
211 iv_copy(mrb_state *mrb, iv_tbl *t)
212 {
213 segment *seg;
214 iv_tbl *t2;
215
216 int i;
217
218 seg = t->rootseg;
219 t2 = iv_new(mrb);
220
221 while (seg != NULL) {
222 for (i=0; i<MRB_SEGMENT_SIZE; i++) {
223 mrb_sym key = seg->key[i];
224 mrb_value val = seg->val[i];
225
226 iv_put(mrb, t2, key, val);
227 if ((seg->next == NULL) && (i >= t->last_len)) {
228 return t2;
229 }
230 }
231 seg = seg->next;
232 }
233 return t2;
234 }
235
236 static void
237 iv_free(mrb_state *mrb, iv_tbl *t)
238 {
239 segment *seg;
240
241 seg = t->rootseg;
242 while (seg) {
243 segment *p = seg;
244 seg = seg->next;
245 mrb_free(mrb, p);
246 }
247 mrb_free(mrb, t);
248 }
249
250 #else
251
252 #include "mruby/khash.h"
253
bf7f9f8 @matz rename config macro name IV_INITIAL_SIZE -> IVHASH_INIT_SIZE
matz authored
254 #ifndef MRB_IVHASH_INIT_SIZE
255 #define MRB_IVHASH_INIT_SIZE 8
857370c @matz use const MRB_IV_INITIAL_SIZE
matz authored
256 #endif
257
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
258 KHASH_DECLARE(iv, mrb_sym, mrb_value, 1)
259 KHASH_DEFINE(iv, mrb_sym, mrb_value, 1, kh_int_hash_func, kh_int_hash_equal);
260
261 typedef struct iv_tbl {
262 khash_t(iv) h;
263 } iv_tbl;
264
265 static iv_tbl*
266 iv_new(mrb_state *mrb)
267 {
bf7f9f8 @matz rename config macro name IV_INITIAL_SIZE -> IVHASH_INIT_SIZE
matz authored
268 return (iv_tbl*)kh_init_size(iv, mrb, MRB_IVHASH_INIT_SIZE);
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
269 }
270
e0d6430 @mimaki add mruby sources
mimaki authored
271 static void
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
272 iv_put(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value val)
273 {
274 khash_t(iv) *h = &t->h;
275 khiter_t k;
276
277 k = kh_put(iv, h, sym);
278 kh_value(h, k) = val;
279 }
280
281 static int
282 iv_get(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp)
e0d6430 @mimaki add mruby sources
mimaki authored
283 {
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
284 khash_t(iv) *h = &t->h;
e0d6430 @mimaki add mruby sources
mimaki authored
285 khiter_t k;
286
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
287 k = kh_get(iv, h, sym);
288 if (k != kh_end(h)) {
289 if (vp) *vp = kh_value(h, k);
1ed39d5 @matz use TRUE/FALSE instead of 1/0
matz authored
290 return TRUE;
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
291 }
1ed39d5 @matz use TRUE/FALSE instead of 1/0
matz authored
292 return FALSE;
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
293 }
294
295 static int
296 iv_del(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp)
297 {
298 khash_t(iv) *h = &t->h;
299 khiter_t k;
300
301 if (h) {
302 k = kh_get(iv, h, sym);
303 if (k != kh_end(h)) {
304 mrb_value val = kh_value(h, k);
305 kh_del(iv, h, k);
306 if (vp) *vp = val;
1ed39d5 @matz use TRUE/FALSE instead of 1/0
matz authored
307 return TRUE;
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
308 }
309 }
1ed39d5 @matz use TRUE/FALSE instead of 1/0
matz authored
310 return FALSE;
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
311 }
312
313 static int
314 iv_foreach(mrb_state *mrb, iv_tbl *t, iv_foreach_func *func, void *p)
315 {
316 khash_t(iv) *h = &t->h;
317 khiter_t k;
318 int n;
319
320 if (h) {
321 for (k = kh_begin(h); k != kh_end(h); k++) {
322 if (kh_exist(h, k)){
323 n = (*func)(mrb, kh_key(h, k), kh_value(h, k), p);
1ed39d5 @matz use TRUE/FALSE instead of 1/0
matz authored
324 if (n > 0) return FALSE;
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
325 if (n < 0) {
326 kh_del(iv, h, k);
327 }
328 }
329 }
330 }
1ed39d5 @matz use TRUE/FALSE instead of 1/0
matz authored
331 return TRUE;
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
332 }
333
334 static int
335 iv_size(mrb_state *mrb, iv_tbl *t)
336 {
337 khash_t(iv) *h = &t->h;
338
339 if (!h) return 0;
340 return kh_size(h);
341 }
342
343 static iv_tbl*
344 iv_copy(mrb_state *mrb, iv_tbl *t)
345 {
346 return (iv_tbl*)kh_copy(iv, mrb, &t->h);
347 }
348
349 static void
350 iv_free(mrb_state *mrb, iv_tbl *t)
351 {
352 kh_destroy(iv, &t->h);
353 }
354
355 #endif
356
357 static int
358 iv_mark_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p)
359 {
360 mrb_gc_mark_value(mrb, v);
361 return 0;
362 }
363
364 static void
365 mark_tbl(mrb_state *mrb, iv_tbl *t)
366 {
367 if (t) {
368 iv_foreach(mrb, t, iv_mark_i, 0);
369 }
e0d6430 @mimaki add mruby sources
mimaki authored
370 }
371
372 void
373 mrb_gc_mark_gv(mrb_state *mrb)
374 {
375 mark_tbl(mrb, mrb->globals);
376 }
377
378 void
379 mrb_gc_free_gv(mrb_state *mrb)
380 {
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
381 if (mrb->globals)
382 iv_free(mrb, mrb->globals);
e0d6430 @mimaki add mruby sources
mimaki authored
383 }
384
385 void
386 mrb_gc_mark_iv(mrb_state *mrb, struct RObject *obj)
387 {
388 mark_tbl(mrb, obj->iv);
389 }
390
391 size_t
392 mrb_gc_mark_iv_size(mrb_state *mrb, struct RObject *obj)
393 {
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
394 return iv_size(mrb, obj->iv);
e0d6430 @mimaki add mruby sources
mimaki authored
395 }
396
397 void
398 mrb_gc_free_iv(mrb_state *mrb, struct RObject *obj)
399 {
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
400 if (obj->iv) {
401 iv_free(mrb, obj->iv);
402 }
e0d6430 @mimaki add mruby sources
mimaki authored
403 }
404
405 mrb_value
406 mrb_vm_special_get(mrb_state *mrb, mrb_sym i)
407 {
408 return mrb_fixnum_value(0);
409 }
410
411 void
412 mrb_vm_special_set(mrb_state *mrb, mrb_sym i, mrb_value v)
413 {
414 }
415
396397b @matz move KHASH_DECLARE to header files
matz authored
416 static int
417 obj_iv_p(mrb_value obj)
418 {
419 switch (mrb_type(obj)) {
420 case MRB_TT_OBJECT:
421 case MRB_TT_CLASS:
422 case MRB_TT_MODULE:
423 case MRB_TT_HASH:
424 case MRB_TT_DATA:
425 return TRUE;
426 default:
427 return FALSE;
428 }
429 }
430
e0d6430 @mimaki add mruby sources
mimaki authored
431 mrb_value
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
432 mrb_obj_iv_get(mrb_state *mrb, struct RObject *obj, mrb_sym sym)
433 {
434 mrb_value v;
435
436 if (obj->iv && iv_get(mrb, obj->iv, sym, &v))
437 return v;
438 return mrb_nil_value();
439 }
440
441 mrb_value
e0d6430 @mimaki add mruby sources
mimaki authored
442 mrb_iv_get(mrb_state *mrb, mrb_value obj, mrb_sym sym)
443 {
396397b @matz move KHASH_DECLARE to header files
matz authored
444 if (obj_iv_p(obj)) {
445 return mrb_obj_iv_get(mrb, mrb_obj_ptr(obj), sym);
446 }
447 return mrb_nil_value();
e0d6430 @mimaki add mruby sources
mimaki authored
448 }
449
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
450 void
451 mrb_obj_iv_set(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v)
e0d6430 @mimaki add mruby sources
mimaki authored
452 {
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
453 iv_tbl *t = obj->iv;
e0d6430 @mimaki add mruby sources
mimaki authored
454
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
455 if (!t) {
456 t = obj->iv = iv_new(mrb);
457 }
458 mrb_write_barrier(mrb, (struct RBasic*)obj);
459 iv_put(mrb, t, sym, v);
e0d6430 @mimaki add mruby sources
mimaki authored
460 }
461
462 void
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
463 mrb_iv_set(mrb_state *mrb, mrb_value obj, mrb_sym sym, mrb_value v)
e0d6430 @mimaki add mruby sources
mimaki authored
464 {
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
465 if (obj_iv_p(obj)) {
466 mrb_obj_iv_set(mrb, mrb_obj_ptr(obj), sym, v);
e0d6430 @mimaki add mruby sources
mimaki authored
467 }
468 else {
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
469 mrb_raise(mrb, E_ARGUMENT_ERROR, "cannot set instance variable");
e0d6430 @mimaki add mruby sources
mimaki authored
470 }
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
471 }
472
473 int
474 mrb_obj_iv_defined(mrb_state *mrb, struct RObject *obj, mrb_sym sym)
475 {
476 iv_tbl *t;
477
478 t = obj->iv;
479 if (t) {
480 return iv_get(mrb, t, sym, NULL);
481 }
1ed39d5 @matz use TRUE/FALSE instead of 1/0
matz authored
482 return FALSE;
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
483 }
484
485 int
486 mrb_iv_defined(mrb_state *mrb, mrb_value obj, mrb_sym sym)
487 {
1ed39d5 @matz use TRUE/FALSE instead of 1/0
matz authored
488 if (!obj_iv_p(obj)) return FALSE;
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
489 return mrb_obj_iv_defined(mrb, mrb_obj_ptr(obj), sym);
e0d6430 @mimaki add mruby sources
mimaki authored
490 }
491
492 void
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
493 mrb_iv_copy(mrb_state *mrb, mrb_value dest, mrb_value src)
e0d6430 @mimaki add mruby sources
mimaki authored
494 {
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
495 struct RObject *d = mrb_obj_ptr(dest);
496 struct RObject *s = mrb_obj_ptr(src);
497
498 if (d->iv) {
499 iv_free(mrb, d->iv);
500 d->iv = 0;
396397b @matz move KHASH_DECLARE to header files
matz authored
501 }
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
502 if (s->iv) {
503 d->iv = iv_copy(mrb, s->iv);
504 }
505 }
506
507 static int
508 inspect_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p)
509 {
510 mrb_value str = *(mrb_value*)p;
511 const char *s;
512 int len;
513
514 /* need not to show internal data */
515 if (RSTRING_PTR(str)[0] == '-') { /* first element */
516 RSTRING_PTR(str)[0] = '#';
517 mrb_str_cat2(mrb, str, " ");
518 }
519 else {
520 mrb_str_cat2(mrb, str, ", ");
521 }
522 s = mrb_sym2name_len(mrb, sym, &len);
523 mrb_str_cat(mrb, str, s, len);
524 mrb_str_cat(mrb, str, "=", 1);
525 mrb_str_append(mrb, str, mrb_inspect(mrb, v));
526 return 0;
396397b @matz move KHASH_DECLARE to header files
matz authored
527 }
528
529 mrb_value
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
530 mrb_obj_iv_inspect(mrb_state *mrb, struct RObject *obj)
396397b @matz move KHASH_DECLARE to header files
matz authored
531 {
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
532 iv_tbl *t = obj->iv;
533 int len = iv_size(mrb, t);
396397b @matz move KHASH_DECLARE to header files
matz authored
534
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
535 if (len > 0) {
536 const char *cn = mrb_obj_classname(mrb, mrb_obj_value(obj));
537 mrb_value str = mrb_sprintf(mrb, "-<%s:%p", cn, (void*)obj);
538
539 iv_foreach(mrb, t, inspect_i, &str);
540 return str;
541 }
542 return mrb_any_to_s(mrb, mrb_obj_value(obj));
543 }
544
545 mrb_value
546 mrb_iv_remove(mrb_state *mrb, mrb_value obj, mrb_sym sym)
547 {
396397b @matz move KHASH_DECLARE to header files
matz authored
548 if (obj_iv_p(obj)) {
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
549 iv_tbl *t = mrb_obj_ptr(obj)->iv;
550 mrb_value val;
551
e79c38b @masamitsu-murase Check iv.
masamitsu-murase authored
552 if (t && iv_del(mrb, t, sym, &val)) {
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
553 return val;
396397b @matz move KHASH_DECLARE to header files
matz authored
554 }
555 }
556 return mrb_undef_value();
e0d6430 @mimaki add mruby sources
mimaki authored
557 }
558
559 mrb_value
560 mrb_vm_iv_get(mrb_state *mrb, mrb_sym sym)
561 {
562 /* get self */
563 return mrb_iv_get(mrb, mrb->stack[0], sym);
564 }
565
566 void
567 mrb_vm_iv_set(mrb_state *mrb, mrb_sym sym, mrb_value v)
568 {
569 /* get self */
570 mrb_iv_set(mrb, mrb->stack[0], sym, v);
571 }
572
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
573 static int
574 iv_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p)
575 {
576 mrb_value ary;
577 const char* s;
578 int len;
579
580 ary = *(mrb_value*)p;
581 s = mrb_sym2name_len(mrb, sym, &len);
582 if (len > 1 && s[0] == '@') {
583 mrb_ary_push(mrb, ary, mrb_symbol_value(sym));
584 }
585 return 0;
586 }
587
1fa6393 @matz check object type before retrieving instance variabls; close #311
matz authored
588 /* 15.3.1.3.23 */
589 /*
590 * call-seq:
591 * obj.instance_variables -> array
592 *
593 * Returns an array of instance variable names for the receiver. Note
594 * that simply defining an accessor does not create the corresponding
595 * instance variable.
596 *
597 * class Fred
598 * attr_accessor :a1
599 * def initialize
600 * @iv = 3
601 * end
602 * end
603 * Fred.new.instance_variables #=> [:@iv]
604 */
605 mrb_value
606 mrb_obj_instance_variables(mrb_state *mrb, mrb_value self)
607 {
608 mrb_value ary;
609
610 ary = mrb_ary_new(mrb);
59bf47e @matz iv table may be empty
matz authored
611 if (obj_iv_p(self) && mrb_obj_ptr(self)->iv) {
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
612 iv_foreach(mrb, mrb_obj_ptr(self)->iv, iv_i, &ary);
1fa6393 @matz check object type before retrieving instance variabls; close #311
matz authored
613 }
614 return ary;
615 }
616
e0d6430 @mimaki add mruby sources
mimaki authored
617 mrb_value
618 mrb_vm_cv_get(mrb_state *mrb, mrb_sym sym)
619 {
52ba6f5 @matz class variable resolution should be same as const resolution
matz authored
620 struct RClass *c = mrb->ci->proc->target_class;
e0d6430 @mimaki add mruby sources
mimaki authored
621
52ba6f5 @matz class variable resolution should be same as const resolution
matz authored
622 if (!c) c = mrb->ci->target_class;
e0d6430 @mimaki add mruby sources
mimaki authored
623 while (c) {
624 if (c->iv) {
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
625 iv_tbl *t = c->iv;
626 mrb_value v;
e0d6430 @mimaki add mruby sources
mimaki authored
627
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
628 if (iv_get(mrb, t, sym, &v))
629 return v;
e0d6430 @mimaki add mruby sources
mimaki authored
630 }
631 c = c->super;
632 }
633 return mrb_nil_value();
634 }
635
636 void
637 mrb_vm_cv_set(mrb_state *mrb, mrb_sym sym, mrb_value v)
638 {
52ba6f5 @matz class variable resolution should be same as const resolution
matz authored
639 struct RClass *c = mrb->ci->proc->target_class;
e0d6430 @mimaki add mruby sources
mimaki authored
640
52ba6f5 @matz class variable resolution should be same as const resolution
matz authored
641 if (!c) c = mrb->ci->target_class;
e0d6430 @mimaki add mruby sources
mimaki authored
642 while (c) {
643 if (c->iv) {
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
644 iv_tbl *t = c->iv;
645
646 if (iv_get(mrb, t, sym, NULL)) {
647 iv_put(mrb, t, sym, v);
e473ce1 @masuidrive fixed const_get && const_missing issue
masuidrive authored
648 return;
e0d6430 @mimaki add mruby sources
mimaki authored
649 }
650 }
651 c = c->super;
652 }
653 c = mrb->ci->target_class;
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
654 if (!c->iv) {
655 c->iv = iv_new(mrb);
84c5d35 @matz class variable table intialization bug; close #206
matz authored
656 }
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
657 iv_put(mrb, c->iv, sym, v);
e0d6430 @mimaki add mruby sources
mimaki authored
658 }
659
660 int
661 mrb_const_defined(mrb_state *mrb, mrb_value mod, mrb_sym sym)
662 {
663 struct RClass *m = mrb_class_ptr(mod);
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
664 iv_tbl *t = m->iv;
e0d6430 @mimaki add mruby sources
mimaki authored
665
1ed39d5 @matz use TRUE/FALSE instead of 1/0
matz authored
666 if (!t) return FALSE;
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
667 return iv_get(mrb, t, sym, NULL);
e0d6430 @mimaki add mruby sources
mimaki authored
668 }
669
670 static void
671 mod_const_check(mrb_state *mrb, mrb_value mod)
672 {
7d02df3 @matz NaN boxing
matz authored
673 switch (mrb_type(mod)) {
e0d6430 @mimaki add mruby sources
mimaki authored
674 case MRB_TT_CLASS:
675 case MRB_TT_MODULE:
676 break;
677 default:
678 mrb_raise(mrb, E_TYPE_ERROR, "constant look-up for non class/module");
679 break;
680 }
681 }
682
683 static mrb_value
684 const_get(mrb_state *mrb, struct RClass *base, mrb_sym sym)
685 {
686 struct RClass *c = base;
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
687 mrb_value v;
688 iv_tbl *t;
b00529e @matz reduce invoking const_missing
matz authored
689 int retry = 0;
690 mrb_sym cm;
e0d6430 @mimaki add mruby sources
mimaki authored
691
8bc506e @matz a bug in contant reference from modules
matz authored
692 L_RETRY:
e0d6430 @mimaki add mruby sources
mimaki authored
693 while (c) {
694 if (c->iv) {
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
695 t = c->iv;
696 if (iv_get(mrb, t, sym, &v))
697 return v;
e0d6430 @mimaki add mruby sources
mimaki authored
698 }
699 c = c->super;
700 }
b00529e @matz reduce invoking const_missing
matz authored
701 if (!retry && base->tt == MRB_TT_MODULE) {
702 c = mrb->object_class;
703 retry = 1;
8bc506e @matz a bug in contant reference from modules
matz authored
704 goto L_RETRY;
705 }
b00529e @matz reduce invoking const_missing
matz authored
706 c = base;
707 cm = mrb_intern(mrb, "const_missing");
708 while (c) {
709 if (mrb_respond_to(mrb, mrb_obj_value(c), cm)) {
710 mrb_value name = mrb_symbol_value(sym);
e5dde46 @matz reduce mrb_funcall invocations
matz authored
711 return mrb_funcall_argv(mrb, mrb_obj_value(c), cm, 1, &name);
b00529e @matz reduce invoking const_missing
matz authored
712 }
713 c = c->super;
714 }
e0d6430 @mimaki add mruby sources
mimaki authored
715 mrb_raise(mrb, E_NAME_ERROR, "uninitialized constant %s",
4ec6d41 rm whitespace
roco authored
716 mrb_sym2name(mrb, sym));
e0d6430 @mimaki add mruby sources
mimaki authored
717 /* not reached */
718 return mrb_nil_value();
719 }
720
721 mrb_value
722 mrb_const_get(mrb_state *mrb, mrb_value mod, mrb_sym sym)
723 {
724 mod_const_check(mrb, mod);
725 return const_get(mrb, mrb_class_ptr(mod), sym);
726 }
727
728 mrb_value
729 mrb_vm_const_get(mrb_state *mrb, mrb_sym sym)
730 {
08213e3 @matz const reference from instance_eval should not cause SEGV
matz authored
731 struct RClass *c = mrb->ci->proc->target_class;
732
733 if (!c) c = mrb->ci->target_class;
734 return const_get(mrb, c, sym);
e0d6430 @mimaki add mruby sources
mimaki authored
735 }
736
737 void
738 mrb_const_set(mrb_state *mrb, mrb_value mod, mrb_sym sym, mrb_value v)
739 {
740 mod_const_check(mrb, mod);
741 mrb_iv_set(mrb, mod, sym, v);
742 }
743
744 void
745 mrb_vm_const_set(mrb_state *mrb, mrb_sym sym, mrb_value v)
746 {
08213e3 @matz const reference from instance_eval should not cause SEGV
matz authored
747 struct RClass *c = mrb->ci->proc->target_class;
748
749 if (!c) c = mrb->ci->target_class;
fd086a7 @matz replace mrb_iv_set by mrb_obj_iv_set
matz authored
750 mrb_obj_iv_set(mrb, (struct RObject*)c, sym, v);
e0d6430 @mimaki add mruby sources
mimaki authored
751 }
752
753 void
754 mrb_define_const(mrb_state *mrb, struct RClass *mod, const char *name, mrb_value v)
755 {
fd086a7 @matz replace mrb_iv_set by mrb_obj_iv_set
matz authored
756 mrb_obj_iv_set(mrb, (struct RObject*)mod, mrb_intern(mrb, name), v);
e0d6430 @mimaki add mruby sources
mimaki authored
757 }
758
759 void
760 mrb_define_global_const(mrb_state *mrb, const char *name, mrb_value val)
761 {
762 mrb_define_const(mrb, mrb->object_class, name, val);
763 }
764
765 mrb_value
766 mrb_gv_get(mrb_state *mrb, mrb_sym sym)
767 {
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
768 mrb_value v;
769
e0d6430 @mimaki add mruby sources
mimaki authored
770 if (!mrb->globals) {
771 return mrb_nil_value();
772 }
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
773 if (iv_get(mrb, mrb->globals, sym, &v))
774 return v;
775 return mrb_nil_value();
e0d6430 @mimaki add mruby sources
mimaki authored
776 }
777
778 void
779 mrb_gv_set(mrb_state *mrb, mrb_sym sym, mrb_value v)
780 {
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
781 iv_tbl *t;
e0d6430 @mimaki add mruby sources
mimaki authored
782
783 if (!mrb->globals) {
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
784 t = mrb->globals = iv_new(mrb);
e0d6430 @mimaki add mruby sources
mimaki authored
785 }
786 else {
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
787 t = mrb->globals;
e0d6430 @mimaki add mruby sources
mimaki authored
788 }
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
789 iv_put(mrb, t, sym, v);
790 }
791
792 static int
793 gv_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p)
794 {
795 mrb_value ary;
796
797 ary = *(mrb_value*)p;
798 mrb_ary_push(mrb, ary, mrb_symbol_value(sym));
799 return 0;
e0d6430 @mimaki add mruby sources
mimaki authored
800 }
801
802 /* 15.3.1.2.4 */
803 /* 15.3.1.3.14 */
804 /*
805 * call-seq:
806 * global_variables -> array
807 *
808 * Returns an array of the names of global variables.
809 *
810 * global_variables.grep /std/ #=> [:$stdin, :$stdout, :$stderr]
811 */
812 mrb_value
813 mrb_f_global_variables(mrb_state *mrb, mrb_value self)
814 {
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
815 iv_tbl *t = mrb->globals;
e0d6430 @mimaki add mruby sources
mimaki authored
816 mrb_value ary = mrb_ary_new(mrb);
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
817 int i;
818 char buf[3];
e0d6430 @mimaki add mruby sources
mimaki authored
819
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
820 if (t) {
821 iv_foreach(mrb, t, gv_i, &ary);
e0d6430 @mimaki add mruby sources
mimaki authored
822 }
823 buf[0] = '$';
824 buf[2] = 0;
825 for (i = 1; i <= 9; ++i) {
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
826 buf[1] = (char)(i + '0');
827 mrb_ary_push(mrb, ary, mrb_symbol_value(mrb_intern2(mrb, buf, 2)));
e0d6430 @mimaki add mruby sources
mimaki authored
828 }
829 return ary;
830 }
831
832 static int
833 mrb_const_defined_0(mrb_state *mrb, struct RClass *klass, mrb_sym id, int exclude, int recurse)
834 {
835 struct RClass * tmp;
836 int mod_retry = 0;
837
838 tmp = klass;
839 retry:
840 while (tmp) {
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
841 if (tmp->iv && iv_get(mrb, tmp->iv, id, NULL)) {
1ed39d5 @matz use TRUE/FALSE instead of 1/0
matz authored
842 return TRUE;
e0d6430 @mimaki add mruby sources
mimaki authored
843 }
844 if (!recurse && (klass != mrb->object_class)) break;
845 tmp = tmp->super;
846 }
847 if (!exclude && !mod_retry && (klass->tt == MRB_TT_MODULE)) {
848 mod_retry = 1;
849 tmp = mrb->object_class;
850 goto retry;
851 }
1ed39d5 @matz use TRUE/FALSE instead of 1/0
matz authored
852 return FALSE;
e0d6430 @mimaki add mruby sources
mimaki authored
853 }
854
855 int
856 mrb_const_defined_at(mrb_state *mrb, struct RClass *klass, mrb_sym id)
857 {
858 return mrb_const_defined_0(mrb, klass, id, TRUE, FALSE);
859 }
860
861 mrb_value
862 mrb_attr_get(mrb_state *mrb, mrb_value obj, mrb_sym id)
863 {
864 return mrb_iv_get(mrb, obj, id);
865 }
866
867 struct RClass *
11b6366 @masuidrive add const to char*
masuidrive authored
868 mrb_class_obj_get(mrb_state *mrb, const char *name)
e0d6430 @mimaki add mruby sources
mimaki authored
869 {
870 mrb_value mod = mrb_obj_value(mrb->object_class);
871 mrb_sym sym = mrb_intern(mrb, name);
872
873 return mrb_class_ptr(mrb_const_get(mrb, mod, sym));
874 }
875
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
876 struct csym_arg {
877 struct RClass *c;
878 mrb_sym sym;
879 };
880
881 static int
882 csym_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p)
883 {
884 struct csym_arg *a = (struct csym_arg*)p;
885 struct RClass *c = a->c;
886
887 if (mrb_type(v) == c->tt && mrb_class_ptr(v) == c) {
888 a->sym = sym;
1ed39d5 @matz use TRUE/FALSE instead of 1/0
matz authored
889 return 1; /* stop iteration */
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
890 }
891 return 0;
892 }
893
894 mrb_sym
895 mrb_class_sym(mrb_state *mrb, struct RClass *c, struct RClass *outer)
896 {
897 mrb_value name;
898
899 name = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern(mrb, "__classid__"));
900 if (mrb_nil_p(name)) {
901
38c4a31 @matz outer might be NULL; close #428
matz authored
902 if (!outer) return 0;
903 else {
904 struct csym_arg arg;
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
905
38c4a31 @matz outer might be NULL; close #428
matz authored
906 arg.c = c;
907 arg.sym = 0;
908 iv_foreach(mrb, outer->iv, csym_i, &arg);
909 return arg.sym;
910 }
c9fe903 @matz now segmented list can be used as instance variable tables by -DMRB_U…
matz authored
911 }
912 return SYM2ID(name);
913 }
Something went wrong with that request. Please try again.