mruby/c VM Source Code release 3.4
Loading...
Searching...
No Matches
class.c
Go to the documentation of this file.
1
13
14/***** Feature test switches ************************************************/
15/***** System headers *******************************************************/
16//@cond
17#include "vm_config.h"
18#include <stdint.h>
19#include <string.h>
20#include <assert.h>
21//@endcond
22
23/***** Local headers ********************************************************/
24#include "mrubyc.h"
25
26/***** Constant values ******************************************************/
27/***** Macros ***************************************************************/
28/***** Typedefs *************************************************************/
29/***** Function prototypes **************************************************/
30/***** Local variables ******************************************************/
31/***** Global variables *****************************************************/
38 0, // MRBC_TT_EMPTY = 0,
39 MRBC_CLASS(NilClass), // MRBC_TT_NIL = 1,
40 MRBC_CLASS(FalseClass), // MRBC_TT_FALSE = 2,
41 MRBC_CLASS(TrueClass), // MRBC_TT_TRUE = 3,
42 MRBC_CLASS(Integer), // MRBC_TT_INTEGER = 4,
43 MRBC_CLASS(Float), // MRBC_TT_FLOAT = 5,
44 MRBC_CLASS(Symbol), // MRBC_TT_SYMBOL = 6,
45 0, // MRBC_TT_CLASS = 7,
46 0, // MRBC_TT_MODULE = 8,
47 0, // MRBC_TT_OBJECT = 9,
48 MRBC_CLASS(Proc), // MRBC_TT_PROC = 10,
49 MRBC_CLASS(Array), // MRBC_TT_ARRAY = 11,
50 MRBC_CLASS(String), // MRBC_TT_STRING = 12,
51 MRBC_CLASS(Range), // MRBC_TT_RANGE = 13,
52 MRBC_CLASS(Hash), // MRBC_TT_HASH = 14,
53 0, // MRBC_TT_EXCEPTION = 15,
54};
55
56
57/***** Signal catching functions ********************************************/
58/***** Local functions ******************************************************/
59//================================================================
67mrbc_class * mrbc_traverse_class_tree( mrbc_class *cls, mrbc_class *nest_buf[], int *nest_idx )
68{
69 cls = cls->super;
70
71 if( cls == 0 ) {
72 if( *nest_idx == 0 ) return 0; // does not have super class.
73 cls = nest_buf[--(*nest_idx)]; // rewind to the saved point.
74 cls = cls->super;
75 }
76
77 // is the next module alias?
78 if( cls->flag_alias ) {
79 if( cls->super ) {
80 // save the branch point to nest_buf.
81 if( *nest_idx >= MRBC_TRAVERSE_NEST_LEVEL ) {
82 mrbc_printf("Warning: Module nest exceeds upper limit.\n");
83 } else {
84 nest_buf[(*nest_idx)++] = cls;
85 }
86 }
87
88 cls = cls->aliased;
89 }
90
91 return cls;
92}
93
94
95//================================================================
103{
104 if( *nest_idx == 0 ) return 0; // does not have super class.
105 return nest_buf[--(*nest_idx)]; // rewind to the saved point.
106}
107
108
109/***** Global functions *****************************************************/
110//================================================================
118mrbc_class * mrbc_define_class(struct VM *vm, const char *name, mrbc_class *super)
119{
120 mrbc_sym sym_id = mrbc_str_to_symid(name);
121 if( sym_id < 0 ) {
122 mrbc_raise(vm, MRBC_CLASS(Exception), "Overflow MAX_SYMBOLS_COUNT");
123 return 0;
124 }
125
126 // already defined?
127 const mrbc_value *val = mrbc_get_const(sym_id);
128 if( val ) {
129 if( mrbc_type(*val) != MRBC_TT_CLASS ) {
130 mrbc_raisef(vm, MRBC_CLASS(TypeError), "%s is not a class", name);
131 }
132 return val->cls;
133 }
134
135 // create a new class.
137 if( !cls ) return cls; // ENOMEM
138
139 *cls = (mrbc_class){
140 .sym_id = sym_id,
141 .super = super ? super : MRBC_CLASS(Object),
142#if defined(MRBC_DEBUG)
143 .name = name,
144#endif
145 };
146
147 // register to global constant
148 mrbc_set_const( sym_id, &(mrbc_value){.tt = MRBC_TT_CLASS, .cls = cls});
149
150 return cls;
151}
152
153
154//================================================================
163mrbc_class * mrbc_define_class_under(struct VM *vm, const mrbc_class *outer, const char *name, mrbc_class *super)
164{
165 mrbc_sym sym_id = mrbc_str_to_symid(name);
166 if( sym_id < 0 ) {
167 mrbc_raise(vm, MRBC_CLASS(Exception), "Overflow MAX_SYMBOLS_COUNT");
168 return 0;
169 }
170
171 // already defined?
172 const mrbc_value *val = mrbc_get_class_const( outer, sym_id );
173 if( val ) {
174 if( val->tt != MRBC_TT_CLASS ) {
175 mrbc_raisef(vm, MRBC_CLASS(TypeError), "%s is not a class", name);
176 return 0;
177 }
178 return val->cls;
179 }
180
181 // create a new nested class.
183 if( !cls ) return cls; // ENOMEM
184
185 char buf[sizeof(mrbc_sym)*4+1];
186 make_nested_symbol_s( buf, outer->sym_id, sym_id );
187
188 *cls = (mrbc_class){
189 .sym_id = mrbc_symbol( mrbc_symbol_new( vm, buf )),
190 .super = super ? super : MRBC_CLASS(Object),
191#if defined(MRBC_DEBUG)
192 .name = name,
193#endif
194 };
195
196 // register to global constant
197 mrbc_set_class_const( outer, sym_id,
198 &(mrbc_value){.tt = MRBC_TT_CLASS, .cls = cls});
199 return cls;
200}
201
202
203//================================================================
210mrbc_class * mrbc_define_module(struct VM *vm, const char *name)
211{
212 mrbc_sym sym_id = mrbc_str_to_symid(name);
213 if( sym_id < 0 ) {
214 mrbc_raise(vm, MRBC_CLASS(Exception), "Overflow MAX_SYMBOLS_COUNT");
215 return 0;
216 }
217
218 // already defined?
219 const mrbc_value *val = mrbc_get_const(sym_id);
220 if( val ) {
221 if( mrbc_type(*val) != MRBC_TT_MODULE ) {
222 mrbc_raisef(vm, MRBC_CLASS(TypeError), "%s is not a module", name);
223 }
224 return val->cls;
225 }
226
227 // create a new module.
229 if( !cls ) return cls; // ENOMEM
230
231 *cls = (mrbc_class){
232 .sym_id = sym_id,
233 .flag_module = 1,
234 .super = 0,
235#if defined(MRBC_DEBUG)
236 .name = name,
237#endif
238 };
239
240 // register to global constant
241 mrbc_set_const( sym_id, &(mrbc_value){.tt = MRBC_TT_MODULE, .cls = cls});
242
243 return cls;
244}
245
246
247//================================================================
255mrbc_class * mrbc_define_module_under(struct VM *vm, const mrbc_class *outer, const char *name)
256{
257 mrbc_sym sym_id = mrbc_str_to_symid(name);
258 if( sym_id < 0 ) {
259 mrbc_raise(vm, MRBC_CLASS(Exception), "Overflow MAX_SYMBOLS_COUNT");
260 return 0;
261 }
262
263 // already defined?
264 const mrbc_value *val = mrbc_get_class_const( outer, sym_id );
265 if( val ) {
266 if( val->tt != MRBC_TT_MODULE ) {
267 mrbc_raisef(vm, MRBC_CLASS(TypeError), "%s is not a module", name);
268 return 0;
269 }
270 return val->cls;
271 }
272
273 // create a new nested module
275 if( !cls ) return cls; // ENOMEM
276
277 char buf[sizeof(mrbc_sym)*4+1];
278 make_nested_symbol_s( buf, outer->sym_id, sym_id );
279
280 *cls = (mrbc_class){
281 .sym_id = mrbc_symbol( mrbc_symbol_new( vm, buf )),
282 .flag_module = 1,
283 .super = 0,
284#if defined(MRBC_DEBUG)
285 .name = name,
286#endif
287 };
288
289 // register to global constant
290 mrbc_set_class_const( outer, sym_id,
291 &(mrbc_value){.tt = MRBC_TT_MODULE, .cls = cls});
292 return cls;
293}
294
295
296//================================================================
304void mrbc_define_method(struct VM *vm, mrbc_class *cls, const char *name, mrbc_func_t cfunc)
305{
306 if( cls == NULL ) cls = MRBC_CLASS(Object); // set default to Object.
307
309 if( !method ) return; // ENOMEM
310
311 method->type = 'm';
312 method->c_func = 1;
313 method->sym_id = mrbc_str_to_symid( name );
314 if( method->sym_id < 0 ) {
315 mrbc_raise(vm, MRBC_CLASS(Exception), "Overflow MAX_SYMBOLS_COUNT");
316 }
317 method->func = cfunc;
318 method->next = cls->method_link;
319 cls->method_link = method;
320}
321
322
323//================================================================
331mrbc_value mrbc_instance_new(struct VM *vm, mrbc_class *cls, int size)
332{
333 mrbc_value v = {.tt = MRBC_TT_OBJECT};
334 v.instance = mrbc_alloc(vm, sizeof(mrbc_instance) + size);
335 if( v.instance == NULL ) return v; // ENOMEM
336
337 if( mrbc_kv_init_handle(vm, &v.instance->ivar, 0) != 0 ) {
339 v.instance = NULL;
340 return v;
341 }
342
344 v.instance->cls = cls;
345
346 return v;
347}
348
349
350//================================================================
356{
357 assert( v->tt == MRBC_TT_OBJECT );
358 mrbc_class *cls = v->instance->cls;
359
360 if( !cls->flag_builtin && cls->destructor ) cls->destructor( v );
361
364}
365
366
367//================================================================
375{
376 mrbc_incref(v);
377 mrbc_kv_set( &obj->instance->ivar, sym_id, v );
378}
379
380
381//================================================================
389{
390 mrbc_value *v = mrbc_kv_get( &obj->instance->ivar, sym_id );
391 if( !v ) return mrbc_nil_value();
392
393 mrbc_incref(v);
394 return *v;
395}
396
397
398#if defined(MRBC_ALLOC_VMID)
399//================================================================
404void mrbc_instance_clear_vm_id(mrbc_value *v)
405{
406 mrbc_set_vm_id( v->instance, 0 );
407 mrbc_kv_clear_vm_id( &v->instance->ivar );
408}
409#endif
410
411
412//================================================================
419int mrbc_obj_is_kind_of( const mrbc_value *obj, const mrbc_class *tcls )
420{
421 mrbc_class *cls = find_class_by_object( obj );
423 int nest_idx = 0;
424
425 while( cls != tcls ) {
426 cls = mrbc_traverse_class_tree( cls, nest_buf, &nest_idx );
427 if( ! cls ) return 0;
428 }
429
430 return 1;
431}
432
433
434//================================================================
443{
445 int nest_idx = 0;
446 int flag_module = cls->flag_module;
447
448 while( 1 ) {
449 mrbc_method *method;
450 for( method = cls->method_link; method != 0; method = method->next ) {
451 if( method->sym_id == sym_id ) {
452 *r_method = *method;
453 r_method->cls = cls;
454 return r_method;
455 }
456 }
457
458 struct RBuiltinClass *c = (struct RBuiltinClass *)cls;
459 int right = c->num_builtin_method;
460 if( right == 0 ) goto NEXT;
461 int left = 0;
462
463 while( left < right ) {
464 int mid = (left + right) / 2;
465 if( c->method_symbols[mid] < sym_id ) {
466 left = mid + 1;
467 } else {
468 right = mid;
469 }
470 }
471
472 if( c->method_symbols[right] == sym_id ) {
473 r_method->type = 'm';
474 r_method->c_func = 2;
475 r_method->sym_id = sym_id;
476 r_method->func = c->method_functions[right];
477 r_method->cls = cls;
478 return r_method;
479 }
480
481 NEXT:
482 cls = mrbc_traverse_class_tree( cls, nest_buf, &nest_idx );
483 if( cls == 0 ) {
484 if( !flag_module ) break;
485
486 cls = MRBC_CLASS(Object);
487 flag_module = 0;
488 }
489 } // loop next.
490
491 return 0;
492}
493
494
495//================================================================
502{
504 if( sym_id < 0 ) return NULL;
505
507 if( obj == NULL ) return NULL;
508
509 if( obj->tt == MRBC_TT_CLASS ||
510 obj->tt == MRBC_TT_MODULE ) return obj->cls;
511
512 return NULL;
513}
514
515
516//================================================================
538mrbc_value mrbc_send( struct VM *vm, mrbc_value *v, int argc,
539 mrbc_value *recv, const char *method_name, int n_params, ... )
540{
541 mrbc_method method;
542 mrbc_class *cls = find_class_by_object(recv);
543
544 if( mrbc_find_method( &method, cls, mrbc_str_to_symid(method_name)) == 0 ) {
545 mrbc_raisef(vm, MRBC_CLASS(NoMethodError), "undefined method '%s' for %s",
546 method_name, mrbc_symid_to_str(cls->sym_id) );
547 goto ERROR;
548 }
549 if( !method.c_func ) {
550 mrbc_raisef(vm, MRBC_CLASS(NotImplementedError),
551 "Method needs to be C function. '%s' for %s",
552 method_name, mrbc_symid_to_str(cls->sym_id) );
553 goto ERROR;
554 }
555
556 // create call stack.
557 mrbc_value *regs = v + argc + 2;
558 mrbc_decref( &regs[0] );
559 regs[0] = *recv;
560 mrbc_incref(recv);
561
562 va_list ap;
563 va_start(ap, n_params);
564 int i;
565 for( i = 1; i <= n_params; i++ ) {
566 mrbc_decref( &regs[i] );
567 regs[i] = *va_arg(ap, mrbc_value *);
568 }
569 mrbc_decref( &regs[i] );
570 regs[i] = mrbc_nil_value();
571 va_end(ap);
572
573 // call method.
574 method.func(vm, regs, n_params);
575 mrbc_value ret = regs[0];
576
577 for(; i >= 0; i-- ) {
578 regs[i].tt = MRBC_TT_EMPTY;
579 }
580
581 return ret;
582
583 ERROR:
584 return mrbc_nil_value();
585}
586
587
588//================================================================
591void c_ineffect(struct VM *vm, mrbc_value v[], int argc)
592{
593 // nothing to do.
594}
595
596
597//================================================================
603int mrbc_run_mrblib(const void *bytecode)
604{
605 // instead of mrbc_vm_open()
607 if( !vm ) return -1; // ENOMEM
608
609 if( mrbc_load_mrb(vm, bytecode) ) {
611 return 2;
612 }
613
614 int ret;
615
616 mrbc_vm_begin(vm);
617 do {
618 ret = mrbc_vm_run(vm);
619 } while( ret == 0 );
620 mrbc_vm_end(vm);
621 mrbc_vm_close(vm);
622
623 return ret;
624}
625
626#define MRBC_DEFINE_BUILTIN_CLASS_TABLE
627#include "_autogen_builtin_class.h"
628#undef MRBC_DEFINE_BUILTIN_CLASS_TABLE
629
630//================================================================
634{
635 // initialize builtin class.
636 mrbc_value vcls;
637
638 for( int i = 0; i < sizeof(MRBC_BuiltinClass)/sizeof(struct MRBC_BuiltinClass); i++ ) {
639 mrbc_class *cls = MRBC_BuiltinClass[i].cls;
640
641 cls->super = MRBC_BuiltinClass[i].super;
642 cls->method_link = 0;
643 vcls.cls = cls;
645
646 mrbc_set_const( cls->sym_id, &vcls );
647 }
648
649#if MRBC_USE_MATH
651#endif
652
653 extern const uint8_t mrblib_bytecode[];
654 mrbc_run_mrblib(mrblib_bytecode);
655}
void * mrbc_raw_alloc_no_free(unsigned int size)
Definition alloc.c:619
void mrbc_raw_free(void *ptr)
Definition alloc.c:695
void mrbc_init_module_math(void)
Definition c_math.c:245
mrbc_value mrbc_instance_new(struct VM *vm, mrbc_class *cls, int size)
Definition class.c:331
mrbc_class * mrbc_get_class_by_name(const char *name)
Definition class.c:501
void mrbc_init_class(void)
Definition class.c:633
mrbc_class * mrbc_define_module_under(struct VM *vm, const mrbc_class *outer, const char *name)
Definition class.c:255
void c_ineffect(struct VM *vm, mrbc_value v[], int argc)
Definition class.c:591
int mrbc_obj_is_kind_of(const mrbc_value *obj, const mrbc_class *tcls)
Definition class.c:419
void mrbc_define_method(struct VM *vm, mrbc_class *cls, const char *name, mrbc_func_t cfunc)
Definition class.c:304
mrbc_value mrbc_instance_getiv(mrbc_value *obj, mrbc_sym sym_id)
Definition class.c:388
mrbc_class * mrbc_traverse_class_tree(mrbc_class *cls, mrbc_class *nest_buf[], int *nest_idx)
Definition class.c:67
void mrbc_instance_delete(mrbc_value *v)
Definition class.c:355
mrbc_class * mrbc_define_module(struct VM *vm, const char *name)
Definition class.c:210
int mrbc_run_mrblib(const void *bytecode)
Definition class.c:603
void mrbc_instance_setiv(mrbc_value *obj, mrbc_sym sym_id, mrbc_value *v)
Definition class.c:374
mrbc_method * mrbc_find_method(mrbc_method *r_method, mrbc_class *cls, mrbc_sym sym_id)
Definition class.c:442
mrbc_value mrbc_send(struct VM *vm, mrbc_value *v, int argc, mrbc_value *recv, const char *method_name, int n_params,...)
Definition class.c:538
mrbc_class * mrbc_define_class_under(struct VM *vm, const mrbc_class *outer, const char *name, mrbc_class *super)
Definition class.c:163
mrbc_class *const mrbc_class_tbl[MRBC_TT_MAXVAL+1]
Definition class.c:37
mrbc_class * mrbc_define_class(struct VM *vm, const char *name, mrbc_class *super)
Definition class.c:118
mrbc_class * mrbc_traverse_class_tree_skip(mrbc_class *nest_buf[], int *nest_idx)
Definition class.c:102
struct RInstance mrbc_instance
Instance object.
#define MRBC_TRAVERSE_NEST_LEVEL
Definition class.h:34
struct RMethod mrbc_method
Method management structure.
#define MRBC_CLASS(cls)
Definition class.h:51
static mrbc_class * find_class_by_object(const mrbc_value *obj)
Definition class.h:235
struct RClass mrbc_class
Class object.
void mrbc_printf(const char *fstr,...)
Definition console.c:180
void mrbc_raise(struct VM *vm, struct RClass *exc_cls, const char *msg)
Definition error.c:150
void mrbc_print_vm_exception(const struct VM *vm)
Definition error.c:236
void mrbc_raisef(struct VM *vm, struct RClass *exc_cls, const char *fstr,...)
Definition error.c:173
mrbc_value * mrbc_get_class_const(const struct RClass *cls, mrbc_sym sym_id)
Definition global.c:101
mrbc_value * mrbc_get_const(mrbc_sym sym_id)
Definition global.c:88
int mrbc_set_class_const(const struct RClass *cls, mrbc_sym sym_id, mrbc_value *v)
Definition global.c:71
int mrbc_set_const(mrbc_sym sym_id, mrbc_value *v)
Definition global.c:53
int mrbc_kv_init_handle(struct VM *vm, mrbc_kv_handle *kvh, int size)
Definition keyvalue.c:131
void mrbc_kv_delete_data(mrbc_kv_handle *kvh)
Definition keyvalue.c:171
mrbc_value * mrbc_kv_get(mrbc_kv_handle *kvh, mrbc_sym sym_id)
Definition keyvalue.c:292
int mrbc_kv_set(mrbc_kv_handle *kvh, mrbc_sym sym_id, mrbc_value *set_val)
Definition keyvalue.c:233
int mrbc_load_mrb(struct VM *vm, const void *bytecode)
Definition load.c:292
Include at once the necessary header files.
Built-in class object.
Definition class.h:108
uint8_t num_builtin_method
num of built-in method.
Definition class.h:113
unsigned int flag_module
is module?
Definition class.h:111
mrbc_sym sym_id
class name's symbol ID
Definition class.h:109
const mrbc_sym * method_symbols
built-in method sym-id table.
Definition class.h:123
const mrbc_func_t * method_functions
built-in method function table.
Definition class.h:124
struct RMethod * method_link
pointer to method link.
Definition class.h:91
unsigned int flag_alias
is module alias?
Definition class.h:87
struct RClass * super
pointer to super class.
Definition class.h:89
struct RClass * aliased
aliased class or module.
Definition class.h:92
unsigned int flag_builtin
is built-in class? (= 0)
Definition class.h:85
mrbc_sym sym_id
class name's symbol ID
Definition class.h:84
void(* destructor)(mrbc_value *)
specify a destructor if need.
Definition class.h:98
unsigned int flag_module
is module?
Definition class.h:86
struct RClass * cls
pointer to class of this object.
Definition class.h:158
struct RKeyValueHandle ivar
instance variable.
Definition class.h:159
struct RClass * cls
return value for mrbc_find_method.
Definition class.h:180
mrbc_sym sym_id
function names symbol ID
Definition class.h:173
uint8_t type
M:OP_DEF or OP_ALIAS, m:mrblib or define_method()
Definition class.h:171
struct RMethod * next
link to next method.
Definition class.h:179
uint8_t c_func
0:IREP, 1:C Func, 2:C Func (built-in)
Definition class.h:172
mrbc_func_t func
to C function.
Definition class.h:176
struct RInstance * instance
Definition value.h:161
mrbc_vtype tt
Definition value.h:152
struct RClass * cls
Definition value.h:160
Virtual Machine.
Definition vm.h:140
mrbc_sym mrbc_search_symid(const char *str)
Definition symbol.c:258
mrbc_value mrbc_symbol_new(struct VM *vm, const char *str)
Definition symbol.c:334
mrbc_sym mrbc_str_to_symid(const char *str)
Definition symbol.c:217
const char * mrbc_symid_to_str(mrbc_sym sym_id)
Definition symbol.c:238
void make_nested_symbol_s(char *buf, mrbc_sym id1, mrbc_sym id2)
Definition symbol.c:278
static void mrbc_decref(mrbc_value *v)
Definition value.h:604
#define mrbc_symbol(o)
Definition value.h:196
#define MRBC_INIT_OBJECT_HEADER(p, t)
Definition value.h:307
#define mrbc_nil_value()
Definition value.h:210
void(* mrbc_func_t)(struct VM *vm, struct RObject *v, int argc)
Definition value.h:60
#define MRBC_TT_MAXVAL
Definition value.h:101
static void mrbc_incref(mrbc_value *v)
Definition value.h:589
#define mrbc_type(o)
Definition value.h:193
int16_t mrbc_sym
mruby/c symbol ID
Definition value.h:59
@ MRBC_TT_EMPTY
Definition value.h:77
@ MRBC_TT_OBJECT
General instance.
Definition value.h:92
@ MRBC_TT_MODULE
Module.
Definition value.h:88
@ MRBC_TT_CLASS
Class.
Definition value.h:87
struct RObject mrbc_value
Definition value.h:174
mrbc_vm * mrbc_vm_new(int regs_size)
Definition vm.c:292
void mrbc_vm_end(struct VM *vm)
Definition vm.c:375
void mrbc_vm_begin(struct VM *vm)
Definition vm.c:348
int mrbc_vm_run(struct VM *vm)
Definition vm.c:2889
void mrbc_vm_close(struct VM *vm)
Definition vm.c:411
struct VM mrbc_vm
Virtual Machine.
Global configuration of mruby/c VM's.
#define MAX_REGS_SIZE
Definition vm_config.h:23