mruby/c VM Source Code release 4.0.0
Loading...
Searching...
No Matches
symbol.c
Go to the documentation of this file.
1
14
15/***** Feature test switches ************************************************/
16/***** System headers *******************************************************/
17//@cond
18#include "vm_config.h"
19#include <stdint.h>
20#include <string.h>
21#include <limits.h>
22#include <assert.h>
23//@endcond
24
25/***** Local headers ********************************************************/
26#define MRBC_DEFINE_SYMBOL_TABLE
27#include "_autogen_builtin_symbol.h"
28#undef MRBC_DEFINE_SYMBOL_TABLE
29#include "mrubyc.h"
30
31/***** Constant values ******************************************************/
32#if !defined(MRBC_SYMBOL_SEARCH_LINEAR) && !defined(MRBC_SYMBOL_SEARCH_BTREE)
33#define MRBC_SYMBOL_SEARCH_BTREE
34#endif
35
36#if MAX_SYMBOLS_COUNT <= UCHAR_MAX
37#define MRBC_SYMBOL_TABLE_INDEX_TYPE uint8_t
38#else
39#define MRBC_SYMBOL_TABLE_INDEX_TYPE uint16_t
40#endif
41
42#define OFFSET_BUILTIN_SYMBOL 256
43#if OFFSET_BUILTIN_SYMBOL <= MRBC_BUILTIN_SYMBOL_MAX
44# error OFFSET_BUILTIN_SYMBOL overflow. Please increase the value.
45#endif
46
47
48/***** Macros ***************************************************************/
49/***** Typedefs *************************************************************/
50struct SYM_INDEX {
51 uint16_t hash;
52#ifdef MRBC_SYMBOL_SEARCH_BTREE
55#endif
56 const char *cstr;
57};
58
59
60/***** Function prototypes **************************************************/
61/***** Local variables ******************************************************/
63static int sym_index_pos; // point to the last(free) sym_index array.
64
65
66/***** Global variables *****************************************************/
67/***** Signal catching functions ********************************************/
68/***** Local functions ******************************************************/
69
70//================================================================
76static inline uint16_t calc_hash(const char *str)
77{
78 uint16_t h = 0;
79
80 while( *str != '\0' ) {
81 h = h * 17 + *str++;
82 }
83 return h;
84}
85
86
87//================================================================
93static int search_builtin_symbol( const char *str )
94{
95 int left = 0;
96 int right = sizeof(builtin_symbols) / sizeof(builtin_symbols[0]);
97
98 while( left < right ) {
99 int mid = (left + right) / 2;
100 const unsigned char *p1 = (const unsigned char *)builtin_symbols[mid];
101 const unsigned char *p2 = (const unsigned char *)str;
102
103 while( 1 ) { // string compare, same order as cruby.
104 if( *p1 < *p2 ) {
105 left = mid + 1;
106 break;
107 }
108 if( *p1 > *p2 ) {
109 right = mid;
110 break;
111 }
112 if( *p1 == 0 ) {
113 return mid;
114 }
115
116 p1++;
117 p2++;
118 }
119 }
120
121 return -1;
122}
123
124
125//================================================================
132static int search_index( uint16_t hash, const char *str )
133{
134#ifdef MRBC_SYMBOL_SEARCH_LINEAR
135 for( int i = 0; i < sym_index_pos; i++ ) {
136 if( sym_index[i].hash == hash && strcmp(str, sym_index[i].cstr) == 0 ) {
137 return i;
138 }
139 }
140 return -1;
141#endif
142
143#ifdef MRBC_SYMBOL_SEARCH_BTREE
144 int i = 0;
145 do {
146 if( sym_index[i].hash == hash && strcmp(str, sym_index[i].cstr) == 0 ) {
147 return i;
148 }
149 if( hash < sym_index[i].hash ) {
150 i = sym_index[i].left;
151 } else {
152 i = sym_index[i].right;
153 }
154 } while( i != 0 );
155 return -1;
156#endif
157}
158
159
160//================================================================
167static int add_index( uint16_t hash, const char *str )
168{
169 if( sym_index_pos >= MAX_SYMBOLS_COUNT ) return -1; // check overflow.
170
171 int idx = sym_index_pos++;
172
173 // append table.
174 sym_index[idx].hash = hash;
175 sym_index[idx].cstr = str;
176
177#ifdef MRBC_SYMBOL_SEARCH_BTREE
178 int i = 0;
179
180 while( 1 ) {
181 if( hash < sym_index[i].hash ) {
182 // left side
183 if( sym_index[i].left == 0 ) { // left is empty?
184 sym_index[i].left = idx;
185 break;
186 }
187 i = sym_index[i].left;
188 } else {
189 // right side
190 if( sym_index[i].right == 0 ) { // right is empty?
191 sym_index[i].right = idx;
192 break;
193 }
194 i = sym_index[i].right;
195 }
196 }
197#endif
198
199 return idx;
200}
201
202
203/***** Global functions *****************************************************/
204
205//================================================================
209{
210 memset(sym_index, 0, sizeof(sym_index));
211 sym_index_pos = 0;
212}
213
214
215//================================================================
222{
223 mrbc_sym sym_id = search_builtin_symbol(str);
224 if( sym_id >= 0 ) return sym_id;
225
226 uint16_t h = calc_hash(str);
227 sym_id = search_index(h, str);
228 if( sym_id < 0 ) sym_id = add_index( h, str );
229 if( sym_id < 0 ) return sym_id;
230
231 return sym_id + OFFSET_BUILTIN_SYMBOL;
232}
233
234
235//================================================================
242const char * mrbc_symid_to_str(mrbc_sym sym_id)
243{
244 if( sym_id < OFFSET_BUILTIN_SYMBOL ) {
245 return builtin_symbols[sym_id];
246 }
247
248 sym_id -= OFFSET_BUILTIN_SYMBOL;
249 if( sym_id < 0 ) return "";
250 if( sym_id >= sym_index_pos ) return "";
251
252 return sym_index[sym_id].cstr;
253}
254
255
256//================================================================
262mrbc_sym mrbc_search_symid( const char *str )
263{
264 mrbc_sym sym_id = search_builtin_symbol(str);
265 if( sym_id >= 0 ) return sym_id;
266
267 uint16_t h = calc_hash(str);
268 sym_id = search_index(h, str);
269 if( sym_id < 0 ) return sym_id;
270
271 return sym_id + OFFSET_BUILTIN_SYMBOL;
272}
273
274
275//================================================================
282void make_nested_symbol_s( char *buf, mrbc_sym id1, mrbc_sym id2 )
283{
284 static const int w = sizeof(mrbc_sym) * 2;
285 char *p = buf + w * 2;
286 *p = 0;
287
288 int i;
289 for( i = w; i > 0; i-- ) {
290 *--p = '0' + (id2 & 0x0f);
291 id2 >>= 4;
292 }
293
294 for( i = w; i > 0; i-- ) {
295 *--p = '0' + (id1 & 0x0f);
296 id1 >>= 4;
297 }
298}
299
300
301//================================================================
310{
311 static const int w = sizeof(mrbc_sym) * 2;
312 const char *s = mrbc_symid_to_str(sym_id);
313
314 *id1 = 0;
315 if( id2 != NULL ) *id2 = 0;
316 if( *s == 0 ) return;
317
318 assert( mrbc_is_nested_symid( sym_id ));
319 assert( strlen(s) == w*2 );
320
321 int i = 0;
322 while( i < w ) {
323 *id1 = (*id1 << 4) + (s[i++] - '0');
324 }
325
326 if( id2 == NULL ) return;
327 while( i < w*2 ) {
328 *id2 = (*id2 << 4) + (s[i++] - '0');
329 }
330}
331
332
333//================================================================
340mrbc_value mrbc_symbol_new(struct VM *vm, const char *str)
341{
342 mrbc_sym sym_id = mrbc_search_symid( str );
343 if( sym_id >= 0 ) goto DONE;
344
345 // create symbol object dynamically.
346 int size = strlen(str) + 1;
347 char *buf = mrbc_raw_alloc_no_free(size);
348
349 memcpy(buf, str, size);
350 sym_id = add_index( calc_hash(buf), buf );
351 if( sym_id < 0 ) {
352 mrbc_raisef(vm, MRBC_CLASS(Exception),
353 "Overflow MAX_SYMBOLS_COUNT for '%s'", str );
354 return mrbc_nil_value();
355 }
356
357 sym_id += OFFSET_BUILTIN_SYMBOL;
358
359 DONE:
360 return mrbc_symbol_value( sym_id );
361}
362
363
364/***** mruby/c methods ******************************************************/
365
366//================================================================
369static void c_symbol_all_symbols(struct VM *vm, mrbc_value v[], int argc)
370{
372
373 for( int i = 0; i < sizeof(builtin_symbols) / sizeof(builtin_symbols[0]); i++ ) {
375 }
376
377 for( int i = 0; i < sym_index_pos; i++ ) {
379 }
380 SET_RETURN(ret);
381}
382
383
384#if MRBC_USE_STRING
385//================================================================
388static void c_symbol_inspect(struct VM *vm, mrbc_value v[], int argc)
389{
390 if( mrbc_type(v[0]) == MRBC_TT_CLASS ) {
391 mrbc_object_inspect(vm, v, argc);
392 return;
393 }
394
395 const char *s = mrbc_symid_to_str( mrbc_symbol(v[0]) );
396
397 if( strchr(s, ':') ) {
398 v[0] = mrbc_string_new_cstr(vm, ":\"");
399 mrbc_string_append_cstr(&v[0], s);
400 mrbc_string_append_cstr(&v[0], "\"");
401 } else {
402 v[0] = mrbc_string_new_cstr(vm, ":");
403 mrbc_string_append_cstr(&v[0], s);
404 }
405}
406
407
408//================================================================
411static void c_symbol_to_s(struct VM *vm, mrbc_value v[], int argc)
412{
413 if( mrbc_type(v[0]) == MRBC_TT_CLASS ) {
414 mrbc_object_inspect(vm, v, argc);
415 return;
416 }
417
419}
420#endif
421
422
423/* MRBC_AUTOGEN_METHOD_TABLE
424
425 CLASS("Symbol")
426 FILE("_autogen_class_symbol.h")
427
428 METHOD( "all_symbols", c_symbol_all_symbols )
429#if MRBC_USE_STRING
430 METHOD( "inspect", c_symbol_inspect )
431 METHOD( "to_s", c_symbol_to_s )
432 METHOD( "id2name", c_symbol_to_s )
433#endif
434 METHOD( "to_sym", c_ineffect )
435*/
436#include "_autogen_class_symbol.h"
437
438
439
440#if defined(MRBC_DEBUG)
441//================================================================
447void mrbc_debug_dump_symbol(void)
448{
449 mrbc_printf("<< Symbol table dump >>\n");
450
451 for( int i = 0; i < sym_index_pos; i++ ) {
452 mrbc_sym sym_id = i + OFFSET_BUILTIN_SYMBOL;
453 mrbc_printf(" %04x: %s", sym_id, sym_index[i].cstr );
454 if( mrbc_is_nested_symid(sym_id) ) {
455 mrbc_printf(" as ");
456 mrbc_print_symbol(sym_id);
457 }
458 mrbc_printf("\n");
459 }
460
461 mrbc_printf("\n");
462}
463
464
465//================================================================
474void mrbc_symbol_statistics( int *total_used )
475{
476 *total_used = sym_index_pos;
477}
478#endif
void * mrbc_raw_alloc_no_free(unsigned int size)
Definition alloc.c:631
#define mrbc_symbol(o)
Definition boxing_no.h:60
#define mrbc_nil_value()
Definition boxing_no.h:66
#define mrbc_symbol_value(n)
Definition boxing_no.h:70
#define mrbc_type(o)
Definition boxing_no.h:57
struct RObject mrbc_value
Value object. Default version.
int mrbc_array_push(mrbc_value *ary, mrbc_value *set_val)
Definition c_array.c:243
mrbc_value mrbc_array_new(mrbc_vm *vm, int size)
Definition c_array.c:83
void mrbc_object_inspect(mrbc_vm *vm, mrbc_value v[], int argc)
Definition c_object.c:83
static int mrbc_string_append_cstr(mrbc_value *s1, const char *s2)
Definition c_string.h:134
static mrbc_value mrbc_string_new_cstr(mrbc_vm *vm, const char *src)
Definition c_string.h:91
#define MRBC_CLASS(cls)
Definition class.h:55
void mrbc_printf(const char *fstr,...)
Definition console.c:201
void mrbc_print_symbol(mrbc_sym sym_id)
Definition console.c:148
void mrbc_raisef(struct VM *vm, struct RClass *exc_cls, const char *fstr,...)
Definition error.c:168
Include at once the necessary header files.
uint16_t hash
hash value, returned by calc_hash().
Definition symbol.c:51
MRBC_SYMBOL_TABLE_INDEX_TYPE right
Definition symbol.c:54
const char * cstr
point to the symbol string.
Definition symbol.c:56
MRBC_SYMBOL_TABLE_INDEX_TYPE left
Definition symbol.c:53
Virtual Machine.
Definition vm.h:150
mrbc_sym mrbc_search_symid(const char *str)
Definition symbol.c:262
static int sym_index_pos
Definition symbol.c:63
mrbc_value mrbc_symbol_new(struct VM *vm, const char *str)
Definition symbol.c:340
mrbc_sym mrbc_str_to_symid(const char *str)
Definition symbol.c:221
static int search_index(uint16_t hash, const char *str)
Definition symbol.c:132
static int add_index(uint16_t hash, const char *str)
Definition symbol.c:167
void mrbc_separate_nested_symid(mrbc_sym sym_id, mrbc_sym *id1, mrbc_sym *id2)
Definition symbol.c:309
#define MRBC_SYMBOL_TABLE_INDEX_TYPE
Definition symbol.c:37
void mrbc_cleanup_symbol(void)
Definition symbol.c:208
static uint16_t calc_hash(const char *str)
Definition symbol.c:76
const char * mrbc_symid_to_str(mrbc_sym sym_id)
Definition symbol.c:242
void make_nested_symbol_s(char *buf, mrbc_sym id1, mrbc_sym id2)
Definition symbol.c:282
#define OFFSET_BUILTIN_SYMBOL
Definition symbol.c:42
static struct SYM_INDEX sym_index[MAX_SYMBOLS_COUNT]
Definition symbol.c:62
static int search_builtin_symbol(const char *str)
Definition symbol.c:93
static int mrbc_is_nested_symid(mrbc_sym sym_id)
Definition symbol.h:71
int16_t mrbc_sym
mruby/c symbol ID
Definition value.h:62
@ MRBC_TT_CLASS
Class.
Definition value.h:90
#define SET_RETURN(n)
Definition value.h:221
Global configuration of mruby/c VM's.
#define MAX_SYMBOLS_COUNT
Definition vm_config.h:30