mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
2f8d3bdc21
modifying buffer is shared. * array.c (ary_make_shared): make an internal buffer of an array to be shared. * array.c (rb_ary_shift): avoid sliding an internal buffer by using shared buffer. * array.c (rb_ary_subseq): avoid copying the buffer. * parse.y (gettable): should freeze __LINE__ string. * io.c (rb_io_puts): old behavoir restored. rationale: a) if you want to call to_s for arrays, you can just call print a, "\n". b) to_s wastes memory if array (and sum of its contents) is huge. c) now any object that has to_ary is treated as an array, using rb_check_convert_type(). * hash.c (rb_hash_initialize): now accepts a block to calculate the default value. [new] * hash.c (rb_hash_aref): call "default" method to get the value corrensponding to the non existing key. * hash.c (rb_hash_default): get the default value based on the block given to 'new'. Now it takes an optinal "key" argument. "default" became the method to get the value for non existing key. Users may override "default" method to change the hash behavior. * hash.c (rb_hash_set_default): clear the flag if a block is given to 'new' * object.c (Init_Object): undef Data.allocate, left Data.new. * ext/curses/curses.c (window_scrollok): use RTEST(). * ext/curses/curses.c (window_idlok): ditto. * ext/curses/curses.c (window_keypad): ditto. * ext/curses/curses.c (window_idlok): idlok() may return void on some platforms; so don't use return value. * ext/curses/curses.c (window_scrollok): ditto for consistency. * ext/curses/curses.c: replace FIX2INT() by typechecking NUM2INT(). * parse.y (str_extend): should not process immature #$x and #@x interpolation, e.g #@#@ etc. * enum.c (enum_sort_by): sort_by does not have to be stable always. * enum.c (enum_sort_by): call qsort directly to gain performance. * util.c (ruby_qsort): ruby_qsort(qs6) is now native thread safe. * error.c (rb_sys_fail): it must be a bug if it's called when errno == 0. * regex.c (WC2MBC1ST): should not pass through > 0x80 number in UTF-8. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1896 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
1322 lines
29 KiB
C
1322 lines
29 KiB
C
/**********************************************************************
|
|
|
|
object.c -
|
|
|
|
$Author$
|
|
$Date$
|
|
created at: Thu Jul 15 12:01:24 JST 1993
|
|
|
|
Copyright (C) 1993-2001 Yukihiro Matsumoto
|
|
Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
|
|
Copyright (C) 2000 Information-technology Promotion Agency, Japan
|
|
|
|
**********************************************************************/
|
|
|
|
#include "ruby.h"
|
|
#include "st.h"
|
|
#include <stdio.h>
|
|
#include <errno.h>
|
|
#include <ctype.h>
|
|
|
|
VALUE rb_mKernel;
|
|
VALUE rb_cObject;
|
|
VALUE rb_cModule;
|
|
VALUE rb_cClass;
|
|
VALUE rb_cData;
|
|
|
|
VALUE rb_cNilClass;
|
|
VALUE rb_cTrueClass;
|
|
VALUE rb_cFalseClass;
|
|
VALUE rb_cSymbol;
|
|
|
|
static ID eq, eql;
|
|
static ID inspect;
|
|
static ID clone;
|
|
static ID alloc;
|
|
|
|
VALUE
|
|
rb_equal(obj1, obj2)
|
|
VALUE obj1, obj2;
|
|
{
|
|
VALUE result;
|
|
|
|
if (obj1 == obj2) return Qtrue;
|
|
result = rb_funcall(obj1, eq, 1, obj2);
|
|
if (RTEST(result)) return Qtrue;
|
|
return Qfalse;
|
|
}
|
|
|
|
int
|
|
rb_eql(obj1, obj2)
|
|
VALUE obj1, obj2;
|
|
{
|
|
return RTEST(rb_funcall(obj1, eql, 1, obj2));
|
|
}
|
|
|
|
static VALUE
|
|
rb_obj_equal(obj1, obj2)
|
|
VALUE obj1, obj2;
|
|
{
|
|
if (obj1 == obj2) return Qtrue;
|
|
return Qfalse;
|
|
}
|
|
|
|
VALUE
|
|
rb_obj_id(obj)
|
|
VALUE obj;
|
|
{
|
|
if (SPECIAL_CONST_P(obj)) {
|
|
return INT2NUM((long)obj);
|
|
}
|
|
return (VALUE)((long)obj|FIXNUM_FLAG);
|
|
}
|
|
|
|
VALUE
|
|
rb_class_real(cl)
|
|
VALUE cl;
|
|
{
|
|
while (FL_TEST(cl, FL_SINGLETON) || TYPE(cl) == T_ICLASS) {
|
|
cl = RCLASS(cl)->super;
|
|
}
|
|
return cl;
|
|
}
|
|
|
|
VALUE
|
|
rb_obj_class(obj)
|
|
VALUE obj;
|
|
{
|
|
return rb_class_real(CLASS_OF(obj));
|
|
}
|
|
|
|
VALUE
|
|
rb_obj_clone(obj)
|
|
VALUE obj;
|
|
{
|
|
VALUE clone;
|
|
|
|
if (rb_special_const_p(obj)) {
|
|
rb_raise(rb_eTypeError, "can't clone %s", rb_class2name(CLASS_OF(obj)));
|
|
}
|
|
clone = rb_obj_alloc(RBASIC(obj)->klass);
|
|
CLONESETUP(clone,obj);
|
|
if (TYPE(clone) == T_OBJECT && ROBJECT(obj)->iv_tbl) {
|
|
ROBJECT(clone)->iv_tbl = st_copy(ROBJECT(obj)->iv_tbl);
|
|
}
|
|
|
|
return clone;
|
|
}
|
|
|
|
VALUE
|
|
rb_obj_dup(obj)
|
|
VALUE obj;
|
|
{
|
|
VALUE dup;
|
|
|
|
dup = rb_funcall(obj, clone, 0, 0);
|
|
if (TYPE(dup) != TYPE(obj)) {
|
|
rb_raise(rb_eTypeError, "dupulicated object must be same type");
|
|
}
|
|
if (!SPECIAL_CONST_P(dup)) {
|
|
OBJSETUP(dup, rb_obj_class(obj), BUILTIN_TYPE(obj));
|
|
OBJ_INFECT(dup, obj);
|
|
if (FL_TEST(obj, FL_EXIVAR)) {
|
|
FL_SET(dup, FL_EXIVAR);
|
|
}
|
|
}
|
|
return dup;
|
|
}
|
|
|
|
static VALUE
|
|
rb_any_to_a(obj)
|
|
VALUE obj;
|
|
{
|
|
return rb_ary_new3(1, obj);
|
|
}
|
|
|
|
VALUE
|
|
rb_any_to_s(obj)
|
|
VALUE obj;
|
|
{
|
|
char *cname = rb_class2name(CLASS_OF(obj));
|
|
VALUE str;
|
|
|
|
str = rb_str_new(0, strlen(cname)+6+16+1); /* 6:tags 16:addr 1:nul */
|
|
sprintf(RSTRING(str)->ptr, "#<%s:0x%lx>", cname, obj);
|
|
RSTRING(str)->len = strlen(RSTRING(str)->ptr);
|
|
if (OBJ_TAINTED(obj)) OBJ_TAINT(str);
|
|
|
|
return str;
|
|
}
|
|
|
|
VALUE
|
|
rb_inspect(obj)
|
|
VALUE obj;
|
|
{
|
|
return rb_obj_as_string(rb_funcall(obj, inspect, 0, 0));
|
|
}
|
|
|
|
static int
|
|
inspect_i(id, value, str)
|
|
ID id;
|
|
VALUE value;
|
|
VALUE str;
|
|
{
|
|
VALUE str2;
|
|
char *ivname;
|
|
|
|
/* need not to show internal data */
|
|
if (CLASS_OF(value) == 0) return ST_CONTINUE;
|
|
if (!rb_is_instance_id(id)) return ST_CONTINUE;
|
|
if (RSTRING(str)->ptr[0] == '-') { /* first element */
|
|
RSTRING(str)->ptr[0] = '#';
|
|
rb_str_cat2(str, " ");
|
|
}
|
|
else {
|
|
rb_str_cat2(str, ", ");
|
|
}
|
|
ivname = rb_id2name(id);
|
|
rb_str_cat2(str, ivname);
|
|
rb_str_cat2(str, "=");
|
|
str2 = rb_inspect(value);
|
|
rb_str_append(str, str2);
|
|
OBJ_INFECT(str, str2);
|
|
|
|
return ST_CONTINUE;
|
|
}
|
|
|
|
static VALUE
|
|
inspect_obj(obj, str)
|
|
VALUE obj, str;
|
|
{
|
|
st_foreach(ROBJECT(obj)->iv_tbl, inspect_i, str);
|
|
rb_str_cat2(str, ">");
|
|
RSTRING(str)->ptr[0] = '#';
|
|
OBJ_INFECT(str, obj);
|
|
|
|
return str;
|
|
}
|
|
|
|
static VALUE
|
|
rb_obj_inspect(obj)
|
|
VALUE obj;
|
|
{
|
|
if (TYPE(obj) == T_OBJECT
|
|
&& ROBJECT(obj)->iv_tbl
|
|
&& ROBJECT(obj)->iv_tbl->num_entries > 0) {
|
|
VALUE str;
|
|
char *c;
|
|
|
|
c = rb_class2name(CLASS_OF(obj));
|
|
if (rb_inspecting_p(obj)) {
|
|
str = rb_str_new(0, strlen(c)+10+16+1); /* 10:tags 16:addr 1:nul */
|
|
sprintf(RSTRING(str)->ptr, "#<%s:0x%lx ...>", c, obj);
|
|
RSTRING(str)->len = strlen(RSTRING(str)->ptr);
|
|
return str;
|
|
}
|
|
str = rb_str_new(0, strlen(c)+6+16+1); /* 6:tags 16:addr 1:nul */
|
|
sprintf(RSTRING(str)->ptr, "-<%s:0x%lx", c, obj);
|
|
RSTRING(str)->len = strlen(RSTRING(str)->ptr);
|
|
return rb_protect_inspect(inspect_obj, obj, str);
|
|
}
|
|
return rb_funcall(obj, rb_intern("to_s"), 0, 0);
|
|
}
|
|
|
|
VALUE
|
|
rb_obj_is_instance_of(obj, c)
|
|
VALUE obj, c;
|
|
{
|
|
switch (TYPE(c)) {
|
|
case T_MODULE:
|
|
case T_CLASS:
|
|
case T_ICLASS:
|
|
break;
|
|
default:
|
|
rb_raise(rb_eTypeError, "class or module required");
|
|
}
|
|
|
|
if (rb_obj_class(obj) == c) return Qtrue;
|
|
return Qfalse;
|
|
}
|
|
|
|
VALUE
|
|
rb_obj_is_kind_of(obj, c)
|
|
VALUE obj, c;
|
|
{
|
|
VALUE cl = CLASS_OF(obj);
|
|
|
|
switch (TYPE(c)) {
|
|
case T_MODULE:
|
|
case T_CLASS:
|
|
case T_ICLASS:
|
|
break;
|
|
|
|
default:
|
|
rb_raise(rb_eTypeError, "class or module required");
|
|
}
|
|
|
|
while (cl) {
|
|
if (cl == c || RCLASS(cl)->m_tbl == RCLASS(c)->m_tbl)
|
|
return Qtrue;
|
|
cl = RCLASS(cl)->super;
|
|
}
|
|
return Qfalse;
|
|
}
|
|
|
|
static VALUE
|
|
rb_obj_dummy()
|
|
{
|
|
return Qnil;
|
|
}
|
|
|
|
VALUE
|
|
rb_obj_tainted(obj)
|
|
VALUE obj;
|
|
{
|
|
if (OBJ_TAINTED(obj))
|
|
return Qtrue;
|
|
return Qfalse;
|
|
}
|
|
|
|
VALUE
|
|
rb_obj_taint(obj)
|
|
VALUE obj;
|
|
{
|
|
rb_secure(4);
|
|
if (!OBJ_TAINTED(obj)) {
|
|
if (OBJ_FROZEN(obj)) {
|
|
rb_error_frozen("object");
|
|
}
|
|
OBJ_TAINT(obj);
|
|
}
|
|
return obj;
|
|
}
|
|
|
|
VALUE
|
|
rb_obj_untaint(obj)
|
|
VALUE obj;
|
|
{
|
|
rb_secure(3);
|
|
if (OBJ_TAINTED(obj)) {
|
|
if (OBJ_FROZEN(obj)) {
|
|
rb_error_frozen("object");
|
|
}
|
|
FL_UNSET(obj, FL_TAINT);
|
|
}
|
|
return obj;
|
|
}
|
|
|
|
VALUE
|
|
rb_obj_freeze(obj)
|
|
VALUE obj;
|
|
{
|
|
if (!OBJ_FROZEN(obj)) {
|
|
if (rb_safe_level() >= 4 && !OBJ_TAINTED(obj)) {
|
|
rb_raise(rb_eSecurityError, "Insecure: can't freeze object");
|
|
}
|
|
OBJ_FREEZE(obj);
|
|
}
|
|
return obj;
|
|
}
|
|
|
|
static VALUE
|
|
rb_obj_frozen_p(obj)
|
|
VALUE obj;
|
|
{
|
|
if (OBJ_FROZEN(obj)) return Qtrue;
|
|
return Qfalse;
|
|
}
|
|
|
|
static VALUE
|
|
nil_to_i(obj)
|
|
VALUE obj;
|
|
{
|
|
return INT2FIX(0);
|
|
}
|
|
|
|
static VALUE
|
|
nil_to_s(obj)
|
|
VALUE obj;
|
|
{
|
|
return rb_str_new2("");
|
|
}
|
|
|
|
static VALUE
|
|
nil_to_a(obj)
|
|
VALUE obj;
|
|
{
|
|
return rb_ary_new2(0);
|
|
}
|
|
|
|
static VALUE
|
|
nil_inspect(obj)
|
|
VALUE obj;
|
|
{
|
|
return rb_str_new2("nil");
|
|
}
|
|
|
|
#ifdef NIL_PLUS
|
|
static VALUE
|
|
nil_plus(x, y)
|
|
VALUE x, y;
|
|
{
|
|
switch (TYPE(y)) {
|
|
case T_NIL:
|
|
case T_FIXNUM:
|
|
case T_FLOAT:
|
|
case T_BIGNUM:
|
|
case T_STRING:
|
|
case T_ARRAY:
|
|
return y;
|
|
default:
|
|
rb_raise(rb_eTypeError, "tried to add %s(%s) to nil",
|
|
RSTRING(rb_inspect(y))->ptr,
|
|
rb_class2name(CLASS_OF(y)));
|
|
}
|
|
/* not reached */
|
|
}
|
|
#endif
|
|
|
|
static VALUE
|
|
main_to_s(obj)
|
|
VALUE obj;
|
|
{
|
|
return rb_str_new2("main");
|
|
}
|
|
|
|
static VALUE
|
|
true_to_s(obj)
|
|
VALUE obj;
|
|
{
|
|
return rb_str_new2("true");
|
|
}
|
|
|
|
static VALUE
|
|
true_and(obj, obj2)
|
|
VALUE obj, obj2;
|
|
{
|
|
return RTEST(obj2)?Qtrue:Qfalse;
|
|
}
|
|
|
|
static VALUE
|
|
true_or(obj, obj2)
|
|
VALUE obj, obj2;
|
|
{
|
|
return Qtrue;
|
|
}
|
|
|
|
static VALUE
|
|
true_xor(obj, obj2)
|
|
VALUE obj, obj2;
|
|
{
|
|
return RTEST(obj2)?Qfalse:Qtrue;
|
|
}
|
|
|
|
static VALUE
|
|
false_to_s(obj)
|
|
VALUE obj;
|
|
{
|
|
return rb_str_new2("false");
|
|
}
|
|
|
|
static VALUE
|
|
false_and(obj, obj2)
|
|
VALUE obj, obj2;
|
|
{
|
|
return Qfalse;
|
|
}
|
|
|
|
static VALUE
|
|
false_or(obj, obj2)
|
|
VALUE obj, obj2;
|
|
{
|
|
return RTEST(obj2)?Qtrue:Qfalse;
|
|
}
|
|
|
|
static VALUE
|
|
false_xor(obj, obj2)
|
|
VALUE obj, obj2;
|
|
{
|
|
return RTEST(obj2)?Qtrue:Qfalse;
|
|
}
|
|
|
|
static VALUE
|
|
rb_true(obj)
|
|
VALUE obj;
|
|
{
|
|
return Qtrue;
|
|
}
|
|
|
|
static VALUE
|
|
rb_false(obj)
|
|
VALUE obj;
|
|
{
|
|
return Qfalse;
|
|
}
|
|
|
|
static VALUE
|
|
sym_to_i(sym)
|
|
VALUE sym;
|
|
{
|
|
ID id = SYM2ID(sym);
|
|
|
|
return INT2FIX(id);
|
|
}
|
|
|
|
static VALUE
|
|
sym_inspect(sym)
|
|
VALUE sym;
|
|
{
|
|
VALUE str;
|
|
char *name;
|
|
|
|
name = rb_id2name(SYM2ID(sym));
|
|
str = rb_str_new(0, strlen(name)+1);
|
|
RSTRING(str)->ptr[0] = ':';
|
|
strcpy(RSTRING(str)->ptr+1, name);
|
|
return str;
|
|
}
|
|
|
|
static VALUE
|
|
sym_to_s(sym)
|
|
VALUE sym;
|
|
{
|
|
return rb_str_new2(rb_id2name(SYM2ID(sym)));
|
|
}
|
|
|
|
static VALUE
|
|
sym_intern(sym)
|
|
VALUE sym;
|
|
{
|
|
return sym;
|
|
}
|
|
|
|
static VALUE
|
|
rb_mod_to_s(klass)
|
|
VALUE klass;
|
|
|
|
{
|
|
if (FL_TEST(klass, FL_SINGLETON)) {
|
|
VALUE s = rb_str_new2("#<");
|
|
|
|
rb_str_cat2(s, "Class:");
|
|
rb_str_cat2(s, rb_class2name(klass));
|
|
rb_str_cat2(s, ">");
|
|
|
|
return s;
|
|
}
|
|
return rb_str_dup(rb_class_path(klass));
|
|
}
|
|
|
|
static VALUE
|
|
rb_mod_eqq(mod, arg)
|
|
VALUE mod, arg;
|
|
{
|
|
return rb_obj_is_kind_of(arg, mod);
|
|
}
|
|
|
|
static VALUE
|
|
rb_mod_le(mod, arg)
|
|
VALUE mod, arg;
|
|
{
|
|
switch (TYPE(arg)) {
|
|
case T_MODULE:
|
|
case T_CLASS:
|
|
break;
|
|
default:
|
|
rb_raise(rb_eTypeError, "compared with non class/module");
|
|
}
|
|
|
|
while (mod) {
|
|
if (RCLASS(mod)->m_tbl == RCLASS(arg)->m_tbl)
|
|
return Qtrue;
|
|
mod = RCLASS(mod)->super;
|
|
}
|
|
|
|
return Qfalse;
|
|
}
|
|
|
|
static VALUE
|
|
rb_mod_lt(mod, arg)
|
|
VALUE mod, arg;
|
|
{
|
|
if (mod == arg) return Qfalse;
|
|
return rb_mod_le(mod, arg);
|
|
}
|
|
|
|
static VALUE
|
|
rb_mod_ge(mod, arg)
|
|
VALUE mod, arg;
|
|
{
|
|
switch (TYPE(arg)) {
|
|
case T_MODULE:
|
|
case T_CLASS:
|
|
break;
|
|
default:
|
|
rb_raise(rb_eTypeError, "compared with non class/module");
|
|
}
|
|
|
|
return rb_mod_le(arg, mod);
|
|
}
|
|
|
|
static VALUE
|
|
rb_mod_gt(mod, arg)
|
|
VALUE mod, arg;
|
|
{
|
|
if (mod == arg) return Qfalse;
|
|
return rb_mod_ge(mod, arg);
|
|
}
|
|
|
|
static VALUE
|
|
rb_mod_cmp(mod, arg)
|
|
VALUE mod, arg;
|
|
{
|
|
if (mod == arg) return INT2FIX(0);
|
|
|
|
switch (TYPE(arg)) {
|
|
case T_MODULE:
|
|
case T_CLASS:
|
|
break;
|
|
default:
|
|
rb_raise(rb_eTypeError, "<=> requires Class or Module (%s given)",
|
|
rb_class2name(CLASS_OF(arg)));
|
|
break;
|
|
}
|
|
|
|
if (rb_mod_le(mod, arg)) {
|
|
return INT2FIX(-1);
|
|
}
|
|
return INT2FIX(1);
|
|
}
|
|
|
|
static VALUE
|
|
rb_mod_initialize(argc, argv, module)
|
|
int argc;
|
|
VALUE *argv;
|
|
VALUE module;
|
|
{
|
|
if (rb_block_given_p()) {
|
|
rb_mod_module_eval(0, 0, module);
|
|
}
|
|
return Qnil;
|
|
}
|
|
|
|
static VALUE
|
|
rb_module_s_alloc(klass)
|
|
VALUE klass;
|
|
{
|
|
VALUE mod = rb_module_new();
|
|
|
|
RBASIC(mod)->klass = klass;
|
|
return mod;
|
|
}
|
|
|
|
static VALUE
|
|
rb_class_s_new(argc, argv)
|
|
int argc;
|
|
VALUE *argv;
|
|
{
|
|
VALUE super, klass;
|
|
|
|
if (rb_scan_args(argc, argv, "01", &super) == 0) {
|
|
super = rb_cObject;
|
|
}
|
|
klass = rb_class_new(super);
|
|
/* make metaclass */
|
|
RBASIC(klass)->klass = rb_singleton_class_new(RBASIC(super)->klass);
|
|
rb_singleton_class_attached(RBASIC(klass)->klass, klass);
|
|
rb_obj_call_init(klass, argc, argv);
|
|
rb_funcall(super, rb_intern("inherited"), 1, klass);
|
|
|
|
return klass;
|
|
}
|
|
|
|
VALUE
|
|
rb_obj_alloc(klass)
|
|
VALUE klass;
|
|
{
|
|
VALUE obj = rb_funcall(klass, alloc, 0, 0);
|
|
|
|
if (rb_obj_class(obj) != rb_class_real(klass)) {
|
|
rb_raise(rb_eTypeError, "wrong instance allocation");
|
|
}
|
|
return obj;
|
|
}
|
|
|
|
static VALUE
|
|
rb_class_allocate_instance(klass)
|
|
VALUE klass;
|
|
{
|
|
NEWOBJ(obj, struct RObject);
|
|
OBJSETUP(obj, klass, T_OBJECT);
|
|
|
|
return (VALUE)obj;
|
|
}
|
|
|
|
VALUE
|
|
rb_class_new_instance(argc, argv, klass)
|
|
int argc;
|
|
VALUE *argv;
|
|
VALUE klass;
|
|
{
|
|
VALUE obj;
|
|
|
|
if (FL_TEST(klass, FL_SINGLETON)) {
|
|
rb_raise(rb_eTypeError, "can't create instance of virtual class");
|
|
}
|
|
obj = rb_obj_alloc(klass);
|
|
rb_obj_call_init(obj, argc, argv);
|
|
|
|
return obj;
|
|
}
|
|
|
|
static VALUE
|
|
rb_class_superclass(klass)
|
|
VALUE klass;
|
|
{
|
|
VALUE super = RCLASS(klass)->super;
|
|
|
|
while (TYPE(super) == T_ICLASS) {
|
|
super = RCLASS(super)->super;
|
|
}
|
|
if (!super) {
|
|
return Qnil;
|
|
}
|
|
return super;
|
|
}
|
|
|
|
ID
|
|
rb_to_id(name)
|
|
VALUE name;
|
|
{
|
|
ID id;
|
|
|
|
switch (TYPE(name)) {
|
|
case T_STRING:
|
|
return rb_intern(RSTRING(name)->ptr);
|
|
case T_FIXNUM:
|
|
id = FIX2INT(name);
|
|
if (!rb_id2name(id)) {
|
|
rb_raise(rb_eArgError, "%d is not a symbol", id);
|
|
}
|
|
break;
|
|
case T_SYMBOL:
|
|
id = SYM2ID(name);
|
|
break;
|
|
default:
|
|
rb_raise(rb_eTypeError, "%s is not a symbol", RSTRING(rb_inspect(name))->ptr);
|
|
}
|
|
return id;
|
|
}
|
|
|
|
static VALUE
|
|
rb_mod_attr(argc, argv, klass)
|
|
int argc;
|
|
VALUE *argv;
|
|
VALUE klass;
|
|
{
|
|
VALUE name, pub;
|
|
|
|
rb_scan_args(argc, argv, "11", &name, &pub);
|
|
rb_attr(klass, rb_to_id(name), 1, RTEST(pub), Qtrue);
|
|
return Qnil;
|
|
}
|
|
|
|
static VALUE
|
|
rb_mod_attr_reader(argc, argv, klass)
|
|
int argc;
|
|
VALUE *argv;
|
|
VALUE klass;
|
|
{
|
|
int i;
|
|
|
|
for (i=0; i<argc; i++) {
|
|
rb_attr(klass, rb_to_id(argv[i]), 1, 0, Qtrue);
|
|
}
|
|
return Qnil;
|
|
}
|
|
|
|
static VALUE
|
|
rb_mod_attr_writer(argc, argv, klass)
|
|
int argc;
|
|
VALUE *argv;
|
|
VALUE klass;
|
|
{
|
|
int i;
|
|
|
|
for (i=0; i<argc; i++) {
|
|
rb_attr(klass, rb_to_id(argv[i]), 0, 1, Qtrue);
|
|
}
|
|
return Qnil;
|
|
}
|
|
|
|
static VALUE
|
|
rb_mod_attr_accessor(argc, argv, klass)
|
|
int argc;
|
|
VALUE *argv;
|
|
VALUE klass;
|
|
{
|
|
int i;
|
|
|
|
for (i=0; i<argc; i++) {
|
|
rb_attr(klass, rb_to_id(argv[i]), 1, 1, Qtrue);
|
|
}
|
|
return Qnil;
|
|
}
|
|
|
|
static VALUE
|
|
rb_mod_const_get(mod, name)
|
|
VALUE mod, name;
|
|
{
|
|
ID id = rb_to_id(name);
|
|
|
|
if (!rb_is_const_id(id)) {
|
|
rb_name_error(id, "wrong constant name %s", rb_id2name(id));
|
|
}
|
|
return rb_const_get(mod, id);
|
|
}
|
|
|
|
static VALUE
|
|
rb_mod_const_set(mod, name, value)
|
|
VALUE mod, name, value;
|
|
{
|
|
ID id = rb_to_id(name);
|
|
|
|
if (!rb_is_const_id(id)) {
|
|
rb_name_error(id, "wrong constant name %s", rb_id2name(id));
|
|
}
|
|
rb_const_set(mod, id, value);
|
|
return value;
|
|
}
|
|
|
|
static VALUE
|
|
rb_mod_const_defined(mod, name)
|
|
VALUE mod, name;
|
|
{
|
|
ID id = rb_to_id(name);
|
|
|
|
if (!rb_is_const_id(id)) {
|
|
rb_name_error(id, "wrong constant name %s", rb_id2name(id));
|
|
}
|
|
return rb_const_defined_at(mod, id);
|
|
}
|
|
|
|
static VALUE
|
|
rb_obj_methods(obj)
|
|
VALUE obj;
|
|
{
|
|
VALUE argv[1];
|
|
|
|
argv[0] = Qtrue;
|
|
return rb_class_instance_methods(1, argv, CLASS_OF(obj));
|
|
}
|
|
|
|
static VALUE
|
|
rb_obj_protected_methods(obj)
|
|
VALUE obj;
|
|
{
|
|
VALUE argv[1];
|
|
|
|
argv[0] = Qtrue;
|
|
return rb_class_protected_instance_methods(1, argv, CLASS_OF(obj));
|
|
}
|
|
|
|
static VALUE
|
|
rb_obj_private_methods(obj)
|
|
VALUE obj;
|
|
{
|
|
VALUE argv[1];
|
|
|
|
argv[0] = Qtrue;
|
|
return rb_class_private_instance_methods(1, argv, CLASS_OF(obj));
|
|
}
|
|
|
|
struct arg_to {
|
|
VALUE val;
|
|
const char *s;
|
|
};
|
|
|
|
static VALUE
|
|
to_type(arg)
|
|
struct arg_to *arg;
|
|
{
|
|
return rb_funcall(arg->val, rb_intern(arg->s), 0);
|
|
}
|
|
|
|
static VALUE
|
|
fail_to_type(arg)
|
|
struct arg_to *arg;
|
|
{
|
|
rb_raise(rb_eTypeError, "failed to convert %s into %s",
|
|
NIL_P(arg->val) ? "nil" :
|
|
arg->val == Qtrue ? "true" :
|
|
arg->val == Qfalse ? "false" :
|
|
rb_class2name(CLASS_OF(arg->val)),
|
|
arg->s);
|
|
return Qnil; /* not reached */
|
|
}
|
|
|
|
VALUE
|
|
rb_convert_type(val, type, tname, method)
|
|
VALUE val;
|
|
int type;
|
|
const char *tname, *method;
|
|
{
|
|
struct arg_to arg1, arg2;
|
|
|
|
if (TYPE(val) == type) return val;
|
|
arg1.val = arg2.val = val;
|
|
arg1.s = method;
|
|
arg2.s = tname;
|
|
val = rb_rescue(to_type, (VALUE)&arg1, fail_to_type, (VALUE)&arg2);
|
|
if (TYPE(val) != type) {
|
|
rb_raise(rb_eTypeError, "%s#%s should return %s",
|
|
rb_class2name(CLASS_OF(arg1.val)), method, tname);
|
|
}
|
|
return val;
|
|
}
|
|
|
|
VALUE
|
|
rb_check_convert_type(val, type, tname, method)
|
|
VALUE val;
|
|
int type;
|
|
const char *tname, *method;
|
|
{
|
|
struct arg_to arg1, arg2;
|
|
|
|
if (TYPE(val) == type) return val;
|
|
arg1.val = arg2.val = val;
|
|
arg1.s = method;
|
|
arg2.s = tname;
|
|
val = rb_rescue(to_type, (VALUE)&arg1, 0, 0);
|
|
if (!NIL_P(val) && TYPE(val) != type) {
|
|
rb_raise(rb_eTypeError, "%s#%s should return %s",
|
|
rb_class2name(CLASS_OF(arg1.val)), method, tname);
|
|
}
|
|
return val;
|
|
}
|
|
|
|
static VALUE
|
|
rb_to_integer(val, method)
|
|
VALUE val;
|
|
char *method;
|
|
{
|
|
struct arg_to arg1, arg2;
|
|
|
|
|
|
arg1.val = arg2.val = val;
|
|
arg1.s = method;
|
|
arg2.s = "Integer";
|
|
val = rb_rescue(to_type, (VALUE)&arg1, fail_to_type, (VALUE)&arg2);
|
|
if (!rb_obj_is_kind_of(val, rb_cInteger)) {
|
|
rb_raise(rb_eTypeError, "%s#%s should return Integer",
|
|
rb_class2name(CLASS_OF(arg1.val)), method);
|
|
}
|
|
return val;
|
|
}
|
|
|
|
VALUE
|
|
rb_to_int(val)
|
|
VALUE val;
|
|
{
|
|
return rb_to_integer(val, "to_int");
|
|
}
|
|
|
|
VALUE
|
|
rb_Integer(val)
|
|
VALUE val;
|
|
{
|
|
switch (TYPE(val)) {
|
|
case T_FLOAT:
|
|
if (RFLOAT(val)->value <= (double)FIXNUM_MAX
|
|
&& RFLOAT(val)->value >= (double)FIXNUM_MIN) {
|
|
break;
|
|
}
|
|
return rb_dbl2big(RFLOAT(val)->value);
|
|
|
|
case T_BIGNUM:
|
|
return val;
|
|
|
|
case T_STRING:
|
|
return rb_str2inum(val, 0);
|
|
|
|
case T_FIXNUM:
|
|
return val;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
return rb_to_integer(val, "to_i");
|
|
}
|
|
|
|
static VALUE
|
|
rb_f_integer(obj, arg)
|
|
VALUE obj, arg;
|
|
{
|
|
return rb_Integer(arg);
|
|
}
|
|
|
|
VALUE
|
|
rb_Float(val)
|
|
VALUE val;
|
|
{
|
|
switch (TYPE(val)) {
|
|
case T_FIXNUM:
|
|
return rb_float_new((double)FIX2LONG(val));
|
|
|
|
case T_FLOAT:
|
|
return val;
|
|
|
|
case T_BIGNUM:
|
|
return rb_float_new(rb_big2dbl(val));
|
|
|
|
case T_STRING:
|
|
{
|
|
char *q, *p, *end;
|
|
double d;
|
|
|
|
q = p = StringValuePtr(val);
|
|
while (*p && ISSPACE(*p)) p++;
|
|
again:
|
|
d = strtod(p, &end);
|
|
if (p == end) {
|
|
bad:
|
|
rb_raise(rb_eArgError, "invalid value for Float(): \"%s\"", q);
|
|
}
|
|
if (*end) {
|
|
if (*end == '_') {
|
|
char *buf = ALLOCA_N(char, strlen(p));
|
|
char *n = buf, *last;
|
|
|
|
while (*p) {
|
|
if (*p == '_') {
|
|
last = ++p;
|
|
continue;
|
|
}
|
|
*n++ = *p++;
|
|
}
|
|
while (*last && (*last == '_' || ISSPACE(*last)))
|
|
last++;
|
|
if (!*last) goto bad;
|
|
*n = '\0';
|
|
p = buf;
|
|
goto again;
|
|
}
|
|
while (*end && ISSPACE(*end)) end++;
|
|
if (*end) goto bad;
|
|
}
|
|
if (errno == ERANGE) {
|
|
errno = 0;
|
|
rb_raise(rb_eArgError, "Float %s out of range", p);
|
|
}
|
|
return rb_float_new(d);
|
|
}
|
|
|
|
case T_NIL:
|
|
return rb_float_new(0.0);
|
|
|
|
default:
|
|
return rb_convert_type(val, T_FLOAT, "Float", "to_f");
|
|
}
|
|
}
|
|
|
|
static VALUE
|
|
rb_f_float(obj, arg)
|
|
VALUE obj, arg;
|
|
{
|
|
return rb_Float(arg);
|
|
}
|
|
|
|
double
|
|
rb_num2dbl(val)
|
|
VALUE val;
|
|
{
|
|
switch (TYPE(val)) {
|
|
case T_FLOAT:
|
|
return RFLOAT(val)->value;
|
|
|
|
case T_STRING:
|
|
rb_raise(rb_eTypeError, "no implicit conversion to float from string");
|
|
break;
|
|
|
|
case T_NIL:
|
|
rb_raise(rb_eTypeError, "no implicit conversion to float from nil");
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return RFLOAT(rb_Float(val))->value;
|
|
}
|
|
|
|
char*
|
|
rb_str2cstr(str, len)
|
|
VALUE str;
|
|
int *len;
|
|
{
|
|
StringValue(str);
|
|
if (len) *len = RSTRING(str)->len;
|
|
else if (ruby_verbose && RSTRING(str)->len != strlen(RSTRING(str)->ptr)) {
|
|
rb_warn("string contains \\0 character");
|
|
}
|
|
return RSTRING(str)->ptr;
|
|
}
|
|
|
|
VALUE
|
|
rb_String(val)
|
|
VALUE val;
|
|
{
|
|
return rb_convert_type(val, T_STRING, "String", "to_s");
|
|
}
|
|
|
|
static VALUE
|
|
rb_f_string(obj, arg)
|
|
VALUE obj, arg;
|
|
{
|
|
return rb_String(arg);
|
|
}
|
|
|
|
VALUE
|
|
rb_Array(val)
|
|
VALUE val;
|
|
{
|
|
ID to_ary;
|
|
|
|
if (TYPE(val) == T_ARRAY) return val;
|
|
to_ary = rb_intern("to_ary");
|
|
if (rb_respond_to(val, to_ary)) {
|
|
val = rb_funcall(val, to_ary, 0);
|
|
}
|
|
else {
|
|
val = rb_funcall(val, rb_intern("to_a"), 0);
|
|
}
|
|
if (TYPE(val) != T_ARRAY) {
|
|
rb_raise(rb_eTypeError, "`to_a' did not return Array");
|
|
}
|
|
return val;
|
|
}
|
|
|
|
static VALUE
|
|
rb_f_array(obj, arg)
|
|
VALUE obj, arg;
|
|
{
|
|
return rb_Array(arg);
|
|
}
|
|
|
|
static VALUE
|
|
boot_defclass(name, super)
|
|
char *name;
|
|
VALUE super;
|
|
{
|
|
extern st_table *rb_class_tbl;
|
|
VALUE obj = rb_class_boot(super);
|
|
ID id = rb_intern(name);
|
|
|
|
rb_name_class(obj, id);
|
|
st_add_direct(rb_class_tbl, id, obj);
|
|
return obj;
|
|
}
|
|
|
|
VALUE ruby_top_self;
|
|
|
|
void
|
|
Init_Object()
|
|
{
|
|
VALUE metaclass;
|
|
|
|
alloc = rb_intern("allocate");
|
|
|
|
rb_cObject = boot_defclass("Object", 0);
|
|
rb_cModule = boot_defclass("Module", rb_cObject);
|
|
rb_cClass = boot_defclass("Class", rb_cModule);
|
|
|
|
metaclass = RBASIC(rb_cObject)->klass = rb_singleton_class_new(rb_cClass);
|
|
rb_singleton_class_attached(metaclass, rb_cObject);
|
|
metaclass = RBASIC(rb_cModule)->klass = rb_singleton_class_new(metaclass);
|
|
rb_singleton_class_attached(metaclass, rb_cModule);
|
|
metaclass = RBASIC(rb_cClass)->klass = rb_singleton_class_new(metaclass);
|
|
rb_singleton_class_attached(metaclass, rb_cClass);
|
|
|
|
rb_mKernel = rb_define_module("Kernel");
|
|
rb_include_module(rb_cObject, rb_mKernel);
|
|
rb_define_private_method(rb_cObject, "initialize", rb_obj_dummy, 0);
|
|
rb_define_private_method(rb_cClass, "inherited", rb_obj_dummy, 1);
|
|
rb_define_private_method(rb_cModule, "included", rb_obj_dummy, 1);
|
|
rb_define_private_method(rb_cModule, "method_added", rb_obj_dummy, 1);
|
|
rb_define_private_method(rb_cModule, "method_removed", rb_obj_dummy, 1);
|
|
rb_define_private_method(rb_cModule, "method_undefined", rb_obj_dummy, 1);
|
|
|
|
/*
|
|
* Ruby's Class Hierarchy Chart
|
|
*
|
|
* +------------------+
|
|
* | |
|
|
* Object---->(Object) |
|
|
* ^ ^ ^ ^ |
|
|
* | | | | |
|
|
* | | +-----+ +---------+ |
|
|
* | | | | |
|
|
* | +-----------+ | |
|
|
* | | | | |
|
|
* +------+ | Module--->(Module) |
|
|
* | | ^ ^ |
|
|
* OtherClass-->(OtherClass) | | |
|
|
* | | |
|
|
* Class---->(Class) |
|
|
* ^ |
|
|
* | |
|
|
* +----------------+
|
|
*
|
|
* + All metaclasses are instances of the class `Class'.
|
|
*/
|
|
|
|
rb_define_method(rb_mKernel, "nil?", rb_false, 0);
|
|
rb_define_method(rb_mKernel, "==", rb_obj_equal, 1);
|
|
rb_define_method(rb_mKernel, "equal?", rb_obj_equal, 1);
|
|
rb_define_method(rb_mKernel, "===", rb_obj_equal, 1);
|
|
rb_define_method(rb_mKernel, "=~", rb_false, 1);
|
|
|
|
rb_define_method(rb_mKernel, "eql?", rb_obj_equal, 1);
|
|
|
|
rb_define_method(rb_mKernel, "hash", rb_obj_id, 0);
|
|
rb_define_method(rb_mKernel, "id", rb_obj_id, 0);
|
|
rb_define_method(rb_mKernel, "__id__", rb_obj_id, 0);
|
|
rb_define_method(rb_mKernel, "type", rb_obj_class, 0);
|
|
rb_define_method(rb_mKernel, "class", rb_obj_class, 0);
|
|
|
|
rb_define_method(rb_mKernel, "clone", rb_obj_clone, 0);
|
|
rb_define_method(rb_mKernel, "dup", rb_obj_dup, 0);
|
|
|
|
rb_define_method(rb_mKernel, "taint", rb_obj_taint, 0);
|
|
rb_define_method(rb_mKernel, "tainted?", rb_obj_tainted, 0);
|
|
rb_define_method(rb_mKernel, "untaint", rb_obj_untaint, 0);
|
|
rb_define_method(rb_mKernel, "freeze", rb_obj_freeze, 0);
|
|
rb_define_method(rb_mKernel, "frozen?", rb_obj_frozen_p, 0);
|
|
|
|
rb_define_method(rb_mKernel, "to_a", rb_any_to_a, 0);
|
|
rb_define_method(rb_mKernel, "to_s", rb_any_to_s, 0);
|
|
rb_define_method(rb_mKernel, "inspect", rb_obj_inspect, 0);
|
|
rb_define_method(rb_mKernel, "methods", rb_obj_methods, 0);
|
|
rb_define_method(rb_mKernel, "public_methods", rb_obj_methods, 0);
|
|
rb_define_method(rb_mKernel, "singleton_methods", rb_obj_singleton_methods, -1);
|
|
rb_define_method(rb_mKernel, "protected_methods", rb_obj_protected_methods, 0);
|
|
rb_define_method(rb_mKernel, "private_methods", rb_obj_private_methods, 0);
|
|
rb_define_method(rb_mKernel, "instance_variables", rb_obj_instance_variables, 0);
|
|
rb_define_private_method(rb_mKernel, "remove_instance_variable",
|
|
rb_obj_remove_instance_variable, 1);
|
|
|
|
rb_define_method(rb_mKernel, "instance_of?", rb_obj_is_instance_of, 1);
|
|
rb_define_method(rb_mKernel, "kind_of?", rb_obj_is_kind_of, 1);
|
|
rb_define_method(rb_mKernel, "is_a?", rb_obj_is_kind_of, 1);
|
|
|
|
rb_define_global_function("singleton_method_added", rb_obj_dummy, 1);
|
|
rb_define_global_function("singleton_method_removed", rb_obj_dummy, 1);
|
|
rb_define_global_function("singleton_method_undefined", rb_obj_dummy, 1);
|
|
|
|
rb_define_global_function("sprintf", rb_f_sprintf, -1);
|
|
rb_define_global_function("format", rb_f_sprintf, -1);
|
|
|
|
rb_define_global_function("Integer", rb_f_integer, 1);
|
|
rb_define_global_function("Float", rb_f_float, 1);
|
|
|
|
rb_define_global_function("String", rb_f_string, 1);
|
|
rb_define_global_function("Array", rb_f_array, 1);
|
|
|
|
rb_cNilClass = rb_define_class("NilClass", rb_cObject);
|
|
rb_define_method(rb_cNilClass, "to_i", nil_to_i, 0);
|
|
rb_define_method(rb_cNilClass, "to_s", nil_to_s, 0);
|
|
rb_define_method(rb_cNilClass, "to_a", nil_to_a, 0);
|
|
rb_define_method(rb_cNilClass, "inspect", nil_inspect, 0);
|
|
rb_define_method(rb_cNilClass, "&", false_and, 1);
|
|
rb_define_method(rb_cNilClass, "|", false_or, 1);
|
|
rb_define_method(rb_cNilClass, "^", false_xor, 1);
|
|
|
|
rb_define_method(rb_cNilClass, "nil?", rb_true, 0);
|
|
rb_undef_method(CLASS_OF(rb_cNilClass), "allocate");
|
|
rb_undef_method(CLASS_OF(rb_cNilClass), "new");
|
|
rb_define_global_const("NIL", Qnil);
|
|
|
|
rb_cSymbol = rb_define_class("Symbol", rb_cObject);
|
|
rb_define_singleton_method(rb_cSymbol, "all_symbols", rb_sym_all_symbols, 0);
|
|
rb_undef_method(CLASS_OF(rb_cSymbol), "allocate");
|
|
rb_undef_method(CLASS_OF(rb_cSymbol), "new");
|
|
|
|
rb_define_method(rb_cSymbol, "to_i", sym_to_i, 0);
|
|
rb_define_method(rb_cSymbol, "to_int", sym_to_i, 0);
|
|
rb_define_method(rb_cSymbol, "inspect", sym_inspect, 0);
|
|
rb_define_method(rb_cSymbol, "to_s", sym_to_s, 0);
|
|
rb_define_method(rb_cSymbol, "id2name", sym_to_s, 0);
|
|
rb_define_method(rb_cSymbol, "intern", sym_intern, 0);
|
|
|
|
rb_define_method(rb_cModule, "===", rb_mod_eqq, 1);
|
|
rb_define_method(rb_cModule, "<=>", rb_mod_cmp, 1);
|
|
rb_define_method(rb_cModule, "<", rb_mod_lt, 1);
|
|
rb_define_method(rb_cModule, "<=", rb_mod_le, 1);
|
|
rb_define_method(rb_cModule, ">", rb_mod_gt, 1);
|
|
rb_define_method(rb_cModule, ">=", rb_mod_ge, 1);
|
|
rb_define_method(rb_cModule, "clone", rb_mod_clone, 0);
|
|
rb_define_method(rb_cModule, "dup", rb_mod_dup, 0);
|
|
rb_define_method(rb_cModule, "to_s", rb_mod_to_s, 0);
|
|
rb_define_method(rb_cModule, "included_modules", rb_mod_included_modules, 0);
|
|
rb_define_method(rb_cModule, "include?", rb_mod_include_p, 1);
|
|
rb_define_method(rb_cModule, "name", rb_mod_name, 0);
|
|
rb_define_method(rb_cModule, "ancestors", rb_mod_ancestors, 0);
|
|
|
|
rb_define_private_method(rb_cModule, "attr", rb_mod_attr, -1);
|
|
rb_define_private_method(rb_cModule, "attr_reader", rb_mod_attr_reader, -1);
|
|
rb_define_private_method(rb_cModule, "attr_writer", rb_mod_attr_writer, -1);
|
|
rb_define_private_method(rb_cModule, "attr_accessor", rb_mod_attr_accessor, -1);
|
|
|
|
rb_define_singleton_method(rb_cModule, "allocate", rb_module_s_alloc, 0);
|
|
rb_define_method(rb_cModule, "initialize", rb_mod_initialize, -1);
|
|
rb_define_method(rb_cModule, "instance_methods", rb_class_instance_methods, -1);
|
|
rb_define_method(rb_cModule, "public_instance_methods", rb_class_instance_methods, -1);
|
|
rb_define_method(rb_cModule, "protected_instance_methods", rb_class_protected_instance_methods, -1);
|
|
rb_define_method(rb_cModule, "private_instance_methods", rb_class_private_instance_methods, -1);
|
|
|
|
rb_define_method(rb_cModule, "constants", rb_mod_constants, 0);
|
|
rb_define_method(rb_cModule, "const_get", rb_mod_const_get, 1);
|
|
rb_define_method(rb_cModule, "const_set", rb_mod_const_set, 2);
|
|
rb_define_method(rb_cModule, "const_defined?", rb_mod_const_defined, 1);
|
|
rb_define_private_method(rb_cModule, "remove_const", rb_mod_remove_const, 1);
|
|
rb_define_method(rb_cModule, "class_variables", rb_mod_class_variables, 0);
|
|
rb_define_private_method(rb_cModule, "remove_class_variable", rb_mod_remove_cvar, 1);
|
|
|
|
rb_define_method(rb_cClass, "allocate", rb_class_allocate_instance, 0);
|
|
rb_define_method(rb_cClass, "new", rb_class_new_instance, -1);
|
|
rb_define_method(rb_cClass, "superclass", rb_class_superclass, 0);
|
|
rb_undef_method(CLASS_OF(rb_cClass), "allocate");
|
|
rb_define_singleton_method(rb_cClass, "new", rb_class_s_new, -1);
|
|
rb_undef_method(rb_cClass, "extend_object");
|
|
rb_undef_method(rb_cClass, "append_features");
|
|
|
|
rb_cData = rb_define_class("Data", rb_cObject);
|
|
rb_undef_method(CLASS_OF(rb_cData), "allocate");
|
|
|
|
ruby_top_self = rb_obj_alloc(rb_cObject);
|
|
rb_global_variable(&ruby_top_self);
|
|
rb_define_singleton_method(ruby_top_self, "to_s", main_to_s, 0);
|
|
|
|
rb_cTrueClass = rb_define_class("TrueClass", rb_cObject);
|
|
rb_define_method(rb_cTrueClass, "to_s", true_to_s, 0);
|
|
rb_define_method(rb_cTrueClass, "&", true_and, 1);
|
|
rb_define_method(rb_cTrueClass, "|", true_or, 1);
|
|
rb_define_method(rb_cTrueClass, "^", true_xor, 1);
|
|
rb_undef_method(CLASS_OF(rb_cTrueClass), "allocate");
|
|
rb_undef_method(CLASS_OF(rb_cTrueClass), "new");
|
|
rb_define_global_const("TRUE", Qtrue);
|
|
|
|
rb_cFalseClass = rb_define_class("FalseClass", rb_cObject);
|
|
rb_define_method(rb_cFalseClass, "to_s", false_to_s, 0);
|
|
rb_define_method(rb_cFalseClass, "&", false_and, 1);
|
|
rb_define_method(rb_cFalseClass, "|", false_or, 1);
|
|
rb_define_method(rb_cFalseClass, "^", false_xor, 1);
|
|
rb_undef_method(CLASS_OF(rb_cFalseClass), "allocate");
|
|
rb_undef_method(CLASS_OF(rb_cFalseClass), "new");
|
|
rb_define_global_const("FALSE", Qfalse);
|
|
|
|
eq = rb_intern("==");
|
|
eql = rb_intern("eql?");
|
|
inspect = rb_intern("inspect");
|
|
clone = rb_intern("clone");
|
|
}
|