source: EcnlProtoTool/trunk/mruby-1.2.0/src/object.c@ 270

Last change on this file since 270 was 270, checked in by coas-nagasima, 7 years ago

mruby版ECNLプロトタイピング・ツールを追加

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-csrc
File size: 14.8 KB
Line 
1/*
2** object.c - Object, NilClass, TrueClass, FalseClass class
3**
4** See Copyright Notice in mruby.h
5*/
6
7#include "mruby.h"
8#include "mruby/class.h"
9#include "mruby/numeric.h"
10#include "mruby/string.h"
11
12MRB_API mrb_bool
13mrb_obj_eq(mrb_state *mrb, mrb_value v1, mrb_value v2)
14{
15 if (mrb_type(v1) != mrb_type(v2)) return FALSE;
16 switch (mrb_type(v1)) {
17 case MRB_TT_TRUE:
18 return TRUE;
19
20 case MRB_TT_FALSE:
21 case MRB_TT_FIXNUM:
22 return (mrb_fixnum(v1) == mrb_fixnum(v2));
23 case MRB_TT_SYMBOL:
24 return (mrb_symbol(v1) == mrb_symbol(v2));
25
26 case MRB_TT_FLOAT:
27 return (mrb_float(v1) == mrb_float(v2));
28
29 default:
30 return (mrb_ptr(v1) == mrb_ptr(v2));
31 }
32}
33
34MRB_API mrb_bool
35mrb_obj_equal(mrb_state *mrb, mrb_value v1, mrb_value v2)
36{
37 /* temporary definition */
38 return mrb_obj_eq(mrb, v1, v2);
39}
40
41MRB_API mrb_bool
42mrb_equal(mrb_state *mrb, mrb_value obj1, mrb_value obj2)
43{
44 mrb_value result;
45
46 if (mrb_obj_eq(mrb, obj1, obj2)) return TRUE;
47 result = mrb_funcall(mrb, obj1, "==", 1, obj2);
48 if (mrb_test(result)) return TRUE;
49 return FALSE;
50}
51
52/*
53 * Document-class: NilClass
54 *
55 * The class of the singleton object <code>nil</code>.
56 */
57
58/* 15.2.4.3.4 */
59/*
60 * call_seq:
61 * nil.nil? -> true
62 *
63 * Only the object <i>nil</i> responds <code>true</code> to <code>nil?</code>.
64 */
65
66static mrb_value
67mrb_true(mrb_state *mrb, mrb_value obj)
68{
69 return mrb_true_value();
70}
71
72/* 15.2.4.3.5 */
73/*
74 * call-seq:
75 * nil.to_s -> ""
76 *
77 * Always returns the empty string.
78 */
79
80static mrb_value
81nil_to_s(mrb_state *mrb, mrb_value obj)
82{
83 return mrb_str_new(mrb, 0, 0);
84}
85
86static mrb_value
87nil_inspect(mrb_state *mrb, mrb_value obj)
88{
89 return mrb_str_new_lit(mrb, "nil");
90}
91
92/***********************************************************************
93 * Document-class: TrueClass
94 *
95 * The global value <code>true</code> is the only instance of class
96 * <code>TrueClass</code> and represents a logically true value in
97 * boolean expressions. The class provides operators allowing
98 * <code>true</code> to be used in logical expressions.
99 */
100
101/* 15.2.5.3.1 */
102/*
103 * call-seq:
104 * true & obj -> true or false
105 *
106 * And---Returns <code>false</code> if <i>obj</i> is
107 * <code>nil</code> or <code>false</code>, <code>true</code> otherwise.
108 */
109
110static mrb_value
111true_and(mrb_state *mrb, mrb_value obj)
112{
113 mrb_bool obj2;
114
115 mrb_get_args(mrb, "b", &obj2);
116
117 return mrb_bool_value(obj2);
118}
119
120/* 15.2.5.3.2 */
121/*
122 * call-seq:
123 * true ^ obj -> !obj
124 *
125 * Exclusive Or---Returns <code>true</code> if <i>obj</i> is
126 * <code>nil</code> or <code>false</code>, <code>false</code>
127 * otherwise.
128 */
129
130static mrb_value
131true_xor(mrb_state *mrb, mrb_value obj)
132{
133 mrb_bool obj2;
134
135 mrb_get_args(mrb, "b", &obj2);
136 return mrb_bool_value(!obj2);
137}
138
139/* 15.2.5.3.3 */
140/*
141 * call-seq:
142 * true.to_s -> "true"
143 *
144 * The string representation of <code>true</code> is "true".
145 */
146
147static mrb_value
148true_to_s(mrb_state *mrb, mrb_value obj)
149{
150 return mrb_str_new_lit(mrb, "true");
151}
152
153/* 15.2.5.3.4 */
154/*
155 * call-seq:
156 * true | obj -> true
157 *
158 * Or---Returns <code>true</code>. As <i>anObject</i> is an argument to
159 * a method call, it is always evaluated; there is no short-circuit
160 * evaluation in this case.
161 *
162 * true | puts("or")
163 * true || puts("logical or")
164 *
165 * <em>produces:</em>
166 *
167 * or
168 */
169
170static mrb_value
171true_or(mrb_state *mrb, mrb_value obj)
172{
173 return mrb_true_value();
174}
175
176/*
177 * Document-class: FalseClass
178 *
179 * The global value <code>false</code> is the only instance of class
180 * <code>FalseClass</code> and represents a logically false value in
181 * boolean expressions. The class provides operators allowing
182 * <code>false</code> to participate correctly in logical expressions.
183 *
184 */
185
186/* 15.2.4.3.1 */
187/* 15.2.6.3.1 */
188/*
189 * call-seq:
190 * false & obj -> false
191 * nil & obj -> false
192 *
193 * And---Returns <code>false</code>. <i>obj</i> is always
194 * evaluated as it is the argument to a method call---there is no
195 * short-circuit evaluation in this case.
196 */
197
198static mrb_value
199false_and(mrb_state *mrb, mrb_value obj)
200{
201 return mrb_false_value();
202}
203
204/* 15.2.4.3.2 */
205/* 15.2.6.3.2 */
206/*
207 * call-seq:
208 * false ^ obj -> true or false
209 * nil ^ obj -> true or false
210 *
211 * Exclusive Or---If <i>obj</i> is <code>nil</code> or
212 * <code>false</code>, returns <code>false</code>; otherwise, returns
213 * <code>true</code>.
214 *
215 */
216
217static mrb_value
218false_xor(mrb_state *mrb, mrb_value obj)
219{
220 mrb_bool obj2;
221
222 mrb_get_args(mrb, "b", &obj2);
223 return mrb_bool_value(obj2);
224}
225
226/* 15.2.4.3.3 */
227/* 15.2.6.3.4 */
228/*
229 * call-seq:
230 * false | obj -> true or false
231 * nil | obj -> true or false
232 *
233 * Or---Returns <code>false</code> if <i>obj</i> is
234 * <code>nil</code> or <code>false</code>; <code>true</code> otherwise.
235 */
236
237static mrb_value
238false_or(mrb_state *mrb, mrb_value obj)
239{
240 mrb_bool obj2;
241
242 mrb_get_args(mrb, "b", &obj2);
243 return mrb_bool_value(obj2);
244}
245
246/* 15.2.6.3.3 */
247/*
248 * call-seq:
249 * false.to_s -> "false"
250 *
251 * 'nuf said...
252 */
253
254static mrb_value
255false_to_s(mrb_state *mrb, mrb_value obj)
256{
257 return mrb_str_new_lit(mrb, "false");
258}
259
260void
261mrb_init_object(mrb_state *mrb)
262{
263 struct RClass *n;
264 struct RClass *t;
265 struct RClass *f;
266
267 mrb->nil_class = n = mrb_define_class(mrb, "NilClass", mrb->object_class);
268 mrb_undef_class_method(mrb, n, "new");
269 mrb_define_method(mrb, n, "&", false_and, MRB_ARGS_REQ(1)); /* 15.2.4.3.1 */
270 mrb_define_method(mrb, n, "^", false_xor, MRB_ARGS_REQ(1)); /* 15.2.4.3.2 */
271 mrb_define_method(mrb, n, "|", false_or, MRB_ARGS_REQ(1)); /* 15.2.4.3.3 */
272 mrb_define_method(mrb, n, "nil?", mrb_true, MRB_ARGS_NONE()); /* 15.2.4.3.4 */
273 mrb_define_method(mrb, n, "to_s", nil_to_s, MRB_ARGS_NONE()); /* 15.2.4.3.5 */
274 mrb_define_method(mrb, n, "inspect", nil_inspect, MRB_ARGS_NONE());
275
276 mrb->true_class = t = mrb_define_class(mrb, "TrueClass", mrb->object_class);
277 mrb_undef_class_method(mrb, t, "new");
278 mrb_define_method(mrb, t, "&", true_and, MRB_ARGS_REQ(1)); /* 15.2.5.3.1 */
279 mrb_define_method(mrb, t, "^", true_xor, MRB_ARGS_REQ(1)); /* 15.2.5.3.2 */
280 mrb_define_method(mrb, t, "to_s", true_to_s, MRB_ARGS_NONE()); /* 15.2.5.3.3 */
281 mrb_define_method(mrb, t, "|", true_or, MRB_ARGS_REQ(1)); /* 15.2.5.3.4 */
282 mrb_define_method(mrb, t, "inspect", true_to_s, MRB_ARGS_NONE());
283
284 mrb->false_class = f = mrb_define_class(mrb, "FalseClass", mrb->object_class);
285 mrb_undef_class_method(mrb, f, "new");
286 mrb_define_method(mrb, f, "&", false_and, MRB_ARGS_REQ(1)); /* 15.2.6.3.1 */
287 mrb_define_method(mrb, f, "^", false_xor, MRB_ARGS_REQ(1)); /* 15.2.6.3.2 */
288 mrb_define_method(mrb, f, "to_s", false_to_s, MRB_ARGS_NONE()); /* 15.2.6.3.3 */
289 mrb_define_method(mrb, f, "|", false_or, MRB_ARGS_REQ(1)); /* 15.2.6.3.4 */
290 mrb_define_method(mrb, f, "inspect", false_to_s, MRB_ARGS_NONE());
291}
292
293static mrb_value
294inspect_type(mrb_state *mrb, mrb_value val)
295{
296 if (mrb_type(val) == MRB_TT_FALSE || mrb_type(val) == MRB_TT_TRUE) {
297 return mrb_inspect(mrb, val);
298 }
299 else {
300 return mrb_str_new_cstr(mrb, mrb_obj_classname(mrb, val));
301 }
302}
303
304static mrb_value
305convert_type(mrb_state *mrb, mrb_value val, const char *tname, const char *method, mrb_bool raise)
306{
307 mrb_sym m = 0;
308
309 m = mrb_intern_cstr(mrb, method);
310 if (!mrb_respond_to(mrb, val, m)) {
311 if (raise) {
312 mrb_raisef(mrb, E_TYPE_ERROR, "can't convert %S into %S", inspect_type(mrb, val), mrb_str_new_cstr(mrb, tname));
313 }
314 return mrb_nil_value();
315 }
316 return mrb_funcall_argv(mrb, val, m, 0, 0);
317}
318
319MRB_API mrb_value
320mrb_check_to_integer(mrb_state *mrb, mrb_value val, const char *method)
321{
322 mrb_value v;
323
324 if (mrb_fixnum_p(val)) return val;
325 v = convert_type(mrb, val, "Integer", method, FALSE);
326 if (mrb_nil_p(v) || !mrb_fixnum_p(v)) {
327 return mrb_nil_value();
328 }
329 return v;
330}
331
332MRB_API mrb_value
333mrb_convert_type(mrb_state *mrb, mrb_value val, enum mrb_vtype type, const char *tname, const char *method)
334{
335 mrb_value v;
336
337 if (mrb_type(val) == type) return val;
338 v = convert_type(mrb, val, tname, method, TRUE);
339 if (mrb_type(v) != type) {
340 mrb_raisef(mrb, E_TYPE_ERROR, "%S cannot be converted to %S by #%S", val,
341 mrb_str_new_cstr(mrb, tname), mrb_str_new_cstr(mrb, method));
342 }
343 return v;
344}
345
346MRB_API mrb_value
347mrb_check_convert_type(mrb_state *mrb, mrb_value val, enum mrb_vtype type, const char *tname, const char *method)
348{
349 mrb_value v;
350
351 if (mrb_type(val) == type && type != MRB_TT_DATA) return val;
352 v = convert_type(mrb, val, tname, method, FALSE);
353 if (mrb_nil_p(v) || mrb_type(v) != type) return mrb_nil_value();
354 return v;
355}
356
357static const struct types {
358 unsigned char type;
359 const char *name;
360} builtin_types[] = {
361/* {MRB_TT_NIL, "nil"}, */
362 {MRB_TT_FALSE, "false"},
363 {MRB_TT_TRUE, "true"},
364 {MRB_TT_FIXNUM, "Fixnum"},
365 {MRB_TT_SYMBOL, "Symbol"}, /* :symbol */
366 {MRB_TT_MODULE, "Module"},
367 {MRB_TT_OBJECT, "Object"},
368 {MRB_TT_CLASS, "Class"},
369 {MRB_TT_ICLASS, "iClass"}, /* internal use: mixed-in module holder */
370 {MRB_TT_SCLASS, "SClass"},
371 {MRB_TT_PROC, "Proc"},
372 {MRB_TT_FLOAT, "Float"},
373 {MRB_TT_ARRAY, "Array"},
374 {MRB_TT_HASH, "Hash"},
375 {MRB_TT_STRING, "String"},
376 {MRB_TT_RANGE, "Range"},
377/* {MRB_TT_BIGNUM, "Bignum"}, */
378 {MRB_TT_FILE, "File"},
379 {MRB_TT_DATA, "Data"}, /* internal use: wrapped C pointers */
380/* {MRB_TT_VARMAP, "Varmap"}, */ /* internal use: dynamic variables */
381/* {MRB_TT_NODE, "Node"}, */ /* internal use: syntax tree node */
382/* {MRB_TT_UNDEF, "undef"}, */ /* internal use: #undef; should not happen */
383 {-1, 0}
384};
385
386MRB_API void
387mrb_check_type(mrb_state *mrb, mrb_value x, enum mrb_vtype t)
388{
389 const struct types *type = builtin_types;
390 enum mrb_vtype xt;
391
392 xt = mrb_type(x);
393 if ((xt != t) || (xt == MRB_TT_DATA)) {
394 while (type->type < MRB_TT_MAXDEFINE) {
395 if (type->type == t) {
396 const char *etype;
397
398 if (mrb_nil_p(x)) {
399 etype = "nil";
400 }
401 else if (mrb_fixnum_p(x)) {
402 etype = "Fixnum";
403 }
404 else if (mrb_type(x) == MRB_TT_SYMBOL) {
405 etype = "Symbol";
406 }
407 else if (mrb_immediate_p(x)) {
408 etype = RSTRING_PTR(mrb_obj_as_string(mrb, x));
409 }
410 else {
411 etype = mrb_obj_classname(mrb, x);
412 }
413 mrb_raisef(mrb, E_TYPE_ERROR, "wrong argument type %S (expected %S)",
414 mrb_str_new_cstr(mrb, etype), mrb_str_new_cstr(mrb, type->name));
415 }
416 type++;
417 }
418 mrb_raisef(mrb, E_TYPE_ERROR, "unknown type %S (%S given)",
419 mrb_fixnum_value(t), mrb_fixnum_value(mrb_type(x)));
420 }
421}
422
423/* 15.3.1.3.46 */
424/*
425 * call-seq:
426 * obj.to_s => string
427 *
428 * Returns a string representing <i>obj</i>. The default
429 * <code>to_s</code> prints the object's class and an encoding of the
430 * object id. As a special case, the top-level object that is the
431 * initial execution context of Ruby programs returns "main."
432 */
433
434MRB_API mrb_value
435mrb_any_to_s(mrb_state *mrb, mrb_value obj)
436{
437 mrb_value str = mrb_str_buf_new(mrb, 20);
438 const char *cname = mrb_obj_classname(mrb, obj);
439
440 mrb_str_cat_lit(mrb, str, "#<");
441 mrb_str_cat_cstr(mrb, str, cname);
442 mrb_str_cat_lit(mrb, str, ":");
443 mrb_str_concat(mrb, str, mrb_ptr_to_str(mrb, mrb_cptr(obj)));
444 mrb_str_cat_lit(mrb, str, ">");
445
446 return str;
447}
448
449/*
450 * call-seq:
451 * obj.is_a?(class) => true or false
452 * obj.kind_of?(class) => true or false
453 *
454 * Returns <code>true</code> if <i>class</i> is the class of
455 * <i>obj</i>, or if <i>class</i> is one of the superclasses of
456 * <i>obj</i> or modules included in <i>obj</i>.
457 *
458 * module M; end
459 * class A
460 * include M
461 * end
462 * class B < A; end
463 * class C < B; end
464 * b = B.new
465 * b.instance_of? A #=> false
466 * b.instance_of? B #=> true
467 * b.instance_of? C #=> false
468 * b.instance_of? M #=> false
469 * b.kind_of? A #=> true
470 * b.kind_of? B #=> true
471 * b.kind_of? C #=> false
472 * b.kind_of? M #=> true
473 */
474
475MRB_API mrb_bool
476mrb_obj_is_kind_of(mrb_state *mrb, mrb_value obj, struct RClass *c)
477{
478 struct RClass *cl = mrb_class(mrb, obj);
479
480 switch (c->tt) {
481 case MRB_TT_MODULE:
482 case MRB_TT_CLASS:
483 case MRB_TT_ICLASS:
484 break;
485
486 default:
487 mrb_raise(mrb, E_TYPE_ERROR, "class or module required");
488 }
489
490 MRB_CLASS_ORIGIN(c);
491 while (cl) {
492 if (cl == c || cl->mt == c->mt)
493 return TRUE;
494 cl = cl->super;
495 }
496 return FALSE;
497}
498
499static mrb_value
500mrb_to_integer(mrb_state *mrb, mrb_value val, const char *method)
501{
502 mrb_value v;
503
504 if (mrb_fixnum_p(val)) return val;
505 v = convert_type(mrb, val, "Integer", method, TRUE);
506 if (!mrb_obj_is_kind_of(mrb, v, mrb->fixnum_class)) {
507 mrb_value type = inspect_type(mrb, val);
508 mrb_raisef(mrb, E_TYPE_ERROR, "can't convert %S to Integer (%S#%S gives %S)",
509 type, type, mrb_str_new_cstr(mrb, method), inspect_type(mrb, v));
510 }
511 return v;
512}
513
514MRB_API mrb_value
515mrb_to_int(mrb_state *mrb, mrb_value val)
516{
517 return mrb_to_integer(mrb, val, "to_int");
518}
519
520MRB_API mrb_value
521mrb_convert_to_integer(mrb_state *mrb, mrb_value val, int base)
522{
523 mrb_value tmp;
524
525 if (mrb_nil_p(val)) {
526 if (base != 0) goto arg_error;
527 mrb_raise(mrb, E_TYPE_ERROR, "can't convert nil into Integer");
528 }
529 switch (mrb_type(val)) {
530 case MRB_TT_FLOAT:
531 if (base != 0) goto arg_error;
532 if (FIXABLE(mrb_float(val))) {
533 break;
534 }
535 return mrb_flo_to_fixnum(mrb, val);
536
537 case MRB_TT_FIXNUM:
538 if (base != 0) goto arg_error;
539 return val;
540
541 case MRB_TT_STRING:
542 string_conv:
543 return mrb_str_to_inum(mrb, val, base, TRUE);
544
545 default:
546 break;
547 }
548 if (base != 0) {
549 tmp = mrb_check_string_type(mrb, val);
550 if (!mrb_nil_p(tmp)) {
551 goto string_conv;
552 }
553arg_error:
554 mrb_raise(mrb, E_ARGUMENT_ERROR, "base specified for non string value");
555 }
556 tmp = convert_type(mrb, val, "Integer", "to_int", FALSE);
557 if (mrb_nil_p(tmp)) {
558 return mrb_to_integer(mrb, val, "to_i");
559 }
560 return tmp;
561}
562
563MRB_API mrb_value
564mrb_Integer(mrb_state *mrb, mrb_value val)
565{
566 return mrb_convert_to_integer(mrb, val, 0);
567}
568
569MRB_API mrb_value
570mrb_Float(mrb_state *mrb, mrb_value val)
571{
572 if (mrb_nil_p(val)) {
573 mrb_raise(mrb, E_TYPE_ERROR, "can't convert nil into Float");
574 }
575 switch (mrb_type(val)) {
576 case MRB_TT_FIXNUM:
577 return mrb_float_value(mrb, (mrb_float)mrb_fixnum(val));
578
579 case MRB_TT_FLOAT:
580 return val;
581
582 case MRB_TT_STRING:
583 return mrb_float_value(mrb, mrb_str_to_dbl(mrb, val, TRUE));
584
585 default:
586 return mrb_convert_type(mrb, val, MRB_TT_FLOAT, "Float", "to_f");
587 }
588}
589
590MRB_API mrb_value
591mrb_inspect(mrb_state *mrb, mrb_value obj)
592{
593 return mrb_obj_as_string(mrb, mrb_funcall(mrb, obj, "inspect", 0));
594}
595
596MRB_API mrb_bool
597mrb_eql(mrb_state *mrb, mrb_value obj1, mrb_value obj2)
598{
599 if (mrb_obj_eq(mrb, obj1, obj2)) return TRUE;
600 return mrb_test(mrb_funcall(mrb, obj1, "eql?", 1, obj2));
601}
Note: See TracBrowser for help on using the repository browser.