mruby/c VM Source Code master (2026/08/06)
Loading...
Searching...
No Matches
value.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 <stdio.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 *****************************************************/
33//================================================================
39void (* const mrbc_delfunc[])(mrbc_value *) = {
40 0, 0, 0, 0, 0, 0, 0, 0, 0,
41 mrbc_instance_delete, // MRBC_TT_OBJECT = 9,
42 mrbc_proc_delete, // MRBC_TT_PROC = 10,
43 mrbc_array_delete, // MRBC_TT_ARRAY = 11,
44#if MRBC_USE_STRING
45 mrbc_string_delete, // MRBC_TT_STRING = 12,
46#else
47 NULL,
48#endif
49 mrbc_range_delete, // MRBC_TT_RANGE = 13,
50 mrbc_hash_delete, // MRBC_TT_HASH = 14,
51 mrbc_exception_delete, // MRBC_TT_EXCEPTION = 15,
52};
53
54
55/***** Signal catching functions ********************************************/
56/***** Local functions ******************************************************/
57/***** Global functions *****************************************************/
58
59//================================================================
68int mrbc_compare(const mrbc_value *v1, const mrbc_value *v2)
69{
70#if MRBC_USE_FLOAT
71 mrbc_float_t d1, d2;
72#endif
73
74 // if TT_XXX is different
75 if( mrbc_type(*v1) != mrbc_type(*v2) ) {
76#if MRBC_USE_FLOAT
77 // but Numeric?
78 if( mrbc_type(*v1) == MRBC_TT_INTEGER && mrbc_type(*v2) == MRBC_TT_FLOAT ) {
79 d1 = v1->i;
80 d2 = v2->d;
81 goto CMP_FLOAT;
82 }
83 if( mrbc_type(*v1) == MRBC_TT_FLOAT && mrbc_type(*v2) == MRBC_TT_INTEGER ) {
84 d1 = v1->d;
85 d2 = v2->i;
86 goto CMP_FLOAT;
87 }
88#endif
89
90 // leak Empty?
91 if((mrbc_type(*v1) == MRBC_TT_EMPTY && mrbc_type(*v2) == MRBC_TT_NIL) ||
92 (mrbc_type(*v1) == MRBC_TT_NIL && mrbc_type(*v2) == MRBC_TT_EMPTY)) return 0;
93
94 // other case
95 return mrbc_type(*v1) - mrbc_type(*v2);
96 }
97
98 // check value
99 switch( mrbc_type(*v1) ) {
100 case MRBC_TT_NIL:
101 case MRBC_TT_FALSE:
102 case MRBC_TT_TRUE:
103 return 0;
104
105 case MRBC_TT_INTEGER:
106 return mrbc_integer(*v1) - mrbc_integer(*v2);
107
108 case MRBC_TT_SYMBOL: {
109 const char *str1 = mrbc_symid_to_str(mrbc_symbol(*v1));
110 const char *str2 = mrbc_symid_to_str(mrbc_symbol(*v2));
111 int diff = strlen(str1) - strlen(str2);
112 int len = diff < 0 ? strlen(str1) : strlen(str2);
113 int res = memcmp(str1, str2, len);
114 return (res != 0) ? res : diff;
115 }
116
117#if MRBC_USE_FLOAT
118 case MRBC_TT_FLOAT:
119 d1 = mrbc_float(*v1);
120 d2 = mrbc_float(*v2);
121 goto CMP_FLOAT;
122#endif
123
124 case MRBC_TT_CLASS:
125 case MRBC_TT_MODULE:
126 case MRBC_TT_OBJECT:
127 case MRBC_TT_PROC:
128 return (v1->cls > v2->cls) * 2 - (v1->cls != v2->cls);
129
130 case MRBC_TT_ARRAY:
131 return mrbc_array_compare( v1, v2 );
132
133#if MRBC_USE_STRING
134 case MRBC_TT_STRING:
135 return mrbc_string_compare( v1, v2 );
136#endif
137
138 case MRBC_TT_RANGE:
139 return mrbc_range_compare( v1, v2 );
140
141 case MRBC_TT_HASH:
142 return mrbc_hash_compare( v1, v2 );
143
144 default:
145 return 1;
146 }
147
148#if MRBC_USE_FLOAT
149 CMP_FLOAT:
150 return -1 + (d1 == d2) + (d1 > d2)*2; // caution: NaN == NaN is false
151#endif
152}
153
154
155#if defined(MRBC_ALLOC_VMID)
156//================================================================
161void mrbc_clear_vm_id(mrbc_value *v)
162{
163 switch( mrbc_type(*v) ) {
164 case MRBC_TT_OBJECT: mrbc_instance_clear_vm_id(v); break;
165 case MRBC_TT_PROC: mrbc_proc_clear_vm_id(v); break;
166 case MRBC_TT_ARRAY: mrbc_array_clear_vm_id(v); break;
167#if MRBC_USE_STRING
168 case MRBC_TT_STRING: mrbc_string_clear_vm_id(v); break;
169#endif
170 case MRBC_TT_RANGE: mrbc_range_clear_vm_id(v); break;
171 case MRBC_TT_HASH: mrbc_hash_clear_vm_id(v); break;
172
173 default:
174 // Nothing
175 break;
176 }
177}
178#endif
179
180
181//================================================================
188mrbc_int_t mrbc_atoi( const char *s, int base )
189{
190 int ret = 0;
191 int sign = 0;
192
193 REDO:
194 switch( *s ) {
195 case '-':
196 sign = 1;
197 // fall through.
198 case '+':
199 s++;
200 break;
201
202 case ' ':
203 s++;
204 goto REDO;
205 }
206
207 int ch;
208 while( (ch = *s++) != '\0' ) {
209 int n;
210
211 if( 'a' <= ch ) {
212 n = ch - 'a' + 10;
213 } else
214 if( 'A' <= ch ) {
215 n = ch - 'A' + 10;
216 } else
217 if( '0' <= ch && ch <= '9' ) {
218 n = ch - '0';
219 } else {
220 break;
221 }
222 if( n >= base ) break;
223
224 ret = ret * base + n;
225 }
226
227 if( sign ) ret = -ret;
228
229 return ret;
230}
231
232
233//================================================================
241int mrbc_strcpy( char *dest, int destsize, const char *src )
242{
243 int n = destsize;
244 if( n <= 0 ) return 0;
245
246 while( --n != 0 ) {
247 if( (*dest++ = *src++) == 0 ) goto RETURN;
248 }
249 *dest = 0;
250
251 RETURN:
252 return destsize - n - 1;
253}
254
255
256#if MRBC_USE_FLOAT
257//================================================================
264void mrbc_format_float(char *buf, int bufsiz, mrbc_float_t flo)
265{
266 snprintf(buf, bufsiz, "%g", flo);
267 if( strpbrk(buf, ".e") ) return;
268
269 int len = strlen(buf);
270 mrbc_strcpy( buf + len, bufsiz - len, ".0" );
271}
272#endif
273
274
275//================================================================
285mrbc_int_t mrbc_val_i(struct VM *vm, const mrbc_value *val)
286{
287 if( val == NULL ) return 0;
288
289 switch( mrbc_type(*val) ) {
290 case MRBC_TT_INTEGER:
291 return val->i;
292
293#if MRBC_USE_FLOAT
294 case MRBC_TT_FLOAT:
295 return val->d;
296#endif
297
298 default:
299 ;
300 }
301
302 mrbc_raise(vm, MRBC_CLASS(TypeError), "argument must be Integer or Float");
303 return 0;
304}
305
306
307//================================================================
318mrbc_int_t mrbc_val_i2(struct VM *vm, const mrbc_value *val, mrbc_int_t default_value )
319{
320 if( val == NULL || mrbc_type(*val) == MRBC_TT_EMPTY ) return default_value;
321
322 return mrbc_val_i( vm, val );
323}
324
325
326//================================================================
336double mrbc_val_f(struct VM *vm, const mrbc_value *val)
337{
338 if( val == NULL ) return 0;
339
340 switch( mrbc_type(*val) ) {
341 case MRBC_TT_INTEGER:
342 return val->i;
343
344#if MRBC_USE_FLOAT
345 case MRBC_TT_FLOAT:
346 return val->d;
347#endif
348
349 default:
350 ;
351 }
352
353 mrbc_raise(vm, MRBC_CLASS(TypeError), "argument must be Integer or Float");
354 return 0;
355}
356
357
358//================================================================
369double mrbc_val_f2(struct VM *vm, const mrbc_value *val, double default_value )
370{
371 if( val == NULL || mrbc_type(*val) == MRBC_TT_EMPTY ) return default_value;
372
373 return mrbc_val_f( vm, val );
374}
375
376
377//================================================================
387const char * mrbc_val_s(struct VM *vm, const mrbc_value *val)
388{
389 if( val == NULL ) return 0;
390
391 switch( mrbc_type(*val) ) {
392 case MRBC_TT_STRING:
393 return mrbc_string_cstr( val );
394
395 default:
396 ;
397 }
398
399 mrbc_raise(vm, MRBC_CLASS(TypeError), "argument must be String");
400 return 0;
401}
402
403
404//================================================================
415const char * mrbc_val_s2(struct VM *vm, const mrbc_value *val, const char * default_value )
416{
417 if( val == NULL || mrbc_type(*val) == MRBC_TT_EMPTY ) return default_value;
418
419 return mrbc_val_s( vm, val );
420}
421
422
423//================================================================
435mrbc_int_t mrbc_to_i(struct VM *vm, mrbc_value v[], int argc, mrbc_value *val)
436{
437 if( val == NULL ) return 0;
438
439 switch( mrbc_type(*val) ) {
440 case MRBC_TT_EMPTY:
441 mrbc_raise(vm, MRBC_CLASS(TypeError), 0);
442 return 0;
443
444 case MRBC_TT_INTEGER:
445 break;
446
447#if MRBC_USE_FLOAT
448 case MRBC_TT_FLOAT:
449 mrbc_set_integer(val, val->d);
450 break;
451#endif
452
453 default:{
454 mrbc_value ret = mrbc_send( vm, v, argc, val, "to_i", 0 );
455 if( mrbc_israised(vm) ) return 0;
456
457 mrbc_decref( val );
458 *val = ret;
459 } break;
460 }
461
462 return val->i;
463}
464
465
466#if MRBC_USE_FLOAT
467//================================================================
479mrbc_float_t mrbc_to_f(struct VM *vm, mrbc_value v[], int argc, mrbc_value *val)
480{
481 if( val == NULL ) return 0;
482
483 switch( mrbc_type(*val) ) {
484 case MRBC_TT_EMPTY:
485 mrbc_raise(vm, MRBC_CLASS(TypeError), 0);
486 return 0;
487
488 case MRBC_TT_INTEGER:
489 mrbc_set_float(val, val->i);
490 break;
491
492 case MRBC_TT_FLOAT:
493 break;
494
495 default:{
496 mrbc_value ret = mrbc_send( vm, v, argc, val, "to_f", 0 );
497 if( mrbc_israised(vm) ) return 0;
498
499 mrbc_decref( val );
500 *val = ret;
501 } break;
502 }
503
504 return val->d;
505}
506#endif
507
508
509//================================================================
521char * mrbc_to_s(struct VM *vm, mrbc_value v[], int argc, mrbc_value *val)
522{
523 if( val == NULL ) return 0;
524
525 switch( mrbc_type(*val) ) {
526 case MRBC_TT_EMPTY:
527 mrbc_raise(vm, MRBC_CLASS(TypeError), 0);
528 return 0;
529
530 case MRBC_TT_STRING:
531 goto RETURN;
532
533 default:{
534 mrbc_value ret = mrbc_send( vm, v, argc, val, "to_s", 0 );
535 if( mrbc_israised(vm) ) return 0;
536
537 mrbc_decref( val );
538 *val = ret;
539 } break;
540 }
541
542 RETURN:
543 return mrbc_string_cstr( val );
544}
545
546
547//================================================================
559mrbc_value * mrbc_arg(struct VM *vm, mrbc_value v[], int argc, int n)
560{
561 if( argc < n ) {
562 mrbc_raisef(vm, MRBC_CLASS(ArgumentError),
563 "wrong number of arguments (given %d, expected %d)", argc, n);
564 return 0;
565 }
566
567 return &v[n];
568}
569
570
571//================================================================
583mrbc_int_t mrbc_arg_i(struct VM *vm, mrbc_value v[], int argc, int n)
584{
585 if( argc < n ) {
586 mrbc_raisef(vm, MRBC_CLASS(ArgumentError),
587 "wrong number of arguments (given %d, expected %d)", argc, n);
588 return 0;
589 }
590
591 switch( mrbc_type(v[n]) ) {
592 case MRBC_TT_INTEGER:
593 return v[n].i;
594
595#if MRBC_USE_FLOAT
596 case MRBC_TT_FLOAT:
597 return v[n].d;
598#endif
599
600 default:
601 ;
602 }
603
604 mrbc_raisef(vm, MRBC_CLASS(TypeError), "argument %d must be Integer or Float", n);
605 return 0;
606}
607
608
609//================================================================
622mrbc_int_t mrbc_arg_i2(struct VM *vm, mrbc_value v[], int argc, int n, mrbc_int_t default_value)
623{
624 if( argc < n ) return default_value;
625
626 return mrbc_arg_i( vm, v, argc, n );
627}
628
629
630//================================================================
642mrbc_float_t mrbc_arg_f(struct VM *vm, mrbc_value v[], int argc, int n)
643{
644 if( argc < n ) {
645 mrbc_raisef(vm, MRBC_CLASS(ArgumentError),
646 "wrong number of arguments (given %d, expected %d)", argc, n);
647 return 0;
648 }
649
650 switch( mrbc_type(v[n]) ) {
651 case MRBC_TT_INTEGER:
652 return v[n].i;
653
654#if MRBC_USE_FLOAT
655 case MRBC_TT_FLOAT:
656 return v[n].d;
657#endif
658
659 default:
660 ;
661 }
662
663 mrbc_raisef(vm, MRBC_CLASS(TypeError), "argument %d must be Integer or Float", n);
664 return 0;
665}
666
667
668//================================================================
681mrbc_float_t mrbc_arg_f2(struct VM *vm, mrbc_value v[], int argc, int n, mrbc_float_t default_value)
682{
683 if( argc < n ) return default_value;
684
685 return mrbc_arg_f( vm, v, argc, n );
686}
687
688
689//================================================================
701const char * mrbc_arg_s(struct VM *vm, mrbc_value v[], int argc, int n)
702{
703 if( argc < n ) {
704 mrbc_raisef(vm, MRBC_CLASS(ArgumentError),
705 "wrong number of arguments (given %d, expected %d)", argc, n);
706 return 0;
707 }
708
709 switch( mrbc_type(v[n]) ) {
710 case MRBC_TT_STRING:
711 return mrbc_string_cstr( &v[n] );
712
713 default:
714 ;
715 }
716
717 mrbc_raisef(vm, MRBC_CLASS(TypeError), "argument %d must be String", n);
718 return 0;
719}
720
721
722//================================================================
735const char * mrbc_arg_s2(struct VM *vm, mrbc_value v[], int argc, int n, const char *default_value)
736{
737 if( argc < n ) return default_value;
738
739 return mrbc_arg_s( vm, v, argc, n );
740}
741
742
743//================================================================
755int mrbc_arg_b(struct VM *vm, mrbc_value v[], int argc, int n)
756{
757 if( argc < n ) {
758 mrbc_raisef(vm, MRBC_CLASS(ArgumentError),
759 "wrong number of arguments (given %d, expected %d)", argc, n);
760 return 0;
761 }
762
763 switch( mrbc_type(v[n]) ) {
764 case MRBC_TT_FALSE:
765 return 0;
766
767 case MRBC_TT_TRUE:
768 return 1;
769
770 default:
771 ;
772 }
773
774 mrbc_raisef(vm, MRBC_CLASS(TypeError), "argument %d must be true or false", n);
775 return 0;
776}
777
778
779//================================================================
792int mrbc_arg_b2(struct VM *vm, mrbc_value v[], int argc, int n, int default_value)
793{
794 if( argc < n ) return default_value;
795
796 return mrbc_arg_b( vm, v, argc, n );
797}
#define mrbc_symbol(o)
Definition boxing_no.h:62
static void mrbc_set_float(mrbc_value *p, mrbc_float_t d)
Definition boxing_no.h:92
#define mrbc_type(o)
Definition boxing_no.h:57
struct RObject mrbc_value
Value object. Default version.
#define mrbc_float(o)
Definition boxing_no.h:60
#define mrbc_integer(o)
Definition boxing_no.h:58
static void mrbc_set_integer(mrbc_value *p, mrbc_int_t n)
Definition boxing_no.h:85
int mrbc_array_compare(const mrbc_value *v1, const mrbc_value *v2)
Definition c_array.c:432
void mrbc_array_delete(mrbc_value *ary)
Definition c_array.c:105
int mrbc_hash_compare(const mrbc_value *v1, const mrbc_value *v2)
Definition c_hash.c:284
void mrbc_hash_delete(mrbc_value *hash)
Definition c_hash.c:100
void mrbc_proc_delete(mrbc_value *val)
Definition c_proc.c:71
void mrbc_range_delete(mrbc_value *v)
Definition c_range.c:63
int mrbc_range_compare(const mrbc_value *v1, const mrbc_value *v2)
Definition c_range.c:96
void mrbc_string_delete(mrbc_value *str)
Definition c_string.c:107
static char * mrbc_string_cstr(const mrbc_value *v)
Definition c_string.h:122
static int mrbc_string_compare(const mrbc_value *v1, const mrbc_value *v2)
Definition c_string.h:100
void mrbc_instance_delete(mrbc_value *v)
Definition class.c:300
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
#define MRBC_CLASS(cls)
Definition class.h:55
void mrbc_raise(struct VM *vm, struct RClass *exc_cls, const char *msg)
Definition error.c:145
void mrbc_exception_delete(mrbc_value *value)
Definition error.c:128
void mrbc_raisef(struct VM *vm, struct RClass *exc_cls, const char *fstr,...)
Definition error.c:168
#define mrbc_israised(vm)
Definition error.h:38
Include at once the necessary header files.
mrbc_float_t d
Definition boxing_no.h:24
struct RClass * cls
Definition boxing_no.h:28
mrbc_int_t i
Definition boxing_no.h:22
Virtual Machine.
Definition vm.h:150
const char * mrbc_symid_to_str(mrbc_sym sym_id)
Definition symbol.c:239
int mrbc_arg_b2(struct VM *vm, mrbc_value v[], int argc, int n, int default_value)
Definition value.c:792
char * mrbc_to_s(struct VM *vm, mrbc_value v[], int argc, mrbc_value *val)
Definition value.c:521
const char * mrbc_val_s2(struct VM *vm, const mrbc_value *val, const char *default_value)
Definition value.c:415
void(*const mrbc_delfunc[])(mrbc_value *)
Definition value.c:39
mrbc_int_t mrbc_to_i(struct VM *vm, mrbc_value v[], int argc, mrbc_value *val)
Definition value.c:435
mrbc_int_t mrbc_val_i(struct VM *vm, const mrbc_value *val)
Definition value.c:285
const char * mrbc_val_s(struct VM *vm, const mrbc_value *val)
Definition value.c:387
mrbc_value * mrbc_arg(struct VM *vm, mrbc_value v[], int argc, int n)
Definition value.c:559
double mrbc_val_f2(struct VM *vm, const mrbc_value *val, double default_value)
Definition value.c:369
const char * mrbc_arg_s(struct VM *vm, mrbc_value v[], int argc, int n)
Definition value.c:701
int mrbc_compare(const mrbc_value *v1, const mrbc_value *v2)
Definition value.c:68
mrbc_float_t mrbc_arg_f(struct VM *vm, mrbc_value v[], int argc, int n)
Definition value.c:642
mrbc_int_t mrbc_arg_i2(struct VM *vm, mrbc_value v[], int argc, int n, mrbc_int_t default_value)
Definition value.c:622
int mrbc_arg_b(struct VM *vm, mrbc_value v[], int argc, int n)
Definition value.c:755
mrbc_int_t mrbc_val_i2(struct VM *vm, const mrbc_value *val, mrbc_int_t default_value)
Definition value.c:318
mrbc_float_t mrbc_to_f(struct VM *vm, mrbc_value v[], int argc, mrbc_value *val)
Definition value.c:479
int mrbc_strcpy(char *dest, int destsize, const char *src)
Definition value.c:241
mrbc_int_t mrbc_atoi(const char *s, int base)
Definition value.c:188
mrbc_float_t mrbc_arg_f2(struct VM *vm, mrbc_value v[], int argc, int n, mrbc_float_t default_value)
Definition value.c:681
const char * mrbc_arg_s2(struct VM *vm, mrbc_value v[], int argc, int n, const char *default_value)
Definition value.c:735
mrbc_int_t mrbc_arg_i(struct VM *vm, mrbc_value v[], int argc, int n)
Definition value.c:583
void mrbc_format_float(char *buf, int bufsiz, mrbc_float_t flo)
Definition value.c:264
double mrbc_val_f(struct VM *vm, const mrbc_value *val)
Definition value.c:336
float mrbc_float_t
Definition value.h:52
int32_t mrbc_int_t
Definition value.h:47
static void mrbc_decref(mrbc_value *v)
Definition value.h:572
@ MRBC_TT_FALSE
FalseClass.
Definition value.h:82
@ MRBC_TT_SYMBOL
Symbol.
Definition value.h:89
@ MRBC_TT_STRING
String.
Definition value.h:98
@ MRBC_TT_FLOAT
Float.
Definition value.h:88
@ MRBC_TT_INTEGER
Integer.
Definition value.h:86
@ MRBC_TT_EMPTY
Definition value.h:80
@ MRBC_TT_PROC
Proc.
Definition value.h:96
@ MRBC_TT_RANGE
Range.
Definition value.h:99
@ MRBC_TT_OBJECT
General instance.
Definition value.h:95
@ MRBC_TT_ARRAY
Array.
Definition value.h:97
@ MRBC_TT_MODULE
Module.
Definition value.h:91
@ MRBC_TT_TRUE
TrueClass.
Definition value.h:85
@ MRBC_TT_NIL
NilClass.
Definition value.h:81
@ MRBC_TT_HASH
Hash.
Definition value.h:100
@ MRBC_TT_CLASS
Class.
Definition value.h:90
Global configuration of mruby/c VM's.