summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/mruby.h3
-rw-r--r--include/mruby/variable.h1
-rw-r--r--mrbgems/mruby-symbol-ext/mrblib/symbol.rb51
-rw-r--r--mrbgems/mruby-symbol-ext/test/symbol.rb22
-rw-r--r--mrblib/numeric.rb132
-rw-r--r--src/backtrace.c13
-rw-r--r--src/class.c13
-rw-r--r--src/codegen.c4
-rw-r--r--src/error.c12
-rw-r--r--src/numeric.c114
-rw-r--r--src/variable.c26
-rw-r--r--src/vm.c33
-rw-r--r--test/t/class.rb5
13 files changed, 262 insertions, 167 deletions
diff --git a/include/mruby.h b/include/mruby.h
index d8c04d1fa..b3dc59a08 100644
--- a/include/mruby.h
+++ b/include/mruby.h
@@ -55,7 +55,8 @@ typedef struct {
int stackidx;
int nregs;
int argc;
- mrb_code *pc;
+ mrb_code *pc; /* return address */
+ mrb_code *err; /* error position */
int acc;
struct RClass *target_class;
int ridx;
diff --git a/include/mruby/variable.h b/include/mruby/variable.h
index 2845e0daa..fdee68b29 100644
--- a/include/mruby/variable.h
+++ b/include/mruby/variable.h
@@ -53,6 +53,7 @@ mrb_value mrb_mod_constants(mrb_state *mrb, mrb_value mod);
mrb_value mrb_f_global_variables(mrb_state *mrb, mrb_value self);
mrb_value mrb_gv_get(mrb_state *mrb, mrb_sym sym);
void mrb_gv_set(mrb_state *mrb, mrb_sym sym, mrb_value val);
+void mrb_gv_remove(mrb_state *mrb, mrb_sym sym);
mrb_value mrb_obj_instance_variables(mrb_state*, mrb_value);
mrb_value mrb_obj_iv_inspect(mrb_state*, struct RObject*);
mrb_sym mrb_class_sym(mrb_state *mrb, struct RClass *c, struct RClass *outer);
diff --git a/mrbgems/mruby-symbol-ext/mrblib/symbol.rb b/mrbgems/mruby-symbol-ext/mrblib/symbol.rb
index f716162e8..a4e8ef7a8 100644
--- a/mrbgems/mruby-symbol-ext/mrblib/symbol.rb
+++ b/mrbgems/mruby-symbol-ext/mrblib/symbol.rb
@@ -6,4 +6,55 @@ class Symbol
end
end
+ ##
+ # call-seq:
+ # sym.length -> integer
+ #
+ # Same as <code>sym.to_s.length</code>.
+
+ def length
+ self.to_s.length
+ end
+ alias :size :length
+
+ ##
+ # call-seq:
+ # sym.capitalize -> symbol
+ #
+ # Same as <code>sym.to_s.capitalize.intern</code>.
+
+ def capitalize
+ self.to_s.capitalize.intern
+ end
+
+ ##
+ # call-seq:
+ # sym.downcase -> symbol
+ #
+ # Same as <code>sym.to_s.downcase.intern</code>.
+
+ def downcase
+ self.to_s.downcase.intern
+ end
+
+ ##
+ # call-seq:
+ # sym.upcase -> symbol
+ #
+ # Same as <code>sym.to_s.upcase.intern</code>.
+
+ def upcase
+ self.to_s.upcase.intern
+ end
+
+ #
+ # call-seq:
+ # sym.empty? -> true or false
+ #
+ # Returns that _sym_ is :"" or not.
+
+ def empty?
+ self.to_s.empty?
+ end
+
end
diff --git a/mrbgems/mruby-symbol-ext/test/symbol.rb b/mrbgems/mruby-symbol-ext/test/symbol.rb
index 741315d74..35bb31aef 100644
--- a/mrbgems/mruby-symbol-ext/test/symbol.rb
+++ b/mrbgems/mruby-symbol-ext/test/symbol.rb
@@ -10,3 +10,25 @@ assert('Symbol.all_symbols') do
symbols = Symbol.all_symbols.select{|sym|sym.to_s.include? '__symbol_test'}.sort
assert_equal foo, symbols
end
+
+assert("Symbol#length") do
+ assert_equal 5, :hello.size
+ assert_equal 5, :mruby.length
+end
+
+assert("Symbol#capitalize") do
+ assert_equal :Hello, :hello.capitalize
+ assert_equal :Hello, :HELLO.capitalize
+end
+
+assert("Symbol#downcase") do
+ assert_equal :hello, :hEllO.downcase
+end
+
+assert("Symbol#upcase") do
+ assert_equal :HELLO, :hEllO.upcase
+end
+
+assert("Symbol#empty?") do
+ assert_true :''.empty?
+end
diff --git a/mrblib/numeric.rb b/mrblib/numeric.rb
index daa35c5d6..e567a4299 100644
--- a/mrblib/numeric.rb
+++ b/mrblib/numeric.rb
@@ -1,24 +1,51 @@
##
-# Integer
+# Numeric
#
-# ISO 15.2.8
-class Integer
-
+# ISO 15.2.7
+class Numeric
+ include Comparable
##
# Returns the receiver simply.
#
- # ISO 15.2.8.3.14
- def ceil
+ # ISO 15.2.7.4.1
+ def +@
self
end
##
+ # Returns the receiver's value, negated.
+ #
+ # ISO 15.2.7.4.2
+ def -@
+ 0 - self
+ end
+
+ ##
+ # Returns the absolute value of the receiver.
+ #
+ # ISO 15.2.7.4.3
+ def abs
+ if self < 0
+ -self
+ else
+ self
+ end
+ end
+end
+
+##
+# Integral
+#
+# mruby special - module to share methods between Floats and Integers
+# to make them compatible
+module Integral
+ ##
# Calls the given block once for each Integer
# from +self+ downto +num+.
#
# ISO 15.2.8.3.15
def downto(num, &block)
- i = self
+ i = self.to_i
while(i >= num)
block.call(i)
i -= 1
@@ -27,12 +54,14 @@ class Integer
end
##
- # Returns the receiver simply.
+ # Returns self + 1
#
- # ISO 15.2.8.3.17
- def floor
- self
+ # ISO 15.2.8.3.19
+ def next
+ self + 1
end
+ # ISO 15.2.8.3.21
+ alias succ next
##
# Calls the given block +self+ times.
@@ -48,28 +77,12 @@ class Integer
end
##
- # Returns the receiver simply.
- #
- # ISO 15.2.8.3.24
- def round
- self
- end
-
- ##
- # Returns the receiver simply.
- #
- # ISO 15.2.8.3.26
- def truncate
- self
- end
-
- ##
# Calls the given block once for each Integer
# from +self+ upto +num+.
#
# ISO 15.2.8.3.27
def upto(num, &block)
- i = self
+ i = self.to_i
while(i <= num)
block.call(i)
i += 1
@@ -92,10 +105,63 @@ class Integer
end
##
-# Numeric is comparable
+# Integer
#
-# ISO 15.2.7.3
-module Comparable; end
-class Numeric
- include Comparable
+# ISO 15.2.8
+class Integer
+ include Integral
+ ##
+ # Returns the receiver simply.
+ #
+ # ISO 15.2.8.3.14
+ def ceil
+ self
+ end
+
+ ##
+ # Returns the receiver simply.
+ #
+ # ISO 15.2.8.3.17
+ def floor
+ self
+ end
+
+ ##
+ # Returns the receiver simply.
+ #
+ # ISO 15.2.8.3.24
+ alias round floor
+
+ ##
+ # Returns the receiver simply.
+ #
+ # ISO 15.2.8.3.26
+ alias truncate floor
+end
+
+##
+# Float
+#
+# ISO 15.2.9
+class Float
+ include Integral
+ # mruby special - since mruby integers may be upgraded to floats,
+ # floats should be compatible to integers.
+ def >> other
+ n = self.to_i
+ other.to_i.times {
+ n /= 2
+ }
+ n
+ end
+ def << other
+ n = self.to_i
+ other.to_i.times {
+ n *= 2
+ }
+ n.to_i
+ end
+
+ def divmod(other)
+ end
end
diff --git a/src/backtrace.c b/src/backtrace.c
index 4ad792a5e..54927ec00 100644
--- a/src/backtrace.c
+++ b/src/backtrace.c
@@ -77,18 +77,21 @@ mrb_output_backtrace(mrb_state *mrb, struct RObject *exc, output_stream_func fun
if (MRB_PROC_CFUNC_P(ci->proc)) {
continue;
}
- if(!MRB_PROC_CFUNC_P(ci->proc)) {
+ else {
mrb_irep *irep = ci->proc->body.irep;
mrb_code *pc;
- if (i+1 <= ciidx) {
- pc = mrb->c->cibase[i+1].pc;
+ if (mrb->c->cibase[i].err) {
+ pc = mrb->c->cibase[i].err;
+ }
+ else if (i+1 <= ciidx) {
+ pc = mrb->c->cibase[i+1].pc - 1;
}
else {
pc = (mrb_code*)mrb_cptr(mrb_obj_iv_get(mrb, exc, mrb_intern2(mrb, "lastpc", 6)));
}
- filename = mrb_debug_get_filename(irep, pc - irep->iseq - 1);
- line = mrb_debug_get_line(irep, pc - irep->iseq - 1);
+ filename = mrb_debug_get_filename(irep, pc - irep->iseq);
+ line = mrb_debug_get_line(irep, pc - irep->iseq);
}
if (line == -1) continue;
if (ci->target_class == ci->proc->target_class)
diff --git a/src/class.c b/src/class.c
index 4b8f2de10..2745f9820 100644
--- a/src/class.c
+++ b/src/class.c
@@ -1828,6 +1828,18 @@ mrb_mod_remove_const(mrb_state *mrb, mrb_value mod)
return val;
}
+mrb_value
+mrb_mod_const_missing(mrb_state *mrb, mrb_value mod)
+{
+ mrb_sym sym;
+
+ mrb_get_args(mrb, "n", &sym);
+ mrb_name_error(mrb, sym, "uninitialized constant %S",
+ mrb_sym2str(mrb, sym));
+ /* not reached */
+ return mrb_nil_value();
+}
+
static mrb_value
mrb_mod_s_constants(mrb_state *mrb, mrb_value mod)
{
@@ -1921,6 +1933,7 @@ mrb_init_class(mrb_state *mrb)
mrb_define_method(mrb, mod, "const_set", mrb_mod_const_set, MRB_ARGS_REQ(2)); /* 15.2.2.4.23 */
mrb_define_method(mrb, mod, "constants", mrb_mod_constants, MRB_ARGS_NONE()); /* 15.2.2.4.24 */
mrb_define_method(mrb, mod, "remove_const", mrb_mod_remove_const, MRB_ARGS_REQ(1)); /* 15.2.2.4.40 */
+ mrb_define_method(mrb, mod, "const_missing", mrb_mod_const_missing, MRB_ARGS_REQ(1));
mrb_define_method(mrb, mod, "define_method", mod_define_method, MRB_ARGS_REQ(1));
mrb_define_method(mrb, mod, "class_variables", mrb_mod_class_variables, MRB_ARGS_NONE()); /* 15.2.2.4.19 */
mrb_define_method(mrb, mod, "===", mrb_mod_eqq, MRB_ARGS_REQ(1));
diff --git a/src/codegen.c b/src/codegen.c
index bb479842c..578fb96ac 100644
--- a/src/codegen.c
+++ b/src/codegen.c
@@ -646,7 +646,9 @@ scope_body(codegen_scope *s, node *tree)
genop(scope, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL));
}
else {
- genop_peep(scope, MKOP_AB(OP_RETURN, scope->sp, OP_R_NORMAL), NOVAL);
+ pop();
+ genop_peep(scope, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL);
+ push();
}
}
scope_finish(scope);
diff --git a/src/error.c b/src/error.c
index 4ce2b4ade..10ba6170f 100644
--- a/src/error.c
+++ b/src/error.c
@@ -194,14 +194,16 @@ exc_debug_info(mrb_state *mrb, struct RObject *exc)
mrb_code *pc = ci->pc;
mrb_obj_iv_set(mrb, exc, mrb_intern2(mrb, "ciidx", 5), mrb_fixnum_value(ci - mrb->c->cibase));
- ci--;
while (ci >= mrb->c->cibase) {
- if (ci->proc && !MRB_PROC_CFUNC_P(ci->proc)) {
+ mrb_code *err = ci->err;
+
+ if (!err && pc) err = pc - 1;
+ if (err && ci->proc && !MRB_PROC_CFUNC_P(ci->proc)) {
mrb_irep *irep = ci->proc->body.irep;
- int32_t const line = mrb_debug_get_line(irep, pc - irep->iseq - 1);
- char const* file = mrb_debug_get_filename(irep, pc - irep->iseq - 1);
- if(line != -1 && file) {
+ int32_t const line = mrb_debug_get_line(irep, err - irep->iseq);
+ char const* file = mrb_debug_get_filename(irep, err - irep->iseq);
+ if (line != -1 && file) {
mrb_obj_iv_set(mrb, exc, mrb_intern2(mrb, "file", 4), mrb_str_new_cstr(mrb, file));
mrb_obj_iv_set(mrb, exc, mrb_intern2(mrb, "line", 4), mrb_fixnum_value(line));
return;
diff --git a/src/numeric.c b/src/numeric.c
index c309abf89..ccb67bcc3 100644
--- a/src/numeric.c
+++ b/src/numeric.c
@@ -42,38 +42,6 @@ mrb_to_flo(mrb_state *mrb, mrb_value val)
}
/*
- * call-seq:
- * +num -> num
- *
- * Unary Plus---Returns the receiver's value.
- */
-
-static mrb_value
-num_uplus(mrb_state *mrb, mrb_value num)
-{
- return num;
-}
-
-/*
- * call-seq:
- * -num -> numeric
- *
- * Unary Minus---Returns the receiver's value, negated.
- */
-
-static mrb_value
-num_uminus(mrb_state *mrb, mrb_value num)
-{
- return mrb_float_value(mrb, (mrb_float)0 - mrb_to_flo(mrb, num));
-}
-
-static mrb_value
-fix_uminus(mrb_state *mrb, mrb_value num)
-{
- return mrb_fixnum_value(0 - mrb_fixnum(num));
-}
-
-/*
* call-seq:
*
* num ** other -> num
@@ -131,27 +99,6 @@ num_div(mrb_state *mrb, mrb_value x)
return mrb_float_value(mrb, mrb_to_flo(mrb, x) / y);
}
-/*
- * call-seq:
- * num.abs -> numeric
- * num.magnitude -> numeric
- *
- * Returns the absolute value of <i>num</i>.
- *
- * 12.abs #=> 12
- * (-34.56).abs #=> 34.56
- * -34.56.abs #=> 34.56
- */
-
-static mrb_value
-num_abs(mrb_state *mrb, mrb_value num)
-{
- if (mrb_to_flo(mrb, num) < 0) {
- return num_uminus(mrb, num);
- }
- return num;
-}
-
/********************************************************************
*
* Document-class: Float
@@ -695,42 +642,6 @@ int_to_i(mrb_state *mrb, mrb_value num)
return num;
}
-/* 15.2.8.3.21 */
-/*
- * call-seq:
- * fixnum.next -> integer
- * fixnum.succ -> integer
- *
- * Returns the <code>Integer</code> equal to <i>int</i> + 1.
- *
- * 1.next #=> 2
- * (-1).next #=> 0
- */
-
-static mrb_value
-fix_succ(mrb_state *mrb, mrb_value num)
-{
- return mrb_fixnum_value(mrb_fixnum(num)+1);
-}
-
-/* 15.2.8.3.19 */
-/*
- * call-seq:
- * int.next -> integer
- * int.succ -> integer
- *
- * Returns the <code>Integer</code> equal to <i>int</i> + 1.
- *
- * 1.next #=> 2
- * (-1).next #=> 0
- */
-static mrb_value
-int_succ(mrb_state *mrb, mrb_value num)
-{
- if (mrb_fixnum_p(num)) return fix_succ(mrb, num);
- return mrb_funcall(mrb, num, "+", 1, mrb_fixnum_value(1));
-}
-
#define SQRT_INT_MAX ((mrb_int)1<<((sizeof(mrb_int)*CHAR_BIT-1)/2))
/*tests if N*N would overflow*/
#define FIT_SQRT_INT(n) (((n)<SQRT_INT_MAX)&&((n)>=-SQRT_INT_MAX))
@@ -873,6 +784,21 @@ fix_divmod(mrb_state *mrb, mrb_value x)
}
}
+static mrb_value
+flo_divmod(mrb_state *mrb, mrb_value x)
+{
+ mrb_value y;
+ mrb_float div, mod;
+ mrb_value a, b;
+
+ mrb_get_args(mrb, "o", &y);
+
+ flodivmod(mrb, mrb_float(x), mrb_to_flo(mrb, y), &div, &mod);
+ a = mrb_float_value(mrb, (mrb_int)div);
+ b = mrb_float_value(mrb, mod);
+ return mrb_assoc_new(mrb, a, b);
+}
+
/* 15.2.8.3.7 */
/*
* call-seq:
@@ -1359,14 +1285,10 @@ mrb_init_numeric(mrb_state *mrb)
/* Numeric Class */
numeric = mrb_define_class(mrb, "Numeric", mrb->object_class);
- mrb_include_module(mrb, numeric, mrb_class_get(mrb, "Comparable"));
- mrb_define_method(mrb, numeric, "+@", num_uplus, MRB_ARGS_REQ(1)); /* 15.2.7.4.1 */
- mrb_define_method(mrb, numeric, "-@", num_uminus, MRB_ARGS_REQ(1)); /* 15.2.7.4.2 */
mrb_define_method(mrb, numeric, "**", num_pow, MRB_ARGS_REQ(1));
mrb_define_method(mrb, numeric, "/", num_div, MRB_ARGS_REQ(1)); /* 15.2.8.3.4 */
mrb_define_method(mrb, numeric, "quo", num_div, MRB_ARGS_REQ(1)); /* 15.2.7.4.5 (x) */
- mrb_define_method(mrb, numeric, "abs", num_abs, MRB_ARGS_NONE()); /* 15.2.7.4.3 */
mrb_define_method(mrb, numeric, "<=>", num_cmp, MRB_ARGS_REQ(1)); /* 15.2.9.3.6 */
/* Integer Class */
@@ -1374,11 +1296,10 @@ mrb_init_numeric(mrb_state *mrb)
mrb_undef_class_method(mrb, integer, "new");
mrb_define_method(mrb, integer, "to_i", int_to_i, MRB_ARGS_NONE()); /* 15.2.8.3.24 */
mrb_define_method(mrb, integer, "to_int", int_to_i, MRB_ARGS_NONE());
- fixnum = mrb->fixnum_class = mrb_define_class(mrb, "Fixnum", integer);
+ fixnum = mrb->fixnum_class = mrb_define_class(mrb, "Fixnum", integer);
mrb_define_method(mrb, fixnum, "+", fix_plus, MRB_ARGS_REQ(1)); /* 15.2.8.3.1 */
mrb_define_method(mrb, fixnum, "-", fix_minus, MRB_ARGS_REQ(1)); /* 15.2.8.3.2 */
- mrb_define_method(mrb, fixnum, "-@", fix_uminus, MRB_ARGS_REQ(1)); /* 15.2.7.4.2 */
mrb_define_method(mrb, fixnum, "*", fix_mul, MRB_ARGS_REQ(1)); /* 15.2.8.3.3 */
mrb_define_method(mrb, fixnum, "%", fix_mod, MRB_ARGS_REQ(1)); /* 15.2.8.3.5 */
mrb_define_method(mrb, fixnum, "==", fix_equal, MRB_ARGS_REQ(1)); /* 15.2.8.3.7 */
@@ -1390,8 +1311,6 @@ mrb_init_numeric(mrb_state *mrb)
mrb_define_method(mrb, fixnum, ">>", fix_rshift, MRB_ARGS_REQ(1)); /* 15.2.8.3.13 */
mrb_define_method(mrb, fixnum, "eql?", num_eql, MRB_ARGS_REQ(1)); /* 15.2.8.3.16 */
mrb_define_method(mrb, fixnum, "hash", flo_hash, MRB_ARGS_NONE()); /* 15.2.8.3.18 */
- mrb_define_method(mrb, fixnum, "next", int_succ, MRB_ARGS_NONE()); /* 15.2.8.3.19 */
- mrb_define_method(mrb, fixnum, "succ", fix_succ, MRB_ARGS_NONE()); /* 15.2.8.3.21 */
mrb_define_method(mrb, fixnum, "to_f", fix_to_f, MRB_ARGS_NONE()); /* 15.2.8.3.23 */
mrb_define_method(mrb, fixnum, "to_s", fix_to_s, MRB_ARGS_NONE()); /* 15.2.8.3.25 */
mrb_define_method(mrb, fixnum, "inspect", fix_to_s, MRB_ARGS_NONE());
@@ -1414,6 +1333,7 @@ mrb_init_numeric(mrb_state *mrb)
mrb_define_method(mrb, fl, "to_i", flo_truncate, MRB_ARGS_NONE()); /* 15.2.9.3.14 */
mrb_define_method(mrb, fl, "to_int", flo_truncate, MRB_ARGS_NONE());
mrb_define_method(mrb, fl, "truncate", flo_truncate, MRB_ARGS_NONE()); /* 15.2.9.3.15 */
+ mrb_define_method(mrb, fl, "divmod", flo_divmod, MRB_ARGS_REQ(1));
mrb_define_method(mrb, fl, "to_s", flo_to_s, MRB_ARGS_NONE()); /* 15.2.9.3.16(x) */
mrb_define_method(mrb, fl, "inspect", flo_to_s, MRB_ARGS_NONE());
diff --git a/src/variable.c b/src/variable.c
index f2a474201..ffad3dad3 100644
--- a/src/variable.c
+++ b/src/variable.c
@@ -867,7 +867,7 @@ const_get(mrb_state *mrb, struct RClass *base, mrb_sym sym)
mrb_value v;
iv_tbl *t;
mrb_bool retry = 0;
- mrb_sym cm;
+ mrb_value name;
L_RETRY:
while (c) {
@@ -883,19 +883,8 @@ L_RETRY:
retry = 1;
goto L_RETRY;
}
- c = base;
- cm = mrb_intern2(mrb, "const_missing", 13);
- while (c) {
- if (mrb_respond_to(mrb, mrb_obj_value(c), cm)) {
- mrb_value name = mrb_symbol_value(sym);
- return mrb_funcall_argv(mrb, mrb_obj_value(c), cm, 1, &name);
- }
- c = c->super;
- }
- mrb_name_error(mrb, sym, "uninitialized constant %S",
- mrb_sym2str(mrb, sym));
- /* not reached */
- return mrb_nil_value();
+ name = mrb_symbol_value(sym);
+ return mrb_funcall_argv(mrb, mrb_obj_value(base), mrb_intern2(mrb, "const_missing", 13), 1, &name);
}
mrb_value
@@ -1031,6 +1020,15 @@ mrb_gv_set(mrb_state *mrb, mrb_sym sym, mrb_value v)
iv_put(mrb, t, sym, v);
}
+void
+mrb_gv_remove(mrb_state *mrb, mrb_sym sym)
+{
+ if (!mrb->globals) {
+ return;
+ }
+ iv_del(mrb, mrb->globals, sym, NULL);
+}
+
static int
gv_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p)
{
diff --git a/src/vm.c b/src/vm.c
index 3047c9360..a08565d55 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -75,7 +75,12 @@ stack_clear(mrb_value *from, size_t count)
const mrb_value mrb_value_zero = { { 0 } };
while (count-- > 0) {
+#ifndef MRB_NAN_BOXING
*from++ = mrb_value_zero;
+#else
+ SET_NIL_VALUE(*from);
+ from++;
+#endif
}
}
@@ -156,15 +161,7 @@ stack_extend(mrb_state *mrb, int room, int keep)
}
if (room > keep) {
-#ifndef MRB_NAN_BOXING
stack_clear(&(mrb->c->stack[keep]), room - keep);
-#else
- struct mrb_context *c = mrb->c;
- int i;
- for (i=keep; i<room; i++) {
- SET_NIL_VALUE(c->stack[i]);
- }
-#endif
}
}
@@ -229,6 +226,8 @@ cipush(mrb_state *mrb)
ci->eidx = eidx;
ci->ridx = ridx;
ci->env = 0;
+ ci->pc = 0;
+
return ci;
}
@@ -512,8 +511,9 @@ argnum_error(mrb_state *mrb, int num)
mrb->exc = mrb_obj_ptr(exc);
}
+#define ERR_PC_HOOK(mrb, pc) mrb->c->ci->err = pc;
#ifdef ENABLE_DEBUG
-#define CODE_FETCH_HOOK(mrb, irep, pc, regs) if ((mrb)->code_fetch_hook) (mrb)->code_fetch_hook((mrb), (irep), (pc), (regs));
+#define CODE_FETCH_HOOK(mrb, irep, pc, regs) if ((mrb)->code_fetch_hook) (mrb)->code_fetch_hook((mrb), (irep), (pc), (regs));
#else
#define CODE_FETCH_HOOK(mrb, irep, pc, regs)
#endif
@@ -596,6 +596,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
stack_init(mrb);
}
stack_extend(mrb, irep->nregs, irep->nregs);
+ mrb->c->ci->err = pc;
mrb->c->ci->proc = proc;
mrb->c->ci->nregs = irep->nregs + 1;
regs = mrb->c->stack;
@@ -687,6 +688,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
CASE(OP_GETCV) {
/* A B R(A) := ivget(Sym(B)) */
+ ERR_PC_HOOK(mrb, pc);
regs[GETARG_A(i)] = mrb_vm_cv_get(mrb, syms[GETARG_Bx(i)]);
NEXT;
}
@@ -699,7 +701,12 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
CASE(OP_GETCONST) {
/* A B R(A) := constget(Sym(B)) */
- regs[GETARG_A(i)] = mrb_vm_const_get(mrb, syms[GETARG_Bx(i)]);
+ mrb_value val;
+
+ ERR_PC_HOOK(mrb, pc);
+ val = mrb_vm_const_get(mrb, syms[GETARG_Bx(i)]);
+ regs = mrb->c->stack;
+ regs[GETARG_A(i)] = val;
NEXT;
}
@@ -711,9 +718,13 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
CASE(OP_GETMCNST) {
/* A B C R(A) := R(C)::Sym(B) */
+ mrb_value val;
int a = GETARG_A(i);
- regs[a] = mrb_const_get(mrb, regs[a], syms[GETARG_Bx(i)]);
+ ERR_PC_HOOK(mrb, pc);
+ val = mrb_const_get(mrb, regs[a], syms[GETARG_Bx(i)]);
+ regs = mrb->c->stack;
+ regs[a] = val;
NEXT;
}
diff --git a/test/t/class.rb b/test/t/class.rb
index 3dea2152f..403a95f10 100644
--- a/test/t/class.rb
+++ b/test/t/class.rb
@@ -222,6 +222,11 @@ assert('Class new') do
assert_equal(Class, Class.new.class)
end
+assert('class to return the last value') do
+ m = class C; :m end
+ assert_equal(m, :m)
+end
+
assert('Class#inherited') do
class Foo
@@subclass_name = nil