mbed I/F binding for mruby

Dependents:   mruby_mbed_web mirb_mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers object.c Source File

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