diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/array.c | 15 | ||||
| -rw-r--r-- | src/cdump.c | 10 | ||||
| -rw-r--r-- | src/class.c | 87 | ||||
| -rw-r--r-- | src/codegen.c | 14 | ||||
| -rw-r--r-- | src/dump.c | 20 | ||||
| -rw-r--r-- | src/etc.c | 181 | ||||
| -rw-r--r-- | src/gc.c | 19 | ||||
| -rw-r--r-- | src/kernel.c | 27 | ||||
| -rw-r--r-- | src/load.c | 4 | ||||
| -rw-r--r-- | src/parse.y | 195 | ||||
| -rw-r--r-- | src/range.c | 77 | ||||
| -rw-r--r-- | src/state.c | 3 | ||||
| -rw-r--r-- | src/string.c | 46 | ||||
| -rw-r--r-- | src/time.c | 3 | ||||
| -rw-r--r-- | src/vm.c | 8 |
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) @@ -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); } } @@ -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; @@ -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; |
