summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/class.c115
-rw-r--r--src/codegen.c3
-rw-r--r--src/hash.c4
-rw-r--r--src/kernel.c2
-rw-r--r--src/math.c5
-rw-r--r--src/string.c4
-rw-r--r--src/time.c2
-rw-r--r--src/variable.c2
-rw-r--r--src/vm.c20
9 files changed, 140 insertions, 17 deletions
diff --git a/src/class.c b/src/class.c
index d95a05789..618a6d1f6 100644
--- a/src/class.c
+++ b/src/class.c
@@ -15,7 +15,7 @@
#include "mruby/array.h"
#include "error.h"
-KHASH_DEFINE(mt, mrb_sym, struct RProc*, 1, kh_int_hash_func, kh_int_hash_equal);
+KHASH_DEFINE(mt, mrb_sym, struct RProc*, 1, kh_int_hash_func, kh_int_hash_equal)
typedef struct fc_result {
mrb_sym name;
@@ -630,7 +630,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
}
break;
default:
- mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalide argument specifier %c", c);
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid argument specifier %c", c);
break;
}
}
@@ -722,6 +722,43 @@ mrb_mod_include(mrb_state *mrb, mrb_value klass)
return klass;
}
+/* 15.2.2.4.28 */
+/*
+ * call-seq:
+ * mod.include?(module) -> true or false
+ *
+ * Returns <code>true</code> if <i>module</i> is included in
+ * <i>mod</i> or one of <i>mod</i>'s ancestors.
+ *
+ * module A
+ * end
+ * class B
+ * include A
+ * end
+ * class C < B
+ * end
+ * B.include?(A) #=> true
+ * C.include?(A) #=> true
+ * A.include?(A) #=> false
+ */
+static mrb_value
+mrb_mod_include_p(mrb_state *mrb, mrb_value mod)
+{
+ mrb_value mod2;
+ struct RClass *c = mrb_class_ptr(mod);
+
+ mrb_get_args(mrb, "o", &mod2);
+ mrb_check_type(mrb, mod2, MRB_TT_MODULE);
+
+ while (c) {
+ if (c->tt == MRB_TT_ICLASS) {
+ if (c->c == mrb_class_ptr(mod2)) return mrb_true_value();
+ }
+ c = c->super;
+ }
+ return mrb_false_value();
+}
+
static mrb_value
mrb_mod_ancestors(mrb_state *mrb, mrb_value self)
{
@@ -770,6 +807,73 @@ mrb_mod_included_modules(mrb_state *mrb, mrb_value self)
return result;
}
+mrb_value class_instance_method_list(mrb_state*, int, mrb_value*, struct RClass*, int);
+
+/* 15.2.2.4.33 */
+/*
+ * call-seq:
+ * mod.instance_methods(include_super=true) -> array
+ *
+ * Returns an array containing the names of the public and protected instance
+ * methods in the receiver. For a module, these are the public and protected methods;
+ * for a class, they are the instance (not singleton) methods. With no
+ * argument, or with an argument that is <code>false</code>, the
+ * instance methods in <i>mod</i> are returned, otherwise the methods
+ * in <i>mod</i> and <i>mod</i>'s superclasses are returned.
+ *
+ * module A
+ * def method1() end
+ * end
+ * class B
+ * def method2() end
+ * end
+ * class C < B
+ * def method3() end
+ * end
+ *
+ * A.instance_methods #=> [:method1]
+ * B.instance_methods(false) #=> [:method2]
+ * C.instance_methods(false) #=> [:method3]
+ * C.instance_methods(true).length #=> 43
+ */
+
+static mrb_value
+mrb_mod_instance_methods(mrb_state *mrb, mrb_value mod)
+{
+ mrb_value *argv;
+ int argc;
+ struct RClass *c = mrb_class_ptr(mod);
+
+ mrb_get_args(mrb, "*", &argv, &argc);
+ return class_instance_method_list(mrb, argc, argv, c, 0);
+}
+
+mrb_value mrb_yield_internal(mrb_state *mrb, mrb_value b, int argc, mrb_value *argv, mrb_value self, struct RClass *c);
+
+/* 15.2.2.4.35 */
+/*
+ * call-seq:
+ * mod.class_eval {| | block } -> obj
+ * mod.module_eval {| | block } -> obj
+ *
+ * Evaluates block in the context of _mod_. This can
+ * be used to add methods to a class. <code>module_eval</code> returns
+ * the result of evaluating its argument.
+ */
+
+mrb_value
+mrb_mod_module_eval(mrb_state *mrb, mrb_value mod)
+{
+ mrb_value a, b;
+ struct RClass *c;
+
+ if (mrb_get_args(mrb, "|S&", &a, &b) == 1) {
+ mrb_raise(mrb, E_NOTIMP_ERROR, "module_eval/class_eval with string not implemented");
+ }
+ c = mrb_class_ptr(mod);
+ return mrb_yield_internal(mrb, b, 0, 0, mod, c);
+}
+
mrb_value
mrb_singleton_class(mrb_state *mrb, mrb_value v)
{
@@ -1400,6 +1504,7 @@ mrb_init_class(mrb_state *mrb)
make_metaclass(mrb, cls);
/* name basic classes */
+ mrb_define_const(mrb, bob, "BasicObject", mrb_obj_value(bob));
mrb_define_const(mrb, obj, "BasicObject", mrb_obj_value(bob));
mrb_define_const(mrb, obj, "Object", mrb_obj_value(obj));
mrb_define_const(mrb, obj, "Module", mrb_obj_value(mod));
@@ -1423,9 +1528,13 @@ mrb_init_class(mrb_state *mrb)
mrb_define_method(mrb, mod, "extend_object", mrb_mod_extend_object, ARGS_REQ(1)); /* 15.2.2.4.25 */
mrb_define_method(mrb, mod, "extended", mrb_bob_init, ARGS_REQ(1)); /* 15.2.2.4.26 */
mrb_define_method(mrb, mod, "include", mrb_mod_include, ARGS_ANY()); /* 15.2.2.4.27 */
+ mrb_define_method(mrb, mod, "include?", mrb_mod_include_p, ARGS_REQ(1)); /* 15.2.2.4.28 */
mrb_define_method(mrb, mod, "append_features", mrb_mod_append_features, ARGS_REQ(1)); /* 15.2.2.4.10 */
- mrb_define_method(mrb, mod, "included", mrb_bob_init, ARGS_REQ(1)); /* 15.2.2.4.29 */
+ mrb_define_method(mrb, mod, "class_eval", mrb_mod_module_eval, ARGS_ANY()); /* 15.2.2.4.15 */
+ mrb_define_method(mrb, mod, "included", mrb_bob_init, ARGS_REQ(1)); /* 15.2.2.4.29 */
mrb_define_method(mrb, mod, "included_modules", mrb_mod_included_modules, ARGS_NONE()); /* 15.2.2.4.30 */
+ mrb_define_method(mrb, mod, "instance_methods", mrb_mod_instance_methods, ARGS_ANY()); /* 15.2.2.4.33 */
+ mrb_define_method(mrb, mod, "module_eval", mrb_mod_module_eval, ARGS_ANY()); /* 15.2.2.4.35 */
mrb_define_method(mrb, mod, "to_s", mrb_mod_to_s, ARGS_NONE());
mrb_define_method(mrb, mod, "inspect", mrb_mod_to_s, ARGS_NONE());
diff --git a/src/codegen.c b/src/codegen.c
index 8015216b7..a6c94d871 100644
--- a/src/codegen.c
+++ b/src/codegen.c
@@ -1412,7 +1412,6 @@ codegen(codegen_scope *s, node *tree, int val)
codegen(s, tree->cdr->cdr->car, VAL);
pop();
gen_assignment(s, tree->car, cursp(), val);
- if (val) pop();
dispatch(s, pos);
break;
}
@@ -1501,7 +1500,7 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_RETURN:
codegen(s, tree, VAL);
pop();
- if (s->loop && s->loop->type != LOOP_NORMAL) {
+ if (s->loop) {
genop(s, MKOP_AB(OP_RETURN, cursp(), OP_R_RETURN));
}
else {
diff --git a/src/hash.c b/src/hash.c
index c74ac837b..c7a419250 100644
--- a/src/hash.c
+++ b/src/hash.c
@@ -29,8 +29,8 @@ mrb_hash_ht_hash_equal(mrb_state *mrb, mrb_value a, mrb_value b)
return mrb_eql(mrb, a, b);
}
-KHASH_DECLARE(ht, mrb_value, mrb_value, 1);
-KHASH_DEFINE (ht, mrb_value, mrb_value, 1, mrb_hash_ht_hash_func, mrb_hash_ht_hash_equal);
+KHASH_DECLARE(ht, mrb_value, mrb_value, 1)
+KHASH_DEFINE (ht, mrb_value, mrb_value, 1, mrb_hash_ht_hash_func, mrb_hash_ht_hash_equal)
static void mrb_hash_modify(mrb_state *mrb, mrb_value hash);
diff --git a/src/kernel.c b/src/kernel.c
index 5fcebc4a9..531c6d9d8 100644
--- a/src/kernel.c
+++ b/src/kernel.c
@@ -717,7 +717,7 @@ method_entry_loop(mrb_state *mrb, struct RClass* klass, mrb_value ary)
}
}
-static mrb_value
+mrb_value
class_instance_method_list(mrb_state *mrb, int argc, mrb_value *argv, struct RClass* klass, int obj)
{
mrb_value ary;
diff --git a/src/math.c b/src/math.c
index 9aae87acd..3e4550946 100644
--- a/src/math.c
+++ b/src/math.c
@@ -51,7 +51,7 @@ erf(double x)
term *= xsqr/j;
sum += term/(2*j+1);
++j;
- } while (fabs(term)/sum > MATH_TOLERANCE);
+ } while (fabs(term/sum) > MATH_TOLERANCE);
return two_sqrtpi*sum;
}
@@ -64,7 +64,8 @@ erfc(double x)
double b = x;
double c = x;
double d = x*x+0.5;
- double q1, q2;
+ double q1;
+ double q2 = b/d;
double n = 1.0;
double t;
if (fabs(x) < 2.2) {
diff --git a/src/string.c b/src/string.c
index 425b79ca7..7ab6e5806 100644
--- a/src/string.c
+++ b/src/string.c
@@ -2511,7 +2511,7 @@ mrb_cstr_to_inum(mrb_state *mrb, const char *str, int base, int badcheck)
return mrb_fixnum_value(result);
}
bad:
- mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalide string for number(%s)", str);
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid string for number(%s)", str);
/* not reached */
return mrb_fixnum_value(0);
}
@@ -2621,7 +2621,7 @@ mrb_cstr_to_dbl(mrb_state *mrb, const char * p, int badcheck)
if (p == end) {
if (badcheck) {
bad:
- mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalide string for float(%s)", p);
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid string for float(%s)", p);
/* not reached */
}
return d;
diff --git a/src/time.c b/src/time.c
index 09ebea78a..c647ef6ce 100644
--- a/src/time.c
+++ b/src/time.c
@@ -395,7 +395,7 @@ mrb_time_yday(mrb_state *mrb, mrb_value self)
tm = (struct mrb_time *)mrb_check_datatype(mrb, self, &mrb_time_type);
if (!tm) return mrb_nil_value();
- return mrb_fixnum_value(tm->datetime.tm_yday);
+ return mrb_fixnum_value(tm->datetime.tm_yday + 1);
}
/* 15.2.19.7.32 */
diff --git a/src/variable.c b/src/variable.c
index 7d583da40..6907a8e2a 100644
--- a/src/variable.c
+++ b/src/variable.c
@@ -256,7 +256,7 @@ iv_free(mrb_state *mrb, iv_tbl *t)
#endif
KHASH_DECLARE(iv, mrb_sym, mrb_value, 1)
-KHASH_DEFINE(iv, mrb_sym, mrb_value, 1, kh_int_hash_func, kh_int_hash_equal);
+KHASH_DEFINE(iv, mrb_sym, mrb_value, 1, kh_int_hash_func, kh_int_hash_equal)
typedef struct iv_tbl {
khash_t(iv) h;
diff --git a/src/vm.c b/src/vm.c
index ebd505366..61274e374 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -151,14 +151,27 @@ uvset(mrb_state *mrb, int up, int idx, mrb_value v)
mrb_write_barrier(mrb, (struct RBasic*)e);
}
+static inline int
+is_strict(mrb_state *mrb, struct REnv *e)
+{
+ int cioff = e->cioff;
+
+ if (cioff >= 0 && mrb->cibase[cioff].proc &&
+ MRB_PROC_STRICT_P(mrb->cibase[cioff].proc)) {
+ return 1;
+ }
+ return 0;
+}
+
struct REnv*
-top_env(struct RProc *proc)
+top_env(mrb_state *mrb, struct RProc *proc)
{
struct REnv *e = proc->env;
+ if (is_strict(mrb, e)) return e;
while (e->c) {
- if (!e) return 0;
e = (struct REnv*)e->c;
+ if (is_strict(mrb, e)) return e;
}
return e;
}
@@ -1165,8 +1178,9 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
break;
case OP_R_RETURN:
if (!proc->env) goto NORMAL_RETURN;
+ if (MRB_PROC_STRICT_P(proc)) goto NORMAL_RETURN;
else {
- struct REnv *e = top_env(proc);
+ struct REnv *e = top_env(mrb, proc);
if (e->cioff < 0) {
localjump_error(mrb, "return");