diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/array.c | 72 | ||||
| -rw-r--r-- | src/class.c | 127 | ||||
| -rw-r--r-- | src/codegen.c | 138 | ||||
| -rw-r--r-- | src/crc.c | 2 | ||||
| -rw-r--r-- | src/dump.c | 5 | ||||
| -rw-r--r-- | src/error.c | 93 | ||||
| -rw-r--r-- | src/gc.c | 52 | ||||
| -rw-r--r-- | src/hash.c | 47 | ||||
| -rw-r--r-- | src/init.c | 4 | ||||
| -rw-r--r-- | src/kernel.c | 104 | ||||
| -rw-r--r-- | src/keywords | 78 | ||||
| -rw-r--r-- | src/lex.def | 92 | ||||
| -rw-r--r-- | src/load.c | 3 | ||||
| -rw-r--r-- | src/node.h | 5 | ||||
| -rw-r--r-- | src/numeric.c | 157 | ||||
| -rw-r--r-- | src/object.c | 19 | ||||
| -rw-r--r-- | src/opcode.h | 25 | ||||
| -rw-r--r-- | src/parse.y | 1907 | ||||
| -rw-r--r-- | src/print.c | 23 | ||||
| -rw-r--r-- | src/range.c | 95 | ||||
| -rw-r--r-- | src/state.c | 9 | ||||
| -rw-r--r-- | src/string.c | 242 | ||||
| -rw-r--r-- | src/symbol.c | 208 | ||||
| -rw-r--r-- | src/value_array.h | 27 | ||||
| -rw-r--r-- | src/variable.c | 81 | ||||
| -rw-r--r-- | src/vm.c | 326 |
26 files changed, 2145 insertions, 1796 deletions
diff --git a/src/array.c b/src/array.c index 5d7b0e690..ba289997f 100644 --- a/src/array.c +++ b/src/array.c @@ -9,6 +9,7 @@ #include <string.h> #include "mruby/string.h" #include "mruby/class.h" +#include "value_array.h" /* SIZE_MAX is not supported by VC++. */ #ifndef SIZE_MAX @@ -301,7 +302,7 @@ mrb_ary_cmp(mrb_state *mrb, mrb_value ary1) a1 = RARRAY(ary1); a2 = RARRAY(ary2); if (a1->len == a2->len && a1->ptr == a2->ptr) return mrb_fixnum_value(0); else { - mrb_sym cmp = mrb_intern(mrb, "<=>"); + mrb_sym cmp = mrb_intern2(mrb, "<=>", 3); len = RARRAY_LEN(ary1); if (len > RARRAY_LEN(ary2)) { @@ -519,7 +520,7 @@ mrb_ary_unshift(mrb_state *mrb, mrb_value self, mrb_value item) ary_modify(mrb, a); if (a->aux.capa < a->len + 1) ary_expand_capa(mrb, a, a->len + 1); - memmove(a->ptr + 1, a->ptr, sizeof(mrb_value)*a->len); + value_move(a->ptr + 1, a->ptr, a->len); a->ptr[0] = item; } a->len++; @@ -546,7 +547,7 @@ mrb_ary_unshift_m(mrb_state *mrb, mrb_value self) if (len == 0) return self; if (a->aux.capa < a->len + len) ary_expand_capa(mrb, a, a->len + len); - memmove(a->ptr + len, a->ptr, sizeof(mrb_value)*a->len); + value_move(a->ptr + len, a->ptr, a->len); } array_copy(a->ptr, vals, len); a->len += len; @@ -631,7 +632,7 @@ mrb_ary_splice(mrb_state *mrb, mrb_value ary, mrb_int head, mrb_int len, mrb_val ary_fill_with_nil(a->ptr + a->len, (int)(head - a->len)); } else if (head < a->len) { - memmove(a->ptr + head + argc, a->ptr + tail, sizeof(mrb_value)*(a->len - tail)); + value_move(a->ptr + head + argc, a->ptr + tail, a->len - tail); } for(i = 0; i < argc; i++) { @@ -702,6 +703,7 @@ mrb_ary_aget(mrb_state *mrb, mrb_value self) default: mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments"); + break; } return mrb_nil_value(); /* dummy to avoid warning : not reach here */ @@ -877,7 +879,7 @@ mrb_ary_empty_p(mrb_state *mrb, mrb_value self) { struct RArray *a = mrb_ary_ptr(self); - return ((a->len == 0)? mrb_true_value(): mrb_false_value()); + return mrb_bool_value(a->len == 0); } mrb_value @@ -917,7 +919,7 @@ inspect_ary(mrb_state *mrb, mrb_value ary, mrb_value list) mrb_str_buf_cat(mrb, arystr, head, sizeof(head)); for(i=0; i<RARRAY_LEN(ary); i++) { - mrb_int ai = mrb_gc_arena_save(mrb); + int ai = mrb_gc_arena_save(mrb); if (i > 0) { mrb_str_buf_cat(mrb, arystr, sep, sizeof(sep)); @@ -1058,31 +1060,39 @@ static mrb_value mrb_ary_equal(mrb_state *mrb, mrb_value ary1) { mrb_value ary2; + mrb_bool equal_p; mrb_get_args(mrb, "o", &ary2); - if (mrb_obj_equal(mrb, ary1, ary2)) return mrb_true_value(); - if (mrb_special_const_p(ary2)) return mrb_false_value(); - if (!mrb_array_p(ary2)) { - if (!mrb_respond_to(mrb, ary2, mrb_intern(mrb, "to_ary"))) { - return mrb_false_value(); - } - if (mrb_equal(mrb, ary2, ary1)){ - return mrb_true_value(); + if (mrb_obj_equal(mrb, ary1, ary2)) { + equal_p = 1; + } + else if (mrb_special_const_p(ary2)) { + equal_p = 0; + } + else if (!mrb_array_p(ary2)) { + if (!mrb_respond_to(mrb, ary2, mrb_intern2(mrb, "to_ary", 6))) { + equal_p = 0; } else { - return mrb_false_value(); + equal_p = mrb_equal(mrb, ary2, ary1); } } - if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return mrb_false_value(); + else if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) { + equal_p = 0; + } else { mrb_int i; + equal_p = 1; for (i=0; i<RARRAY_LEN(ary1); i++) { - if (!mrb_equal(mrb, ary_elt(ary1, i), ary_elt(ary2, i))) - return mrb_false_value(); + if (!mrb_equal(mrb, ary_elt(ary1, i), ary_elt(ary2, i))) { + equal_p = 0; + break; + } } - return mrb_true_value(); } + + return mrb_bool_value(equal_p); } /* 15.2.12.5.34 (x) */ @@ -1098,20 +1108,30 @@ static mrb_value mrb_ary_eql(mrb_state *mrb, mrb_value ary1) { mrb_value ary2; + mrb_bool eql_p; mrb_get_args(mrb, "o", &ary2); - if (mrb_obj_equal(mrb, ary1, ary2)) return mrb_true_value(); - if (!mrb_array_p(ary2)) return mrb_false_value(); - if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return mrb_false_value(); + if (mrb_obj_equal(mrb, ary1, ary2)) { + eql_p = 1; + } + else if (!mrb_array_p(ary2)) { + eql_p = 0; + } + else if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) { + eql_p = 0; + } else { mrb_int i; - + eql_p = 1; for (i=0; i<RARRAY_LEN(ary1); i++) { - if (!mrb_eql(mrb, ary_elt(ary1, i), ary_elt(ary2, i))) - return mrb_false_value(); + if (!mrb_eql(mrb, ary_elt(ary1, i), ary_elt(ary2, i))) { + eql_p = 0; + break; + } } - return mrb_true_value(); } + + return mrb_bool_value(eql_p); } void diff --git a/src/class.c b/src/class.c index a3defc2ae..c421376b8 100644 --- a/src/class.c +++ b/src/class.c @@ -7,6 +7,7 @@ #include "mruby.h" #include <stdarg.h> #include <ctype.h> +#include <string.h> #include "mruby/class.h" #include "mruby/proc.h" #include "mruby/string.h" @@ -53,7 +54,7 @@ void mrb_name_class(mrb_state *mrb, struct RClass *c, mrb_sym name) { mrb_obj_iv_set(mrb, (struct RObject*)c, - mrb_intern(mrb, "__classid__"), mrb_symbol_value(name)); + mrb_intern2(mrb, "__classid__", 11), mrb_symbol_value(name)); } #define make_metaclass(mrb, c) prepare_singleton_class((mrb), (struct RBasic*)(c)) @@ -87,7 +88,7 @@ prepare_singleton_class(mrb_state *mrb, struct RBasic *o) o->c = sc; mrb_field_write_barrier(mrb, (struct RBasic*)o, (struct RBasic*)sc); mrb_field_write_barrier(mrb, (struct RBasic*)sc, (struct RBasic*)o); - mrb_obj_iv_set(mrb, (struct RObject*)sc, mrb_intern(mrb, "__attached__"), mrb_obj_value(o)); + mrb_obj_iv_set(mrb, (struct RObject*)sc, mrb_intern2(mrb, "__attached__", 12), mrb_obj_value(o)); } struct RClass* @@ -114,7 +115,7 @@ setup_class(mrb_state *mrb, mrb_value outer, struct RClass *c, mrb_sym id) mrb_name_class(mrb, c, id); mrb_const_set(mrb, outer, id, mrb_obj_value(c)); mrb_obj_iv_set(mrb, (struct RObject*)c, - mrb_intern(mrb, "__outer__"), outer); + mrb_intern2(mrb, "__outer__", 9), outer); } struct RClass* @@ -122,7 +123,7 @@ mrb_class_outer_module(mrb_state *mrb, struct RClass *c) { mrb_value outer; - outer = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern(mrb, "__outer__")); + outer = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern2(mrb, "__outer__", 9)); if (mrb_nil_p(outer)) return 0; return mrb_class_ptr(outer); } @@ -203,6 +204,12 @@ mrb_vm_define_class(mrb_state *mrb, mrb_value outer, mrb_value super, mrb_sym id return c; } +int +mrb_class_defined(mrb_state *mrb, const char *name) +{ + return mrb_const_defined(mrb, mrb_obj_value(mrb->object_class), mrb_intern(mrb, name)); +} + static struct RClass * class_from_sym(mrb_state *mrb, struct RClass *klass, mrb_sym id) { @@ -290,17 +297,19 @@ mrb_define_method_raw(mrb_state *mrb, struct RClass *c, mrb_sym mid, struct RPro } void -mrb_define_method_id(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_func_t func, int aspec) +mrb_define_method_id(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_func_t func, mrb_aspec aspec) { struct RProc *p; + int ai = mrb_gc_arena_save(mrb); p = mrb_proc_new_cfunc(mrb, func); p->target_class = c; mrb_define_method_raw(mrb, c, mid, p); + mrb_gc_arena_restore(mrb, ai); } void -mrb_define_method(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t func, int aspec) +mrb_define_method(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t func, mrb_aspec aspec) { mrb_define_method_id(mrb, c, mrb_intern(mrb, name), func, aspec); } @@ -400,6 +409,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) if (argc <= i && !opt) { mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments"); } + break; } switch (c) { @@ -912,26 +922,26 @@ mrb_singleton_class(mrb_state *mrb, mrb_value v) default: break; } - obj = mrb_object(v); + obj = mrb_basic_ptr(v); prepare_singleton_class(mrb, obj); return mrb_obj_value(obj->c); } void -mrb_define_singleton_method(mrb_state *mrb, struct RObject *o, const char *name, mrb_func_t func, int aspec) +mrb_define_singleton_method(mrb_state *mrb, struct RObject *o, const char *name, mrb_func_t func, mrb_aspec aspec) { prepare_singleton_class(mrb, (struct RBasic*)o); mrb_define_method_id(mrb, o->c, mrb_intern(mrb, name), func, aspec); } void -mrb_define_class_method(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t func, int aspec) +mrb_define_class_method(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t func, mrb_aspec aspec) { mrb_define_singleton_method(mrb, (struct RObject*)c, name, func, aspec); } void -mrb_define_module_function(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t func, int aspec) +mrb_define_module_function(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t func, mrb_aspec aspec) { mrb_define_class_method(mrb, c, name, func, aspec); mrb_define_method(mrb, c, name, func, aspec); @@ -1080,9 +1090,7 @@ mrb_bob_init(mrb_state *mrb, mrb_value cv) static mrb_value mrb_bob_not(mrb_state *mrb, mrb_value cv) { - if (mrb_test(cv)) - return mrb_false_value(); - return mrb_true_value(); + return mrb_bool_value(!mrb_test(cv)); } /* 15.3.1.3.30 */ @@ -1130,8 +1138,13 @@ mrb_bob_missing(mrb_state *mrb, mrb_value mod) mrb_raise(mrb, E_TYPE_ERROR, "name should be a symbol"); } - inspect = mrb_funcall(mrb, mod, "inspect", 0); - if (RSTRING_LEN(inspect) > 64) { + if (mrb_respond_to(mrb,mod,mrb_intern2(mrb,"inspect",7))){ + inspect = mrb_funcall(mrb, mod, "inspect", 0); + if (RSTRING_LEN(inspect) > 64) { + inspect = mrb_any_to_s(mrb, mod); + } + } + else { inspect = mrb_any_to_s(mrb, mod); } @@ -1176,9 +1189,10 @@ mrb_class_path(mrb_state *mrb, struct RClass *c) { mrb_value path; const char *name; - int len; + size_t len; + mrb_sym classpath = mrb_intern2(mrb, "__classpath__", 13); - path = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern(mrb, "__classpath__")); + path = mrb_obj_iv_get(mrb, (struct RObject*)c, classpath); if (mrb_nil_p(path)) { struct RClass *outer = mrb_class_outer_module(mrb, c); mrb_sym sym = mrb_class_sym(mrb, c, outer); @@ -1195,7 +1209,7 @@ mrb_class_path(mrb_state *mrb, struct RClass *c) name = mrb_sym2name_len(mrb, sym, &len); path = mrb_str_new(mrb, name, len); } - mrb_obj_iv_set(mrb, (struct RObject*)c, mrb_intern(mrb, "__classpath__"), path); + mrb_obj_iv_set(mrb, (struct RObject*)c, classpath, path); } return path; } @@ -1214,10 +1228,9 @@ mrb_class_name(mrb_state *mrb, struct RClass* c) { mrb_value path = mrb_class_path(mrb, c); if (mrb_nil_p(path)) { - char buf[32]; - - snprintf(buf, 32, "#<Class:%p>", c); - path = mrb_str_new_cstr(mrb, buf); + path = mrb_str_new(mrb, "#<Class:", 8); + mrb_str_concat(mrb, path, mrb_ptr_to_str(mrb, c)); + mrb_str_cat(mrb, path, ">", 1); } return mrb_str_ptr(path)->ptr; } @@ -1336,51 +1349,54 @@ mrb_define_alias(mrb_state *mrb, struct RClass *klass, const char *name1, const static mrb_value mrb_mod_to_s(mrb_state *mrb, mrb_value klass) { + mrb_value str; + if (mrb_type(klass) == MRB_TT_SCLASS) { - mrb_value s = mrb_str_new(mrb, "#<", 2); - mrb_value v = mrb_iv_get(mrb, klass, mrb_intern(mrb, "__attached__")); + mrb_value v = mrb_iv_get(mrb, klass, mrb_intern2(mrb, "__attached__", 12)); + + str = mrb_str_new(mrb, "#<Class:", 8); - mrb_str_cat2(mrb, s, "Class:"); switch (mrb_type(v)) { case MRB_TT_CLASS: case MRB_TT_MODULE: case MRB_TT_SCLASS: - mrb_str_append(mrb, s, mrb_inspect(mrb, v)); + mrb_str_append(mrb, str, mrb_inspect(mrb, v)); break; default: - mrb_str_append(mrb, s, mrb_any_to_s(mrb, v)); + mrb_str_append(mrb, str, mrb_any_to_s(mrb, v)); break; } - mrb_str_cat2(mrb, s, ">"); - - return s; + mrb_str_cat(mrb, str, ">", 1); } else { + str = mrb_str_buf_new(mrb, 32); struct RClass *c = mrb_class_ptr(klass); - const char *cn = mrb_class_name(mrb, c); - - if (!cn) { - char buf[256]; - int n = 0; + mrb_value path = mrb_class_path(mrb, c); + if (mrb_nil_p(path)) { switch (mrb_type(klass)) { case MRB_TT_CLASS: - n = snprintf(buf, sizeof(buf), "#<Class:%p>", c); + mrb_str_cat(mrb, str, "#<Class:", 8); break; case MRB_TT_MODULE: - n = snprintf(buf, sizeof(buf), "#<Module:%p>", c); + mrb_str_cat(mrb, str, "#<Module:", 9); break; default: + /* Shouldn't be happened? */ + mrb_str_cat(mrb, str, "#<??????:", 9); break; } - return mrb_str_dup(mrb, mrb_str_new(mrb, buf, n)); + mrb_str_concat(mrb, str, mrb_ptr_to_str(mrb, c)); + mrb_str_cat(mrb, str, ">", 1); } else { - return mrb_str_dup(mrb, mrb_str_new_cstr(mrb, cn)); + str = path; } } + + return str; } mrb_value @@ -1453,7 +1469,7 @@ static void check_cv_name(mrb_state *mrb, mrb_sym id) { const char *s; - int len; + size_t len; s = mrb_sym2name_len(mrb, id, &len); if (len < 3 || !(s[0] == '@' && s[1] == '@')) { @@ -1480,12 +1496,12 @@ static mrb_value mrb_mod_cvar_defined(mrb_state *mrb, mrb_value mod) { mrb_sym id; + mrb_bool defined_p; mrb_get_args(mrb, "n", &id); check_cv_name(mrb, id); - if(mrb_cv_defined(mrb, mod, id)) - return mrb_true_value(); - return mrb_false_value(); + defined_p = mrb_cv_defined(mrb, mod, id); + return mrb_bool_value(defined_p); } /* 15.2.2.4.17 */ @@ -1621,12 +1637,11 @@ static mrb_value mrb_mod_method_defined(mrb_state *mrb, mrb_value mod) { mrb_sym id; + mrb_bool method_defined_p; mrb_get_args(mrb, "n", &id); - if (mrb_obj_respond_to(mrb_class_ptr(mod), id)) { - return mrb_true_value(); - } - return mrb_false_value(); + method_defined_p = mrb_obj_respond_to(mrb_class_ptr(mod), id); + return mrb_bool_value(method_defined_p); } static void @@ -1675,7 +1690,7 @@ static void check_const_name(mrb_state *mrb, mrb_sym id) { const char *s; - int len; + size_t len; s = mrb_sym2name_len(mrb, id, &len); if (len < 1 || !ISUPPER(*s)) { @@ -1687,13 +1702,13 @@ mrb_value mrb_mod_const_defined(mrb_state *mrb, mrb_value mod) { mrb_sym id; + mrb_bool const_defined_p; mrb_get_args(mrb, "n", &id); check_const_name(mrb, id); - if(mrb_const_defined(mrb, mod, id)) { - return mrb_true_value(); - } - return mrb_false_value(); + const_defined_p = mrb_const_defined(mrb, mod, id); + + return mrb_bool_value(const_defined_p); } mrb_value @@ -1737,11 +1752,12 @@ static mrb_value mrb_mod_eqq(mrb_state *mrb, mrb_value mod) { mrb_value obj; + mrb_bool eqq; mrb_get_args(mrb, "o", &obj); - if (!mrb_obj_is_kind_of(mrb, obj, mrb_class_ptr(mod))) - return mrb_false_value(); - return mrb_true_value(); + eqq = mrb_obj_is_kind_of(mrb, obj, mrb_class_ptr(mod)); + + return mrb_bool_value(eqq); } void @@ -1789,6 +1805,7 @@ mrb_init_class(mrb_state *mrb) 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_SET_INSTANCE_TT(mod, MRB_TT_MODULE); mrb_define_method(mrb, mod, "class_variable_defined?", mrb_mod_cvar_defined, ARGS_REQ(1)); /* 15.2.2.4.16 */ mrb_define_method(mrb, mod, "class_variable_get", mrb_mod_cvar_get, ARGS_REQ(1)); /* 15.2.2.4.17 */ mrb_define_method(mrb, mod, "class_variable_set", mrb_mod_cvar_set, ARGS_REQ(2)); /* 15.2.2.4.18 */ diff --git a/src/codegen.c b/src/codegen.c index ed44f1792..5b86c90a9 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -4,8 +4,6 @@ ** See Copyright Notice in mruby.h */ -#define CODEGEN_DUMP - #include "mruby.h" #include "mruby/string.h" #include "mruby/irep.h" @@ -49,7 +47,7 @@ typedef struct scope { int pc; int lastlabel; int ainfo:15; - int mscope:1; + mrb_bool mscope:1; struct loopinfo *loop; int ensure_level; @@ -379,6 +377,7 @@ dispatch(codegen_scope *s, int pc) fprintf(stderr, "bug: dispatch on non JMP op\n"); #endif scope_error(s); + break; } s->iseq[pc] = MKOP_AsBx(c, GETARG_A(i), diff); } @@ -540,11 +539,11 @@ for_body(codegen_scope *s, node *tree) // generate loop variable n2 = tree->car; if (n2->car && !n2->car->cdr && !n2->cdr) { - genop(s, MKOP_Ax(OP_ENTER, 1<<18)); + genop(s, MKOP_Ax(OP_ENTER, 0x40000)); gen_assignment(s, n2->car->car, 1, NOVAL); } else { - genop(s, MKOP_Ax(OP_ENTER, 1<<18)); + genop(s, MKOP_Ax(OP_ENTER, 0x40000)); gen_vmassignment(s, n2, 1, VAL); } codegen(s, tree->cdr->cdr->car, VAL); @@ -559,7 +558,7 @@ for_body(codegen_scope *s, node *tree) s = prev; genop(s, MKOP_Abc(OP_LAMBDA, cursp(), idx - base, OP_L_BLOCK)); pop(); - idx = new_msym(s, mrb_intern(s->mrb, "each")); + idx = new_msym(s, mrb_intern2(s->mrb, "each", 4)); genop(s, MKOP_ABC(OP_SENDB, cursp(), idx, 0)); } @@ -579,7 +578,8 @@ lambda_body(codegen_scope *s, node *tree, int blk) } tree = tree->cdr; if (tree->car) { - int ma, oa, ra, pa, ka, kd, ba, a; + int32_t a; + int ma, oa, ra, pa, ka, kd, ba; int pos, i; node *n, *opt; @@ -594,8 +594,8 @@ lambda_body(codegen_scope *s, node *tree, int blk) ka = kd = 0; ba = tree->car->cdr->cdr->cdr->cdr ? 1 : 0; - a = ((ma & 0x1f) << 18) - | ((oa & 0x1f) << 13) + a = ((int32_t)(ma & 0x1f) << 18) + | ((int32_t)(oa & 0x1f) << 13) | ((ra & 1) << 12) | ((pa & 0x1f) << 7) | ((ka & 0x1f) << 2) @@ -690,7 +690,7 @@ static mrb_sym attrsym(codegen_scope *s, mrb_sym a) { const char *name; - int len; + size_t len; char *name2; name = mrb_sym2name_len(s->mrb, a, &len); @@ -789,7 +789,7 @@ gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val) } pop_n(n+1); { - int len; + size_t len; const char *name = mrb_sym2name_len(s->mrb, sym, &len); if (!noop && len == 1 && name[0] == '+') { @@ -955,6 +955,68 @@ gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val) } static void +gen_send_intern(codegen_scope *s) +{ + pop(); + genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern2(s->mrb, "intern", 6)), 0)); + push(); +} +static void +gen_literal_array(codegen_scope *s, node *tree, int sym, int val) +{ + if (val) { + int i = 0, j = 0; + + while (tree) { + switch ((intptr_t)tree->car->car) { + case NODE_STR: + if ((tree->cdr == NULL) && ((intptr_t)tree->car->cdr->cdr == 0)) + break; + /* fall through */ + case NODE_BEGIN: + codegen(s, tree->car, VAL); + ++j; + break; + + case NODE_LITERAL_DELIM: + if (j > 0) { + j = 0; + ++i; + if (sym) + gen_send_intern(s); + } + break; + } + if (j >= 2) { + pop(); pop(); + genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL); + push(); + j = 1; + } + tree = tree->cdr; + } + if (j > 0) { + j = 0; + ++i; + if (sym) + gen_send_intern(s); + } + pop_n(i); + genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), i)); + push(); + } + else { + while (tree) { + switch ((intptr_t)tree->car->car) { + case NODE_BEGIN: case NODE_BLOCK: + codegen(s, tree->car, NOVAL); + } + tree = tree->cdr; + } + } +} + +static void raise_error(codegen_scope *s, const char *msg) { int idx = new_lit(s, mrb_str_new_cstr(s->mrb, msg)); @@ -1088,12 +1150,12 @@ codegen(codegen_scope *s, node *tree, int val) codegen(s, n4->car, VAL); } else { - genop(s, MKOP_ABx(OP_GETCONST, cursp(), new_msym(s, mrb_intern(s->mrb, "StandardError")))); + genop(s, MKOP_ABx(OP_GETCONST, cursp(), new_msym(s, mrb_intern2(s->mrb, "StandardError", 13)))); push(); } genop(s, MKOP_AB(OP_MOVE, cursp(), exc)); pop(); - genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern(s->mrb, "===")), 1)); + genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern2(s->mrb, "===", 3)), 1)); tmp = new_label(s); genop(s, MKOP_AsBx(OP_JMPIF, cursp(), pos2)); pos2 = tmp; @@ -1297,7 +1359,7 @@ codegen(codegen_scope *s, node *tree, int val) if (head) { genop(s, MKOP_AB(OP_MOVE, cursp(), head)); pop(); - genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern(s->mrb, "===")), 1)); + genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern2(s->mrb, "===", 3)), 1)); } else { pop(); @@ -1491,7 +1553,7 @@ codegen(codegen_scope *s, node *tree, int val) case NODE_OP_ASGN: { mrb_sym sym = sym(tree->cdr->car); - int len; + size_t len; const char *name = mrb_sym2name_len(s->mrb, sym, &len); int idx; @@ -1638,7 +1700,7 @@ codegen(codegen_scope *s, node *tree, int val) } pop_n(n+1); if (sendv) n = CALL_MAXARGS; - genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern(s->mrb, "call")), n)); + genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern2(s->mrb, "call", 4)), n)); if (val) push(); } break; @@ -1905,7 +1967,7 @@ codegen(codegen_scope *s, node *tree, int val) default: { - int sym = new_msym(s, mrb_intern(s->mrb, "-")); + int sym = new_msym(s, mrb_intern2(s->mrb, "-", 1)); genop(s, MKOP_ABx(OP_LOADI, cursp(), 0)); push(); @@ -1932,9 +1994,7 @@ codegen(codegen_scope *s, node *tree, int val) break; case NODE_HEREDOC: - /*if(tree == NULL){printf("heredoc error 1\n");exit(11);}*/ tree = ((struct mrb_parser_heredoc_info *)tree)->doc; - /*if(tree == NULL){printf("heredoc error 2\n");exit(12);}*/ /* fall through */ case NODE_DSTR: if (val) { @@ -1962,6 +2022,34 @@ codegen(codegen_scope *s, node *tree, int val) } break; + case NODE_WORDS: + gen_literal_array(s, tree, FALSE, val); + break; + + case NODE_SYMBOLS: + gen_literal_array(s, tree, TRUE, val); + break; + + case NODE_XSTR: + if (val) { + char *p = (char*)tree->car; + size_t len = (intptr_t)tree->cdr; + int ai = mrb_gc_arena_save(s->mrb); + int sym = new_sym(s, mrb_intern2(s->mrb, "Kernel", 6)); + int off = new_lit(s, mrb_str_new(s->mrb, p, len)); + + genop(s, MKOP_A(OP_OCLASS, cursp())); + genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym)); + push(); + genop(s, MKOP_ABx(OP_STRING, cursp(), off)); + pop(); + sym = new_sym(s, mrb_intern2(s->mrb, "`", 1)); + genop(s, MKOP_ABC(OP_SEND, cursp(), sym, 1)); + mrb_gc_arena_restore(s->mrb, ai); + push(); + } + break; + case NODE_REGX: if (val) { char *p1 = (char*)tree->car; @@ -1983,7 +2071,7 @@ codegen(codegen_scope *s, node *tree, int val) pop(); } pop(); - sym = new_sym(s, mrb_intern(s->mrb, "compile")); + sym = new_sym(s, mrb_intern2(s->mrb, "compile", 7)); genop(s, MKOP_ABC(OP_SEND, cursp(), sym, argc)); mrb_gc_arena_restore(s->mrb, ai); push(); @@ -2031,7 +2119,7 @@ codegen(codegen_scope *s, node *tree, int val) pop(); } pop(); - sym = new_sym(s, mrb_intern(s->mrb, "compile")); + sym = new_sym(s, mrb_intern2(s->mrb, "compile", 7)); genop(s, MKOP_ABC(OP_SEND, cursp(), sym, argc)); mrb_gc_arena_restore(s->mrb, ai); push(); @@ -2060,9 +2148,7 @@ codegen(codegen_scope *s, node *tree, int val) case NODE_DSYM: codegen(s, tree, val); if (val) { - pop(); - genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern(s->mrb, "intern")), 0)); - push(); + gen_send_intern(s); } break; @@ -2098,7 +2184,7 @@ codegen(codegen_scope *s, node *tree, int val) { int a = new_msym(s, sym(tree->car)); int b = new_msym(s, sym(tree->cdr)); - int c = new_msym(s, mrb_intern(s->mrb, "alias_method")); + int c = new_msym(s, mrb_intern2(s->mrb, "alias_method", 12)); genop(s, MKOP_A(OP_TCLASS, cursp())); push(); @@ -2117,7 +2203,7 @@ codegen(codegen_scope *s, node *tree, int val) case NODE_UNDEF: { - int undef = new_msym(s, mrb_intern(s->mrb, "undef_method")); + int undef = new_msym(s, mrb_intern2(s->mrb, "undef_method", 12)); int num = 0; node *t = tree; @@ -13,7 +13,7 @@ // carry #define CRC_16_CCITT 0x11021ul //x^16+x^12+x^5+1 #define CRC_XOR_PATTERN (CRC_16_CCITT << 8) -#define CRC_CARRY_BIT (1 << 24) +#define CRC_CARRY_BIT (0x01000000) uint16_t calc_crc_16_ccitt(unsigned char *src, int nbytes) diff --git a/src/dump.c b/src/dump.c index ba5a69a56..9666f7562 100644 --- a/src/dump.c +++ b/src/dump.c @@ -279,7 +279,7 @@ get_syms_block_size(mrb_state *mrb, mrb_irep *irep, int type) size += DUMP_SIZE(MRB_DUMP_SIZE_OF_SHORT, type); /* snl(n) */ if (irep->syms[sym_no] != 0) { - int len; + size_t len; name = mrb_sym2name_len(mrb, irep->syms[sym_no], &len); nlen = str_dump_len((char*)name, len, type); @@ -421,9 +421,10 @@ write_syms_block(mrb_state *mrb, mrb_irep *irep, char *buf, int type) uint16_t nlen =0; if (irep->syms[sym_no] != 0) { - int len; + size_t len; name = mrb_sym2name_len(mrb, irep->syms[sym_no], &len); + if (len > UINT16_MAX) goto error_exit; nlen = str_dump_len((char*)name, len, type); if ( nlen > buf_size - 1) { buf_size = nlen + 1; diff --git a/src/error.c b/src/error.c index ed30173bc..f46887465 100644 --- a/src/error.c +++ b/src/error.c @@ -5,7 +5,9 @@ */ #include "mruby.h" +#include <errno.h> #include <stdarg.h> +#include <stdlib.h> #include <setjmp.h> #include <string.h> #include "error.h" @@ -42,7 +44,7 @@ exc_initialize(mrb_state *mrb, mrb_value exc) mrb_value mesg; if (mrb_get_args(mrb, "|o", &mesg) == 1) { - mrb_iv_set(mrb, exc, mrb_intern(mrb, "mesg"), mesg); + mrb_iv_set(mrb, exc, mrb_intern2(mrb, "mesg", 4), mesg); } return exc; } @@ -71,7 +73,7 @@ exc_exception(mrb_state *mrb, mrb_value self) if (argc == 0) return self; if (mrb_obj_equal(mrb, self, a)) return self; exc = mrb_obj_clone(mrb, self); - mrb_iv_set(mrb, exc, mrb_intern(mrb, "mesg"), a); + mrb_iv_set(mrb, exc, mrb_intern2(mrb, "mesg", 4), a); return exc; } @@ -87,9 +89,9 @@ exc_exception(mrb_state *mrb, mrb_value self) static mrb_value exc_to_s(mrb_state *mrb, mrb_value exc) { - mrb_value mesg = mrb_attr_get(mrb, exc, mrb_intern(mrb, "mesg")); + mrb_value mesg = mrb_attr_get(mrb, exc, mrb_intern2(mrb, "mesg", 4)); - if (mrb_nil_p(mesg)) return mrb_str_new2(mrb, mrb_obj_classname(mrb, exc)); + if (mrb_nil_p(mesg)) return mrb_str_new_cstr(mrb, mrb_obj_classname(mrb, exc)); return mesg; } @@ -121,32 +123,32 @@ exc_inspect(mrb_state *mrb, mrb_value exc) { mrb_value str, mesg, file, line; - mesg = mrb_attr_get(mrb, exc, mrb_intern(mrb, "mesg")); - file = mrb_attr_get(mrb, exc, mrb_intern(mrb, "file")); - line = mrb_attr_get(mrb, exc, mrb_intern(mrb, "line")); + mesg = mrb_attr_get(mrb, exc, mrb_intern2(mrb, "mesg", 4)); + file = mrb_attr_get(mrb, exc, mrb_intern2(mrb, "file", 4)); + line = mrb_attr_get(mrb, exc, mrb_intern2(mrb, "line", 4)); if (!mrb_nil_p(file) && !mrb_nil_p(line)) { str = file; - mrb_str_cat2(mrb, str, ":"); + mrb_str_cat(mrb, str, ":", 1); mrb_str_append(mrb, str, line); - mrb_str_cat2(mrb, str, ": "); + mrb_str_cat(mrb, str, ": ", 2); if (!mrb_nil_p(mesg) && RSTRING_LEN(mesg) > 0) { mrb_str_append(mrb, str, mesg); - mrb_str_cat2(mrb, str, " ("); + mrb_str_cat(mrb, str, " (", 2); } - mrb_str_cat2(mrb, str, mrb_obj_classname(mrb, exc)); + mrb_str_cat_cstr(mrb, str, mrb_obj_classname(mrb, exc)); if (!mrb_nil_p(mesg) && RSTRING_LEN(mesg) > 0) { - mrb_str_cat2(mrb, str, ")"); + mrb_str_cat(mrb, str, ")", 1); } } else { - str = mrb_str_new2(mrb, mrb_obj_classname(mrb, exc)); + str = mrb_str_new_cstr(mrb, mrb_obj_classname(mrb, exc)); if (!mrb_nil_p(mesg) && RSTRING_LEN(mesg) > 0) { - mrb_str_cat2(mrb, str, ": "); + mrb_str_cat(mrb, str, ": ", 2); mrb_str_append(mrb, str, mesg); } else { - mrb_str_cat2(mrb, str, ": "); - mrb_str_cat2(mrb, str, mrb_obj_classname(mrb, exc)); + mrb_str_cat(mrb, str, ": ", 2); + mrb_str_cat_cstr(mrb, str, mrb_obj_classname(mrb, exc)); } } return str; @@ -158,25 +160,29 @@ exc_equal(mrb_state *mrb, mrb_value exc) { mrb_value obj; mrb_value mesg; - mrb_sym id_mesg = mrb_intern(mrb, "mesg"); + mrb_bool equal_p; + mrb_sym id_mesg = mrb_intern2(mrb, "mesg", 4); mrb_get_args(mrb, "o", &obj); - if (mrb_obj_equal(mrb, exc, obj)) return mrb_true_value(); - - if (mrb_obj_class(mrb, exc) != mrb_obj_class(mrb, obj)) { - if (mrb_respond_to(mrb, obj, mrb_intern(mrb, "message"))) { - mesg = mrb_funcall(mrb, obj, "message", 0); - } - else - return mrb_false_value(); + if (mrb_obj_equal(mrb, exc, obj)) { + equal_p = 1; } else { - mesg = mrb_attr_get(mrb, obj, id_mesg); + if (mrb_obj_class(mrb, exc) != mrb_obj_class(mrb, obj)) { + if (mrb_respond_to(mrb, obj, mrb_intern2(mrb, "message", 7))) { + mesg = mrb_funcall(mrb, obj, "message", 0); + } + else + return mrb_false_value(); + } + else { + mesg = mrb_attr_get(mrb, obj, id_mesg); + } + + equal_p = mrb_equal(mrb, mrb_attr_get(mrb, exc, id_mesg), mesg); } - if (!mrb_equal(mrb, mrb_attr_get(mrb, exc, id_mesg), mesg)) - return mrb_false_value(); - return mrb_true_value(); + return mrb_bool_value(equal_p); } static void @@ -185,15 +191,15 @@ exc_debug_info(mrb_state *mrb, struct RObject *exc) mrb_callinfo *ci = mrb->ci; mrb_code *pc = ci->pc; - mrb_obj_iv_set(mrb, exc, mrb_intern(mrb, "ciidx"), mrb_fixnum_value(ci - mrb->cibase)); + mrb_obj_iv_set(mrb, exc, mrb_intern2(mrb, "ciidx", 5), mrb_fixnum_value(ci - mrb->cibase)); ci--; while (ci >= mrb->cibase) { if (ci->proc && !MRB_PROC_CFUNC_P(ci->proc)) { mrb_irep *irep = ci->proc->body.irep; if (irep->filename && irep->lines && irep->iseq <= pc && pc < irep->iseq + irep->ilen) { - mrb_obj_iv_set(mrb, exc, mrb_intern(mrb, "file"), mrb_str_new_cstr(mrb, irep->filename)); - mrb_obj_iv_set(mrb, exc, mrb_intern(mrb, "line"), mrb_fixnum_value(irep->lines[pc - irep->iseq - 1])); + mrb_obj_iv_set(mrb, exc, mrb_intern2(mrb, "file", 4), mrb_str_new_cstr(mrb, irep->filename)); + mrb_obj_iv_set(mrb, exc, mrb_intern2(mrb, "line", 4), mrb_fixnum_value(irep->lines[pc - irep->iseq - 1])); return; } } @@ -205,7 +211,7 @@ exc_debug_info(mrb_state *mrb, struct RObject *exc) void mrb_exc_raise(mrb_state *mrb, mrb_value exc) { - mrb->exc = (struct RObject*)mrb_object(exc); + mrb->exc = mrb_obj_ptr(exc); exc_debug_info(mrb, mrb->exc); if (!mrb->jmp) { mrb_p(mrb, exc); @@ -218,7 +224,7 @@ void mrb_raise(mrb_state *mrb, struct RClass *c, const char *msg) { mrb_value mesg; - mesg = mrb_str_new2(mrb, msg); + mesg = mrb_str_new_cstr(mrb, msg); mrb_exc_raise(mrb, mrb_exc_new3(mrb, c, mesg)); } @@ -329,7 +335,7 @@ mrb_bug_errno(const char *mesg, int errno_arg) int sysexit_status(mrb_state *mrb, mrb_value err) { - mrb_value st = mrb_iv_get(mrb, err, mrb_intern(mrb, "status")); + mrb_value st = mrb_iv_get(mrb, err, mrb_intern2(mrb, "status", 6)); return mrb_fixnum(st); } @@ -367,7 +373,7 @@ make_exception(mrb_state *mrb, int argc, mrb_value *argv, int isstr) n = 1; exception_call: { - mrb_sym exc = mrb_intern(mrb, "exception"); + mrb_sym exc = mrb_intern2(mrb, "exception", 9); if (mrb_respond_to(mrb, argv[0], exc)) { mesg = mrb_funcall_argv(mrb, argv[0], exc, n, argv+1); } @@ -401,7 +407,20 @@ mrb_make_exception(mrb_state *mrb, int argc, mrb_value *argv) void mrb_sys_fail(mrb_state *mrb, const char *mesg) { - mrb_raise(mrb, E_RUNTIME_ERROR, mesg); + struct RClass *sce; + mrb_int no; + + no = (mrb_int)errno; + if (mrb_class_defined(mrb, "SystemCallError")) { + sce = mrb_class_get(mrb, "SystemCallError"); + if (mesg != NULL) { + mrb_funcall(mrb, mrb_obj_value(sce), "_sys_fail", 2, mrb_fixnum_value(no), mrb_str_new_cstr(mrb, mesg)); + } else { + mrb_funcall(mrb, mrb_obj_value(sce), "_sys_fail", 1, mrb_fixnum_value(no)); + } + } else { + mrb_raise(mrb, E_RUNTIME_ERROR, mesg); + } } void @@ -197,7 +197,7 @@ struct heap_page { struct heap_page *next; struct heap_page *free_next; struct heap_page *free_prev; - unsigned int old:1; + mrb_bool old:1; RVALUE objects[MRB_HEAP_PAGE_SIZE]; }; @@ -322,7 +322,7 @@ void mrb_gc_protect(mrb_state *mrb, mrb_value obj) { if (mrb_special_const_p(obj)) return; - gc_protect(mrb, mrb_basic(obj)); + gc_protect(mrb, mrb_basic_ptr(obj)); } struct RBasic* @@ -542,7 +542,9 @@ obj_free(mrb_state *mrb, struct RBasic *obj) static void root_scan_phase(mrb_state *mrb) { - int i, j, e; + int j; + size_t i; + size_t e; mrb_callinfo *ci; if (!is_minor_gc(mrb)) { @@ -982,8 +984,8 @@ gc_enable(mrb_state *mrb, mrb_value obj) int old = mrb->gc_disabled; mrb->gc_disabled = FALSE; - if (old) return mrb_true_value(); - return mrb_false_value(); + + return mrb_bool_value(old); } /* @@ -1004,8 +1006,8 @@ gc_disable(mrb_state *mrb, mrb_value obj) int old = mrb->gc_disabled; mrb->gc_disabled = TRUE; - if (old) return mrb_true_value(); - return mrb_false_value(); + + return mrb_bool_value(old); } /* @@ -1101,10 +1103,7 @@ change_gen_gc_mode(mrb_state *mrb, mrb_int enable) static mrb_value gc_generational_mode_get(mrb_state *mrb, mrb_value self) { - if (mrb->is_generational_gc_mode) - return mrb_true_value(); - else - return mrb_false_value(); + return mrb_bool_value(mrb->is_generational_gc_mode); } /* @@ -1124,10 +1123,7 @@ gc_generational_mode_set(mrb_state *mrb, mrb_value self) if (mrb->is_generational_gc_mode != enable) change_gen_gc_mode(mrb, enable); - if (enable) - return mrb_true_value(); - else - return mrb_false_value(); + return mrb_bool_value(enable); } #ifdef GC_TEST @@ -1168,8 +1164,8 @@ test_mrb_field_write_barrier(void) puts("test_mrb_field_write_barrier"); mrb->is_generational_gc_mode = FALSE; - obj = mrb_basic(mrb_ary_new(mrb)); - value = mrb_basic(mrb_str_new_cstr(mrb, "value")); + obj = mrb_basic_ptr(mrb_ary_new(mrb)); + value = mrb_basic_ptr(mrb_str_new_cstr(mrb, "value")); paint_black(obj); paint_partial_white(mrb,value); @@ -1210,15 +1206,15 @@ test_mrb_field_write_barrier(void) { puts("test_mrb_field_write_barrier_value"); - obj = mrb_basic(mrb_ary_new(mrb)); + obj = mrb_basic_ptr(mrb_ary_new(mrb)); mrb_value value = mrb_str_new_cstr(mrb, "value"); paint_black(obj); - paint_partial_white(mrb, mrb_basic(value)); + paint_partial_white(mrb, mrb_basic_ptr(value)); mrb->gc_state = GC_STATE_MARK; mrb_field_write_barrier_value(mrb, obj, value); - gc_assert(is_gray(mrb_basic(value))); + gc_assert(is_gray(mrb_basic_ptr(value))); } mrb_close(mrb); @@ -1231,7 +1227,7 @@ test_mrb_write_barrier(void) struct RBasic *obj; puts("test_mrb_write_barrier"); - obj = mrb_basic(mrb_ary_new(mrb)); + obj = mrb_basic_ptr(mrb_ary_new(mrb)); paint_black(obj); puts(" in GC_STATE_MARK"); @@ -1260,12 +1256,12 @@ test_add_gray_list(void) puts("test_add_gray_list"); change_gen_gc_mode(mrb, FALSE); gc_assert(mrb->gray_list == NULL); - obj1 = mrb_basic(mrb_str_new_cstr(mrb, "test")); + obj1 = mrb_basic_ptr(mrb_str_new_cstr(mrb, "test")); add_gray_list(mrb, obj1); gc_assert(mrb->gray_list == obj1); gc_assert(is_gray(obj1)); - obj2 = mrb_basic(mrb_str_new_cstr(mrb, "test")); + obj2 = mrb_basic_ptr(mrb_str_new_cstr(mrb, "test")); add_gray_list(mrb, obj2); gc_assert(mrb->gray_list == obj2); gc_assert(mrb->gray_list->gcnext == obj1); @@ -1294,12 +1290,12 @@ test_gc_gray_mark(void) puts(" in MRB_TT_ARRAY"); obj_v = mrb_ary_new(mrb); value_v = mrb_str_new_cstr(mrb, "test"); - paint_gray(mrb_basic(obj_v)); - paint_partial_white(mrb, mrb_basic(value_v)); + paint_gray(mrb_basic_ptr(obj_v)); + paint_partial_white(mrb, mrb_basic_ptr(value_v)); mrb_ary_push(mrb, obj_v, value_v); - gray_num = gc_gray_mark(mrb, mrb_basic(obj_v)); - gc_assert(is_black(mrb_basic(obj_v))); - gc_assert(is_gray(mrb_basic(value_v))); + gray_num = gc_gray_mark(mrb, mrb_basic_ptr(obj_v)); + gc_assert(is_black(mrb_basic_ptr(obj_v))); + gc_assert(is_gray(mrb_basic_ptr(value_v))); gc_assert(gray_num == 1); mrb_close(mrb); diff --git a/src/hash.c b/src/hash.c index 728fc0f2f..8de7b55c8 100644 --- a/src/hash.c +++ b/src/hash.c @@ -15,7 +15,7 @@ static inline khint_t mrb_hash_ht_hash_func(mrb_state *mrb, mrb_value key) { - khint_t h = mrb_type(key) << 24; + khint_t h = (khint_t)mrb_type(key) << 24; mrb_value h2; h2 = mrb_funcall(mrb, key, "hash", 0, 0); @@ -52,11 +52,15 @@ mrb_gc_mark_ht(mrb_state *mrb, struct RHash *hash) khash_t(ht) *h = hash->ht; if (!h) return; - for (k = kh_begin(h); k != kh_end(h); k++) + for (k = kh_begin(h); k != kh_end(h); k++) { if (kh_exist(h, k)) { - mrb_gc_mark_value(mrb, kh_key(h, k)); - mrb_gc_mark_value(mrb, kh_value(h, k)); + mrb_value key = kh_key(h, k); + mrb_value val = kh_value(h, k); + + mrb_gc_mark_value(mrb, key); + mrb_gc_mark_value(mrb, val); } + } } size_t @@ -258,7 +262,7 @@ mrb_hash_init_core(mrb_state *mrb, mrb_value hash) RHASH(hash)->flags |= MRB_HASH_PROC_DEFAULT; ifnone = block; } - mrb_iv_set(mrb, hash, mrb_intern(mrb, "ifnone"), ifnone); + mrb_iv_set(mrb, hash, mrb_intern2(mrb, "ifnone", 6), ifnone); return hash; } @@ -423,7 +427,7 @@ mrb_hash_set_default(mrb_state *mrb, mrb_value hash) mrb_get_args(mrb, "o", &ifnone); mrb_hash_modify(mrb, hash); - mrb_iv_set(mrb, hash, mrb_intern(mrb, "ifnone"), ifnone); + mrb_iv_set(mrb, hash, mrb_intern2(mrb, "ifnone", 6), ifnone); RHASH(hash)->flags &= ~(MRB_HASH_PROC_DEFAULT); return ifnone; @@ -474,7 +478,7 @@ mrb_hash_set_default_proc(mrb_state *mrb, mrb_value hash) mrb_get_args(mrb, "o", &ifnone); mrb_hash_modify(mrb, hash); - mrb_iv_set(mrb, hash, mrb_intern(mrb, "ifnone"), ifnone); + mrb_iv_set(mrb, hash, mrb_intern2(mrb, "ifnone", 6), ifnone); RHASH(hash)->flags |= MRB_HASH_PROC_DEFAULT; return ifnone; @@ -755,7 +759,7 @@ mrb_hash_replace(mrb_state *mrb, mrb_value hash) else { ifnone = RHASH_IFNONE(hash2); } - mrb_iv_set(mrb, hash, mrb_intern(mrb, "ifnone"), ifnone); + mrb_iv_set(mrb, hash, mrb_intern2(mrb, "ifnone", 6), ifnone); return hash; } @@ -797,13 +801,16 @@ static mrb_value mrb_hash_empty_p(mrb_state *mrb, mrb_value self) { khash_t(ht) *h = RHASH_TBL(self); + mrb_bool empty_p; if (h) { - if (kh_size(h) == 0) - return mrb_true_value(); - return mrb_false_value(); + empty_p = (kh_size(h) == 0); } - return mrb_true_value(); + else { + empty_p = 1; + } + + return mrb_bool_value(empty_p); } /* 15.2.13.4.11 */ @@ -887,7 +894,7 @@ inspect_hash(mrb_state *mrb, mrb_value hash, int recur) ai = mrb_gc_arena_save(mrb); - if (RSTRING_LEN(str) > 1) mrb_str_cat2(mrb, str, ", "); + if (RSTRING_LEN(str) > 1) mrb_str_cat(mrb, str, ", ", 2); str2 = mrb_inspect(mrb, kh_key(h,k)); mrb_str_append(mrb, str, str2); @@ -1006,14 +1013,17 @@ mrb_hash_has_keyWithKey(mrb_state *mrb, mrb_value hash, mrb_value key) { khash_t(ht) *h = RHASH_TBL(hash); khiter_t k; + mrb_bool result; if (h) { k = kh_get(ht, h, key); - if (k != kh_end(h)) - return mrb_true_value(); + result = (k != kh_end(h)); + } + else { + result = 0; } - return mrb_false_value(); + return mrb_bool_value(result); } /* 15.2.13.4.13 */ @@ -1094,7 +1104,7 @@ hash_equal(mrb_state *mrb, mrb_value hash1, mrb_value hash2, int eql) if (mrb_obj_equal(mrb, hash1, hash2)) return mrb_true_value(); if (!mrb_hash_p(hash2)) { - if (!mrb_respond_to(mrb, hash2, mrb_intern(mrb, "to_hash"))) { + if (!mrb_respond_to(mrb, hash2, mrb_intern2(mrb, "to_hash", 7))) { return mrb_false_value(); } if (eql) @@ -1105,8 +1115,7 @@ hash_equal(mrb_state *mrb, mrb_value hash1, mrb_value hash2, int eql) h1 = RHASH_TBL(hash1); h2 = RHASH_TBL(hash2); if (!h1) { - if (!h2) return mrb_true_value(); - return mrb_false_value(); + return mrb_bool_value(!h2); } if (!h2) return mrb_false_value(); if (kh_size(h1) != kh_size(h2)) return mrb_false_value(); diff --git a/src/init.c b/src/init.c index 0d1a24881..e97c72d68 100644 --- a/src/init.c +++ b/src/init.c @@ -21,7 +21,6 @@ void mrb_init_hash(mrb_state*); void mrb_init_numeric(mrb_state*); void mrb_init_range(mrb_state*); void mrb_init_gc(mrb_state*); -void mrb_init_print(mrb_state*); void mrb_init_math(mrb_state*); void mrb_init_mrblib(mrb_state*); void mrb_init_mrbgems(mrb_state*); @@ -48,9 +47,6 @@ mrb_init_core(mrb_state *mrb) mrb_init_numeric(mrb); DONE; mrb_init_range(mrb); DONE; mrb_init_gc(mrb); DONE; -#ifdef ENABLE_STDIO - mrb_init_print(mrb); DONE; -#endif mrb_init_mrblib(mrb); DONE; #ifndef DISABLE_GEMS mrb_init_mrbgems(mrb); DONE; diff --git a/src/kernel.c b/src/kernel.c index 7187a125d..0c746d987 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -29,7 +29,7 @@ typedef enum { int mrb_obj_basic_to_s_p(mrb_state *mrb, mrb_value obj) { - struct RProc *me = mrb_method_search(mrb, mrb_class(mrb, obj), mrb_intern(mrb, "to_s")); + struct RProc *me = mrb_method_search(mrb, mrb_class(mrb, obj), mrb_intern2(mrb, "to_s", 4)); if (me && MRB_PROC_CFUNC_P(me) && (me->body.func == mrb_any_to_s)) return TRUE; return FALSE; @@ -96,28 +96,24 @@ static mrb_value mrb_obj_equal_m(mrb_state *mrb, mrb_value self) { mrb_value arg; + mrb_bool eql_p; mrb_get_args(mrb, "o", &arg); - if (mrb_obj_equal(mrb, self, arg)) { - return mrb_true_value(); - } - else { - return mrb_false_value(); - } + eql_p = mrb_obj_equal(mrb, self, arg); + + return mrb_bool_value(eql_p); } static mrb_value mrb_obj_not_equal_m(mrb_state *mrb, mrb_value self) { mrb_value arg; + mrb_bool eql_p; mrb_get_args(mrb, "o", &arg); - if (mrb_equal(mrb, self, arg)) { - return mrb_false_value(); - } - else { - return mrb_true_value(); - } + eql_p = mrb_obj_equal(mrb, self, arg); + + return mrb_bool_value(!eql_p); } /* 15.3.1.3.2 */ @@ -133,14 +129,12 @@ static mrb_value mrb_equal_m(mrb_state *mrb, mrb_value self) { mrb_value arg; + mrb_bool equal_p; mrb_get_args(mrb, "o", &arg); - if (mrb_equal(mrb, self, arg)){ - return mrb_true_value(); - } - else { - return mrb_false_value(); - } + equal_p = mrb_equal(mrb, self, arg); + + return mrb_bool_value(equal_p); } /* 15.3.1.3.3 */ @@ -225,21 +219,28 @@ mrb_f_block_given_p_m(mrb_state *mrb, mrb_value self) { mrb_callinfo *ci = mrb->ci; mrb_value *bp; + mrb_bool given_p; bp = mrb->stbase + ci->stackidx + 1; ci--; - if (ci <= mrb->cibase) return mrb_false_value(); - /* block_given? called within block; check upper scope */ - if (ci->proc->env && ci->proc->env->stack) { - if (ci->proc->env->stack == mrb->stbase || mrb_nil_p(ci->proc->env->stack[1])) - return mrb_false_value(); - return mrb_true_value(); + if (ci <= mrb->cibase) { + given_p = 0; } - if (ci->argc > 0) { - bp += ci->argc; + else { + /* block_given? called within block; check upper scope */ + if (ci->proc->env && ci->proc->env->stack) { + given_p = !(ci->proc->env->stack == mrb->stbase || + mrb_nil_p(ci->proc->env->stack[1])); + } + else { + if (ci->argc > 0) { + bp += ci->argc; + } + given_p = !mrb_nil_p(*bp); + } } - if (mrb_nil_p(*bp)) return mrb_false_value(); - return mrb_true_value(); + + return mrb_bool_value(given_p); } /* 15.3.1.3.7 */ @@ -263,7 +264,7 @@ mrb_obj_class_m(mrb_state *mrb, mrb_value self) struct RClass* mrb_singleton_class_clone(mrb_state *mrb, mrb_value obj) { - struct RClass *klass = mrb_basic(obj)->c; + struct RClass *klass = mrb_basic_ptr(obj)->c; if (klass->tt != MRB_TT_SCLASS) return klass; @@ -282,7 +283,7 @@ mrb_singleton_class_clone(mrb_state *mrb, mrb_value obj) clone->super = klass->super; if (klass->iv) { mrb_iv_copy(mrb, mrb_obj_value(clone), mrb_obj_value(klass)); - mrb_obj_iv_set(mrb, (struct RObject*)clone, mrb_intern(mrb, "__attached__"), obj); + mrb_obj_iv_set(mrb, (struct RObject*)clone, mrb_intern2(mrb, "__attached__", 12), obj); } if (klass->mt) { clone->mt = kh_copy(mt, mrb, klass->mt); @@ -518,6 +519,7 @@ mrb_obj_instance_eval(mrb_state *mrb, mrb_value self) default: cv = mrb_singleton_class(mrb, self); c = mrb_class_ptr(cv); + break; } return mrb_yield_internal(mrb, b, 0, 0, self, c); } @@ -541,21 +543,19 @@ static mrb_value obj_is_instance_of(mrb_state *mrb, mrb_value self) { mrb_value arg; + mrb_bool instance_of_p; mrb_get_args(mrb, "o", &arg); - if (mrb_obj_is_instance_of(mrb, self, mrb_class_ptr(arg))){ - return mrb_true_value(); - } - else { - return mrb_false_value(); - } + instance_of_p = mrb_obj_is_instance_of(mrb, self, mrb_class_ptr(arg)); + + return mrb_bool_value(instance_of_p); } static void check_iv_name(mrb_state *mrb, mrb_sym id) { const char *s; - int len; + size_t len; s = mrb_sym2name_len(mrb, id, &len); if (len < 2 || !(s[0] == '@' && s[1] != '@')) { @@ -585,12 +585,13 @@ mrb_value mrb_obj_ivar_defined(mrb_state *mrb, mrb_value self) { mrb_sym mid; + mrb_bool defined_p; mrb_get_args(mrb, "n", &mid); check_iv_name(mrb, mid); - if (mrb_obj_iv_defined(mrb, mrb_obj_ptr(self), mid)) - return mrb_true_value(); - return mrb_false_value(); + defined_p = mrb_obj_iv_defined(mrb, mrb_obj_ptr(self), mid); + + return mrb_bool_value(defined_p); } /* 15.3.1.3.21 */ @@ -687,14 +688,12 @@ mrb_value mrb_obj_is_kind_of_m(mrb_state *mrb, mrb_value self) { mrb_value arg; + mrb_bool kind_of_p; mrb_get_args(mrb, "o", &arg); - if (mrb_obj_is_kind_of(mrb, self, mrb_class_ptr(arg))) { - return mrb_true_value(); - } - else { - return mrb_false_value(); - } + kind_of_p = mrb_obj_is_kind_of(mrb, self, mrb_class_ptr(arg)); + + return mrb_bool_value(kind_of_p); } static void @@ -929,8 +928,9 @@ mrb_f_raise(mrb_state *mrb, mrb_value self) /* fall through */ default: exc = mrb_make_exception(mrb, argc, a); - mrb_obj_iv_set(mrb, mrb_obj_ptr(exc), mrb_intern(mrb, "lastpc"), mrb_voidp_value(mrb->ci->pc)); + mrb_obj_iv_set(mrb, mrb_obj_ptr(exc), mrb_intern2(mrb, "lastpc", 6), mrb_voidp_value(mrb->ci->pc)); mrb_exc_raise(mrb, exc); + break; } return mrb_nil_value(); /* not reached */ } @@ -1000,15 +1000,17 @@ obj_respond_to(mrb_state *mrb, mrb_value self) int argc; mrb_value mid, priv; mrb_sym id; + mrb_bool respond_to_p; mrb_get_args(mrb, "*", &argv, &argc); mid = argv[0]; if (argc > 1) priv = argv[1]; else priv = mrb_nil_value(); id = mrb_to_id(mrb, mid); - if (basic_obj_respond_to(mrb, self, id, !mrb_test(priv))) - return mrb_true_value(); - return mrb_false_value(); + + respond_to_p = basic_obj_respond_to(mrb, self, id, !mrb_test(priv)); + + return mrb_bool_value(respond_to_p); } /* 15.3.1.3.45 */ diff --git a/src/keywords b/src/keywords index be5324875..9cb86608c 100644 --- a/src/keywords +++ b/src/keywords @@ -8,43 +8,43 @@ static const struct kwtable *reserved_word(const char *, unsigned int); struct kwtable; %% __ENCODING__, {keyword__ENCODING__, keyword__ENCODING__}, EXPR_END -__LINE__, {keyword__LINE__, keyword__LINE__}, EXPR_END -__FILE__, {keyword__FILE__, keyword__FILE__}, EXPR_END -BEGIN, {keyword_BEGIN, keyword_BEGIN}, EXPR_END -END, {keyword_END, keyword_END}, EXPR_END -alias, {keyword_alias, keyword_alias}, EXPR_FNAME -and, {keyword_and, keyword_and}, EXPR_VALUE -begin, {keyword_begin, keyword_begin}, EXPR_BEG -break, {keyword_break, keyword_break}, EXPR_MID -case, {keyword_case, keyword_case}, EXPR_VALUE -class, {keyword_class, keyword_class}, EXPR_CLASS -def, {keyword_def, keyword_def}, EXPR_FNAME -do, {keyword_do, keyword_do}, EXPR_BEG -else, {keyword_else, keyword_else}, EXPR_BEG -elsif, {keyword_elsif, keyword_elsif}, EXPR_VALUE -end, {keyword_end, keyword_end}, EXPR_END -ensure, {keyword_ensure, keyword_ensure}, EXPR_BEG -false, {keyword_false, keyword_false}, EXPR_END -for, {keyword_for, keyword_for}, EXPR_VALUE -if, {keyword_if, modifier_if}, EXPR_VALUE -in, {keyword_in, keyword_in}, EXPR_VALUE -module, {keyword_module, keyword_module}, EXPR_VALUE -next, {keyword_next, keyword_next}, EXPR_MID -nil, {keyword_nil, keyword_nil}, EXPR_END -not, {keyword_not, keyword_not}, EXPR_ARG -or, {keyword_or, keyword_or}, EXPR_VALUE -redo, {keyword_redo, keyword_redo}, EXPR_END -rescue, {keyword_rescue, modifier_rescue}, EXPR_MID -retry, {keyword_retry, keyword_retry}, EXPR_END -return, {keyword_return, keyword_return}, EXPR_MID -self, {keyword_self, keyword_self}, EXPR_END -super, {keyword_super, keyword_super}, EXPR_ARG -then, {keyword_then, keyword_then}, EXPR_BEG -true, {keyword_true, keyword_true}, EXPR_END -undef, {keyword_undef, keyword_undef}, EXPR_FNAME -unless, {keyword_unless, modifier_unless}, EXPR_VALUE -until, {keyword_until, modifier_until}, EXPR_VALUE -when, {keyword_when, keyword_when}, EXPR_VALUE -while, {keyword_while, modifier_while}, EXPR_VALUE -yield, {keyword_yield, keyword_yield}, EXPR_ARG +__FILE__, {keyword__FILE__, keyword__FILE__}, EXPR_END +__LINE__, {keyword__LINE__, keyword__LINE__}, EXPR_END +BEGIN, {keyword_BEGIN, keyword_BEGIN}, EXPR_END +END, {keyword_END, keyword_END}, EXPR_END +alias, {keyword_alias, keyword_alias}, EXPR_FNAME +and, {keyword_and, keyword_and}, EXPR_VALUE +begin, {keyword_begin, keyword_begin}, EXPR_BEG +break, {keyword_break, keyword_break}, EXPR_MID +case, {keyword_case, keyword_case}, EXPR_VALUE +class, {keyword_class, keyword_class}, EXPR_CLASS +def, {keyword_def, keyword_def}, EXPR_FNAME +do, {keyword_do, keyword_do}, EXPR_BEG +else, {keyword_else, keyword_else}, EXPR_BEG +elsif, {keyword_elsif, keyword_elsif}, EXPR_VALUE +end, {keyword_end, keyword_end}, EXPR_END +ensure, {keyword_ensure, keyword_ensure}, EXPR_BEG +false, {keyword_false, keyword_false}, EXPR_END +for, {keyword_for, keyword_for}, EXPR_VALUE +if, {keyword_if, modifier_if}, EXPR_VALUE +in, {keyword_in, keyword_in}, EXPR_VALUE +module, {keyword_module, keyword_module}, EXPR_VALUE +next, {keyword_next, keyword_next}, EXPR_MID +nil, {keyword_nil, keyword_nil}, EXPR_END +not, {keyword_not, keyword_not}, EXPR_ARG +or, {keyword_or, keyword_or}, EXPR_VALUE +redo, {keyword_redo, keyword_redo}, EXPR_END +rescue, {keyword_rescue, modifier_rescue}, EXPR_MID +retry, {keyword_retry, keyword_retry}, EXPR_END +return, {keyword_return, keyword_return}, EXPR_MID +self, {keyword_self, keyword_self}, EXPR_END +super, {keyword_super, keyword_super}, EXPR_ARG +then, {keyword_then, keyword_then}, EXPR_BEG +true, {keyword_true, keyword_true}, EXPR_END +undef, {keyword_undef, keyword_undef}, EXPR_FNAME +unless, {keyword_unless, modifier_unless}, EXPR_VALUE +until, {keyword_until, modifier_until}, EXPR_VALUE +when, {keyword_when, keyword_when}, EXPR_VALUE +while, {keyword_while, modifier_while}, EXPR_VALUE +yield, {keyword_yield, keyword_yield}, EXPR_ARG %% diff --git a/src/lex.def b/src/lex.def index 5223aac1b..ea456a843 100644 --- a/src/lex.def +++ b/src/lex.def @@ -1,4 +1,4 @@ -/* ANSI-C code produced by gperf version 3.0.4 */ +/* ANSI-C code produced by gperf version 3.0.3 */ /* Command-line: gperf -L ANSI-C -C -p -j1 -i 1 -g -o -t -N mrb_reserved_word -k'1,3,$' src/keywords */ #if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ @@ -44,10 +44,12 @@ struct kwtable; #define MAX_HASH_VALUE 50 /* maximum key range = 43, duplicates = 0 */ -#if (defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__cplusplus) || defined(__GNUC_STDC_INLINE__) -inline -#elif defined(__GNUC__) +#ifdef __GNUC__ __inline +#else +#ifdef __cplusplus +inline +#endif #endif static unsigned int hash (register const char *str, register unsigned int len) @@ -98,7 +100,7 @@ hash (register const char *str, register unsigned int len) #ifdef __GNUC__ __inline -#if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__ +#ifdef __GNUC_STDC_INLINE__ __attribute__ ((__gnu_inline__)) #endif #endif @@ -109,87 +111,87 @@ mrb_reserved_word (register const char *str, register unsigned int len) { {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, #line 18 "src/keywords" - {"break", {keyword_break, keyword_break}, EXPR_MID}, + {"break", {keyword_break, keyword_break}, EXPR_MID}, #line 23 "src/keywords" - {"else", {keyword_else, keyword_else}, EXPR_BEG}, + {"else", {keyword_else, keyword_else}, EXPR_BEG}, #line 33 "src/keywords" - {"nil", {keyword_nil, keyword_nil}, EXPR_END}, + {"nil", {keyword_nil, keyword_nil}, EXPR_END}, #line 26 "src/keywords" - {"ensure", {keyword_ensure, keyword_ensure}, EXPR_BEG}, + {"ensure", {keyword_ensure, keyword_ensure}, EXPR_BEG}, #line 25 "src/keywords" - {"end", {keyword_end, keyword_end}, EXPR_END}, + {"end", {keyword_end, keyword_end}, EXPR_END}, #line 42 "src/keywords" - {"then", {keyword_then, keyword_then}, EXPR_BEG}, + {"then", {keyword_then, keyword_then}, EXPR_BEG}, #line 34 "src/keywords" - {"not", {keyword_not, keyword_not}, EXPR_ARG}, + {"not", {keyword_not, keyword_not}, EXPR_ARG}, #line 27 "src/keywords" - {"false", {keyword_false, keyword_false}, EXPR_END}, + {"false", {keyword_false, keyword_false}, EXPR_END}, #line 40 "src/keywords" - {"self", {keyword_self, keyword_self}, EXPR_END}, + {"self", {keyword_self, keyword_self}, EXPR_END}, #line 24 "src/keywords" - {"elsif", {keyword_elsif, keyword_elsif}, EXPR_VALUE}, + {"elsif", {keyword_elsif, keyword_elsif}, EXPR_VALUE}, #line 37 "src/keywords" - {"rescue", {keyword_rescue, modifier_rescue}, EXPR_MID}, + {"rescue", {keyword_rescue, modifier_rescue}, EXPR_MID}, #line 43 "src/keywords" - {"true", {keyword_true, keyword_true}, EXPR_END}, + {"true", {keyword_true, keyword_true}, EXPR_END}, #line 46 "src/keywords" - {"until", {keyword_until, modifier_until}, EXPR_VALUE}, + {"until", {keyword_until, modifier_until}, EXPR_VALUE}, #line 45 "src/keywords" - {"unless", {keyword_unless, modifier_unless}, EXPR_VALUE}, + {"unless", {keyword_unless, modifier_unless}, EXPR_VALUE}, #line 39 "src/keywords" - {"return", {keyword_return, keyword_return}, EXPR_MID}, + {"return", {keyword_return, keyword_return}, EXPR_MID}, #line 21 "src/keywords" - {"def", {keyword_def, keyword_def}, EXPR_FNAME}, + {"def", {keyword_def, keyword_def}, EXPR_FNAME}, #line 16 "src/keywords" - {"and", {keyword_and, keyword_and}, EXPR_VALUE}, + {"and", {keyword_and, keyword_and}, EXPR_VALUE}, #line 22 "src/keywords" - {"do", {keyword_do, keyword_do}, EXPR_BEG}, + {"do", {keyword_do, keyword_do}, EXPR_BEG}, #line 49 "src/keywords" - {"yield", {keyword_yield, keyword_yield}, EXPR_ARG}, + {"yield", {keyword_yield, keyword_yield}, EXPR_ARG}, #line 28 "src/keywords" - {"for", {keyword_for, keyword_for}, EXPR_VALUE}, + {"for", {keyword_for, keyword_for}, EXPR_VALUE}, #line 44 "src/keywords" - {"undef", {keyword_undef, keyword_undef}, EXPR_FNAME}, + {"undef", {keyword_undef, keyword_undef}, EXPR_FNAME}, #line 35 "src/keywords" - {"or", {keyword_or, keyword_or}, EXPR_VALUE}, + {"or", {keyword_or, keyword_or}, EXPR_VALUE}, #line 30 "src/keywords" - {"in", {keyword_in, keyword_in}, EXPR_VALUE}, + {"in", {keyword_in, keyword_in}, EXPR_VALUE}, #line 47 "src/keywords" - {"when", {keyword_when, keyword_when}, EXPR_VALUE}, + {"when", {keyword_when, keyword_when}, EXPR_VALUE}, #line 38 "src/keywords" - {"retry", {keyword_retry, keyword_retry}, EXPR_END}, + {"retry", {keyword_retry, keyword_retry}, EXPR_END}, #line 29 "src/keywords" - {"if", {keyword_if, modifier_if}, EXPR_VALUE}, + {"if", {keyword_if, modifier_if}, EXPR_VALUE}, #line 19 "src/keywords" - {"case", {keyword_case, keyword_case}, EXPR_VALUE}, + {"case", {keyword_case, keyword_case}, EXPR_VALUE}, #line 36 "src/keywords" - {"redo", {keyword_redo, keyword_redo}, EXPR_END}, + {"redo", {keyword_redo, keyword_redo}, EXPR_END}, #line 32 "src/keywords" - {"next", {keyword_next, keyword_next}, EXPR_MID}, + {"next", {keyword_next, keyword_next}, EXPR_MID}, #line 41 "src/keywords" - {"super", {keyword_super, keyword_super}, EXPR_ARG}, + {"super", {keyword_super, keyword_super}, EXPR_ARG}, #line 31 "src/keywords" - {"module", {keyword_module, keyword_module}, EXPR_VALUE}, + {"module", {keyword_module, keyword_module}, EXPR_VALUE}, #line 17 "src/keywords" - {"begin", {keyword_begin, keyword_begin}, EXPR_BEG}, -#line 11 "src/keywords" - {"__LINE__", {keyword__LINE__, keyword__LINE__}, EXPR_END}, + {"begin", {keyword_begin, keyword_begin}, EXPR_BEG}, #line 12 "src/keywords" - {"__FILE__", {keyword__FILE__, keyword__FILE__}, EXPR_END}, + {"__LINE__", {keyword__LINE__, keyword__LINE__}, EXPR_END}, +#line 11 "src/keywords" + {"__FILE__", {keyword__FILE__, keyword__FILE__}, EXPR_END}, #line 10 "src/keywords" {"__ENCODING__", {keyword__ENCODING__, keyword__ENCODING__}, EXPR_END}, #line 14 "src/keywords" - {"END", {keyword_END, keyword_END}, EXPR_END}, + {"END", {keyword_END, keyword_END}, EXPR_END}, #line 15 "src/keywords" - {"alias", {keyword_alias, keyword_alias}, EXPR_FNAME}, + {"alias", {keyword_alias, keyword_alias}, EXPR_FNAME}, #line 13 "src/keywords" - {"BEGIN", {keyword_BEGIN, keyword_BEGIN}, EXPR_END}, + {"BEGIN", {keyword_BEGIN, keyword_BEGIN}, EXPR_END}, {""}, #line 20 "src/keywords" - {"class", {keyword_class, keyword_class}, EXPR_CLASS}, + {"class", {keyword_class, keyword_class}, EXPR_CLASS}, {""}, {""}, #line 48 "src/keywords" - {"while", {keyword_while, modifier_while}, EXPR_VALUE} + {"while", {keyword_while, modifier_while}, EXPR_VALUE} }; if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) diff --git a/src/load.c b/src/load.c index 84c21c186..fcffcd9de 100644 --- a/src/load.c +++ b/src/load.c @@ -4,6 +4,7 @@ ** See Copyright Notice in mruby.h */ +#include <stdlib.h> #include <string.h> #include "mruby/dump.h" @@ -683,7 +684,7 @@ static void irep_error(mrb_state *mrb, int n) { static const char msg[] = "irep load error"; - mrb->exc = (struct RObject*)mrb_object(mrb_exc_new(mrb, E_SCRIPT_ERROR, msg, sizeof(msg) - 1)); + mrb->exc = mrb_obj_ptr(mrb_exc_new(mrb, E_SCRIPT_ERROR, msg, sizeof(msg) - 1)); } #ifdef ENABLE_STDIO diff --git a/src/node.h b/src/node.h index e12672bfe..df27c431f 100644 --- a/src/node.h +++ b/src/node.h @@ -65,6 +65,8 @@ enum node_type { NODE_SYM, NODE_STR, NODE_DSTR, + NODE_XSTR, + NODE_DXSTR, NODE_REGX, NODE_DREGX, NODE_DREGX_ONCE, @@ -106,6 +108,9 @@ enum node_type { NODE_DSYM, NODE_ATTRASGN, NODE_HEREDOC, + NODE_LITERAL_DELIM, + NODE_WORDS, + NODE_SYMBOLS, NODE_LAST }; diff --git a/src/numeric.c b/src/numeric.c index 61b9a2f73..1e089c970 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -9,17 +9,15 @@ #include "mruby/string.h" #include "mruby/array.h" +#include <float.h> #include <math.h> #include <assert.h> +#include <stdlib.h> #if defined(__FreeBSD__) && __FreeBSD__ < 4 #include <floatingpoint.h> #endif -#ifdef HAVE_FLOAT_H -#include <float.h> -#endif - #ifdef HAVE_IEEEFP_H #include <ieeefp.h> #endif @@ -165,6 +163,99 @@ num_abs(mrb_state *mrb, mrb_value num) * representation. */ +mrb_value +mrb_flo_to_str(mrb_state *mrb, mrb_float n, int max_digit) +{ + mrb_value result; + + if (max_digit > 40) { + mrb_raise(mrb, E_RANGE_ERROR, "Too large max_digit."); + } + + if (isnan(n)) { + result = mrb_str_new(mrb, "NaN", 3); + } + else if (isinf(n)) { + if (n < 0) { + result = mrb_str_new(mrb, "-inf", 4); + } + else { + result = mrb_str_new(mrb, "inf", 3); + } + } + else { + int digit; + int m; + int exp; + int e = 0; + char s[48]; + char *c = &s[0]; + + if (n < 0) { + n = -n; + *(c++) = '-'; + } + + exp = log10(n); + + if ((exp < 0 ? -exp : exp) > max_digit) { + /* exponent representation */ + e = 1; + m = exp; + if (m < 0) { + m -= 1; + } + n = n / pow(10.0, m); + m = 0; + } + else { + /* un-exponent (normal) representation */ + m = exp; + if (m < 0) { + m = 0; + } + } + + /* puts digits */ + while (max_digit >= 0) { + mrb_float weight = pow(10.0, m); + digit = floor(n / weight + FLT_EPSILON); + *(c++) = '0' + digit; + n -= (digit * weight); + max_digit--; + if (m-- == 0) { + *(c++) = '.'; + } + else if (m < -1 && n < FLT_EPSILON) { + break; + } + } + + if (e) { + *(c++) = 'e'; + if (exp > 0) { + *(c++) = '+'; + } else { + *(c++) = '-'; + exp = -exp; + } + + if (exp >= 100) { + mrb_raise(mrb, E_RANGE_ERROR, "Too large expornent."); + } + + *(c++) = '0' + exp / 10; + *(c++) = '0' + exp % 10; + } + + *c = '\0'; + + result = mrb_str_new(mrb, &s[0], c - &s[0]); + } + + return result; +} + /* 15.2.9.3.16(x) */ /* * call-seq: @@ -179,27 +270,11 @@ num_abs(mrb_state *mrb, mrb_value num) static mrb_value flo_to_s(mrb_state *mrb, mrb_value flt) { - char buf[32]; - int n; - - mrb_float value = mrb_float(flt); - - if (isinf(value)) { - static const char s[2][5] = { "-inf", "inf" }; - static const int n[] = { 4, 3 }; - int idx; - idx = (value < 0) ? 0 : 1; - return mrb_str_new(mrb, s[idx], n[idx]); - } else if(isnan(value)) - return mrb_str_new(mrb, "NaN", 3); - #ifdef MRB_USE_FLOAT - n = sprintf(buf, "%.7g", value); + return mrb_flo_to_str(mrb, mrb_float(flt), 7); #else - n = sprintf(buf, "%.14g", value); + return mrb_flo_to_str(mrb, mrb_float(flt), 14); #endif - assert(n >= 0); - return mrb_str_new(mrb, buf, n); } /* 15.2.9.3.2 */ @@ -305,15 +380,17 @@ static mrb_value num_eql(mrb_state *mrb, mrb_value x) { mrb_value y; + mrb_bool eql_p; mrb_get_args(mrb, "o", &y); - if (mrb_type(x) != mrb_type(y)) return mrb_false_value(); - if (mrb_equal(mrb, x, y)) { - return mrb_true_value(); + if (mrb_type(x) != mrb_type(y)) { + eql_p = 0; } else { - return mrb_false_value(); + eql_p = mrb_equal(mrb, x, y); } + + return mrb_bool_value(eql_p); } static mrb_value @@ -355,7 +432,7 @@ flo_eq(mrb_state *mrb, mrb_value x) return num_equal(mrb, x, y); } a = mrb_float(x); - return (a == b)?mrb_true_value():mrb_false_value(); + return mrb_bool_value(a == b); } /* 15.2.8.3.18 */ @@ -370,7 +447,8 @@ flo_hash(mrb_state *mrb, mrb_value num) { mrb_float d; char *c; - int i, hash; + size_t i; + int hash; d = (mrb_float)mrb_fixnum(num); /* normalize -0.0 to 0.0 */ @@ -436,10 +514,11 @@ static mrb_value flo_finite_p(mrb_state *mrb, mrb_value num) { mrb_float value = mrb_float(num); + mrb_bool finite_p; - if (isinf(value) || isnan(value)) - return mrb_false_value(); - return mrb_true_value(); + finite_p = !(isinf(value) || isnan(value)); + + return mrb_bool_value(finite_p); } /* 15.2.9.3.10 */ @@ -848,19 +927,15 @@ static mrb_value fix_equal(mrb_state *mrb, mrb_value x) { mrb_value y; + mrb_bool equal_p; mrb_get_args(mrb, "o", &y); - if (mrb_obj_equal(mrb, x, y)) return mrb_true_value(); - switch (mrb_type(y)) { - case MRB_TT_FLOAT: - if ((mrb_float)mrb_fixnum(x) == mrb_float(y)) - return mrb_true_value(); - /* fall through */ - case MRB_TT_FIXNUM: - default: - return mrb_false_value(); - } + equal_p = mrb_obj_equal(mrb, x, y) || + (mrb_type(y) == MRB_TT_FLOAT && + (mrb_float)mrb_fixnum(x) == mrb_float(y)); + + return mrb_bool_value(equal_p); } /* 15.2.8.3.8 */ diff --git a/src/object.c b/src/object.c index 0d1cc85b9..5cf165000 100644 --- a/src/object.c +++ b/src/object.c @@ -5,7 +5,6 @@ */ #include "mruby.h" -#include <string.h> #include "mruby/string.h" #include "mruby/class.h" #include "mruby/numeric.h" @@ -115,7 +114,8 @@ true_and(mrb_state *mrb, mrb_value obj) int obj2; mrb_get_args(mrb, "b", &obj2); - return obj2 ? mrb_true_value() : mrb_false_value(); + + return mrb_bool_value(obj2); } /* 15.2.5.3.2 */ @@ -134,7 +134,7 @@ true_xor(mrb_state *mrb, mrb_value obj) int obj2; mrb_get_args(mrb, "b", &obj2); - return obj2 ? mrb_false_value() : mrb_true_value(); + return mrb_bool_value(!obj2); } /* 15.2.5.3.3 */ @@ -227,7 +227,7 @@ false_xor(mrb_state *mrb, mrb_value obj) int obj2; mrb_get_args(mrb, "b", &obj2); - return obj2 ? mrb_true_value() : mrb_false_value(); + return mrb_bool_value(obj2); } /* 15.2.4.3.3 */ @@ -247,7 +247,7 @@ false_or(mrb_state *mrb, mrb_value obj) int obj2; mrb_get_args(mrb, "b", &obj2); - return obj2 ? mrb_true_value() : mrb_false_value(); + return mrb_bool_value(obj2); } /* 15.2.6.3.3 */ @@ -439,8 +439,15 @@ mrb_check_type(mrb_state *mrb, mrb_value x, enum mrb_vtype t) mrb_value mrb_any_to_s(mrb_state *mrb, mrb_value obj) { + mrb_value str = mrb_str_buf_new(mrb, 20); const char *cname = mrb_obj_classname(mrb, obj); - return mrb_sprintf(mrb, "#<%s:%p>", cname, mrb_voidp(obj)); + + mrb_str_buf_cat(mrb, str, "#<", 2); + mrb_str_cat2(mrb, str, cname); + mrb_str_concat(mrb, str, mrb_ptr_to_str(mrb, mrb_voidp(obj))); + mrb_str_buf_cat(mrb, str, ">", 1); + + return str; } /* diff --git a/src/opcode.h b/src/opcode.h index d77e2451f..b4f843116 100644 --- a/src/opcode.h +++ b/src/opcode.h @@ -7,12 +7,15 @@ #ifndef OPCODE_H #define OPCODE_H -#define MAXARG_Bx ((1<<16)-1) +#define MAXARG_Bx (0xffff) #define MAXARG_sBx (MAXARG_Bx>>1) /* `sBx' is signed */ -/* instructions OP:A:B:C = 7:9:9:7 (32 bits) */ -/* OP:A:Bx = 7:9:16 */ -/* OP:Ax = 7:25 */ +/* instructions: packed 32 bit */ +/* ------------------------------- */ +/* A:B:C:OP = 9: 9: 7: 7 */ +/* A:Bx:OP = 9:16: 7 */ +/* Ax:OP = 25: 7 */ +/* A:Bz:Cz:OP = 9:14: 2: 7 */ #define GET_OPCODE(i) ((int)(((mrb_code)(i)) & 0x7f)) #define GETARG_A(i) ((int)((((mrb_code)(i)) >> 23) & 0x1ff)) @@ -20,19 +23,19 @@ #define GETARG_C(i) ((int)((((mrb_code)(i)) >> 7) & 0x7f)) #define GETARG_Bx(i) ((int)((((mrb_code)(i)) >> 7) & 0xffff)) #define GETARG_sBx(i) ((int)(GETARG_Bx(i)-MAXARG_sBx)) -#define GETARG_Ax(i) ((int)((((mrb_code)(i)) >> 7) & 0x1ffffff)) -#define GETARG_UNPACK_b(i,n1,n2) ((int)((((mrb_code)(i)) >> (7+n2)) & (((1<<n1)-1)))) -#define GETARG_UNPACK_c(i,n1,n2) ((int)((((mrb_code)(i)) >> 7) & (((1<<n2)-1)))) +#define GETARG_Ax(i) ((int32_t)((((mrb_code)(i)) >> 7) & 0x1ffffff)) +#define GETARG_UNPACK_b(i,n1,n2) ((int)((((mrb_code)(i)) >> (7+(n2))) & (((1<<(n1))-1)))) +#define GETARG_UNPACK_c(i,n1,n2) ((int)((((mrb_code)(i)) >> 7) & (((1<<(n2))-1)))) #define GETARG_b(i) GETARG_UNPACK_b(i,14,2) #define GETARG_c(i) GETARG_UNPACK_c(i,14,2) #define MKOPCODE(op) ((op) & 0x7f) -#define MKARG_A(c) (((c) & 0x1ff) << 23) -#define MKARG_B(c) (((c) & 0x1ff) << 14) +#define MKARG_A(c) ((mrb_code)((c) & 0x1ff) << 23) +#define MKARG_B(c) ((mrb_code)((c) & 0x1ff) << 14) #define MKARG_C(c) (((c) & 0x7f) << 7) -#define MKARG_Bx(v) (((v) & 0xffff) << 7) +#define MKARG_Bx(v) ((mrb_code)((v) & 0xffff) << 7) #define MKARG_sBx(v) MKARG_Bx((v)+MAXARG_sBx) -#define MKARG_Ax(v) (((v) & 0x1ffffff) << 7) +#define MKARG_Ax(v) ((mrb_code)((v) & 0x1ffffff) << 7) #define MKARG_PACK(b,n1,c,n2) ((((b) & ((1<<n1)-1)) << (7+n2))|(((c) & ((1<<n2)-1)) << 7)) #define MKARG_bc(b,c) MKARG_PACK(b,14,c,2) diff --git a/src/parse.y b/src/parse.y index 62393a0bb..29ea34c59 100644 --- a/src/parse.y +++ b/src/parse.y @@ -25,6 +25,7 @@ #include <errno.h> #include <ctype.h> #include <string.h> +#include <stdlib.h> #define YYLEX_PARAM p @@ -60,13 +61,27 @@ typedef unsigned int stack_type; #define sym(x) ((mrb_sym)(intptr_t)(x)) #define nsym(x) ((node*)(intptr_t)(x)) -static mrb_sym +static inline mrb_sym intern_gen(parser_state *p, const char *s) { return mrb_intern(p->mrb, s); } #define intern(s) intern_gen(p,(s)) +static inline mrb_sym +intern_gen2(parser_state *p, const char *s, size_t len) +{ + return mrb_intern2(p->mrb, s, len); +} +#define intern2(s,len) intern_gen2(p,(s),(len)) + +static inline mrb_sym +intern_gen_c(parser_state *p, const char c) +{ + return mrb_intern2(p->mrb, &c, 1); +} +#define intern_c(c) intern_gen_c(p,(c)) + static void cons_free_gen(parser_state *p, node *cons) { @@ -701,6 +716,20 @@ new_dstr(parser_state *p, node *a) return cons((node*)NODE_DSTR, a); } +// (:str . (s . len)) +static node* +new_xstr(parser_state *p, const char *s, int len) +{ + return cons((node*)NODE_XSTR, cons((node*)strndup(s, len), (node*)(intptr_t)len)); +} + +// (:xstr . a) +static node* +new_dxstr(parser_state *p, node *a) +{ + return cons((node*)NODE_DXSTR, a); +} + // (:dsym . a) static node* new_dsym(parser_state *p, node *a) @@ -749,6 +778,26 @@ new_bv(parser_state *p, mrb_sym id) { } +static node* +new_literal_delim(parser_state *p) +{ + return cons((node*)NODE_LITERAL_DELIM, 0); +} + +// (:words . a) +static node* +new_words(parser_state *p, node *a) +{ + return cons((node*)NODE_WORDS, a); +} + +// (:symbols . a) +static node* +new_symbols(parser_state *p, node *a) +{ + return cons((node*)NODE_SYMBOLS, a); +} + // xxx ----------------------------- // (:call a op) @@ -843,48 +892,21 @@ var_reference(parser_state *p, node *lhs) return lhs; } +typedef enum mrb_string_type string_type; static node* -heredoc_start_sb(parser_state *p, const char* term, size_t term_len, enum heredoc_type type, int allow_indent) -{ - node *newnode = new_heredoc(p); - parser_heredoc_info *inf = (parser_heredoc_info*)newnode->cdr; - inf->term = term; - inf->term_len = term_len; - inf->type = type; - inf->allow_indent = allow_indent; - inf->line_head = TRUE; - inf->doc = NULL; - p->heredocs = push(p->heredocs, newnode); - if (p->parsing_heredoc == NULL) { - node *c = p->heredocs; - while (c->cdr) - c = c->cdr; - p->parsing_heredoc = c; - } - p->heredoc_starts_nextline = TRUE; - p->lstate = EXPR_END; - return newnode; -} - -static node* -heredoc_start(parser_state *p, node *beg, node *str, enum heredoc_type type) +new_strterm(parser_state *p, string_type type, int term, int paren) { - char *bs = (char*)beg->cdr->car; - int allow_indent = (bs[2] == '-'); - const char *s = (char*)str->cdr->car; - size_t len = (intptr_t)str->cdr->cdr; - return heredoc_start_sb(p, s, len, type, allow_indent); + return cons((node*)(intptr_t)type, cons((node*)0, cons((node*)(intptr_t)paren, (node*)(intptr_t)term))); } -static node* -heredoc_start_sym(parser_state *p, node *beg, mrb_sym sym, enum heredoc_type type) +static void +end_strterm(parser_state *p) { - char *bs = (char*)beg->cdr->car; - int allow_indent = (bs[2] == '-'); - int len; - const char *s = mrb_sym2name_len(p->mrb, sym, &len); - return heredoc_start_sb(p, s, len, type, allow_indent); + cons_free(p->lex_strterm->cdr->cdr); + cons_free(p->lex_strterm->cdr); + cons_free(p->lex_strterm); + p->lex_strterm = NULL; } parser_heredoc_info * @@ -904,19 +926,19 @@ heredoc_end(parser_state *p) if (p->parsing_heredoc == NULL) { p->lstate = EXPR_BEG; p->cmd_start = TRUE; - p->sterm = 0; + end_strterm(p); p->heredoc_end_now = TRUE; } else { - p->sterm = ' '; /* next heredoc */ + /* next heredoc */ + p->lex_strterm->car = (node*)(intptr_t)parsing_heredoc_inf(p)->type; } } - +#define is_strterm_type(p,str_func) ((int)(intptr_t)((p)->lex_strterm->car) & (str_func)) // xxx ----------------------------- %} -%expect 2 %pure_parser %parse-param {parser_state *p} %lex-param {parser_state *p} @@ -980,12 +1002,12 @@ heredoc_end(parser_state *p) keyword__ENCODING__ %token <id> tIDENTIFIER tFID tGVAR tIVAR tCONSTANT tCVAR tLABEL -%token <nd> tINTEGER tFLOAT tCHAR tREGEXP -%token <nd> tSTRING tSTRING_PART +%token <nd> tINTEGER tFLOAT tCHAR tXSTRING tREGEXP +%token <nd> tSTRING tSTRING_PART tSTRING_MID %token <nd> tNTH_REF tBACK_REF %token <num> tREGEXP_END -%type <nd> singleton string string_interp regexp +%type <nd> singleton string string_rep string_interp xstring regexp %type <nd> literal numeric cpath symbol %type <nd> top_compstmt top_stmts top_stmt %type <nd> bodystmt compstmt stmts stmt expr arg primary command command_call method_call @@ -1004,7 +1026,7 @@ heredoc_end(parser_state *p) %type <nd> mlhs mlhs_list mlhs_post mlhs_basic mlhs_item mlhs_node mlhs_inner %type <id> fsym sym basic_symbol operation operation2 operation3 %type <id> cname fname op f_rest_arg f_block_arg opt_f_block_arg f_norm_arg -%type <nd> heredoc heredoc_rep heredoc_interp +%type <nd> heredoc words symbols %token tUPLUS /* unary+ */ %token tUMINUS /* unary- */ @@ -1033,10 +1055,10 @@ heredoc_end(parser_state *p) %token tSTAR /* * */ %token tAMPER /* & */ %token tLAMBDA /* -> */ -%token tSYMBEG tREGEXP_BEG tWORDS_BEG tQWORDS_BEG -%token tSTRING_BEG tSTRING_DVAR tLAMBEG +%token tSYMBEG tREGEXP_BEG tWORDS_BEG tSYMBOLS_BEG +%token tSTRING_BEG tXSTRING_BEG tSTRING_DVAR tLAMBEG %token <nd> tHEREDOC_BEG /* <<, <<- */ -%token tHEREDOC_END +%token tHEREDOC_END tLITERAL_DELIM /* * precedence table @@ -1096,7 +1118,7 @@ top_compstmt : top_stmts opt_terms ; top_stmts : none - { + { $$ = new_begin(p, 0); } | top_stmt @@ -1159,7 +1181,7 @@ compstmt : stmts opt_terms ; stmts : none - { + { $$ = new_begin(p, 0); } | stmt @@ -1220,7 +1242,7 @@ stmt : keyword_alias fsym {p->lstate = EXPR_FNAME;} fsym } | primary_value '[' opt_call_args rbracket tOP_ASGN command_call { - $$ = new_op_asgn(p, new_call(p, $1, intern("[]"), $3), $5, $6); + $$ = new_op_asgn(p, new_call(p, $1, intern2("[]",2), $3), $5, $6); } | primary_value '.' tIDENTIFIER tOP_ASGN command_call { @@ -1459,7 +1481,7 @@ mlhs_node : variable } | primary_value '[' opt_call_args rbracket { - $$ = new_call(p, $1, intern("[]"), $3); + $$ = new_call(p, $1, intern2("[]",2), $3); } | primary_value '.' tIDENTIFIER { @@ -1498,7 +1520,7 @@ lhs : variable } | primary_value '[' opt_call_args rbracket { - $$ = new_call(p, $1, intern("[]"), $3); + $$ = new_call(p, $1, intern2("[]",2), $3); } | primary_value '.' tIDENTIFIER { @@ -1581,34 +1603,35 @@ undef_list : fsym } ; -op : '|' { $$ = intern("|"); } - | '^' { $$ = intern("^"); } - | '&' { $$ = intern("&"); } - | tCMP { $$ = intern("<=>"); } - | tEQ { $$ = intern("=="); } - | tEQQ { $$ = intern("==="); } - | tMATCH { $$ = intern("=~"); } - | tNMATCH { $$ = intern("!~"); } - | '>' { $$ = intern(">"); } - | tGEQ { $$ = intern(">="); } - | '<' { $$ = intern("<"); } - | tLEQ { $$ = intern("<="); } - | tNEQ { $$ = intern("!="); } - | tLSHFT { $$ = intern("<<"); } - | tRSHFT { $$ = intern(">>"); } - | '+' { $$ = intern("+"); } - | '-' { $$ = intern("-"); } - | '*' { $$ = intern("*"); } - | tSTAR { $$ = intern("*"); } - | '/' { $$ = intern("/"); } - | '%' { $$ = intern("%"); } - | tPOW { $$ = intern("**"); } - | '!' { $$ = intern("!"); } - | '~' { $$ = intern("~"); } - | tUPLUS { $$ = intern("+@"); } - | tUMINUS { $$ = intern("-@"); } - | tAREF { $$ = intern("[]"); } - | tASET { $$ = intern("[]="); } +op : '|' { $$ = intern_c('|'); } + | '^' { $$ = intern_c('^'); } + | '&' { $$ = intern_c('&'); } + | tCMP { $$ = intern2("<=>",3); } + | tEQ { $$ = intern2("==",2); } + | tEQQ { $$ = intern2("===",3); } + | tMATCH { $$ = intern2("=~",2); } + | tNMATCH { $$ = intern2("!~",2); } + | '>' { $$ = intern_c('>'); } + | tGEQ { $$ = intern2(">=",2); } + | '<' { $$ = intern_c('<'); } + | tLEQ { $$ = intern2("<=",2); } + | tNEQ { $$ = intern2("!=",2); } + | tLSHFT { $$ = intern2("<<",2); } + | tRSHFT { $$ = intern2(">>",2); } + | '+' { $$ = intern_c('+'); } + | '-' { $$ = intern_c('-'); } + | '*' { $$ = intern_c('*'); } + | tSTAR { $$ = intern_c('*'); } + | '/' { $$ = intern_c('/'); } + | '%' { $$ = intern_c('%'); } + | tPOW { $$ = intern2("**",2); } + | '!' { $$ = intern_c('!'); } + | '~' { $$ = intern_c('~'); } + | tUPLUS { $$ = intern2("+@",2); } + | tUMINUS { $$ = intern2("-@",2); } + | tAREF { $$ = intern2("[]",2); } + | tASET { $$ = intern2("[]=",3); } + | '`' { $$ = intern_c('`'); } ; reswords : keyword__LINE__ | keyword__FILE__ | keyword__ENCODING__ @@ -1643,7 +1666,7 @@ arg : lhs '=' arg } | primary_value '[' opt_call_args rbracket tOP_ASGN arg { - $$ = new_op_asgn(p, new_call(p, $1, intern("[]"), $3), $5, $6); + $$ = new_op_asgn(p, new_call(p, $1, intern2("[]",2), $3), $5, $6); } | primary_value '.' tIDENTIFIER tOP_ASGN arg { @@ -1942,6 +1965,7 @@ mrhs : args ',' arg_value primary : literal | string + | xstring | regexp | heredoc | var_ref @@ -2281,7 +2305,7 @@ block_param : f_arg ',' f_block_optarg ',' f_rest_arg opt_f_block_arg { $$ = new_args(p, $1, $3, 0, $5, $6); } - | f_arg ',' f_rest_arg opt_f_block_arg + | f_arg ',' f_rest_arg opt_f_block_arg { $$ = new_args(p, $1, 0, $3, 0, $4); } @@ -2413,7 +2437,7 @@ block_call : command do_block yyerror(p, "block given to yield"); } else { - call_with_block(p, $1, $2); + call_with_block(p, $1, $2); } $$ = $1; } @@ -2451,11 +2475,11 @@ method_call : operation paren_args } | primary_value '.' paren_args { - $$ = new_call(p, $1, intern("call"), $3); + $$ = new_call(p, $1, intern2("call",4), $3); } | primary_value tCOLON2 paren_args { - $$ = new_call(p, $1, intern("call"), $3); + $$ = new_call(p, $1, intern2("call",4), $3); } | keyword_super paren_args { @@ -2467,7 +2491,7 @@ method_call : operation paren_args } | primary_value '[' opt_call_args rbracket { - $$ = new_call(p, $1, intern("[]"), $3); + $$ = new_call(p, $1, intern2("[]",2), $3); } ; @@ -2547,6 +2571,8 @@ opt_ensure : keyword_ensure compstmt literal : numeric | symbol + | words + | symbols ; string : tCHAR @@ -2555,65 +2581,62 @@ string : tCHAR { $$ = $2; } - | tSTRING_BEG string_interp tSTRING + | tSTRING_BEG string_rep tSTRING { $$ = new_dstr(p, push($2, $3)); } ; -string_interp : tSTRING_PART +string_rep : string_interp + | string_rep string_interp { - $<num>$ = p->sterm; - p->sterm = 0; + $$ = append($1, $2); } - compstmt - '}' + ; + +string_interp : tSTRING_MID { - p->sterm = $<num>2; - $$ = list2($1, $3); + $$ = list1($1); } - | string_interp - tSTRING_PART + | tSTRING_PART { - $<num>$ = p->sterm; - p->sterm = 0; + $<nd>$ = p->lex_strterm; + p->lex_strterm = NULL; } compstmt '}' { - p->sterm = $<num>3; - $$ = push(push($1, $2), $4); + p->lex_strterm = $<nd>2; + $$ = list2($1, $3); + } + | tLITERAL_DELIM + { + $$ = list1(new_literal_delim(p)); } ; -regexp : tREGEXP_BEG tREGEXP +xstring : tXSTRING_BEG tXSTRING { $$ = $2; } - | tREGEXP_BEG string_interp tREGEXP + | tXSTRING_BEG string_rep tXSTRING { - $$ = new_dregx(p, $2, $3); + $$ = new_dxstr(p, push($2, $3)); } ; -heredoc : tHEREDOC_BEG tSTRING_BEG tSTRING - { - $$ = heredoc_start(p, $1, $3, heredoc_type_norm); - } - | tHEREDOC_BEG tSTRING - { - $$ = heredoc_start(p, $1, $2, heredoc_type_quote); - } - | tHEREDOC_BEG tIDENTIFIER +regexp : tREGEXP_BEG tREGEXP { - $$ = heredoc_start_sym(p, $1, $2, heredoc_type_norm); + $$ = $2; } - | tHEREDOC_BEG tCONSTANT + | tREGEXP_BEG string_rep tREGEXP { - $$ = heredoc_start_sym(p, $1, $2, heredoc_type_norm); + $$ = new_dregx(p, $2, $3); } ; +heredoc : tHEREDOC_BEG + ; opt_heredoc_bodies : none | heredoc_bodies @@ -2625,42 +2648,27 @@ heredoc_bodies : heredoc_body heredoc_body : tHEREDOC_END { - /* assert(parsing_heredoc_inf(p) != NULL); */ parsing_heredoc_inf(p)->doc = list1(new_str(p, "", 0)); heredoc_end(p); } - | heredoc_rep tHEREDOC_END + | string_rep tHEREDOC_END { - /* assert(parsing_heredoc_inf(p) != NULL); */ parsing_heredoc_inf(p)->doc = $1; heredoc_end(p); } ; -heredoc_rep : heredoc_interp - | heredoc_rep heredoc_interp +words : tWORDS_BEG tSTRING { - $$ = append($1, $2); + $$ = new_words(p, list1($2)); } - ; - -heredoc_interp : tSTRING + | tWORDS_BEG string_rep tSTRING { - $$ = list1($1); - } - | tSTRING_PART - { - $<num>$ = p->sterm; - p->sterm = 0; - } - compstmt - '}' - { - p->sterm = $<num>2; - $$ = list2($1, $3); + $$ = new_words(p, push($2, $3)); } ; + symbol : basic_symbol { $$ = new_sym(p, $1); @@ -2693,6 +2701,16 @@ sym : fname } ; +symbols : tSYMBOLS_BEG tSTRING + { + $$ = new_symbols(p, list1($2)); + } + | tSYMBOLS_BEG string_rep tSTRING + { + $$ = new_symbols(p, push($2, $3)); + } + ; + numeric : tINTEGER | tFLOAT | tUMINUS_NUM tINTEGER %prec tLOWEST @@ -3007,6 +3025,8 @@ singleton : var_ref switch ((enum node_type)(int)(intptr_t)$3->car) { case NODE_STR: case NODE_DSTR: + case NODE_XSTR: + case NODE_DXSTR: case NODE_DREGX: case NODE_MATCH: case NODE_FLOAT: @@ -3232,7 +3252,6 @@ nextc(parser_state *p) else { c = (unsigned char)*p->s++; } - /* if (c == '\n') { } */ /* heredoc treated in parser_yylex() */ } p->column++; return c; @@ -3315,7 +3334,7 @@ skips(parser_state *p, const char *s) int len = strlen(s); while (len--) { - nextc(p); + nextc(p); } return TRUE; } @@ -3326,23 +3345,6 @@ skips(parser_state *p, const char *s) return FALSE; } -#define STR_FUNC_ESCAPE 0x01 -#define STR_FUNC_EXPAND 0x02 -#define STR_FUNC_REGEXP 0x04 -#define STR_FUNC_QWORDS 0x08 -#define STR_FUNC_SYMBOL 0x10 -#define STR_FUNC_INDENT 0x20 - -enum string_type { - str_squote = (0), - str_dquote = (STR_FUNC_EXPAND), - str_xquote = (STR_FUNC_EXPAND), - str_regexp = (STR_FUNC_REGEXP|STR_FUNC_ESCAPE|STR_FUNC_EXPAND), - str_sword = (STR_FUNC_QWORDS), - str_dword = (STR_FUNC_QWORDS|STR_FUNC_EXPAND), - str_ssym = (STR_FUNC_SYMBOL), - str_dsym = (STR_FUNC_SYMBOL|STR_FUNC_EXPAND) -}; static int newtok(parser_state *p) @@ -3354,7 +3356,7 @@ newtok(parser_state *p) static void tokadd(parser_state *p, int c) { - if (p->bidx < 1024) { + if (p->bidx < MRB_PARSER_BUF_SIZE) { p->buf[p->bidx++] = c; } } @@ -3368,7 +3370,7 @@ toklast(parser_state *p) static void tokfix(parser_state *p) { - if (p->bidx >= 1024) { + if (p->bidx >= MRB_PARSER_BUF_SIZE) { yyerror(p, "string too long (truncated)"); } p->buf[p->bidx] = '\0'; @@ -3393,34 +3395,38 @@ toklen(parser_state *p) #define IS_LABEL_POSSIBLE() ((p->lstate == EXPR_BEG && !cmd_state) || IS_ARG()) #define IS_LABEL_SUFFIX(n) (peek_n(p, ':',(n)) && !peek_n(p, ':', (n)+1)) -static unsigned long +static int scan_oct(const int *start, int len, int *retlen) { const int *s = start; - unsigned long retval = 0; + int retval = 0; + /* assert(len <= 3) */ while (len-- && *s >= '0' && *s <= '7') { retval <<= 3; retval |= *s++ - '0'; } *retlen = s - start; + return retval; } -static unsigned long +static int scan_hex(const int *start, int len, int *retlen) { static const char hexdigit[] = "0123456789abcdef0123456789ABCDEF"; register const int *s = start; - register unsigned long retval = 0; + register int retval = 0; char *tmp; - while (len-- && *s && (tmp = (char *)strchr(hexdigit, *s))) { + /* assert(len <= 2) */ + while (len-- && *s && (tmp = strchr(hexdigit, *s))) { retval <<= 4; retval |= (tmp - hexdigit) & 15; s++; } *retlen = s - start; + return retval; } @@ -3457,19 +3463,19 @@ read_escape(parser_state *p) case '0': case '1': case '2': case '3': /* octal constant */ case '4': case '5': case '6': case '7': { - int buf[3]; - int i; + int buf[3]; + int i; - buf[0] = c; - for (i=1; i<3; i++) { + buf[0] = c; + for (i=1; i<3; i++) { buf[i] = nextc(p); if (buf[i] == -1) goto eof; - if (buf[i] < '0' || '7' < buf[i]) { - pushback(p, buf[i]); - break; - } - } - c = scan_oct(buf, i, &i); + if (buf[i] < '0' || '7' < buf[i]) { + pushback(p, buf[i]); + break; + } + } + c = scan_oct(buf, i, &i); } return c; @@ -3479,33 +3485,25 @@ read_escape(parser_state *p) int i; for (i=0; i<2; i++) { - buf[i] = nextc(p); - if (buf[i] == -1) goto eof; - if (!isxdigit(buf[i])) { - pushback(p, buf[i]); - break; - } + buf[i] = nextc(p); + if (buf[i] == -1) goto eof; + if (!isxdigit(buf[i])) { + pushback(p, buf[i]); + break; + } } c = scan_hex(buf, i, &i); if (i == 0) { - yyerror(p, "Invalid escape character syntax"); - return 0; + yyerror(p, "Invalid escape character syntax"); + return 0; } } return c; case 'b': /* backspace */ - if (p->regexp) { - tokadd(p, '\\'); - return 'b'; - } return '\010'; case 's': /* space */ - if (p->regexp) { - tokadd(p, '\\'); - return 's'; - } return ' '; case 'M': @@ -3543,57 +3541,154 @@ read_escape(parser_state *p) return '\0'; default: - if (p->regexp) { - tokadd(p, '\\'); - } return c; } } + static int -parse_string(parser_state *p, int term) +parse_string(parser_state *p) { int c; + string_type type = (string_type)(intptr_t)p->lex_strterm->car; + int nest_level = (intptr_t)p->lex_strterm->cdr->car; + int beg = (intptr_t)p->lex_strterm->cdr->cdr->car; + int end = (intptr_t)p->lex_strterm->cdr->cdr->cdr; + parser_heredoc_info *hinf = (type & STR_FUNC_HEREDOC) ? parsing_heredoc_inf(p) : NULL; newtok(p); - while ((c = nextc(p)) != term) { - if (c == -1) { + while ((c = nextc(p)) != end || nest_level != 0) { + if (hinf && (c == '\n' || c == -1)) { + int line_head; + tokadd(p, '\n'); + tokfix(p); + p->lineno++; + p->column = 0; + line_head = hinf->line_head; + hinf->line_head = TRUE; + if (line_head) { + /* check whether end of heredoc */ + const char *s = tok(p); + int len = toklen(p); + if (hinf->allow_indent) { + while (ISSPACE(*s) && len > 0) { + ++s; + --len; + } + } + if ((len-1 == hinf->term_len) && (strncmp(s, hinf->term, len-1) == 0)) { + return tHEREDOC_END; + } + } + if (c == -1) { + char buf[256]; + snprintf(buf, sizeof(buf), "can't find string \"%s\" anywhere before EOF", hinf->term); + yyerror(p, buf); + return 0; + } + yylval.nd = new_str(p, tok(p), toklen(p)); + return tSTRING_MID; + } + if (c == -1) { yyerror(p, "unterminated string meets end of file"); return 0; } + else if (c == beg) { + nest_level++; + p->lex_strterm->cdr->car = (node*)(intptr_t)nest_level; + } + else if (c == end) { + nest_level--; + p->lex_strterm->cdr->car = (node*)(intptr_t)nest_level; + } else if (c == '\\') { c = nextc(p); - if (c == term) { - tokadd(p, c); - } - else { - pushback(p, c); - tokadd(p, read_escape(p)); + if (type & STR_FUNC_EXPAND) { + if (c == end || c == beg) { + tokadd(p, c); + } + else if ((c == '\n') && (type & STR_FUNC_ARRAY)) { + p->lineno++; + p->column = 0; + tokadd(p, '\n'); + } + else { + pushback(p, c); + + if(type & STR_FUNC_REGEXP) + tokadd(p, '\\'); + + tokadd(p, read_escape(p)); + if (hinf) + hinf->line_head = FALSE; + } + } else { + if (c != beg && c != end) { + switch (c) { + case '\n': + p->lineno++; + p->column = 0; + break; + + case '\\': + break; + + default: + if (! ISSPACE(c)) + tokadd(p, '\\'); + } + } + tokadd(p, c); } continue; } - if (c == '#') { + else if ((c == '#') && (type & STR_FUNC_EXPAND)) { c = nextc(p); if (c == '{') { - tokfix(p); - p->lstate = EXPR_BEG; - p->sterm = term; - p->cmd_start = TRUE; - yylval.nd = new_str(p, tok(p), toklen(p)); - return tSTRING_PART; + tokfix(p); + p->lstate = EXPR_BEG; + p->cmd_start = TRUE; + yylval.nd = new_str(p, tok(p), toklen(p)); + if (hinf) + hinf->line_head = FALSE; + return tSTRING_PART; } tokadd(p, '#'); pushback(p, c); continue; } + if ((type & STR_FUNC_ARRAY) && ISSPACE(c)) { + if (toklen(p) == 0) { + do { + if (c == '\n') { + p->lineno++; + p->column = 0; + } + } while (ISSPACE(c = nextc(p))); + pushback(p, c); + return tLITERAL_DELIM; + } else { + pushback(p, c); + tokfix(p); + yylval.nd = new_str(p, tok(p), toklen(p)); + return tSTRING_MID; + } + } + tokadd(p, c); - } + + } tokfix(p); p->lstate = EXPR_END; - p->sterm = 0; + end_strterm(p); - if (p->regexp) { + if (type & STR_FUNC_XQUOTE) { + yylval.nd = new_xstr(p, tok(p), toklen(p)); + return tXSTRING; + } + + if (type & STR_FUNC_REGEXP) { int f = 0; int c; char *s = strndup(tok(p), toklen(p)); @@ -3613,14 +3708,13 @@ parse_string(parser_state *p, int term) char msg[128]; tokfix(p); snprintf(msg, sizeof(msg), "unknown regexp option%s - %s", - toklen(p) > 1 ? "s" : "", tok(p)); + toklen(p) > 1 ? "s" : "", tok(p)); yyerror(p, msg); } if (f & 1) strcat(flag, "i"); if (f & 2) strcat(flag, "x"); if (f & 4) strcat(flag, "m"); yylval.nd = new_regx(p, s, strdup(flag)); - p->regexp = 0; return tREGEXP; } @@ -3628,128 +3722,78 @@ parse_string(parser_state *p, int term) yylval.nd = new_str(p, tok(p), toklen(p)); return tSTRING; } + -static node* -qstring_node(parser_state *p, int beg, int end) +static int +heredoc_identifier(parser_state *p) { int c; - int nest_level = 0; - - newtok(p); - while ((c = nextc(p)) != end || nest_level != 0) { - if (c == -1) { - yyerror(p, "unterminated string meets end of file"); - return 0; - } - else if (c == beg) { - nest_level++; - } - else if (c == end) { - nest_level--; - } - else if (c == '\\') { - c = nextc(p); - if (c != beg && c != end) { - switch (c) { - case '\n': - p->lineno++; - p->column = 0; - continue; - - case '\\': - c = '\\'; - break; - - default: - tokadd(p, '\\'); - } - } - } - tokadd(p, c); + int type = str_heredoc; + int indent = FALSE; + int quote = FALSE; + node *newnode; + parser_heredoc_info *info; + + c = nextc(p); + if (ISSPACE(c) || c == '=') { + pushback(p, c); + return 0; } - - tokfix(p); - p->lstate = EXPR_END; - return new_str(p, tok(p), toklen(p)); -} - -static int -parse_qstring(parser_state *p, int beg, int end) -{ - node *nd = qstring_node(p, beg, end); - - if (nd) { - yylval.nd = nd; - return tSTRING; + if (c == '-') { + indent = TRUE; + c = nextc(p); } - return 0; -} - -static int -parse_heredoc_line(parser_state *p) -{ - parser_heredoc_info *inf = parsing_heredoc_inf(p); - /* assert(inf != NULL); */ - int c; - int line_head; - - newtok(p); - while ((c = nextc(p)) != '\n') { - if (c == -1) - break; - if (inf->type != heredoc_type_quote) { - if (c == '\\') { - tokadd(p, read_escape(p)); - inf->line_head = FALSE; - continue; - } - if (c == '#') { - c = nextc(p); - if (c == '{') { - tokfix(p); - p->lstate = EXPR_BEG; - p->sterm = ' '; - p->cmd_start = TRUE; - yylval.nd = new_str(p, tok(p), toklen(p)); - inf->line_head = FALSE; - return tSTRING_PART; - } - tokadd(p, '#'); - pushback(p, c); - continue; + if (c == '\'' || c == '"') { + int term = c; + if (c == '\'') + quote = TRUE; + newtok(p); + while ((c = nextc(p)) != -1 && c != term) { + if (c == '\n') { + c = -1; + break; } + tokadd(p, c); } - tokadd(p, c); - } - tokadd(p, '\n'); - tokfix(p); - p->lineno++; - p->column = 0; - line_head = inf->line_head; - inf->line_head = TRUE; - if (line_head) { - /* check whether end of heredoc */ - const char *s = tok(p); - int len = toklen(p); - if (inf->allow_indent) { - while (ISSPACE(*s) && len > 0) { - ++s; - --len; - } + if (c == -1) { + yyerror(p, "unterminated here document identifier"); + return 0; } - if ((len-1 == inf->term_len) && (strncmp(s, inf->term, len-1) == 0)) { - return tHEREDOC_END; + } else { + if (! identchar(c)) { + pushback(p, c); + if (indent) pushback(p, '-'); + return 0; } + newtok(p); + do { + tokadd(p, c); + } while ((c = nextc(p)) != -1 && identchar(c)); + pushback(p, c); } - if (c == -1) { - char buf[256]; - snprintf(buf, sizeof(buf), "can't find string \"%s\" anywhere before EOF", inf->term); - yyerror(p, buf); - return 0; + tokfix(p); + newnode = new_heredoc(p); + info = (parser_heredoc_info*)newnode->cdr; + info->term = strndup(tok(p), toklen(p)); + info->term_len = toklen(p); + if (! quote) + type |= STR_FUNC_EXPAND; + info->type = type; + info->allow_indent = indent; + info->line_head = TRUE; + info->doc = NULL; + p->heredocs = push(p->heredocs, newnode); + if (p->parsing_heredoc == NULL) { + node *n = p->heredocs; + while (n->cdr) + n = n->cdr; + p->parsing_heredoc = n; } + p->heredoc_starts_nextline = TRUE; + p->lstate = EXPR_END; - yylval.nd = new_str(p, tok(p), toklen(p)); - return tSTRING; + yylval.nd = newnode; + return tHEREDOC_BEG; } static int @@ -3765,17 +3809,18 @@ static int parser_yylex(parser_state *p) { register int c; - int c2; int space_seen = 0; int cmd_state; enum mrb_lex_state_enum last_state; int token_column; - if ((p->sterm == ' ') && (p->parsing_heredoc != NULL) && (! p->heredoc_starts_nextline)) { - return parse_heredoc_line(p); - } - if (p->sterm) { - return parse_string(p, p->sterm); + if (p->lex_strterm) { + if (is_strterm_type(p, STR_FUNC_HEREDOC)) { + if ((p->parsing_heredoc != NULL) && (! p->heredoc_starts_nextline)) + return parse_string(p); + } + else + return parse_string(p); } cmd_state = p->cmd_start; p->cmd_start = FALSE; @@ -3800,7 +3845,7 @@ parser_yylex(parser_state *p) case '\n': p->heredoc_starts_nextline = FALSE; if (p->parsing_heredoc != NULL) { - p->sterm = ' '; + p->lex_strterm = new_strterm(p, parsing_heredoc_inf(p)->type, 0, 0); goto normal_newline; } switch (p->lstate) { @@ -3819,19 +3864,19 @@ parser_yylex(parser_state *p) switch (c) { case ' ': case '\t': case '\f': case '\r': case '\13': /* '\v' */ - space_seen = 1; - break; + space_seen = 1; + break; case '.': - if ((c = nextc(p)) != '.') { - pushback(p, c); - pushback(p, '.'); - goto retry; - } + if ((c = nextc(p)) != '.') { + pushback(p, c); + pushback(p, '.'); + goto retry; + } case -1: /* EOF */ - goto normal_newline; + goto normal_newline; default: - pushback(p, c); - goto normal_newline; + pushback(p, c); + goto normal_newline; } } normal_newline: @@ -3842,29 +3887,29 @@ parser_yylex(parser_state *p) case '*': if ((c = nextc(p)) == '*') { if ((c = nextc(p)) == '=') { - yylval.id = intern("**"); - p->lstate = EXPR_BEG; - return tOP_ASGN; + yylval.id = intern2("**",2); + p->lstate = EXPR_BEG; + return tOP_ASGN; } pushback(p, c); c = tPOW; } else { if (c == '=') { - yylval.id = intern("*"); - p->lstate = EXPR_BEG; - return tOP_ASGN; + yylval.id = intern_c('*'); + p->lstate = EXPR_BEG; + return tOP_ASGN; } pushback(p, c); if (IS_SPCARG(c)) { - yywarning(p, "`*' interpreted as argument prefix"); - c = tSTAR; + yywarning(p, "`*' interpreted as argument prefix"); + c = tSTAR; } else if (IS_BEG()) { - c = tSTAR; + c = tSTAR; } else { - c = '*'; + c = '*'; } } if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) { @@ -3879,7 +3924,7 @@ parser_yylex(parser_state *p) if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) { p->lstate = EXPR_ARG; if (c == '@') { - return '!'; + return '!'; } } else { @@ -3897,7 +3942,7 @@ parser_yylex(parser_state *p) case '=': if (p->column == 1) { if (peeks(p, "begin\n")) { - skips(p, "\n=end\n"); + skips(p, "\n=end\n"); goto retry; } } @@ -3908,7 +3953,7 @@ parser_yylex(parser_state *p) } if ((c = nextc(p)) == '=') { if ((c = nextc(p)) == '=') { - return tEQQ; + return tEQQ; } pushback(p, c); return tEQ; @@ -3926,45 +3971,34 @@ parser_yylex(parser_state *p) last_state = p->lstate; c = nextc(p); if (c == '<' && - p->lstate != EXPR_DOT && - p->lstate != EXPR_CLASS && - !IS_END() && - (!IS_ARG() || space_seen)) { - /* heredocument check */ - newtok(p); tokadd(p, '<'); tokadd(p, '<'); - c2 = nextc(p); - if (c2 == '-') { - tokadd(p, c2); - c2 = nextc(p); - } - pushback(p, c2); - if (!ISSPACE(c2)) { - tokfix(p); - yylval.nd = new_str(p, tok(p), toklen(p)); - p->lstate = EXPR_DOT; - return tHEREDOC_BEG; - } + p->lstate != EXPR_DOT && + p->lstate != EXPR_CLASS && + !IS_END() && + (!IS_ARG() || space_seen)) { + int token = heredoc_identifier(p); + if (token) + return token; } if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) { p->lstate = EXPR_ARG; } else { p->lstate = EXPR_BEG; if (p->lstate == EXPR_CLASS) { - p->cmd_start = TRUE; + p->cmd_start = TRUE; } } if (c == '=') { if ((c = nextc(p)) == '>') { - return tCMP; + return tCMP; } pushback(p, c); return tLEQ; } if (c == '<') { if ((c = nextc(p)) == '=') { - yylval.id = intern("<<"); - p->lstate = EXPR_BEG; - return tOP_ASGN; + yylval.id = intern2("<<",2); + p->lstate = EXPR_BEG; + return tOP_ASGN; } pushback(p, c); return tLSHFT; @@ -3983,9 +4017,9 @@ parser_yylex(parser_state *p) } if (c == '>') { if ((c = nextc(p)) == '=') { - yylval.id = intern(">>"); - p->lstate = EXPR_BEG; - return tOP_ASGN; + yylval.id = intern2(">>",2); + p->lstate = EXPR_BEG; + return tOP_ASGN; } pushback(p, c); return tRSHFT; @@ -3994,11 +4028,27 @@ parser_yylex(parser_state *p) return '>'; case '"': - p->sterm = '"'; + p->lex_strterm = new_strterm(p, str_dquote, '"', 0); return tSTRING_BEG; case '\'': - return parse_qstring(p, '\'', '\''); + p->lex_strterm = new_strterm(p, str_squote, '\'', 0); + return parse_string(p); + + case '`': + if (p->lstate == EXPR_FNAME) { + p->lstate = EXPR_ENDFN; + return '`'; + } + if (p->lstate == EXPR_DOT) { + if (cmd_state) + p->lstate = EXPR_CMDARG; + else + p->lstate = EXPR_ARG; + return '`'; + } + p->lex_strterm = new_strterm(p, str_xquote, '`', 0); + return tXSTRING_BEG; case '?': if (IS_END()) { @@ -4012,35 +4062,35 @@ parser_yylex(parser_state *p) } if (isspace(c)) { if (!IS_ARG()) { - int c2; - switch (c) { - case ' ': - c2 = 's'; - break; - case '\n': - c2 = 'n'; - break; - case '\t': - c2 = 't'; - break; - case '\v': - c2 = 'v'; - break; - case '\r': - c2 = 'r'; - break; - case '\f': - c2 = 'f'; - break; - default: - c2 = 0; - break; - } - if (c2) { - char buf[256]; - snprintf(buf, sizeof(buf), "invalid character syntax; use ?\\%c", c2); - yyerror(p, buf); - } + int c2; + switch (c) { + case ' ': + c2 = 's'; + break; + case '\n': + c2 = 'n'; + break; + case '\t': + c2 = 't'; + break; + case '\v': + c2 = 'v'; + break; + case '\r': + c2 = 'r'; + break; + case '\f': + c2 = 'f'; + break; + default: + c2 = 0; + break; + } + if (c2) { + char buf[256]; + snprintf(buf, sizeof(buf), "invalid character syntax; use ?\\%c", c2); + yyerror(p, buf); + } } ternary: pushback(p, c); @@ -4053,20 +4103,20 @@ parser_yylex(parser_state *p) int c2 = nextc(p); pushback(p, c2); if ((isalnum(c2) || c2 == '_')) { - goto ternary; + goto ternary; } } if (c == '\\') { c = nextc(p); if (c == 'u') { #if 0 - tokadd_utf8(p); + tokadd_utf8(p); #endif } else { - pushback(p, c); - c = read_escape(p); - tokadd(p, c); + pushback(p, c); + c = read_escape(p); + tokadd(p, c); } } else { @@ -4081,15 +4131,15 @@ parser_yylex(parser_state *p) if ((c = nextc(p)) == '&') { p->lstate = EXPR_BEG; if ((c = nextc(p)) == '=') { - yylval.id = intern("&&"); - p->lstate = EXPR_BEG; - return tOP_ASGN; + yylval.id = intern2("&&",2); + p->lstate = EXPR_BEG; + return tOP_ASGN; } pushback(p, c); return tANDOP; } else if (c == '=') { - yylval.id = intern("&"); + yylval.id = intern_c('&'); p->lstate = EXPR_BEG; return tOP_ASGN; } @@ -4115,15 +4165,15 @@ parser_yylex(parser_state *p) if ((c = nextc(p)) == '|') { p->lstate = EXPR_BEG; if ((c = nextc(p)) == '=') { - yylval.id = intern("||"); - p->lstate = EXPR_BEG; - return tOP_ASGN; + yylval.id = intern2("||",2); + p->lstate = EXPR_BEG; + return tOP_ASGN; } pushback(p, c); return tOROP; } if (c == '=') { - yylval.id = intern("|"); + yylval.id = intern_c('|'); p->lstate = EXPR_BEG; return tOP_ASGN; } @@ -4141,13 +4191,13 @@ parser_yylex(parser_state *p) if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) { p->lstate = EXPR_ARG; if (c == '@') { - return tUPLUS; + return tUPLUS; } pushback(p, c); return '+'; } if (c == '=') { - yylval.id = intern("+"); + yylval.id = intern_c('+'); p->lstate = EXPR_BEG; return tOP_ASGN; } @@ -4155,8 +4205,8 @@ parser_yylex(parser_state *p) p->lstate = EXPR_BEG; pushback(p, c); if (c != -1 && ISDIGIT(c)) { - c = '+'; - goto start_num; + c = '+'; + goto start_num; } return tUPLUS; } @@ -4169,13 +4219,13 @@ parser_yylex(parser_state *p) if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) { p->lstate = EXPR_ARG; if (c == '@') { - return tUMINUS; + return tUMINUS; } pushback(p, c); return '-'; } if (c == '=') { - yylval.id = intern("-"); + yylval.id = intern_c('-'); p->lstate = EXPR_BEG; return tOP_ASGN; } @@ -4187,7 +4237,7 @@ parser_yylex(parser_state *p) p->lstate = EXPR_BEG; pushback(p, c); if (c != -1 && ISDIGIT(c)) { - return tUMINUS_NUM; + return tUMINUS_NUM; } return tUMINUS; } @@ -4199,7 +4249,7 @@ parser_yylex(parser_state *p) p->lstate = EXPR_BEG; if ((c = nextc(p)) == '.') { if ((c = nextc(p)) == '.') { - return tDOT3; + return tDOT3; } pushback(p, c); return tDOT2; @@ -4221,218 +4271,218 @@ parser_yylex(parser_state *p) p->lstate = EXPR_END; token_column = newtok(p); if (c == '-' || c == '+') { - tokadd(p, c); - c = nextc(p); + tokadd(p, c); + c = nextc(p); } if (c == '0') { #define no_digits() do {yyerror(p,"numeric literal without digits"); return 0;} while (0) - int start = toklen(p); - c = nextc(p); - if (c == 'x' || c == 'X') { - /* hexadecimal */ - c = nextc(p); - if (c != -1 && ISXDIGIT(c)) { - do { - if (c == '_') { - if (nondigit) break; - nondigit = c; - continue; - } - if (!ISXDIGIT(c)) break; - nondigit = 0; - tokadd(p, tolower(c)); - } while ((c = nextc(p)) != -1); - } - pushback(p, c); - tokfix(p); - if (toklen(p) == start) { - no_digits(); - } - else if (nondigit) goto trailing_uc; - yylval.nd = new_int(p, tok(p), 16); - return tINTEGER; - } - if (c == 'b' || c == 'B') { - /* binary */ - c = nextc(p); - if (c == '0' || c == '1') { - do { - if (c == '_') { - if (nondigit) break; - nondigit = c; - continue; - } - if (c != '0' && c != '1') break; - nondigit = 0; - tokadd(p, c); - } while ((c = nextc(p)) != -1); - } - pushback(p, c); - tokfix(p); - if (toklen(p) == start) { - no_digits(); - } - else if (nondigit) goto trailing_uc; - yylval.nd = new_int(p, tok(p), 2); - return tINTEGER; - } - if (c == 'd' || c == 'D') { - /* decimal */ - c = nextc(p); - if (c != -1 && ISDIGIT(c)) { - do { - if (c == '_') { - if (nondigit) break; - nondigit = c; - continue; - } - if (!ISDIGIT(c)) break; - nondigit = 0; - tokadd(p, c); - } while ((c = nextc(p)) != -1); - } - pushback(p, c); - tokfix(p); - if (toklen(p) == start) { - no_digits(); - } - else if (nondigit) goto trailing_uc; - yylval.nd = new_int(p, tok(p), 10); - return tINTEGER; - } - if (c == '_') { - /* 0_0 */ - goto octal_number; - } - if (c == 'o' || c == 'O') { - /* prefixed octal */ - c = nextc(p); - if (c == -1 || c == '_' || !ISDIGIT(c)) { - no_digits(); - } - } - if (c >= '0' && c <= '7') { - /* octal */ - octal_number: - do { - if (c == '_') { - if (nondigit) break; - nondigit = c; - continue; - } - if (c < '0' || c > '9') break; - if (c > '7') goto invalid_octal; - nondigit = 0; - tokadd(p, c); - } while ((c = nextc(p)) != -1); - - if (toklen(p) > start) { - pushback(p, c); - tokfix(p); - if (nondigit) goto trailing_uc; - yylval.nd = new_int(p, tok(p), 8); - return tINTEGER; - } - if (nondigit) { - pushback(p, c); - goto trailing_uc; - } - } - if (c > '7' && c <= '9') { - invalid_octal: - yyerror(p, "Invalid octal digit"); - } - else if (c == '.' || c == 'e' || c == 'E') { - tokadd(p, '0'); - } - else { - pushback(p, c); - yylval.nd = new_int(p, "0", 10); - return tINTEGER; - } + int start = toklen(p); + c = nextc(p); + if (c == 'x' || c == 'X') { + /* hexadecimal */ + c = nextc(p); + if (c != -1 && ISXDIGIT(c)) { + do { + if (c == '_') { + if (nondigit) break; + nondigit = c; + continue; + } + if (!ISXDIGIT(c)) break; + nondigit = 0; + tokadd(p, tolower(c)); + } while ((c = nextc(p)) != -1); + } + pushback(p, c); + tokfix(p); + if (toklen(p) == start) { + no_digits(); + } + else if (nondigit) goto trailing_uc; + yylval.nd = new_int(p, tok(p), 16); + return tINTEGER; + } + if (c == 'b' || c == 'B') { + /* binary */ + c = nextc(p); + if (c == '0' || c == '1') { + do { + if (c == '_') { + if (nondigit) break; + nondigit = c; + continue; + } + if (c != '0' && c != '1') break; + nondigit = 0; + tokadd(p, c); + } while ((c = nextc(p)) != -1); + } + pushback(p, c); + tokfix(p); + if (toklen(p) == start) { + no_digits(); + } + else if (nondigit) goto trailing_uc; + yylval.nd = new_int(p, tok(p), 2); + return tINTEGER; + } + if (c == 'd' || c == 'D') { + /* decimal */ + c = nextc(p); + if (c != -1 && ISDIGIT(c)) { + do { + if (c == '_') { + if (nondigit) break; + nondigit = c; + continue; + } + if (!ISDIGIT(c)) break; + nondigit = 0; + tokadd(p, c); + } while ((c = nextc(p)) != -1); + } + pushback(p, c); + tokfix(p); + if (toklen(p) == start) { + no_digits(); + } + else if (nondigit) goto trailing_uc; + yylval.nd = new_int(p, tok(p), 10); + return tINTEGER; + } + if (c == '_') { + /* 0_0 */ + goto octal_number; + } + if (c == 'o' || c == 'O') { + /* prefixed octal */ + c = nextc(p); + if (c == -1 || c == '_' || !ISDIGIT(c)) { + no_digits(); + } + } + if (c >= '0' && c <= '7') { + /* octal */ + octal_number: + do { + if (c == '_') { + if (nondigit) break; + nondigit = c; + continue; + } + if (c < '0' || c > '9') break; + if (c > '7') goto invalid_octal; + nondigit = 0; + tokadd(p, c); + } while ((c = nextc(p)) != -1); + + if (toklen(p) > start) { + pushback(p, c); + tokfix(p); + if (nondigit) goto trailing_uc; + yylval.nd = new_int(p, tok(p), 8); + return tINTEGER; + } + if (nondigit) { + pushback(p, c); + goto trailing_uc; + } + } + if (c > '7' && c <= '9') { + invalid_octal: + yyerror(p, "Invalid octal digit"); + } + else if (c == '.' || c == 'e' || c == 'E') { + tokadd(p, '0'); + } + else { + pushback(p, c); + yylval.nd = new_int(p, "0", 10); + return tINTEGER; + } } for (;;) { - switch (c) { - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - nondigit = 0; - tokadd(p, c); - break; - - case '.': - if (nondigit) goto trailing_uc; - if (seen_point || seen_e) { - goto decode_num; - } - else { - int c0 = nextc(p); - if (c0 == -1 || !ISDIGIT(c0)) { - pushback(p, c0); - goto decode_num; - } - c = c0; - } - tokadd(p, '.'); - tokadd(p, c); - is_float++; - seen_point++; - nondigit = 0; - break; - - case 'e': - case 'E': - if (nondigit) { - pushback(p, c); - c = nondigit; - goto decode_num; - } - if (seen_e) { - goto decode_num; - } - tokadd(p, c); - seen_e++; - is_float++; - nondigit = c; - c = nextc(p); - if (c != '-' && c != '+') continue; - tokadd(p, c); - nondigit = c; - break; - - case '_': /* `_' in number just ignored */ - if (nondigit) goto decode_num; - nondigit = c; - break; - - default: - goto decode_num; - } - c = nextc(p); + switch (c) { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + nondigit = 0; + tokadd(p, c); + break; + + case '.': + if (nondigit) goto trailing_uc; + if (seen_point || seen_e) { + goto decode_num; + } + else { + int c0 = nextc(p); + if (c0 == -1 || !ISDIGIT(c0)) { + pushback(p, c0); + goto decode_num; + } + c = c0; + } + tokadd(p, '.'); + tokadd(p, c); + is_float++; + seen_point++; + nondigit = 0; + break; + + case 'e': + case 'E': + if (nondigit) { + pushback(p, c); + c = nondigit; + goto decode_num; + } + if (seen_e) { + goto decode_num; + } + tokadd(p, c); + seen_e++; + is_float++; + nondigit = c; + c = nextc(p); + if (c != '-' && c != '+') continue; + tokadd(p, c); + nondigit = c; + break; + + case '_': /* `_' in number just ignored */ + if (nondigit) goto decode_num; + nondigit = c; + break; + + default: + goto decode_num; + } + c = nextc(p); } decode_num: pushback(p, c); if (nondigit) { trailing_uc: - yyerror_i(p, "trailing `%c' in number", nondigit); + yyerror_i(p, "trailing `%c' in number", nondigit); } tokfix(p); if (is_float) { - 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; - } - yylval.nd = new_float(p, tok(p)); - return tFLOAT; + 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; + } + yylval.nd = new_float(p, tok(p)); + return tFLOAT; } yylval.nd = new_int(p, tok(p), 10); return tINTEGER; @@ -4454,8 +4504,8 @@ parser_yylex(parser_state *p) c = nextc(p); if (c == ':') { if (IS_BEG() || p->lstate == EXPR_CLASS || IS_SPCARG(-1)) { - p->lstate = EXPR_BEG; - return tCOLON3; + p->lstate = EXPR_BEG; + return tCOLON3; } p->lstate = EXPR_DOT; return tCOLON2; @@ -4471,25 +4521,17 @@ parser_yylex(parser_state *p) case '/': if (IS_BEG()) { -#if 0 p->lex_strterm = new_strterm(p, str_regexp, '/', 0); -#endif - p->regexp = 1; - p->sterm = '/'; return tREGEXP_BEG; } if ((c = nextc(p)) == '=') { - yylval.id = intern("/"); + yylval.id = intern_c('/'); p->lstate = EXPR_BEG; return tOP_ASGN; } pushback(p, c); if (IS_SPCARG(c)) { -#if 0 p->lex_strterm = new_strterm(p, str_regexp, '/', 0); -#endif - p->regexp = 1; - p->sterm = '/'; return tREGEXP_BEG; } if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) { @@ -4501,7 +4543,7 @@ parser_yylex(parser_state *p) case '^': if ((c = nextc(p)) == '=') { - yylval.id = intern("^"); + yylval.id = intern_c('^'); p->lstate = EXPR_BEG; return tOP_ASGN; } @@ -4524,7 +4566,7 @@ parser_yylex(parser_state *p) case '~': if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) { if ((c = nextc(p)) != '@') { - pushback(p, c); + pushback(p, c); } p->lstate = EXPR_ARG; } @@ -4551,11 +4593,11 @@ parser_yylex(parser_state *p) if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) { p->lstate = EXPR_ARG; if ((c = nextc(p)) == ']') { - if ((c = nextc(p)) == '=') { - return tASET; - } - pushback(p, c); - return tAREF; + if ((c = nextc(p)) == '=') { + return tASET; + } + pushback(p, c); + return tAREF; } pushback(p, c); return '['; @@ -4604,92 +4646,77 @@ parser_yylex(parser_state *p) case '%': if (IS_BEG()) { - int beg = 0, term; -#if 0 + int term; int paren; -#endif c = nextc(p); quotation: if (c == -1 || !ISALNUM(c)) { - term = c; - c = 'Q'; + term = c; + c = 'Q'; } else { - beg = term = nextc(p); - if (isalnum(term)) { - yyerror(p, "unknown type of %string"); - return 0; - } + term = nextc(p); + if (isalnum(term)) { + yyerror(p, "unknown type of %string"); + return 0; + } } if (c == -1 || term == -1) { - yyerror(p, "unterminated quoted string meets end of file"); - return 0; + yyerror(p, "unterminated quoted string meets end of file"); + return 0; } -#if 0 paren = term; -#endif if (term == '(') term = ')'; else if (term == '[') term = ']'; else if (term == '{') term = '}'; else if (term == '<') term = '>'; - p->sterm = term; -#if 0 else paren = 0; -#endif switch (c) { case 'Q': -#if 0 - p->lex_strterm = new_strterm(p, str_dquote, term, paren); -#endif - return tSTRING_BEG; + p->lex_strterm = new_strterm(p, str_dquote, term, paren); + return tSTRING_BEG; case 'q': -#if 0 - p->lex_strterm = new_strterm(p, str_squote, term, paren); -#endif - p->sterm = 0; - return parse_qstring(p, beg, term); + p->lex_strterm = new_strterm(p, str_squote, term, paren); + return parse_string(p); case 'W': -#if 0 - p->lex_strterm = new_strterm(p, str_dword, term, paren); -#endif - do {c = nextc(p);} while (isspace(c)); - pushback(p, c); - return tWORDS_BEG; + p->lex_strterm = new_strterm(p, str_dword, term, paren); + return tWORDS_BEG; case 'w': -#if 0 - p->lex_strterm = new_strterm(p, str_sword, term, paren); -#endif - do {c = nextc(p);} while (isspace(c)); - pushback(p, c); - return tQWORDS_BEG; + p->lex_strterm = new_strterm(p, str_sword, term, paren); + return tWORDS_BEG; + + case 'x': + p->lex_strterm = new_strterm(p, str_xquote, term, paren); + return tXSTRING_BEG; case 'r': -#if 0 - p->lex_strterm = new_strterm(p, str_regexp, term, paren); -#endif - p->regexp = 1; - p->sterm = term; - return tREGEXP_BEG; + p->lex_strterm = new_strterm(p, str_regexp, term, paren); + return tREGEXP_BEG; case 's': -#if 0 - p->lex_strterm = new_strterm(p, str_ssym, term, paren); -#endif - p->lstate = EXPR_FNAME; - return tSYMBEG; + p->lex_strterm = new_strterm(p, str_ssym, term, paren); + return tSYMBEG; + + case 'I': + p->lex_strterm = new_strterm(p, str_dsymbols, term, paren); + return tSYMBOLS_BEG; + + case 'i': + p->lex_strterm = new_strterm(p, str_ssymbols, term, paren); + return tSYMBOLS_BEG; default: - yyerror(p, "unknown type of %string"); - return 0; + yyerror(p, "unknown type of %string"); + return 0; } } if ((c = nextc(p)) == '=') { - yylval.id = intern("%"); + yylval.id = intern_c('%'); p->lstate = EXPR_BEG; return tOP_ASGN; } @@ -4751,9 +4778,9 @@ parser_yylex(parser_state *p) case '\'': /* $': string after last match */ case '+': /* $+: string matches last pattern */ if (last_state == EXPR_FNAME) { - tokadd(p, '$'); - tokadd(p, c); - goto gvar; + tokadd(p, '$'); + tokadd(p, c); + goto gvar; } yylval.nd = new_back_ref(p, c); return tBACK_REF; @@ -4762,8 +4789,8 @@ parser_yylex(parser_state *p) case '4': case '5': case '6': case '7': case '8': case '9': do { - tokadd(p, c); - c = nextc(p); + tokadd(p, c); + c = nextc(p); } while (c != -1 && isdigit(c)); pushback(p, c); if (last_state == EXPR_FNAME) goto gvar; @@ -4773,8 +4800,8 @@ parser_yylex(parser_state *p) default: if (!identchar(c)) { - pushback(p, c); - return '$'; + pushback(p, c); + return '$'; } case '0': tokadd(p, '$'); @@ -4791,10 +4818,10 @@ parser_yylex(parser_state *p) } if (c != -1 && isdigit(c)) { if (p->bidx == 1) { - yyerror_i(p, "`@%c' is not allowed as an instance variable name", c); + yyerror_i(p, "`@%c' is not allowed as an instance variable name", c); } else { - yyerror_i(p, "`@@%c' is not allowed as a class variable name", c); + yyerror_i(p, "`@@%c' is not allowed as a class variable name", c); } return 0; } @@ -4852,95 +4879,95 @@ parser_yylex(parser_state *p) case '@': p->lstate = EXPR_END; if (tok(p)[1] == '@') - result = tCVAR; + result = tCVAR; else - result = tIVAR; + result = tIVAR; break; default: if (toklast(p) == '!' || toklast(p) == '?') { - result = tFID; + result = tFID; } else { - if (p->lstate == EXPR_FNAME) { - if ((c = nextc(p)) == '=' && !peek(p, '~') && !peek(p, '>') && - (!peek(p, '=') || (peek_n(p, '>', 1)))) { - result = tIDENTIFIER; - tokadd(p, c); - tokfix(p); - } - else { - pushback(p, c); - } - } - if (result == 0 && isupper((int)tok(p)[0])) { - result = tCONSTANT; - } - else { - result = tIDENTIFIER; - } + if (p->lstate == EXPR_FNAME) { + if ((c = nextc(p)) == '=' && !peek(p, '~') && !peek(p, '>') && + (!peek(p, '=') || (peek_n(p, '>', 1)))) { + result = tIDENTIFIER; + tokadd(p, c); + tokfix(p); + } + else { + pushback(p, c); + } + } + if (result == 0 && isupper((int)tok(p)[0])) { + result = tCONSTANT; + } + else { + result = tIDENTIFIER; + } } if (IS_LABEL_POSSIBLE()) { - if (IS_LABEL_SUFFIX(0)) { - p->lstate = EXPR_BEG; - nextc(p); - tokfix(p); - yylval.id = intern(tok(p)); - return tLABEL; - } + if (IS_LABEL_SUFFIX(0)) { + p->lstate = EXPR_BEG; + nextc(p); + tokfix(p); + yylval.id = intern(tok(p)); + return tLABEL; + } } if (p->lstate != EXPR_DOT) { - const struct kwtable *kw; - - /* See if it is a reserved word. */ - kw = mrb_reserved_word(tok(p), toklen(p)); - if (kw) { - enum mrb_lex_state_enum state = p->lstate; - p->lstate = kw->state; - if (state == EXPR_FNAME) { - yylval.id = intern(kw->name); - return kw->id[0]; - } - if (p->lstate == EXPR_BEG) { - p->cmd_start = TRUE; - } - if (kw->id[0] == keyword_do) { - if (p->lpar_beg && p->lpar_beg == p->paren_nest) { - p->lpar_beg = 0; - p->paren_nest--; - return keyword_do_LAMBDA; - } - if (COND_P()) return keyword_do_cond; - if (CMDARG_P() && state != EXPR_CMDARG) - return keyword_do_block; - if (state == EXPR_ENDARG || state == EXPR_BEG) - return keyword_do_block; - return keyword_do; - } - if (state == EXPR_BEG || state == EXPR_VALUE) - return kw->id[0]; - else { - if (kw->id[0] != kw->id[1]) - p->lstate = EXPR_BEG; - return kw->id[1]; - } - } + const struct kwtable *kw; + + /* See if it is a reserved word. */ + kw = mrb_reserved_word(tok(p), toklen(p)); + if (kw) { + enum mrb_lex_state_enum state = p->lstate; + p->lstate = kw->state; + if (state == EXPR_FNAME) { + yylval.id = intern(kw->name); + return kw->id[0]; + } + if (p->lstate == EXPR_BEG) { + p->cmd_start = TRUE; + } + if (kw->id[0] == keyword_do) { + if (p->lpar_beg && p->lpar_beg == p->paren_nest) { + p->lpar_beg = 0; + p->paren_nest--; + return keyword_do_LAMBDA; + } + if (COND_P()) return keyword_do_cond; + if (CMDARG_P() && state != EXPR_CMDARG) + return keyword_do_block; + if (state == EXPR_ENDARG || state == EXPR_BEG) + return keyword_do_block; + return keyword_do; + } + if (state == EXPR_BEG || state == EXPR_VALUE) + return kw->id[0]; + else { + if (kw->id[0] != kw->id[1]) + p->lstate = EXPR_BEG; + return kw->id[1]; + } + } } if (IS_BEG() || p->lstate == EXPR_DOT || IS_ARG()) { - if (cmd_state) { - p->lstate = EXPR_CMDARG; - } - else { - p->lstate = EXPR_ARG; - } + if (cmd_state) { + p->lstate = EXPR_CMDARG; + } + else { + p->lstate = EXPR_ARG; + } } else if (p->lstate == EXPR_FNAME) { - p->lstate = EXPR_ENDFN; + p->lstate = EXPR_ENDFN; } else { - p->lstate = EXPR_END; + p->lstate = EXPR_END; } } { @@ -4949,7 +4976,7 @@ parser_yylex(parser_state *p) yylval.id = ident; #if 0 if (last_state != EXPR_DOT && islower(tok(p)[0]) && lvar_defined(ident)) { - p->lstate = EXPR_END; + p->lstate = EXPR_END; } #endif } @@ -5021,7 +5048,7 @@ mrb_parser_parse(parser_state *p, mrbc_context *c) p->cmd_start = TRUE; p->in_def = p->in_single = FALSE; p->nerr = p->nwarn = 0; - p->sterm = 0; + p->lex_strterm = NULL; parser_init_cxt(p, c); yyparse(p); @@ -5064,6 +5091,7 @@ mrb_parser_new(mrb_state *mrb) yydebug = 1; #endif + p->lex_strterm = NULL; p->heredocs = p->parsing_heredoc = NULL; return p; @@ -5153,13 +5181,13 @@ load_exec(mrb_state *mrb, parser_state *p, mrbc_context *c) 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->exc = mrb_obj_ptr(mrb_exc_new(mrb, E_SYNTAX_ERROR, buf, n)); mrb_parser_free(p); return mrb_undef_value(); } else { static const char msg[] = "syntax error"; - mrb->exc = (struct RObject*)mrb_object(mrb_exc_new(mrb, E_SYNTAX_ERROR, msg, sizeof(msg) - 1)); + mrb->exc = mrb_obj_ptr(mrb_exc_new(mrb, E_SYNTAX_ERROR, msg, sizeof(msg) - 1)); mrb_parser_free(p); return mrb_undef_value(); } @@ -5168,7 +5196,7 @@ load_exec(mrb_state *mrb, parser_state *p, mrbc_context *c) mrb_parser_free(p); if (n < 0) { static const char msg[] = "codegen error"; - mrb->exc = (struct RObject*)mrb_object(mrb_exc_new(mrb, E_SCRIPT_ERROR, msg, sizeof(msg) - 1)); + mrb->exc = mrb_obj_ptr(mrb_exc_new(mrb, E_SCRIPT_ERROR, msg, sizeof(msg) - 1)); return mrb_nil_value(); } if (c) { @@ -5269,23 +5297,23 @@ parser_dump(mrb_state *mrb, node *tree, int offset) dump_prefix(offset+1); printf("rescue:\n"); while (n2) { - node *n3 = n2->car; - if (n3->car) { - dump_prefix(offset+2); - printf("handle classes:\n"); - dump_recur(mrb, n3->car, offset+3); - } - if (n3->cdr->car) { - dump_prefix(offset+2); - printf("exc_var:\n"); - parser_dump(mrb, n3->cdr->car, offset+3); - } - if (n3->cdr->cdr->car) { - dump_prefix(offset+2); - printf("rescue body:\n"); - parser_dump(mrb, n3->cdr->cdr->car, offset+3); - } - n2 = n2->cdr; + node *n3 = n2->car; + if (n3->car) { + dump_prefix(offset+2); + printf("handle classes:\n"); + dump_recur(mrb, n3->car, offset+3); + } + if (n3->cdr->car) { + dump_prefix(offset+2); + printf("exc_var:\n"); + parser_dump(mrb, n3->cdr->car, offset+3); + } + if (n3->cdr->cdr->car) { + dump_prefix(offset+2); + printf("rescue body:\n"); + parser_dump(mrb, n3->cdr->cdr->car, offset+3); + } + n2 = n2->cdr; } } tree = tree->cdr; @@ -5318,40 +5346,40 @@ parser_dump(mrb_state *mrb, node *tree, int offset) node *n = tree->car; if (n->car) { - dump_prefix(offset+1); - printf("mandatory args:\n"); - dump_recur(mrb, n->car, offset+2); + dump_prefix(offset+1); + printf("mandatory args:\n"); + dump_recur(mrb, n->car, offset+2); } n = n->cdr; if (n->car) { - dump_prefix(offset+1); - printf("optional args:\n"); - { - node *n2 = n->car; - - while (n2) { - dump_prefix(offset+2); - printf("%s=", mrb_sym2name(mrb, sym(n2->car->car))); - parser_dump(mrb, n2->car->cdr, 0); - n2 = n2->cdr; - } - } + dump_prefix(offset+1); + printf("optional args:\n"); + { + node *n2 = n->car; + + while (n2) { + dump_prefix(offset+2); + printf("%s=", mrb_sym2name(mrb, sym(n2->car->car))); + parser_dump(mrb, n2->car->cdr, 0); + n2 = n2->cdr; + } + } } n = n->cdr; if (n->car) { - dump_prefix(offset+1); - printf("rest=*%s\n", mrb_sym2name(mrb, sym(n->car))); + dump_prefix(offset+1); + printf("rest=*%s\n", mrb_sym2name(mrb, sym(n->car))); } n = n->cdr; if (n->car) { - dump_prefix(offset+1); - printf("post mandatory args:\n"); - dump_recur(mrb, n->car, offset+2); + dump_prefix(offset+1); + printf("post mandatory args:\n"); + dump_recur(mrb, n->car, offset+2); } n = n->cdr; if (n) { - dump_prefix(offset+1); - printf("blk=&%s\n", mrb_sym2name(mrb, sym(n))); + dump_prefix(offset+1); + printf("blk=&%s\n", mrb_sym2name(mrb, sym(n))); } } dump_prefix(offset+1); @@ -5431,25 +5459,25 @@ parser_dump(mrb_state *mrb, node *tree, int offset) node *n2 = tree->car; if (n2->car) { - dump_prefix(offset+2); - printf("pre:\n"); - dump_recur(mrb, n2->car, offset+3); + dump_prefix(offset+2); + printf("pre:\n"); + dump_recur(mrb, n2->car, offset+3); } n2 = n2->cdr; if (n2) { - if (n2->car) { - dump_prefix(offset+2); - printf("rest:\n"); - parser_dump(mrb, n2->car, offset+3); - } - n2 = n2->cdr; - if (n2) { - if (n2->car) { - dump_prefix(offset+2); - printf("post:\n"); - dump_recur(mrb, n2->car, offset+3); - } - } + if (n2->car) { + dump_prefix(offset+2); + printf("rest:\n"); + parser_dump(mrb, n2->car, offset+3); + } + n2 = n2->cdr; + if (n2) { + if (n2->car) { + dump_prefix(offset+2); + printf("post:\n"); + dump_recur(mrb, n2->car, offset+3); + } + } } } tree = tree->cdr; @@ -5468,17 +5496,17 @@ parser_dump(mrb_state *mrb, node *tree, int offset) node *n2 = tree->car; if (n2 && (n2->car || n2->cdr)) { - dump_prefix(offset+1); - printf("local variables:\n"); - dump_prefix(offset+2); - while (n2) { - if (n2->car) { - if (n2 != tree->car) printf(", "); - printf("%s", mrb_sym2name(mrb, sym(n2->car))); - } - n2 = n2->cdr; - } - printf("\n"); + dump_prefix(offset+1); + printf("local variables:\n"); + dump_prefix(offset+2); + while (n2) { + if (n2->car) { + if (n2 != tree->car) printf(", "); + printf("%s", mrb_sym2name(mrb, sym(n2->car))); + } + n2 = n2->cdr; + } + printf("\n"); } } tree = tree->cdr; @@ -5499,9 +5527,9 @@ parser_dump(mrb_state *mrb, node *tree, int offset) printf("args:\n"); dump_recur(mrb, tree->car, offset+2); if (tree->cdr) { - dump_prefix(offset+1); - printf("block:\n"); - parser_dump(mrb, tree->cdr, offset+2); + dump_prefix(offset+1); + printf("block:\n"); + parser_dump(mrb, tree->cdr, offset+2); } } break; @@ -5572,31 +5600,31 @@ parser_dump(mrb_state *mrb, node *tree, int offset) node *n2 = tree->car; if (n2->car) { - dump_prefix(offset+2); - printf("pre:\n"); - dump_recur(mrb, n2->car, offset+3); + dump_prefix(offset+2); + printf("pre:\n"); + dump_recur(mrb, n2->car, offset+3); } n2 = n2->cdr; if (n2) { - if (n2->car) { - dump_prefix(offset+2); - printf("rest:\n"); - if (n2->car == (node*)-1) { - dump_prefix(offset+2); - printf("(empty)\n"); - } - else { - parser_dump(mrb, n2->car, offset+3); - } - } - n2 = n2->cdr; - if (n2) { - if (n2->car) { - dump_prefix(offset+2); - printf("post:\n"); - dump_recur(mrb, n2->car, offset+3); - } - } + if (n2->car) { + dump_prefix(offset+2); + printf("rest:\n"); + if (n2->car == (node*)-1) { + dump_prefix(offset+2); + printf("(empty)\n"); + } + else { + parser_dump(mrb, n2->car, offset+3); + } + } + n2 = n2->cdr; + if (n2) { + if (n2->car) { + dump_prefix(offset+2); + printf("post:\n"); + dump_recur(mrb, n2->car, offset+3); + } + } } } dump_prefix(offset+1); @@ -5623,9 +5651,9 @@ parser_dump(mrb_state *mrb, node *tree, int offset) printf("args:\n"); dump_recur(mrb, tree->car, offset+2); if (tree->cdr) { - dump_prefix(offset+1); - printf("block:\n"); - parser_dump(mrb, tree->cdr, offset+2); + dump_prefix(offset+1); + printf("block:\n"); + parser_dump(mrb, tree->cdr, offset+2); } } break; @@ -5731,6 +5759,15 @@ parser_dump(mrb_state *mrb, node *tree, int offset) dump_recur(mrb, tree, offset+1); break; + case NODE_XSTR: + printf("NODE_XSTR \"%s\" len %d\n", (char*)tree->car, (int)(intptr_t)tree->cdr); + break; + + case NODE_DXSTR: + printf("NODE_DXSTR\n"); + dump_recur(mrb, tree, offset+1); + break; + case NODE_REGX: printf("NODE_REGX /%s/%s\n", (char*)tree->car, (char*)tree->cdr); break; @@ -5766,8 +5803,8 @@ parser_dump(mrb_state *mrb, node *tree, int offset) case NODE_ALIAS: printf("NODE_ALIAS %s %s:\n", - mrb_sym2name(mrb, sym(tree->car)), - mrb_sym2name(mrb, sym(tree->cdr))); + mrb_sym2name(mrb, sym(tree->car)), + mrb_sym2name(mrb, sym(tree->cdr))); break; case NODE_UNDEF: @@ -5775,8 +5812,8 @@ parser_dump(mrb_state *mrb, node *tree, int offset) { node *t = tree; while (t) { - printf(" %s", mrb_sym2name(mrb, sym(t->car))); - t = t->cdr; + printf(" %s", mrb_sym2name(mrb, sym(t->car))); + t = t->cdr; } } printf(":\n"); @@ -5844,17 +5881,17 @@ parser_dump(mrb_state *mrb, node *tree, int offset) node *n2 = tree->car; if (n2 && (n2->car || n2->cdr)) { - dump_prefix(offset+1); - printf("local variables:\n"); - dump_prefix(offset+2); - while (n2) { - if (n2->car) { - if (n2 != tree->car) printf(", "); - printf("%s", mrb_sym2name(mrb, sym(n2->car))); - } - n2 = n2->cdr; - } - printf("\n"); + dump_prefix(offset+1); + printf("local variables:\n"); + dump_prefix(offset+2); + while (n2) { + if (n2->car) { + if (n2 != tree->car) printf(", "); + printf("%s", mrb_sym2name(mrb, sym(n2->car))); + } + n2 = n2->cdr; + } + printf("\n"); } } tree = tree->cdr; @@ -5862,40 +5899,40 @@ parser_dump(mrb_state *mrb, node *tree, int offset) node *n = tree->car; if (n->car) { - dump_prefix(offset+1); - printf("mandatory args:\n"); - dump_recur(mrb, n->car, offset+2); + dump_prefix(offset+1); + printf("mandatory args:\n"); + dump_recur(mrb, n->car, offset+2); } n = n->cdr; if (n->car) { - dump_prefix(offset+1); - printf("optional args:\n"); - { - node *n2 = n->car; - - while (n2) { - dump_prefix(offset+2); - printf("%s=", mrb_sym2name(mrb, sym(n2->car->car))); - parser_dump(mrb, n2->car->cdr, 0); - n2 = n2->cdr; - } - } + dump_prefix(offset+1); + printf("optional args:\n"); + { + node *n2 = n->car; + + while (n2) { + dump_prefix(offset+2); + printf("%s=", mrb_sym2name(mrb, sym(n2->car->car))); + parser_dump(mrb, n2->car->cdr, 0); + n2 = n2->cdr; + } + } } n = n->cdr; if (n->car) { - dump_prefix(offset+1); - printf("rest=*%s\n", mrb_sym2name(mrb, sym(n->car))); + dump_prefix(offset+1); + printf("rest=*%s\n", mrb_sym2name(mrb, sym(n->car))); } n = n->cdr; if (n->car) { - dump_prefix(offset+1); - printf("post mandatory args:\n"); - dump_recur(mrb, n->car, offset+2); + dump_prefix(offset+1); + printf("post mandatory args:\n"); + dump_recur(mrb, n->car, offset+2); } n = n->cdr; if (n) { - dump_prefix(offset+1); - printf("blk=&%s\n", mrb_sym2name(mrb, sym(n))); + dump_prefix(offset+1); + printf("blk=&%s\n", mrb_sym2name(mrb, sym(n))); } } parser_dump(mrb, tree->cdr->car, offset+1); @@ -5912,40 +5949,40 @@ parser_dump(mrb_state *mrb, node *tree, int offset) node *n = tree->car; if (n->car) { - dump_prefix(offset+1); - printf("mandatory args:\n"); - dump_recur(mrb, n->car, offset+2); + dump_prefix(offset+1); + printf("mandatory args:\n"); + dump_recur(mrb, n->car, offset+2); } n = n->cdr; if (n->car) { - dump_prefix(offset+1); - printf("optional args:\n"); - { - node *n2 = n->car; - - while (n2) { - dump_prefix(offset+2); - printf("%s=", mrb_sym2name(mrb, sym(n2->car->car))); - parser_dump(mrb, n2->car->cdr, 0); - n2 = n2->cdr; - } - } + dump_prefix(offset+1); + printf("optional args:\n"); + { + node *n2 = n->car; + + while (n2) { + dump_prefix(offset+2); + printf("%s=", mrb_sym2name(mrb, sym(n2->car->car))); + parser_dump(mrb, n2->car->cdr, 0); + n2 = n2->cdr; + } + } } n = n->cdr; if (n->car) { - dump_prefix(offset+1); - printf("rest=*%s\n", mrb_sym2name(mrb, sym(n->car))); + dump_prefix(offset+1); + printf("rest=*%s\n", mrb_sym2name(mrb, sym(n->car))); } n = n->cdr; if (n->car) { - dump_prefix(offset+1); - printf("post mandatory args:\n"); - dump_recur(mrb, n->car, offset+2); + dump_prefix(offset+1); + printf("post mandatory args:\n"); + dump_recur(mrb, n->car, offset+2); } n = n->cdr; if (n) { - dump_prefix(offset+1); - printf("blk=&%s\n", mrb_sym2name(mrb, sym(n))); + dump_prefix(offset+1); + printf("blk=&%s\n", mrb_sym2name(mrb, sym(n))); } } tree = tree->cdr; diff --git a/src/print.c b/src/print.c index 9d8a751f7..5367781f5 100644 --- a/src/print.c +++ b/src/print.c @@ -34,29 +34,6 @@ mrb_p(mrb_state *mrb, mrb_value obj) #endif } -/* 15.3.1.2.9 */ -/* 15.3.1.3.34 */ -mrb_value -mrb_printstr(mrb_state *mrb, mrb_value self) -{ - mrb_value argv; - - mrb_get_args(mrb, "o", &argv); - printstr(mrb, argv); - - return argv; -} - -void -mrb_init_print(mrb_state *mrb) -{ - struct RClass *krn; - - krn = mrb->kernel_module; - - mrb_define_method(mrb, krn, "__printstr__", mrb_printstr, ARGS_REQ(1)); -} - void mrb_show_version(mrb_state *mrb) { diff --git a/src/range.c b/src/range.c index 59bf445aa..fb4d975e7 100644 --- a/src/range.c +++ b/src/range.c @@ -8,7 +8,6 @@ #include "mruby/class.h" #include "mruby/range.h" #include "mruby/string.h" -#include <string.h> #define RANGE_CLASS (mrb_class_obj_get(mrb, "Range")) @@ -92,7 +91,7 @@ mrb_range_excl(mrb_state *mrb, mrb_value range) { struct RRange *r = mrb_range_ptr(range); - return r->excl ? mrb_true_value() : mrb_false_value(); + return mrb_bool_value(r->excl); } static void @@ -153,25 +152,30 @@ mrb_range_eq(mrb_state *mrb, mrb_value range) struct RRange *rr; struct RRange *ro; mrb_value obj; + mrb_bool eq_p; mrb_get_args(mrb, "o", &obj); - if (mrb_obj_equal(mrb, range, obj)) return mrb_true_value(); - - /* same class? */ - if (!mrb_obj_is_instance_of(mrb, obj, mrb_obj_class(mrb, range))) - return mrb_false_value(); - - rr = mrb_range_ptr(range); - ro = mrb_range_ptr(obj); - if (!mrb_obj_equal(mrb, rr->edges->beg, ro->edges->beg)) - return mrb_false_value(); - if (!mrb_obj_equal(mrb, rr->edges->end, ro->edges->end)) - return mrb_false_value(); - if (rr->excl != ro->excl) - return mrb_false_value(); + if (mrb_obj_equal(mrb, range, obj)) { + eq_p = 1; + } + else if (!mrb_obj_is_instance_of(mrb, obj, mrb_obj_class(mrb, range))) { /* same class? */ + eq_p = 0; + } + else { + rr = mrb_range_ptr(range); + ro = mrb_range_ptr(obj); + if (!mrb_obj_equal(mrb, rr->edges->beg, ro->edges->beg) || + !mrb_obj_equal(mrb, rr->edges->end, ro->edges->end) || + rr->excl != ro->excl) { + eq_p = 0; + } + else { + eq_p = 1; + } + } - return mrb_true_value(); + return mrb_bool_value(eq_p); } static int @@ -228,21 +232,17 @@ mrb_range_include(mrb_state *mrb, mrb_value range) mrb_value val; struct RRange *r = mrb_range_ptr(range); mrb_value beg, end; + mrb_bool include_p; mrb_get_args(mrb, "o", &val); beg = r->edges->beg; end = r->edges->end; - if (r_le(mrb, beg, val)) { - /* beg <= val */ - if (r->excl) { - if (r_gt(mrb, end, val)) return mrb_true_value(); /* end > val */ - } - else { - if (r_ge(mrb, end, val)) return mrb_true_value(); /* end >= val */ - } - } - return mrb_false_value(); + include_p = r_le(mrb, beg, val) && /* beg <= val */ + ((r->excl && r_gt(mrb, end, val)) || /* end > val */ + (r_ge(mrb, end, val))); /* end >= val */ + + return mrb_bool_value(include_p); } /* @@ -385,23 +385,34 @@ range_eql(mrb_state *mrb, mrb_value range) { mrb_value obj; struct RRange *r, *o; + mrb_bool eql_p; mrb_get_args(mrb, "o", &obj); - if (mrb_obj_equal(mrb, range, obj)) - return mrb_true_value(); - if (!mrb_obj_is_kind_of(mrb, obj, RANGE_CLASS)) - return mrb_false_value(); - - r = mrb_range_ptr(range); - if (mrb_type(obj) != MRB_TT_RANGE) return mrb_false_value(); - o = mrb_range_ptr(obj); - if (!mrb_eql(mrb, r->edges->beg, o->edges->beg)) - return mrb_false_value(); - if (!mrb_eql(mrb, r->edges->end, o->edges->end)) - return mrb_false_value(); - if (r->excl != o->excl) - return mrb_false_value(); - return mrb_true_value(); + if (mrb_obj_equal(mrb, range, obj)) { + eql_p = 1; + } + else if (!mrb_obj_is_kind_of(mrb, obj, RANGE_CLASS)) { + eql_p = 0; + } + else { + r = mrb_range_ptr(range); + if (mrb_type(obj) != MRB_TT_RANGE) { + eql_p = 0; + } + else { + o = mrb_range_ptr(obj); + if (!mrb_eql(mrb, r->edges->beg, o->edges->beg) || + !mrb_eql(mrb, r->edges->end, o->edges->end) || + (r->excl != o->excl)) { + eql_p = 0; + } + else { + eql_p = 1; + } + } + } + + return mrb_bool_value(eql_p); } /* 15.2.14.4.15(x) */ diff --git a/src/state.c b/src/state.c index b6805a4a4..7b5bd1002 100644 --- a/src/state.c +++ b/src/state.c @@ -7,6 +7,7 @@ #include "mruby.h" #include "mruby/irep.h" #include "mruby/variable.h" +#include <stdlib.h> #include <string.h> void mrb_init_heap(mrb_state*); @@ -53,6 +54,7 @@ mrb_alloca(mrb_state *mrb, size_t size) struct alloca_header *p; p = (struct alloca_header*) mrb_malloc(mrb, sizeof(struct alloca_header)+size); + if (p == NULL) return NULL; p->next = mrb->mems; mrb->mems = p; return (void*)p->buf; @@ -61,9 +63,12 @@ mrb_alloca(mrb_state *mrb, size_t size) static void mrb_alloca_free(mrb_state *mrb) { - struct alloca_header *p = mrb->mems; + struct alloca_header *p; struct alloca_header *tmp; + if (mrb == NULL) return; + p = mrb->mems; + while (p) { tmp = p; p = p->next; @@ -134,7 +139,7 @@ mrb_add_irep(mrb_state *mrb) mrb->irep_capa = max; } else if (mrb->irep_capa <= mrb->irep_len) { - int i; + size_t i; size_t old_capa = mrb->irep_capa; while (mrb->irep_capa <= mrb->irep_len) { mrb->irep_capa *= 2; diff --git a/src/string.c b/src/string.c index cfef5730c..09777ac69 100644 --- a/src/string.c +++ b/src/string.c @@ -6,6 +6,8 @@ #include "mruby.h" +#include <stddef.h> +#include <stdlib.h> #include <string.h> #include "mruby/string.h" #include "mruby/class.h" @@ -20,19 +22,13 @@ const char mrb_digitmap[] = "0123456789abcdefghijklmnopqrstuvwxyz"; static mrb_value str_replace(mrb_state *mrb, struct RString *s1, struct RString *s2); -static mrb_value mrb_str_subseq(mrb_state *mrb, mrb_value str, int beg, int len); +static mrb_value mrb_str_subseq(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len); #define RESIZE_CAPA(s,capacity) do {\ s->ptr = (char *)mrb_realloc(mrb, s->ptr, (capacity)+1);\ s->aux.capa = capacity;\ } while (0) -static const char* -_obj_classname(mrb_state *mrb, mrb_value obj) -{ - return mrb_class_name(mrb, mrb_obj_class(mrb, obj)); -} - void mrb_str_decref(mrb_state *mrb, mrb_shared_string *shared) { @@ -56,11 +52,11 @@ str_modify(mrb_state *mrb, struct RString *s) } else { char *ptr, *p; - long len; + mrb_int len; p = s->ptr; len = s->len; - ptr = (char *)mrb_malloc(mrb, len+1); + ptr = (char *)mrb_malloc(mrb, (size_t)len + 1); if (p) { memcpy(ptr, p, len); } @@ -104,21 +100,6 @@ str_mod_check(mrb_state *mrb, mrb_value str, char *p, mrb_int len) #define mrb_obj_alloc_string(mrb) ((struct RString*)mrb_obj_alloc((mrb), MRB_TT_STRING, (mrb)->string_class)) -static struct RString* -str_alloc(mrb_state *mrb, struct RClass *c) -{ - struct RString* s; - - s = mrb_obj_alloc_string(mrb); - - s->c = c; - s->ptr = 0; - s->len = 0; - s->aux.capa = 0; - - return s; -} - /* char offset to byte offset */ int mrb_str_offset(mrb_state *mrb, mrb_value str, int pos) @@ -129,8 +110,9 @@ mrb_str_offset(mrb_state *mrb, mrb_value str, int pos) static struct RString* str_new(mrb_state *mrb, const char *p, int len) { - struct RString *s = str_alloc(mrb, mrb->string_class); + struct RString *s; + s = mrb_obj_alloc_string(mrb); s->len = len; s->aux.capa = len; s->ptr = (char *)mrb_malloc(mrb, len+1); @@ -156,6 +138,10 @@ mrb_str_new_empty(mrb_state *mrb, mrb_value str) return mrb_obj_value(s); } +#ifndef MRB_STR_BUF_MIN_SIZE +# define MRB_STR_BUF_MIN_SIZE 128 +#endif + mrb_value mrb_str_buf_new(mrb_state *mrb, int capa) { @@ -163,8 +149,8 @@ mrb_str_buf_new(mrb_state *mrb, int capa) s = mrb_obj_alloc_string(mrb); - if (capa < STR_BUF_MIN_SIZE) { - capa = STR_BUF_MIN_SIZE; + if (capa < MRB_STR_BUF_MIN_SIZE) { + capa = MRB_STR_BUF_MIN_SIZE; } s->len = 0; s->aux.capa = capa; @@ -175,9 +161,11 @@ mrb_str_buf_new(mrb_state *mrb, int capa) } static void -str_buf_cat(mrb_state *mrb, struct RString *s, const char *ptr, int len) +str_buf_cat(mrb_state *mrb, struct RString *s, const char *ptr, size_t len) { - long capa, total, off = -1; + mrb_int capa; + mrb_int total; + ptrdiff_t off = -1; str_modify(mrb, s); if (ptr >= s->ptr && ptr <= s->ptr + s->len) { @@ -185,13 +173,13 @@ str_buf_cat(mrb_state *mrb, struct RString *s, const char *ptr, int len) } if (len == 0) return; capa = s->aux.capa; - if (s->len >= INT_MAX - len) { + if (s->len >= MRB_INT_MAX - len) { mrb_raise(mrb, E_ARGUMENT_ERROR, "string sizes too big"); } total = s->len+len; if (capa <= total) { while (total > capa) { - if (capa + 1 >= INT_MAX / 2) { + if (capa + 1 >= MRB_INT_MAX / 2) { capa = (total + 4095) / 4096; break; } @@ -208,7 +196,7 @@ str_buf_cat(mrb_state *mrb, struct RString *s, const char *ptr, int len) } mrb_value -mrb_str_buf_cat(mrb_state *mrb, mrb_value str, const char *ptr, int len) +mrb_str_buf_cat(mrb_state *mrb, mrb_value str, const char *ptr, size_t len) { if (len == 0) return str; str_buf_cat(mrb, mrb_str_ptr(str), ptr, len); @@ -216,7 +204,7 @@ mrb_str_buf_cat(mrb_state *mrb, mrb_value str, const char *ptr, int len) } mrb_value -mrb_str_new(mrb_state *mrb, const char *p, int len) +mrb_str_new(mrb_state *mrb, const char *p, size_t len) { struct RString *s; @@ -224,17 +212,6 @@ mrb_str_new(mrb_state *mrb, const char *p, int len) return mrb_obj_value(s); } -mrb_value -mrb_str_new2(mrb_state *mrb, const char *ptr) -{ - struct RString *s; - if (!ptr) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "NULL pointer given"); - } - s = str_new(mrb, ptr, strlen(ptr)); - return mrb_obj_value(s); -} - /* * call-seq: (Caution! NULL string) * String.new(str="") => new_str @@ -246,11 +223,23 @@ mrb_value mrb_str_new_cstr(mrb_state *mrb, const char *p) { struct RString *s; - int len = strlen(p); + size_t len; + + if (p) { + len = strlen(p); + if ((mrb_int)len < 0) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "argument too big"); + } + } + else { + len = 0; + } s = mrb_obj_alloc_string(mrb); s->ptr = (char *)mrb_malloc(mrb, len+1); - memcpy(s->ptr, p, len); + if (p) { + memcpy(s->ptr, p, len); + } s->ptr[len] = 0; s->len = len; s->aux.capa = len; @@ -263,6 +252,10 @@ mrb_str_to_cstr(mrb_state *mrb, mrb_value str0) { mrb_value str; + if (!mrb_string_p(str0)) { + mrb_raise(mrb, E_TYPE_ERROR, "expected String"); + } + str = mrb_str_new(mrb, RSTRING_PTR(str0), RSTRING_LEN(str0)); if (strlen(RSTRING_PTR(str)) != RSTRING_LEN(str)) { mrb_raise(mrb, E_ARGUMENT_ERROR, "string contains null byte"); @@ -302,7 +295,7 @@ mrb_str_literal(mrb_state *mrb, mrb_value str) struct RString *s, *orig; mrb_shared_string *shared; - s = str_alloc(mrb, mrb->string_class); + s = mrb_obj_alloc_string(mrb); orig = mrb_str_ptr(str); if (!(orig->flags & MRB_STR_SHARED)) { str_make_shared(mrb, mrb_str_ptr(str)); @@ -311,6 +304,7 @@ mrb_str_literal(mrb_state *mrb, mrb_value str) shared->refcnt++; s->ptr = shared->ptr; s->len = shared->len; + s->aux.capa = 0; s->aux.shared = shared; s->flags |= MRB_STR_SHARED; @@ -446,7 +440,7 @@ mrb_str_times(mrb_state *mrb, mrb_value self) if (times < 0) { mrb_raise(mrb, E_ARGUMENT_ERROR, "negative argument"); } - if (times && INT_MAX/times < RSTRING_LEN(self)) { + if (times && MRB_INT_MAX / times < RSTRING_LEN(self)) { mrb_raise(mrb, E_ARGUMENT_ERROR, "argument too big"); } @@ -532,10 +526,10 @@ mrb_str_cmp_m(mrb_state *mrb, mrb_value str1) mrb_get_args(mrb, "o", &str2); if (!mrb_string_p(str2)) { - if (!mrb_respond_to(mrb, str2, mrb_intern(mrb, "to_s"))) { + if (!mrb_respond_to(mrb, str2, mrb_intern2(mrb, "to_s", 4))) { return mrb_nil_value(); } - else if (!mrb_respond_to(mrb, str2, mrb_intern(mrb, "<=>"))) { + else if (!mrb_respond_to(mrb, str2, mrb_intern2(mrb, "<=>", 3))) { return mrb_nil_value(); } else { @@ -557,8 +551,9 @@ mrb_str_cmp_m(mrb_state *mrb, mrb_value str1) static int str_eql(mrb_state *mrb, const mrb_value str1, const mrb_value str2) { - const long len = RSTRING_LEN(str1); + const size_t len = RSTRING_LEN(str1); + /* assert(SIZE_MAX >= MRB_INT_MAX) */ if (len != RSTRING_LEN(str2)) return FALSE; if (memcmp(RSTRING_PTR(str1), RSTRING_PTR(str2), len) == 0) return TRUE; @@ -571,7 +566,7 @@ mrb_str_equal(mrb_state *mrb, mrb_value str1, mrb_value str2) if (mrb_obj_equal(mrb, str1, str2)) return TRUE; if (!mrb_string_p(str2)) { if (mrb_nil_p(str2)) return FALSE; - if (!mrb_respond_to(mrb, str2, mrb_intern(mrb, "to_str"))) { + if (!mrb_respond_to(mrb, str2, mrb_intern2(mrb, "to_str", 6))) { return FALSE; } str2 = mrb_funcall(mrb, str2, "to_str", 0); @@ -595,11 +590,12 @@ static mrb_value mrb_str_equal_m(mrb_state *mrb, mrb_value str1) { mrb_value str2; + mrb_bool equal_p; mrb_get_args(mrb, "o", &str2); - if (mrb_str_equal(mrb, str1, str2)) - return mrb_true_value(); - return mrb_false_value(); + equal_p = mrb_str_equal(mrb, str1, str2); + + return mrb_bool_value(equal_p); } /* ---------------------------------- */ mrb_value @@ -657,8 +653,8 @@ mrb_str_match(mrb_state *mrb, mrb_value self/* x */) return mrb_nil_value(); } -static inline long -mrb_memsearch_qs(const unsigned char *xs, long m, const unsigned char *ys, long n) +static inline mrb_int +mrb_memsearch_qs(const unsigned char *xs, mrb_int m, const unsigned char *ys, mrb_int n) { const unsigned char *x = xs, *xe = xs + m; const unsigned char *y = ys; @@ -677,8 +673,8 @@ mrb_memsearch_qs(const unsigned char *xs, long m, const unsigned char *ys, long return -1; } -static int -mrb_memsearch(const void *x0, int m, const void *y0, int n) +static mrb_int +mrb_memsearch(const void *x0, mrb_int m, const void *y0, mrb_int n) { const unsigned char *x = (const unsigned char *)x0, *y = (const unsigned char *)y0; @@ -705,7 +701,8 @@ mrb_str_index(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int offset) { mrb_int pos; char *s, *sptr; - int len, slen; + mrb_int len, slen; + len = RSTRING_LEN(str); slen = RSTRING_LEN(sub); if (offset < 0) { @@ -739,9 +736,9 @@ mrb_str_dup(mrb_state *mrb, mrb_value str) static mrb_value mrb_str_aref(mrb_state *mrb, mrb_value str, mrb_value indx) { - long idx; + mrb_int idx; - if (!strcmp(_obj_classname(mrb, indx), REGEXP_CLASS)) { + if (!strcmp(mrb_obj_classname(mrb, indx), REGEXP_CLASS)) { mrb_raise(mrb, E_NOTIMP_ERROR, "Regexp Class not implemented"); } switch (mrb_type(indx)) { @@ -920,7 +917,8 @@ mrb_str_chomp_bang(mrb_state *mrb, mrb_value str) mrb_value rs; mrb_int newline; char *p, *pp; - long len, rslen; + mrb_int rslen; + mrb_int len; struct RString *s = mrb_str_ptr(str); str_modify(mrb, s); @@ -1131,9 +1129,7 @@ mrb_str_empty_p(mrb_state *mrb, mrb_value self) { struct RString *s = mrb_str_ptr(self); - if (s->len == 0) - return mrb_true_value(); - return mrb_false_value(); + return mrb_bool_value(s->len == 0); } /* 15.2.10.5.17 */ @@ -1147,17 +1143,16 @@ static mrb_value mrb_str_eql(mrb_state *mrb, mrb_value self) { mrb_value str2; + mrb_bool eql_p; mrb_get_args(mrb, "o", &str2); - if (mrb_type(str2) != MRB_TT_STRING) - return mrb_false_value(); - if (str_eql(mrb, self, str2)) - return mrb_true_value(); - return mrb_false_value(); + eql_p = (mrb_type(str2) == MRB_TT_STRING) && str_eql(mrb, self, str2); + + return mrb_bool_value(eql_p); } static mrb_value -mrb_str_subseq(mrb_state *mrb, mrb_value str, int beg, int len) +mrb_str_subseq(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len) { struct RString *orig, *s; mrb_shared_string *shared; @@ -1176,7 +1171,7 @@ mrb_str_subseq(mrb_state *mrb, mrb_value str, int beg, int len) } mrb_value -mrb_str_substr(mrb_state *mrb, mrb_value str, mrb_int beg, int len) +mrb_str_substr(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len) { mrb_value str2; @@ -1267,7 +1262,7 @@ mrb_str_hash(mrb_state *mrb, mrb_value str) { /* 1-8-7 */ struct RString *s = mrb_str_ptr(str); - long len = s->len; + mrb_int len = s->len; char *p = s->ptr; mrb_int key = 0; @@ -1311,18 +1306,20 @@ mrb_str_include(mrb_state *mrb, mrb_value self) { mrb_int i; mrb_value str2; + mrb_bool include_p; mrb_get_args(mrb, "o", &str2); if (mrb_type(str2) == MRB_TT_FIXNUM) { - if (memchr(RSTRING_PTR(self), mrb_fixnum(str2), RSTRING_LEN(self))) - return mrb_true_value(); - return mrb_false_value(); + include_p = memchr(RSTRING_PTR(self), mrb_fixnum(str2), RSTRING_LEN(self)); + } + else { + mrb_string_value(mrb, &str2); + i = mrb_str_index(mrb, self, str2, 0); + + include_p = (i != -1); } - mrb_string_value(mrb, &str2); - i = mrb_str_index(mrb, self, str2, 0); - if (i == -1) return mrb_false_value(); - return mrb_true_value(); + return mrb_bool_value(include_p); } /* 15.2.10.5.22 */ @@ -1381,7 +1378,7 @@ mrb_str_index_m(mrb_state *mrb, mrb_value str) switch (mrb_type(sub)) { case MRB_TT_FIXNUM: { int c = mrb_fixnum(sub); - long len = RSTRING_LEN(str); + mrb_int len = RSTRING_LEN(str); unsigned char *p = (unsigned char*)RSTRING_PTR(str); for (;pos<len;pos++) { @@ -1396,7 +1393,7 @@ mrb_str_index_m(mrb_state *mrb, mrb_value str) tmp = mrb_check_string_type(mrb, sub); if (mrb_nil_p(tmp)) { mrb_raisef(mrb, E_TYPE_ERROR, "type mismatch: %s given", - _obj_classname(mrb, sub)); + mrb_obj_classname(mrb, sub)); } sub = tmp; } @@ -1404,10 +1401,10 @@ mrb_str_index_m(mrb_state *mrb, mrb_value str) case MRB_TT_STRING: pos = mrb_str_index(mrb, str, sub, pos); break; - } + } - if (pos == -1) return mrb_nil_value(); - return mrb_fixnum_value(pos); + if (pos == -1) return mrb_nil_value(); + return mrb_fixnum_value(pos); } #define STR_REPLACE_SHARED_MIN 10 @@ -1532,6 +1529,36 @@ mrb_obj_as_string(mrb_state *mrb, mrb_value obj) } mrb_value +mrb_ptr_to_str(mrb_state *mrb, void *p) +{ + struct RString *p_str; + char *p1; + char *p2; + intptr_t n = (intptr_t)p; + + p_str = str_new(mrb, NULL, 2 + sizeof(uintptr_t) * CHAR_BIT / 4); + p1 = p_str->ptr; + *p1++ = '0'; + *p1++ = 'x'; + p2 = p1; + + do { + *p2++ = mrb_digitmap[n % 16]; + n /= 16; + } while (n > 0); + *p2 = '\0'; + p_str->len = (mrb_int)(p2 - p_str->ptr); + + while (p1 < p2) { + const char c = *p1; + *p1++ = *--p2; + *p2 = c; + } + + return mrb_obj_value(p_str); +} + +mrb_value mrb_check_string_type(mrb_state *mrb, mrb_value str) { return mrb_check_convert_type(mrb, str, MRB_TT_STRING, "String", "to_str"); @@ -1637,7 +1664,7 @@ mrb_str_rindex(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int pos) char *s, *sbeg, *t; struct RString *ps = mrb_str_ptr(str); struct RString *psub = mrb_str_ptr(sub); - long len = psub->len; + mrb_int len = psub->len; /* substring longer than string */ if (ps->len < len) return -1; @@ -1661,15 +1688,6 @@ mrb_str_rindex(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int pos) } } -#ifdef INCLUDE_ENCODING -/* byte offset to char offset */ -int -mrb_str_sublen(mrb_state *mrb, mrb_value str, long pos) -{ - return pos; -} -#endif //INCLUDE_ENCODING - /* 15.2.10.5.31 */ /* * call-seq: @@ -1728,7 +1746,7 @@ mrb_str_rindex_m(mrb_state *mrb, mrb_value str) switch (mrb_type(sub)) { case MRB_TT_FIXNUM: { int c = mrb_fixnum(sub); - long len = RSTRING_LEN(str); + mrb_int len = RSTRING_LEN(str); unsigned char *p = (unsigned char*)RSTRING_PTR(str); for (pos=len;pos>=0;pos--) { @@ -1865,7 +1883,9 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str) int argc; mrb_value spat = mrb_nil_value(); enum {awk, string, regexp} split_type = string; - long beg, end, i = 0, lim_p; + long i = 0, lim_p; + mrb_int beg; + mrb_int end; mrb_int lim = 0; mrb_value result, tmp; @@ -1934,7 +1954,7 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str) char *ptr = RSTRING_PTR(str); char *temp = ptr; char *eptr = RSTRING_END(str); - long slen = RSTRING_LEN(spat); + mrb_int slen = RSTRING_LEN(spat); if (slen == 0) { int ai = mrb_gc_arena_save(mrb); @@ -1972,7 +1992,7 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str) mrb_ary_push(mrb, result, tmp); } if (!lim_p && lim == 0) { - long len; + mrb_int len; while ((len = RARRAY_LEN(result)) > 0 && (tmp = RARRAY_PTR(result)[len-1], RSTRING_LEN(tmp) == 0)) mrb_ary_pop(mrb, result); @@ -2054,7 +2074,8 @@ mrb_cstr_to_inum(mrb_state *mrb, const char *str, int base, int badcheck) char *end; char sign = 1; int c; - unsigned long val; + unsigned long n; + mrb_int val; #undef ISDIGIT #define ISDIGIT(c) ('0' <= (c) && (c) <= '9') @@ -2158,19 +2179,18 @@ mrb_cstr_to_inum(mrb_state *mrb, const char *str, int base, int badcheck) return mrb_fixnum_value(0); } - val = strtoul((char*)str, &end, base); - + n = strtoul((char*)str, &end, base); + if (n > MRB_INT_MAX) { + mrb_raisef(mrb, E_ARGUMENT_ERROR, "string (%s) too big for integer", str); + } + val = n; 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); - } + return mrb_fixnum_value(sign ? val : -val); bad: mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid string for number(%s)", str); /* not reached */ @@ -2440,7 +2460,7 @@ mrb_str_upcase(mrb_state *mrb, mrb_value self) mrb_value mrb_str_dump(mrb_state *mrb, mrb_value str) { - long len; + mrb_int len; const char *p, *pend; char *q; struct RString *result; @@ -2542,7 +2562,7 @@ mrb_str_dump(mrb_state *mrb, mrb_value str) } mrb_value -mrb_str_cat(mrb_state *mrb, mrb_value str, const char *ptr, long len) +mrb_str_cat(mrb_state *mrb, mrb_value str, const char *ptr, mrb_int len) { if (len < 0) { mrb_raise(mrb, E_ARGUMENT_ERROR, "negative string size (or size too big)"); @@ -2552,7 +2572,7 @@ mrb_str_cat(mrb_state *mrb, mrb_value str, const char *ptr, long len) } mrb_value -mrb_str_cat2(mrb_state *mrb, mrb_value str, const char *ptr) +mrb_str_cat_cstr(mrb_state *mrb, mrb_value str, const char *ptr) { return mrb_str_cat(mrb, str, ptr, strlen(ptr)); } diff --git a/src/symbol.c b/src/symbol.c index 72a5bea6b..243cb4b5d 100644 --- a/src/symbol.c +++ b/src/symbol.c @@ -10,10 +10,11 @@ #include "mruby/string.h" #include <ctype.h> +#include <limits.h> /* ------------------------------------------------------ */ typedef struct symbol_name { - int len; + size_t len; const char *name; } symbol_name; @@ -35,7 +36,7 @@ KHASH_DECLARE(n2s, symbol_name, mrb_sym, 1) KHASH_DEFINE (n2s, symbol_name, mrb_sym, 1, sym_hash_func, sym_hash_equal) /* ------------------------------------------------------ */ mrb_sym -mrb_intern2(mrb_state *mrb, const char *name, int len) +mrb_intern2(mrb_state *mrb, const char *name, size_t len) { khash_t(n2s) *h = mrb->name2sym; symbol_name sname; @@ -61,7 +62,7 @@ mrb_intern2(mrb_state *mrb, const char *name, int len) } mrb_sym -mrb_intern(mrb_state *mrb, const char *name) +mrb_intern_cstr(mrb_state *mrb, const char *name) { return mrb_intern2(mrb, name, strlen(name)); } @@ -72,8 +73,9 @@ mrb_intern_str(mrb_state *mrb, mrb_value str) return mrb_intern2(mrb, RSTRING_PTR(str), RSTRING_LEN(str)); } +/* lenp must be a pointer to a size_t variable */ const char* -mrb_sym2name_len(mrb_state *mrb, mrb_sym sym, int *lenp) +mrb_sym2name_len(mrb_state *mrb, mrb_sym sym, size_t *lenp) { khash_t(n2s) *h = mrb->name2sym; khiter_t k; @@ -156,10 +158,12 @@ static mrb_value sym_equal(mrb_state *mrb, mrb_value sym1) { mrb_value sym2; + mrb_bool equal_p; mrb_get_args(mrb, "o", &sym2); - if (mrb_obj_equal(mrb, sym1, sym2)) return mrb_true_value(); - return mrb_false_value(); + equal_p = mrb_obj_equal(mrb, sym1, sym2); + + return mrb_bool_value(equal_p); } /* 15.2.11.3.2 */ @@ -178,7 +182,7 @@ mrb_sym_to_s(mrb_state *mrb, mrb_value sym) { mrb_sym id = mrb_symbol(sym); const char *p; - int len; + size_t len; p = mrb_sym2name_len(mrb, id, &len); return mrb_str_new(mrb, p, len); @@ -198,7 +202,7 @@ mrb_sym_to_s(mrb_state *mrb, mrb_value sym) static mrb_value sym_to_sym(mrb_state *mrb, mrb_value sym) { - return sym; + return sym; } /* 15.2.11.3.5(x) */ @@ -222,106 +226,107 @@ sym_to_sym(mrb_state *mrb, mrb_value sym) static int is_special_global_name(const char* m) { - switch (*m) { - case '~': case '*': case '$': case '?': case '!': case '@': - case '/': case '\\': case ';': case ',': case '.': case '=': - case ':': case '<': case '>': case '\"': - case '&': case '`': case '\'': case '+': - case '0': - ++m; - break; - case '-': - ++m; - if (is_identchar(*m)) m += 1; - break; - default: - if (!ISDIGIT(*m)) return FALSE; - do ++m; while (ISDIGIT(*m)); - } - return !*m; + switch (*m) { + case '~': case '*': case '$': case '?': case '!': case '@': + case '/': case '\\': case ';': case ',': case '.': case '=': + case ':': case '<': case '>': case '\"': + case '&': case '`': case '\'': case '+': + case '0': + ++m; + break; + case '-': + ++m; + if (is_identchar(*m)) m += 1; + break; + default: + if (!ISDIGIT(*m)) return FALSE; + do ++m; while (ISDIGIT(*m)); + break; + } + return !*m; } static int symname_p(const char *name) { - const char *m = name; - int localid = FALSE; - - if (!m) return FALSE; - switch (*m) { - case '\0': - return FALSE; - - case '$': - if (is_special_global_name(++m)) return TRUE; - goto id; - - case '@': - if (*++m == '@') ++m; - goto id; - - case '<': - switch (*++m) { - case '<': ++m; break; - case '=': if (*++m == '>') ++m; break; - default: break; - } - break; + const char *m = name; + int localid = FALSE; + + if (!m) return FALSE; + switch (*m) { + case '\0': + return FALSE; + + case '$': + if (is_special_global_name(++m)) return TRUE; + goto id; + + case '@': + if (*++m == '@') ++m; + goto id; + + case '<': + switch (*++m) { + case '<': ++m; break; + case '=': if (*++m == '>') ++m; break; + default: break; + } + break; - case '>': - switch (*++m) { - case '>': case '=': ++m; break; - default: break; - } - break; + case '>': + switch (*++m) { + case '>': case '=': ++m; break; + default: break; + } + break; - case '=': - switch (*++m) { - case '~': ++m; break; - case '=': if (*++m == '=') ++m; break; - default: return FALSE; - } - break; - - case '*': - if (*++m == '*') ++m; - break; - case '!': - if (*++m == '=') ++m; - break; - case '+': case '-': - if (*++m == '@') ++m; - break; - case '|': - if (*++m == '|') ++m; - break; - case '&': - if (*++m == '&') ++m; - break; - - case '^': case '/': case '%': case '~': case '`': - ++m; - break; - - case '[': - if (*++m != ']') return FALSE; - if (*++m == '=') ++m; - break; - - default: - localid = !ISUPPER(*m); + case '=': + switch (*++m) { + case '~': ++m; break; + case '=': if (*++m == '=') ++m; break; + default: return FALSE; + } + break; + + case '*': + if (*++m == '*') ++m; + break; + case '!': + if (*++m == '=') ++m; + break; + case '+': case '-': + if (*++m == '@') ++m; + break; + case '|': + if (*++m == '|') ++m; + break; + case '&': + if (*++m == '&') ++m; + break; + + case '^': case '/': case '%': case '~': case '`': + ++m; + break; + + case '[': + if (*++m != ']') return FALSE; + if (*++m == '=') ++m; + break; + + default: + localid = !ISUPPER(*m); id: - if (*m != '_' && !ISALPHA(*m)) return FALSE; - while (is_identchar(*m)) m += 1; - if (localid) { - switch (*m) { - case '!': case '?': case '=': ++m; - default: break; + if (*m != '_' && !ISALPHA(*m)) return FALSE; + while (is_identchar(*m)) m += 1; + if (localid) { + switch (*m) { + case '!': case '?': case '=': ++m; + default: break; } } - break; - } - return *m ? FALSE : TRUE; + break; + } + return *m ? FALSE : TRUE; } static mrb_value @@ -329,7 +334,7 @@ sym_inspect(mrb_state *mrb, mrb_value sym) { mrb_value str; const char *name; - int len; + size_t len; mrb_sym id = mrb_symbol(sym); name = mrb_sym2name_len(mrb, id, &len); @@ -346,7 +351,7 @@ sym_inspect(mrb_state *mrb, mrb_value sym) const char* mrb_sym2name(mrb_state *mrb, mrb_sym sym) { - int len; + size_t len; const char *name = mrb_sym2name_len(mrb, sym, &len); if (!name) return NULL; @@ -374,7 +379,8 @@ sym_cmp(mrb_state *mrb, mrb_value s1) if (sym1 == sym2) return mrb_fixnum_value(0); else { const char *p1, *p2; - int len, len1, len2, retval; + int retval; + size_t len, len1, len2; p1 = mrb_sym2name_len(mrb, sym1, &len1); p2 = mrb_sym2name_len(mrb, sym2, &len2); diff --git a/src/value_array.h b/src/value_array.h new file mode 100644 index 000000000..cabd2426d --- /dev/null +++ b/src/value_array.h @@ -0,0 +1,27 @@ +#ifndef MRB_VALUE_ARRAY_H__ +#define MRB_VALUE_ARRAY_H__ + +#include "mruby.h" + +static inline void +value_move(mrb_value *s1, const mrb_value *s2, size_t n) +{ + if (s1 > s2 && s1 < s2 + n) + { + s1 += n; + s2 += n; + while (n-- > 0) { + *--s1 = *--s2; + } + } + else if (s1 != s2) { + while (n-- > 0) { + *s1++ = *s2++; + } + } + else { + /* nothing to do. */ + } +} + +#endif /* MRB_VALUE_ARRAY_H__ */ diff --git a/src/variable.c b/src/variable.c index 8715505c3..c191b2be2 100644 --- a/src/variable.c +++ b/src/variable.c @@ -28,8 +28,8 @@ typedef struct segment { typedef struct iv_tbl { segment *rootseg; - int size; - int last_len; + size_t size; + size_t last_len; } iv_tbl; static iv_tbl* @@ -52,8 +52,8 @@ iv_put(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value val) segment *seg = t->rootseg; segment *prev = NULL; segment *matched_seg = NULL; - int matched_idx = 0; - int i; + size_t matched_idx = 0; + size_t i; while (seg) { for (i=0; i<MRB_SEGMENT_SIZE; i++) { @@ -102,11 +102,11 @@ iv_put(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value val) return; } -static int +static mrb_bool iv_get(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp) { segment *seg; - int i; + size_t i; seg = t->rootseg; while (seg) { @@ -126,11 +126,11 @@ iv_get(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp) return FALSE; } -static int +static mrb_bool iv_del(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp) { segment *seg; - int i; + size_t i; seg = t->rootseg; while (seg) { @@ -152,11 +152,12 @@ iv_del(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp) return FALSE; } -static int +static mrb_bool iv_foreach(mrb_state *mrb, iv_tbl *t, iv_foreach_func *func, void *p) { segment *seg; - int i, n; + size_t i; + int n; seg = t->rootseg; while (seg) { @@ -181,11 +182,11 @@ iv_foreach(mrb_state *mrb, iv_tbl *t, iv_foreach_func *func, void *p) return TRUE; } -static int +static size_t iv_size(mrb_state *mrb, iv_tbl *t) { segment *seg; - int size = 0; + size_t size = 0; if (!t) return 0; if (t->size > 0) return t->size; @@ -208,7 +209,7 @@ iv_copy(mrb_state *mrb, iv_tbl *t) segment *seg; iv_tbl *t2; - int i; + size_t i; seg = t->rootseg; t2 = iv_new(mrb); @@ -273,7 +274,7 @@ iv_put(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value val) kh_value(h, k) = val; } -static int +static mrb_bool iv_get(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp) { khash_t(iv) *h = &t->h; @@ -287,7 +288,7 @@ iv_get(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp) return FALSE; } -static int +static mrb_bool iv_del(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp) { khash_t(iv) *h = &t->h; @@ -305,7 +306,7 @@ iv_del(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp) return FALSE; } -static int +static mrb_bool iv_foreach(mrb_state *mrb, iv_tbl *t, iv_foreach_func *func, void *p) { khash_t(iv) *h = &t->h; @@ -326,7 +327,7 @@ iv_foreach(mrb_state *mrb, iv_tbl *t, iv_foreach_func *func, void *p) return TRUE; } -static int +static size_t iv_size(mrb_state *mrb, iv_tbl *t) { khash_t(iv) *h = &t->h; @@ -408,7 +409,7 @@ mrb_vm_special_set(mrb_state *mrb, mrb_sym i, mrb_value v) { } -static int +static mrb_bool obj_iv_p(mrb_value obj) { switch (mrb_type(obj)) { @@ -481,7 +482,7 @@ mrb_iv_set(mrb_state *mrb, mrb_value obj, mrb_sym sym, mrb_value v) } } -int +mrb_bool mrb_obj_iv_defined(mrb_state *mrb, struct RObject *obj, mrb_sym sym) { iv_tbl *t; @@ -493,7 +494,7 @@ mrb_obj_iv_defined(mrb_state *mrb, struct RObject *obj, mrb_sym sym) return FALSE; } -int +mrb_bool mrb_iv_defined(mrb_state *mrb, mrb_value obj, mrb_sym sym) { if (!obj_iv_p(obj)) return FALSE; @@ -520,15 +521,15 @@ inspect_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p) { mrb_value str = *(mrb_value*)p; const char *s; - int len; + size_t len; /* need not to show internal data */ if (RSTRING_PTR(str)[0] == '-') { /* first element */ RSTRING_PTR(str)[0] = '#'; - mrb_str_cat2(mrb, str, " "); + mrb_str_cat(mrb, str, " ", 1); } else { - mrb_str_cat2(mrb, str, ", "); + mrb_str_cat(mrb, str, ", ", 2); } s = mrb_sym2name_len(mrb, sym, &len); mrb_str_cat(mrb, str, s, len); @@ -541,13 +542,19 @@ mrb_value mrb_obj_iv_inspect(mrb_state *mrb, struct RObject *obj) { iv_tbl *t = obj->iv; - int len = iv_size(mrb, t); + size_t len = iv_size(mrb, t); if (len > 0) { const char *cn = mrb_obj_classname(mrb, mrb_obj_value(obj)); - mrb_value str = mrb_sprintf(mrb, "-<%s:%p", cn, (void*)obj); + mrb_value str = mrb_str_buf_new(mrb, 30); + + mrb_str_buf_cat(mrb, str, "-<", 2); + mrb_str_cat2(mrb, str, cn); + mrb_str_cat(mrb, str, ":", 1); + mrb_str_concat(mrb, str, mrb_ptr_to_str(mrb, obj)); iv_foreach(mrb, t, inspect_i, &str); + mrb_str_cat(mrb, str, ">", 1); return str; } return mrb_any_to_s(mrb, mrb_obj_value(obj)); @@ -586,7 +593,7 @@ iv_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p) { mrb_value ary; const char* s; - int len; + size_t len; ary = *(mrb_value*)p; s = mrb_sym2name_len(mrb, sym, &len); @@ -630,7 +637,7 @@ cv_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p) { mrb_value ary; const char* s; - int len; + size_t len; ary = *(mrb_value*)p; s = mrb_sym2name_len(mrb, sym, &len); @@ -727,7 +734,7 @@ mrb_cv_set(mrb_state *mrb, mrb_value mod, mrb_sym sym, mrb_value v) mrb_mod_cv_set(mrb, mrb_class_ptr(mod), sym, v); } -int +mrb_bool mrb_mod_cv_defined(mrb_state *mrb, struct RClass * c, mrb_sym sym) { while (c) { @@ -741,7 +748,7 @@ mrb_mod_cv_defined(mrb_state *mrb, struct RClass * c, mrb_sym sym) return FALSE; } -int +mrb_bool mrb_cv_defined(mrb_state *mrb, mrb_value mod, mrb_sym sym) { return mrb_mod_cv_defined(mrb, mrb_class_ptr(mod), sym); @@ -783,7 +790,7 @@ mrb_vm_cv_set(mrb_state *mrb, mrb_sym sym, mrb_value v) iv_put(mrb, c->iv, sym, v); } -int +mrb_bool mrb_const_defined(mrb_state *mrb, mrb_value mod, mrb_sym sym) { struct RClass *m = mrb_class_ptr(mod); @@ -813,7 +820,7 @@ const_get(mrb_state *mrb, struct RClass *base, mrb_sym sym) struct RClass *c = base; mrb_value v; iv_tbl *t; - int retry = 0; + mrb_bool retry = 0; mrb_sym cm; L_RETRY: @@ -831,7 +838,7 @@ L_RETRY: goto L_RETRY; } c = base; - cm = mrb_intern(mrb, "const_missing"); + 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); @@ -964,7 +971,7 @@ mrb_f_global_variables(mrb_state *mrb, mrb_value self) { iv_tbl *t = mrb->globals; mrb_value ary = mrb_ary_new(mrb); - int i; + size_t i; char buf[3]; if (t) { @@ -979,11 +986,11 @@ mrb_f_global_variables(mrb_state *mrb, mrb_value self) return ary; } -static int -mrb_const_defined_0(mrb_state *mrb, struct RClass *klass, mrb_sym id, int exclude, int recurse) +static mrb_bool +mrb_const_defined_0(mrb_state *mrb, struct RClass *klass, mrb_sym id, mrb_bool exclude, mrb_bool recurse) { struct RClass * tmp; - int mod_retry = 0; + mrb_bool mod_retry = 0; tmp = klass; retry: @@ -1046,7 +1053,7 @@ mrb_class_sym(mrb_state *mrb, struct RClass *c, struct RClass *outer) { mrb_value name; - name = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern(mrb, "__classid__")); + name = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern2(mrb, "__classid__", 11)); if (mrb_nil_p(name)) { if (!outer) return 0; @@ -16,6 +16,7 @@ #include "mruby/class.h" #include "mruby/numeric.h" #include "error.h" +#include "value_array.h" #include <string.h> #include <setjmp.h> @@ -45,7 +46,7 @@ /* Maximum stack depth. Should be set lower on memory constrained systems. The value below allows about 60000 recursive calls in the simplest case. */ #ifndef MRB_STACK_MAX -#define MRB_STACK_MAX ((1<<18) - MRB_STACK_GROWTH) +#define MRB_STACK_MAX (0x40000 - MRB_STACK_GROWTH) #endif #ifdef VM_DEBUG @@ -55,12 +56,20 @@ The value below allows about 60000 recursive calls in the simplest case. */ #endif static inline void -stack_copy(mrb_value *dst, const mrb_value *src, size_t size) +stack_clear(mrb_value *from, size_t count) { - size_t i; + const mrb_value mrb_value_zero = { { 0 } }; + + while(count-- > 0) { + *from++ = mrb_value_zero; + } +} - for (i = 0; i < size; i++) { - dst[i] = src[i]; +static inline void +stack_copy(mrb_value *dst, const mrb_value *src, size_t size) +{ + while (size-- > 0) { + *dst++ = *src++; } } @@ -79,7 +88,7 @@ stack_init(mrb_state *mrb) mrb->ci->target_class = mrb->object_class; } -static void +static inline void envadjust(mrb_state *mrb, mrb_value *oldbase, mrb_value *newbase) { mrb_callinfo *ci = mrb->cibase; @@ -87,7 +96,7 @@ envadjust(mrb_state *mrb, mrb_value *oldbase, mrb_value *newbase) while (ci <= mrb->ci) { struct REnv *e = ci->env; if (e && e->cioff >= 0) { - int off = e->stack - oldbase; + ptrdiff_t off = e->stack - oldbase; e->stack = newbase + off; } @@ -100,8 +109,9 @@ envadjust(mrb_state *mrb, mrb_value *oldbase, mrb_value *newbase) static void stack_extend(mrb_state *mrb, int room, int keep) { - int size, off; if (mrb->stack + room >= mrb->stend) { + int size, off; + mrb_value *oldbase = mrb->stbase; size = mrb->stend - mrb->stbase; @@ -130,26 +140,18 @@ stack_extend(mrb_state *mrb, int room, int keep) } if (room > keep) { - int i; - for (i=keep; i<room; i++) { #ifndef MRB_NAN_BOXING - static const mrb_value mrb_value_zero = { { 0 } }; - mrb->stack[i] = mrb_value_zero; + stack_clear(&(mrb->stack[keep]), room - keep); #else + int i; + for (i=keep; i<room; i++) { SET_NIL_VALUE(mrb->stack[i]); -#endif } +#endif } } -int -mrb_checkstack(mrb_state *mrb, int size) -{ - stack_extend(mrb, size+1, 1); - return 0; -} - -struct REnv* +static inline struct REnv* uvenv(mrb_state *mrb, int up) { struct REnv *e = mrb->ci->proc->env; @@ -161,25 +163,6 @@ uvenv(mrb_state *mrb, int up) return e; } -static mrb_value -uvget(mrb_state *mrb, int up, int idx) -{ - struct REnv *e = uvenv(mrb, up); - - if (!e) return mrb_nil_value(); - return e->stack[idx]; -} - -static void -uvset(mrb_state *mrb, int up, int idx, mrb_value v) -{ - struct REnv *e = uvenv(mrb, up); - - if (!e) return; - e->stack[idx] = v; - mrb_write_barrier(mrb, (struct RBasic*)e); -} - static inline int is_strict(mrb_state *mrb, struct REnv *e) { @@ -192,7 +175,7 @@ is_strict(mrb_state *mrb, struct REnv *e) return 0; } -struct REnv* +inline struct REnv* top_env(mrb_state *mrb, struct RProc *proc) { struct REnv *e = proc->env; @@ -231,7 +214,7 @@ cipop(mrb_state *mrb) { if (mrb->ci->env) { struct REnv *e = mrb->ci->env; - int len = (int)e->flags; + size_t len = (size_t)e->flags; mrb_value *p = (mrb_value *)mrb_malloc(mrb, sizeof(mrb_value)*len); e->cioff = -1; @@ -273,14 +256,13 @@ mrb_value mrb_funcall(mrb_state *mrb, mrb_value self, const char *name, int argc, ...) { mrb_sym mid = mrb_intern(mrb, name); - va_list ap; - int i; if (argc == 0) { return mrb_funcall_argv(mrb, self, mid, 0, 0); } else if (argc == 1) { mrb_value v; + va_list ap; va_start(ap, argc); v = va_arg(ap, mrb_value); @@ -289,6 +271,8 @@ mrb_funcall(mrb_state *mrb, mrb_value self, const char *name, int argc, ...) } else { mrb_value argv[MRB_FUNCALL_ARGC_MAX]; + va_list ap; + int i; if (argc > MRB_FUNCALL_ARGC_MAX) { mrb_raisef(mrb, E_ARGUMENT_ERROR, "Too long arguments. (limit=%d)", MRB_FUNCALL_ARGC_MAX); @@ -306,11 +290,6 @@ mrb_funcall(mrb_state *mrb, mrb_value self, const char *name, int argc, ...) mrb_value mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, int argc, mrb_value *argv, mrb_value blk) { - struct RProc *p; - struct RClass *c; - mrb_sym undef = 0; - mrb_callinfo *ci; - int n; mrb_value val; if (!mrb->jmp) { @@ -323,66 +302,74 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, int argc, mr cipop(mrb); } mrb->jmp = 0; - return mrb_nil_value(); + val = mrb_nil_value(); + } + else { + mrb->jmp = &c_jmp; + /* recursive call */ + val = mrb_funcall_with_block(mrb, self, mid, argc, argv, blk); + mrb->jmp = 0; } - mrb->jmp = &c_jmp; - /* recursive call */ - val = mrb_funcall_with_block(mrb, self, mid, argc, argv, blk); - mrb->jmp = 0; - return val; - } - - if (!mrb->stack) { - stack_init(mrb); - } - n = mrb->ci->nregs; - if (argc < 0) { - mrb_raisef(mrb, E_ARGUMENT_ERROR, "negative argc for funcall (%d)", argc); - } - c = mrb_class(mrb, self); - p = mrb_method_search_vm(mrb, &c, mid); - if (!p) { - undef = mid; - mid = mrb_intern(mrb, "method_missing"); - p = mrb_method_search_vm(mrb, &c, mid); - n++; argc++; - } - ci = cipush(mrb); - ci->mid = mid; - ci->proc = p; - ci->stackidx = mrb->stack - mrb->stbase; - ci->argc = argc; - ci->target_class = p->target_class; - if (MRB_PROC_CFUNC_P(p)) { - ci->nregs = argc + 2; } else { - ci->nregs = p->body.irep->nregs + 2; - } - ci->acc = -1; - mrb->stack = mrb->stack + n; + struct RProc *p; + struct RClass *c; + mrb_sym undef = 0; + mrb_callinfo *ci; + int n; - stack_extend(mrb, ci->nregs, 0); - mrb->stack[0] = self; - if (undef) { - mrb->stack[1] = mrb_symbol_value(undef); - stack_copy(mrb->stack+2, argv, argc-1); - } - else if (argc > 0) { - stack_copy(mrb->stack+1, argv, argc); - } - mrb->stack[argc+1] = blk; - - if (MRB_PROC_CFUNC_P(p)) { - int ai = mrb_gc_arena_save(mrb); - val = p->body.func(mrb, self); - mrb_gc_arena_restore(mrb, ai); - mrb_gc_protect(mrb, val); - mrb->stack = mrb->stbase + mrb->ci->stackidx; - cipop(mrb); - } - else { - val = mrb_run(mrb, p, self); + if (!mrb->stack) { + stack_init(mrb); + } + n = mrb->ci->nregs; + if (argc < 0) { + mrb_raisef(mrb, E_ARGUMENT_ERROR, "negative argc for funcall (%d)", argc); + } + c = mrb_class(mrb, self); + p = mrb_method_search_vm(mrb, &c, mid); + if (!p) { + undef = mid; + mid = mrb_intern2(mrb, "method_missing", 14); + p = mrb_method_search_vm(mrb, &c, mid); + n++; argc++; + } + ci = cipush(mrb); + ci->mid = mid; + ci->proc = p; + ci->stackidx = mrb->stack - mrb->stbase; + ci->argc = argc; + ci->target_class = p->target_class; + if (MRB_PROC_CFUNC_P(p)) { + ci->nregs = argc + 2; + } + else { + ci->nregs = p->body.irep->nregs + 2; + } + ci->acc = -1; + mrb->stack = mrb->stack + n; + + stack_extend(mrb, ci->nregs, 0); + mrb->stack[0] = self; + if (undef) { + mrb->stack[1] = mrb_symbol_value(undef); + stack_copy(mrb->stack+2, argv, argc-1); + } + else if (argc > 0) { + stack_copy(mrb->stack+1, argv, argc); + } + mrb->stack[argc+1] = blk; + + if (MRB_PROC_CFUNC_P(p)) { + int ai = mrb_gc_arena_save(mrb); + val = p->body.func(mrb, self); + mrb_gc_arena_restore(mrb, ai); + mrb_gc_protect(mrb, val); + mrb->stack = mrb->stbase + mrb->ci->stackidx; + cipop(mrb); + } + else { + val = mrb_run(mrb, p, self); + } } return val; } @@ -471,14 +458,14 @@ localjump_error(mrb_state *mrb, localjump_error_kind kind) mrb_str_buf_cat(mrb, msg, lead, sizeof(lead) - 1); mrb_str_buf_cat(mrb, msg, kind_str[kind], kind_str_len[kind]); exc = mrb_exc_new3(mrb, E_LOCALJUMP_ERROR, msg); - mrb->exc = (struct RObject*)mrb_object(exc); + mrb->exc = mrb_obj_ptr(exc); } static void argnum_error(mrb_state *mrb, int num) { char buf[256]; - int len; + size_t len; mrb_value exc; if (mrb->ci->mid) { @@ -491,7 +478,7 @@ argnum_error(mrb_state *mrb, int num) mrb->ci->argc, num); } exc = mrb_exc_new(mrb, E_ARGUMENT_ERROR, buf, len); - mrb->exc = (struct RObject*)mrb_object(exc); + mrb->exc = mrb_obj_ptr(exc); } #ifdef ENABLE_DEBUG @@ -709,14 +696,34 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) CASE(OP_GETUPVAR) { /* A B C R(A) := uvget(B,C) */ + mrb_value *regs_a = regs + GETARG_A(i); + int up = GETARG_C(i); + + struct REnv *e = uvenv(mrb, up); - regs[GETARG_A(i)] = uvget(mrb, GETARG_C(i), GETARG_B(i)); + if (!e) { + *regs_a = mrb_nil_value(); + } + else { + int idx = GETARG_B(i); + *regs_a = e->stack[idx]; + } NEXT; } CASE(OP_SETUPVAR) { /* A B C uvset(B,C,R(A)) */ - uvset(mrb, GETARG_C(i), GETARG_B(i), regs[GETARG_A(i)]); + /* A B C R(A) := uvget(B,C) */ + int up = GETARG_C(i); + + struct REnv *e = uvenv(mrb, up); + + if (e) { + mrb_value *regs_a = regs + GETARG_A(i); + int idx = GETARG_B(i); + e->stack[idx] = *regs_a; + mrb_write_barrier(mrb, (struct RBasic*)e); + } NEXT; } @@ -773,7 +780,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) CASE(OP_RAISE) { /* A raise(R(A)) */ - mrb->exc = (struct RObject*)mrb_object(regs[GETARG_A(i)]); + mrb->exc = mrb_obj_ptr(regs[GETARG_A(i)]); goto L_RAISE; } @@ -842,15 +849,14 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) if (!m) { mrb_value sym = mrb_symbol_value(mid); - mid = mrb_intern(mrb, "method_missing"); + mid = mrb_intern2(mrb, "method_missing", 14); m = mrb_method_search_vm(mrb, &c, mid); if (n == CALL_MAXARGS) { mrb_ary_unshift(mrb, regs[a+1], sym); } else { - memmove(regs+a+2, regs+a+1, sizeof(mrb_value)*(n+1)); + value_move(regs+a+2, regs+a+1, ++n); regs[a+1] = sym; - n++; } } @@ -859,8 +865,12 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) ci->mid = mid; ci->proc = m; ci->stackidx = mrb->stack - mrb->stbase; - ci->argc = n; - if (ci->argc == CALL_MAXARGS) ci->argc = -1; + if (n == CALL_MAXARGS) { + ci->argc = -1; + } + else { + ci->argc = n; + } ci->target_class = c; ci->pc = pc + 1; ci->acc = a; @@ -981,15 +991,14 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) c = mrb->ci->target_class->super; m = mrb_method_search_vm(mrb, &c, mid); if (!m) { - mid = mrb_intern(mrb, "method_missing"); + mid = mrb_intern2(mrb, "method_missing", 14); m = mrb_method_search_vm(mrb, &c, mid); if (n == CALL_MAXARGS) { mrb_ary_unshift(mrb, regs[a+1], mrb_symbol_value(ci->mid)); } else { - memmove(regs+a+2, regs+a+1, sizeof(mrb_value)*(n+1)); + value_move(regs+a+2, regs+a+1, ++n); SET_SYM_VALUE(regs[a+1], ci->mid); - n++; } } @@ -998,8 +1007,12 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) ci->mid = mid; ci->proc = m; ci->stackidx = mrb->stack - mrb->stbase; - ci->argc = n; - if (ci->argc == CALL_MAXARGS) ci->argc = -1; + if (n == CALL_MAXARGS) { + ci->argc = -1; + } + else { + ci->argc = n; + } ci->target_class = m->target_class; ci->pc = pc + 1; @@ -1026,7 +1039,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) pool = irep->pool; syms = irep->syms; ci->nregs = irep->nregs; - if (ci->argc < 0) { + if (n == CALL_MAXARGS) { stack_extend(mrb, (irep->nregs < 3) ? 3 : irep->nregs, 3); } else { @@ -1055,7 +1068,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) mrb_value exc; static const char m[] = "super called outside of method"; exc = mrb_exc_new(mrb, E_NOMETHOD_ERROR, m, sizeof(m) - 1); - mrb->exc = (struct RObject*)mrb_object(exc); + mrb->exc = mrb_obj_ptr(exc); goto L_RAISE; } stack = e->stack + 1; @@ -1093,7 +1106,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) CASE(OP_ENTER) { /* Ax arg setup according to flags (24=5:5:1:5:5:1:1) */ /* number of optional arguments times OP_JMP should follow */ - int ax = GETARG_Ax(i); + int32_t ax = GETARG_Ax(i); int m1 = (ax>>18)&0x1f; int o = (ax>>13)&0x1f; int r = (ax>>12)&0x1; @@ -1131,10 +1144,10 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) if (argc < len) { regs[len+1] = *blk; /* move block */ if (argv0 != argv) { - memmove(®s[1], argv, sizeof(mrb_value)*(argc-m2)); /* m1 + o */ + value_move(®s[1], argv, argc-m2); /* m1 + o */ } if (m2) { - memmove(®s[len-m2+1], &argv[argc-m2], sizeof(mrb_value)*m2); /* m2 */ + value_move(®s[len-m2+1], &argv[argc-m2], m2); /* m2 */ } if (r) { /* r */ regs[m1+o+1] = mrb_ary_new_capa(mrb, 0); @@ -1146,13 +1159,13 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) else { if (argv0 != argv) { regs[len+1] = *blk; /* move block */ - memmove(®s[1], argv, sizeof(mrb_value)*(m1+o)); /* m1 + o */ + value_move(®s[1], argv, m1+o); /* m1 + o */ } if (r) { /* r */ regs[m1+o+1] = mrb_ary_new_from_values(mrb, argc-m1-o-m2, argv+m1+o); } if (m2) { - memmove(®s[m1+o+r+1], &argv[argc-m2], sizeof(mrb_value)*m2); + value_move(®s[m1+o+r+1], &argv[argc-m2], m2); } if (argv0 == argv) { regs[len+1] = *blk; /* move block */ @@ -1183,8 +1196,8 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) L_RAISE: ci = mrb->ci; - mrb_obj_iv_ifnone(mrb, mrb->exc, mrb_intern(mrb, "lastpc"), mrb_voidp_value(pc)); - mrb_obj_iv_ifnone(mrb, mrb->exc, mrb_intern(mrb, "ciidx"), mrb_fixnum_value(ci - mrb->cibase)); + mrb_obj_iv_ifnone(mrb, mrb->exc, mrb_intern2(mrb, "lastpc", 6), mrb_voidp_value(pc)); + mrb_obj_iv_ifnone(mrb, mrb->exc, mrb_intern2(mrb, "ciidx", 5), mrb_fixnum_value(ci - mrb->cibase)); eidx = ci->eidx; if (ci == mrb->cibase) { if (ci->ridx == 0) goto L_STOP; @@ -1300,15 +1313,14 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) if (!m) { mrb_value sym = mrb_symbol_value(mid); - mid = mrb_intern(mrb, "method_missing"); + mid = mrb_intern2(mrb, "method_missing", 14); m = mrb_method_search_vm(mrb, &c, mid); if (n == CALL_MAXARGS) { mrb_ary_unshift(mrb, regs[a+1], sym); } else { - memmove(regs+a+2, regs+a+1, sizeof(mrb_value)*(n+1)); + value_move(regs+a+2, regs+a+1, ++n); regs[a+1] = sym; - n++; } } @@ -1317,11 +1329,15 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) ci = mrb->ci; ci->mid = mid; ci->target_class = m->target_class; - ci->argc = n; - if (ci->argc == CALL_MAXARGS) ci->argc = -1; + if (n == CALL_MAXARGS) { + ci->argc = -1; + } + else { + ci->argc = n; + } /* move stack */ - memmove(mrb->stack, ®s[a], (ci->argc+1)*sizeof(mrb_value)); + value_move(mrb->stack, ®s[a], ci->argc+1); if (MRB_PROC_CFUNC_P(m)) { mrb->stack[0] = m->body.func(mrb, recv); @@ -1375,7 +1391,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) #define attr_f value.f #endif -#define TYPES2(a,b) (((((int)(a))<<8)|((int)(b)))&0xffff) +#define TYPES2(a,b) ((((uint16_t)(a))<<8)|(((uint16_t)(b))&0xff)) #define OP_MATH_BODY(op,v1,v2) do {\ regs[a].v1 = regs[a].v1 op regs[a+1].v2;\ } while(0) @@ -1389,16 +1405,18 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM): { mrb_int x, y, z; + mrb_value *regs_a = regs + a; - x = mrb_fixnum(regs[a]); - y = mrb_fixnum(regs[a+1]); + x = mrb_fixnum(regs_a[0]); + y = mrb_fixnum(regs_a[1]); z = x + y; - if (((x < 0) ^ (y < 0)) == 0 && (x < 0) != (z < 0)) { + if ((x < 0) != (z < 0) && ((x < 0) ^ (y < 0)) == 0) { /* integer overflow */ - SET_FLT_VALUE(regs[a], (mrb_float)x + (mrb_float)y); - break; + SET_FLT_VALUE(regs_a[0], (mrb_float)x + (mrb_float)y); + } + else { + regs_a[0].attr_i = z; } - SET_INT_VALUE(regs[a], z); } break; case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT): @@ -1570,28 +1588,30 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) CASE(OP_SUBI) { /* A B C R(A) := R(A)-C (Syms[B]=:+)*/ int a = GETARG_A(i); + mrb_value *regs_a = regs + a; /* need to check if + is overridden */ - switch (mrb_type(regs[a])) { + switch (mrb_type(regs_a[0])) { case MRB_TT_FIXNUM: { - mrb_int x = regs[a].attr_i; + mrb_int x = regs_a[0].attr_i; mrb_int y = GETARG_C(i); mrb_int z = x - y; - if (((x < 0) ^ (y < 0)) != 0 && (x < 0) != (z < 0)) { + if ((x < 0) != (z < 0) && ((x < 0) ^ (y < 0)) != 0) { /* integer overflow */ - SET_FLT_VALUE(regs[a], (mrb_float)x - (mrb_float)y); - break; + SET_FLT_VALUE(regs_a[0], (mrb_float)x - (mrb_float)y); + } + else { + regs_a[0].attr_i = z; } - regs[a].attr_i = z; } break; case MRB_TT_FLOAT: - regs[a].attr_f -= GETARG_C(i); + regs_a[0].attr_f -= GETARG_C(i); break; default: - SET_INT_VALUE(regs[a+1], GETARG_C(i)); + SET_INT_VALUE(regs_a[1], GETARG_C(i)); i = MKOP_ABC(OP_SEND, a, GETARG_B(i), 1); goto L_SEND; } @@ -1904,7 +1924,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) if (!mrb->ci->target_class) { static const char msg[] = "no target class or module"; mrb_value exc = mrb_exc_new(mrb, E_TYPE_ERROR, msg, sizeof(msg) - 1); - mrb->exc = (struct RObject*)mrb_object(exc); + mrb->exc = mrb_obj_ptr(exc); goto L_RAISE; } regs[GETARG_A(i)] = mrb_obj_value(mrb->ci->target_class); @@ -1957,7 +1977,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) else { exc = mrb_exc_new3(mrb, E_LOCALJUMP_ERROR, msg); } - mrb->exc = (struct RObject*)mrb_object(exc); + mrb->exc = mrb_obj_ptr(exc); goto L_RAISE; } } |
