mruby/c VM Source Code release 4.0.0
Loading...
Searching...
No Matches
class.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 <assert.h>
22//@endcond
23
24/***** Local headers ********************************************************/
25#include "mrubyc.h"
26
27/***** Constant values ******************************************************/
28/***** Macros ***************************************************************/
29/***** Typedefs *************************************************************/
30/***** Function prototypes **************************************************/
31/***** Local variables ******************************************************/
32/***** Global variables *****************************************************/
39 0, // MRBC_TT_EMPTY = 0,
40 MRBC_CLASS(NilClass), // MRBC_TT_NIL = 1,
41 MRBC_CLASS(FalseClass), // MRBC_TT_FALSE = 2,
42 MRBC_CLASS(TrueClass), // MRBC_TT_TRUE = 3,
43 MRBC_CLASS(Integer), // MRBC_TT_INTEGER = 4,
44 MRBC_CLASS(Float), // MRBC_TT_FLOAT = 5,
45 MRBC_CLASS(Symbol), // MRBC_TT_SYMBOL = 6,
46 0, // MRBC_TT_CLASS = 7,
47 0, // MRBC_TT_MODULE = 8,
48 0, // MRBC_TT_OBJECT = 9,
49 MRBC_CLASS(Proc), // MRBC_TT_PROC = 10,
50 MRBC_CLASS(Array), // MRBC_TT_ARRAY = 11,
51 MRBC_CLASS(String), // MRBC_TT_STRING = 12,
52 MRBC_CLASS(Range), // MRBC_TT_RANGE = 13,
53 MRBC_CLASS(Hash), // MRBC_TT_HASH = 14,
54 0, // MRBC_TT_EXCEPTION = 15,
55};
56
57
58/***** Signal catching functions ********************************************/
59/***** Local functions ******************************************************/
60//================================================================
68mrbc_class * mrbc_traverse_class_tree( mrbc_class *cls, mrbc_class *nest_buf[], int *nest_idx )
69{
70 cls = cls->super;
71
72 if( cls == 0 ) {
73 if( *nest_idx == 0 ) return 0; // does not have super class.
74 cls = nest_buf[--(*nest_idx)]; // rewind to the saved point.
75 cls = cls->super;
76 }
77
78 // when alias module
79 if( cls->flag_alias && 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 return cls;
89}
90
91
92//================================================================
100{
101 if( *nest_idx == 0 ) return 0; // does not have super class.
102 return nest_buf[--(*nest_idx)]; // rewind to the saved point.
103}
104
105
106/***** Global functions *****************************************************/
107
108//----------------------------------------------------------------
109static mrbc_class * sub_define_class_or_module(struct VM *vm, const char *name, mrbc_class *super, mrbc_vtype vtype)
110{
111 mrbc_sym sym_id = mrbc_str_to_symid(name);
112 if( sym_id < 0 ) {
113 mrbc_raise(vm, MRBC_CLASS(Exception), "Overflow MAX_SYMBOLS_COUNT");
114 return NULL;
115 }
116
117 // already defined?
118 const mrbc_value *val = mrbc_get_const(sym_id);
119 if( val ) {
120 if( mrbc_type(*val) != vtype ) { // is not TT_CLASS or TT_MODULE
121 mrbc_raisef(vm, MRBC_CLASS(TypeError), "%s is not a %s", name,
122 vtype == MRBC_TT_CLASS ? "class" : "module");
123 return NULL;
124 }
125 return val->cls;
126 }
127
128 // create a new class/module.
130
131 *cls = (mrbc_class){
132 .sym_id = sym_id,
133 .flag_module = (vtype == MRBC_TT_MODULE),
134 .super = super,
135#if defined(MRBC_DEBUG)
136 .name = name,
137#endif
138 };
139#if defined(MRBC_DEBUG)
140 if( vtype == MRBC_TT_CLASS ) {
141 cls->obj_mark_[0] = 'C';
142 cls->obj_mark_[1] = 'L';
143 } else {
144 cls->obj_mark_[0] = 'M';
145 cls->obj_mark_[1] = 'O';
146 }
147#endif
148
149 // register to global constant
150 mrbc_set_const( sym_id, &mrbc_immediate_value(vtype, .cls = cls) );
151
152 return cls;
153}
154
155
156//----------------------------------------------------------------
157static mrbc_class * sub_mrbc_define_class_module_under(struct VM *vm, const mrbc_class *outer, const char *name, mrbc_class *super, mrbc_vtype vtype)
158{
159 mrbc_sym sym_id = mrbc_str_to_symid(name);
160 if( sym_id < 0 ) {
161 mrbc_raise(vm, MRBC_CLASS(Exception), "Overflow MAX_SYMBOLS_COUNT");
162 return NULL;
163 }
164
165 // already defined?
166 const mrbc_value *val = mrbc_get_class_const( outer, sym_id );
167 if( val ) {
168 if( mrbc_type(*val) != vtype ) { // is not TT_CLASS or TT_MODULE
169 mrbc_raisef(vm, MRBC_CLASS(TypeError), "%s is not a %s", name,
170 vtype == MRBC_TT_CLASS ? "class" : "module");
171 return NULL;
172 }
173 return val->cls;
174 }
175
176 // create a new nested class/module.
178
179 char buf[sizeof(mrbc_sym)*4+1];
180 make_nested_symbol_s( buf, outer->sym_id, sym_id );
181
182 *cls = (mrbc_class){
183 .sym_id = mrbc_symbol( mrbc_symbol_new( vm, buf )),
184 .flag_module = (vtype == MRBC_TT_MODULE),
185 .super = super,
186#if defined(MRBC_DEBUG)
187 .name = name,
188#endif
189 };
190#if defined(MRBC_DEBUG)
191 if( vtype == MRBC_TT_CLASS ) {
192 cls->obj_mark_[0] = 'C';
193 cls->obj_mark_[1] = 'L';
194 } else {
195 cls->obj_mark_[0] = 'M';
196 cls->obj_mark_[1] = 'O';
197 }
198#endif
199
200 // register to global constant
201 mrbc_set_class_const( outer, sym_id, &mrbc_immediate_value(vtype, .cls = cls) );
202
203 return cls;
204}
205
206
207//================================================================
215mrbc_class * mrbc_define_class(struct VM *vm, const char *name, mrbc_class *super)
216{
217 return sub_define_class_or_module( vm, name,
218 (super ? super : MRBC_CLASS(Object)), MRBC_TT_CLASS );
219}
220
221
222//================================================================
231mrbc_class * mrbc_define_class_under(struct VM *vm, const mrbc_class *outer, const char *name, mrbc_class *super)
232{
233 return sub_mrbc_define_class_module_under( vm, outer, name,
234 (super ? super : MRBC_CLASS(Object)), MRBC_TT_CLASS );
235}
236
237
238//================================================================
245mrbc_class * mrbc_define_module(struct VM *vm, const char *name)
246{
247 return sub_define_class_or_module( vm, name, NULL, MRBC_TT_MODULE );
248}
249
250
251//================================================================
259mrbc_class * mrbc_define_module_under(struct VM *vm, const mrbc_class *outer, const char *name)
260{
261 return sub_mrbc_define_class_module_under( vm, outer, name,
262 NULL, MRBC_TT_MODULE);
263}
264
265
266//================================================================
274void mrbc_define_method(struct VM *vm, mrbc_class *cls, const char *name, mrbc_func_t cfunc)
275{
276 if( cls == NULL ) cls = MRBC_CLASS(Object); // set default to Object.
277 if( cls->flag_nomethod ) {
278 mrbc_raisef(vm, MRBC_CLASS(NotImplementedError),
279 "Adding methods to the %s class is not supported",
281 return;
282 }
283
285
286 method->type = 'm';
287 method->c_func = 1;
288 method->sym_id = mrbc_str_to_symid( name );
289 if( method->sym_id < 0 ) {
290 mrbc_raise(vm, MRBC_CLASS(Exception), "Overflow MAX_SYMBOLS_COUNT");
291 }
292 method->func = cfunc;
293 method->next = cls->method_link;
294 cls->method_link = method;
295}
296
297
298//================================================================
306mrbc_value mrbc_instance_new(struct VM *vm, mrbc_class *cls, int size)
307{
308 mrbc_instance *instance = mrbc_alloc(vm, sizeof(mrbc_instance) + size);
309
310 *instance = (mrbc_instance){
312 .cls = cls,
313 .ivar = MRBC_KVH_INITIALIZER(vm),
314 };
315
316 return mrbc_immediate_value(MRBC_TT_OBJECT, .instance = instance);
317}
318
319
320//================================================================
326{
327 assert( mrbc_type(*v) == MRBC_TT_OBJECT );
328
329#if MRBC_INSTANCE_DESTRUCTOR
330 mrbc_class *cls = v->instance->cls;
331 if( !cls->flag_builtin && cls->destructor ) cls->destructor( v );
332#endif
333
336}
337
338
339//================================================================
347{
348 mrbc_incref(v);
349 mrbc_kv_set( &obj->instance->ivar, sym_id, v );
350}
351
352
353//================================================================
361{
362 mrbc_value *v = mrbc_kv_get( &obj->instance->ivar, sym_id );
363 if( !v ) return mrbc_nil_value();
364
365 mrbc_incref(v);
366 return *v;
367}
368
369
370#if defined(MRBC_ALLOC_VMID)
371//================================================================
376void mrbc_instance_clear_vm_id(mrbc_value *v)
377{
378 mrbc_set_vm_id( v->instance, 0 );
379 mrbc_kv_clear_vm_id( &v->instance->ivar );
380}
381#endif
382
383
384//================================================================
391int mrbc_obj_is_kind_of( const mrbc_value *obj, const mrbc_class *tcls )
392{
393 mrbc_class *cls = find_class_by_object( obj );
395 int nest_idx = 0;
396
397 while( cls != tcls ) {
398 cls = mrbc_traverse_class_tree( cls, nest_buf, &nest_idx );
399 if( !cls ) return 0;
400 if( cls->flag_alias ) cls = cls->aliased;
401 }
402
403 return 1;
404}
405
406
407//================================================================
416{
418 int nest_idx = 0;
419 int flag_module = cls->flag_module;
420 mrbc_class *cls_save = cls;
421
422 if( cls->flag_alias ) {
423 if( cls->super ) nest_buf[nest_idx++] = cls;
424 cls = cls->aliased;
425 }
426
427 while( 1 ) {
428 mrbc_method *method;
429
430 assert( !cls->flag_alias );
431 if( cls->flag_nomethod ) goto next_class;
432 for( method = cls->method_link; method != 0; method = method->next ) {
433 if( method->sym_id == sym_id ) {
434 *r_method = *method;
435 r_method->cls = cls_save;
436 return cls_save;
437 }
438 }
439
440 struct RBuiltinClass *c = (struct RBuiltinClass *)cls;
441 int right = c->num_builtin_method;
442 if( right == 0 ) goto next_class;
443 right--;
444 int left = 0;
445
446 while( left < right ) {
447 int mid = (left + right) / 2;
448 if( c->method_symbols[mid] < sym_id ) {
449 left = mid + 1;
450 } else {
451 right = mid;
452 }
453 }
454
455 if( c->method_symbols[right] == sym_id ) {
456 *r_method = (mrbc_method){
457 .type = 'm',
458 .c_func = 2,
459 .sym_id = sym_id,
460 .func = c->method_functions[right],
461 .cls = cls_save,
462 };
463 return cls_save;
464 }
465
466 next_class:
467 cls = mrbc_traverse_class_tree( cls, nest_buf, &nest_idx );
468 if( cls == NULL ) {
469 if( !flag_module ) break;
470 cls = MRBC_CLASS(Object);
471 flag_module = 0;
472 }
473 cls_save = cls;
474 if( cls->flag_alias ) {
475 cls = cls->aliased;
476 }
477 } // loop next.
478
479 return NULL;
480}
481
482
483//================================================================
490{
492 if( sym_id < 0 ) return NULL;
493
495 if( obj == NULL ) return NULL;
496
497 if( mrbc_type(*obj) == MRBC_TT_CLASS ||
498 mrbc_type(*obj) == MRBC_TT_MODULE ) return obj->cls;
499
500 return NULL;
501}
502
503
504//================================================================
526mrbc_value mrbc_send( struct VM *vm, mrbc_value *v, int argc,
527 mrbc_value *recv, const char *method_name, int n_params, ... )
528{
529 mrbc_method method;
530 mrbc_class *cls = find_class_by_object(recv);
531 mrbc_sym sym_id = mrbc_str_to_symid(method_name);
532
533 if( mrbc_find_method( &method, cls, sym_id ) == 0 ) {
534 mrbc_raisef(vm, MRBC_CLASS(NoMethodError), "undefined method '%s' for %s",
535 method_name, mrbc_symid_to_str(cls->sym_id) );
536 goto ERROR;
537 }
538 if( !method.c_func ) {
539 mrbc_raisef(vm, MRBC_CLASS(NotImplementedError),
540 "Method needs to be C function. '%s' for %s",
541 method_name, mrbc_symid_to_str(cls->sym_id) );
542 goto ERROR;
543 }
544
545 // create call stack.
546 mrbc_value *regs = v + argc + 2;
547 mrbc_decref( &regs[0] );
548 regs[0] = *recv;
549 mrbc_incref(recv);
550
551 va_list ap;
552 va_start(ap, n_params);
553 int i;
554 for( i = 1; i <= n_params; i++ ) {
555 mrbc_decref( &regs[i] );
556 regs[i] = *va_arg(ap, mrbc_value *);
557 }
558 mrbc_decref( &regs[i] );
559 mrbc_set_nil( &regs[i] );
560 va_end(ap);
561
562 // call method.
563 vm->callee_sym_id = sym_id;
564 method.func(vm, regs, n_params);
565 mrbc_value ret = regs[0];
566
567 for(; i >= 0; i-- ) {
568 mrbc_set_tt(&regs[i], MRBC_TT_EMPTY);
569 }
570
571 return ret;
572
573 ERROR:
574 return mrbc_nil_value();
575}
576
577
578//================================================================
581void c_ineffect(struct VM *vm, mrbc_value v[], int argc)
582{
583 // nothing to do.
584}
585
586
587//================================================================
593int mrbc_run_mrblib(const void *bytecode)
594{
595 // instead of mrbc_vm_open()
597
598 if( mrbc_load_mrb(vm, bytecode) ) {
600 return 2;
601 }
602
603 int ret;
604
605 mrbc_vm_begin(vm);
606 do {
607 ret = mrbc_vm_run(vm);
608 } while( ret == 0 );
609 mrbc_vm_end(vm);
610 mrbc_vm_close(vm);
611
612 return ret;
613}
614
615#define MRBC_DEFINE_BUILTIN_CLASS_TABLE
616#include "_autogen_builtin_class.h"
617#undef MRBC_DEFINE_BUILTIN_CLASS_TABLE
618
619//================================================================
623{
624 // initialize builtin class.
625 mrbc_value vcls;
626
627 for( int i = 0; i < sizeof(MRBC_BuiltinClass)/sizeof(struct MRBC_BuiltinClass); i++ ) {
628 mrbc_class *cls = MRBC_BuiltinClass[i].cls;
629
630 cls->super = MRBC_BuiltinClass[i].super;
631 if( !cls->flag_nomethod ) cls->method_link = 0;
633 vcls.cls = cls;
634 mrbc_set_const( cls->sym_id, &vcls );
635 }
636
637#if MRBC_USE_MATH
639#endif
640
641 extern const uint8_t mrblib_bytecode[];
642 mrbc_run_mrblib(mrblib_bytecode);
643}
void * mrbc_raw_alloc_no_free(unsigned int size)
Definition alloc.c:631
void mrbc_raw_free(void *ptr)
Definition alloc.c:707
static void mrbc_set_nil(mrbc_value *p)
Definition boxing_no.h:93
#define mrbc_immediate_value(...)
Definition boxing_no.h:71
#define mrbc_symbol(o)
Definition boxing_no.h:60
#define mrbc_nil_value()
Definition boxing_no.h:66
static void mrbc_set_tt(mrbc_value *p, mrbc_vtype type)
Definition boxing_no.h:119
#define mrbc_type(o)
Definition boxing_no.h:57
struct RObject mrbc_value
Value object. Default version.
void mrbc_init_module_math(void)
Definition c_math.c:246
mrbc_value mrbc_instance_new(struct VM *vm, mrbc_class *cls, int size)
Definition class.c:306
mrbc_class * mrbc_get_class_by_name(const char *name)
Definition class.c:489
mrbc_class * mrbc_find_method(mrbc_method *r_method, mrbc_class *cls, mrbc_sym sym_id)
Definition class.c:415
void mrbc_init_class(void)
Definition class.c:622
mrbc_class * mrbc_define_module_under(struct VM *vm, const mrbc_class *outer, const char *name)
Definition class.c:259
void c_ineffect(struct VM *vm, mrbc_value v[], int argc)
Definition class.c:581
static mrbc_class * sub_mrbc_define_class_module_under(struct VM *vm, const mrbc_class *outer, const char *name, mrbc_class *super, mrbc_vtype vtype)
Definition class.c:157
int mrbc_obj_is_kind_of(const mrbc_value *obj, const mrbc_class *tcls)
Definition class.c:391
void mrbc_define_method(struct VM *vm, mrbc_class *cls, const char *name, mrbc_func_t cfunc)
Definition class.c:274
mrbc_value mrbc_instance_getiv(mrbc_value *obj, mrbc_sym sym_id)
Definition class.c:360
mrbc_class * mrbc_traverse_class_tree(mrbc_class *cls, mrbc_class *nest_buf[], int *nest_idx)
Definition class.c:68
static mrbc_class * sub_define_class_or_module(struct VM *vm, const char *name, mrbc_class *super, mrbc_vtype vtype)
Definition class.c:109
void mrbc_instance_delete(mrbc_value *v)
Definition class.c:325
mrbc_class * mrbc_define_module(struct VM *vm, const char *name)
Definition class.c:245
int mrbc_run_mrblib(const void *bytecode)
Definition class.c:593
void mrbc_instance_setiv(mrbc_value *obj, mrbc_sym sym_id, mrbc_value *v)
Definition class.c:346
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:526
mrbc_class * mrbc_define_class_under(struct VM *vm, const mrbc_class *outer, const char *name, mrbc_class *super)
Definition class.c:231
mrbc_class *const mrbc_class_tbl[MRBC_TT_MAXVAL+1]
Definition class.c:38
mrbc_class * mrbc_define_class(struct VM *vm, const char *name, mrbc_class *super)
Definition class.c:215
mrbc_class * mrbc_traverse_class_tree_skip(mrbc_class *nest_buf[], int *nest_idx)
Definition class.c:99
struct RInstance mrbc_instance
Instance object.
#define MRBC_TRAVERSE_NEST_LEVEL
Definition class.h:35
struct RMethod mrbc_method
Method management structure.
#define MRBC_CLASS(cls)
Definition class.h:55
static mrbc_class * find_class_by_object(const mrbc_value *obj)
Definition class.h:262
struct RClass mrbc_class
Class object.
void mrbc_printf(const char *fstr,...)
Definition console.c:201
void mrbc_raise(struct VM *vm, struct RClass *exc_cls, const char *msg)
Definition error.c:145
void mrbc_print_vm_exception(const struct VM *vm)
Definition error.c:231
void mrbc_raisef(struct VM *vm, struct RClass *exc_cls, const char *fstr,...)
Definition error.c:168
int mrbc_set_class_const(const mrbc_class *cls, mrbc_sym sym_id, mrbc_value *v)
Definition global.c:75
mrbc_value * mrbc_get_const(mrbc_sym sym_id)
Definition global.c:92
int mrbc_set_const(mrbc_sym sym_id, mrbc_value *v)
Definition global.c:57
mrbc_value * mrbc_get_class_const(const mrbc_class *cls, mrbc_sym sym_id)
Definition global.c:105
void mrbc_kv_delete_data(mrbc_kv_handle *kvh)
Definition keyvalue.c:167
mrbc_value * mrbc_kv_get(mrbc_kv_handle *kvh, mrbc_sym sym_id)
Definition keyvalue.c:284
int mrbc_kv_set(mrbc_kv_handle *kvh, mrbc_sym sym_id, mrbc_value *set_val)
Definition keyvalue.c:228
#define MRBC_KVH_INITIALIZER(vm)
Definition keyvalue.h:63
int mrbc_load_mrb(mrbc_vm *vm, const void *bytecode)
Definition load.c:303
Include at once the necessary header files.
Built-in class object.
Definition class.h:127
uint8_t num_builtin_method
num of built-in method.
Definition class.h:138
unsigned int flag_module
is module?
Definition class.h:136
mrbc_sym sym_id
class name's symbol ID
Definition class.h:133
const mrbc_sym * method_symbols
built-in method sym-id table.
Definition class.h:147
const mrbc_func_t * method_functions
built-in method function table.
Definition class.h:148
struct RMethod * method_link
pointer to method link.
Definition class.h:107
unsigned int flag_alias
is module alias?
Definition class.h:101
struct RClass * super
pointer to super class.
Definition class.h:103
struct RClass * aliased
aliased class or module.
Definition class.h:108
unsigned int flag_builtin
is built-in class? (= 0)
Definition class.h:98
mrbc_sym sym_id
class name's symbol ID
Definition class.h:97
void(* destructor)(mrbc_value *)
specify a destructor if need.
Definition class.h:112
unsigned int flag_nomethod
is built-in no method class? (= 0)
Definition class.h:99
unsigned int flag_module
is module?
Definition class.h:100
struct RClass * cls
pointer to class of this object.
Definition class.h:182
struct RKeyValueHandle ivar
instance variable.
Definition class.h:183
struct RClass * cls
return value for mrbc_find_method.
Definition class.h:207
mrbc_sym sym_id
function names symbol ID
Definition class.h:200
uint8_t type
M:OP_DEF or OP_ALIAS, m:mrblib or define_method().
Definition class.h:198
struct RMethod * next
link to next method.
Definition class.h:206
uint8_t c_func
0:IREP, 1:C Func, 2:C Func (built-in)
Definition class.h:199
mrbc_func_t func
to C function.
Definition class.h:203
struct RInstance * instance
Definition boxing_no.h:29
struct RClass * cls
Definition boxing_no.h:28
Virtual Machine.
Definition vm.h:150
mrbc_sym callee_sym_id
Current called method.
Definition vm.h:170
mrbc_sym mrbc_search_symid(const char *str)
Definition symbol.c:262
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
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
static void mrbc_decref(mrbc_value *v)
Definition value.h:561
#define MRBC_INIT_OBJECT_HEADER_DI(t)
Definition value.h:147
void(* mrbc_func_t)(struct VM *vm, struct RObject *v, int argc)
Definition value.h:63
#define MRBC_TT_MAXVAL
Definition value.h:104
static void mrbc_incref(mrbc_value *v)
Definition value.h:546
int16_t mrbc_sym
mruby/c symbol ID
Definition value.h:62
mrbc_vtype
Definition value.h:69
@ MRBC_TT_EMPTY
Definition value.h:80
@ MRBC_TT_OBJECT
General instance.
Definition value.h:95
@ MRBC_TT_MODULE
Module.
Definition value.h:91
@ MRBC_TT_CLASS
Class.
Definition value.h:90
void mrbc_vm_close(mrbc_vm *vm)
Definition vm.c:398
mrbc_vm * mrbc_vm_new(int regs_size)
Definition vm.c:283
int mrbc_vm_run(mrbc_vm *vm)
Definition vm.c:3160
void mrbc_vm_end(mrbc_vm *vm)
Definition vm.c:362
void mrbc_vm_begin(mrbc_vm *vm)
Definition vm.c:336
struct VM mrbc_vm
Virtual Machine.
Global configuration of mruby/c VM's.
#define MAX_REGS_SIZE
Definition vm_config.h:25
#define MRBC_DEBUG
Definition vm_config.h:122