mbed I/F binding for mruby

Dependents:   mruby_mbed_web mirb_mbed

mbed-mruby

How to use

Class

Committer:
mzta
Date:
Wed Mar 25 17:36:16 2015 +0000
Revision:
0:158c61bb030f
mirb_mbed initial commit;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mzta 0:158c61bb030f 1 /*
mzta 0:158c61bb030f 2 ** symbol.c - Symbol class
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 <limits.h>
mzta 0:158c61bb030f 9 #include <string.h>
mzta 0:158c61bb030f 10 #include "mruby.h"
mzta 0:158c61bb030f 11 #include "mruby/khash.h"
mzta 0:158c61bb030f 12 #include "mruby/string.h"
mzta 0:158c61bb030f 13 #include "mruby/dump.h"
mzta 0:158c61bb030f 14
mzta 0:158c61bb030f 15 /* ------------------------------------------------------ */
mzta 0:158c61bb030f 16 typedef struct symbol_name {
mzta 0:158c61bb030f 17 mrb_bool lit : 1;
mzta 0:158c61bb030f 18 uint16_t len;
mzta 0:158c61bb030f 19 const char *name;
mzta 0:158c61bb030f 20 } symbol_name;
mzta 0:158c61bb030f 21
mzta 0:158c61bb030f 22 static inline khint_t
mzta 0:158c61bb030f 23 sym_hash_func(mrb_state *mrb, mrb_sym s)
mzta 0:158c61bb030f 24 {
mzta 0:158c61bb030f 25 khint_t h = 0;
mzta 0:158c61bb030f 26 size_t i, len = mrb->symtbl[s].len;
mzta 0:158c61bb030f 27 const char *p = mrb->symtbl[s].name;
mzta 0:158c61bb030f 28
mzta 0:158c61bb030f 29 for (i=0; i<len; i++) {
mzta 0:158c61bb030f 30 h = (h << 5) - h + *p++;
mzta 0:158c61bb030f 31 }
mzta 0:158c61bb030f 32 return h;
mzta 0:158c61bb030f 33 }
mzta 0:158c61bb030f 34 #define sym_hash_equal(mrb,a, b) (mrb->symtbl[a].len == mrb->symtbl[b].len && memcmp(mrb->symtbl[a].name, mrb->symtbl[b].name, mrb->symtbl[a].len) == 0)
mzta 0:158c61bb030f 35
mzta 0:158c61bb030f 36 KHASH_DECLARE(n2s, mrb_sym, mrb_sym, FALSE)
mzta 0:158c61bb030f 37 KHASH_DEFINE (n2s, mrb_sym, mrb_sym, FALSE, sym_hash_func, sym_hash_equal)
mzta 0:158c61bb030f 38 /* ------------------------------------------------------ */
mzta 0:158c61bb030f 39
mzta 0:158c61bb030f 40 static void
mzta 0:158c61bb030f 41 sym_validate_len(mrb_state *mrb, size_t len)
mzta 0:158c61bb030f 42 {
mzta 0:158c61bb030f 43 if (len >= RITE_LV_NULL_MARK) {
mzta 0:158c61bb030f 44 mrb_raise(mrb, E_ARGUMENT_ERROR, "symbol length too long");
mzta 0:158c61bb030f 45 }
mzta 0:158c61bb030f 46 }
mzta 0:158c61bb030f 47
mzta 0:158c61bb030f 48 static mrb_sym
mzta 0:158c61bb030f 49 sym_intern(mrb_state *mrb, const char *name, size_t len, mrb_bool lit)
mzta 0:158c61bb030f 50 {
mzta 0:158c61bb030f 51 khash_t(n2s) *h = mrb->name2sym;
mzta 0:158c61bb030f 52 symbol_name *sname = mrb->symtbl; /* symtbl[0] for working memory */
mzta 0:158c61bb030f 53 khiter_t k;
mzta 0:158c61bb030f 54 mrb_sym sym;
mzta 0:158c61bb030f 55 char *p;
mzta 0:158c61bb030f 56
mzta 0:158c61bb030f 57 sym_validate_len(mrb, len);
mzta 0:158c61bb030f 58 if (sname) {
mzta 0:158c61bb030f 59 sname->lit = lit;
mzta 0:158c61bb030f 60 sname->len = (uint16_t)len;
mzta 0:158c61bb030f 61 sname->name = name;
mzta 0:158c61bb030f 62 k = kh_get(n2s, mrb, h, 0);
mzta 0:158c61bb030f 63 if (k != kh_end(h))
mzta 0:158c61bb030f 64 return kh_key(h, k);
mzta 0:158c61bb030f 65 }
mzta 0:158c61bb030f 66
mzta 0:158c61bb030f 67 /* registering a new symbol */
mzta 0:158c61bb030f 68 sym = ++mrb->symidx;
mzta 0:158c61bb030f 69 if (mrb->symcapa < sym) {
mzta 0:158c61bb030f 70 if (mrb->symcapa == 0) mrb->symcapa = 100;
mzta 0:158c61bb030f 71 else mrb->symcapa = (size_t)(mrb->symcapa * 1.2);
mzta 0:158c61bb030f 72 mrb->symtbl = (symbol_name*)mrb_realloc(mrb, mrb->symtbl, sizeof(symbol_name)*(mrb->symcapa+1));
mzta 0:158c61bb030f 73 }
mzta 0:158c61bb030f 74 sname = &mrb->symtbl[sym];
mzta 0:158c61bb030f 75 sname->len = (uint16_t)len;
mzta 0:158c61bb030f 76 if (lit || mrb_ro_data_p(name)) {
mzta 0:158c61bb030f 77 sname->name = name;
mzta 0:158c61bb030f 78 sname->lit = TRUE;
mzta 0:158c61bb030f 79 }
mzta 0:158c61bb030f 80 else {
mzta 0:158c61bb030f 81 p = (char *)mrb_malloc(mrb, len+1);
mzta 0:158c61bb030f 82 memcpy(p, name, len);
mzta 0:158c61bb030f 83 p[len] = 0;
mzta 0:158c61bb030f 84 sname->name = (const char*)p;
mzta 0:158c61bb030f 85 sname->lit = FALSE;
mzta 0:158c61bb030f 86 }
mzta 0:158c61bb030f 87 kh_put(n2s, mrb, h, sym);
mzta 0:158c61bb030f 88
mzta 0:158c61bb030f 89 return sym;
mzta 0:158c61bb030f 90 }
mzta 0:158c61bb030f 91
mzta 0:158c61bb030f 92 MRB_API mrb_sym
mzta 0:158c61bb030f 93 mrb_intern(mrb_state *mrb, const char *name, size_t len)
mzta 0:158c61bb030f 94 {
mzta 0:158c61bb030f 95 return sym_intern(mrb, name, len, FALSE);
mzta 0:158c61bb030f 96 }
mzta 0:158c61bb030f 97
mzta 0:158c61bb030f 98 MRB_API mrb_sym
mzta 0:158c61bb030f 99 mrb_intern_static(mrb_state *mrb, const char *name, size_t len)
mzta 0:158c61bb030f 100 {
mzta 0:158c61bb030f 101 return sym_intern(mrb, name, len, TRUE);
mzta 0:158c61bb030f 102 }
mzta 0:158c61bb030f 103
mzta 0:158c61bb030f 104 MRB_API mrb_sym
mzta 0:158c61bb030f 105 mrb_intern_cstr(mrb_state *mrb, const char *name)
mzta 0:158c61bb030f 106 {
mzta 0:158c61bb030f 107 return mrb_intern(mrb, name, strlen(name));
mzta 0:158c61bb030f 108 }
mzta 0:158c61bb030f 109
mzta 0:158c61bb030f 110 MRB_API mrb_sym
mzta 0:158c61bb030f 111 mrb_intern_str(mrb_state *mrb, mrb_value str)
mzta 0:158c61bb030f 112 {
mzta 0:158c61bb030f 113 return mrb_intern(mrb, RSTRING_PTR(str), RSTRING_LEN(str));
mzta 0:158c61bb030f 114 }
mzta 0:158c61bb030f 115
mzta 0:158c61bb030f 116 MRB_API mrb_value
mzta 0:158c61bb030f 117 mrb_check_intern(mrb_state *mrb, const char *name, size_t len)
mzta 0:158c61bb030f 118 {
mzta 0:158c61bb030f 119 khash_t(n2s) *h = mrb->name2sym;
mzta 0:158c61bb030f 120 symbol_name *sname = mrb->symtbl;
mzta 0:158c61bb030f 121 khiter_t k;
mzta 0:158c61bb030f 122
mzta 0:158c61bb030f 123 sym_validate_len(mrb, len);
mzta 0:158c61bb030f 124 sname->len = (uint16_t)len;
mzta 0:158c61bb030f 125 sname->name = name;
mzta 0:158c61bb030f 126
mzta 0:158c61bb030f 127 k = kh_get(n2s, mrb, h, 0);
mzta 0:158c61bb030f 128 if (k != kh_end(h)) {
mzta 0:158c61bb030f 129 return mrb_symbol_value(kh_key(h, k));
mzta 0:158c61bb030f 130 }
mzta 0:158c61bb030f 131 return mrb_nil_value();
mzta 0:158c61bb030f 132 }
mzta 0:158c61bb030f 133
mzta 0:158c61bb030f 134 MRB_API mrb_value
mzta 0:158c61bb030f 135 mrb_check_intern_cstr(mrb_state *mrb, const char *name)
mzta 0:158c61bb030f 136 {
mzta 0:158c61bb030f 137 return mrb_check_intern(mrb, name, (mrb_int)strlen(name));
mzta 0:158c61bb030f 138 }
mzta 0:158c61bb030f 139
mzta 0:158c61bb030f 140 MRB_API mrb_value
mzta 0:158c61bb030f 141 mrb_check_intern_str(mrb_state *mrb, mrb_value str)
mzta 0:158c61bb030f 142 {
mzta 0:158c61bb030f 143 return mrb_check_intern(mrb, RSTRING_PTR(str), RSTRING_LEN(str));
mzta 0:158c61bb030f 144 }
mzta 0:158c61bb030f 145
mzta 0:158c61bb030f 146 /* lenp must be a pointer to a size_t variable */
mzta 0:158c61bb030f 147 MRB_API const char*
mzta 0:158c61bb030f 148 mrb_sym2name_len(mrb_state *mrb, mrb_sym sym, mrb_int *lenp)
mzta 0:158c61bb030f 149 {
mzta 0:158c61bb030f 150 if (sym == 0 || mrb->symidx < sym) {
mzta 0:158c61bb030f 151 if (lenp) *lenp = 0;
mzta 0:158c61bb030f 152 return NULL;
mzta 0:158c61bb030f 153 }
mzta 0:158c61bb030f 154
mzta 0:158c61bb030f 155 if (lenp) *lenp = mrb->symtbl[sym].len;
mzta 0:158c61bb030f 156 return mrb->symtbl[sym].name;
mzta 0:158c61bb030f 157 }
mzta 0:158c61bb030f 158
mzta 0:158c61bb030f 159 void
mzta 0:158c61bb030f 160 mrb_free_symtbl(mrb_state *mrb)
mzta 0:158c61bb030f 161 {
mzta 0:158c61bb030f 162 mrb_sym i, lim;
mzta 0:158c61bb030f 163
mzta 0:158c61bb030f 164 for (i=1, lim=mrb->symidx+1; i<lim; i++) {
mzta 0:158c61bb030f 165 if (!mrb->symtbl[i].lit) {
mzta 0:158c61bb030f 166 mrb_free(mrb, (char*)mrb->symtbl[i].name);
mzta 0:158c61bb030f 167 }
mzta 0:158c61bb030f 168 }
mzta 0:158c61bb030f 169 mrb_free(mrb, mrb->symtbl);
mzta 0:158c61bb030f 170 kh_destroy(n2s, mrb, mrb->name2sym);
mzta 0:158c61bb030f 171 }
mzta 0:158c61bb030f 172
mzta 0:158c61bb030f 173 void
mzta 0:158c61bb030f 174 mrb_init_symtbl(mrb_state *mrb)
mzta 0:158c61bb030f 175 {
mzta 0:158c61bb030f 176 mrb->name2sym = kh_init(n2s, mrb);
mzta 0:158c61bb030f 177 }
mzta 0:158c61bb030f 178
mzta 0:158c61bb030f 179 /**********************************************************************
mzta 0:158c61bb030f 180 * Document-class: Symbol
mzta 0:158c61bb030f 181 *
mzta 0:158c61bb030f 182 * <code>Symbol</code> objects represent names and some strings
mzta 0:158c61bb030f 183 * inside the Ruby
mzta 0:158c61bb030f 184 * interpreter. They are generated using the <code>:name</code> and
mzta 0:158c61bb030f 185 * <code>:"string"</code> literals
mzta 0:158c61bb030f 186 * syntax, and by the various <code>to_sym</code> methods. The same
mzta 0:158c61bb030f 187 * <code>Symbol</code> object will be created for a given name or string
mzta 0:158c61bb030f 188 * for the duration of a program's execution, regardless of the context
mzta 0:158c61bb030f 189 * or meaning of that name. Thus if <code>Fred</code> is a constant in
mzta 0:158c61bb030f 190 * one context, a method in another, and a class in a third, the
mzta 0:158c61bb030f 191 * <code>Symbol</code> <code>:Fred</code> will be the same object in
mzta 0:158c61bb030f 192 * all three contexts.
mzta 0:158c61bb030f 193 *
mzta 0:158c61bb030f 194 * module One
mzta 0:158c61bb030f 195 * class Fred
mzta 0:158c61bb030f 196 * end
mzta 0:158c61bb030f 197 * $f1 = :Fred
mzta 0:158c61bb030f 198 * end
mzta 0:158c61bb030f 199 * module Two
mzta 0:158c61bb030f 200 * Fred = 1
mzta 0:158c61bb030f 201 * $f2 = :Fred
mzta 0:158c61bb030f 202 * end
mzta 0:158c61bb030f 203 * def Fred()
mzta 0:158c61bb030f 204 * end
mzta 0:158c61bb030f 205 * $f3 = :Fred
mzta 0:158c61bb030f 206 * $f1.object_id #=> 2514190
mzta 0:158c61bb030f 207 * $f2.object_id #=> 2514190
mzta 0:158c61bb030f 208 * $f3.object_id #=> 2514190
mzta 0:158c61bb030f 209 *
mzta 0:158c61bb030f 210 */
mzta 0:158c61bb030f 211
mzta 0:158c61bb030f 212
mzta 0:158c61bb030f 213 /* 15.2.11.3.1 */
mzta 0:158c61bb030f 214 /*
mzta 0:158c61bb030f 215 * call-seq:
mzta 0:158c61bb030f 216 * sym == obj -> true or false
mzta 0:158c61bb030f 217 *
mzta 0:158c61bb030f 218 * Equality---If <i>sym</i> and <i>obj</i> are exactly the same
mzta 0:158c61bb030f 219 * symbol, returns <code>true</code>.
mzta 0:158c61bb030f 220 */
mzta 0:158c61bb030f 221
mzta 0:158c61bb030f 222 static mrb_value
mzta 0:158c61bb030f 223 sym_equal(mrb_state *mrb, mrb_value sym1)
mzta 0:158c61bb030f 224 {
mzta 0:158c61bb030f 225 mrb_value sym2;
mzta 0:158c61bb030f 226
mzta 0:158c61bb030f 227 mrb_get_args(mrb, "o", &sym2);
mzta 0:158c61bb030f 228
mzta 0:158c61bb030f 229 return mrb_bool_value(mrb_obj_equal(mrb, sym1, sym2));
mzta 0:158c61bb030f 230 }
mzta 0:158c61bb030f 231
mzta 0:158c61bb030f 232 /* 15.2.11.3.2 */
mzta 0:158c61bb030f 233 /* 15.2.11.3.3 */
mzta 0:158c61bb030f 234 /*
mzta 0:158c61bb030f 235 * call-seq:
mzta 0:158c61bb030f 236 * sym.id2name -> string
mzta 0:158c61bb030f 237 * sym.to_s -> string
mzta 0:158c61bb030f 238 *
mzta 0:158c61bb030f 239 * Returns the name or string corresponding to <i>sym</i>.
mzta 0:158c61bb030f 240 *
mzta 0:158c61bb030f 241 * :fred.id2name #=> "fred"
mzta 0:158c61bb030f 242 */
mzta 0:158c61bb030f 243 static mrb_value
mzta 0:158c61bb030f 244 mrb_sym_to_s(mrb_state *mrb, mrb_value sym)
mzta 0:158c61bb030f 245 {
mzta 0:158c61bb030f 246 mrb_sym id = mrb_symbol(sym);
mzta 0:158c61bb030f 247 const char *p;
mzta 0:158c61bb030f 248 mrb_int len;
mzta 0:158c61bb030f 249
mzta 0:158c61bb030f 250 p = mrb_sym2name_len(mrb, id, &len);
mzta 0:158c61bb030f 251 return mrb_str_new_static(mrb, p, len);
mzta 0:158c61bb030f 252 }
mzta 0:158c61bb030f 253
mzta 0:158c61bb030f 254 /* 15.2.11.3.4 */
mzta 0:158c61bb030f 255 /*
mzta 0:158c61bb030f 256 * call-seq:
mzta 0:158c61bb030f 257 * sym.to_sym -> sym
mzta 0:158c61bb030f 258 * sym.intern -> sym
mzta 0:158c61bb030f 259 *
mzta 0:158c61bb030f 260 * In general, <code>to_sym</code> returns the <code>Symbol</code> corresponding
mzta 0:158c61bb030f 261 * to an object. As <i>sym</i> is already a symbol, <code>self</code> is returned
mzta 0:158c61bb030f 262 * in this case.
mzta 0:158c61bb030f 263 */
mzta 0:158c61bb030f 264
mzta 0:158c61bb030f 265 static mrb_value
mzta 0:158c61bb030f 266 sym_to_sym(mrb_state *mrb, mrb_value sym)
mzta 0:158c61bb030f 267 {
mzta 0:158c61bb030f 268 return sym;
mzta 0:158c61bb030f 269 }
mzta 0:158c61bb030f 270
mzta 0:158c61bb030f 271 /* 15.2.11.3.5(x) */
mzta 0:158c61bb030f 272 /*
mzta 0:158c61bb030f 273 * call-seq:
mzta 0:158c61bb030f 274 * sym.inspect -> string
mzta 0:158c61bb030f 275 *
mzta 0:158c61bb030f 276 * Returns the representation of <i>sym</i> as a symbol literal.
mzta 0:158c61bb030f 277 *
mzta 0:158c61bb030f 278 * :fred.inspect #=> ":fred"
mzta 0:158c61bb030f 279 */
mzta 0:158c61bb030f 280
mzta 0:158c61bb030f 281 #if __STDC__
mzta 0:158c61bb030f 282 # define SIGN_EXTEND_CHAR(c) ((signed char)(c))
mzta 0:158c61bb030f 283 #else /* not __STDC__ */
mzta 0:158c61bb030f 284 /* As in Harbison and Steele. */
mzta 0:158c61bb030f 285 # define SIGN_EXTEND_CHAR(c) ((((unsigned char)(c)) ^ 128) - 128)
mzta 0:158c61bb030f 286 #endif
mzta 0:158c61bb030f 287 #define is_identchar(c) (SIGN_EXTEND_CHAR(c)!=-1&&(ISALNUM(c) || (c) == '_'))
mzta 0:158c61bb030f 288
mzta 0:158c61bb030f 289 static mrb_bool
mzta 0:158c61bb030f 290 is_special_global_name(const char* m)
mzta 0:158c61bb030f 291 {
mzta 0:158c61bb030f 292 switch (*m) {
mzta 0:158c61bb030f 293 case '~': case '*': case '$': case '?': case '!': case '@':
mzta 0:158c61bb030f 294 case '/': case '\\': case ';': case ',': case '.': case '=':
mzta 0:158c61bb030f 295 case ':': case '<': case '>': case '\"':
mzta 0:158c61bb030f 296 case '&': case '`': case '\'': case '+':
mzta 0:158c61bb030f 297 case '0':
mzta 0:158c61bb030f 298 ++m;
mzta 0:158c61bb030f 299 break;
mzta 0:158c61bb030f 300 case '-':
mzta 0:158c61bb030f 301 ++m;
mzta 0:158c61bb030f 302 if (is_identchar(*m)) m += 1;
mzta 0:158c61bb030f 303 break;
mzta 0:158c61bb030f 304 default:
mzta 0:158c61bb030f 305 if (!ISDIGIT(*m)) return FALSE;
mzta 0:158c61bb030f 306 do ++m; while (ISDIGIT(*m));
mzta 0:158c61bb030f 307 break;
mzta 0:158c61bb030f 308 }
mzta 0:158c61bb030f 309 return !*m;
mzta 0:158c61bb030f 310 }
mzta 0:158c61bb030f 311
mzta 0:158c61bb030f 312 static mrb_bool
mzta 0:158c61bb030f 313 symname_p(const char *name)
mzta 0:158c61bb030f 314 {
mzta 0:158c61bb030f 315 const char *m = name;
mzta 0:158c61bb030f 316 mrb_bool localid = FALSE;
mzta 0:158c61bb030f 317
mzta 0:158c61bb030f 318 if (!m) return FALSE;
mzta 0:158c61bb030f 319 switch (*m) {
mzta 0:158c61bb030f 320 case '\0':
mzta 0:158c61bb030f 321 return FALSE;
mzta 0:158c61bb030f 322
mzta 0:158c61bb030f 323 case '$':
mzta 0:158c61bb030f 324 if (is_special_global_name(++m)) return TRUE;
mzta 0:158c61bb030f 325 goto id;
mzta 0:158c61bb030f 326
mzta 0:158c61bb030f 327 case '@':
mzta 0:158c61bb030f 328 if (*++m == '@') ++m;
mzta 0:158c61bb030f 329 goto id;
mzta 0:158c61bb030f 330
mzta 0:158c61bb030f 331 case '<':
mzta 0:158c61bb030f 332 switch (*++m) {
mzta 0:158c61bb030f 333 case '<': ++m; break;
mzta 0:158c61bb030f 334 case '=': if (*++m == '>') ++m; break;
mzta 0:158c61bb030f 335 default: break;
mzta 0:158c61bb030f 336 }
mzta 0:158c61bb030f 337 break;
mzta 0:158c61bb030f 338
mzta 0:158c61bb030f 339 case '>':
mzta 0:158c61bb030f 340 switch (*++m) {
mzta 0:158c61bb030f 341 case '>': case '=': ++m; break;
mzta 0:158c61bb030f 342 default: break;
mzta 0:158c61bb030f 343 }
mzta 0:158c61bb030f 344 break;
mzta 0:158c61bb030f 345
mzta 0:158c61bb030f 346 case '=':
mzta 0:158c61bb030f 347 switch (*++m) {
mzta 0:158c61bb030f 348 case '~': ++m; break;
mzta 0:158c61bb030f 349 case '=': if (*++m == '=') ++m; break;
mzta 0:158c61bb030f 350 default: return FALSE;
mzta 0:158c61bb030f 351 }
mzta 0:158c61bb030f 352 break;
mzta 0:158c61bb030f 353
mzta 0:158c61bb030f 354 case '*':
mzta 0:158c61bb030f 355 if (*++m == '*') ++m;
mzta 0:158c61bb030f 356 break;
mzta 0:158c61bb030f 357 case '!':
mzta 0:158c61bb030f 358 if (*++m == '=') ++m;
mzta 0:158c61bb030f 359 break;
mzta 0:158c61bb030f 360 case '+': case '-':
mzta 0:158c61bb030f 361 if (*++m == '@') ++m;
mzta 0:158c61bb030f 362 break;
mzta 0:158c61bb030f 363 case '|':
mzta 0:158c61bb030f 364 if (*++m == '|') ++m;
mzta 0:158c61bb030f 365 break;
mzta 0:158c61bb030f 366 case '&':
mzta 0:158c61bb030f 367 if (*++m == '&') ++m;
mzta 0:158c61bb030f 368 break;
mzta 0:158c61bb030f 369
mzta 0:158c61bb030f 370 case '^': case '/': case '%': case '~': case '`':
mzta 0:158c61bb030f 371 ++m;
mzta 0:158c61bb030f 372 break;
mzta 0:158c61bb030f 373
mzta 0:158c61bb030f 374 case '[':
mzta 0:158c61bb030f 375 if (*++m != ']') return FALSE;
mzta 0:158c61bb030f 376 if (*++m == '=') ++m;
mzta 0:158c61bb030f 377 break;
mzta 0:158c61bb030f 378
mzta 0:158c61bb030f 379 default:
mzta 0:158c61bb030f 380 localid = !ISUPPER(*m);
mzta 0:158c61bb030f 381 id:
mzta 0:158c61bb030f 382 if (*m != '_' && !ISALPHA(*m)) return FALSE;
mzta 0:158c61bb030f 383 while (is_identchar(*m)) m += 1;
mzta 0:158c61bb030f 384 if (localid) {
mzta 0:158c61bb030f 385 switch (*m) {
mzta 0:158c61bb030f 386 case '!': case '?': case '=': ++m;
mzta 0:158c61bb030f 387 default: break;
mzta 0:158c61bb030f 388 }
mzta 0:158c61bb030f 389 }
mzta 0:158c61bb030f 390 break;
mzta 0:158c61bb030f 391 }
mzta 0:158c61bb030f 392 return *m ? FALSE : TRUE;
mzta 0:158c61bb030f 393 }
mzta 0:158c61bb030f 394
mzta 0:158c61bb030f 395 static mrb_value
mzta 0:158c61bb030f 396 sym_inspect(mrb_state *mrb, mrb_value sym)
mzta 0:158c61bb030f 397 {
mzta 0:158c61bb030f 398 mrb_value str;
mzta 0:158c61bb030f 399 const char *name;
mzta 0:158c61bb030f 400 mrb_int len;
mzta 0:158c61bb030f 401 mrb_sym id = mrb_symbol(sym);
mzta 0:158c61bb030f 402 char *sp;
mzta 0:158c61bb030f 403
mzta 0:158c61bb030f 404 name = mrb_sym2name_len(mrb, id, &len);
mzta 0:158c61bb030f 405 str = mrb_str_new(mrb, 0, len+1);
mzta 0:158c61bb030f 406 sp = RSTRING_PTR(str);
mzta 0:158c61bb030f 407 RSTRING_PTR(str)[0] = ':';
mzta 0:158c61bb030f 408 memcpy(sp+1, name, len);
mzta 0:158c61bb030f 409 mrb_assert_int_fit(mrb_int, len, size_t, SIZE_MAX);
mzta 0:158c61bb030f 410 if (!symname_p(name) || strlen(name) != (size_t)len) {
mzta 0:158c61bb030f 411 str = mrb_str_dump(mrb, str);
mzta 0:158c61bb030f 412 sp = RSTRING_PTR(str);
mzta 0:158c61bb030f 413 sp[0] = ':';
mzta 0:158c61bb030f 414 sp[1] = '"';
mzta 0:158c61bb030f 415 }
mzta 0:158c61bb030f 416 return str;
mzta 0:158c61bb030f 417 }
mzta 0:158c61bb030f 418
mzta 0:158c61bb030f 419 MRB_API mrb_value
mzta 0:158c61bb030f 420 mrb_sym2str(mrb_state *mrb, mrb_sym sym)
mzta 0:158c61bb030f 421 {
mzta 0:158c61bb030f 422 mrb_int len;
mzta 0:158c61bb030f 423 const char *name = mrb_sym2name_len(mrb, sym, &len);
mzta 0:158c61bb030f 424
mzta 0:158c61bb030f 425 if (!name) return mrb_undef_value(); /* can't happen */
mzta 0:158c61bb030f 426 return mrb_str_new_static(mrb, name, len);
mzta 0:158c61bb030f 427 }
mzta 0:158c61bb030f 428
mzta 0:158c61bb030f 429 MRB_API const char*
mzta 0:158c61bb030f 430 mrb_sym2name(mrb_state *mrb, mrb_sym sym)
mzta 0:158c61bb030f 431 {
mzta 0:158c61bb030f 432 mrb_int len;
mzta 0:158c61bb030f 433 const char *name = mrb_sym2name_len(mrb, sym, &len);
mzta 0:158c61bb030f 434
mzta 0:158c61bb030f 435 if (!name) return NULL;
mzta 0:158c61bb030f 436 if (symname_p(name) && strlen(name) == (size_t)len) {
mzta 0:158c61bb030f 437 return name;
mzta 0:158c61bb030f 438 }
mzta 0:158c61bb030f 439 else {
mzta 0:158c61bb030f 440 mrb_value str = mrb_str_dump(mrb, mrb_str_new_static(mrb, name, len));
mzta 0:158c61bb030f 441 return RSTRING_PTR(str);
mzta 0:158c61bb030f 442 }
mzta 0:158c61bb030f 443 }
mzta 0:158c61bb030f 444
mzta 0:158c61bb030f 445 #define lesser(a,b) (((a)>(b))?(b):(a))
mzta 0:158c61bb030f 446
mzta 0:158c61bb030f 447 static mrb_value
mzta 0:158c61bb030f 448 sym_cmp(mrb_state *mrb, mrb_value s1)
mzta 0:158c61bb030f 449 {
mzta 0:158c61bb030f 450 mrb_value s2;
mzta 0:158c61bb030f 451 mrb_sym sym1, sym2;
mzta 0:158c61bb030f 452
mzta 0:158c61bb030f 453 mrb_get_args(mrb, "o", &s2);
mzta 0:158c61bb030f 454 if (mrb_type(s2) != MRB_TT_SYMBOL) return mrb_nil_value();
mzta 0:158c61bb030f 455 sym1 = mrb_symbol(s1);
mzta 0:158c61bb030f 456 sym2 = mrb_symbol(s2);
mzta 0:158c61bb030f 457 if (sym1 == sym2) return mrb_fixnum_value(0);
mzta 0:158c61bb030f 458 else {
mzta 0:158c61bb030f 459 const char *p1, *p2;
mzta 0:158c61bb030f 460 int retval;
mzta 0:158c61bb030f 461 mrb_int len, len1, len2;
mzta 0:158c61bb030f 462
mzta 0:158c61bb030f 463 p1 = mrb_sym2name_len(mrb, sym1, &len1);
mzta 0:158c61bb030f 464 p2 = mrb_sym2name_len(mrb, sym2, &len2);
mzta 0:158c61bb030f 465 len = lesser(len1, len2);
mzta 0:158c61bb030f 466 retval = memcmp(p1, p2, len);
mzta 0:158c61bb030f 467 if (retval == 0) {
mzta 0:158c61bb030f 468 if (len1 == len2) return mrb_fixnum_value(0);
mzta 0:158c61bb030f 469 if (len1 > len2) return mrb_fixnum_value(1);
mzta 0:158c61bb030f 470 return mrb_fixnum_value(-1);
mzta 0:158c61bb030f 471 }
mzta 0:158c61bb030f 472 if (retval > 0) return mrb_fixnum_value(1);
mzta 0:158c61bb030f 473 return mrb_fixnum_value(-1);
mzta 0:158c61bb030f 474 }
mzta 0:158c61bb030f 475 }
mzta 0:158c61bb030f 476
mzta 0:158c61bb030f 477 void
mzta 0:158c61bb030f 478 mrb_init_symbol(mrb_state *mrb)
mzta 0:158c61bb030f 479 {
mzta 0:158c61bb030f 480 struct RClass *sym;
mzta 0:158c61bb030f 481
mzta 0:158c61bb030f 482 sym = mrb->symbol_class = mrb_define_class(mrb, "Symbol", mrb->object_class); /* 15.2.11 */
mzta 0:158c61bb030f 483
mzta 0:158c61bb030f 484 mrb_define_method(mrb, sym, "===", sym_equal, MRB_ARGS_REQ(1)); /* 15.2.11.3.1 */
mzta 0:158c61bb030f 485 mrb_define_method(mrb, sym, "id2name", mrb_sym_to_s, MRB_ARGS_NONE()); /* 15.2.11.3.2 */
mzta 0:158c61bb030f 486 mrb_define_method(mrb, sym, "to_s", mrb_sym_to_s, MRB_ARGS_NONE()); /* 15.2.11.3.3 */
mzta 0:158c61bb030f 487 mrb_define_method(mrb, sym, "to_sym", sym_to_sym, MRB_ARGS_NONE()); /* 15.2.11.3.4 */
mzta 0:158c61bb030f 488 mrb_define_method(mrb, sym, "inspect", sym_inspect, MRB_ARGS_NONE()); /* 15.2.11.3.5(x) */
mzta 0:158c61bb030f 489 mrb_define_method(mrb, sym, "<=>", sym_cmp, MRB_ARGS_REQ(1));
mzta 0:158c61bb030f 490 }
mzta 0:158c61bb030f 491