mbed I/F binding for mruby
Dependents: mruby_mbed_web mirb_mbed
object.c
00001 /* 00002 ** object.c - Object, NilClass, TrueClass, FalseClass class 00003 ** 00004 ** See Copyright Notice in mruby.h 00005 */ 00006 00007 #include "mruby.h" 00008 #include "mruby/class.h" 00009 #include "mruby/numeric.h" 00010 #include "mruby/string.h" 00011 00012 MRB_API mrb_bool 00013 mrb_obj_eq(mrb_state *mrb, mrb_value v1, mrb_value v2) 00014 { 00015 if (mrb_type(v1) != mrb_type(v2)) return FALSE; 00016 switch (mrb_type(v1)) { 00017 case MRB_TT_TRUE: 00018 return TRUE; 00019 00020 case MRB_TT_FALSE: 00021 case MRB_TT_FIXNUM: 00022 return (mrb_fixnum(v1) == mrb_fixnum(v2)); 00023 case MRB_TT_SYMBOL: 00024 return (mrb_symbol(v1) == mrb_symbol(v2)); 00025 00026 case MRB_TT_FLOAT: 00027 return (mrb_float(v1) == mrb_float(v2)); 00028 00029 default: 00030 return (mrb_ptr(v1) == mrb_ptr(v2)); 00031 } 00032 } 00033 00034 MRB_API mrb_bool 00035 mrb_obj_equal(mrb_state *mrb, mrb_value v1, mrb_value v2) 00036 { 00037 /* temporary definition */ 00038 return mrb_obj_eq(mrb, v1, v2); 00039 } 00040 00041 MRB_API mrb_bool 00042 mrb_equal(mrb_state *mrb, mrb_value obj1, mrb_value obj2) 00043 { 00044 mrb_value result; 00045 00046 if (mrb_obj_eq(mrb, obj1, obj2)) return TRUE; 00047 result = mrb_funcall(mrb, obj1, "==", 1, obj2); 00048 if (mrb_test(result)) return TRUE; 00049 return FALSE; 00050 } 00051 00052 /* 00053 * Document-class: NilClass 00054 * 00055 * The class of the singleton object <code>nil</code>. 00056 */ 00057 00058 /* 15.2.4.3.4 */ 00059 /* 00060 * call_seq: 00061 * nil.nil? -> true 00062 * 00063 * Only the object <i>nil</i> responds <code>true</code> to <code>nil?</code>. 00064 */ 00065 00066 static mrb_value 00067 mrb_true(mrb_state *mrb, mrb_value obj) 00068 { 00069 return mrb_true_value(); 00070 } 00071 00072 /* 15.2.4.3.5 */ 00073 /* 00074 * call-seq: 00075 * nil.to_s -> "" 00076 * 00077 * Always returns the empty string. 00078 */ 00079 00080 static mrb_value 00081 nil_to_s(mrb_state *mrb, mrb_value obj) 00082 { 00083 return mrb_str_new(mrb, 0, 0); 00084 } 00085 00086 static mrb_value 00087 nil_inspect(mrb_state *mrb, mrb_value obj) 00088 { 00089 return mrb_str_new_lit(mrb, "nil"); 00090 } 00091 00092 /*********************************************************************** 00093 * Document-class: TrueClass 00094 * 00095 * The global value <code>true</code> is the only instance of class 00096 * <code>TrueClass</code> and represents a logically true value in 00097 * boolean expressions. The class provides operators allowing 00098 * <code>true</code> to be used in logical expressions. 00099 */ 00100 00101 /* 15.2.5.3.1 */ 00102 /* 00103 * call-seq: 00104 * true & obj -> true or false 00105 * 00106 * And---Returns <code>false</code> if <i>obj</i> is 00107 * <code>nil</code> or <code>false</code>, <code>true</code> otherwise. 00108 */ 00109 00110 static mrb_value 00111 true_and(mrb_state *mrb, mrb_value obj) 00112 { 00113 mrb_bool obj2; 00114 00115 mrb_get_args(mrb, "b", &obj2); 00116 00117 return mrb_bool_value(obj2); 00118 } 00119 00120 /* 15.2.5.3.2 */ 00121 /* 00122 * call-seq: 00123 * true ^ obj -> !obj 00124 * 00125 * Exclusive Or---Returns <code>true</code> if <i>obj</i> is 00126 * <code>nil</code> or <code>false</code>, <code>false</code> 00127 * otherwise. 00128 */ 00129 00130 static mrb_value 00131 true_xor(mrb_state *mrb, mrb_value obj) 00132 { 00133 mrb_bool obj2; 00134 00135 mrb_get_args(mrb, "b", &obj2); 00136 return mrb_bool_value(!obj2); 00137 } 00138 00139 /* 15.2.5.3.3 */ 00140 /* 00141 * call-seq: 00142 * true.to_s -> "true" 00143 * 00144 * The string representation of <code>true</code> is "true". 00145 */ 00146 00147 static mrb_value 00148 true_to_s(mrb_state *mrb, mrb_value obj) 00149 { 00150 return mrb_str_new_lit(mrb, "true"); 00151 } 00152 00153 /* 15.2.5.3.4 */ 00154 /* 00155 * call-seq: 00156 * true | obj -> true 00157 * 00158 * Or---Returns <code>true</code>. As <i>anObject</i> is an argument to 00159 * a method call, it is always evaluated; there is no short-circuit 00160 * evaluation in this case. 00161 * 00162 * true | puts("or") 00163 * true || puts("logical or") 00164 * 00165 * <em>produces:</em> 00166 * 00167 * or 00168 */ 00169 00170 static mrb_value 00171 true_or(mrb_state *mrb, mrb_value obj) 00172 { 00173 return mrb_true_value(); 00174 } 00175 00176 /* 00177 * Document-class: FalseClass 00178 * 00179 * The global value <code>false</code> is the only instance of class 00180 * <code>FalseClass</code> and represents a logically false value in 00181 * boolean expressions. The class provides operators allowing 00182 * <code>false</code> to participate correctly in logical expressions. 00183 * 00184 */ 00185 00186 /* 15.2.4.3.1 */ 00187 /* 15.2.6.3.1 */ 00188 /* 00189 * call-seq: 00190 * false & obj -> false 00191 * nil & obj -> false 00192 * 00193 * And---Returns <code>false</code>. <i>obj</i> is always 00194 * evaluated as it is the argument to a method call---there is no 00195 * short-circuit evaluation in this case. 00196 */ 00197 00198 static mrb_value 00199 false_and(mrb_state *mrb, mrb_value obj) 00200 { 00201 return mrb_false_value(); 00202 } 00203 00204 /* 15.2.4.3.2 */ 00205 /* 15.2.6.3.2 */ 00206 /* 00207 * call-seq: 00208 * false ^ obj -> true or false 00209 * nil ^ obj -> true or false 00210 * 00211 * Exclusive Or---If <i>obj</i> is <code>nil</code> or 00212 * <code>false</code>, returns <code>false</code>; otherwise, returns 00213 * <code>true</code>. 00214 * 00215 */ 00216 00217 static mrb_value 00218 false_xor(mrb_state *mrb, mrb_value obj) 00219 { 00220 mrb_bool obj2; 00221 00222 mrb_get_args(mrb, "b", &obj2); 00223 return mrb_bool_value(obj2); 00224 } 00225 00226 /* 15.2.4.3.3 */ 00227 /* 15.2.6.3.4 */ 00228 /* 00229 * call-seq: 00230 * false | obj -> true or false 00231 * nil | obj -> true or false 00232 * 00233 * Or---Returns <code>false</code> if <i>obj</i> is 00234 * <code>nil</code> or <code>false</code>; <code>true</code> otherwise. 00235 */ 00236 00237 static mrb_value 00238 false_or(mrb_state *mrb, mrb_value obj) 00239 { 00240 mrb_bool obj2; 00241 00242 mrb_get_args(mrb, "b", &obj2); 00243 return mrb_bool_value(obj2); 00244 } 00245 00246 /* 15.2.6.3.3 */ 00247 /* 00248 * call-seq: 00249 * false.to_s -> "false" 00250 * 00251 * 'nuf said... 00252 */ 00253 00254 static mrb_value 00255 false_to_s(mrb_state *mrb, mrb_value obj) 00256 { 00257 return mrb_str_new_lit(mrb, "false"); 00258 } 00259 00260 void 00261 mrb_init_object(mrb_state *mrb) 00262 { 00263 struct RClass *n; 00264 struct RClass *t; 00265 struct RClass *f; 00266 00267 n = mrb->nil_class = mrb_define_class(mrb, "NilClass", mrb->object_class); 00268 mrb_undef_class_method(mrb, n, "new"); 00269 mrb_define_method(mrb, n, "&", false_and, MRB_ARGS_REQ(1)); /* 15.2.4.3.1 */ 00270 mrb_define_method(mrb, n, "^", false_xor, MRB_ARGS_REQ(1)); /* 15.2.4.3.2 */ 00271 mrb_define_method(mrb, n, "|", false_or, MRB_ARGS_REQ(1)); /* 15.2.4.3.3 */ 00272 mrb_define_method(mrb, n, "nil?", mrb_true, MRB_ARGS_NONE()); /* 15.2.4.3.4 */ 00273 mrb_define_method(mrb, n, "to_s", nil_to_s, MRB_ARGS_NONE()); /* 15.2.4.3.5 */ 00274 mrb_define_method(mrb, n, "inspect", nil_inspect, MRB_ARGS_NONE()); 00275 00276 t = mrb->true_class = mrb_define_class(mrb, "TrueClass", mrb->object_class); 00277 mrb_undef_class_method(mrb, t, "new"); 00278 mrb_define_method(mrb, t, "&", true_and, MRB_ARGS_REQ(1)); /* 15.2.5.3.1 */ 00279 mrb_define_method(mrb, t, "^", true_xor, MRB_ARGS_REQ(1)); /* 15.2.5.3.2 */ 00280 mrb_define_method(mrb, t, "to_s", true_to_s, MRB_ARGS_NONE()); /* 15.2.5.3.3 */ 00281 mrb_define_method(mrb, t, "|", true_or, MRB_ARGS_REQ(1)); /* 15.2.5.3.4 */ 00282 mrb_define_method(mrb, t, "inspect", true_to_s, MRB_ARGS_NONE()); 00283 00284 f = mrb->false_class = mrb_define_class(mrb, "FalseClass", mrb->object_class); 00285 mrb_undef_class_method(mrb, f, "new"); 00286 mrb_define_method(mrb, f, "&", false_and, MRB_ARGS_REQ(1)); /* 15.2.6.3.1 */ 00287 mrb_define_method(mrb, f, "^", false_xor, MRB_ARGS_REQ(1)); /* 15.2.6.3.2 */ 00288 mrb_define_method(mrb, f, "to_s", false_to_s, MRB_ARGS_NONE()); /* 15.2.6.3.3 */ 00289 mrb_define_method(mrb, f, "|", false_or, MRB_ARGS_REQ(1)); /* 15.2.6.3.4 */ 00290 mrb_define_method(mrb, f, "inspect", false_to_s, MRB_ARGS_NONE()); 00291 } 00292 00293 static mrb_value 00294 inspect_type(mrb_state *mrb, mrb_value val) 00295 { 00296 if (mrb_type(val) == MRB_TT_FALSE || mrb_type(val) == MRB_TT_TRUE) { 00297 return mrb_inspect(mrb, val); 00298 } 00299 else { 00300 return mrb_str_new_cstr(mrb, mrb_obj_classname(mrb, val)); 00301 } 00302 } 00303 00304 static mrb_value 00305 convert_type(mrb_state *mrb, mrb_value val, const char *tname, const char *method, mrb_bool raise) 00306 { 00307 mrb_sym m = 0; 00308 00309 m = mrb_intern_cstr(mrb, method); 00310 if (!mrb_respond_to(mrb, val, m)) { 00311 if (raise) { 00312 mrb_raisef(mrb, E_TYPE_ERROR, "can't convert %S into %S", inspect_type(mrb, val), mrb_str_new_cstr(mrb, tname)); 00313 } 00314 return mrb_nil_value(); 00315 } 00316 return mrb_funcall_argv(mrb, val, m, 0, 0); 00317 } 00318 00319 MRB_API mrb_value 00320 mrb_check_to_integer(mrb_state *mrb, mrb_value val, const char *method) 00321 { 00322 mrb_value v; 00323 00324 if (mrb_fixnum_p(val)) return val; 00325 v = convert_type(mrb, val, "Integer", method, FALSE); 00326 if (mrb_nil_p(v) || !mrb_fixnum_p(v)) { 00327 return mrb_nil_value(); 00328 } 00329 return v; 00330 } 00331 00332 MRB_API mrb_value 00333 mrb_convert_type(mrb_state *mrb, mrb_value val, enum mrb_vtype type, const char *tname, const char *method) 00334 { 00335 mrb_value v; 00336 00337 if (mrb_type(val) == type) return val; 00338 v = convert_type(mrb, val, tname, method, TRUE); 00339 if (mrb_type(v) != type) { 00340 mrb_raisef(mrb, E_TYPE_ERROR, "%S cannot be converted to %S by #%S", val, 00341 mrb_str_new_cstr(mrb, tname), mrb_str_new_cstr(mrb, method)); 00342 } 00343 return v; 00344 } 00345 00346 MRB_API mrb_value 00347 mrb_check_convert_type(mrb_state *mrb, mrb_value val, enum mrb_vtype type, const char *tname, const char *method) 00348 { 00349 mrb_value v; 00350 00351 if (mrb_type(val) == type && type != MRB_TT_DATA) return val; 00352 v = convert_type(mrb, val, tname, method, FALSE); 00353 if (mrb_nil_p(v) || mrb_type(v) != type) return mrb_nil_value(); 00354 return v; 00355 } 00356 00357 static const struct types { 00358 unsigned char type; 00359 const char *name; 00360 } builtin_types[] = { 00361 /* {MRB_TT_NIL, "nil"}, */ 00362 {MRB_TT_FALSE, "false"}, 00363 {MRB_TT_TRUE, "true"}, 00364 {MRB_TT_FIXNUM, "Fixnum"}, 00365 {MRB_TT_SYMBOL, "Symbol"}, /* :symbol */ 00366 {MRB_TT_MODULE, "Module"}, 00367 {MRB_TT_OBJECT, "Object"}, 00368 {MRB_TT_CLASS, "Class"}, 00369 {MRB_TT_ICLASS, "iClass"}, /* internal use: mixed-in module holder */ 00370 {MRB_TT_SCLASS, "SClass"}, 00371 {MRB_TT_PROC, "Proc"}, 00372 {MRB_TT_FLOAT, "Float"}, 00373 {MRB_TT_ARRAY, "Array"}, 00374 {MRB_TT_HASH, "Hash"}, 00375 {MRB_TT_STRING, "String"}, 00376 {MRB_TT_RANGE, "Range"}, 00377 /* {MRB_TT_BIGNUM, "Bignum"}, */ 00378 {MRB_TT_FILE, "File"}, 00379 {MRB_TT_DATA, "Data"}, /* internal use: wrapped C pointers */ 00380 /* {MRB_TT_VARMAP, "Varmap"}, */ /* internal use: dynamic variables */ 00381 /* {MRB_TT_NODE, "Node"}, */ /* internal use: syntax tree node */ 00382 /* {MRB_TT_UNDEF, "undef"}, */ /* internal use: #undef; should not happen */ 00383 {-1, 0} 00384 }; 00385 00386 MRB_API void 00387 mrb_check_type(mrb_state *mrb, mrb_value x, enum mrb_vtype t) 00388 { 00389 const struct types *type = builtin_types; 00390 enum mrb_vtype xt; 00391 00392 xt = mrb_type(x); 00393 if ((xt != t) || (xt == MRB_TT_DATA)) { 00394 while (type->type < MRB_TT_MAXDEFINE) { 00395 if (type->type == t) { 00396 const char *etype; 00397 00398 if (mrb_nil_p(x)) { 00399 etype = "nil"; 00400 } 00401 else if (mrb_fixnum_p(x)) { 00402 etype = "Fixnum"; 00403 } 00404 else if (mrb_type(x) == MRB_TT_SYMBOL) { 00405 etype = "Symbol"; 00406 } 00407 else if (mrb_immediate_p(x)) { 00408 etype = RSTRING_PTR(mrb_obj_as_string(mrb, x)); 00409 } 00410 else { 00411 etype = mrb_obj_classname(mrb, x); 00412 } 00413 mrb_raisef(mrb, E_TYPE_ERROR, "wrong argument type %S (expected %S)", 00414 mrb_str_new_cstr(mrb, etype), mrb_str_new_cstr(mrb, type->name)); 00415 } 00416 type++; 00417 } 00418 mrb_raisef(mrb, E_TYPE_ERROR, "unknown type %S (%S given)", 00419 mrb_fixnum_value(t), mrb_fixnum_value(mrb_type(x))); 00420 } 00421 } 00422 00423 /* 15.3.1.3.46 */ 00424 /* 00425 * call-seq: 00426 * obj.to_s => string 00427 * 00428 * Returns a string representing <i>obj</i>. The default 00429 * <code>to_s</code> prints the object's class and an encoding of the 00430 * object id. As a special case, the top-level object that is the 00431 * initial execution context of Ruby programs returns ``main.'' 00432 */ 00433 00434 MRB_API mrb_value 00435 mrb_any_to_s(mrb_state *mrb, mrb_value obj) 00436 { 00437 mrb_value str = mrb_str_buf_new(mrb, 20); 00438 const char *cname = mrb_obj_classname(mrb, obj); 00439 00440 mrb_str_cat_lit(mrb, str, "#<"); 00441 mrb_str_cat_cstr(mrb, str, cname); 00442 mrb_str_cat_lit(mrb, str, ":"); 00443 mrb_str_concat(mrb, str, mrb_ptr_to_str(mrb, mrb_cptr(obj))); 00444 mrb_str_cat_lit(mrb, str, ">"); 00445 00446 return str; 00447 } 00448 00449 /* 00450 * call-seq: 00451 * obj.is_a?(class) => true or false 00452 * obj.kind_of?(class) => true or false 00453 * 00454 * Returns <code>true</code> if <i>class</i> is the class of 00455 * <i>obj</i>, or if <i>class</i> is one of the superclasses of 00456 * <i>obj</i> or modules included in <i>obj</i>. 00457 * 00458 * module M; end 00459 * class A 00460 * include M 00461 * end 00462 * class B < A; end 00463 * class C < B; end 00464 * b = B.new 00465 * b.instance_of? A #=> false 00466 * b.instance_of? B #=> true 00467 * b.instance_of? C #=> false 00468 * b.instance_of? M #=> false 00469 * b.kind_of? A #=> true 00470 * b.kind_of? B #=> true 00471 * b.kind_of? C #=> false 00472 * b.kind_of? M #=> true 00473 */ 00474 00475 MRB_API mrb_bool 00476 mrb_obj_is_kind_of(mrb_state *mrb, mrb_value obj, struct RClass *c) 00477 { 00478 struct RClass *cl = mrb_class(mrb, obj); 00479 00480 switch (c->tt) { 00481 case MRB_TT_MODULE: 00482 case MRB_TT_CLASS: 00483 case MRB_TT_ICLASS: 00484 break; 00485 00486 default: 00487 mrb_raise(mrb, E_TYPE_ERROR, "class or module required"); 00488 } 00489 00490 while (cl) { 00491 if (cl == c || cl->mt == c->mt) 00492 return TRUE; 00493 cl = cl->super; 00494 } 00495 return FALSE; 00496 } 00497 00498 static mrb_value 00499 mrb_to_integer(mrb_state *mrb, mrb_value val, const char *method) 00500 { 00501 mrb_value v; 00502 00503 if (mrb_fixnum_p(val)) return val; 00504 v = convert_type(mrb, val, "Integer", method, TRUE); 00505 if (!mrb_obj_is_kind_of(mrb, v, mrb->fixnum_class)) { 00506 mrb_value type = inspect_type(mrb, val); 00507 mrb_raisef(mrb, E_TYPE_ERROR, "can't convert %S to Integer (%S#%S gives %S)", 00508 type, type, mrb_str_new_cstr(mrb, method), inspect_type(mrb, v)); 00509 } 00510 return v; 00511 } 00512 00513 MRB_API mrb_value 00514 mrb_to_int(mrb_state *mrb, mrb_value val) 00515 { 00516 return mrb_to_integer(mrb, val, "to_int"); 00517 } 00518 00519 MRB_API mrb_value 00520 mrb_convert_to_integer(mrb_state *mrb, mrb_value val, int base) 00521 { 00522 mrb_value tmp; 00523 00524 if (mrb_nil_p(val)) { 00525 if (base != 0) goto arg_error; 00526 mrb_raise(mrb, E_TYPE_ERROR, "can't convert nil into Integer"); 00527 } 00528 switch (mrb_type(val)) { 00529 case MRB_TT_FLOAT: 00530 if (base != 0) goto arg_error; 00531 if (FIXABLE(mrb_float(val))) { 00532 break; 00533 } 00534 return mrb_flo_to_fixnum(mrb, val); 00535 00536 case MRB_TT_FIXNUM: 00537 if (base != 0) goto arg_error; 00538 return val; 00539 00540 case MRB_TT_STRING: 00541 string_conv: 00542 return mrb_str_to_inum(mrb, val, base, TRUE); 00543 00544 default: 00545 break; 00546 } 00547 if (base != 0) { 00548 tmp = mrb_check_string_type(mrb, val); 00549 if (!mrb_nil_p(tmp)) { 00550 goto string_conv; 00551 } 00552 arg_error: 00553 mrb_raise(mrb, E_ARGUMENT_ERROR, "base specified for non string value"); 00554 } 00555 tmp = convert_type(mrb, val, "Integer", "to_int", FALSE); 00556 if (mrb_nil_p(tmp)) { 00557 return mrb_to_integer(mrb, val, "to_i"); 00558 } 00559 return tmp; 00560 } 00561 00562 MRB_API mrb_value 00563 mrb_Integer(mrb_state *mrb, mrb_value val) 00564 { 00565 return mrb_convert_to_integer(mrb, val, 0); 00566 } 00567 00568 MRB_API mrb_value 00569 mrb_Float(mrb_state *mrb, mrb_value val) 00570 { 00571 if (mrb_nil_p(val)) { 00572 mrb_raise(mrb, E_TYPE_ERROR, "can't convert nil into Float"); 00573 } 00574 switch (mrb_type(val)) { 00575 case MRB_TT_FIXNUM: 00576 return mrb_float_value(mrb, (mrb_float)mrb_fixnum(val)); 00577 00578 case MRB_TT_FLOAT: 00579 return val; 00580 00581 case MRB_TT_STRING: 00582 return mrb_float_value(mrb, mrb_str_to_dbl(mrb, val, TRUE)); 00583 00584 default: 00585 return mrb_convert_type(mrb, val, MRB_TT_FLOAT, "Float", "to_f"); 00586 } 00587 } 00588 00589 MRB_API mrb_value 00590 mrb_inspect(mrb_state *mrb, mrb_value obj) 00591 { 00592 return mrb_obj_as_string(mrb, mrb_funcall(mrb, obj, "inspect", 0)); 00593 } 00594 00595 MRB_API mrb_bool 00596 mrb_eql(mrb_state *mrb, mrb_value obj1, mrb_value obj2) 00597 { 00598 if (mrb_obj_eq(mrb, obj1, obj2)) return TRUE; 00599 return mrb_test(mrb_funcall(mrb, obj1, "eql?", 1, obj2)); 00600 } 00601
Generated on Tue Jul 12 2022 18:00:34 by 1.7.2