diff options
Diffstat (limited to 'src/variable.c')
| -rw-r--r-- | src/variable.c | 465 |
1 files changed, 247 insertions, 218 deletions
diff --git a/src/variable.c b/src/variable.c index 72c13aa1f..d89295229 100644 --- a/src/variable.c +++ b/src/variable.c @@ -9,24 +9,19 @@ #include <mruby/class.h> #include <mruby/proc.h> #include <mruby/string.h> +#include <mruby/variable.h> +#include <mruby/presym.h> -typedef int (iv_foreach_func)(mrb_state*,mrb_sym,mrb_value,void*); - -#ifndef MRB_IV_SEGMENT_SIZE -#define MRB_IV_SEGMENT_SIZE 4 -#endif - -typedef struct segment { - mrb_sym key[MRB_IV_SEGMENT_SIZE]; - mrb_value val[MRB_IV_SEGMENT_SIZE]; - struct segment *next; -} segment; +struct iv_elem { + mrb_sym key; + mrb_value val; +}; /* Instance variable table structure */ typedef struct iv_tbl { - segment *rootseg; size_t size; - size_t last_len; + size_t alloc; + struct iv_elem *table; } iv_tbl; /* Creates the instance variable table. */ @@ -37,67 +32,82 @@ iv_new(mrb_state *mrb) t = (iv_tbl*)mrb_malloc(mrb, sizeof(iv_tbl)); t->size = 0; - t->rootseg = NULL; - t->last_len = 0; + t->alloc = 0; + t->table = NULL; return t; } +static void iv_put(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value val); + +static void +iv_rehash(mrb_state *mrb, iv_tbl *t) +{ + size_t old_alloc = t->alloc; + size_t new_alloc = old_alloc+1; + struct iv_elem *old_table = t->table; + + khash_power2(new_alloc); + if (old_alloc == new_alloc) return; + + t->alloc = new_alloc; + t->size = 0; + t->table = (struct iv_elem*)mrb_calloc(mrb, sizeof(struct iv_elem), new_alloc); + + for (size_t i = 0; i < old_alloc; i++) { + struct iv_elem *slot = &old_table[i]; + + /* key = 0 means empty; val = undef means deleted */ + if (slot->key != 0 && !mrb_undef_p(slot->val)) { + iv_put(mrb, t, slot->key, slot->val); + } + } + mrb_free(mrb, old_table); +} + +#define slot_empty_p(slot) ((slot)->key == 0 && !mrb_undef_p((slot)->val)) + /* Set the value for the symbol in the instance variable table. */ static void iv_put(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value val) { - segment *seg; - segment *prev = NULL; - segment *matched_seg = NULL; - size_t matched_idx = 0; - size_t i; + size_t hash, pos, start; + struct iv_elem *dslot = NULL; if (t == NULL) return; - seg = t->rootseg; - while (seg) { - for (i=0; i<MRB_IV_SEGMENT_SIZE; i++) { - mrb_sym key = seg->key[i]; - /* Found room in last segment after last_len */ - if (!seg->next && i >= t->last_len) { - seg->key[i] = sym; - seg->val[i] = val; - t->last_len = i+1; + if (t->alloc == 0) { + iv_rehash(mrb, t); + } + hash = kh_int_hash_func(mrb, sym); + start = pos = hash & (t->alloc-1); + for (;;) { + struct iv_elem *slot = &t->table[pos]; + + if (slot->key == sym) { + slot->val = val; + return; + } + else if (slot_empty_p(slot)) { + t->size++; + slot->key = sym; + slot->val = val; + return; + } + else if (!dslot && mrb_undef_p(slot->val)) { /* deleted */ + dslot = slot; + } + pos = (pos+1) & (t->alloc-1); + if (pos == start) { /* not found */ + if (dslot) { t->size++; + dslot->key = sym; + dslot->val = val; return; } - if (!matched_seg && key == 0) { - matched_seg = seg; - matched_idx = i; - } - else if (key == sym) { - seg->val[i] = val; - return; - } + /* no room */ + iv_rehash(mrb, t); + start = pos = hash & (t->alloc-1); } - prev = seg; - seg = seg->next; - } - - /* Not found */ - t->size++; - if (matched_seg) { - matched_seg->key[matched_idx] = sym; - matched_seg->val[matched_idx] = val; - return; - } - - seg = (segment*)mrb_malloc(mrb, sizeof(segment)); - if (!seg) return; - seg->next = NULL; - seg->key[0] = sym; - seg->val[0] = val; - t->last_len = 1; - if (prev) { - prev->next = seg; - } - else { - t->rootseg = seg; } } @@ -105,133 +115,111 @@ iv_put(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value val) static mrb_bool iv_get(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp) { - segment *seg; - size_t i; + size_t hash, pos, start; if (t == NULL) return FALSE; - seg = t->rootseg; - while (seg) { - for (i=0; i<MRB_IV_SEGMENT_SIZE; i++) { - mrb_sym key = seg->key[i]; + if (t->alloc == 0) return FALSE; + if (t->size == 0) return FALSE; - if (!seg->next && i >= t->last_len) { - return FALSE; - } - if (key == sym) { - if (vp) *vp = seg->val[i]; - return TRUE; - } + hash = kh_int_hash_func(mrb, sym); + start = pos = hash & (t->alloc-1); + for (;;) { + struct iv_elem *slot = &t->table[pos]; + + if (slot->key == sym) { + if (vp) *vp = slot->val; + return TRUE; + } + else if (slot_empty_p(slot)) { + return FALSE; + } + pos = (pos+1) & (t->alloc-1); + if (pos == start) { /* not found */ + return FALSE; } - seg = seg->next; } - return FALSE; } /* Deletes the value for the symbol from the instance variable table. */ static mrb_bool iv_del(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp) { - segment *seg; - size_t i; + size_t hash, pos, start; if (t == NULL) return FALSE; - seg = t->rootseg; - while (seg) { - for (i=0; i<MRB_IV_SEGMENT_SIZE; i++) { - mrb_sym key = seg->key[i]; + if (t->alloc == 0) return FALSE; + if (t->size == 0) return FALSE; - if (!seg->next && i >= t->last_len) { - return FALSE; - } - if (key == sym) { - t->size--; - seg->key[i] = 0; - if (vp) *vp = seg->val[i]; - return TRUE; - } + hash = kh_int_hash_func(mrb, sym); + start = pos = hash & (t->alloc-1); + for (;;) { + struct iv_elem *slot = &t->table[pos]; + + if (slot->key == sym) { + if (vp) *vp = slot->val; + t->size--; + slot->key = 0; + slot->val = mrb_undef_value(); + return TRUE; + } + else if (slot_empty_p(slot)) { + return FALSE; + } + pos = (pos+1) & (t->alloc-1); + if (pos == start) { /* not found */ + return FALSE; } - seg = seg->next; } - return FALSE; } /* Iterates over the instance variable table. */ -static mrb_bool -iv_foreach(mrb_state *mrb, iv_tbl *t, iv_foreach_func *func, void *p) +static void +iv_foreach(mrb_state *mrb, iv_tbl *t, mrb_iv_foreach_func *func, void *p) { - segment *seg; size_t i; - int n; - if (t == NULL) return TRUE; - seg = t->rootseg; - while (seg) { - for (i=0; i<MRB_IV_SEGMENT_SIZE; i++) { - mrb_sym key = seg->key[i]; + if (t == NULL) return; + if (t->alloc == 0) return; + if (t->size == 0) return; - /* no value in last segment after last_len */ - if (!seg->next && i >= t->last_len) { - return FALSE; - } - if (key != 0) { - n =(*func)(mrb, key, seg->val[i], p); - if (n > 0) return FALSE; - if (n < 0) { - t->size--; - seg->key[i] = 0; - } + for (i=0; i<t->alloc; i++) { + struct iv_elem *slot = &t->table[i]; + + if (slot->key && !mrb_undef_p(slot->val)) { + if ((*func)(mrb, slot->key, slot->val, p) != 0) { + return; } } - seg = seg->next; } - return TRUE; + return; } /* Get the size of the instance variable table. */ static size_t iv_size(mrb_state *mrb, iv_tbl *t) { - segment *seg; - size_t size = 0; - if (t == NULL) return 0; - if (t->size > 0) return t->size; - seg = t->rootseg; - while (seg) { - if (seg->next == NULL) { - size += t->last_len; - return size; - } - seg = seg->next; - size += MRB_IV_SEGMENT_SIZE; - } - /* empty iv_tbl */ - return 0; + return t->size; } /* Copy the instance variable table. */ static iv_tbl* iv_copy(mrb_state *mrb, iv_tbl *t) { - segment *seg; iv_tbl *t2; - size_t i; - seg = t->rootseg; - t2 = iv_new(mrb); + if (t == NULL) return NULL; + if (t->alloc == 0) return NULL; + if (t->size == 0) return NULL; - while (seg != NULL) { - for (i=0; i<MRB_IV_SEGMENT_SIZE; i++) { - mrb_sym key = seg->key[i]; - mrb_value val = seg->val[i]; + t2 = iv_new(mrb); + for (i=0; i<t->alloc; i++) { + struct iv_elem *slot = &t->table[i]; - if ((seg->next == NULL) && (i >= t->last_len)) { - return t2; - } - iv_put(mrb, t2, key, val); + if (slot->key && !mrb_undef_p(slot->val)) { + iv_put(mrb, t2, slot->key, slot->val); } - seg = seg->next; } return t2; } @@ -240,14 +228,7 @@ iv_copy(mrb_state *mrb, iv_tbl *t) static void iv_free(mrb_state *mrb, iv_tbl *t) { - segment *seg; - - seg = t->rootseg; - while (seg) { - segment *p = seg; - seg = seg->next; - mrb_free(mrb, p); - } + mrb_free(mrb, t->table); mrb_free(mrb, t); } @@ -346,21 +327,30 @@ mrb_iv_get(mrb_state *mrb, mrb_value obj, mrb_sym sym) static inline void assign_class_name(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v); -MRB_API void -mrb_obj_iv_set(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v) +void +mrb_obj_iv_set_force(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v) { - iv_tbl *t; - - if (MRB_FROZEN_P(obj)) { - mrb_raisef(mrb, E_FROZEN_ERROR, "can't modify frozen %S", mrb_obj_value(obj)); - } assign_class_name(mrb, obj, sym, v); if (!obj->iv) { obj->iv = iv_new(mrb); } - t = obj->iv; - iv_put(mrb, t, sym, v); - mrb_write_barrier(mrb, (struct RBasic*)obj); + iv_put(mrb, obj->iv, sym, v); + mrb_field_write_barrier_value(mrb, (struct RBasic*)obj, v); +} + +MRB_API void +mrb_obj_iv_set(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v) +{ + mrb_check_frozen(mrb, obj); + mrb_obj_iv_set_force(mrb, obj, sym, v); +} + +/* Iterates over the instance variable table. */ +MRB_API void +mrb_iv_foreach(mrb_state *mrb, mrb_value obj, mrb_iv_foreach_func *func, void *p) +{ + if (!obj_iv_p(obj)) return; + iv_foreach(mrb, mrb_obj_ptr(obj)->iv, func, p); } static inline mrb_bool @@ -374,20 +364,20 @@ assign_class_name(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v) { if (namespace_p(obj->tt) && namespace_p(mrb_type(v))) { struct RObject *c = mrb_obj_ptr(v); - if (obj != c && ISUPPER(mrb_sym2name(mrb, sym)[0])) { - mrb_sym id_classname = mrb_intern_lit(mrb, "__classname__"); + if (obj != c && ISUPPER(mrb_sym_name_len(mrb, sym, NULL)[0])) { + mrb_sym id_classname = MRB_SYM(__classname__); mrb_value o = mrb_obj_iv_get(mrb, c, id_classname); if (mrb_nil_p(o)) { - mrb_sym id_outer = mrb_intern_lit(mrb, "__outer__"); + mrb_sym id_outer = MRB_SYM(__outer__); o = mrb_obj_iv_get(mrb, c, id_outer); if (mrb_nil_p(o)) { if ((struct RClass *)obj == mrb->object_class) { - mrb_obj_iv_set(mrb, c, id_classname, mrb_symbol_value(sym)); + mrb_obj_iv_set_force(mrb, c, id_classname, mrb_symbol_value(sym)); } else { - mrb_obj_iv_set(mrb, c, id_outer, mrb_obj_value(obj)); + mrb_obj_iv_set_force(mrb, c, id_outer, mrb_obj_value(obj)); } } } @@ -425,29 +415,24 @@ mrb_iv_defined(mrb_state *mrb, mrb_value obj, mrb_sym sym) return mrb_obj_iv_defined(mrb, mrb_obj_ptr(obj), sym); } -#define identchar(c) (ISALNUM(c) || (c) == '_' || !ISASCII(c)) - MRB_API mrb_bool mrb_iv_name_sym_p(mrb_state *mrb, mrb_sym iv_name) { const char *s; - mrb_int i, len; + mrb_int len; - s = mrb_sym2name_len(mrb, iv_name, &len); + s = mrb_sym_name_len(mrb, iv_name, &len); if (len < 2) return FALSE; if (s[0] != '@') return FALSE; - if (s[1] == '@') return FALSE; - for (i=1; i<len; i++) { - if (!identchar(s[i])) return FALSE; - } - return TRUE; + if (ISDIGIT(s[1])) return FALSE; + return mrb_ident_p(s+1, len-1); } MRB_API void mrb_iv_name_sym_check(mrb_state *mrb, mrb_sym iv_name) { if (!mrb_iv_name_sym_p(mrb, iv_name)) { - mrb_name_error(mrb, iv_name, "'%S' is not allowed as an instance variable name", mrb_sym2str(mrb, iv_name)); + mrb_name_error(mrb, iv_name, "'%n' is not allowed as an instance variable name", iv_name); } } @@ -484,10 +469,10 @@ inspect_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p) else { mrb_str_cat_lit(mrb, str, ", "); } - s = mrb_sym2name_len(mrb, sym, &len); + s = mrb_sym_name_len(mrb, sym, &len); mrb_str_cat(mrb, str, s, len); mrb_str_cat_lit(mrb, str, "="); - if (mrb_type(v) == MRB_TT_OBJECT) { + if (mrb_object_p(v)) { ins = mrb_any_to_s(mrb, v); } else { @@ -510,7 +495,7 @@ mrb_obj_iv_inspect(mrb_state *mrb, struct RObject *obj) mrb_str_cat_lit(mrb, str, "-<"); mrb_str_cat_cstr(mrb, str, cn); mrb_str_cat_lit(mrb, str, ":"); - mrb_str_concat(mrb, str, mrb_ptr_to_str(mrb, obj)); + mrb_str_cat_str(mrb, str, mrb_ptr_to_str(mrb, obj)); iv_foreach(mrb, t, inspect_i, &str); mrb_str_cat_lit(mrb, str, ">"); @@ -526,6 +511,7 @@ mrb_iv_remove(mrb_state *mrb, mrb_value obj, mrb_sym sym) iv_tbl *t = mrb_obj_ptr(obj)->iv; mrb_value val; + mrb_check_frozen(mrb, mrb_obj_ptr(obj)); if (iv_del(mrb, t, sym, &val)) { return val; } @@ -541,7 +527,7 @@ iv_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p) mrb_int len; ary = *(mrb_value*)p; - s = mrb_sym2name_len(mrb, sym, &len); + s = mrb_sym_name_len(mrb, sym, &len); if (len > 1 && s[0] == '@' && s[1] != '@') { mrb_ary_push(mrb, ary, mrb_symbol_value(sym)); } @@ -585,7 +571,7 @@ cv_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p) mrb_int len; ary = *(mrb_value*)p; - s = mrb_sym2name_len(mrb, sym, &len); + s = mrb_sym_name_len(mrb, sym, &len); if (len > 2 && s[0] == '@' && s[1] == '@') { mrb_ary_push(mrb, ary, mrb_symbol_value(sym)); } @@ -595,7 +581,7 @@ cv_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p) /* 15.2.2.4.19 */ /* * call-seq: - * mod.class_variables -> array + * mod.class_variables(inherit=true) -> array * * Returns an array of the names of class variables in <i>mod</i>. * @@ -613,17 +599,20 @@ mrb_mod_class_variables(mrb_state *mrb, mrb_value mod) { mrb_value ary; struct RClass *c; + mrb_bool inherit = TRUE; + mrb_get_args(mrb, "|b", &inherit); ary = mrb_ary_new(mrb); c = mrb_class_ptr(mod); while (c) { iv_foreach(mrb, c->iv, cv_i, &ary); + if (!inherit) break; c = c->super; } return ary; } -MRB_API mrb_value +mrb_value mrb_mod_cv_get(mrb_state *mrb, struct RClass *c, mrb_sym sym) { struct RClass * cls = c; @@ -640,8 +629,7 @@ mrb_mod_cv_get(mrb_state *mrb, struct RClass *c, mrb_sym sym) if (cls && cls->tt == MRB_TT_SCLASS) { mrb_value klass; - klass = mrb_obj_iv_get(mrb, (struct RObject *)cls, - mrb_intern_lit(mrb, "__attached__")); + klass = mrb_obj_iv_get(mrb, (struct RObject *)cls, MRB_SYM(__attached__)); c = mrb_class_ptr(klass); if (c->tt == MRB_TT_CLASS || c->tt == MRB_TT_MODULE) { given = FALSE; @@ -654,8 +642,7 @@ mrb_mod_cv_get(mrb_state *mrb, struct RClass *c, mrb_sym sym) if (given) return v; } } - mrb_name_error(mrb, sym, "uninitialized class variable %S in %S", - mrb_sym2str(mrb, sym), mrb_obj_value(cls)); + mrb_name_error(mrb, sym, "uninitialized class variable %n in %C", sym, cls); /* not reached */ return mrb_nil_value(); } @@ -675,8 +662,9 @@ mrb_mod_cv_set(mrb_state *mrb, struct RClass *c, mrb_sym sym, mrb_value v) iv_tbl *t = c->iv; if (iv_get(mrb, t, sym, NULL)) { + mrb_check_frozen(mrb, c); iv_put(mrb, t, sym, v); - mrb_write_barrier(mrb, (struct RBasic*)c); + mrb_field_write_barrier_value(mrb, (struct RBasic*)c, v); return; } c = c->super; @@ -685,8 +673,7 @@ mrb_mod_cv_set(mrb_state *mrb, struct RClass *c, mrb_sym sym, mrb_value v) if (cls && cls->tt == MRB_TT_SCLASS) { mrb_value klass; - klass = mrb_obj_iv_get(mrb, (struct RObject*)cls, - mrb_intern_lit(mrb, "__attached__")); + klass = mrb_obj_iv_get(mrb, (struct RObject*)cls, MRB_SYM(__attached__)); switch (mrb_type(klass)) { case MRB_TT_CLASS: case MRB_TT_MODULE: @@ -702,12 +689,13 @@ mrb_mod_cv_set(mrb_state *mrb, struct RClass *c, mrb_sym sym, mrb_value v) c = cls; } + mrb_check_frozen(mrb, c); if (!c->iv) { c->iv = iv_new(mrb); } iv_put(mrb, c->iv, sym, v); - mrb_write_barrier(mrb, (struct RBasic*)c); + mrb_field_write_barrier_value(mrb, (struct RBasic*)c, v); } MRB_API void @@ -716,7 +704,7 @@ mrb_cv_set(mrb_state *mrb, mrb_value mod, mrb_sym sym, mrb_value v) mrb_mod_cv_set(mrb, mrb_class_ptr(mod), sym, v); } -MRB_API mrb_bool +mrb_bool mrb_mod_cv_defined(mrb_state *mrb, struct RClass * c, mrb_sym sym) { while (c) { @@ -739,7 +727,13 @@ mrb_vm_cv_get(mrb_state *mrb, mrb_sym sym) { struct RClass *c; - c = MRB_PROC_TARGET_CLASS(mrb->c->ci->proc); + const struct RProc *p = mrb->c->ci->proc; + + for (;;) { + c = MRB_PROC_TARGET_CLASS(p); + if (c && c->tt != MRB_TT_SCLASS) break; + p = p->upper; + } return mrb_mod_cv_get(mrb, c, sym); } @@ -747,8 +741,13 @@ void mrb_vm_cv_set(mrb_state *mrb, mrb_sym sym, mrb_value v) { struct RClass *c; + const struct RProc *p = mrb->c->ci->proc; - c = MRB_PROC_TARGET_CLASS(mrb->c->ci->proc); + for (;;) { + c = MRB_PROC_TARGET_CLASS(p); + if (c && c->tt != MRB_TT_SCLASS) break; + p = p->upper; + } mrb_mod_cv_set(mrb, c, sym, v); } @@ -767,16 +766,17 @@ mod_const_check(mrb_state *mrb, mrb_value mod) } static mrb_value -const_get(mrb_state *mrb, struct RClass *base, mrb_sym sym) +const_get(mrb_state *mrb, struct RClass *base, mrb_sym sym, mrb_bool skip) { struct RClass *c = base; mrb_value v; mrb_bool retry = FALSE; mrb_value name; + if (skip) c = c->super; L_RETRY: while (c) { - if (c->iv) { + if (!MRB_FLAG_TEST(c, MRB_FL_CLASS_IS_PREPENDED) && c->iv) { if (iv_get(mrb, c->iv, sym, &v)) return v; } @@ -788,14 +788,14 @@ L_RETRY: goto L_RETRY; } name = mrb_symbol_value(sym); - return mrb_funcall_argv(mrb, mrb_obj_value(base), mrb_intern_lit(mrb, "const_missing"), 1, &name); + return mrb_funcall_argv(mrb, mrb_obj_value(base), MRB_SYM(const_missing), 1, &name); } MRB_API mrb_value mrb_const_get(mrb_state *mrb, mrb_value mod, mrb_sym sym) { mod_const_check(mrb, mod); - return const_get(mrb, mrb_class_ptr(mod), sym); + return const_get(mrb, mrb_class_ptr(mod), sym, FALSE); } mrb_value @@ -804,9 +804,10 @@ mrb_vm_const_get(mrb_state *mrb, mrb_sym sym) struct RClass *c; struct RClass *c2; mrb_value v; - struct RProc *proc; + const struct RProc *proc = mrb->c->ci->proc; - c = MRB_PROC_TARGET_CLASS(mrb->c->ci->proc); + c = MRB_PROC_TARGET_CLASS(proc); + if (!c) c = mrb->object_class; if (iv_get(mrb, c->iv, sym, &v)) { return v; } @@ -814,15 +815,14 @@ mrb_vm_const_get(mrb_state *mrb, mrb_sym sym) while (c2 && c2->tt == MRB_TT_SCLASS) { mrb_value klass; - if (!iv_get(mrb, c2->iv, mrb_intern_lit(mrb, "__attached__"), &klass)) { + if (!iv_get(mrb, c2->iv, MRB_SYM(__attached__), &klass)) { c2 = NULL; break; } c2 = mrb_class_ptr(klass); } if (c2 && (c2->tt == MRB_TT_CLASS || c2->tt == MRB_TT_MODULE)) c = c2; - mrb_assert(!MRB_PROC_CFUNC_P(mrb->c->ci->proc)); - proc = mrb->c->ci->proc; + proc = proc->upper; while (proc) { c2 = MRB_PROC_TARGET_CLASS(proc); if (c2 && iv_get(mrb, c2->iv, sym, &v)) { @@ -830,7 +830,7 @@ mrb_vm_const_get(mrb_state *mrb, mrb_sym sym) } proc = proc->upper; } - return const_get(mrb, c, sym); + return const_get(mrb, c, sym, TRUE); } MRB_API void @@ -849,6 +849,7 @@ mrb_vm_const_set(mrb_state *mrb, mrb_sym sym, mrb_value v) struct RClass *c; c = MRB_PROC_TARGET_CLASS(mrb->c->ci->proc); + if (!c) c = mrb->object_class; mrb_obj_iv_set(mrb, (struct RObject*)c, sym, v); } @@ -860,6 +861,12 @@ mrb_const_remove(mrb_state *mrb, mrb_value mod, mrb_sym sym) } MRB_API void +mrb_define_const_id(mrb_state *mrb, struct RClass *mod, mrb_sym name, mrb_value v) +{ + mrb_obj_iv_set(mrb, (struct RObject*)mod, name, v); +} + +MRB_API void mrb_define_const(mrb_state *mrb, struct RClass *mod, const char *name, mrb_value v) { mrb_obj_iv_set(mrb, (struct RObject*)mod, mrb_intern_cstr(mrb, name), v); @@ -879,9 +886,17 @@ const_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p) mrb_int len; ary = *(mrb_value*)p; - s = mrb_sym2name_len(mrb, sym, &len); + s = mrb_sym_name_len(mrb, sym, &len); if (len >= 1 && ISUPPER(s[0])) { - mrb_ary_push(mrb, ary, mrb_symbol_value(sym)); + mrb_int i, alen = RARRAY_LEN(ary); + + for (i=0; i<alen; i++) { + if (mrb_symbol(RARRAY_PTR(ary)[i]) == sym) + break; + } + if (i==alen) { + mrb_ary_push(mrb, ary, mrb_symbol_value(sym)); + } } return 0; } @@ -891,7 +906,7 @@ const_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p) * call-seq: * mod.constants -> array * - * Returns an array of all names of contants defined in the receiver. + * Returns an array of all names of constants defined in the receiver. */ mrb_value mrb_mod_constants(mrb_state *mrb, mrb_value mod) @@ -964,16 +979,8 @@ mrb_f_global_variables(mrb_state *mrb, mrb_value self) { iv_tbl *t = mrb->globals; mrb_value ary = mrb_ary_new(mrb); - size_t i; - char buf[3]; iv_foreach(mrb, t, gv_i, &ary); - buf[0] = '$'; - buf[2] = 0; - for (i = 1; i <= 9; ++i) { - buf[1] = (char)(i + '0'); - mrb_ary_push(mrb, ary, mrb_symbol_value(mrb_intern(mrb, buf, 2))); - } return ary; } @@ -1055,7 +1062,7 @@ outer_class(mrb_state *mrb, struct RClass *c) { mrb_value ov; - ov = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern_lit(mrb, "__outer__")); + ov = mrb_obj_iv_get(mrb, (struct RObject*)c, MRB_SYM(__outer__)); if (mrb_nil_p(ov)) return NULL; switch (mrb_type(ov)) { case MRB_TT_CLASS: @@ -1102,12 +1109,34 @@ mrb_class_find_path(mrb_state *mrb, struct RClass *c) mrb_str_cat_cstr(mrb, path, str); mrb_str_cat_cstr(mrb, path, "::"); - str = mrb_sym2name_len(mrb, name, &len); + str = mrb_sym_name_len(mrb, name, &len); mrb_str_cat(mrb, path, str, len); if (RSTRING_PTR(path)[0] != '#') { - iv_del(mrb, c->iv, mrb_intern_lit(mrb, "__outer__"), NULL); - iv_put(mrb, c->iv, mrb_intern_lit(mrb, "__classname__"), path); + iv_del(mrb, c->iv, MRB_SYM(__outer__), NULL); + iv_put(mrb, c->iv, MRB_SYM(__classname__), path); mrb_field_write_barrier_value(mrb, (struct RBasic*)c, path); + path = mrb_str_dup(mrb, path); } return path; } + +size_t +mrb_obj_iv_tbl_memsize(mrb_value obj) +{ + iv_tbl *t = mrb_obj_ptr(obj)->iv; + if (t == NULL) return 0; + return sizeof(iv_tbl) + t->alloc*sizeof(struct iv_elem); +} + +#define identchar(c) (ISALNUM(c) || (c) == '_' || !ISASCII(c)) + +mrb_bool +mrb_ident_p(const char *s, mrb_int len) +{ + mrb_int i; + + for (i = 0; i < len; i++) { + if (!identchar(s[i])) return FALSE; + } + return TRUE; +} |
