summaryrefslogtreecommitdiffhomepage
path: root/src/kernel.c
diff options
context:
space:
mode:
authormimaki <[email protected]>2012-04-20 09:39:03 +0900
committermimaki <[email protected]>2012-04-20 09:39:03 +0900
commite0d6430f63c4cbe0c71ce82ee23284671389a818 (patch)
tree41abad7f12eced98d9ac14d141cea62464c3332f /src/kernel.c
parent54ad561098ed353ada70205c39b2c42a2a2eb9e5 (diff)
downloadmruby-e0d6430f63c4cbe0c71ce82ee23284671389a818.tar.gz
mruby-e0d6430f63c4cbe0c71ce82ee23284671389a818.zip
add mruby sources
Diffstat (limited to 'src/kernel.c')
-rw-r--r--src/kernel.c1530
1 files changed, 1530 insertions, 0 deletions
diff --git a/src/kernel.c b/src/kernel.c
new file mode 100644
index 000000000..e5b2cab04
--- /dev/null
+++ b/src/kernel.c
@@ -0,0 +1,1530 @@
+#include "mruby.h"
+#include "mruby/string.h"
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "mruby/proc.h"
+
+#include "mruby/range.h"
+#include "mruby/array.h"
+#include "mruby/hash.h"
+#include "mruby/class.h"
+#include "mruby/struct.h"
+#include "variable.h"
+#include "ritehash.h"
+#include "error.h"
+#include "method.h"
+#include "mdata.h"
+
+#ifdef INCLUDE_REGEXP
+#include "re.h"
+#include "regint.h"
+#endif
+
+KHASH_MAP_INIT_INT(mt, struct RProc*);
+KHASH_MAP_INIT_INT(iv, mrb_value);
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+static mrb_value tst_setconst(mrb_state *mrb, mrb_value obj);
+int kiv_lookup(khash_t(iv) *table, mrb_sym key, mrb_value *value);
+
+struct obj_ivar_tag {
+ mrb_value obj;
+ int (*func)(mrb_sym key, mrb_value val, void * arg);
+ void * arg;
+};
+
+static int
+obj_ivar_i(mrb_sym key, int index, struct obj_ivar_tag *arg)
+{
+ enum st_retval {ST_CONTINUE, ST_STOP, ST_DELETE, ST_CHECK};
+ struct obj_ivar_tag *data = (struct obj_ivar_tag *)arg;
+ if ((long)index < ROBJECT_NUMIV(data->obj)) {
+ mrb_value val = ROBJECT_IVPTR(data->obj)->vals[(long)index];
+ if (val.tt != MRB_TT_FREE) {
+ return (data->func)((mrb_sym)key, val, data->arg);
+ }
+ }
+ return ST_CONTINUE;
+}
+
+void
+mrb_ivar_foreach(mrb_state *mrb, mrb_value obj, int (*func)(ANYARGS), void* arg)
+{
+ struct obj_ivar_tag data;
+ switch (mrb_type(obj)) {
+ case MRB_TT_OBJECT:
+ //obj_ivar_each(mrb, obj, func, arg);
+ if (RCLASS_IV_TBL(obj)) {
+ data.obj = obj;
+ data.func = (int (*)(mrb_sym key, mrb_value val, void * arg))func;
+ data.arg = arg;
+ st_foreach_safe(mrb, RCLASS_IV_TBL(obj), obj_ivar_i, (void *)&data);
+ }
+ break;
+ case MRB_TT_CLASS:
+ case MRB_TT_MODULE:
+ if (RCLASS_IV_TBL(obj)) {
+ st_foreach_safe(mrb, RCLASS_IV_TBL(obj), func, arg);
+ }
+ break;
+ default:
+ if (!ROBJECT_IVPTR(obj)/*generic_iv_tbl*/) break;
+ if (/*FL_TEST(obj, FL_EXIVAR) ||*/ mrb_special_const_p(obj)) {
+ mrb_value *tbl=0;
+ if (kiv_lookup(ROBJECT_IVPTR(obj)/*generic_iv_tbl*/, SYM2ID(obj), tbl)) {
+ st_foreach_safe(mrb, (void *)tbl, func, arg);
+ }
+ }
+ break;
+ }
+}
+
+static int
+inspect_i(mrb_state *mrb, mrb_sym id, mrb_value value, mrb_value str)
+{
+ enum st_retval {ST_CONTINUE, ST_STOP, ST_DELETE, ST_CHECK};
+ mrb_value str2;
+ const char *ivname;
+ /* need not to show internal data */
+ if (RSTRING_PTR(str)[0] == '-') { /* first element */
+ RSTRING_PTR(str)[0] = '#';
+ mrb_str_cat2(mrb, str, " ");
+ }
+ else {
+ mrb_str_cat2(mrb, str, ", ");
+ }
+ ivname = mrb_sym2name(mrb, id);
+ mrb_str_cat2(mrb, str, ivname);
+ mrb_str_cat2(mrb, str, "=");
+ str2 = mrb_inspect(mrb, value);
+ mrb_str_append(mrb, str, str2);
+ //OBJ_INFECT(str, str2);
+
+ return ST_CONTINUE;
+}
+
+static mrb_value
+inspect_obj(mrb_state *mrb, mrb_value obj, mrb_value str, int recur)
+{
+ if (recur) {
+ mrb_str_cat2(mrb, str, " ...");
+ }
+ else {
+ mrb_ivar_foreach(mrb, obj, inspect_i, &str);
+ }
+ mrb_str_cat2(mrb, str, ">");
+ RSTRING_PTR(str)[0] = '#';
+ //OBJ_INFECT(str, obj);
+
+ return str;
+}
+
+int
+mrb_obj_basic_to_s_p(mrb_state *mrb, mrb_value obj)
+{
+ //const mrb_method_entry_t *me = mrb_method_entry(CLASS_OF(obj), mrb_intern("to_s"));
+ //if (me && me->def && me->def->type == VM_METHOD_TYPE_CFUNC &&
+ //me->def->body.cfunc.func == mrb_any_to_s)
+ struct RProc *me = mrb_method_search(mrb, mrb_class(mrb, obj), mrb_intern(mrb, "to_s"));
+ if (me && MRB_PROC_CFUNC_P(me) && (me->body.func == mrb_any_to_s))
+ return 1;
+ return 0;
+}
+
+/* 15.3.1.3.17 */
+/*
+ * call-seq:
+ * obj.inspect -> string
+ *
+ * Returns a string containing a human-readable representation of
+ * <i>obj</i>. If not overridden and no instance variables, uses the
+ * <code>to_s</code> method to generate the string.
+ * <i>obj</i>. If not overridden, uses the <code>to_s</code> method to
+ * generate the string.
+ *
+ * [ 1, 2, 3..4, 'five' ].inspect #=> "[1, 2, 3..4, \"five\"]"
+ * Time.new.inspect #=> "2008-03-08 19:43:39 +0900"
+ */
+mrb_value
+mrb_obj_inspect(mrb_state *mrb, mrb_value obj)
+{
+ if ((mrb_type(obj) == MRB_TT_OBJECT) && mrb_obj_basic_to_s_p(mrb, obj)) {
+ int has_ivar = 0;
+ mrb_value *ptr = (mrb_value *)ROBJECT_IVPTR(obj);
+ long len = ROBJECT_NUMIV(obj);
+ long i;
+
+ for (i = 0; i < len; i++) {
+ if (ptr[i].tt != MRB_TT_FREE) {
+ has_ivar = 1;
+ break;
+ }
+ }
+
+ if (has_ivar) {
+ mrb_value str;
+ const char *c = mrb_obj_classname(mrb, obj);
+
+ str = mrb_sprintf(mrb, "-<%s:%p", c, (void*)&obj);
+ return inspect_obj(mrb, obj, str, 0);
+ }
+ return mrb_any_to_s(mrb, obj);
+ }
+ else if (mrb_nil_p(obj)) {
+ return mrb_str_new_cstr(mrb, "nil");
+ }
+ return mrb_funcall(mrb, obj, "to_s", 0, 0);
+}
+
+/* 15.3.1.3.1 */
+/* 15.3.1.3.10 */
+/* 15.3.1.3.11 */
+/*
+ * call-seq:
+ * obj == other -> true or false
+ * obj.equal?(other) -> true or false
+ * obj.eql?(other) -> true or false
+ *
+ * Equality---At the <code>Object</code> level, <code>==</code> returns
+ * <code>true</code> only if <i>obj</i> and <i>other</i> are the
+ * same object. Typically, this method is overridden in descendant
+ * classes to provide class-specific meaning.
+ *
+ * Unlike <code>==</code>, the <code>equal?</code> method should never be
+ * overridden by subclasses: it is used to determine object identity
+ * (that is, <code>a.equal?(b)</code> iff <code>a</code> is the same
+ * object as <code>b</code>).
+ *
+ * The <code>eql?</code> method returns <code>true</code> if
+ * <i>obj</i> and <i>anObject</i> have the same value. Used by
+ * <code>Hash</code> to test members for equality. For objects of
+ * class <code>Object</code>, <code>eql?</code> is synonymous with
+ * <code>==</code>. Subclasses normally continue this tradition, but
+ * there are exceptions. <code>Numeric</code> types, for example,
+ * perform type conversion across <code>==</code>, but not across
+ * <code>eql?</code>, so:
+ *
+ * 1 == 1.0 #=> true
+ * 1.eql? 1.0 #=> false
+ */
+static mrb_value
+mrb_obj_equal_m(mrb_state *mrb, mrb_value self)
+{
+ mrb_value arg;
+
+ mrb_get_args(mrb, "o", &arg);
+ if (mrb_obj_equal(mrb, self, arg)) {
+ return mrb_true_value();
+ }
+ else {
+ return mrb_false_value();
+ }
+}
+
+static mrb_value
+mrb_obj_not_equal_m(mrb_state *mrb, mrb_value self)
+{
+ mrb_value arg;
+
+ mrb_get_args(mrb, "o", &arg);
+ if (mrb_obj_equal(mrb, self, arg)) {
+ return mrb_false_value();
+ }
+ else {
+ return mrb_true_value();
+ }
+}
+
+/* 15.3.1.3.2 */
+/*
+ * call-seq:
+ * obj === other -> true or false
+ *
+ * Case Equality---For class <code>Object</code>, effectively the same
+ * as calling <code>#==</code>, but typically overridden by descendants
+ * to provide meaningful semantics in <code>case</code> statements.
+ */
+static mrb_value
+mrb_equal_m(mrb_state *mrb, mrb_value self)
+{
+ mrb_value arg;
+
+ mrb_get_args(mrb, "o", &arg);
+ if (mrb_equal(mrb, self, arg)){
+ return mrb_true_value();
+ }
+ else {
+ return mrb_false_value();
+ }
+}
+
+/* 15.3.1.3.3 */
+/* 15.3.1.3.33 */
+/*
+ * call-seq:
+ * obj.hash -> fixnum
+ *
+ * Generates a <code>Fixnum</code> hash value for this object. This
+ * function must have the property that <code>a.eql?(b)</code> implies
+ * <code>a.hash == b.hash</code>. The hash value is used by class
+ * <code>Hash</code>. Any hash value that exceeds the capacity of a
+ * <code>Fixnum</code> will be truncated before being used.
+ */
+static mrb_value
+mrb_obj_id_m(mrb_state *mrb, mrb_value self)
+{
+ return mrb_fixnum_value(mrb_obj_id(self));
+}
+
+mrb_value
+send_internal(int argc, mrb_value *argv, mrb_value recv, enum call_type ctype)
+{
+ return mrb_nil_value(); /* dummy */
+}
+
+mrb_value
+mrb_f_send(int argc, mrb_value *argv, mrb_value recv)
+{
+ return send_internal(argc, argv, recv, CALL_FCALL);
+}
+
+/* 15.3.1.3.4 */
+/* 15.3.1.3.44 */
+/*
+ * call-seq:
+ * obj.send(symbol [, args...]) -> obj
+ * obj.__send__(symbol [, args...]) -> obj
+ *
+ * Invokes the method identified by _symbol_, passing it any
+ * arguments specified. You can use <code>__send__</code> if the name
+ * +send+ clashes with an existing method in _obj_.
+ *
+ * class Klass
+ * def hello(*args)
+ * "Hello " + args.join(' ')
+ * end
+ * end
+ * k = Klass.new
+ * k.send :hello, "gentle", "readers" #=> "Hello gentle readers"
+ */
+static mrb_value
+mrb_f_send_m(mrb_state *mrb, mrb_value self)
+{
+ mrb_value *argv;
+ int argc;
+
+ mrb_get_args(mrb, "*", &argv, &argc);
+ return mrb_f_send(argc, argv, self);
+}
+
+/* 15.3.1.2.1 */
+/* 15.3.1.3.5 */
+/*
+ * call-seq:
+ * spawn([env,] command... [,options]) -> pid
+ * Process.spawn([env,] command... [,options]) -> pid
+ *
+ * spawn executes specified command and return its pid.
+ */
+static mrb_value
+mrb_f_spawn_m(mrb_state *mrb, mrb_value self)
+{
+ mrb_value *argv;
+ int argc;
+
+ mrb_get_args(mrb, "*", &argv, &argc);
+ return (mrb_f_send(argc, argv, self));
+}
+
+static mrb_value
+mrb_f_block_given_p(void)
+{
+ return mrb_false_value(); /* dummy */
+}
+
+/* 15.3.1.2.2 */
+/* 15.3.1.2.5 */
+/* 15.3.1.3.6 */
+/* 15.3.1.3.25 */
+/*
+ * call-seq:
+ * block_given? -> true or false
+ * iterator? -> true or false
+ *
+ * Returns <code>true</code> if <code>yield</code> would execute a
+ * block in the current context. The <code>iterator?</code> form
+ * is mildly deprecated.
+ *
+ * def try
+ * if block_given?
+ * yield
+ * else
+ * "no block"
+ * end
+ * end
+ * try #=> "no block"
+ * try { "hello" } #=> "hello"
+ * try do "hello" end #=> "hello"
+ */
+static mrb_value
+mrb_f_block_given_p_m(mrb_state *mrb, mrb_value self)
+{
+ return mrb_f_block_given_p();
+}
+
+/* 15.3.1.3.7 */
+/*
+ * call-seq:
+ * obj.class -> class
+ *
+ * Returns the class of <i>obj</i>. This method must always be
+ * called with an explicit receiver, as <code>class</code> is also a
+ * reserved word in Ruby.
+ *
+ * 1.class #=> Fixnum
+ * self.class #=> Object
+ */
+static mrb_value
+mrb_obj_class_m(mrb_state *mrb, mrb_value self)
+{
+ return mrb_obj_value(mrb_obj_class(mrb, self));
+}
+
+struct RClass*
+mrb_singleton_class_clone(mrb_state *mrb, mrb_value obj)
+{
+ struct RClass *klass = RBASIC(obj)->c;
+
+ //if (!FL_TEST(klass, FL_SINGLETON))
+ //return klass;
+ if (klass->tt != MRB_TT_SCLASS)
+ return klass;
+ else {
+ //struct clone_method_data data;
+ /* copy singleton(unnamed) class */
+ //VALUE clone = class_alloc(RBASIC(klass)->flags, 0);
+ struct RClass *clone = mrb_obj_alloc(mrb, klass->tt, mrb->class_class);
+ //clone->super = objklass->super;
+
+ if ((mrb_type(obj) == MRB_TT_CLASS) ||
+ (mrb_type(obj) == MRB_TT_SCLASS)) { /* BUILTIN_TYPE(obj) == T_CLASS */
+ clone->c = clone;
+ }
+ else {
+ clone->c = mrb_singleton_class_clone(mrb, mrb_obj_value(klass));
+ }
+
+ clone->super = klass->super;
+ if (klass->iv) {
+ //clone->iv = st_copy(klass->iv);
+ clone->iv = klass->iv;
+ }
+ clone->mt = kh_init(mt, mrb);
+ clone->tt = MRB_TT_SCLASS;
+ return clone;
+ }
+}
+
+static void
+init_copy(mrb_state *mrb, mrb_value dest, mrb_value obj)
+{
+ //if (OBJ_FROZEN(dest)) {
+ // rb_raise(rb_eTypeError, "[bug] frozen object (%s) allocated", rb_obj_classname(dest));
+ //}
+ //RBASIC(dest)->flags &= ~(T_MASK|FL_EXIVAR);
+ //RBASIC(dest)->flags |= RBASIC(obj)->flags & (T_MASK|FL_EXIVAR|FL_TAINT);
+ //if (FL_TEST(obj, FL_EXIVAR)) {
+ // mrb_copy_generic_ivar(dest, obj);
+ //}
+ //mrb_gc_copy_finalizer(dest, obj);
+ switch (mrb_type(obj)) {
+ case MRB_TT_OBJECT:
+ case MRB_TT_CLASS:
+ case MRB_TT_MODULE:
+ if (ROBJECT(dest)->iv) {
+ //st_free_table(ROBJECT(dest)->iv);
+ ROBJECT(dest)->iv = 0;
+ }
+ if (ROBJECT(obj)->iv) {
+ //ROBJECT(dest)->iv = st_copy((st_table *)ROBJECT(obj)->iv);
+ ROBJECT(dest)->iv = ROBJECT(obj)->iv;
+ }
+ }
+ mrb_funcall(mrb, dest, "initialize_copy", 1, obj);
+}
+
+/* 15.3.1.3.8 */
+/*
+ * call-seq:
+ * obj.clone -> an_object
+ *
+ * Produces a shallow copy of <i>obj</i>---the instance variables of
+ * <i>obj</i> are copied, but not the objects they reference. Copies
+ * the frozen and tainted state of <i>obj</i>. See also the discussion
+ * under <code>Object#dup</code>.
+ *
+ * class Klass
+ * attr_accessor :str
+ * end
+ * s1 = Klass.new #=> #<Klass:0x401b3a38>
+ * s1.str = "Hello" #=> "Hello"
+ * s2 = s1.clone #=> #<Klass:0x401b3998 @str="Hello">
+ * s2.str[1,4] = "i" #=> "i"
+ * s1.inspect #=> "#<Klass:0x401b3a38 @str=\"Hi\">"
+ * s2.inspect #=> "#<Klass:0x401b3998 @str=\"Hi\">"
+ *
+ * This method may have class-specific behavior. If so, that
+ * behavior will be documented under the #+initialize_copy+ method of
+ * the class.
+ *
+ * Some Class(True False Nil Symbol Fixnum Float) Object cannot clone.
+ */
+mrb_value
+mrb_obj_clone(mrb_state *mrb, mrb_value self)
+{
+ struct RObject *clone;
+
+ if (mrb_special_const_p(self)) {
+ mrb_raise(mrb, E_TYPE_ERROR, "can't clone %s", mrb_obj_classname(mrb, self));
+ }
+ clone = mrb_obj_alloc(mrb, self.tt, mrb_obj_class(mrb, self));
+ clone->c = mrb_singleton_class_clone(mrb, self);
+ //RBASIC(clone)->flags = (RBASIC(obj)->flags | FL_TEST(clone, FL_TAINT) | FL_TEST(clone, FL_UNTRUSTED)) & ~(FL_FREEZE|FL_FINALIZE);
+ init_copy(mrb, mrb_obj_value(clone), self);
+ //1-9-2 no bug mrb_funcall(mrb, clone, "initialize_clone", 1, self);
+ //RBASIC(clone)->flags |= RBASIC(obj)->flags & FL_FREEZE;
+
+ return mrb_obj_value(clone);
+}
+
+/* 15.3.1.3.9 */
+/*
+ * call-seq:
+ * obj.dup -> an_object
+ *
+ * Produces a shallow copy of <i>obj</i>---the instance variables of
+ * <i>obj</i> are copied, but not the objects they reference.
+ * <code>dup</code> copies the tainted state of <i>obj</i>. See also
+ * the discussion under <code>Object#clone</code>. In general,
+ * <code>clone</code> and <code>dup</code> may have different semantics
+ * in descendant classes. While <code>clone</code> is used to duplicate
+ * an object, including its internal state, <code>dup</code> typically
+ * uses the class of the descendant object to create the new instance.
+ *
+ * This method may have class-specific behavior. If so, that
+ * behavior will be documented under the #+initialize_copy+ method of
+ * the class.
+ */
+
+mrb_value
+mrb_obj_dup(mrb_state *mrb, mrb_value obj)
+{
+ struct RBasic *p;
+ mrb_value dup;
+
+ if (mrb_special_const_p(obj)) {
+ mrb_raise(mrb, E_TYPE_ERROR, "can't dup %s", mrb_obj_classname(mrb, obj));
+ }
+ p = mrb_obj_alloc(mrb, mrb_type(obj), mrb_obj_class(mrb, obj));
+ //init_copy(dup, obj);
+ dup = mrb_obj_value(p);
+ mrb_funcall(mrb, dup, "initialize_copy", 1, obj);
+
+ return dup;
+}
+
+/* 15.3.1.2.3 */
+/* 15.3.1.3.12 */
+/*
+ * call-seq:
+ * eval(string [, binding [, filename [,lineno]]]) -> obj
+ *
+ * Evaluates the Ruby expression(s) in <em>string</em>. If
+ * <em>binding</em> is given, which must be a <code>Binding</code>
+ * object, the evaluation is performed in its context. If the
+ * optional <em>filename</em> and <em>lineno</em> parameters are
+ * present, they will be used when reporting syntax errors.
+ *
+ * def getBinding(str)
+ * return binding
+ * end
+ * str = "hello"
+ * eval "str + ' Fred'" #=> "hello Fred"
+ * eval "str + ' Fred'", getBinding("bye") #=> "bye Fred"
+ */
+mrb_value
+mrb_f_eval(int argc, mrb_value *argv, mrb_value self)
+{
+ return mrb_false_value(); /* dummy */
+}
+mrb_value
+mrb_f_eval_m(mrb_state *mrb, mrb_value self)
+{
+ mrb_value *argv;
+ int argc;
+
+ mrb_get_args(mrb, "*", &argv, &argc);
+ return mrb_f_eval(argc, argv, self);
+}
+
+static mrb_value
+mrb_obj_extend(mrb_state *mrb, int argc, mrb_value *argv, mrb_value obj)
+{
+ int i;
+
+ if (argc == 0) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments (at least 1)");
+ }
+ for (i = 0; i < argc; i++) {
+ //Check_Type(argv[i], T_MODULE);
+ mrb_check_type(mrb, argv[i], MRB_TT_MODULE);
+ }
+ while (argc--) {
+ mrb_funcall(mrb, argv[argc], "extend_object", 1, obj);
+ mrb_funcall(mrb, argv[argc], "extended", 1, obj);
+ }
+ return obj;
+}
+
+/* 15.3.1.3.13 */
+/*
+ * call-seq:
+ * obj.extend(module, ...) -> obj
+ *
+ * Adds to _obj_ the instance methods from each module given as a
+ * parameter.
+ *
+ * module Mod
+ * def hello
+ * "Hello from Mod.\n"
+ * end
+ * end
+ *
+ * class Klass
+ * def hello
+ * "Hello from Klass.\n"
+ * end
+ * end
+ *
+ * k = Klass.new
+ * k.hello #=> "Hello from Klass.\n"
+ * k.extend(Mod) #=> #<Klass:0x401b3bc8>
+ * k.hello #=> "Hello from Mod.\n"
+ */
+mrb_value
+mrb_obj_extend_m(mrb_state *mrb, mrb_value self)
+{
+ mrb_value *argv;
+ int argc;
+
+ mrb_get_args(mrb, "*", &argv, &argc);
+ return mrb_obj_extend(mrb, argc, argv, self);
+}
+
+/* 15.3.1.2.4 */
+/* 15.3.1.3.14 */
+/*
+ * call-seq:
+ * global_variables -> array
+ *
+ * Returns an array of the names of global variables.
+ *
+ * global_variables.grep /std/ #=> [:$stdin, :$stdout, :$stderr]
+ */
+//mrb_value
+//mrb_f_global_variables(mrb_state *mrb, mrb_value self)
+
+/* 15.3.1.3.15 */
+mrb_value
+mrb_obj_hash(mrb_state *mrb, mrb_value self)
+{
+ return mrb_fixnum_value(mrb_obj_id(self));
+}
+
+/* 15.3.1.3.16 */
+mrb_value
+mrb_obj_init_copy(mrb_state *mrb, mrb_value self)
+{
+ mrb_value orig;
+
+ mrb_get_args(mrb, "o", &orig);
+ if (mrb_obj_equal(mrb, self, orig)) return self;
+ if ((mrb_type(self) != mrb_type(orig)) || (mrb_obj_class(mrb, self) != mrb_obj_class(mrb, orig))) {
+ mrb_raise(mrb, E_TYPE_ERROR, "initialize_copy should take same class object");
+ }
+ return self;
+}
+
+/* 15.3.1.3.18 */
+/*
+ * call-seq:
+ * obj.instance_eval(string [, filename [, lineno]] ) -> obj
+ * obj.instance_eval {| | block } -> obj
+ *
+ * Evaluates a string containing Ruby source code, or the given block,
+ * within the context of the receiver (_obj_). In order to set the
+ * context, the variable +self+ is set to _obj_ while
+ * the code is executing, giving the code access to _obj_'s
+ * instance variables. In the version of <code>instance_eval</code>
+ * that takes a +String+, the optional second and third
+ * parameters supply a filename and starting line number that are used
+ * when reporting compilation errors.
+ *
+ * class KlassWithSecret
+ * def initialize
+ * @secret = 99
+ * end
+ * end
+ * k = KlassWithSecret.new
+ * k.instance_eval { @secret } #=> 99
+ */
+mrb_value
+mrb_obj_instance_eval(mrb_state *mrb, mrb_value self)
+{
+ mrb_value *argv;
+ int argc;
+ mrb_value b, klass;
+
+ mrb_get_args(mrb, "&", &b);
+ return mrb_yield_with_self(mrb, b, 0, 0, self);
+}
+
+/* 15.3.1.3.19 */
+/*
+ * call-seq:
+ * obj.instance_of?(class) -> true or false
+ *
+ * Returns <code>true</code> if <i>obj</i> is an instance of the given
+ * class. See also <code>Object#kind_of?</code>.
+ */
+mrb_value
+rb_obj_is_instance_of(mrb_state *mrb, mrb_value self)
+{
+ mrb_value arg;
+
+ mrb_get_args(mrb, "o", &arg);
+ if (mrb_obj_is_instance_of(mrb, self, mrb_class_ptr(arg))){
+ return mrb_true_value();
+ }
+ else {
+ return mrb_false_value();
+ }
+}
+
+/* 15.3.1.3.20 */
+/*
+ * call-seq:
+ * obj.instance_variable_defined?(symbol) -> true or false
+ *
+ * Returns <code>true</code> if the given instance variable is
+ * defined in <i>obj</i>.
+ *
+ * class Fred
+ * def initialize(p1, p2)
+ * @a, @b = p1, p2
+ * end
+ * end
+ * fred = Fred.new('cat', 99)
+ * fred.instance_variable_defined?(:@a) #=> true
+ * fred.instance_variable_defined?("@b") #=> true
+ * fred.instance_variable_defined?("@c") #=> false
+ */
+mrb_value
+mrb_obj_ivar_defined(mrb_state *mrb, mrb_value self)
+{
+ mrb_value arg;
+ khiter_t k;
+ kh_iv_t *h = RCLASS_IV_TBL(self);
+
+ mrb_get_args(mrb, "o", &arg);
+ mrb_sym mid = mrb_to_id(mrb, arg);
+
+ //if (!mrb_is_instance_id(id)) {
+ // mrb_name_error(id, "`%s' is not allowed as an instance variable name", mrb_sym2name(mrb, id));
+ //}
+ //return mrb_ivar_defined(self, id);
+ k = kh_get(iv, h, mid);
+ if (k != kh_end(h)) {
+ return mrb_true_value();
+ }
+ else {
+ return mrb_false_value();
+ }
+}
+
+/* 15.3.1.3.21 */
+/*
+ * call-seq:
+ * obj.instance_variable_get(symbol) -> obj
+ *
+ * Returns the value of the given instance variable, or nil if the
+ * instance variable is not set. The <code>@</code> part of the
+ * variable name should be included for regular instance
+ * variables. Throws a <code>NameError</code> exception if the
+ * supplied symbol is not valid as an instance variable name.
+ *
+ * class Fred
+ * def initialize(p1, p2)
+ * @a, @b = p1, p2
+ * end
+ * end
+ * fred = Fred.new('cat', 99)
+ * fred.instance_variable_get(:@a) #=> "cat"
+ * fred.instance_variable_get("@b") #=> 99
+ */
+mrb_value
+mrb_obj_ivar_get(mrb_state *mrb, mrb_value self)
+{
+ mrb_value arg;
+
+ mrb_get_args(mrb, "o", &arg);
+ mrb_sym id = mrb_to_id(mrb, arg);
+
+ //if (!mrb_is_instance_id(id)) {
+ // mrb_name_error(mrb, id, "`%s' is not allowed as an instance variable name", mrb_sym2name(mrb, id));
+ //}
+ return mrb_iv_get(mrb, self, id);
+}
+
+/* 15.3.1.3.22 */
+/*
+ * call-seq:
+ * obj.instance_variable_set(symbol, obj) -> obj
+ *
+ * Sets the instance variable names by <i>symbol</i> to
+ * <i>object</i>, thereby frustrating the efforts of the class's
+ * author to attempt to provide proper encapsulation. The variable
+ * did not have to exist prior to this call.
+ *
+ * class Fred
+ * def initialize(p1, p2)
+ * @a, @b = p1, p2
+ * end
+ * end
+ * fred = Fred.new('cat', 99)
+ * fred.instance_variable_set(:@a, 'dog') #=> "dog"
+ * fred.instance_variable_set(:@c, 'cat') #=> "cat"
+ * fred.inspect #=> "#<Fred:0x401b3da8 @a=\"dog\", @b=99, @c=\"cat\">"
+ */
+mrb_value
+mrb_obj_ivar_set(mrb_state *mrb, mrb_value self)
+{
+ mrb_value key;
+ mrb_value val;
+
+ mrb_get_args(mrb, "oo", &key, &val);
+ mrb_sym id = mrb_to_id(mrb, key);
+
+ //if (!mrb_is_instance_id(id)) {
+ // mrb_name_error(mrb, id, "`%s' is not allowed as an instance variable name", mrb_sym2name(mrb, id));
+ //}
+ mrb_iv_set(mrb, self, id, val);
+ return val;
+}
+
+/* 15.3.1.3.23 */
+/*
+ * call-seq:
+ * obj.instance_variables -> array
+ *
+ * Returns an array of instance variable names for the receiver. Note
+ * that simply defining an accessor does not create the corresponding
+ * instance variable.
+ *
+ * class Fred
+ * attr_accessor :a1
+ * def initialize
+ * @iv = 3
+ * end
+ * end
+ * Fred.new.instance_variables #=> [:@iv]
+ */
+mrb_value
+mrb_obj_instance_variables(mrb_state *mrb, mrb_value self)
+{
+ mrb_value ary;
+ kh_iv_t *h = RCLASS_IV_TBL(self);
+ int i;
+ const char* p;
+
+ ary = mrb_ary_new(mrb);
+ //if (mrb_is_instance_id(key)) {
+ // mrb_ary_push(mrb, ary, mrb_sym2name(mrb, key));
+ //}
+ for (i=0;i<kh_end(h);i++) {
+ if (kh_exist(h, i)) {
+ p = mrb_sym2name(mrb, kh_key(h,i));
+ if (*p == '@') {
+ if (mrb_type(kh_value(h, i)) != MRB_TT_UNDEF)
+ mrb_ary_push(mrb, ary, mrb_str_new_cstr(mrb, p));
+ }
+ }
+ }
+ return ary;
+}
+
+/* 15.3.1.3.24 */
+/* 15.3.1.3.26 */
+/*
+ * call-seq:
+ * obj.is_a?(class) -> true or false
+ * obj.kind_of?(class) -> true or false
+ *
+ * Returns <code>true</code> if <i>class</i> is the class of
+ * <i>obj</i>, or if <i>class</i> is one of the superclasses of
+ * <i>obj</i> or modules included in <i>obj</i>.
+ *
+ * module M; end
+ * class A
+ * include M
+ * end
+ * class B < A; end
+ * class C < B; end
+ * b = B.new
+ * b.instance_of? A #=> false
+ * b.instance_of? B #=> true
+ * b.instance_of? C #=> false
+ * b.instance_of? M #=> false
+ * b.kind_of? A #=> true
+ * b.kind_of? B #=> true
+ * b.kind_of? C #=> false
+ * b.kind_of? M #=> true
+ */
+mrb_value
+mrb_obj_is_kind_of_m(mrb_state *mrb, mrb_value self)
+{
+ mrb_value arg;
+
+ mrb_get_args(mrb, "o", &arg);
+ if (mrb_obj_is_kind_of(mrb, self, mrb_class_ptr(arg))) {
+ return mrb_true_value();
+ }
+ else {
+ return mrb_false_value();
+ }
+}
+
+/* 15.3.1.2.6 */
+/* 15.3.1.3.27 */
+/*
+ * call-seq:
+ * lambda { |...| block } -> a_proc
+ *
+ * Equivalent to <code>Proc.new</code>, except the resulting Proc objects
+ * check the number of parameters passed when called.
+ */
+mrb_value
+proc_lambda(mrb_state *mrb, mrb_value self)
+{
+ //return mrb_block_lambda();
+ return mrb_nil_value(); /* dummy */
+}
+
+/* 15.3.1.2.7 */
+/* 15.3.1.3.28 */
+/*
+ * call-seq:
+ * local_variables -> array
+ *
+ * Returns the names of the current local variables.
+ *
+ * fred = 1
+ * for i in 1..10
+ * # ...
+ * end
+ * local_variables #=> [:fred, :i]
+ */
+mrb_value
+mrb_f_local_variables(mrb_state *mrb, mrb_value self)
+{
+ mrb_value ary;
+
+ ary = mrb_ary_new(mrb);
+ return ary; /* dummy */
+}
+
+/* 15.3.1.2.8 */
+/* 15.3.1.3.29 */
+/*
+ * call-seq:
+ * loop { block }
+ * loop -> an_enumerator
+ *
+ * Repeatedly executes the block.
+ *
+ * If no block is given, an enumerator is returned instead.
+ *
+ * loop do
+ * print "Input: "
+ * line = gets
+ * break if !line or line =~ /^qQ/
+ * # ...
+ * end
+ *
+ * StopIteration raised in the block breaks the loop.
+ */
+mrb_value
+mrb_f_loop(mrb_state *mrb, mrb_value self)
+{
+ return mrb_nil_value(); /* dummy */
+}
+
+static void
+method_entry_loop(mrb_state *mrb, struct RClass* klass, mrb_value ary)
+{
+ int i;
+
+ khash_t(mt) *h = klass->mt;
+ for (i=0;i<kh_end(h);i++) {
+ if (kh_exist(h, i)) {
+ mrb_ary_push(mrb, ary, mrb_symbol_value(kh_key(h,i)));
+ }
+ }
+}
+
+static mrb_value
+class_instance_method_list(mrb_state *mrb, int argc, mrb_value *argv, struct RClass* klass, int obj)
+{
+ mrb_value ary;
+ int recur;
+ //st_table *list;
+ struct RClass* oldklass;
+
+ if (argc == 0) {
+ recur = TRUE;
+ }
+ else {
+ mrb_value r;
+ mrb_get_args(mrb, "o", &r);
+ recur = mrb_test(r);
+ }
+
+ //list = st_init_numtable();
+ ary = mrb_ary_new(mrb);
+ //for (; mod; mod = RCLASS_SUPER(mod)) {
+ oldklass = 0;
+ while (klass && (klass != oldklass)) {
+ //st_foreach(RCLASS_M_TBL(mod), method_entry, (st_data_t)list);
+ method_entry_loop(mrb, klass, ary);
+ if ((klass->tt == MRB_TT_ICLASS) ||
+ (klass->tt == MRB_TT_SCLASS)) {
+ }
+ else
+ {
+ if (!recur) break;
+ }
+ oldklass = klass;
+ klass = klass->super;
+ }
+ //st_foreach(list, func, ary);
+ //st_free_table(list);
+
+ return ary;
+}
+
+mrb_value
+mrb_obj_singleton_methods(mrb_state *mrb, int argc, mrb_value *argv, mrb_value obj)
+{
+ mrb_value recur, ary;
+ //st_table *list;
+ struct RClass* klass;
+
+ if (argc == 0) {
+ recur = mrb_true_value();
+ }
+ else {
+ //mrb_scan_args(argc, argv, "01", &recur);
+ recur = argv[0];
+ }
+ klass = mrb_class(mrb, obj);
+ //list = st_init_numtable();
+ ary = mrb_ary_new(mrb);
+ if (klass && (klass->tt == MRB_TT_SCLASS)) {
+ //st_foreach(RCLASS_M_TBL(klass), method_entry, (st_data_t)list);
+ method_entry_loop(mrb, klass, ary);
+ klass = klass->super;
+ }
+ if (RTEST(recur)) {
+ while (klass && ((klass->tt == MRB_TT_SCLASS) || (klass->tt == MRB_TT_ICLASS))) {
+ //st_foreach(RCLASS_M_TBL(klass), method_entry, (st_data_t)list);
+ method_entry_loop(mrb, klass, ary);
+ klass = klass->super;
+ }
+ }
+ //st_foreach(list, ins_methods_i, ary);
+ //st_free_table(list);
+
+ return ary;
+}
+
+mrb_value
+mrb_obj_methods(mrb_state *mrb, int argc, mrb_value *argv, mrb_value obj, mrb_method_flag_t flag)
+{
+retry:
+ if (argc == 0) {
+ mrb_value args[1];
+
+ args[0] = mrb_true_value();
+ return class_instance_method_list(mrb, argc, argv, mrb_class(mrb, obj), 0);
+ }
+ else {
+ mrb_value recur;
+
+ //mrb_scan_args(argc, argv, "1", &recur);
+ recur = argv[0];
+ if (mrb_test(recur)) {
+ argc = 0;
+ goto retry;
+ }
+ return mrb_obj_singleton_methods(mrb, argc, argv, obj);
+ }
+}
+/* 15.3.1.3.31 */
+/*
+ * call-seq:
+ * obj.methods -> array
+ *
+ * Returns a list of the names of methods publicly accessible in
+ * <i>obj</i>. This will include all the methods accessible in
+ * <i>obj</i>'s ancestors.
+ *
+ * class Klass
+ * def kMethod()
+ * end
+ * end
+ * k = Klass.new
+ * k.methods[0..9] #=> [:kMethod, :freeze, :nil?, :is_a?,
+ * # :class, :instance_variable_set,
+ * # :methods, :extend, :__send__, :instance_eval]
+ * k.methods.length #=> 42
+ */
+mrb_value
+mrb_obj_methods_m(mrb_state *mrb, mrb_value self)
+{
+ mrb_value *argv;
+ int argc;
+
+ mrb_get_args(mrb, "*", &argv, &argc);
+ return mrb_obj_methods(mrb, argc, argv, self, 0); /* everything but private */
+}
+
+/* 15.3.1.3.32 */
+/*
+ * call_seq:
+ * nil.nil? -> true
+ * <anything_else>.nil? -> false
+ *
+ * Only the object <i>nil</i> responds <code>true</code> to <code>nil?</code>.
+ */
+mrb_value
+mrb_false(mrb_state *mrb, mrb_value self)
+{
+ return mrb_false_value();
+}
+
+/* 15.3.1.2.10 */
+/* 15.3.1.3.35 */
+/*
+ * call-seq:
+ * print(obj, ...) -> nil
+ *
+ * Prints each object in turn to <code>$stdout</code>. If the output
+ * field separator (<code>$,</code>) is not +nil+, its
+ * contents will appear between each field. If the output record
+ * separator (<code>$\\</code>) is not +nil+, it will be
+ * appended to the output. If no arguments are given, prints
+ * <code>$_</code>. Objects that aren't strings will be converted by
+ * calling their <code>to_s</code> method.
+ *
+ * print "cat", [1,2,3], 99, "\n"
+ * $, = ", "
+ * $\ = "\n"
+ * print "cat", [1,2,3], 99
+ *
+ * <em>produces:</em>
+ *
+ * cat12399
+ * cat, 1, 2, 3, 99
+ */
+
+/* 15.3.1.3.36 */
+/*
+ * call-seq:
+ * obj.private_methods(all=true) -> array
+ *
+ * Returns the list of private methods accessible to <i>obj</i>. If
+ * the <i>all</i> parameter is set to <code>false</code>, only those methods
+ * in the receiver will be listed.
+ */
+mrb_value
+mrb_obj_private_methods(mrb_state *mrb, mrb_value self)
+{
+ mrb_value *argv;
+ int argc;
+
+ mrb_get_args(mrb, "*", &argv, &argc);
+ return mrb_obj_methods(mrb, argc, argv, self, NOEX_PRIVATE); /* private attribute not define */
+}
+
+/* 15.3.1.3.37 */
+/*
+ * call-seq:
+ * obj.protected_methods(all=true) -> array
+ *
+ * Returns the list of protected methods accessible to <i>obj</i>. If
+ * the <i>all</i> parameter is set to <code>false</code>, only those methods
+ * in the receiver will be listed.
+ */
+mrb_value
+mrb_obj_protected_methods(mrb_state *mrb, mrb_value self)
+{
+ mrb_value *argv;
+ int argc;
+
+ mrb_get_args(mrb, "*", &argv, &argc);
+ return mrb_obj_methods(mrb, argc, argv, self, NOEX_PROTECTED); /* protected attribute not define */
+}
+
+/* 15.3.1.3.38 */
+/*
+ * call-seq:
+ * obj.public_methods(all=true) -> array
+ *
+ * Returns the list of public methods accessible to <i>obj</i>. If
+ * the <i>all</i> parameter is set to <code>false</code>, only those methods
+ * in the receiver will be listed.
+ */
+mrb_value
+mrb_obj_public_methods(mrb_state *mrb, mrb_value self)
+{
+ mrb_value *argv;
+ int argc;
+
+ mrb_get_args(mrb, "*", &argv, &argc);
+ return mrb_obj_methods(mrb, argc, argv, self, NOEX_PUBLIC); /* public attribute not define */
+}
+
+/* 15.3.1.2.11 */
+/* 15.3.1.3.39 */
+/*
+ * call-seq:
+ * puts(obj, ...) -> nil
+ *
+ * Equivalent to
+ *
+ * $stdout.puts(obj, ...)
+ */
+
+static mrb_value
+get_errinfo(mrb_state *mrb)
+{
+ //return get_thread_errinfo(GET_THREAD());
+ return mrb_str_new_cstr(mrb, "error!!"); /* dummy */
+}
+
+/* 15.3.1.2.12 */
+/* 15.3.1.3.40 */
+/*
+ * call-seq:
+ * raise
+ * raise(string)
+ * raise(exception [, string [, array]])
+ * fail
+ * fail(string)
+ * fail(exception [, string [, array]])
+ *
+ * With no arguments, raises the exception in <code>$!</code> or raises
+ * a <code>RuntimeError</code> if <code>$!</code> is +nil+.
+ * With a single +String+ argument, raises a
+ * +RuntimeError+ with the string as a message. Otherwise,
+ * the first parameter should be the name of an +Exception+
+ * class (or an object that returns an +Exception+ object when sent
+ * an +exception+ message). The optional second parameter sets the
+ * message associated with the exception, and the third parameter is an
+ * array of callback information. Exceptions are caught by the
+ * +rescue+ clause of <code>begin...end</code> blocks.
+ *
+ * raise "Failed to create socket"
+ * raise ArgumentError, "No parameters", caller
+ */
+mrb_value
+mrb_f_raise(mrb_state *mrb, mrb_value self)
+{
+ mrb_value err;
+ mrb_value *argv;
+ int argc;
+
+ mrb_get_args(mrb, "*", &argv, &argc);
+ if (argc == 0) {
+ err = get_errinfo(mrb);
+ if (!mrb_nil_p(err)) {
+ argc = 1;
+ argv[0] = err;
+ }
+ }
+ mrb_exc_raise(mrb, mrb_make_exception(mrb, argc, argv));
+ return mrb_nil_value(); /* not reached */
+}
+
+/* 15.3.1.3.41 */
+/*
+ * call-seq:
+ * obj.remove_instance_variable(symbol) -> obj
+ *
+ * Removes the named instance variable from <i>obj</i>, returning that
+ * variable's value.
+ *
+ * class Dummy
+ * attr_reader :var
+ * def initialize
+ * @var = 99
+ * end
+ * def remove
+ * remove_instance_variable(:@var)
+ * end
+ * end
+ * d = Dummy.new
+ * d.var #=> 99
+ * d.remove #=> 99
+ * d.var #=> nil
+ */
+mrb_value
+mrb_obj_remove_instance_variable(mrb_state *mrb, mrb_value self)
+{
+ mrb_sym sym;
+ mrb_value name;
+ khash_t(iv) *h;
+ khiter_t k;
+ mrb_value val;
+ mrb_value Qundef = mrb_undef_value();
+
+ mrb_get_args(mrb, "o", &name);
+ sym = mrb_to_id(mrb, name);
+ //if (OBJ_FROZEN(obj)) mrb_error_frozen("object");
+ //if (!mrb_is_instance_id(id)) {
+ // mrb_name_error(mrb, id, "`%s' is not allowed as an instance variable name", mrb_sym2name(mrb, id));
+ //}
+ switch (mrb_type(self)) {
+ case MRB_TT_OBJECT:
+ case MRB_TT_CLASS:
+ case MRB_TT_MODULE:
+ if (!mrb_obj_ptr(self)->iv) break;
+ h = mrb_obj_ptr(self)->iv;
+ k = kh_get(iv, h, sym);
+ if (k != kh_end(h)) {
+ val = kh_value(h, k);
+ if (!mrb_obj_equal(mrb, val, Qundef)) {
+ kh_value(h, k) = Qundef;
+ return val;
+ }
+ }
+ break;
+ //default:
+ // if (mrb_special_const_p(obj)) {
+ // v = val;
+ // if (generic_ivar_remove(obj, (st_data_t)id, &v)) {
+ // return (VALUE)v;
+ // }
+ // }
+ // break;
+ }
+ mrb_name_error(mrb, sym, "instance variable %s not defined", mrb_sym2name(mrb, sym));
+ return mrb_nil_value(); /* not reached */
+}
+
+/* 15.3.1.2.13 */
+/* 15.3.1.3.42 */
+/*
+ * call-seq:
+ * require(string) -> true or false
+ *
+ * Ruby tries to load the library named _string_, returning
+ * +true+ if successful. If the filename does not resolve to
+ * an absolute path, it will be searched for in the directories listed
+ * in <code>$:</code>. If the file has the extension ``.rb'', it is
+ * loaded as a source file; if the extension is ``.so'', ``.o'', or
+ * ``.dll'', or whatever the default shared library extension is on
+ * the current platform, Ruby loads the shared library as a Ruby
+ * extension. Otherwise, Ruby tries adding ``.rb'', ``.so'', and so on
+ * to the name. The name of the loaded feature is added to the array in
+ * <code>$"</code>. A feature will not be loaded if its name already
+ * appears in <code>$"</code>. The file name is converted to an absolute
+ * path, so ``<code>require 'a'; require './a'</code>'' will not load
+ * <code>a.rb</code> twice.
+ *
+ * require "my-library.rb"
+ * require "db-driver"
+ */
+mrb_value
+mrb_f_require(mrb_state *mrb, mrb_value self)
+{
+ mrb_value fname;
+
+ mrb_get_args(mrb, "o", &fname);
+ return mrb_nil_value(); /* dummy */
+}
+
+
+static inline int
+basic_obj_respond_to(mrb_state *mrb, mrb_value obj, mrb_sym id, int pub)
+{
+ return mrb_respond_to(mrb, obj, id);
+ //return TRUE;
+}
+/* 15.3.1.3.43 */
+/*
+ * call-seq:
+ * obj.respond_to?(symbol, include_private=false) -> true or false
+ *
+ * Returns +true+ if _obj_ responds to the given
+ * method. Private methods are included in the search only if the
+ * optional second parameter evaluates to +true+.
+ *
+ * If the method is not implemented,
+ * as Process.fork on Windows, File.lchmod on GNU/Linux, etc.,
+ * false is returned.
+ *
+ * If the method is not defined, <code>respond_to_missing?</code>
+ * method is called and the result is returned.
+ */
+mrb_value
+obj_respond_to(mrb_state *mrb, mrb_value self)
+{
+ mrb_value *argv;
+ int argc;
+ mrb_value mid, priv;
+ mrb_sym id;
+
+ mrb_get_args(mrb, "*", &argv, &argc);
+ //mrb_scan_args(argc, argv, "11", &mid, &priv);
+ mid = argv[0];
+ if (argc > 1) priv = argv[1];
+ else priv = mrb_nil_value();
+ id = mrb_to_id(mrb, mid);
+ if (basic_obj_respond_to(mrb, self, id, !RTEST(priv)))
+ return mrb_true_value();
+ return mrb_false_value();
+}
+
+/* 15.3.1.3.45 */
+/*
+ * call-seq:
+ * obj.singleton_methods(all=true) -> array
+ *
+ * Returns an array of the names of singleton methods for <i>obj</i>.
+ * If the optional <i>all</i> parameter is true, the list will include
+ * methods in modules included in <i>obj</i>.
+ * Only public and protected singleton methods are returned.
+ *
+ * module Other
+ * def three() end
+ * end
+ *
+ * class Single
+ * def Single.four() end
+ * end
+ *
+ * a = Single.new
+ *
+ * def a.one()
+ * end
+ *
+ * class << a
+ * include Other
+ * def two()
+ * end
+ * end
+ *
+ * Single.singleton_methods #=> [:four]
+ * a.singleton_methods(false) #=> [:two, :one]
+ * a.singleton_methods #=> [:two, :one, :three]
+ */
+mrb_value
+mrb_obj_singleton_methods_m(mrb_state *mrb, mrb_value self)
+{
+ mrb_value *argv;
+ int argc;
+
+ mrb_get_args(mrb, "*", &argv, &argc);
+ return mrb_obj_singleton_methods(mrb, argc, argv, self);
+}
+
+mrb_value mrb_f_sprintf(mrb_state *mrb, mrb_value obj); /* in sprintf.c */
+
+void
+mrb_init_kernel(mrb_state *mrb)
+{
+ struct RClass *krn;
+
+ krn = mrb->kernel_module = mrb_define_module(mrb, "Kernel");
+ mrb_define_class_method(mrb, krn, "'", mrb_f_spawn_m, ARGS_ANY()); /* 15.3.1.2.1 */
+ mrb_define_class_method(mrb, krn, "block_given?", mrb_f_block_given_p_m, ARGS_NONE()); /* 15.3.1.2.2 */
+ mrb_define_class_method(mrb, krn, "eval", mrb_f_eval_m, ARGS_ANY()); /* 15.3.1.2.3 */
+ mrb_define_class_method(mrb, krn, "global_variables", mrb_f_global_variables, ARGS_NONE()); /* 15.3.1.2.4 */
+ mrb_define_class_method(mrb, krn, "iterator?", mrb_f_block_given_p_m, ARGS_NONE()); /* 15.3.1.2.5 */
+ mrb_define_class_method(mrb, krn, "lambda", proc_lambda, ARGS_NONE()); /* 15.3.1.2.6 */
+ mrb_define_class_method(mrb, krn, "local_variables", mrb_f_local_variables, ARGS_NONE()); /* 15.3.1.2.7 */
+ mrb_define_class_method(mrb, krn, "loop", mrb_f_loop, ARGS_NONE()); /* 15.3.1.2.8 */
+; /* 15.3.1.2.11 */
+ mrb_define_class_method(mrb, krn, "raise", mrb_f_raise, ARGS_ANY()); /* 15.3.1.2.12 */
+ mrb_define_class_method(mrb, krn, "require", mrb_f_require, ARGS_REQ(1)); /* 15.3.1.2.13 */
+
+ mrb_define_method(mrb, krn, "singleton_class", mrb_singleton_class, ARGS_NONE());
+
+ mrb_define_method(mrb, krn, "==", mrb_obj_equal_m, ARGS_REQ(1)); /* 15.3.1.3.1 */
+ mrb_define_method(mrb, krn, "!=", mrb_obj_not_equal_m, ARGS_REQ(1));
+ mrb_define_method(mrb, krn, "===", mrb_equal_m, ARGS_REQ(1)); /* 15.3.1.3.2 */
+ mrb_define_method(mrb, krn, "__id__", mrb_obj_id_m, ARGS_NONE()); /* 15.3.1.3.3 */
+ mrb_define_method(mrb, krn, "__send__", mrb_f_send_m, ARGS_ANY()); /* 15.3.1.3.4 */
+ mrb_define_method(mrb, krn, "'", mrb_f_spawn_m, ARGS_ANY()); /* 15.3.1.3.5 *//* "spawn"->"'" */
+ mrb_define_method(mrb, krn, "block_given?", mrb_f_block_given_p_m, ARGS_NONE()); /* 15.3.1.3.6 */
+ mrb_define_method(mrb, krn, "class", mrb_obj_class_m, ARGS_NONE()); /* 15.3.1.3.7 */
+ mrb_define_method(mrb, krn, "clone", mrb_obj_clone, ARGS_NONE()); /* 15.3.1.3.8 */
+ mrb_define_method(mrb, krn, "dup", mrb_obj_dup, ARGS_NONE()); /* 15.3.1.3.9 */
+ mrb_define_method(mrb, krn, "eql?", mrb_obj_equal_m, ARGS_REQ(1)); /* 15.3.1.3.10 */
+ mrb_define_method(mrb, krn, "equal?", mrb_obj_equal_m, ARGS_REQ(1)); /* 15.3.1.3.11 */
+ mrb_define_method(mrb, krn, "eval", mrb_f_eval_m, ARGS_ANY()); /* 15.3.1.3.12 */
+ mrb_define_method(mrb, krn, "extend", mrb_obj_extend_m, ARGS_ANY()); /* 15.3.1.3.13 */
+ mrb_define_method(mrb, krn, "global_variables", mrb_f_global_variables, ARGS_NONE()); /* 15.3.1.3.14 */
+ mrb_define_method(mrb, krn, "hash", mrb_obj_hash, ARGS_NONE()); /* 15.3.1.3.15 */
+ mrb_define_method(mrb, krn, "initialize_copy", mrb_obj_init_copy, ARGS_REQ(1)); /* 15.3.1.3.16 */
+ mrb_define_method(mrb, krn, "inspect", mrb_obj_inspect, ARGS_NONE()); /* 15.3.1.3.17 */
+ mrb_define_method(mrb, krn, "instance_eval", mrb_obj_instance_eval, ARGS_ANY()); /* 15.3.1.3.18 */
+ mrb_define_method(mrb, krn, "instance_of?", rb_obj_is_instance_of, ARGS_REQ(1)); /* 15.3.1.3.19 */
+ mrb_define_method(mrb, krn, "instance_variable_defined?", mrb_obj_ivar_defined, ARGS_REQ(1)); /* 15.3.1.3.20 */
+ mrb_define_method(mrb, krn, "instance_variable_get", mrb_obj_ivar_get, ARGS_REQ(1)); /* 15.3.1.3.21 */
+ mrb_define_method(mrb, krn, "instance_variable_set", mrb_obj_ivar_set, ARGS_REQ(2)); /* 15.3.1.3.22 */
+ mrb_define_method(mrb, krn, "instance_variables", mrb_obj_instance_variables, ARGS_NONE()); /* 15.3.1.3.23 */
+ mrb_define_method(mrb, krn, "is_a?", mrb_obj_is_kind_of_m, ARGS_REQ(1)); /* 15.3.1.3.24 */
+ mrb_define_method(mrb, krn, "iterator?", mrb_f_block_given_p_m, ARGS_NONE()); /* 15.3.1.3.25 */
+ mrb_define_method(mrb, krn, "kind_of?", mrb_obj_is_kind_of_m, ARGS_REQ(1)); /* 15.3.1.3.26 */
+ mrb_define_method(mrb, krn, "lambda", proc_lambda, ARGS_NONE()); /* 15.3.1.3.27 */
+ mrb_define_method(mrb, krn, "local_variables", mrb_f_local_variables, ARGS_NONE()); /* 15.3.1.3.28 */
+ mrb_define_method(mrb, krn, "loop", mrb_f_loop, ARGS_NONE()); /* 15.3.1.3.29 */
+ mrb_define_method(mrb, krn, "methods", mrb_obj_methods_m, ARGS_ANY()); /* 15.3.1.3.31 */
+ mrb_define_method(mrb, krn, "nil?", mrb_false, ARGS_NONE()); /* 15.3.1.3.32 */
+ mrb_define_method(mrb, krn, "object_id", mrb_obj_id_m, ARGS_NONE()); /* 15.3.1.3.33 */
+ mrb_define_method(mrb, krn, "private_methods", mrb_obj_private_methods, ARGS_ANY()); /* 15.3.1.3.36 */
+ mrb_define_method(mrb, krn, "protected_methods", mrb_obj_protected_methods, ARGS_ANY()); /* 15.3.1.3.37 */
+ mrb_define_method(mrb, krn, "public_methods", mrb_obj_public_methods, ARGS_ANY()); /* 15.3.1.3.38 */
+ mrb_define_method(mrb, krn, "raise", mrb_f_raise, ARGS_ANY()); /* 15.3.1.3.40 */
+ mrb_define_method(mrb, krn, "remove_instance_variable", mrb_obj_remove_instance_variable,ARGS_REQ(1)); /* 15.3.1.3.41 */
+ mrb_define_method(mrb, krn, "require", mrb_f_require, ARGS_REQ(1)); /* 15.3.1.3.42 */
+ mrb_define_method(mrb, krn, "respond_to?", obj_respond_to, ARGS_ANY()); /* 15.3.1.3.43 */
+ mrb_define_method(mrb, krn, "send", mrb_f_send_m, ARGS_ANY()); /* 15.3.1.3.44 */
+ mrb_define_method(mrb, krn, "singleton_methods", mrb_obj_singleton_methods_m, ARGS_ANY()); /* 15.3.1.3.45 */
+ mrb_define_method(mrb, krn, "to_s", mrb_any_to_s, ARGS_NONE()); /* 15.3.1.3.46 */
+
+ mrb_define_method(mrb, krn, "sprintf", mrb_f_sprintf, ARGS_ANY()); /* in sprintf.c */
+ mrb_define_method(mrb, krn, "format", mrb_f_sprintf, ARGS_ANY()); /* in sprintf.c */
+
+ mrb_include_module(mrb, mrb->object_class, mrb->kernel_module);
+}