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