summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/array.c15
-rw-r--r--src/cdump.c10
-rw-r--r--src/class.c87
-rw-r--r--src/codegen.c14
-rw-r--r--src/dump.c20
-rw-r--r--src/etc.c181
-rw-r--r--src/gc.c19
-rw-r--r--src/kernel.c27
-rw-r--r--src/load.c4
-rw-r--r--src/parse.y195
-rw-r--r--src/range.c77
-rw-r--r--src/state.c3
-rw-r--r--src/string.c46
-rw-r--r--src/time.c3
-rw-r--r--src/vm.c8
15 files changed, 411 insertions, 298 deletions
diff --git a/src/array.c b/src/array.c
index 981da7afb..d65a99cc4 100644
--- a/src/array.c
+++ b/src/array.c
@@ -46,8 +46,7 @@ ary_new_capa(mrb_state *mrb, int capa)
}
a = (struct RArray*)mrb_obj_alloc(mrb, MRB_TT_ARRAY, mrb->array_class);
- a->ptr = mrb_malloc(mrb, blen);
- memset(a->ptr, 0, blen);
+ a->ptr = mrb_calloc(mrb, blen, 1);
a->aux.capa = capa;
a->len = 0;
@@ -566,9 +565,11 @@ mrb_ary_set(mrb_state *mrb, mrb_value ary, mrb_int n, mrb_value val) /* rb_ary_s
ary_modify(mrb, a);
/* range check */
- if (n < 0) n += a->len;
if (n < 0) {
- mrb_raise(mrb, E_INDEX_ERROR, "index %ld out of array", n - a->len);
+ n += a->len;
+ if (n < 0) {
+ mrb_raise(mrb, E_INDEX_ERROR, "index %ld out of array", n - a->len);
+ }
}
if (a->len <= (int)n) {
if (a->aux.capa <= (int)n)
@@ -592,9 +593,11 @@ mrb_ary_splice(mrb_state *mrb, mrb_value ary, mrb_int head, mrb_int len, mrb_val
ary_modify(mrb, a);
/* range check */
- if (head < 0) head += a->len;
if (head < 0) {
- mrb_raise(mrb, E_INDEX_ERROR, "index is out of array");
+ head += a->len;
+ if (head < 0) {
+ mrb_raise(mrb, E_INDEX_ERROR, "index is out of array");
+ }
}
tail = head + len;
diff --git a/src/cdump.c b/src/cdump.c
index 0df2bb491..16c1dc8ae 100644
--- a/src/cdump.c
+++ b/src/cdump.c
@@ -112,6 +112,7 @@ make_cdump_irep(mrb_state *mrb, int irep_no, FILE *f)
return MRB_CDUMP_GENERAL_FAILURE;
}
+ SOURCE_CODE0 (" ai = mrb->arena_idx;");
SOURCE_CODE0 (" irep = mrb->irep[idx] = mrb_malloc(mrb, sizeof(mrb_irep));");
SOURCE_CODE0 (" irep->idx = idx++;");
SOURCE_CODE (" irep->flags = %d | MRB_ISEQ_NOFREE;", irep->flags);
@@ -138,7 +139,9 @@ make_cdump_irep(mrb_state *mrb, int irep_no, FILE *f)
switch (irep->pool[n].tt) {
case MRB_TT_FLOAT:
SOURCE_CODE(" irep->pool[%d] = mrb_float_value(%.16e);", n, irep->pool[n].value.f); break;
- case MRB_TT_STRING:
+ case MRB_TT_FIXNUM:
+ SOURCE_CODE(" irep->pool[%d] = mrb_fixnum_value(%d);", n, irep->pool[n].value.i); break;
+ case MRB_TT_STRING:
str_len = str_format_len(irep->pool[n]) + 1;
if ( str_len > buf_len ) {
buf_len = str_len;
@@ -155,6 +158,8 @@ make_cdump_irep(mrb_state *mrb, int irep_no, FILE *f)
}
else
SOURCE_CODE0 (" irep->pool = NULL;");
+ SOURCE_CODE0 (" mrb->irep_len = idx;");
+ SOURCE_CODE0 (" mrb->arena_idx = ai;");
SOURCE_CODE0("");
return MRB_CDUMP_OK;
}
@@ -185,6 +190,7 @@ mrb_cdump_irep(mrb_state *mrb, int n, FILE *f,const char *initname)
SOURCE_CODE0("{");
SOURCE_CODE0(" int n = mrb->irep_len;");
SOURCE_CODE0(" int idx = n;");
+ SOURCE_CODE0(" int ai;");
SOURCE_CODE0(" mrb_irep *irep;");
SOURCE_CODE0("");
SOURCE_CODE (" mrb_add_irep(mrb, idx+%d);", irep_num);
@@ -194,8 +200,6 @@ mrb_cdump_irep(mrb_state *mrb, int n, FILE *f,const char *initname)
return -1;
}
- SOURCE_CODE0(" mrb->irep_len = idx;");
- SOURCE_CODE0("");
SOURCE_CODE0(" mrb_run(mrb, mrb_proc_new(mrb, mrb->irep[n]), mrb_top_self(mrb));");
SOURCE_CODE0("}");
diff --git a/src/class.c b/src/class.c
index b53c18590..9003c3bc5 100644
--- a/src/class.c
+++ b/src/class.c
@@ -641,31 +641,90 @@ boot_defclass(mrb_state *mrb, struct RClass *super)
return c;
}
+static int
+find_in_ancestors(struct RClass *c, struct RClass *m)
+{
+ while(c) {
+ if (c == m || c->mt == m->mt){
+ return 1;
+ }
+ c = c->super;
+ }
+ return 0;
+}
+
void
mrb_include_module(mrb_state *mrb, struct RClass *c, struct RClass *m)
{
- struct RClass *ic;
+ struct RClass *ic, *ins_pos;
- ic = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_ICLASS, mrb->class_class);
- ic->c = m;
- ic->mt = m->mt;
- ic->iv = m->iv;
- ic->super = c->super;
- c->super = ic;
- mrb_field_write_barrier(mrb, (struct RBasic*)c, (struct RBasic*)ic);
+ ins_pos = c;
+ while (m) {
+ if (!find_in_ancestors(c, m)) {
+ ic = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_ICLASS, mrb->class_class);
+ if (m->tt == MRB_TT_ICLASS) {
+ ic->c = m->c;
+ }
+ else {
+ ic->c = m;
+ }
+ ic->mt = m->mt;
+ ic->iv = m->iv;
+ ic->super = ins_pos->super;
+ ins_pos->super = ic;
+ mrb_field_write_barrier(mrb, (struct RBasic*)ins_pos, (struct RBasic*)ic);
+ ins_pos = ic;
+ }
+ m = m->super;
+ }
}
static mrb_value
-mrb_mod_include(mrb_state *mrb, mrb_value klass)
+mrb_mod_append_features(mrb_state *mrb, mrb_value mod)
{
- mrb_value mod;
+ mrb_value klass;
- mrb_get_args(mrb, "o", &mod);
mrb_check_type(mrb, mod, MRB_TT_MODULE);
+ mrb_get_args(mrb, "o", &klass);
mrb_include_module(mrb, mrb_class_ptr(klass), mrb_class_ptr(mod));
return mod;
}
+static mrb_value
+mrb_mod_include(mrb_state *mrb, mrb_value klass)
+{
+ mrb_value *argv;
+ int argc, i;
+
+ mrb_get_args(mrb, "*", &argv, &argc);
+ for (i=0; i<argc; i++) {
+ mrb_check_type(mrb, argv[i], MRB_TT_MODULE);
+ }
+ while (argc--) {
+ mrb_funcall_argv(mrb, argv[argc], "append_features", 1, &klass);
+ mrb_funcall_argv(mrb, argv[argc], "included", 1, &klass);
+ }
+
+ return klass;
+}
+
+static mrb_value
+mrb_mod_included_modules(mrb_state *mrb, mrb_value self)
+{
+ mrb_value result;
+ struct RClass *c = mrb_class_ptr(self);
+
+ result = mrb_ary_new(mrb);
+ while (c) {
+ if (c->tt == MRB_TT_ICLASS) {
+ mrb_ary_push(mrb, result, mrb_obj_value(c->c));
+ }
+ c = c->super;
+ }
+
+ return result;
+}
+
static struct RClass *
mrb_singleton_class_ptr(mrb_state *mrb, struct RClass *c)
{
@@ -1065,6 +1124,7 @@ struct RClass *
mrb_module_new(mrb_state *mrb)
{
struct RClass *m = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_MODULE, mrb->module_class);
+ m->mt = kh_init(mt, mrb);
return m;
}
@@ -1321,7 +1381,10 @@ mrb_init_class(mrb_state *mrb)
mrb_define_method(mrb, cls, "superclass", mrb_class_superclass, ARGS_NONE()); /* 15.2.3.3.4 */
mrb_define_method(mrb, cls, "new", mrb_instance_new, ARGS_ANY()); /* 15.2.3.3.3 */
mrb_define_method(mrb, cls, "inherited", mrb_bob_init, ARGS_REQ(1));
- mrb_define_method(mrb, mod, "include", mrb_mod_include, ARGS_REQ(1)); /* 15.2.2.4.27 */
+ mrb_define_method(mrb, mod, "include", mrb_mod_include, ARGS_ANY()); /* 15.2.2.4.27 */
+ 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, "included_modules", mrb_mod_included_modules, ARGS_NONE()); /* 15.2.2.4.30 */
mrb_define_method(mrb, mod, "to_s", mrb_mod_to_s, ARGS_NONE());
mrb_define_method(mrb, mod, "alias_method", mrb_mod_alias, ARGS_ANY()); /* 15.2.2.4.8 */
diff --git a/src/codegen.c b/src/codegen.c
index 2654fcbe3..3236713e2 100644
--- a/src/codegen.c
+++ b/src/codegen.c
@@ -802,8 +802,10 @@ readint_float(codegen_scope *s, const char *p, int base)
mrb_float f = 0;
int n;
- while (p <= e) {
- char c = tolower(*p);
+ if (*p == '+') p++;
+ while (p < e) {
+ char c = *p;
+ c = tolower((unsigned char)c);
for (n=0; n<base; n++) {
if (mrb_digitmap[n] == c) {
f *= base;
@@ -811,6 +813,9 @@ readint_float(codegen_scope *s, const char *p, int base)
break;
}
}
+ if (n == base) {
+ codegen_error(s, "malformed readint input");
+ }
p++;
}
return f;
@@ -2144,6 +2149,11 @@ codedump(mrb_state *mrb, int n)
mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
GETARG_C(c));
break;
+ case OP_TAILCALL:
+ printf("OP_TAILCALL\tR%d\t:%s\t%d\n", GETARG_A(c),
+ mrb_sym2name(mrb, irep->syms[GETARG_B(c)]),
+ GETARG_C(c));
+ break;
case OP_SUPER:
printf("OP_SUPER\tR%d\t%d\n", GETARG_A(c),
GETARG_C(c));
diff --git a/src/dump.c b/src/dump.c
index bbdd58eee..a720090fa 100644
--- a/src/dump.c
+++ b/src/dump.c
@@ -331,6 +331,7 @@ write_pool_block(mrb_state *mrb, mrb_irep *irep, char *buf, int type)
char *buf_top = buf;
char *char_buf;
uint16_t buf_size =0;
+ int len;
buf_size = MRB_DUMP_DEFAULT_STR_LEN;
if ((char_buf = mrb_malloc(mrb, buf_size)) == 0)
@@ -384,10 +385,12 @@ write_pool_block(mrb_state *mrb, mrb_irep *irep, char *buf, int type)
continue;
}
- buf += uint16_dump((uint16_t)strlen(char_buf), buf, type); /* data length */
+ len = strlen(char_buf);
- memcpy(buf, char_buf, strlen(char_buf));
- buf += strlen(char_buf);
+ buf += uint16_dump((uint16_t)len, buf, type); /* data length */
+
+ memcpy(buf, char_buf, len);
+ buf += len;
}
error_exit:
@@ -457,11 +460,10 @@ calc_crc_section(mrb_state *mrb, mrb_irep *irep, uint16_t *crc, int section)
default: return MRB_DUMP_GENERAL_FAILURE;
}
- if ((buf = mrb_malloc(mrb, buf_size)) == 0)
+ if ((buf = mrb_calloc(mrb, 1, buf_size)) == 0)
return MRB_DUMP_GENERAL_FAILURE;
buf_top = buf;
- memset(buf, 0, buf_size);
switch (section) {
case DUMP_IREP_HEADER: buf += write_irep_header(mrb, irep, buf, type); break;
@@ -595,13 +597,13 @@ dump_irep_record(mrb_state *mrb, int irep_no, FILE* fp, uint32_t *rlen)
if (irep_record_size == 0)
return MRB_DUMP_GENERAL_FAILURE;
- if ((buf = mrb_malloc(mrb, irep_record_size)) == 0)
+ if ((buf = mrb_calloc(mrb, 1, irep_record_size)) == 0)
return MRB_DUMP_GENERAL_FAILURE;
- memset( buf, 0, irep_record_size);
-
- if ((rc = write_irep_record(mrb, irep_no, buf, rlen, DUMP_TYPE_HEX)) != MRB_DUMP_OK)
+ if ((rc = write_irep_record(mrb, irep_no, buf, rlen, DUMP_TYPE_HEX)) != MRB_DUMP_OK) {
+ rc = MRB_DUMP_GENERAL_FAILURE;
goto error_exit;
+ }
if (fwrite(buf, irep_record_size, 1, fp) != 1)
diff --git a/src/etc.c b/src/etc.c
index ac1f79f2f..73cf31087 100644
--- a/src/etc.c
+++ b/src/etc.c
@@ -126,136 +126,65 @@ mrb_block_proc(void)
return mrb_nil_value();//proc_new(mrb_cProc, FALSE);
}
-/*
- * Document-method: __id__
- * Document-method: object_id
- *
- * call-seq:
- * obj.__id__ -> fixnum
- * obj.object_id -> fixnum
- *
- * Returns an integer identifier for <i>obj</i>. The same number will
- * be returned on all calls to <code>id</code> for a given object, and
- * no two active objects will share an id.
- * <code>Object#object_id</code> is a different concept from the
- * <code>:name</code> notation, which returns the symbol id of
- * <code>name</code>. Replaces the deprecated <code>Object#id</code>.
- */
+#include <stdio.h>
+static mrb_int
+float_id(mrb_float f)
+{
+ const char *p = (const char*)&f;
+ int len = sizeof(f);
+ mrb_int id = 0;
-/*
- * 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.
- */
+ while (len--) {
+ id = id*65599 + *p;
+ p++;
+ }
+ id = id + (id>>5);
+
+ return id;
+}
-int
+mrb_int
mrb_obj_id(mrb_value obj)
{
- /*
- * 32-bit mrb_value space
- * MSB ------------------------ LSB
- * false 00000000000000000000000000000000
- * true 00000000000000000000000000000010
- * nil 00000000000000000000000000000100
- * undef 00000000000000000000000000000110
- * symbol ssssssssssssssssssssssss00001110
- * object oooooooooooooooooooooooooooooo00 = 0 (mod sizeof(RVALUE))
- * fixnum fffffffffffffffffffffffffffffff1
- *
- * object_id space
- * LSB
- * false 00000000000000000000000000000000
- * true 00000000000000000000000000000010
- * nil 00000000000000000000000000000100
- * undef 00000000000000000000000000000110
- * symbol 000SSSSSSSSSSSSSSSSSSSSSSSSSSS0 S...S % A = 4 (S...S = s...s * A + 4)
- * object oooooooooooooooooooooooooooooo0 o...o % A = 0
- * fixnum fffffffffffffffffffffffffffffff1 bignum if required
- *
- * where A = sizeof(RVALUE)/4
- *
- * sizeof(RVALUE) is
- * 20 if 32-bit, double is 4-byte aligned
- * 24 if 32-bit, double is 8-byte aligned
- * 40 if 64-bit
- */
- /*
- * 128-bit mrb_value space
- * MSB -------- LSB
- * x86 [0,1] [2,3] [4,5] [6,7] [8,9] [A,B] [C,D] [E,F]
- * 7 6 5 4 3 2 1 0
- * 0123456789ABCDEF 0123456789ABCDEF 0123456789ABCDEF 0123456789ABCDEF 0123456789ABCDEF 0123456789ABCDEF 0123456789ABCDEF 0123456789ABCDEF
- * FEDCBA9876543210 FEDCBA9876543210 FEDCBA9876543210 FEDCBA9876543210 FEDCBA9876543210 FEDCBA9876543210 FEDCBA9876543210 FEDCBA9876543210
- * false 0000000000000000 0000000000000000 xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxx00000001 xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx
- * true 0000000000000001 0000000000000000 xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxx00000010 xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx
- * nil 0000000000000001 0000000000000000 xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxx00000001 xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx
- * undef 0000000000000000 0000000000000000 xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxx00000101 xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx
- * symbol ssssssssssssssss ssssssssssssssss xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxx00000100 xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx
- * object oooooooooooooooo oooooooooooooo00 = 0 (mod sizeof(RVALUE))
- (1)fixnum 0000000000000001 0000000000000000 xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxx00000011 xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx
- * float 0000000000000001 0000000000000000 0000000000000000 0000000000000000 xxxxxxxx00000011 xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx
- * <-- mrb_float --> xxxxxxxx00001101 xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx
- *
- * object_id space
- * LSB
- * false 0000000000000000 0000000000000000
- * true 0000000000000000 0000000000000010
- * nil 0000000000000000 0000000000000100
- * undef 0000000000000000 0000000000000110
- * symbol 000SSSSSSSSSSSS SSSSSSSSSSSSSSS0 S...S % A = 4 (S...S = s...s * A + 4)
- * object ooooooooooooooo ooooooooooooooo0 o...o % A = 0
- * fixnum ffffffffffffffff fffffffffffffff1 bignum if required
- *
- * where A = sizeof(RVALUE)/4
- *
- * sizeof(RVALUE) is
- * 20 if 32-bit, double is 4-byte aligned
- * 24 if 32-bit, double is 8-byte aligned
- * 40 if 64-bit
- */
- /* tt:0_27 */
- switch (mrb_type(obj)) {
- case MRB_TT_FREE:
- return 0; /* not define */
- case MRB_TT_FALSE:
- if (mrb_nil_p(obj))
- return 4;
- return 0;
- case MRB_TT_TRUE:
- return 2;
- case MRB_TT_FIXNUM:
- return mrb_fixnum(obj)*2+1; /* odd number */
- case MRB_TT_SYMBOL:
- return SYM2ID(obj) * 2;
- case MRB_TT_UNDEF:
- return 0; /* not define */
- case MRB_TT_FLOAT:
- return (int)mrb_float(obj)*2; /* even number */
- case MRB_TT_OBJECT:
- case MRB_TT_CLASS:
- case MRB_TT_MODULE:
- case MRB_TT_ICLASS:
- case MRB_TT_SCLASS:
- case MRB_TT_PROC:
- case MRB_TT_ARRAY:
- case MRB_TT_HASH:
- case MRB_TT_STRING:
- case MRB_TT_RANGE:
- case MRB_TT_REGEX:
- case MRB_TT_STRUCT:
- case MRB_TT_EXCEPTION:
- case MRB_TT_MATCH:
- case MRB_TT_FILE:
- case MRB_TT_DATA:
- case MRB_TT_THREAD:
- case MRB_TT_THREADGRP:
- default:
- return mrb_fixnum(obj); /* even number */
+ mrb_int tt = obj.tt;
+
+#define MakeID2(p,t) (((intptr_t)(p))^(t))
+#define MakeID(p) MakeID2(p,tt)
+
+ switch (tt) {
+ case MRB_TT_FREE:
+ case MRB_TT_UNDEF:
+ return MakeID(0); /* not define */
+ case MRB_TT_FALSE:
+ if (mrb_nil_p(obj))
+ return MakeID(1);
+ return MakeID(0);
+ case MRB_TT_TRUE:
+ return MakeID(1);
+ case MRB_TT_SYMBOL:
+ return MakeID(SYM2ID(obj));
+ case MRB_TT_FIXNUM:
+ return MakeID2(float_id((mrb_float)mrb_fixnum(obj)), MRB_TT_FLOAT);
+ case MRB_TT_FLOAT:
+ return MakeID(float_id(mrb_float(obj)));
+ case MRB_TT_STRING:
+ case MRB_TT_OBJECT:
+ case MRB_TT_CLASS:
+ case MRB_TT_MODULE:
+ case MRB_TT_ICLASS:
+ case MRB_TT_SCLASS:
+ case MRB_TT_PROC:
+ case MRB_TT_ARRAY:
+ case MRB_TT_HASH:
+ case MRB_TT_RANGE:
+ case MRB_TT_REGEX:
+ case MRB_TT_STRUCT:
+ case MRB_TT_EXCEPTION:
+ case MRB_TT_MATCH:
+ case MRB_TT_FILE:
+ case MRB_TT_DATA:
+ default:
+ return MakeID(obj.value.p);
}
}
diff --git a/src/gc.c b/src/gc.c
index 22175a958..78d8ee6a9 100644
--- a/src/gc.c
+++ b/src/gc.c
@@ -167,10 +167,17 @@ mrb_malloc(mrb_state *mrb, size_t len)
void*
mrb_calloc(mrb_state *mrb, size_t nelem, size_t len)
{
- void *p = mrb_realloc(mrb, 0, nelem*len);
+ void *p = NULL;
+ size_t size;
+
+ if (nelem <= SIZE_MAX / len) {
+ size = nelem * len;
+ p = mrb_realloc(mrb, 0, size);
+
+ if (p && size > 0)
+ memset(p, 0, size);
+ }
- if (len > 0)
- memset(p, 0, nelem*len);
return p;
}
@@ -239,12 +246,10 @@ unlink_free_heap_page(mrb_state *mrb, struct heap_page *page)
static void
add_heap(mrb_state *mrb)
{
- struct heap_page *page = mrb_malloc(mrb, sizeof(struct heap_page));
+ struct heap_page *page = mrb_calloc(mrb, 1, sizeof(struct heap_page));
RVALUE *p, *e;
struct RBasic *prev = NULL;
- memset(page, 0, sizeof(struct heap_page));
-
for (p = page->objects, e=p+HEAP_PAGE_SIZE; p<e; p++) {
p->as.free.tt = MRB_TT_FREE;
p->as.free.next = prev;
@@ -528,6 +533,7 @@ obj_free(mrb_state *mrb, struct RBasic *obj)
if (d->type->dfree) {
d->type->dfree(mrb, d->data);
}
+ mrb_gc_free_iv(mrb, (struct RObject*)obj);
}
break;
@@ -607,6 +613,7 @@ gc_gray_mark(mrb_state *mrb, struct RBasic *obj)
break;
case MRB_TT_OBJECT:
+ case MRB_TT_DATA:
children += mrb_gc_mark_iv_size(mrb, (struct RObject*)obj);
break;
diff --git a/src/kernel.c b/src/kernel.c
index 605b84124..d230305da 100644
--- a/src/kernel.c
+++ b/src/kernel.c
@@ -207,14 +207,19 @@ mrb_equal_m(mrb_state *mrb, mrb_value self)
/* 15.3.1.3.3 */
/* 15.3.1.3.33 */
/*
+ * Document-method: __id__
+ * Document-method: object_id
+ *
* call-seq:
- * obj.hash -> fixnum
+ * obj.__id__ -> fixnum
+ * obj.object_id -> 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.
+ * Returns an integer identifier for <i>obj</i>. The same number will
+ * be returned on all calls to <code>id</code> for a given object, and
+ * no two active objects will share an id.
+ * <code>Object#object_id</code> is a different concept from the
+ * <code>:name</code> notation, which returns the symbol id of
+ * <code>name</code>. Replaces the deprecated <code>Object#id</code>.
*/
static mrb_value
mrb_obj_id_m(mrb_state *mrb, mrb_value self)
@@ -526,6 +531,16 @@ mrb_obj_extend_m(mrb_state *mrb, mrb_value self)
//mrb_f_global_variables(mrb_state *mrb, mrb_value self)
/* 15.3.1.3.15 */
+/*
+ * 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.
+ */
mrb_value
mrb_obj_hash(mrb_state *mrb, mrb_value self)
{
diff --git a/src/load.c b/src/load.c
index eb9cd119c..c1c0a7eed 100644
--- a/src/load.c
+++ b/src/load.c
@@ -248,12 +248,12 @@ mrb_load_irep(mrb_state *mrb, FILE* fp)
unsigned char hex8[8], hcrc[4];
unsigned char *dst, *rite_dst = NULL;
rite_binary_header bin_header;
- RiteFILE ritefp, *rfp;
+ RiteFILE ritefp = { 0 };
+ RiteFILE *rfp;
if ((mrb == NULL) || (fp == NULL)) {
return MRB_DUMP_INVALID_ARGUMENT;
}
- memset(&ritefp, 0, sizeof(ritefp));
ritefp.fp = fp;
rfp = &ritefp;
diff --git a/src/parse.y b/src/parse.y
index c68bcb0bb..97c2e6d2e 100644
--- a/src/parse.y
+++ b/src/parse.y
@@ -20,6 +20,7 @@
#include "mruby.h"
#include "mruby/compile.h"
+#include "mruby/proc.h"
#include "node.h"
#include "st.h"
@@ -686,7 +687,7 @@ new_float(parser_state *p, const char *s)
// (:str . (s . len))
static node*
-new_str(parser_state *p, const char *s, size_t len)
+new_str(parser_state *p, const char *s, int len)
{
return cons((node*)NODE_STR, cons((node*)strndup(s, len), (node*)len));
}
@@ -2961,7 +2962,7 @@ static void
yyerror(parser_state *p, const char *s)
{
char* c;
- size_t n;
+ int n;
if (! p->capture_errors) {
if (p->filename) {
@@ -2995,7 +2996,7 @@ static void
yywarn(parser_state *p, const char *s)
{
char* c;
- size_t n;
+ int n;
if (! p->capture_errors) {
if (p->filename) {
@@ -3948,7 +3949,7 @@ parser_yylex(parser_state *p)
}
if (!ISXDIGIT(c)) break;
nondigit = 0;
- tokadd(p, c);
+ tokadd(p, tolower(c));
} while ((c = nextc(p)) != -1);
}
pushback(p, c);
@@ -4127,8 +4128,15 @@ parser_yylex(parser_state *p)
}
tokfix(p);
if (is_float) {
- (void)strtod(tok(p), 0); /* just check if float is within range */
- if (errno == ERANGE) {
+ double d;
+ char *endp;
+
+ errno = 0;
+ d = strtod(tok(p), &endp);
+ if (d == 0 && endp == tok(p)) {
+ yywarning_s(p, "corrupted float value %s", tok(p));
+ }
+ else if (errno == ERANGE) {
yywarning_s(p, "float %s out of range", tok(p));
errno = 0;
}
@@ -4668,8 +4676,45 @@ yylex(void *lval, parser_state *p)
return t;
}
+static void
+parser_init_cxt(parser_state *p, mrbc_context *cxt)
+{
+ if (!cxt) return;
+ if (cxt->lineno) p->lineno = cxt->lineno;
+ if (cxt->filename) p->filename = cxt->filename;
+ if (cxt->syms) {
+ int len = cxt->slen;
+
+ p->locals = cons(0,0);
+ while (len--) {
+ local_add_f(p, cxt->syms[len]);
+ }
+ }
+ p->capture_errors = cxt->capture_errors;
+}
+
+static void
+parser_update_cxt(parser_state *p, mrbc_context *cxt)
+{
+ node *n, *n0;
+ int i = 0;
+
+ if (!cxt) return;
+ if ((int)p->tree->car != NODE_SCOPE) return;
+ n0 = n = p->tree->cdr->car;
+ while (n) {
+ i++;
+ n = n->cdr;
+ }
+ cxt->syms = mrb_realloc(p->mrb, cxt->syms, i*sizeof(mrb_sym));
+ cxt->slen = i;
+ for (i=0, n=n0; n; i++,n=n->cdr) {
+ cxt->syms[i] = (mrb_sym)n->car;
+ }
+}
+
void
-mrb_parser_parse(parser_state *p)
+mrb_parser_parse(parser_state *p, mrbc_context *c)
{
node *tree;
@@ -4685,6 +4730,7 @@ mrb_parser_parse(parser_state *p)
p->nerr = p->nwarn = 0;
p->sterm = 0;
+ parser_init_cxt(p, c);
yyparse(p);
tree = p->tree;
if (!tree) {
@@ -4696,9 +4742,7 @@ mrb_parser_parse(parser_state *p)
}
}
else {
- if ((intptr_t)tree->car == NODE_SCOPE) {
- p->locals = cons(tree->cdr->car, 0);
- }
+ parser_update_cxt(p, c);
if (p->begin_tree) {
tree = new_begin(p, p->begin_tree);
append(tree, p->tree);
@@ -4729,7 +4773,6 @@ mrb_parser_new(mrb_state *mrb)
p->in_def = p->in_single = FALSE;
p->capture_errors = 0;
-
p->lineno = 1;
p->column = 0;
#if defined(PARSER_TEST) || defined(PARSER_DEBUG)
@@ -4739,28 +4782,45 @@ mrb_parser_new(mrb_state *mrb)
return p;
}
-const char*
-mrb_parser_filename(parser_state *p, const char *s)
+void
+mrb_parser_free(parser_state *p) {
+ mrb_pool_close(p->pool);
+}
+
+mrbc_context*
+mrbc_context_new(mrb_state *mrb)
{
- if (s) {
- p->filename = strdup(s);
- }
- return p->filename;
+ mrbc_context *c;
+
+ c = mrb_calloc(mrb, 1, sizeof(mrbc_context));
+ return c;
}
-int
-mrb_parser_lineno(struct mrb_parser_state *p, int n)
+void
+mrbc_context_free(mrb_state *mrb, mrbc_context *cxt)
{
- if (n <= 0) {
- return p->lineno;
+ mrb_free(mrb, cxt->syms);
+ mrb_free(mrb, cxt->filename);
+ mrb_free(mrb, cxt);
+}
+
+const char*
+mrbc_filename(mrb_state *mrb, mrbc_context *c, const char *s)
+{
+ if (s) {
+ int len = strlen(s);
+ char *p = mrb_malloc(mrb, len);
+
+ memcpy(p, s, len);
+ if (c->filename) mrb_free(mrb, c->filename);
+ c->filename = p;
+ c->lineno = 1;
}
- p->column = 0;
- p->lineno = n;
- return n;
+ return c->filename;
}
parser_state*
-mrb_parse_file(mrb_state *mrb, FILE *f)
+mrb_parse_file(mrb_state *mrb, FILE *f, mrbc_context *c)
{
parser_state *p;
@@ -4769,12 +4829,12 @@ mrb_parse_file(mrb_state *mrb, FILE *f)
p->s = p->send = NULL;
p->f = f;
- mrb_parser_parse(p);
+ mrb_parser_parse(p, c);
return p;
}
parser_state*
-mrb_parse_nstring(mrb_state *mrb, const char *s, size_t len)
+mrb_parse_nstring(mrb_state *mrb, const char *s, int len, mrbc_context *c)
{
parser_state *p;
@@ -4783,56 +4843,81 @@ mrb_parse_nstring(mrb_state *mrb, const char *s, size_t len)
p->s = s;
p->send = s + len;
- mrb_parser_parse(p);
+ mrb_parser_parse(p, c);
return p;
}
parser_state*
-mrb_parse_string(mrb_state *mrb, const char *s)
+mrb_parse_string(mrb_state *mrb, const char *s, mrbc_context *c)
{
- return mrb_parse_nstring(mrb, s, strlen(s));
+ return mrb_parse_nstring(mrb, s, strlen(s), c);
}
-void parser_dump(mrb_state *mrb, node *tree, int offset);
-
-int
-mrb_compile_file(mrb_state * mrb, FILE *f)
+static mrb_value
+load_exec(mrb_state *mrb, parser_state *p)
{
- parser_state *p;
int n;
- p = mrb_parse_file(mrb, f);
- if (!p) return -1;
- if (!p->tree) return -1;
- if (p->nerr) return -1;
+ if (!p) {
+ mrb_parser_free(p);
+ return mrb_nil_value();
+ }
+ if (p->capture_errors && (!p->tree || p->nerr)) {
+ char buf[256];
+
+ n = snprintf(buf, sizeof(buf), "line %d: %s\n",
+ p->error_buffer[0].lineno, p->error_buffer[0].message);
+ mrb->exc = (struct RObject*)mrb_object(mrb_exc_new(mrb, E_SYNTAX_ERROR, buf, n));
+ mrb_parser_free(p);
+ return mrb_nil_value();
+ }
n = mrb_generate_code(mrb, p->tree);
- mrb_pool_close(p->pool);
+ mrb_parser_free(p);
+ if (n < 0) {
+ mrb->exc = (struct RObject*)mrb_object(mrb_exc_new(mrb, E_SCRIPT_ERROR, "codegen error", 13));
+ return mrb_nil_value();
+ }
+ return mrb_run(mrb, mrb_proc_new(mrb, mrb->irep[n]), mrb_top_self(mrb));
+}
- return n;
+mrb_value
+mrb_load_file_cxt(mrb_state *mrb, FILE *f, mrbc_context *c)
+{
+ return load_exec(mrb, mrb_parse_file(mrb, f, c));
}
-int
-mrb_compile_nstring(mrb_state *mrb, char *s, size_t len)
+mrb_value
+mrb_load_file(mrb_state *mrb, FILE *f)
{
- parser_state *p;
- int n;
+ return mrb_load_file_cxt(mrb, f, NULL);
+}
- p = mrb_parse_nstring(mrb, s, len);
- if (!p) return -1;
- if (!p->tree) return -1;
- if (p->nerr) return -1;
- n = mrb_generate_code(mrb, p->tree);
- mrb_pool_close(p->pool);
+mrb_value
+mrb_load_nstring_cxt(mrb_state *mrb, const char *s, int len, mrbc_context *c)
+{
+ return load_exec(mrb, mrb_parse_nstring(mrb, s, len, c));
+}
- return n;
+mrb_value
+mrb_load_nstring(mrb_state *mrb, const char *s, int len)
+{
+ return mrb_load_nstring_cxt(mrb, s, len, NULL);
}
-int
-mrb_compile_string(mrb_state *mrb, char *s)
+mrb_value
+mrb_load_string_cxt(mrb_state *mrb, const char *s, mrbc_context *c)
+{
+ return load_exec(mrb, mrb_parse_nstring(mrb, s, strlen(s), c));
+}
+
+mrb_value
+mrb_load_string(mrb_state *mrb, const char *s)
{
- return mrb_compile_nstring(mrb, s, strlen(s));
+ return mrb_load_string_cxt(mrb, s, NULL);
}
+void parser_dump(mrb_state *mrb, node *tree, int offset);
+
static void
dump_prefix(int offset)
{
diff --git a/src/range.c b/src/range.c
index 859bb277e..1514313f1 100644
--- a/src/range.c
+++ b/src/range.c
@@ -21,6 +21,30 @@
#define RANGE_CLASS (mrb_class_obj_get(mrb, "Range"))
+static void
+range_check(mrb_state *mrb, mrb_value a, mrb_value b)
+{
+ mrb_value ans;
+
+ switch (mrb_type(a)) {
+ case MRB_TT_FIXNUM:
+ case MRB_TT_FLOAT:
+ switch (mrb_type(b)) {
+ case MRB_TT_FIXNUM:
+ case MRB_TT_FLOAT:
+ return;
+ }
+ }
+
+ mrb_p(mrb, a);
+ mrb_p(mrb, b);
+ ans = mrb_funcall(mrb, a, "<=>", 1, b);
+ if (mrb_nil_p(ans)) {
+ /* can not be compared */
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "bad value for range");
+ }
+}
+
mrb_value
mrb_range_new(mrb_state *mrb, mrb_value beg, mrb_value end, int excl)
{
@@ -28,6 +52,7 @@ mrb_range_new(mrb_state *mrb, mrb_value beg, mrb_value end, int excl)
r = (struct RRange*)mrb_obj_alloc(mrb, MRB_TT_RANGE, RANGE_CLASS);
r->edges = mrb_malloc(mrb, sizeof(struct mrb_range_edges));
+ range_check(mrb, beg, end);
r->edges->beg = beg;
r->edges->end = end;
r->excl = excl;
@@ -82,39 +107,12 @@ mrb_range_excl(mrb_state *mrb, mrb_value range)
return r->excl ? mrb_true_value() : mrb_false_value();
}
-/*
- * call-seq:
- * beg end
- * args[0] <= args[1] => true
- * args[0] > args[1] => false
- */
-static int
-range_check(mrb_state *mrb, mrb_value *args)
-{
- mrb_value ans = mrb_funcall(mrb, args[0], "<=>", 1, args[1]);
- /* beg end
- ans :args[0] < args[1] => -1
- args[0] = args[1] => 0
- args[0] > args[1] => +1 */
- if (mrb_nil_p(ans)) return FALSE;
- //if (mrb_obj_equal(mrb, ans, mrb_fixnum_value(1))) return FALSE;
- if (mrb_fixnum(ans) == 1) return FALSE;
- return TRUE;
-}
-
static void
range_init(mrb_state *mrb, mrb_value range, mrb_value beg, mrb_value end, mrb_int exclude_end)
{
- mrb_value args[2];
struct RRange *r = mrb_range_ptr(range);
- if ((mrb_type(beg) != MRB_TT_FIXNUM) || (mrb_type(end) != MRB_TT_FIXNUM)) {
- args[0] = beg;
- args[1] = end;
- if (!range_check(mrb, args)) {
- printf("range_failed()\n");
- }
- }
+ range_check(mrb, beg, end);
r->excl = exclude_end;
r->edges->beg = beg;
r->edges->end = end;
@@ -166,7 +164,6 @@ mrb_range_eq(mrb_state *mrb, mrb_value range)
if (mrb_obj_equal(mrb, range, obj)) return mrb_true_value();
/* same class? */
- // if (!rb_obj_is_instance_of(obj, rb_obj_class(range)))
if (!mrb_obj_is_instance_of(mrb, obj, mrb_obj_class(mrb, range)))
return mrb_false_value();
@@ -185,41 +182,41 @@ mrb_range_eq(mrb_state *mrb, mrb_value range)
static int
r_le(mrb_state *mrb, mrb_value a, mrb_value b)
{
- //int c;
mrb_value r = mrb_funcall(mrb, a, "<=>", 1, b); /* compare result */
/* output :a < b => -1, a = b => 0, a > b => +1 */
- if (mrb_nil_p(r)) return FALSE;
+ if (mrb_type(r) == MRB_TT_FIXNUM) {
+ int c = mrb_fixnum(r);
+ if (c == 0 || c == -1) return TRUE;
+ }
- if (mrb_obj_equal(mrb, r, mrb_fixnum_value(0))) return TRUE;
- if (mrb_obj_equal(mrb, r, mrb_fixnum_value(-1))) return TRUE;
return FALSE;
}
static int
r_gt(mrb_state *mrb, mrb_value a, mrb_value b)
{
- //int c;
mrb_value r = mrb_funcall(mrb, a, "<=>", 1, b);
/* output :a < b => -1, a = b => 0, a > b => +1 */
- if (mrb_nil_p(r)) return FALSE;
+ if (mrb_type(r) == MRB_TT_FIXNUM) {
+ if (mrb_fixnum(r) == 1) return TRUE;
+ }
- if (mrb_obj_equal(mrb, r, mrb_fixnum_value(1))) return TRUE;
return FALSE;
}
static int
r_ge(mrb_state *mrb, mrb_value a, mrb_value b)
{
- //int c;
mrb_value r = mrb_funcall(mrb, a, "<=>", 1, b); /* compare result */
/* output :a < b => -1, a = b => 0, a > b => +1 */
- if (mrb_nil_p(r)) return FALSE;
+ if (mrb_type(r) == MRB_TT_FIXNUM) {
+ int c = mrb_fixnum(r);
+ if (c == 0 || c == 1) return TRUE;
+ }
- if (mrb_obj_equal(mrb, r, mrb_fixnum_value(0))) return TRUE;
- if (mrb_obj_equal(mrb, r, mrb_fixnum_value(1))) return TRUE;
return FALSE;
}
diff --git a/src/state.c b/src/state.c
index e4729ca70..7f74606ff 100644
--- a/src/state.c
+++ b/src/state.c
@@ -76,8 +76,7 @@ mrb_add_irep(mrb_state *mrb, int idx)
int max = 256;
if (idx > max) max = idx+1;
- mrb->irep = mrb_malloc(mrb, sizeof(mrb_irep*)*max);
- memset(mrb->irep, 0, sizeof(mrb_irep*)*max);
+ mrb->irep = mrb_calloc(mrb, max, sizeof(mrb_irep*));
mrb->irep_capa = max;
}
else if (mrb->irep_capa <= idx) {
diff --git a/src/string.c b/src/string.c
index 8e61e6bb9..b2cdc1212 100644
--- a/src/string.c
+++ b/src/string.c
@@ -1549,10 +1549,17 @@ str_replace(mrb_state *mrb, struct RString *s1, struct RString *s2)
{
if (s2->flags & MRB_STR_SHARED) {
L_SHARE:
+ if (s1->flags & MRB_STR_SHARED){
+ mrb_str_decref(mrb, s1->aux.shared);
+ }
+ else {
+ mrb_free(mrb, s1->ptr);
+ }
s1->ptr = s2->ptr;
s1->len = s2->len;
s1->aux.shared = s2->aux.shared;
s1->flags |= MRB_STR_SHARED;
+ s1->aux.shared->refcnt++;
}
else if (s2->len > STR_REPLACE_SHARED_MIN) {
str_make_shared(mrb, s2);
@@ -1561,6 +1568,7 @@ str_replace(mrb_state *mrb, struct RString *s1, struct RString *s2)
else {
if (s1->flags & MRB_STR_SHARED) {
mrb_str_decref(mrb, s1->aux.shared);
+ s1->flags &= ~MRB_STR_SHARED;
s1->ptr = mrb_malloc(mrb, s2->len+1);
}
else {
@@ -1569,7 +1577,7 @@ str_replace(mrb_state *mrb, struct RString *s1, struct RString *s2)
memcpy(s1->ptr, s2->ptr, s2->len);
s1->ptr[s2->len] = 0;
s1->len = s2->len;
- s2->aux.capa = s2->len;
+ s1->aux.capa = s2->len;
}
return mrb_obj_value(s1);
}
@@ -2373,17 +2381,10 @@ mrb_cstr_to_inum(mrb_state *mrb, const char *str, int base, int badcheck)
#define BDIGIT unsigned int
#define BDIGIT_DBL unsigned long
-// const char *s = str;
char *end;
char sign = 1;
-// char nondigit = 0;
int c;
-// BDIGIT_DBL num;
long len;
-// long blen = 1;
-// long i;
-// mrb_value z;
-// BDIGIT *zds;
unsigned long val;
#undef ISDIGIT
@@ -2500,21 +2501,22 @@ mrb_cstr_to_inum(mrb_state *mrb, const char *str, int base, int badcheck)
}
len *= strlen(str)*sizeof(char);
- val = strtoul((char*)str, &end, base);
+ val = strtoul((char*)str, &end, base);
- if (badcheck) {
- if (end == str) goto bad; /* no number */
- while (*end && ISSPACE(*end)) end++;
- if (*end) goto bad; /* trailing garbage */
- }
+ if (badcheck) {
+ if (end == str) goto bad; /* no number */
+ while (*end && ISSPACE(*end)) end++;
+ if (*end) goto bad; /* trailing garbage */
+ }
- if (sign) return mrb_fixnum_value(val);
- else {
- long result = -(long)val;
- return mrb_fixnum_value(result);
- }
+ if (sign) return mrb_fixnum_value(val);
+ else {
+ long result = -(long)val;
+ return mrb_fixnum_value(result);
+ }
bad:
- printf("Integer");
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "invalide string for number(%s)", str);
+ /* not reached */
return mrb_fixnum_value(0);
}
@@ -2623,8 +2625,8 @@ mrb_cstr_to_dbl(mrb_state *mrb, const char * p, int badcheck)
if (p == end) {
if (badcheck) {
bad:
- //mrb_invalid_str(q, "Float()");
- printf("Float()\n");
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "invalide string for float(%s)", p);
+ /* not reached */
}
return d;
}
diff --git a/src/time.c b/src/time.c
index 3da824e82..45e796069 100644
--- a/src/time.c
+++ b/src/time.c
@@ -239,9 +239,8 @@ time_mktime(mrb_state *mrb, mrb_int ayear, mrb_int amonth, mrb_int aday,
enum mrb_timezone timezone)
{
time_t nowsecs;
- struct tm nowtime;
+ struct tm nowtime = { 0 };
- memset(&nowtime, 0, sizeof(struct tm));
nowtime.tm_year = (int)ayear - 1900;
nowtime.tm_mon = (int)amonth - 1;
nowtime.tm_mday = (int)aday;
diff --git a/src/vm.c b/src/vm.c
index d69081c9c..9ee6b9883 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -28,16 +28,14 @@ static void
stack_init(mrb_state *mrb)
{
/* assert(mrb->stack == NULL); */
- mrb->stbase = mrb_malloc(mrb, sizeof(mrb_value) * STACK_INIT_SIZE);
- memset(mrb->stbase, 0, sizeof(mrb_value) * STACK_INIT_SIZE);
+ mrb->stbase = mrb_calloc(mrb, STACK_INIT_SIZE, sizeof(mrb_value));
mrb->stend = mrb->stbase + STACK_INIT_SIZE;
mrb->stack = mrb->stbase;
/* assert(mrb->ci == NULL); */
- mrb->cibase = mrb_malloc(mrb, sizeof(mrb_callinfo)*CALLINFO_INIT_SIZE);
+ mrb->cibase = mrb_calloc(mrb, CALLINFO_INIT_SIZE, sizeof(mrb_callinfo));
mrb->ciend = mrb->cibase + CALLINFO_INIT_SIZE;
mrb->ci = mrb->cibase;
- memset(mrb->ci, 0, sizeof(mrb_callinfo));
mrb->ci->target_class = mrb->object_class;
}
@@ -1120,7 +1118,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
/* replace callinfo */
- mrb->ci = ci = &mrb->ci[-1];
+ ci = mrb->ci;
ci->mid = mid;
ci->target_class = m->target_class;
ci->argc = n;