diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/array.c | 192 | ||||
| -rw-r--r-- | src/backtrace.c | 32 | ||||
| -rw-r--r-- | src/class.c | 275 | ||||
| -rw-r--r-- | src/codegen.c | 159 | ||||
| -rw-r--r-- | src/debug.c | 2 | ||||
| -rw-r--r-- | src/dump.c | 84 | ||||
| -rw-r--r-- | src/error.c | 45 | ||||
| -rw-r--r-- | src/error.h | 4 | ||||
| -rw-r--r-- | src/etc.c | 57 | ||||
| -rw-r--r-- | src/gc.c | 68 | ||||
| -rw-r--r-- | src/hash.c | 43 | ||||
| -rw-r--r-- | src/init.c | 2 | ||||
| -rw-r--r-- | src/kernel.c | 56 | ||||
| -rw-r--r-- | src/load.c | 84 | ||||
| -rw-r--r-- | src/numeric.c | 25 | ||||
| -rw-r--r-- | src/object.c | 32 | ||||
| -rw-r--r-- | src/parse.y | 6036 | ||||
| -rw-r--r-- | src/print.c | 9 | ||||
| -rw-r--r-- | src/proc.c | 13 | ||||
| -rw-r--r-- | src/range.c | 16 | ||||
| -rw-r--r-- | src/re.h | 1 | ||||
| -rw-r--r-- | src/state.c | 56 | ||||
| -rw-r--r-- | src/string.c | 45 | ||||
| -rw-r--r-- | src/symbol.c | 69 | ||||
| -rw-r--r-- | src/variable.c | 54 | ||||
| -rw-r--r-- | src/version.c | 13 | ||||
| -rw-r--r-- | src/vm.c | 196 |
27 files changed, 3944 insertions, 3724 deletions
diff --git a/src/array.c b/src/array.c index 966d4956c..9fe11bee0 100644 --- a/src/array.c +++ b/src/array.c @@ -4,16 +4,11 @@ ** See Copyright Notice in mruby.h */ -#ifndef SIZE_MAX - /* Some versions of VC++ - * has SIZE_MAX in stdint.h - */ -# include <limits.h> -#endif #include "mruby.h" #include "mruby/array.h" #include "mruby/class.h" #include "mruby/string.h" +#include "mruby/range.h" #include "value_array.h" #define ARY_DEFAULT_LEN 4 @@ -309,7 +304,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_intern2(mrb, "<=>", 3); + mrb_sym cmp = mrb_intern_lit(mrb, "<=>"); len = RARRAY_LEN(ary1); if (len > RARRAY_LEN(ary2)) { @@ -318,7 +313,7 @@ mrb_ary_cmp(mrb_state *mrb, mrb_value ary1) for (i=0; i<len; i++) { mrb_value v = ary_elt(ary2, i); r = mrb_funcall_argv(mrb, ary_elt(ary1, i), cmp, 1, &v); - if (mrb_type(r) != MRB_TT_FIXNUM || mrb_fixnum(r) != 0) return r; + if (!mrb_fixnum_p(r) || mrb_fixnum(r) != 0) return r; } } len = a1->len - a2->len; @@ -683,63 +678,144 @@ ary_subseq(mrb_state *mrb, struct RArray *a, mrb_int beg, mrb_int len) return mrb_obj_value(b); } +static mrb_int +aget_index(mrb_state *mrb, mrb_value index) +{ + if (mrb_fixnum_p(index)) { + return mrb_fixnum(index); + } + else { + mrb_int i; + + mrb_get_args(mrb, "i", &i); + return i; + } +} + +/* + * call-seq: + * ary[index] -> obj or nil + * ary[start, length] -> new_ary or nil + * ary[range] -> new_ary or nil + * ary.slice(index) -> obj or nil + * ary.slice(start, length) -> new_ary or nil + * ary.slice(range) -> new_ary or nil + * + * Element Reference --- Returns the element at +index+, or returns a + * subarray starting at the +start+ index and continuing for +length+ + * elements, or returns a subarray specified by +range+ of indices. + * + * Negative indices count backward from the end of the array (-1 is the last + * element). For +start+ and +range+ cases the starting index is just before + * an element. Additionally, an empty array is returned when the starting + * index for an element range is at the end of the array. + * + * Returns +nil+ if the index (or starting index) are out of range. + * + * a = [ "a", "b", "c", "d", "e" ] + * a[1] => "b" + * a[1,2] => ["b", "c"] + * a[1..-2] => ["b", "c", "d"] + * + */ + mrb_value mrb_ary_aget(mrb_state *mrb, mrb_value self) { struct RArray *a = mrb_ary_ptr(self); - mrb_int index, len; - mrb_value *argv; - int size; - - mrb_get_args(mrb, "i*", &index, &argv, &size); - switch(size) { - case 0: - return mrb_ary_ref(mrb, self, index); - - case 1: - if (mrb_type(argv[0]) != MRB_TT_FIXNUM) { - mrb_raise(mrb, E_TYPE_ERROR, "expected Fixnum"); + mrb_int i, len; + mrb_value index; + + if (mrb_get_args(mrb, "o|i", &index, &len) == 1) { + switch (mrb_type(index)) { + /* a[n..m] */ + case MRB_TT_RANGE: + if (mrb_range_beg_len(mrb, index, &i, &len, a->len)) { + return ary_subseq(mrb, a, i, len); + } + else { + return mrb_nil_value(); + } + case MRB_TT_FIXNUM: + return mrb_ary_ref(mrb, self, mrb_fixnum(index)); + default: + return mrb_ary_ref(mrb, self, aget_index(mrb, index)); } - if (index < 0) index += a->len; - if (index < 0 || a->len < (int)index) return mrb_nil_value(); - len = mrb_fixnum(argv[0]); - if (len < 0) return mrb_nil_value(); - if (a->len == (int)index) return mrb_ary_new(mrb); - if (len > a->len - index) len = a->len - index; - return ary_subseq(mrb, a, index, len); - - default: - mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments"); - break; } - return mrb_nil_value(); /* dummy to avoid warning : not reach here */ + i = aget_index(mrb, index); + if (i < 0) i += a->len; + if (i < 0 || a->len < (int)i) return mrb_nil_value(); + if (len < 0) return mrb_nil_value(); + if (a->len == (int)i) return mrb_ary_new(mrb); + if (len > a->len - i) len = a->len - i; + + return ary_subseq(mrb, a, i, len); } +/* + * call-seq: + * ary[index] = obj -> obj + * ary[start, length] = obj or other_ary or nil -> obj or other_ary or nil + * ary[range] = obj or other_ary or nil -> obj or other_ary or nil + * + * Element Assignment --- Sets the element at +index+, or replaces a subarray + * from the +start+ index for +length+ elements, or replaces a subarray + * specified by the +range+ of indices. + * + * If indices are greater than the current capacity of the array, the array + * grows automatically. Elements are inserted into the array at +start+ if + * +length+ is zero. + * + * Negative indices will count backward from the end of the array. For + * +start+ and +range+ cases the starting index is just before an element. + * + * An IndexError is raised if a negative index points past the beginning of + * the array. + * + * See also Array#push, and Array#unshift. + * + * a = Array.new + * a[4] = "4"; #=> [nil, nil, nil, nil, "4"] + * a[0, 3] = [ 'a', 'b', 'c' ] #=> ["a", "b", "c", nil, "4"] + * a[1..2] = [ 1, 2 ] #=> ["a", 1, 2, nil, "4"] + * a[0, 2] = "?" #=> ["?", 2, nil, "4"] + * a[0..2] = "A" #=> ["A", "4"] + * a[-1] = "Z" #=> ["A", "Z"] + * a[1..-1] = nil #=> ["A", nil] + * a[1..-1] = [] #=> ["A"] + * a[0, 0] = [ 1, 2 ] #=> [1, 2, "A"] + * a[3, 0] = "B" #=> [1, 2, "A", "B"] + */ + mrb_value mrb_ary_aset(mrb_state *mrb, mrb_value self) { - mrb_value *argv; - int argc; - - mrb_get_args(mrb, "*", &argv, &argc); - switch(argc) { - case 2: - if (!mrb_fixnum_p(argv[0])) { - /* Should we support Range object for 1st arg ? */ - mrb_raise(mrb, E_TYPE_ERROR, "expected Fixnum for 1st argument"); - } - mrb_ary_set(mrb, self, mrb_fixnum(argv[0]), argv[1]); - return argv[1]; - - case 3: - mrb_ary_splice(mrb, self, mrb_fixnum(argv[0]), mrb_fixnum(argv[1]), argv[2]); - return argv[2]; + mrb_value v1, v2, v3; + mrb_int i, len; - default: - mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments"); - return mrb_nil_value(); + if (mrb_get_args(mrb, "oo|o", &v1, &v2, &v3) == 2) { + switch (mrb_type(v1)) { + /* a[n..m] = v */ + case MRB_TT_RANGE: + if (mrb_range_beg_len(mrb, v1, &i, &len, RARRAY_LEN(self))) { + mrb_ary_splice(mrb, self, i, len, v2); + } + break; + /* a[n] = v */ + case MRB_TT_FIXNUM: + mrb_ary_set(mrb, self, mrb_fixnum(v1), v2); + break; + default: + mrb_ary_set(mrb, self, aget_index(mrb, v1), v2); + break; + } + return v2; } + + /* a[n,m] = v */ + mrb_ary_splice(mrb, self, aget_index(mrb, v1), aget_index(mrb, v2), v3); + return v3; } mrb_value @@ -854,6 +930,9 @@ mrb_ary_splat(mrb_state *mrb, mrb_value v) if (mrb_array_p(v)) { return v; } + if (mrb_respond_to(mrb, v, mrb_intern_lit(mrb, "to_a"))) { + return mrb_funcall(mrb, v, "to_a", 0); + } else { return mrb_ary_new_from_values(mrb, 1, &v); } @@ -916,7 +995,7 @@ inspect_ary(mrb_state *mrb, mrb_value ary, mrb_value list) /* check recursive */ for(i=0; i<RARRAY_LEN(list); i++) { if (mrb_obj_equal(mrb, ary, RARRAY_PTR(list)[i])) { - return mrb_str_new(mrb, "[...]", 5); + return mrb_str_new_lit(mrb, "[...]"); } } @@ -959,7 +1038,7 @@ inspect_ary(mrb_state *mrb, mrb_value ary, mrb_value list) static mrb_value mrb_ary_inspect(mrb_state *mrb, mrb_value ary) { - if (RARRAY_LEN(ary) == 0) return mrb_str_new(mrb, "[]", 2); + if (RARRAY_LEN(ary) == 0) return mrb_str_new_lit(mrb, "[]"); return inspect_ary(mrb, ary, mrb_ary_new(mrb)); } @@ -1070,7 +1149,7 @@ mrb_ary_equal(mrb_state *mrb, mrb_value ary1) 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_intern2(mrb, "to_ary", 6))) { + if (!mrb_respond_to(mrb, ary2, mrb_intern_lit(mrb, "to_ary"))) { return mrb_false_value(); } else { @@ -1120,12 +1199,11 @@ mrb_init_array(mrb_state *mrb) a = mrb->array_class = mrb_define_class(mrb, "Array", mrb->object_class); MRB_SET_INSTANCE_TT(a, MRB_TT_ARRAY); - mrb_include_module(mrb, a, mrb_class_get(mrb, "Enumerable")); mrb_define_class_method(mrb, a, "[]", mrb_ary_s_create, MRB_ARGS_ANY()); /* 15.2.12.4.1 */ - mrb_define_method(mrb, a, "*", mrb_ary_times, MRB_ARGS_REQ(1)); /* 15.2.12.5.1 */ - mrb_define_method(mrb, a, "+", mrb_ary_plus, MRB_ARGS_REQ(1)); /* 15.2.12.5.2 */ + mrb_define_method(mrb, a, "+", mrb_ary_plus, MRB_ARGS_REQ(1)); /* 15.2.12.5.1 */ + mrb_define_method(mrb, a, "*", mrb_ary_times, MRB_ARGS_REQ(1)); /* 15.2.12.5.2 */ mrb_define_method(mrb, a, "<<", mrb_ary_push_m, MRB_ARGS_REQ(1)); /* 15.2.12.5.3 */ mrb_define_method(mrb, a, "[]", mrb_ary_aget, MRB_ARGS_ANY()); /* 15.2.12.5.4 */ mrb_define_method(mrb, a, "[]=", mrb_ary_aset, MRB_ARGS_ANY()); /* 15.2.12.5.5 */ diff --git a/src/backtrace.c b/src/backtrace.c index 54927ec00..a221d5e5c 100644 --- a/src/backtrace.c +++ b/src/backtrace.c @@ -4,6 +4,7 @@ ** See Copyright Notice in mruby.h */ +#include <stdarg.h> #include "mruby.h" #include "mruby/variable.h" #include "mruby/proc.h" @@ -11,7 +12,6 @@ #include "mruby/string.h" #include "mruby/class.h" #include "mruby/debug.h" -#include <stdarg.h> typedef void (*output_stream_func)(mrb_state*, void*, int, const char*, ...); @@ -62,17 +62,16 @@ mrb_output_backtrace(mrb_state *mrb, struct RObject *exc, output_stream_func fun mrb_callinfo *ci; mrb_int ciidx; const char *filename, *method, *sep; - int i, line; + int i, lineno, tracehead = 1; - func(mrb, stream, 1, "trace:\n"); - ciidx = mrb_fixnum(mrb_obj_iv_get(mrb, exc, mrb_intern2(mrb, "ciidx", 5))); + ciidx = mrb_fixnum(mrb_obj_iv_get(mrb, exc, mrb_intern_lit(mrb, "ciidx"))); if (ciidx >= mrb->c->ciend - mrb->c->cibase) ciidx = 10; /* ciidx is broken... */ for (i = ciidx; i >= 0; i--) { ci = &mrb->c->cibase[i]; filename = NULL; - line = -1; + lineno = -1; if (MRB_PROC_CFUNC_P(ci->proc)) { continue; @@ -88,12 +87,12 @@ mrb_output_backtrace(mrb_state *mrb, struct RObject *exc, output_stream_func fun pc = mrb->c->cibase[i+1].pc - 1; } else { - pc = (mrb_code*)mrb_cptr(mrb_obj_iv_get(mrb, exc, mrb_intern2(mrb, "lastpc", 6))); + pc = (mrb_code*)mrb_cptr(mrb_obj_iv_get(mrb, exc, mrb_intern_lit(mrb, "lastpc"))); } filename = mrb_debug_get_filename(irep, pc - irep->iseq); - line = mrb_debug_get_line(irep, pc - irep->iseq); + lineno = mrb_debug_get_line(irep, pc - irep->iseq); } - if (line == -1) continue; + if (lineno == -1) continue; if (ci->target_class == ci->proc->target_class) sep = "."; else @@ -103,29 +102,40 @@ mrb_output_backtrace(mrb_state *mrb, struct RObject *exc, output_stream_func fun filename = "(unknown)"; } + if (tracehead) { + func(mrb, stream, 1, "trace:\n"); + tracehead = 0; + } method = mrb_sym2name(mrb, ci->mid); if (method) { const char *cn = mrb_class_name(mrb, ci->proc->target_class); if (cn) { func(mrb, stream, 1, "\t[%d] ", i); - func(mrb, stream, 0, "%s:%d:in %s%s%s", filename, line, cn, sep, method); + func(mrb, stream, 0, "%s:%d:in %s%s%s", filename, lineno, cn, sep, method); func(mrb, stream, 1, "\n"); } else { func(mrb, stream, 1, "\t[%d] ", i); - func(mrb, stream, 0, "%s:%d:in %s", filename, line, method); + func(mrb, stream, 0, "%s:%d:in %s", filename, lineno, method); func(mrb, stream, 1, "\n"); } } else { func(mrb, stream, 1, "\t[%d] ", i); - func(mrb, stream, 0, "%s:%d", filename, line); + func(mrb, stream, 0, "%s:%d", filename, lineno); func(mrb, stream, 1, "\n"); } } } +/* mrb_print_backtrace/mrb_get_backtrace: + + function to retrieve backtrace information from the exception. + note that if you call method after the exception, call stack will be + overwritten. So invoke these functions just after detecting exceptions. +*/ + void mrb_print_backtrace(mrb_state *mrb) { diff --git a/src/class.c b/src/class.c index a07cf17e4..58eaaab0e 100644 --- a/src/class.c +++ b/src/class.c @@ -4,9 +4,9 @@ ** See Copyright Notice in mruby.h */ -#include "mruby.h" -#include <stdarg.h> #include <ctype.h> +#include <stdarg.h> +#include "mruby.h" #include "mruby/array.h" #include "mruby/class.h" #include "mruby/numeric.h" @@ -46,14 +46,25 @@ mrb_gc_mark_mt_size(mrb_state *mrb, struct RClass *c) void mrb_gc_free_mt(mrb_state *mrb, struct RClass *c) { - kh_destroy(mt, c->mt); + kh_destroy(mt, mrb, c->mt); } -void -mrb_name_class(mrb_state *mrb, struct RClass *c, mrb_sym name) +static void +name_class(mrb_state *mrb, struct RClass *c, mrb_sym name) { mrb_obj_iv_set(mrb, (struct RObject*)c, - mrb_intern2(mrb, "__classid__", 11), mrb_symbol_value(name)); + mrb_intern_lit(mrb, "__classid__"), mrb_symbol_value(name)); +} + +static void +setup_class(mrb_state *mrb, struct RClass *outer, struct RClass *c, mrb_sym id) +{ + name_class(mrb, c, id); + mrb_obj_iv_set(mrb, (struct RObject*)outer, id, mrb_obj_value(c)); + if (outer != mrb->object_class) { + mrb_obj_iv_set(mrb, (struct RObject*)c, mrb_intern_lit(mrb, "__outer__"), + mrb_obj_value(outer)); + } } #define make_metaclass(mrb, c) prepare_singleton_class((mrb), (struct RBasic*)(c)) @@ -89,34 +100,25 @@ 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_intern2(mrb, "__attached__", 12), mrb_obj_value(o)); + mrb_obj_iv_set(mrb, (struct RObject*)sc, mrb_intern_lit(mrb, "__attached__"), mrb_obj_value(o)); } -struct RClass* -mrb_define_module_id(mrb_state *mrb, mrb_sym name) +static struct RClass * +class_from_sym(mrb_state *mrb, struct RClass *klass, mrb_sym id) { - struct RClass *m = mrb_module_new(mrb); - - mrb_obj_iv_set(mrb, (struct RObject*)mrb->object_class, - name, mrb_obj_value(m)); - mrb_name_class(mrb, m, name); + mrb_value c = mrb_const_get(mrb, mrb_obj_value(klass), id); - return m; + mrb_check_type(mrb, c, MRB_TT_CLASS); + return mrb_class_ptr(c); } -struct RClass* -mrb_define_module(mrb_state *mrb, const char *name) +static struct RClass * +module_from_sym(mrb_state *mrb, struct RClass *klass, mrb_sym id) { - return mrb_define_module_id(mrb, mrb_intern_cstr(mrb, name)); -} + mrb_value c = mrb_const_get(mrb, mrb_obj_value(klass), id); -static void -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_intern2(mrb, "__outer__", 9), outer); + mrb_check_type(mrb, c, MRB_TT_MODULE); + return mrb_class_ptr(c); } struct RClass* @@ -124,41 +126,84 @@ mrb_class_outer_module(mrb_state *mrb, struct RClass *c) { mrb_value outer; - outer = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern2(mrb, "__outer__", 9)); + outer = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern_lit(mrb, "__outer__")); if (mrb_nil_p(outer)) return 0; return mrb_class_ptr(outer); } +static struct RClass* +define_module(mrb_state *mrb, mrb_sym name, struct RClass *outer) +{ + struct RClass *m; + + if (mrb_const_defined_at(mrb, outer, name)) { + return module_from_sym(mrb, outer, name); + } + m = mrb_module_new(mrb); + setup_class(mrb, outer, m, name); + + return m; +} + +struct RClass* +mrb_define_module_id(mrb_state *mrb, mrb_sym name) +{ + return define_module(mrb, name, mrb->object_class); +} + +struct RClass* +mrb_define_module(mrb_state *mrb, const char *name) +{ + return define_module(mrb, mrb_intern_cstr(mrb, name), mrb->object_class); +} + struct RClass* mrb_vm_define_module(mrb_state *mrb, mrb_value outer, mrb_sym id) { - struct RClass *c; - mrb_value v; + return define_module(mrb, id, mrb_class_ptr(outer)); +} - if (mrb_const_defined(mrb, outer, id)) { - v = mrb_const_get(mrb, outer, id); - c = mrb_class_ptr(v); - } - else { - c = mrb_module_new(mrb); - setup_class(mrb, outer, c, id); - } +struct RClass * +mrb_define_module_under(mrb_state *mrb, struct RClass *outer, const char *name) +{ + mrb_sym id = mrb_intern_cstr(mrb, name); + struct RClass * c = define_module(mrb, id, outer); + + setup_class(mrb, outer, c, id); return c; } -struct RClass* -mrb_define_class_id(mrb_state *mrb, mrb_sym name, struct RClass *super) +static struct RClass* +define_class(mrb_state *mrb, mrb_sym name, struct RClass *super, struct RClass *outer) { - struct RClass *c = mrb_class_new(mrb, super); + struct RClass * c; - mrb_obj_iv_set(mrb, (struct RObject*)mrb->object_class, - name, mrb_obj_value(c)); - mrb_name_class(mrb, c, name); + if (mrb_const_defined_at(mrb, outer, name)) { + c = class_from_sym(mrb, outer, name); + if (super && mrb_class_real(c->super) != super) { + mrb_raisef(mrb, E_TYPE_ERROR, "superclass mismatch for Class %S (%S not %S)", + mrb_sym2str(mrb, name), + mrb_obj_value(c->super), mrb_obj_value(super)); + } + return c; + } + + c = mrb_class_new(mrb, super); + setup_class(mrb, outer, c, name); return c; } struct RClass* +mrb_define_class_id(mrb_state *mrb, mrb_sym name, struct RClass *super) +{ + if (!super) { + mrb_warn(mrb, "no super class for `%S', Object assumed", mrb_sym2str(mrb, name)); + } + return define_class(mrb, name, super, mrb->object_class); +} + +struct RClass* mrb_define_class(mrb_state *mrb, const char *name, struct RClass *super) { return mrb_define_class_id(mrb, mrb_intern_cstr(mrb, name), super); @@ -167,24 +212,8 @@ mrb_define_class(mrb_state *mrb, const char *name, struct RClass *super) struct RClass* mrb_vm_define_class(mrb_state *mrb, mrb_value outer, mrb_value super, mrb_sym id) { - struct RClass *c, *s; - - if (mrb_const_defined(mrb, outer, id)) { - mrb_value v = mrb_const_get(mrb, outer, id); - - mrb_check_type(mrb, v, MRB_TT_CLASS); - c = mrb_class_ptr(v); - if (!mrb_nil_p(super)) { - if (mrb_type(super) != MRB_TT_CLASS) { - mrb_raisef(mrb, E_TYPE_ERROR, "superclass must be a Class (%S given)", super); - } - - if (!c->super || mrb_class_ptr(super) != mrb_class_real(c->super)) { - mrb_raisef(mrb, E_TYPE_ERROR, "superclass mismatch for class %S", mrb_sym2str(mrb, id)); - } - } - return c; - } + struct RClass *s; + struct RClass *c; if (!mrb_nil_p(super)) { if (mrb_type(super) != MRB_TT_CLASS) { @@ -193,12 +222,18 @@ mrb_vm_define_class(mrb_state *mrb, mrb_value outer, mrb_value super, mrb_sym id s = mrb_class_ptr(super); } else { - s = mrb->object_class; + s = 0; } - - c = mrb_class_new(mrb, s); - setup_class(mrb, outer, c, id); - mrb_funcall(mrb, mrb_obj_value(s), "inherited", 1, mrb_obj_value(c)); + switch (mrb_type(outer)) { + case MRB_TT_CLASS: + case MRB_TT_MODULE: + break; + default: + mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a class/module", outer); + break; + } + c = define_class(mrb, id, s, mrb_class_ptr(outer)); + mrb_funcall(mrb, mrb_obj_value(mrb_class_real(c->super)), "inherited", 1, mrb_obj_value(c)); return c; } @@ -213,15 +248,10 @@ mrb_class_defined(mrb_state *mrb, const char *name) return mrb_const_defined(mrb, mrb_obj_value(mrb->object_class), mrb_symbol(sym)); } -static struct RClass * -class_from_sym(mrb_state *mrb, struct RClass *klass, mrb_sym id) +struct RClass * +mrb_class_get_under(mrb_state *mrb, struct RClass *outer, const char *name) { - mrb_value c = mrb_const_get(mrb, mrb_obj_value(klass), id); - - if (mrb_type(c) != MRB_TT_MODULE && mrb_type(c) != MRB_TT_CLASS) { - mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a class/module", mrb_sym2str(mrb, id)); - } - return mrb_class_ptr(c); + return class_from_sym(mrb, outer, mrb_intern_cstr(mrb, name)); } struct RClass * @@ -231,9 +261,15 @@ mrb_class_get(mrb_state *mrb, const char *name) } struct RClass * -mrb_class_get_under(mrb_state *mrb, struct RClass *outer, const char *name) +mrb_module_get_under(mrb_state *mrb, struct RClass *outer, const char *name) { - return class_from_sym(mrb, outer, mrb_intern_cstr(mrb, name)); + return module_from_sym(mrb, outer, mrb_intern_cstr(mrb, name)); +} + +struct RClass * +mrb_module_get(mrb_state *mrb, const char *name) +{ + return mrb_module_get_under(mrb, mrb->object_class, name); } /*! @@ -255,38 +291,17 @@ mrb_class_get_under(mrb_state *mrb, struct RClass *outer, const char *name) struct RClass * mrb_define_class_under(mrb_state *mrb, struct RClass *outer, const char *name, struct RClass *super) { - struct RClass * c; mrb_sym id = mrb_intern_cstr(mrb, name); - - if (mrb_const_defined_at(mrb, outer, id)) { - c = class_from_sym(mrb, outer, id); - if (mrb_class_real(c->super) != super) { - mrb_name_error(mrb, id, "%S is already defined", name); - } - return c; - } - if (!super) { - mrb_warn(mrb, "no super class for `%S::%S', Object assumed", outer, name); - } - c = mrb_class_new(mrb, super); - setup_class(mrb, mrb_obj_value(outer), c, id); - - return c; -} - -struct RClass * -mrb_define_module_under(mrb_state *mrb, struct RClass *outer, const char *name) -{ struct RClass * c; - mrb_sym id = mrb_intern_cstr(mrb, name); - if (mrb_const_defined_at(mrb, outer, id)) { - c = class_from_sym(mrb, outer, id); - return c; +#if 0 + if (!super) { + mrb_warn(mrb, "no super class for `%S::%S', Object assumed", + mrb_obj_value(outer), mrb_sym2str(mrb, id)); } - c = mrb_module_new(mrb); - setup_class(mrb, mrb_obj_value(outer), c, id); - +#endif + c = define_class(mrb, id, super, outer); + setup_class(mrb, outer, c, id); return c; } @@ -297,7 +312,7 @@ mrb_define_method_raw(mrb_state *mrb, struct RClass *c, mrb_sym mid, struct RPro khiter_t k; if (!h) h = c->mt = kh_init(mt, mrb); - k = kh_put(mt, h, mid); + k = kh_put(mt, mrb, h, mid); kh_value(h, k) = p; if (p) { mrb_field_write_barrier(mrb, (struct RBasic *)c, (struct RBasic *)p); @@ -330,7 +345,7 @@ mrb_define_method_vm(mrb_state *mrb, struct RClass *c, mrb_sym name, mrb_value b struct RProc *p; if (!h) h = c->mt = kh_init(mt, mrb); - k = kh_put(mt, h, name); + k = kh_put(mt, mrb, h, name); p = mrb_proc_ptr(body); kh_value(h, k) = p; if (p) { @@ -522,7 +537,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) s = mrb_str_ptr(ss); len = (mrb_int)strlen(s->ptr); if (len < s->len) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "String contains NUL"); + mrb_raise(mrb, E_ARGUMENT_ERROR, "string contains null byte"); } else if (len > s->len) { mrb_str_modify(mrb, s); @@ -866,7 +881,7 @@ mrb_mod_included_modules(mrb_state *mrb, mrb_value self) return result; } -mrb_value class_instance_method_list(mrb_state*, mrb_bool, struct RClass*, int); +mrb_value mrb_class_instance_method_list(mrb_state*, mrb_bool, struct RClass*, int); /* 15.2.2.4.33 */ /* @@ -902,7 +917,7 @@ mrb_mod_instance_methods(mrb_state *mrb, mrb_value mod) struct RClass *c = mrb_class_ptr(mod); mrb_bool recur = TRUE; mrb_get_args(mrb, "|b", &recur); - return class_instance_method_list(mrb, recur, c, 0); + return mrb_class_instance_method_list(mrb, recur, c, 0); } mrb_value mrb_yield_internal(mrb_state *mrb, mrb_value b, int argc, mrb_value *argv, mrb_value self, struct RClass *c); @@ -995,7 +1010,7 @@ mrb_method_search_vm(mrb_state *mrb, struct RClass **cp, mrb_sym mid) khash_t(mt) *h = c->mt; if (h) { - k = kh_get(mt, h, mid); + k = kh_get(mt, mrb, h, mid); if (k != kh_end(h)) { m = kh_value(h, k); if (!m) break; @@ -1061,7 +1076,7 @@ mrb_instance_new(mrb_state *mrb, mrb_value cv) obj = mrb_instance_alloc(mrb, cv); mrb_get_args(mrb, "*&", &argv, &argc, &blk); - mrb_funcall_with_block(mrb, obj, mrb_intern2(mrb, "initialize", 10), argc, argv, blk); + mrb_funcall_with_block(mrb, obj, mrb_intern_lit(mrb, "initialize"), argc, argv, blk); return obj; } @@ -1072,7 +1087,7 @@ mrb_obj_new(mrb_state *mrb, struct RClass *c, int argc, mrb_value *argv) mrb_value obj; obj = mrb_instance_alloc(mrb, mrb_obj_value(c)); - mrb_funcall_argv(mrb, obj, mrb_intern2(mrb, "initialize", 10), argc, argv); + mrb_funcall_argv(mrb, obj, mrb_intern_lit(mrb, "initialize"), argc, argv); return obj; } @@ -1163,7 +1178,7 @@ mrb_bob_missing(mrb_state *mrb, mrb_value mod) mrb_get_args(mrb, "n*", &name, &a, &alen); - if (mrb_respond_to(mrb,mod,mrb_intern2(mrb, "inspect",7))){ + if (mrb_respond_to(mrb,mod,mrb_intern_lit(mrb, "inspect"))){ inspect = mrb_funcall(mrb, mod, "inspect", 0); if (RSTRING_LEN(inspect) > 64) { inspect = mrb_any_to_s(mrb, mod); @@ -1180,7 +1195,7 @@ mrb_bob_missing(mrb_state *mrb, mrb_value mod) } mrb_bool -mrb_obj_respond_to(struct RClass* c, mrb_sym mid) +mrb_obj_respond_to(mrb_state *mrb, struct RClass* c, mrb_sym mid) { khiter_t k; @@ -1188,7 +1203,7 @@ mrb_obj_respond_to(struct RClass* c, mrb_sym mid) khash_t(mt) *h = c->mt; if (h) { - k = kh_get(mt, h, mid); + k = kh_get(mt, mrb, h, mid); if (k != kh_end(h)) { if (kh_value(h, k)) { return TRUE; /* method exists */ @@ -1206,7 +1221,7 @@ mrb_obj_respond_to(struct RClass* c, mrb_sym mid) mrb_bool mrb_respond_to(mrb_state *mrb, mrb_value obj, mrb_sym mid) { - return mrb_obj_respond_to(mrb_class(mrb, obj), mid); + return mrb_obj_respond_to(mrb, mrb_class(mrb, obj), mid); } mrb_value @@ -1215,7 +1230,7 @@ mrb_class_path(mrb_state *mrb, struct RClass *c) mrb_value path; const char *name; size_t len; - mrb_sym classpath = mrb_intern2(mrb, "__classpath__", 13); + mrb_sym classpath = mrb_intern_lit(mrb, "__classpath__"); path = mrb_obj_iv_get(mrb, (struct RObject*)c, classpath); if (mrb_nil_p(path)) { @@ -1226,7 +1241,7 @@ mrb_class_path(mrb_state *mrb, struct RClass *c) } else if (outer && outer != mrb->object_class) { mrb_value base = mrb_class_path(mrb, outer); - path = mrb_str_plus(mrb, base, mrb_str_new(mrb, "::", 2)); + path = mrb_str_plus(mrb, base, mrb_str_new_lit(mrb, "::")); name = mrb_sym2name_len(mrb, sym, &len); mrb_str_concat(mrb, path, mrb_str_new(mrb, name, len)); } @@ -1253,7 +1268,7 @@ mrb_class_name(mrb_state *mrb, struct RClass* c) { mrb_value path = mrb_class_path(mrb, c); if (mrb_nil_p(path)) { - path = mrb_str_new(mrb, "#<Class:", 8); + path = mrb_str_new_lit(mrb, "#<Class:"); mrb_str_concat(mrb, path, mrb_ptr_to_str(mrb, c)); mrb_str_cat(mrb, path, ">", 1); } @@ -1376,9 +1391,9 @@ mrb_mod_to_s(mrb_state *mrb, mrb_value klass) mrb_value str; if (mrb_type(klass) == MRB_TT_SCLASS) { - mrb_value v = mrb_iv_get(mrb, klass, mrb_intern2(mrb, "__attached__", 12)); + mrb_value v = mrb_iv_get(mrb, klass, mrb_intern_lit(mrb, "__attached__")); - str = mrb_str_new(mrb, "#<Class:", 8); + str = mrb_str_new_lit(mrb, "#<Class:"); switch (mrb_type(v)) { case MRB_TT_CLASS: @@ -1442,7 +1457,7 @@ undef_method(mrb_state *mrb, struct RClass *c, mrb_sym a) { mrb_value m; - if (!mrb_obj_respond_to(c, a)) { + if (!mrb_obj_respond_to(mrb, c, a)) { mrb_name_error(mrb, a, "undefined method '%S' for class '%S'", mrb_sym2str(mrb, a), mrb_obj_value(c)); } else { @@ -1713,7 +1728,7 @@ mrb_mod_method_defined(mrb_state *mrb, mrb_value mod) id = get_sym_or_str_arg(mrb); if (mrb_symbol_p(id)) { - method_defined_p = mrb_obj_respond_to(mrb_class_ptr(mod), mrb_symbol(id)); + method_defined_p = mrb_obj_respond_to(mrb, mrb_class_ptr(mod), mrb_symbol(id)); } else { mrb_value sym = mrb_check_intern_str(mrb, id); @@ -1721,7 +1736,7 @@ mrb_mod_method_defined(mrb_state *mrb, mrb_value mod) method_defined_p = FALSE; } else { - method_defined_p = mrb_obj_respond_to(mrb_class_ptr(mod), mrb_symbol(sym)); + method_defined_p = mrb_obj_respond_to(mrb, mrb_class_ptr(mod), mrb_symbol(sym)); } } return mrb_bool_value(method_defined_p); @@ -1735,9 +1750,9 @@ remove_method(mrb_state *mrb, mrb_value mod, mrb_sym mid) khiter_t k; if (h) { - k = kh_get(mt, h, mid); + k = kh_get(mt, mrb, h, mid); if (k != kh_end(h)) { - kh_del(mt, h, k); + kh_del(mt, mrb, h, k); return; } } @@ -1912,10 +1927,10 @@ mrb_init_class(mrb_state *mrb) mrb_define_const(mrb, obj, "Class", mrb_obj_value(cls)); /* name each classes */ - mrb_name_class(mrb, bob, mrb_intern2(mrb, "BasicObject", 11)); - mrb_name_class(mrb, obj, mrb_intern2(mrb, "Object", 6)); - mrb_name_class(mrb, mod, mrb_intern2(mrb, "Module", 6)); - mrb_name_class(mrb, cls, mrb_intern2(mrb, "Class", 5)); + name_class(mrb, bob, mrb_intern_lit(mrb, "BasicObject")); + name_class(mrb, obj, mrb_intern_lit(mrb, "Object")); + name_class(mrb, mod, mrb_intern_lit(mrb, "Module")); + name_class(mrb, cls, mrb_intern_lit(mrb, "Class")); MRB_SET_INSTANCE_TT(cls, MRB_TT_CLASS); mrb_define_method(mrb, bob, "initialize", mrb_bob_init, MRB_ARGS_NONE()); diff --git a/src/codegen.c b/src/codegen.c index 2072d278a..11273bf7e 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -26,7 +26,7 @@ enum looptype { LOOP_FOR, LOOP_BEGIN, LOOP_RESCUE, -} type; +}; struct loopinfo { enum looptype type; @@ -61,8 +61,8 @@ typedef struct scope { mrb_irep *irep; size_t pcapa; - int scapa; - int rcapa; + size_t scapa; + size_t rcapa; int nlocals; int nregs; @@ -89,10 +89,10 @@ codegen_error(codegen_scope *s, const char *message) { if (!s) return; while (s->prev) { + codegen_scope *tmp = s->prev; mrb_pool_close(s->mpool); - s = s->prev; + s = tmp; } - mrb_pool_close(s->mpool); #ifdef ENABLE_STDIO if (s->filename && s->lineno) { fprintf(stderr, "codegen error:%s:%d: %s\n", s->filename, s->lineno, message); @@ -113,19 +113,19 @@ codegen_palloc(codegen_scope *s, size_t len) return p; } -void* +static void* codegen_malloc(codegen_scope *s, size_t len) { - void *p = mrb_malloc(s->mrb, len); + void *p = mrb_malloc_simple(s->mrb, len); if (!p) codegen_error(s, "mrb_malloc"); return p; } -void* +static void* codegen_realloc(codegen_scope *s, void *p, size_t len) { - p = mrb_realloc(s->mrb, p, len); + p = mrb_realloc_simple(s->mrb, p, len); if (!p && len > 0) codegen_error(s, "mrb_realloc"); return p; @@ -316,8 +316,8 @@ genop_peep(codegen_scope *s, mrb_code i, int val) if (c0 == OP_STRING) { int i = GETARG_Bx(i0); - if (s->irep->pool[i].type == IREP_TT_STRING && - s->irep->pool[i].value.s->len == 0) { + if (mrb_type(s->irep->pool[i]) == MRB_TT_STRING && + RSTRING_LEN(s->irep->pool[i]) == 0) { s->pc--; return; } @@ -397,7 +397,7 @@ static inline int new_lit(codegen_scope *s, mrb_value val) { size_t i; - struct irep_pool *pv; + mrb_value *pv; switch (mrb_type(val)) { case MRB_TT_STRING: @@ -405,24 +405,24 @@ new_lit(codegen_scope *s, mrb_value val) mrb_int len; pv = &s->irep->pool[i]; - if (pv->type != IREP_TT_STRING) continue; - if ((len = pv->value.s->len) != RSTRING_LEN(val)) continue; - if (memcmp(pv->value.s->buf, RSTRING_PTR(val), len) == 0) + if (mrb_type(*pv) != MRB_TT_STRING) continue; + if ((len = RSTRING_LEN(*pv)) != RSTRING_LEN(val)) continue; + if (memcmp(RSTRING_PTR(*pv), RSTRING_PTR(val), len) == 0) return i; } break; case MRB_TT_FLOAT: for (i=0; i<s->irep->plen; i++) { pv = &s->irep->pool[i]; - if (pv->type != IREP_TT_FLOAT) continue; - if (pv->value.f == mrb_float(val)) return i; + if (mrb_type(*pv) != MRB_TT_FLOAT) continue; + if (mrb_float(*pv) == mrb_float(val)) return i; } break; case MRB_TT_FIXNUM: for (i=0; i<s->irep->plen; i++) { pv = &s->irep->pool[i]; - if (pv->type != IREP_TT_FIXNUM) continue; - if (pv->value.i == mrb_fixnum(val)) return i; + if (!mrb_fixnum_p(*pv)) continue; + if (mrb_fixnum(*pv) == mrb_fixnum(val)) return i; } break; default: @@ -432,7 +432,7 @@ new_lit(codegen_scope *s, mrb_value val) if (s->irep->plen == s->pcapa) { s->pcapa *= 2; - s->irep->pool = (struct irep_pool*)codegen_realloc(s, s->irep->pool, sizeof(struct irep_pool)*s->pcapa); + s->irep->pool = (mrb_value *)codegen_realloc(s, s->irep->pool, sizeof(mrb_value)*s->pcapa); } pv = &s->irep->pool[s->irep->plen]; @@ -440,19 +440,18 @@ new_lit(codegen_scope *s, mrb_value val) switch (mrb_type(val)) { case MRB_TT_STRING: - pv->type = IREP_TT_STRING; - pv->value.s = (struct irep_pool_string*)codegen_malloc(s, sizeof(struct irep_pool_string) + RSTRING_LEN(val)); - pv->value.s->len = RSTRING_LEN(val); - memcpy(pv->value.s->buf, RSTRING_PTR(val), RSTRING_LEN(val)); + *pv = mrb_str_pool(s->mrb, val); break; + case MRB_TT_FLOAT: - pv->type = IREP_TT_FLOAT; - pv->value.f = mrb_float(val); +#ifdef MRB_WORD_BOXING + *pv = mrb_float_pool(s->mrb, mrb_float(val)); break; +#endif case MRB_TT_FIXNUM: - pv->type = IREP_TT_FIXNUM; - pv->value.i = mrb_fixnum(val); + *pv = val; break; + default: /* should not happen */ break; @@ -566,7 +565,7 @@ for_body(codegen_scope *s, node *tree) s = prev; genop(s, MKOP_Abc(OP_LAMBDA, cursp(), s->irep->rlen-1, OP_L_BLOCK)); pop(); - idx = new_msym(s, mrb_intern2(s->mrb, "each", 4)); + idx = new_msym(s, mrb_intern_lit(s->mrb, "each")); genop(s, MKOP_ABC(OP_SENDB, cursp(), idx, 0)); } @@ -658,7 +657,7 @@ lambda_body(codegen_scope *s, node *tree, int blk) } static int -scope_body(codegen_scope *s, node *tree) +scope_body(codegen_scope *s, node *tree, int val) { codegen_scope *scope = scope_new(s->mrb, s, tree->car); @@ -666,15 +665,16 @@ scope_body(codegen_scope *s, node *tree) if (!s->iseq) { genop(scope, MKOP_A(OP_STOP, 0)); } + else if (!val) { + genop(scope, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL)); + } else { if (scope->nregs == 0) { genop(scope, MKOP_A(OP_LOADNIL, 0)); genop(scope, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL)); } else { - pop(); - genop_peep(scope, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL); - push(); + genop_peep(scope, MKOP_AB(OP_RETURN, scope->sp-1, OP_R_NORMAL), NOVAL); } } scope_finish(scope); @@ -708,7 +708,7 @@ attrsym(codegen_scope *s, mrb_sym a) name2[len] = '='; name2[len+1] = '\0'; - return mrb_intern2(s->mrb, name2, len+1); + return mrb_intern(s->mrb, name2, len+1); } static int @@ -977,11 +977,11 @@ 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)); + genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "intern")), 0)); push(); } static void -gen_literal_array(codegen_scope *s, node *tree, int sym, int val) +gen_literal_array(codegen_scope *s, node *tree, mrb_bool sym, int val) { if (val) { int i = 0, j = 0; @@ -1069,7 +1069,7 @@ readint_float(codegen_scope *s, const char *p, int base) } static mrb_int -readint_mrb_int(codegen_scope *s, const char *p, int base, int neg, int *overflow) +readint_mrb_int(codegen_scope *s, const char *p, int base, mrb_bool neg, mrb_bool *overflow) { const char *e = p + strlen(p); mrb_int result = 0; @@ -1177,12 +1177,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_intern2(s->mrb, "StandardError", 13)))); + genop(s, MKOP_ABx(OP_GETCONST, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "StandardError")))); push(); } genop(s, MKOP_AB(OP_MOVE, cursp(), exc)); pop(); - genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern2(s->mrb, "===", 3)), 1)); + genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "===")), 1)); tmp = new_label(s); genop(s, MKOP_AsBx(OP_JMPIF, cursp(), pos2)); pos2 = tmp; @@ -1236,7 +1236,7 @@ codegen(codegen_scope *s, node *tree, int val) genop(s, MKOP_Bx(OP_EPUSH, 0)); s->ensure_level++; codegen(s, tree->car, val); - idx = scope_body(s, tree->cdr); + idx = scope_body(s, tree->cdr, NOVAL); s->iseq[epush] = MKOP_Bx(OP_EPUSH, idx); s->ensure_level--; genop_peep(s, MKOP_A(OP_EPOP, 1), NOVAL); @@ -1386,7 +1386,12 @@ 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_intern2(s->mrb, "===", 3)), 1)); + if ((intptr_t)n->car->car == NODE_SPLAT) { + genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "__case_eqq")), 1)); + } + else { + genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "===")), 1)); + } } else { pop(); @@ -1410,15 +1415,21 @@ codegen(codegen_scope *s, node *tree, int val) tree = tree->cdr; } if (val) { + int pos = cursp(); genop(s, MKOP_A(OP_LOADNIL, cursp())); + if (pos3) dispatch_linked(s, pos3); + pop(); + genop(s, MKOP_AB(OP_MOVE, cursp(), pos)); push(); } - if (pos3) dispatch_linked(s, pos3); + else if (pos3) { + dispatch_linked(s, pos3); + } } break; case NODE_SCOPE: - scope_body(s, tree); + scope_body(s, tree, NOVAL); break; case NODE_FCALL: @@ -1726,7 +1737,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_intern2(s->mrb, "call", 4)), n)); + genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "call")), n)); if (val) push(); } break; @@ -1915,7 +1926,7 @@ codegen(codegen_scope *s, node *tree, int val) int base = (intptr_t)tree->cdr->car; mrb_int i; mrb_code co; - int overflow; + mrb_bool overflow; i = readint_mrb_int(s, p, base, FALSE, &overflow); if (overflow) { @@ -1971,7 +1982,7 @@ codegen(codegen_scope *s, node *tree, int val) int base = (intptr_t)tree->cdr->car; mrb_int i; mrb_code co; - int overflow; + mrb_bool overflow; i = readint_mrb_int(s, p, base, TRUE, &overflow); if (overflow) { @@ -1996,7 +2007,7 @@ codegen(codegen_scope *s, node *tree, int val) default: { - int sym = new_msym(s, mrb_intern2(s->mrb, "-", 1)); + int sym = new_msym(s, mrb_intern_lit(s->mrb, "-")); genop(s, MKOP_ABx(OP_LOADI, cursp(), 0)); push(); @@ -2064,7 +2075,7 @@ codegen(codegen_scope *s, node *tree, int 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 sym = new_sym(s, mrb_intern_lit(s->mrb, "Kernel")); int off = new_lit(s, mrb_str_new(s->mrb, p, len)); genop(s, MKOP_A(OP_OCLASS, cursp())); @@ -2072,7 +2083,7 @@ codegen(codegen_scope *s, node *tree, int val) push(); genop(s, MKOP_ABx(OP_STRING, cursp(), off)); pop(); - sym = new_sym(s, mrb_intern2(s->mrb, "`", 1)); + sym = new_sym(s, mrb_intern_lit(s->mrb, "`")); genop(s, MKOP_ABC(OP_SEND, cursp(), sym, 1)); mrb_gc_arena_restore(s->mrb, ai); push(); @@ -2084,7 +2095,7 @@ codegen(codegen_scope *s, node *tree, int val) char *p1 = (char*)tree->car; char *p2 = (char*)tree->cdr; int ai = mrb_gc_arena_save(s->mrb); - int sym = new_sym(s, mrb_intern2(s->mrb, REGEXP_CLASS, REGEXP_CLASS_CSTR_LEN)); + int sym = new_sym(s, mrb_intern_lit(s->mrb, REGEXP_CLASS)); int off = new_lit(s, mrb_str_new(s->mrb, p1, strlen(p1))); int argc = 1; @@ -2100,7 +2111,7 @@ codegen(codegen_scope *s, node *tree, int val) pop(); } pop(); - sym = new_sym(s, mrb_intern2(s->mrb, "compile", 7)); + sym = new_sym(s, mrb_intern_lit(s->mrb, "compile")); genop(s, MKOP_ABC(OP_SEND, cursp(), sym, argc)); mrb_gc_arena_restore(s->mrb, ai); push(); @@ -2111,7 +2122,7 @@ codegen(codegen_scope *s, node *tree, int val) if (val) { node *n = tree->car; int ai = mrb_gc_arena_save(s->mrb); - int sym = new_sym(s, mrb_intern2(s->mrb, REGEXP_CLASS, REGEXP_CLASS_CSTR_LEN)); + int sym = new_sym(s, mrb_intern_lit(s->mrb, REGEXP_CLASS)); int argc = 1; int off; char *p; @@ -2148,7 +2159,7 @@ codegen(codegen_scope *s, node *tree, int val) pop(); } pop(); - sym = new_sym(s, mrb_intern2(s->mrb, "compile", 7)); + sym = new_sym(s, mrb_intern_lit(s->mrb, "compile")); genop(s, MKOP_ABC(OP_SEND, cursp(), sym, argc)); mrb_gc_arena_restore(s->mrb, ai); push(); @@ -2213,7 +2224,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_intern2(s->mrb, "alias_method", 12)); + int c = new_msym(s, mrb_intern_lit(s->mrb,"alias_method")); genop(s, MKOP_A(OP_TCLASS, cursp())); push(); @@ -2232,7 +2243,7 @@ codegen(codegen_scope *s, node *tree, int val) case NODE_UNDEF: { - int undef = new_msym(s, mrb_intern2(s->mrb, "undef_method", 12)); + int undef = new_msym(s, mrb_intern_lit(s->mrb, "undef_method")); int num = 0; node *t = tree; @@ -2278,7 +2289,7 @@ codegen(codegen_scope *s, node *tree, int val) pop(); pop(); idx = new_msym(s, sym(tree->car->cdr)); genop(s, MKOP_AB(OP_CLASS, cursp(), idx)); - idx = scope_body(s, tree->cdr->cdr->car); + idx = scope_body(s, tree->cdr->cdr->car, val); genop(s, MKOP_ABx(OP_EXEC, cursp(), idx)); if (val) { push(); @@ -2304,7 +2315,7 @@ codegen(codegen_scope *s, node *tree, int val) pop(); idx = new_msym(s, sym(tree->car->cdr)); genop(s, MKOP_AB(OP_MODULE, cursp(), idx)); - idx = scope_body(s, tree->cdr->car); + idx = scope_body(s, tree->cdr->car, val); genop(s, MKOP_ABx(OP_EXEC, cursp(), idx)); if (val) { push(); @@ -2319,7 +2330,7 @@ codegen(codegen_scope *s, node *tree, int val) codegen(s, tree->car, VAL); pop(); genop(s, MKOP_AB(OP_SCLASS, cursp(), cursp())); - idx = scope_body(s, tree->cdr->car); + idx = scope_body(s, tree->cdr->car, val); genop(s, MKOP_ABx(OP_EXEC, cursp(), idx)); if (val) { push(); @@ -2412,13 +2423,14 @@ scope_new(mrb_state *mrb, codegen_scope *prev, node *lv) p->icapa = 1024; p->iseq = (mrb_code*)mrb_malloc(mrb, sizeof(mrb_code)*p->icapa); + p->irep->iseq = p->iseq; p->pcapa = 32; - p->irep->pool = (struct irep_pool*)mrb_malloc(mrb, sizeof(struct irep_pool)*p->pcapa); + p->irep->pool = (mrb_value*)mrb_malloc(mrb, sizeof(mrb_value)*p->pcapa); p->irep->plen = 0; p->scapa = 256; - p->irep->syms = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym)*256); + p->irep->syms = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym)*p->scapa); p->irep->slen = 0; p->lv = lv; @@ -2467,7 +2479,7 @@ scope_finish(codegen_scope *s) irep->lines = 0; } } - irep->pool = (struct irep_pool*)codegen_realloc(s, irep->pool, sizeof(struct irep_pool)*irep->plen); + irep->pool = (mrb_value*)codegen_realloc(s, irep->pool, sizeof(mrb_value)*irep->plen); irep->syms = (mrb_sym*)codegen_realloc(s, irep->syms, sizeof(mrb_sym)*irep->slen); irep->reps = (mrb_irep**)codegen_realloc(s, irep->reps, sizeof(mrb_irep*)*irep->rlen); if (s->filename) { @@ -2722,7 +2734,7 @@ codedump(mrb_state *mrb, mrb_irep *irep) break; case OP_LAMBDA: - printf("OP_LAMBDA\tR%d\tI(%+d)\t%d\n", GETARG_A(c), GETARG_b(c), GETARG_c(c)); + printf("OP_LAMBDA\tR%d\tI(%+d)\t%d\n", GETARG_A(c), GETARG_b(c)+1, GETARG_c(c)); break; case OP_RANGE: printf("OP_RANGE\tR%d\tR%d\t%d\n", GETARG_A(c), GETARG_B(c), GETARG_C(c)); @@ -2809,8 +2821,8 @@ codedump(mrb_state *mrb, mrb_irep *irep) break; case OP_STRING: { - struct irep_pool *pv = &irep->pool[GETARG_Bx(c)]; - mrb_value s = mrb_str_dump(mrb, mrb_str_new(mrb, pv->value.s->buf, pv->value.s->len)); + mrb_value v = irep->pool[GETARG_Bx(c)]; + mrb_value s = mrb_str_dump(mrb, mrb_str_new(mrb, RSTRING_PTR(v), RSTRING_LEN(v))); printf("OP_STRING\tR%d\t%s\n", GETARG_A(c), RSTRING_PTR(s)); } break; @@ -2833,7 +2845,7 @@ codedump(mrb_state *mrb, mrb_irep *irep) mrb_sym2name(mrb, irep->syms[GETARG_B(c)])); break; case OP_EXEC: - printf("OP_EXEC\tR%d\tI(%+d)\n", GETARG_A(c), GETARG_Bx(c)); + printf("OP_EXEC\tR%d\tI(%+d)\n", GETARG_A(c), GETARG_Bx(c)+1); break; case OP_SCLASS: printf("OP_SCLASS\tR%d\tR%d\n", GETARG_A(c), GETARG_B(c)); @@ -2842,10 +2854,14 @@ codedump(mrb_state *mrb, mrb_irep *irep) printf("OP_TCLASS\tR%d\n", GETARG_A(c)); break; case OP_ERR: - printf("OP_ERR\tL(%d)\n", GETARG_Bx(c)); + { + mrb_value v = irep->pool[GETARG_Bx(c)]; + mrb_value s = mrb_str_dump(mrb, mrb_str_new(mrb, RSTRING_PTR(v), RSTRING_LEN(v))); + printf("OP_ERR\t%s\n", RSTRING_PTR(s)); + } break; case OP_EPUSH: - printf("OP_EPUSH\t:I(%+d)\n", GETARG_Bx(c)); + printf("OP_EPUSH\t:I(%+d)\n", GETARG_Bx(c)+1); break; case OP_ONERR: printf("OP_ONERR\t%03d\n", i+GETARG_sBx(c)); @@ -2886,9 +2902,9 @@ codedump_recur(mrb_state *mrb, mrb_irep *irep) } void -codedump_all(mrb_state *mrb, struct RProc *proc) +mrb_codedump_all(mrb_state *mrb, struct RProc *proc) { - return codedump_recur(mrb, proc->body.irep); + codedump_recur(mrb, proc->body.irep); } struct RProc* @@ -2913,6 +2929,11 @@ mrb_generate_code(mrb_state *mrb, parser_state *p) return proc; } else { + if (scope->filename == scope->irep->filename) { + scope->irep->filename = NULL; + } + mrb_irep_decref(mrb, scope->irep); + mrb_pool_close(scope->mpool); return NULL; } } diff --git a/src/debug.c b/src/debug.c index 8e4311f6c..075af5c24 100644 --- a/src/debug.c +++ b/src/debug.c @@ -154,7 +154,7 @@ mrb_debug_info_append_file(mrb_state *mrb, mrb_irep *irep, info->pc_count = end_pos; fn_len = strlen(irep->filename); - ret->filename_sym = mrb_intern2(mrb, irep->filename, fn_len); + ret->filename_sym = mrb_intern(mrb, irep->filename, fn_len); len = 0; ret->filename = mrb_sym2name_len(mrb, ret->filename_sym, &len); diff --git a/src/dump.c b/src/dump.c index 77555f8ee..37cafb134 100644 --- a/src/dump.c +++ b/src/dump.c @@ -4,10 +4,9 @@ ** See Copyright Notice in mruby.h */ +#include <ctype.h> #include <string.h> #include "mruby/dump.h" -#include <ctype.h> - #include "mruby/string.h" #include "mruby/irep.h" #include "mruby/numeric.h" @@ -79,19 +78,19 @@ get_pool_block_size(mrb_state *mrb, mrb_irep *irep) for (pool_no = 0; pool_no < irep->plen; pool_no++) { int ai = mrb_gc_arena_save(mrb); - switch (irep->pool[pool_no].type) { - case IREP_TT_FIXNUM: - str = mrb_fixnum_to_str(mrb, mrb_fixnum_value(irep->pool[pool_no].value.i), 10); + switch (mrb_type(irep->pool[pool_no])) { + case MRB_TT_FIXNUM: + str = mrb_fixnum_to_str(mrb, irep->pool[pool_no], 10); size += RSTRING_LEN(str); break; - case IREP_TT_FLOAT: - len = mrb_float_to_str(buf, irep->pool[pool_no].value.f); + case MRB_TT_FLOAT: + len = mrb_float_to_str(buf, mrb_float(irep->pool[pool_no])); size += len; break; - case IREP_TT_STRING: - size += irep->pool[pool_no].value.s->len; + case MRB_TT_STRING: + size += RSTRING_LEN(irep->pool[pool_no]); break; default: @@ -118,23 +117,24 @@ write_pool_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf) for (pool_no = 0; pool_no < irep->plen; pool_no++) { int ai = mrb_gc_arena_save(mrb); - cur += uint8_to_bin(irep->pool[pool_no].type, cur); /* data type */ - - switch (irep->pool[pool_no].type) { - case IREP_TT_FIXNUM: - str = mrb_fixnum_to_str(mrb, mrb_fixnum_value(irep->pool[pool_no].value.i), 10); + switch (mrb_type(irep->pool[pool_no])) { + case MRB_TT_FIXNUM: + cur += uint8_to_bin(IREP_TT_FIXNUM, cur); /* data type */ + str = mrb_fixnum_to_str(mrb, irep->pool[pool_no], 10); char_ptr = RSTRING_PTR(str); len = RSTRING_LEN(str); break; - case IREP_TT_FLOAT: - len = mrb_float_to_str(char_buf, irep->pool[pool_no].value.f); + case MRB_TT_FLOAT: + cur += uint8_to_bin(IREP_TT_FLOAT, cur); /* data type */ + len = mrb_float_to_str(char_buf, mrb_float(irep->pool[pool_no])); char_ptr = &char_buf[0]; break; - case IREP_TT_STRING: - char_ptr = irep->pool[pool_no].value.s->buf; - len = irep->pool[pool_no].value.s->len; + case MRB_TT_STRING: + cur += uint8_to_bin(IREP_TT_STRING, cur); /* data type */ + char_ptr = RSTRING_PTR(irep->pool[pool_no]); + len = RSTRING_LEN(irep->pool[pool_no]); break; default: @@ -384,7 +384,7 @@ write_lineno_record(mrb_state *mrb, mrb_irep *irep, uint8_t* bin) bin += rlen; size += rlen; for (i=0; i<irep->rlen; i++) { - rlen = write_lineno_record_1(mrb, irep, bin); + rlen = write_lineno_record(mrb, irep, bin); bin += rlen; size += rlen; } @@ -405,7 +405,6 @@ write_section_lineno(mrb_state *mrb, mrb_irep *irep, uint8_t *bin) section_size += sizeof(struct rite_section_lineno_header); rlen = write_lineno_record(mrb, irep, cur); - cur += rlen; section_size += rlen; write_section_lineno_header(mrb, section_size, bin); @@ -483,7 +482,7 @@ get_filename_table_size(mrb_state *mrb, mrb_irep *irep, mrb_sym **fp, size_t *lp if (find_filename_index(filenames, *lp, file->filename_sym) == -1) { // register filename *lp += 1; - *fp = filenames = (mrb_sym *)mrb_realloc(mrb, filenames, sizeof(mrb_sym*) * (*lp)); + *fp = filenames = (mrb_sym *)mrb_realloc(mrb, filenames, sizeof(mrb_sym) * (*lp)); filenames[*lp - 1] = file->filename_sym; // filename @@ -492,13 +491,14 @@ get_filename_table_size(mrb_state *mrb, mrb_irep *irep, mrb_sym **fp, size_t *lp } for (i=0; i<irep->rlen; i++) { size += get_filename_table_size(mrb, irep->reps[i], fp, lp); + filenames = *fp; } } return size; } static int -write_debug_record(mrb_state *mrb, mrb_irep *irep, uint8_t *bin, mrb_sym const* filenames, size_t filenames_len) +write_debug_record_1(mrb_state *mrb, mrb_irep *irep, uint8_t *bin, mrb_sym const* filenames, size_t filenames_len) { uint8_t *cur; uint32_t f_idx; @@ -546,12 +546,28 @@ write_debug_record(mrb_state *mrb, mrb_irep *irep, uint8_t *bin, mrb_sym const* ret = cur - bin; uint32_to_bin(ret, bin); - mrb_assert((cur - bin) == (int)get_debug_record_size(mrb, irep)); - return ret; } static int +write_debug_record(mrb_state *mrb, mrb_irep *irep, uint8_t *bin, mrb_sym const* filenames, size_t filenames_len) +{ + uint32_t size, len; + size_t irep_no; + + size = len = write_debug_record_1(mrb, irep, bin, filenames, filenames_len); + bin += len; + for (irep_no = 0; irep_no < irep->rlen; irep_no++) { + len = write_debug_record(mrb, irep->reps[irep_no], bin, filenames, filenames_len); + bin += len; + size += len; + } + + mrb_assert(size == (int)get_debug_record_size(mrb, irep)); + return size; +} + +static int write_filename_table(mrb_state *mrb, mrb_irep *irep, uint8_t **cp, mrb_sym **fp, size_t *lp) { uint8_t *cur = *cp; @@ -578,6 +594,9 @@ write_filename_table(mrb_state *mrb, mrb_irep *irep, uint8_t **cp, mrb_sym **fp, size += sizeof(uint16_t) + fn_len; } + for (file_i=0; file_i<irep->rlen; file_i++) { + size += write_filename_table(mrb, irep->reps[file_i], &cur, fp, lp); + } *cp = cur; return size; } @@ -589,7 +608,7 @@ write_section_debug(mrb_state *mrb, mrb_irep *irep, uint8_t *cur) const uint8_t *bin = cur; struct rite_section_debug_header *header; mrb_sym *filenames; - size_t filenames_len = 0, i; + size_t filenames_len = 0; uint8_t *filenames_len_out; uint32_t dlen; @@ -602,25 +621,16 @@ write_section_debug(mrb_state *mrb, mrb_irep *irep, uint8_t *cur) section_size += sizeof(struct rite_section_debug_header); // filename table - filenames = (mrb_sym *)mrb_malloc(mrb, sizeof(mrb_sym *) * 1); + filenames = (mrb_sym *)mrb_malloc(mrb, sizeof(mrb_sym) * 1); filenames_len_out = cur; cur += sizeof(uint16_t); section_size += sizeof(uint16_t); section_size += write_filename_table(mrb, irep, &cur, &filenames, &filenames_len); - for (i=0; i<irep->rlen; i++) { - section_size += write_filename_table(mrb, irep->reps[i], &cur, &filenames, &filenames_len); - } uint16_to_bin(filenames_len, filenames_len_out); // debug records dlen = write_debug_record(mrb, irep, cur, filenames, filenames_len); - cur += dlen; section_size += dlen; - for (i=0; i<irep->rlen; i++) { - dlen = write_debug_record(mrb, irep->reps[i], cur, filenames, filenames_len); - cur += dlen; - section_size += dlen; - } memcpy(header->section_identify, RITE_SECTION_DEBUG_IDENTIFIER, sizeof(header->section_identify)); uint32_to_bin(section_size, header->section_size); @@ -686,7 +696,7 @@ dump_irep(mrb_state *mrb, mrb_irep *irep, int debug_info, uint8_t **bin, size_t section_lineno_size += sizeof(struct rite_section_debug_header); // filename table - filenames = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym *) + 1); + filenames = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym) + 1); // filename table size section_lineno_size += sizeof(uint16_t); diff --git a/src/error.c b/src/error.c index 10ba6170f..1ee891619 100644 --- a/src/error.c +++ b/src/error.c @@ -7,10 +7,8 @@ #include <errno.h> #include <stdarg.h> #include <stdlib.h> -#include <string.h> #include "mruby.h" #include "mruby/array.h" -#include "mruby/class.h" #include "mruby/irep.h" #include "mruby/proc.h" #include "mruby/string.h" @@ -25,7 +23,7 @@ mrb_exc_new(mrb_state *mrb, struct RClass *c, const char *ptr, long len) } mrb_value -mrb_exc_new3(mrb_state *mrb, struct RClass* c, mrb_value str) +mrb_exc_new_str(mrb_state *mrb, struct RClass* c, mrb_value str) { str = mrb_str_to_str(mrb, str); return mrb_funcall(mrb, mrb_obj_value(c), "new", 1, str); @@ -45,7 +43,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_intern2(mrb, "mesg", 4), mesg); + mrb_iv_set(mrb, exc, mrb_intern_lit(mrb, "mesg"), mesg); } return exc; } @@ -74,7 +72,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_intern2(mrb, "mesg", 4), a); + mrb_iv_set(mrb, exc, mrb_intern_lit(mrb, "mesg"), a); return exc; } @@ -90,7 +88,7 @@ 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_intern2(mrb, "mesg", 4)); + mrb_value mesg = mrb_attr_get(mrb, exc, mrb_intern_lit(mrb, "mesg")); if (mrb_nil_p(mesg)) return mrb_str_new_cstr(mrb, mrb_obj_classname(mrb, exc)); return mesg; @@ -124,9 +122,9 @@ exc_inspect(mrb_state *mrb, mrb_value exc) { mrb_value str, mesg, file, 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)); + mesg = mrb_attr_get(mrb, exc, mrb_intern_lit(mrb, "mesg")); + file = mrb_attr_get(mrb, exc, mrb_intern_lit(mrb, "file")); + line = mrb_attr_get(mrb, exc, mrb_intern_lit(mrb, "line")); if (!mrb_nil_p(file) && !mrb_nil_p(line)) { str = file; @@ -163,7 +161,7 @@ exc_equal(mrb_state *mrb, mrb_value exc) mrb_value obj; mrb_value mesg; mrb_bool equal_p; - mrb_sym id_mesg = mrb_intern2(mrb, "mesg", 4); + mrb_sym id_mesg = mrb_intern_lit(mrb, "mesg"); mrb_get_args(mrb, "o", &obj); if (mrb_obj_equal(mrb, exc, obj)) { @@ -171,7 +169,7 @@ exc_equal(mrb_state *mrb, mrb_value exc) } else { if (mrb_obj_class(mrb, exc) != mrb_obj_class(mrb, obj)) { - if (mrb_respond_to(mrb, obj, mrb_intern2(mrb, "message", 7))) { + if (mrb_respond_to(mrb, obj, mrb_intern_lit(mrb, "message"))) { mesg = mrb_funcall(mrb, obj, "message", 0); } else @@ -193,7 +191,7 @@ exc_debug_info(mrb_state *mrb, struct RObject *exc) mrb_callinfo *ci = mrb->c->ci; mrb_code *pc = ci->pc; - mrb_obj_iv_set(mrb, exc, mrb_intern2(mrb, "ciidx", 5), mrb_fixnum_value(ci - mrb->c->cibase)); + mrb_obj_iv_set(mrb, exc, mrb_intern_lit(mrb, "ciidx"), mrb_fixnum_value(ci - mrb->c->cibase)); while (ci >= mrb->c->cibase) { mrb_code *err = ci->err; @@ -204,8 +202,8 @@ exc_debug_info(mrb_state *mrb, struct RObject *exc) int32_t const line = mrb_debug_get_line(irep, err - irep->iseq); char const* file = mrb_debug_get_filename(irep, err - irep->iseq); if (line != -1 && file) { - mrb_obj_iv_set(mrb, exc, mrb_intern2(mrb, "file", 4), mrb_str_new_cstr(mrb, file)); - mrb_obj_iv_set(mrb, exc, mrb_intern2(mrb, "line", 4), mrb_fixnum_value(line)); + mrb_obj_iv_set(mrb, exc, mrb_intern_lit(mrb, "file"), mrb_str_new_cstr(mrb, file)); + mrb_obj_iv_set(mrb, exc, mrb_intern_lit(mrb, "line"), mrb_fixnum_value(line)); return; } } @@ -231,7 +229,7 @@ mrb_raise(mrb_state *mrb, struct RClass *c, const char *msg) { mrb_value mesg; mesg = mrb_str_new_cstr(mrb, msg); - mrb_exc_raise(mrb, mrb_exc_new3(mrb, c, mesg)); + mrb_exc_raise(mrb, mrb_exc_new_str(mrb, c, mesg)); } mrb_value @@ -297,7 +295,7 @@ mrb_raisef(mrb_state *mrb, struct RClass *c, const char *fmt, ...) va_start(args, fmt); mesg = mrb_vformat(mrb, fmt, args); va_end(args); - mrb_exc_raise(mrb, mrb_exc_new3(mrb, c, mesg)); + mrb_exc_raise(mrb, mrb_exc_new_str(mrb, c, mesg)); } void @@ -347,21 +345,14 @@ mrb_bug(mrb_state *mrb, const char *fmt, ...) exit(EXIT_FAILURE); } -int -sysexit_status(mrb_state *mrb, mrb_value err) -{ - mrb_value st = mrb_iv_get(mrb, err, mrb_intern2(mrb, "status", 6)); - return mrb_fixnum(st); -} - static void set_backtrace(mrb_state *mrb, mrb_value info, mrb_value bt) { mrb_funcall(mrb, info, "set_backtrace", 1, bt); } -mrb_value -make_exception(mrb_state *mrb, int argc, mrb_value *argv, int isstr) +static mrb_value +make_exception(mrb_state *mrb, int argc, mrb_value *argv, mrb_bool isstr) { mrb_value mesg; int n; @@ -376,7 +367,7 @@ make_exception(mrb_state *mrb, int argc, mrb_value *argv, int isstr) if (isstr) { mesg = mrb_check_string_type(mrb, argv[0]); if (!mrb_nil_p(mesg)) { - mesg = mrb_exc_new3(mrb, E_RUNTIME_ERROR, mesg); + mesg = mrb_exc_new_str(mrb, E_RUNTIME_ERROR, mesg); break; } } @@ -388,7 +379,7 @@ make_exception(mrb_state *mrb, int argc, mrb_value *argv, int isstr) n = 1; exception_call: { - mrb_sym exc = mrb_intern2(mrb, "exception", 9); + mrb_sym exc = mrb_intern_lit(mrb, "exception"); if (mrb_respond_to(mrb, argv[0], exc)) { mesg = mrb_funcall_argv(mrb, argv[0], exc, n, argv+1); } diff --git a/src/error.h b/src/error.h index 5aa4ca374..b04dc1082 100644 --- a/src/error.h +++ b/src/error.h @@ -8,9 +8,7 @@ #define MRUBY_ERROR_H void mrb_sys_fail(mrb_state *mrb, const char *mesg); -int sysexit_status(mrb_state *mrb, mrb_value err); -mrb_value mrb_exc_new3(mrb_state *mrb, struct RClass* c, mrb_value str); -mrb_value make_exception(mrb_state *mrb, int argc, mrb_value *argv, int isstr); +mrb_value mrb_exc_new_str(mrb_state *mrb, struct RClass* c, mrb_value str); mrb_value mrb_make_exception(mrb_state *mrb, int argc, mrb_value *argv); mrb_value mrb_format(mrb_state *mrb, const char *format, ...); void mrb_exc_print(mrb_state *mrb, struct RObject *exc); @@ -6,8 +6,6 @@ #include "mruby.h" #include "mruby/string.h" -#include "error.h" -#include "mruby/numeric.h" #include "mruby/data.h" #include "mruby/class.h" @@ -18,7 +16,7 @@ mrb_data_object_alloc(mrb_state *mrb, struct RClass *klass, void *ptr, const mrb data = (struct RData*)mrb_obj_alloc(mrb, MRB_TT_DATA, klass); data->data = ptr; - data->type = (mrb_data_type*) type; + data->type = type; return data; } @@ -64,34 +62,6 @@ mrb_data_get_ptr(mrb_state *mrb, mrb_value obj, const mrb_data_type *type) return DATA_PTR(obj); } -mrb_value -mrb_lastline_get(mrb_state *mrb) -{ - mrb_value *argv; - int argc; - - mrb_get_args(mrb, "*", &argv, &argc); - if (argc < 1) { - return mrb_nil_value(); - } - else - { - return argv[0]; - } -} - -/* ------------------------------------------------ */ -/* - * Calls func(obj, arg, recursive), where recursive is non-zero if the - * current method is called recursively on obj - */ - -mrb_value -mrb_exec_recursive(mrb_state *mrb, mrb_value (*func) (mrb_state *, mrb_value, mrb_value, int), mrb_value obj, void *arg) -{ - return func(mrb, obj, *(mrb_value*)arg, 0); -} - mrb_sym mrb_obj_to_sym(mrb_state *mrb, mrb_value name) { @@ -111,24 +81,11 @@ mrb_obj_to_sym(mrb_state *mrb, mrb_value name) name = mrb_str_intern(mrb, name); /* fall through */ case MRB_TT_SYMBOL: - return mrb_symbol(name); + id = mrb_symbol(name); } return id; } -/* - * call-seq: - * proc { |...| block } -> a_proc - * - * Equivalent to <code>Proc.new</code>. - */ - -mrb_value -mrb_block_proc(void) -{ - return mrb_nil_value(); -} - static mrb_int float_id(mrb_float f) { @@ -199,6 +156,16 @@ mrb_float_value(mrb_state *mrb, mrb_float f) } mrb_value +mrb_float_pool(mrb_state *mrb, mrb_float f) +{ + struct RFloat *nf = (struct RFloat *)mrb_malloc(mrb, sizeof(struct RFloat)); + nf->tt = MRB_TT_FLOAT; + nf->c = mrb->float_class; + nf->f = f; + return mrb_obj_value(nf); +} + +mrb_value mrb_cptr_value(mrb_state *mrb, void *p) { mrb_value v; @@ -4,12 +4,6 @@ ** See Copyright Notice in mruby.h */ -#ifndef SIZE_MAX - /* Some versions of VC++ - * has SIZE_MAX in stdint.h - */ -# include <limits.h> -#endif #include <string.h> #include <stdlib.h> #include "mruby.h" @@ -370,11 +364,19 @@ mrb_free_heap(mrb_state *mrb) static void gc_protect(mrb_state *mrb, struct RBasic *p) { - if (mrb->arena_idx >= MRB_ARENA_SIZE) { +#ifdef MRB_GC_FIXED_ARENA + if (mrb->arena_idx >= MRB_GC_ARENA_SIZE) { /* arena overflow error */ - mrb->arena_idx = MRB_ARENA_SIZE - 4; /* force room in arena */ + mrb->arena_idx = MRB_GC_ARENA_SIZE - 4; /* force room in arena */ mrb_raise(mrb, E_RUNTIME_ERROR, "arena overflow error"); } +#else + if (mrb->arena_idx >= mrb->arena_capa) { + /* extend arena */ + mrb->arena_capa *= 1.5; + mrb->arena = (struct RBasic**)mrb_realloc(mrb, mrb->arena, sizeof(struct RBasic*)*mrb->arena_capa); + } +#endif mrb->arena[mrb->arena_idx++] = p; } @@ -832,13 +834,13 @@ incremental_sweep_phase(mrb_state *mrb, size_t limit) RVALUE *p = page->objects; RVALUE *e = p + MRB_HEAP_PAGE_SIZE; size_t freed = 0; - int dead_slot = 1; + mrb_bool dead_slot = TRUE; int full = (page->freelist == NULL); if (is_minor_gc(mrb) && page->old) { /* skip a slot which doesn't contain any young object */ p = e; - dead_slot = 0; + dead_slot = FALSE; } while (p<e) { if (is_dead(mrb, &p->as.basic)) { @@ -1041,6 +1043,20 @@ mrb_gc_arena_save(mrb_state *mrb) void mrb_gc_arena_restore(mrb_state *mrb, int idx) { +#ifndef MRB_GC_FIXED_ARENA + int capa = mrb->arena_capa; + + if (idx < capa / 2) { + capa *= 0.66; + if (capa < MRB_GC_ARENA_SIZE) { + capa = MRB_GC_ARENA_SIZE; + } + if (capa != mrb->arena_capa) { + mrb->arena = (struct RBasic**)mrb_realloc(mrb, mrb->arena, sizeof(struct RBasic*)*capa); + mrb->arena_capa = capa; + } + } +#endif mrb->arena_idx = idx; } @@ -1265,21 +1281,21 @@ gc_generational_mode_set(mrb_state *mrb, mrb_value self) } void -mrb_objspace_each_objects(mrb_state *mrb, each_object_callback* callback, void *data) +mrb_objspace_each_objects(mrb_state *mrb, mrb_each_object_callback *callback, void *data) { - struct heap_page* page = mrb->heaps; + struct heap_page* page = mrb->heaps; - while (page != NULL) { - RVALUE *p, *pend; - - p = page->objects; - pend = p + MRB_HEAP_PAGE_SIZE; - for (;p < pend; p++) { - (*callback)(mrb, &p->as.basic, data); - } + while (page != NULL) { + RVALUE *p, *pend; - page = page->next; + p = page->objects; + pend = p + MRB_HEAP_PAGE_SIZE; + for (;p < pend; p++) { + (*callback)(mrb, &p->as.basic, data); } + + page = page->next; + } } #ifdef GC_TEST @@ -1322,7 +1338,7 @@ test_mrb_field_write_barrier(void) puts("test_mrb_field_write_barrier"); mrb->is_generational_gc_mode = FALSE; obj = mrb_basic_ptr(mrb_ary_new(mrb)); - value = mrb_basic_ptr(mrb_str_new_cstr(mrb, "value")); + value = mrb_basic_ptr(mrb_str_new_lit(mrb, "value")); paint_black(obj); paint_partial_white(mrb,value); @@ -1364,7 +1380,7 @@ test_mrb_field_write_barrier(void) { puts("test_mrb_field_write_barrier_value"); obj = mrb_basic_ptr(mrb_ary_new(mrb)); - mrb_value value = mrb_str_new_cstr(mrb, "value"); + mrb_value value = mrb_str_new_lit(mrb, "value"); paint_black(obj); paint_partial_white(mrb, mrb_basic_ptr(value)); @@ -1413,12 +1429,12 @@ test_add_gray_list(void) puts("test_add_gray_list"); change_gen_gc_mode(mrb, FALSE); mrb_assert(mrb->gray_list == NULL); - obj1 = mrb_basic_ptr(mrb_str_new_cstr(mrb, "test")); + obj1 = mrb_basic_ptr(mrb_str_new_lit(mrb, "test")); add_gray_list(mrb, obj1); mrb_assert(mrb->gray_list == obj1); mrb_assert(is_gray(obj1)); - obj2 = mrb_basic_ptr(mrb_str_new_cstr(mrb, "test")); + obj2 = mrb_basic_ptr(mrb_str_new_lit(mrb, "test")); add_gray_list(mrb, obj2); mrb_assert(mrb->gray_list == obj2); mrb_assert(mrb->gray_list->gcnext == obj1); @@ -1446,7 +1462,7 @@ test_gc_gray_mark(void) puts(" in MRB_TT_ARRAY"); obj_v = mrb_ary_new(mrb); - value_v = mrb_str_new_cstr(mrb, "test"); + value_v = mrb_str_new_lit(mrb, "test"); paint_gray(mrb_basic_ptr(obj_v)); paint_partial_white(mrb, mrb_basic_ptr(value_v)); mrb_ary_push(mrb, obj_v, value_v); diff --git a/src/hash.c b/src/hash.c index 3684b3b40..2b98e5fd1 100644 --- a/src/hash.c +++ b/src/hash.c @@ -73,7 +73,7 @@ mrb_gc_mark_hash_size(mrb_state *mrb, struct RHash *hash) void mrb_gc_free_hash(mrb_state *mrb, struct RHash *hash) { - if (hash->ht) kh_destroy(ht, hash->ht); + if (hash->ht) kh_destroy(ht, mrb, hash->ht); } @@ -85,7 +85,7 @@ mrb_hash_new_capa(mrb_state *mrb, int capa) h = (struct RHash*)mrb_obj_alloc(mrb, MRB_TT_HASH, mrb->hash_class); h->ht = kh_init(ht, mrb); if (capa > 0) { - kh_resize(ht, h->ht, capa); + kh_resize(ht, mrb, h->ht, capa); } h->iv = 0; return mrb_obj_value(h); @@ -104,7 +104,7 @@ mrb_hash_get(mrb_state *mrb, mrb_value hash, mrb_value key) khiter_t k; if (h) { - k = kh_get(ht, h, key); + k = kh_get(ht, mrb, h, key); if (k != kh_end(h)) return kh_value(h, k); } @@ -123,7 +123,7 @@ mrb_hash_fetch(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value def) khiter_t k; if (h) { - k = kh_get(ht, h, key); + k = kh_get(ht, mrb, h, key); if (k != kh_end(h)) return kh_value(h, k); } @@ -142,11 +142,11 @@ mrb_hash_set(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value val) /* mr h = RHASH_TBL(hash); if (!h) h = RHASH_TBL(hash) = kh_init(ht, mrb); - k = kh_get(ht, h, key); + k = kh_get(ht, mrb, h, key); if (k == kh_end(h)) { /* expand */ int ai = mrb_gc_arena_save(mrb); - k = kh_put(ht, h, KEY(key)); + k = kh_put(ht, mrb, h, KEY(key)); mrb_gc_arena_restore(mrb, ai); } @@ -172,7 +172,7 @@ mrb_hash_dup(mrb_state *mrb, mrb_value hash) for (k = kh_begin(h); k != kh_end(h); k++) { if (kh_exist(h,k)) { int ai = mrb_gc_arena_save(mrb); - ret_k = kh_put(ht, ret_h, KEY(kh_key(h,k))); + ret_k = kh_put(ht, mrb, ret_h, KEY(kh_key(h,k))); mrb_gc_arena_restore(mrb, ai); kh_val(ret_h, ret_k) = kh_val(h,k); } @@ -266,7 +266,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_intern2(mrb, "ifnone", 6), ifnone); + mrb_iv_set(mrb, hash, mrb_intern_lit(mrb, "ifnone"), ifnone); return hash; } @@ -425,7 +425,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_intern2(mrb, "ifnone", 6), ifnone); + mrb_iv_set(mrb, hash, mrb_intern_lit(mrb, "ifnone"), ifnone); RHASH(hash)->flags &= ~(MRB_HASH_PROC_DEFAULT); return ifnone; @@ -476,7 +476,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_intern2(mrb, "ifnone", 6), ifnone); + mrb_iv_set(mrb, hash, mrb_intern_lit(mrb, "ifnone"), ifnone); RHASH(hash)->flags |= MRB_HASH_PROC_DEFAULT; return ifnone; @@ -490,10 +490,10 @@ mrb_hash_delete_key(mrb_state *mrb, mrb_value hash, mrb_value key) mrb_value delVal; if (h) { - k = kh_get(ht, h, key); + k = kh_get(ht, mrb, h, key); if (k != kh_end(h)) { delVal = kh_value(h, k); - kh_del(ht, h, k); + kh_del(ht, mrb, h, k); return delVal; } } @@ -660,7 +660,7 @@ mrb_hash_clear(mrb_state *mrb, mrb_value hash) { khash_t(ht) *h = RHASH_TBL(hash); - if (h) kh_clear(ht, h); + if (h) kh_clear(ht, mrb, h); return hash; } @@ -734,7 +734,7 @@ mrb_hash_replace(mrb_state *mrb, mrb_value hash) else { ifnone = RHASH_IFNONE(hash2); } - mrb_iv_set(mrb, hash, mrb_intern2(mrb, "ifnone", 6), ifnone); + mrb_iv_set(mrb, hash, mrb_intern_lit(mrb, "ifnone"), ifnone); return hash; } @@ -788,9 +788,9 @@ inspect_hash(mrb_state *mrb, mrb_value hash, int recur) khash_t(ht) *h = RHASH_TBL(hash); khiter_t k; - if (recur) return mrb_str_new(mrb, "{...}", 5); + if (recur) return mrb_str_new_lit(mrb, "{...}"); - str = mrb_str_new(mrb, "{", 1); + str = mrb_str_new_lit(mrb, "{"); if (h && kh_size(h) > 0) { for (k = kh_begin(h); k != kh_end(h); k++) { int ai; @@ -833,7 +833,7 @@ mrb_hash_inspect(mrb_state *mrb, mrb_value hash) khash_t(ht) *h = RHASH_TBL(hash); if (!h || kh_size(h) == 0) - return mrb_str_new(mrb, "{}", 2); + return mrb_str_new_lit(mrb, "{}"); return inspect_hash(mrb, hash, 0); } @@ -920,7 +920,7 @@ mrb_hash_has_keyWithKey(mrb_state *mrb, mrb_value hash, mrb_value key) khiter_t k; if (h) { - k = kh_get(ht, h, key); + k = kh_get(ht, mrb, h, key); return mrb_bool_value(k != kh_end(h)); } return mrb_false_value(); @@ -998,13 +998,13 @@ mrb_hash_has_value(mrb_state *mrb, mrb_value hash) } static mrb_value -hash_equal(mrb_state *mrb, mrb_value hash1, mrb_value hash2, int eql) +hash_equal(mrb_state *mrb, mrb_value hash1, mrb_value hash2, mrb_bool eql) { khash_t(ht) *h1, *h2; if (mrb_obj_equal(mrb, hash1, hash2)) return mrb_true_value(); if (!mrb_hash_p(hash2)) { - if (!mrb_respond_to(mrb, hash2, mrb_intern2(mrb, "to_hash", 7))) { + if (!mrb_respond_to(mrb, hash2, mrb_intern_lit(mrb, "to_hash"))) { return mrb_false_value(); } if (eql) @@ -1026,7 +1026,7 @@ hash_equal(mrb_state *mrb, mrb_value hash1, mrb_value hash2, int eql) for (k1 = kh_begin(h1); k1 != kh_end(h1); k1++) { if (!kh_exist(h1, k1)) continue; key = kh_key(h1,k1); - k2 = kh_get(ht, h2, key); + k2 = kh_get(ht, mrb, h2, key); if (k2 != kh_end(h2)) { if (mrb_equal(mrb, kh_value(h1,k1), kh_value(h2,k2))) { continue; /* next key */ @@ -1227,7 +1227,6 @@ mrb_init_hash(mrb_state *mrb) h = mrb->hash_class = mrb_define_class(mrb, "Hash", mrb->object_class); MRB_SET_INSTANCE_TT(h, MRB_TT_HASH); - mrb_include_module(mrb, h, mrb_class_get(mrb, "Enumerable")); mrb_define_method(mrb, h, "==", mrb_hash_equal, MRB_ARGS_REQ(1)); /* 15.2.13.4.1 */ mrb_define_method(mrb, h, "[]", mrb_hash_aget, MRB_ARGS_REQ(1)); /* 15.2.13.4.2 */ mrb_define_method(mrb, h, "[]=", mrb_hash_aset, MRB_ARGS_REQ(2)); /* 15.2.13.4.3 */ diff --git a/src/init.c b/src/init.c index e97c72d68..c08c4b046 100644 --- a/src/init.c +++ b/src/init.c @@ -22,6 +22,7 @@ void mrb_init_numeric(mrb_state*); void mrb_init_range(mrb_state*); void mrb_init_gc(mrb_state*); void mrb_init_math(mrb_state*); +void mrb_init_version(mrb_state*); void mrb_init_mrblib(mrb_state*); void mrb_init_mrbgems(mrb_state*); void mrb_final_mrbgems(mrb_state*); @@ -47,6 +48,7 @@ mrb_init_core(mrb_state *mrb) mrb_init_numeric(mrb); DONE; mrb_init_range(mrb); DONE; mrb_init_gc(mrb); DONE; + mrb_init_version(mrb); DONE; mrb_init_mrblib(mrb); DONE; #ifndef DISABLE_GEMS mrb_init_mrbgems(mrb); DONE; diff --git a/src/kernel.c b/src/kernel.c index f07fbbab1..f13a13ea2 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -29,7 +29,7 @@ typedef enum { mrb_bool mrb_obj_basic_to_s_p(mrb_state *mrb, mrb_value obj) { - struct RProc *me = mrb_method_search(mrb, mrb_class(mrb, obj), mrb_intern2(mrb, "to_s", 4)); + struct RProc *me = mrb_method_search(mrb, mrb_class(mrb, obj), mrb_intern_lit(mrb, "to_s")); if (me && MRB_PROC_CFUNC_P(me) && (me->body.func == mrb_any_to_s)) return TRUE; return FALSE; @@ -218,7 +218,7 @@ mrb_f_block_given_p_m(mrb_state *mrb, mrb_value self) mrb_value *bp; mrb_bool given_p; - bp = mrb->c->stbase + ci->stackidx + 1; + bp = ci->stackent + 1; ci--; if (ci <= mrb->c->cibase) { given_p = 0; @@ -280,7 +280,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_intern2(mrb, "__attached__", 12), obj); + mrb_obj_iv_set(mrb, (struct RObject*)clone, mrb_intern_lit(mrb, "__attached__"), obj); } if (klass->mt) { clone->mt = kh_copy(mt, mrb, klass->mt); @@ -294,12 +294,22 @@ mrb_singleton_class_clone(mrb_state *mrb, mrb_value obj) } static void +copy_class(mrb_state *mrb, mrb_value dst, mrb_value src) +{ + struct RClass *dc = mrb_class_ptr(dst); + struct RClass *sc = mrb_class_ptr(src); + dc->mt = kh_copy(mt, mrb, sc->mt); + dc->super = sc->super; +} + +static void init_copy(mrb_state *mrb, mrb_value dest, mrb_value obj) { - switch (mrb_type(obj)) { - case MRB_TT_OBJECT: + switch (mrb_type(obj)) { case MRB_TT_CLASS: case MRB_TT_MODULE: + copy_class(mrb, dest, obj); + case MRB_TT_OBJECT: case MRB_TT_SCLASS: case MRB_TT_HASH: case MRB_TT_DATA: @@ -733,13 +743,13 @@ method_entry_loop(mrb_state *mrb, struct RClass* klass, khash_t(st)* set) if (!h) return; for (i=0;i<kh_end(h);i++) { if (kh_exist(h, i)) { - kh_put(st, set, kh_key(h,i)); + kh_put(st, mrb, set, kh_key(h,i)); } } } mrb_value -class_instance_method_list(mrb_state *mrb, mrb_bool recur, struct RClass* klass, int obj) +mrb_class_instance_method_list(mrb_state *mrb, mrb_bool recur, struct RClass* klass, int obj) { khint_t i; mrb_value ary; @@ -765,7 +775,7 @@ class_instance_method_list(mrb_state *mrb, mrb_bool recur, struct RClass* klass, mrb_ary_push(mrb, ary, mrb_symbol_value(kh_key(set,i))); } } - kh_destroy(st, set); + kh_destroy(st, mrb, set); return ary; } @@ -797,7 +807,7 @@ mrb_obj_singleton_methods(mrb_state *mrb, mrb_bool recur, mrb_value obj) mrb_ary_push(mrb, ary, mrb_symbol_value(kh_key(set,i))); } } - kh_destroy(st, set); + kh_destroy(st, mrb, set); return ary; } @@ -806,7 +816,7 @@ mrb_value mrb_obj_methods(mrb_state *mrb, mrb_bool recur, mrb_value obj, mrb_method_flag_t flag) { if (recur) - return class_instance_method_list(mrb, recur, mrb_class(mrb, obj), 0); + return mrb_class_instance_method_list(mrb, recur, mrb_class(mrb, obj), 0); else return mrb_obj_singleton_methods(mrb, recur, obj); } @@ -944,7 +954,7 @@ 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_intern2(mrb, "lastpc", 6), mrb_cptr_value(mrb, mrb->c->ci->pc)); + mrb_obj_iv_set(mrb, mrb_obj_ptr(exc), mrb_intern_lit(mrb, "lastpc"), mrb_cptr_value(mrb, mrb->c->ci->pc)); mrb_exc_raise(mrb, exc); break; } @@ -1009,7 +1019,7 @@ basic_obj_respond_to(mrb_state *mrb, mrb_value obj, mrb_sym id, int pub) * If the method is not defined, <code>respond_to_missing?</code> * method is called and the result is returned. */ -mrb_value +static mrb_value obj_respond_to(mrb_state *mrb, mrb_value self) { mrb_value *argv; @@ -1049,7 +1059,7 @@ obj_respond_to(mrb_state *mrb, mrb_value self) } if (!respond_to_p) { - rtm_id = mrb_intern2(mrb, "respond_to_missing?", 19); + rtm_id = mrb_intern_lit(mrb, "respond_to_missing?"); if (basic_obj_respond_to(mrb, self, rtm_id, !mrb_test(priv))) { return mrb_funcall_argv(mrb, self, rtm_id, argc, argv); } @@ -1098,6 +1108,23 @@ mrb_obj_singleton_methods_m(mrb_state *mrb, mrb_value self) return mrb_obj_singleton_methods(mrb, recur, self); } +static mrb_value +mrb_obj_ceqq(mrb_state *mrb, mrb_value self) +{ + mrb_value v; + mrb_int i, len; + mrb_sym eqq = mrb_intern_lit(mrb, "==="); + mrb_value ary = mrb_ary_splat(mrb, self); + + mrb_get_args(mrb, "o", &v); + len = RARRAY_LEN(ary); + for (i=0; i<len; i++) { + mrb_value c = mrb_funcall_argv(mrb, mrb_ary_entry(ary, i), eqq, 1, &v); + if (mrb_test(c)) return mrb_true_value(); + } + return mrb_false_value(); +} + void mrb_init_kernel(mrb_state *mrb) { @@ -1149,7 +1176,8 @@ mrb_init_kernel(mrb_state *mrb) mrb_define_method(mrb, krn, "send", mrb_f_send, MRB_ARGS_ANY()); /* 15.3.1.3.44 */ mrb_define_method(mrb, krn, "singleton_methods", mrb_obj_singleton_methods_m, MRB_ARGS_OPT(1)); /* 15.3.1.3.45 */ mrb_define_method(mrb, krn, "to_s", mrb_any_to_s, MRB_ARGS_NONE()); /* 15.3.1.3.46 */ + mrb_define_method(mrb, krn, "__case_eqq", mrb_obj_ceqq, MRB_ARGS_REQ(1)); /* internal */ mrb_include_module(mrb, mrb->object_class, mrb->kernel_module); - mrb_alias_method(mrb, mrb->module_class, mrb_intern2(mrb, "dup", 3), mrb_intern2(mrb, "clone", 5)); + mrb_alias_method(mrb, mrb->module_class, mrb_intern_lit(mrb, "dup"), mrb_intern_lit(mrb, "clone")); } diff --git a/src/load.c b/src/load.c index 68ebb1f7b..57845b2ca 100644 --- a/src/load.c +++ b/src/load.c @@ -4,12 +4,7 @@ ** See Copyright Notice in mruby.h */ -#ifndef SIZE_MAX - /* Some versions of VC++ - * has SIZE_MAX in stdint.h - */ -# include <limits.h> -#endif +#include <limits.h> #include <stdlib.h> #include <string.h> #include "mruby/dump.h" @@ -38,7 +33,7 @@ offset_crc_body(void) } static mrb_irep* -read_irep_record_1(mrb_state *mrb, const uint8_t *bin, uint32_t *len) +read_irep_record_1(mrb_state *mrb, const uint8_t *bin, uint32_t *len, mrb_bool alloc) { size_t i; const uint8_t *src = bin; @@ -87,7 +82,7 @@ read_irep_record_1(mrb_state *mrb, const uint8_t *bin, uint32_t *len) if (SIZE_ERROR_MUL(sizeof(mrb_value), plen)) { return NULL; } - irep->pool = (struct irep_pool*)mrb_malloc(mrb, sizeof(struct irep_pool) * plen); + irep->pool = (mrb_value*)mrb_malloc(mrb, sizeof(mrb_value) * plen); if (irep->pool == NULL) { return NULL; } @@ -98,40 +93,29 @@ read_irep_record_1(mrb_state *mrb, const uint8_t *bin, uint32_t *len) tt = *src++; //pool TT pool_data_len = bin_to_uint16(src); //pool data length src += sizeof(uint16_t); - s = mrb_str_new(mrb, (char *)src, pool_data_len); + if (alloc) { + s = mrb_str_new(mrb, (char *)src, pool_data_len); + } + else { + s = mrb_str_new_static(mrb, (char *)src, pool_data_len); + } src += pool_data_len; - irep->pool[i].type = tt; switch (tt) { //pool data case IREP_TT_FIXNUM: - { - mrb_value v = mrb_str_to_inum(mrb, s, 10, FALSE); - - switch (mrb_type(v)) { - case MRB_TT_FIXNUM: - irep->pool[i].value.i = mrb_fixnum(v); - break; - case MRB_TT_FLOAT: - irep->pool[i].type = MRB_TT_FLOAT; - irep->pool[i].value.f = mrb_float(v); - default: - /* broken data; should not happen */ - irep->pool[i].value.i = 0; - } - } + irep->pool[i] = mrb_str_to_inum(mrb, s, 10, FALSE); break; case IREP_TT_FLOAT: - irep->pool[i].value.f = mrb_str_to_dbl(mrb, s, FALSE); + irep->pool[i] = mrb_float_pool(mrb, mrb_str_to_dbl(mrb, s, FALSE)); break; case IREP_TT_STRING: - irep->pool[i].value.s = (struct irep_pool_string*)mrb_malloc(mrb, sizeof(struct irep_pool_string) + pool_data_len); - irep->pool[i].value.s->len = pool_data_len; - memcpy(irep->pool[i].value.s->buf, src-pool_data_len, pool_data_len); + irep->pool[i] = mrb_str_pool(mrb, s); break; default: /* should not happen */ + irep->pool[i] = mrb_nil_value(); break; } irep->plen++; @@ -160,7 +144,12 @@ read_irep_record_1(mrb_state *mrb, const uint8_t *bin, uint32_t *len) continue; } - irep->syms[i] = mrb_intern2(mrb, (char *)src, snl); + if (alloc) { + irep->syms[i] = mrb_intern(mrb, (char *)src, snl); + } + else { + irep->syms[i] = mrb_intern_static(mrb, (char *)src, snl); + } src += snl + 1; mrb_gc_arena_restore(mrb, ai); @@ -174,16 +163,16 @@ read_irep_record_1(mrb_state *mrb, const uint8_t *bin, uint32_t *len) } static mrb_irep* -read_irep_record(mrb_state *mrb, const uint8_t *bin, uint32_t *len) +read_irep_record(mrb_state *mrb, const uint8_t *bin, uint32_t *len, mrb_bool alloc) { - mrb_irep *irep = read_irep_record_1(mrb, bin, len); + mrb_irep *irep = read_irep_record_1(mrb, bin, len, alloc); size_t i; bin += *len; for (i=0; i<irep->rlen; i++) { uint32_t rlen; - irep->reps[i] = read_irep_record(mrb, bin, &rlen); + irep->reps[i] = read_irep_record(mrb, bin, &rlen, alloc); bin += rlen; *len += rlen; } @@ -191,12 +180,12 @@ read_irep_record(mrb_state *mrb, const uint8_t *bin, uint32_t *len) } static mrb_irep* -read_section_irep(mrb_state *mrb, const uint8_t *bin) +read_section_irep(mrb_state *mrb, const uint8_t *bin, mrb_bool alloc) { uint32_t len; bin += sizeof(struct rite_section_irep_header); - return read_irep_record(mrb, bin, &len); + return read_irep_record(mrb, bin, &len, alloc); } static int @@ -360,7 +349,7 @@ read_debug_record(mrb_state *mrb, const uint8_t *start, mrb_irep* irep, uint32_t } static int -read_section_debug(mrb_state *mrb, const uint8_t *start, mrb_irep *irep) +read_section_debug(mrb_state *mrb, const uint8_t *start, mrb_irep *irep, mrb_bool alloc) { const uint8_t *bin; struct rite_section_debug_header *header; @@ -380,7 +369,12 @@ read_section_debug(mrb_state *mrb, const uint8_t *start, mrb_irep *irep) for(i = 0; i < filenames_len; ++i) { uint16_t f_len = bin_to_uint16(bin); bin += sizeof(uint16_t); - filenames[i] = mrb_intern2(mrb, (const char *)bin, f_len); + if (alloc) { + filenames[i] = mrb_intern(mrb, (const char *)bin, f_len); + } + else { + filenames[i] = mrb_intern_static(mrb, (const char *)bin, f_len); + } bin += f_len; } @@ -446,7 +440,7 @@ mrb_read_irep(mrb_state *mrb, const uint8_t *bin) do { section_header = (const struct rite_section_header *)bin; if (memcmp(section_header->section_identify, RITE_SECTION_IREP_IDENTIFIER, sizeof(section_header->section_identify)) == 0) { - irep = read_section_irep(mrb, bin); + irep = read_section_irep(mrb, bin, FALSE); if (!irep) return NULL; } else if (memcmp(section_header->section_identify, RITE_SECTION_LINENO_IDENTIFIER, sizeof(section_header->section_identify)) == 0) { @@ -458,7 +452,7 @@ mrb_read_irep(mrb_state *mrb, const uint8_t *bin) } else if (memcmp(section_header->section_identify, RITE_SECTION_DEBUG_IDENTIFIER, sizeof(section_header->section_identify)) == 0) { if (!irep) return NULL; /* corrupted data */ - result = read_section_debug(mrb, bin, irep); + result = read_section_debug(mrb, bin, irep, FALSE); if (result < MRB_DUMP_OK) { return NULL; } @@ -505,8 +499,8 @@ mrb_load_irep(mrb_state *mrb, const uint8_t *bin) static int read_lineno_record_file(mrb_state *mrb, FILE *fp, mrb_irep *irep) { - const size_t record_header_size = 4; - uint8_t header[record_header_size]; + uint8_t header[4]; + const size_t record_header_size = sizeof(header); int result; size_t i, buf_size; uint32_t len; @@ -555,8 +549,8 @@ read_section_lineno_file(mrb_state *mrb, FILE *fp, mrb_irep *irep) static mrb_irep* read_irep_record_file(mrb_state *mrb, FILE *fp) { - const size_t record_header_size = 1 + 4; - uint8_t header[record_header_size]; + uint8_t header[1 + 4]; + const size_t record_header_size = sizeof(header); size_t buf_size, i; uint32_t len; mrb_irep *irep = NULL; @@ -577,7 +571,7 @@ read_irep_record_file(mrb_state *mrb, FILE *fp) if (fread(&buf[record_header_size], buf_size - record_header_size, 1, fp) == 0) { return NULL; } - irep = read_irep_record_1(mrb, buf, &len); + irep = read_irep_record_1(mrb, buf, &len, TRUE); mrb_free(mrb, ptr); if (!irep) return NULL; for (i=0; i<irep->rlen; i++) { @@ -685,7 +679,7 @@ mrb_read_irep_file(mrb_state *mrb, FILE* fp) mrb_free(mrb, bin); return NULL; } - result = read_section_debug(mrb, bin, irep); + result = read_section_debug(mrb, bin, irep, TRUE); mrb_free(mrb, bin); } if (result < MRB_DUMP_OK) return NULL; diff --git a/src/numeric.c b/src/numeric.c index 4a22c23c7..462faf686 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -5,12 +5,6 @@ */ #include <float.h> -#if defined(__FreeBSD__) && __FreeBSD__ < 4 -# include <floatingpoint.h> -#endif -#ifdef HAVE_IEEEFP_H -# include <ieeefp.h> -#endif #include <limits.h> #include <math.h> #include <stdlib.h> @@ -54,7 +48,7 @@ static mrb_value num_pow(mrb_state *mrb, mrb_value x) { mrb_value y; - int both_int = FALSE; + mrb_bool both_int = FALSE; mrb_float d; mrb_get_args(mrb, "o", &y); @@ -124,14 +118,14 @@ mrb_flo_to_str(mrb_state *mrb, mrb_value flo, int max_digit) n = mrb_float(flo); if (isnan(n)) { - result = mrb_str_new(mrb, "NaN", 3); + result = mrb_str_new_lit(mrb, "NaN"); } else if (isinf(n)) { if (n < 0) { - result = mrb_str_new(mrb, "-inf", 4); + result = mrb_str_new_lit(mrb, "-inf"); } else { - result = mrb_str_new(mrb, "inf", 3); + result = mrb_str_new_lit(mrb, "inf"); } } else { @@ -193,7 +187,7 @@ mrb_flo_to_str(mrb_state *mrb, mrb_value flo, int max_digit) } if (exp >= 100) { - mrb_raise(mrb, E_RANGE_ERROR, "Too large expornent."); + mrb_raise(mrb, E_RANGE_ERROR, "Too large exponent."); } *(c++) = '0' + exp / 10; @@ -618,6 +612,12 @@ flo_truncate(mrb_state *mrb, mrb_value num) return mrb_fixnum_value((mrb_int)f); } +static mrb_value +flo_nan_p(mrb_state *mrb, mrb_value num) +{ + return mrb_bool_value(isnan(mrb_float(num))); +} + /* * Document-class: Integer * @@ -663,7 +663,7 @@ mrb_fixnum_mul(mrb_state *mrb, mrb_value x, mrb_value y) if (a != 0 && c/a != b) { return mrb_float_value(mrb, (mrb_float)a*(mrb_float)b); } - return mrb_fixnum_value(c);; + return mrb_fixnum_value(c); } return mrb_float_value(mrb, (mrb_float)a * mrb_to_flo(mrb, y)); } @@ -1337,4 +1337,5 @@ mrb_init_numeric(mrb_state *mrb) mrb_define_method(mrb, fl, "to_s", flo_to_s, MRB_ARGS_NONE()); /* 15.2.9.3.16(x) */ mrb_define_method(mrb, fl, "inspect", flo_to_s, MRB_ARGS_NONE()); + mrb_define_method(mrb, fl, "nan?", flo_nan_p, MRB_ARGS_NONE()); } diff --git a/src/object.c b/src/object.c index 56d5e65cd..c11a30055 100644 --- a/src/object.c +++ b/src/object.c @@ -5,11 +5,9 @@ */ #include "mruby.h" -#include "mruby/array.h" #include "mruby/class.h" #include "mruby/numeric.h" #include "mruby/string.h" -#include "error.h" mrb_bool mrb_obj_eq(mrb_state *mrb, mrb_value v1, mrb_value v2) @@ -88,7 +86,7 @@ nil_to_s(mrb_state *mrb, mrb_value obj) static mrb_value nil_inspect(mrb_state *mrb, mrb_value obj) { - return mrb_str_new(mrb, "nil", 3); + return mrb_str_new_lit(mrb, "nil"); } /*********************************************************************** @@ -149,7 +147,7 @@ true_xor(mrb_state *mrb, mrb_value obj) static mrb_value true_to_s(mrb_state *mrb, mrb_value obj) { - return mrb_str_new(mrb, "true", 4); + return mrb_str_new_lit(mrb, "true"); } /* 15.2.5.3.4 */ @@ -256,7 +254,7 @@ false_or(mrb_state *mrb, mrb_value obj) static mrb_value false_to_s(mrb_state *mrb, mrb_value obj) { - return mrb_str_new(mrb, "false", 5); + return mrb_str_new_lit(mrb, "false"); } void @@ -293,14 +291,25 @@ mrb_init_object(mrb_state *mrb) } static mrb_value -convert_type(mrb_state *mrb, mrb_value val, const char *tname, const char *method, int raise) +inspect_type(mrb_state *mrb, mrb_value val) +{ + if (mrb_type(val) == MRB_TT_FALSE || mrb_type(val) == MRB_TT_TRUE) { + return mrb_inspect(mrb, val); + } + else { + return mrb_str_new_cstr(mrb, mrb_obj_classname(mrb, val)); + } +} + +static mrb_value +convert_type(mrb_state *mrb, mrb_value val, const char *tname, const char *method, mrb_bool raise) { mrb_sym m = 0; m = mrb_intern_cstr(mrb, method); if (!mrb_respond_to(mrb, val, m)) { if (raise) { - mrb_raisef(mrb, E_TYPE_ERROR, "can't convert %S into %S", val, mrb_str_new_cstr(mrb, tname)); + mrb_raisef(mrb, E_TYPE_ERROR, "can't convert %S into %S", inspect_type(mrb, val), mrb_str_new_cstr(mrb, tname)); return mrb_nil_value(); } else { @@ -315,9 +324,9 @@ mrb_check_to_integer(mrb_state *mrb, mrb_value val, const char *method) { mrb_value v; - if (mrb_type(val) == MRB_TT_FIXNUM) return val; + if (mrb_fixnum_p(val)) return val; v = convert_type(mrb, val, "Integer", method, FALSE); - if (mrb_nil_p(v) || mrb_type(v) != MRB_TT_FIXNUM) { + if (mrb_nil_p(v) || !mrb_fixnum_p(v)) { return mrb_nil_value(); } return v; @@ -393,7 +402,7 @@ mrb_check_type(mrb_state *mrb, mrb_value x, enum mrb_vtype t) if (mrb_nil_p(x)) { etype = "nil"; } - else if (mrb_type(x) == MRB_TT_FIXNUM) { + else if (mrb_fixnum_p(x)) { etype = "Fixnum"; } else if (mrb_type(x) == MRB_TT_SYMBOL) { @@ -499,8 +508,9 @@ mrb_to_integer(mrb_state *mrb, mrb_value val, const char *method) if (mrb_fixnum_p(val)) return val; v = convert_type(mrb, val, "Integer", method, TRUE); if (!mrb_obj_is_kind_of(mrb, v, mrb->fixnum_class)) { + mrb_value type = inspect_type(mrb, val); mrb_raisef(mrb, E_TYPE_ERROR, "can't convert %S to Integer (%S#%S gives %S)", - val, val, mrb_str_new_cstr(mrb, method), v); + type, type, mrb_str_new_cstr(mrb, method), inspect_type(mrb, v)); } return v; } diff --git a/src/parse.y b/src/parse.y index 63204dfb0..f0e9369a9 100644 --- a/src/parse.y +++ b/src/parse.y @@ -32,6 +32,7 @@ typedef mrb_ast_node node; typedef struct mrb_parser_state parser_state; typedef struct mrb_parser_heredoc_info parser_heredoc_info; +static int yyparse(parser_state *p); static int yylex(void *lval, parser_state *p); static void yyerror(parser_state *p, const char *s); static void yywarn(parser_state *p, const char *s); @@ -62,27 +63,29 @@ typedef unsigned int stack_type; #define CMDARG_LEXPOP() BITSTACK_LEXPOP(p->cmdarg_stack) #define CMDARG_P() BITSTACK_SET_P(p->cmdarg_stack) +#define SET_LINENO(c,n) ((c)->lineno = (n)) + #define sym(x) ((mrb_sym)(intptr_t)(x)) #define nsym(x) ((node*)(intptr_t)(x)) static inline mrb_sym -intern_gen(parser_state *p, const char *s) +intern_cstr_gen(parser_state *p, const char *s) { return mrb_intern_cstr(p->mrb, s); } -#define intern(s) intern_gen(p,(s)) +#define intern_cstr(s) intern_cstr_gen(p,(s)) static inline mrb_sym -intern_gen2(parser_state *p, const char *s, size_t len) +intern_gen(parser_state *p, const char *s, size_t len) { - return mrb_intern2(p->mrb, s, len); + return mrb_intern(p->mrb, s, len); } -#define intern2(s,len) intern_gen2(p,(s),(len)) +#define intern(s,len) intern_gen(p,(s),(len)) static inline mrb_sym intern_gen_c(parser_state *p, const char c) { - return mrb_intern2(p->mrb, &c, 1); + return mrb_intern(p->mrb, &c, 1); } #define intern_c(c) intern_gen_c(p,(c)) @@ -538,7 +541,7 @@ new_strsym(parser_state *p, node* str) const char *s = (const char*)str->cdr->car; size_t len = (size_t)str->cdr->cdr; - return mrb_intern2(p->mrb, s, len); + return mrb_intern(p->mrb, s, len); } // (:lvar . a) @@ -800,14 +803,14 @@ new_symbols(parser_state *p, node *a) static node* call_uni_op(parser_state *p, node *recv, char *m) { - return new_call(p, recv, intern(m), 0); + return new_call(p, recv, intern_cstr(m), 0); } // (:call a op b) static node* call_bin_op(parser_state *p, node *recv, char *m, node *arg1) { - return new_call(p, recv, intern(m), list1(list1(arg1))); + return new_call(p, recv, intern_cstr(m), list1(list1(arg1))); } static void @@ -906,7 +909,7 @@ end_strterm(parser_state *p) p->lex_strterm = NULL; } -parser_heredoc_info * +static parser_heredoc_info * parsing_heredoc_inf(parser_state *p) { node *nd = p->parsing_heredoc; @@ -929,7 +932,7 @@ heredoc_treat_nextline(parser_state *p) n = p->all_heredocs; if (n) { while (n->cdr) - n = n->cdr; + n = n->cdr; n->cdr = p->parsing_heredoc; } else { p->all_heredocs = p->parsing_heredoc; @@ -947,8 +950,8 @@ heredoc_treat_nextline(parser_state *p) p->parsing_heredoc = p->heredocs_from_nextline; } else { while (n->cdr != p->parsing_heredoc) { - n = n->cdr; - mrb_assert(n != NULL); + n = n->cdr; + mrb_assert(n != NULL); } m->cdr = n->cdr; n->cdr = p->heredocs_from_nextline; @@ -993,54 +996,54 @@ heredoc_end(parser_state *p) } %token - keyword_class - keyword_module - keyword_def - keyword_undef - keyword_begin - keyword_rescue - keyword_ensure - keyword_end - keyword_if - keyword_unless - keyword_then - keyword_elsif - keyword_else - keyword_case - keyword_when - keyword_while - keyword_until - keyword_for - keyword_break - keyword_next - keyword_redo - keyword_retry - keyword_in - keyword_do - keyword_do_cond - keyword_do_block - keyword_do_LAMBDA - keyword_return - keyword_yield - keyword_super - keyword_self - keyword_nil - keyword_true - keyword_false - keyword_and - keyword_or - keyword_not - modifier_if - modifier_unless - modifier_while - modifier_until - modifier_rescue - keyword_alias - keyword_BEGIN - keyword_END - keyword__LINE__ - keyword__FILE__ - keyword__ENCODING__ + keyword_class + keyword_module + keyword_def + keyword_undef + keyword_begin + keyword_rescue + keyword_ensure + keyword_end + keyword_if + keyword_unless + keyword_then + keyword_elsif + keyword_else + keyword_case + keyword_when + keyword_while + keyword_until + keyword_for + keyword_break + keyword_next + keyword_redo + keyword_retry + keyword_in + keyword_do + keyword_do_cond + keyword_do_block + keyword_do_LAMBDA + keyword_return + keyword_yield + keyword_super + keyword_self + keyword_nil + keyword_true + keyword_false + keyword_and + keyword_or + keyword_not + modifier_if + modifier_unless + modifier_while + modifier_until + modifier_rescue + keyword_alias + keyword_BEGIN + keyword_END + keyword__LINE__ + keyword__FILE__ + keyword__ENCODING__ %token <id> tIDENTIFIER tFID tGVAR tIVAR tCONSTANT tCVAR tLABEL %token <nd> tINTEGER tFLOAT tCHAR tXSTRING tREGEXP @@ -1103,7 +1106,7 @@ heredoc_end(parser_state *p) %token <nd> tHD_STRING_PART tHD_STRING_MID /* - * precedence table + * precedence table */ %nonassoc tLOWEST @@ -1143,2063 +1146,2082 @@ heredoc_end(parser_state *p) %token tLAST_TOKEN %% -program : { - p->lstate = EXPR_BEG; - if (!p->locals) p->locals = cons(0,0); - } - top_compstmt - { - p->tree = new_scope(p, $2); - } - ; - -top_compstmt : top_stmts opt_terms - { - $$ = $1; - } - ; - -top_stmts : none - { - $$ = new_begin(p, 0); - } - | top_stmt - { - $$ = new_begin(p, $1); - } - | top_stmts terms top_stmt - { - $$ = push($1, newline_node($3)); - } - | error top_stmt - { - $$ = new_begin(p, 0); - } - ; - -top_stmt : stmt - | keyword_BEGIN - { - $<nd>$ = local_switch(p); - } - '{' top_compstmt '}' - { - yyerror(p, "BEGIN not supported"); - local_resume(p, $<nd>2); - $$ = 0; - } - ; - -bodystmt : compstmt - opt_rescue - opt_else - opt_ensure - { - if ($2) { - $$ = new_rescue(p, $1, $2, $3); - } - else if ($3) { - yywarn(p, "else without rescue is useless"); - $$ = push($1, $3); - } - else { - $$ = $1; - } - if ($4) { - if ($$) { - $$ = new_ensure(p, $$, $4); - } - else { - $$ = push($4, new_nil(p)); - } - } - } - ; - -compstmt : stmts opt_terms - { - $$ = $1; - } - ; - -stmts : none - { - $$ = new_begin(p, 0); - } - | stmt - { - $$ = new_begin(p, $1); - } - | stmts terms stmt - { - $$ = push($1, newline_node($3)); - } - | error stmt - { - $$ = new_begin(p, $2); - } - ; - -stmt : keyword_alias fsym {p->lstate = EXPR_FNAME;} fsym - { - $$ = new_alias(p, $2, $4); - } - | keyword_undef undef_list - { - $$ = $2; - } - | stmt modifier_if expr_value - { - $$ = new_if(p, cond($3), $1, 0); - } - | stmt modifier_unless expr_value - { - $$ = new_unless(p, cond($3), $1, 0); - } - | stmt modifier_while expr_value - { - $$ = new_while(p, cond($3), $1); - } - | stmt modifier_until expr_value - { - $$ = new_until(p, cond($3), $1); - } - | stmt modifier_rescue stmt - { - $$ = new_rescue(p, $1, list1(list3(0, 0, $3)), 0); - } - | keyword_END '{' compstmt '}' - { - yyerror(p, "END not suported"); - $$ = new_postexe(p, $3); - } - | command_asgn - | mlhs '=' command_call - { - $$ = new_masgn(p, $1, $3); - } - | var_lhs tOP_ASGN command_call - { - $$ = new_op_asgn(p, $1, $2, $3); - } - | primary_value '[' opt_call_args rbracket tOP_ASGN command_call - { - $$ = new_op_asgn(p, new_call(p, $1, intern2("[]",2), $3), $5, $6); - } - | primary_value '.' tIDENTIFIER tOP_ASGN command_call - { - $$ = new_op_asgn(p, new_call(p, $1, $3, 0), $4, $5); - } - | primary_value '.' tCONSTANT tOP_ASGN command_call - { - $$ = new_op_asgn(p, new_call(p, $1, $3, 0), $4, $5); - } - | primary_value tCOLON2 tCONSTANT tOP_ASGN command_call - { - yyerror(p, "constant re-assignment"); - $$ = 0; - } - | primary_value tCOLON2 tIDENTIFIER tOP_ASGN command_call - { - $$ = new_op_asgn(p, new_call(p, $1, $3, 0), $4, $5); - } - | backref tOP_ASGN command_call - { - backref_error(p, $1); - $$ = new_begin(p, 0); - } - | lhs '=' mrhs - { - $$ = new_asgn(p, $1, new_array(p, $3)); - } - | mlhs '=' arg_value - { - $$ = new_masgn(p, $1, $3); - } - | mlhs '=' mrhs - { - $$ = new_masgn(p, $1, new_array(p, $3)); - } - | expr - ; - -command_asgn : lhs '=' command_call - { - $$ = new_asgn(p, $1, $3); - } - | lhs '=' command_asgn - { - $$ = new_asgn(p, $1, $3); - } - ; - - -expr : command_call - | expr keyword_and expr - { - $$ = new_and(p, $1, $3); - } - | expr keyword_or expr - { - $$ = new_or(p, $1, $3); - } - | keyword_not opt_nl expr - { - $$ = call_uni_op(p, cond($3), "!"); - } - | '!' command_call - { - $$ = call_uni_op(p, cond($2), "!"); - } - | arg - ; - -expr_value : expr - { - if (!$1) $$ = new_nil(p); - else $$ = $1; - } - ; - -command_call : command - | block_command - ; - -block_command : block_call - | block_call dot_or_colon operation2 command_args - ; - -cmd_brace_block : tLBRACE_ARG - { - local_nest(p); - } - opt_block_param - compstmt - '}' - { - $$ = new_block(p, $3, $4); - local_unnest(p); - } - ; - -command : operation command_args %prec tLOWEST - { - $$ = new_fcall(p, $1, $2); - } - | operation command_args cmd_brace_block - { - args_with_block(p, $2, $3); - $$ = new_fcall(p, $1, $2); - } - | primary_value '.' operation2 command_args %prec tLOWEST - { - $$ = new_call(p, $1, $3, $4); - } - | primary_value '.' operation2 command_args cmd_brace_block - { - args_with_block(p, $4, $5); - $$ = new_call(p, $1, $3, $4); - } - | primary_value tCOLON2 operation2 command_args %prec tLOWEST - { - $$ = new_call(p, $1, $3, $4); - } - | primary_value tCOLON2 operation2 command_args cmd_brace_block - { - args_with_block(p, $4, $5); - $$ = new_call(p, $1, $3, $4); - } - | keyword_super command_args - { - $$ = new_super(p, $2); - } - | keyword_yield command_args - { - $$ = new_yield(p, $2); - } - | keyword_return call_args - { - $$ = new_return(p, ret_args(p, $2)); - } - | keyword_break call_args - { - $$ = new_break(p, ret_args(p, $2)); - } - | keyword_next call_args - { - $$ = new_next(p, ret_args(p, $2)); - } - ; - -mlhs : mlhs_basic - { - $$ = $1; - } - | tLPAREN mlhs_inner rparen - { - $$ = $2; - } - ; - -mlhs_inner : mlhs_basic - | tLPAREN mlhs_inner rparen - { - $$ = list1($2); - } - ; - -mlhs_basic : mlhs_list - { - $$ = list1($1); - } - | mlhs_list mlhs_item - { - $$ = list1(push($1,$2)); - } - | mlhs_list tSTAR mlhs_node - { - $$ = list2($1, $3); - } - | mlhs_list tSTAR mlhs_node ',' mlhs_post - { - $$ = list3($1, $3, $5); - } - | mlhs_list tSTAR - { - $$ = list2($1, new_nil(p)); - } - | mlhs_list tSTAR ',' mlhs_post - { - $$ = list3($1, new_nil(p), $4); - } - | tSTAR mlhs_node - { - $$ = list2(0, $2); - } - | tSTAR mlhs_node ',' mlhs_post - { - $$ = list3(0, $2, $4); - } - | tSTAR - { - $$ = list2(0, new_nil(p)); - } - | tSTAR ',' mlhs_post - { - $$ = list3(0, new_nil(p), $3); - } - ; - -mlhs_item : mlhs_node - | tLPAREN mlhs_inner rparen - { - $$ = $2; - } - ; - -mlhs_list : mlhs_item ',' - { - $$ = list1($1); - } - | mlhs_list mlhs_item ',' - { - $$ = push($1, $2); - } - ; - -mlhs_post : mlhs_item - { - $$ = list1($1); - } - | mlhs_list mlhs_item - { - $$ = push($1, $2); - } - ; - -mlhs_node : variable - { - assignable(p, $1); - } - | primary_value '[' opt_call_args rbracket - { - $$ = new_call(p, $1, intern2("[]",2), $3); - } - | primary_value '.' tIDENTIFIER - { - $$ = new_call(p, $1, $3, 0); - } - | primary_value tCOLON2 tIDENTIFIER - { - $$ = new_call(p, $1, $3, 0); - } - | primary_value '.' tCONSTANT - { - $$ = new_call(p, $1, $3, 0); - } - | primary_value tCOLON2 tCONSTANT - { - if (p->in_def || p->in_single) - yyerror(p, "dynamic constant assignment"); - $$ = new_colon2(p, $1, $3); - } - | tCOLON3 tCONSTANT - { - if (p->in_def || p->in_single) - yyerror(p, "dynamic constant assignment"); - $$ = new_colon3(p, $2); - } - | backref - { - backref_error(p, $1); - $$ = 0; - } - ; - -lhs : variable - { - assignable(p, $1); - } - | primary_value '[' opt_call_args rbracket - { - $$ = new_call(p, $1, intern2("[]",2), $3); - } - | primary_value '.' tIDENTIFIER - { - $$ = new_call(p, $1, $3, 0); - } - | primary_value tCOLON2 tIDENTIFIER - { - $$ = new_call(p, $1, $3, 0); - } - | primary_value '.' tCONSTANT - { - $$ = new_call(p, $1, $3, 0); - } - | primary_value tCOLON2 tCONSTANT - { - if (p->in_def || p->in_single) - yyerror(p, "dynamic constant assignment"); - $$ = new_colon2(p, $1, $3); - } - | tCOLON3 tCONSTANT - { - if (p->in_def || p->in_single) - yyerror(p, "dynamic constant assignment"); - $$ = new_colon3(p, $2); - } - | backref - { - backref_error(p, $1); - $$ = 0; - } - ; - -cname : tIDENTIFIER - { - yyerror(p, "class/module name must be CONSTANT"); - } - | tCONSTANT - ; - -cpath : tCOLON3 cname - { - $$ = cons((node*)1, nsym($2)); - } - | cname - { - $$ = cons((node*)0, nsym($1)); - } - | primary_value tCOLON2 cname - { - $$ = cons($1, nsym($3)); - } - ; - -fname : tIDENTIFIER - | tCONSTANT - | tFID - | op - { - p->lstate = EXPR_ENDFN; - $$ = $1; - } - | reswords - { - p->lstate = EXPR_ENDFN; - $$ = $<id>1; - } - ; - -fsym : fname - | basic_symbol - ; - -undef_list : fsym - { - $$ = new_undef(p, $1); - } - | undef_list ',' {p->lstate = EXPR_FNAME;} fsym - { - $$ = push($1, nsym($4)); - } - ; - -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__ - | keyword_BEGIN | keyword_END - | keyword_alias | keyword_and | keyword_begin - | keyword_break | keyword_case | keyword_class | keyword_def - | keyword_do | keyword_else | keyword_elsif - | keyword_end | keyword_ensure | keyword_false - | keyword_for | keyword_in | keyword_module | keyword_next - | keyword_nil | keyword_not | keyword_or | keyword_redo - | keyword_rescue | keyword_retry | keyword_return | keyword_self - | keyword_super | keyword_then | keyword_true | keyword_undef - | keyword_when | keyword_yield | keyword_if | keyword_unless - | keyword_while | keyword_until - ; - -arg : lhs '=' arg - { - $$ = new_asgn(p, $1, $3); - } - | lhs '=' arg modifier_rescue arg - { - $$ = new_asgn(p, $1, new_rescue(p, $3, list1(list3(0, 0, $5)), 0)); - } - | var_lhs tOP_ASGN arg - { - $$ = new_op_asgn(p, $1, $2, $3); - } - | var_lhs tOP_ASGN arg modifier_rescue arg - { - $$ = new_op_asgn(p, $1, $2, new_rescue(p, $3, list1(list3(0, 0, $5)), 0)); - } - | primary_value '[' opt_call_args rbracket tOP_ASGN arg - { - $$ = new_op_asgn(p, new_call(p, $1, intern2("[]",2), $3), $5, $6); - } - | primary_value '.' tIDENTIFIER tOP_ASGN arg - { - $$ = new_op_asgn(p, new_call(p, $1, $3, 0), $4, $5); - } - | primary_value '.' tCONSTANT tOP_ASGN arg - { - $$ = new_op_asgn(p, new_call(p, $1, $3, 0), $4, $5); - } - | primary_value tCOLON2 tIDENTIFIER tOP_ASGN arg - { - $$ = new_op_asgn(p, new_call(p, $1, $3, 0), $4, $5); - } - | primary_value tCOLON2 tCONSTANT tOP_ASGN arg - { - yyerror(p, "constant re-assignment"); - $$ = new_begin(p, 0); - } - | tCOLON3 tCONSTANT tOP_ASGN arg - { - yyerror(p, "constant re-assignment"); - $$ = new_begin(p, 0); - } - | backref tOP_ASGN arg - { - backref_error(p, $1); - $$ = new_begin(p, 0); - } - | arg tDOT2 arg - { - $$ = new_dot2(p, $1, $3); - } - | arg tDOT3 arg - { - $$ = new_dot3(p, $1, $3); - } - | arg '+' arg - { - $$ = call_bin_op(p, $1, "+", $3); - } - | arg '-' arg - { - $$ = call_bin_op(p, $1, "-", $3); - } - | arg '*' arg - { - $$ = call_bin_op(p, $1, "*", $3); - } - | arg '/' arg - { - $$ = call_bin_op(p, $1, "/", $3); - } - | arg '%' arg - { - $$ = call_bin_op(p, $1, "%", $3); - } - | arg tPOW arg - { - $$ = call_bin_op(p, $1, "**", $3); - } - | tUMINUS_NUM tINTEGER tPOW arg - { - $$ = call_uni_op(p, call_bin_op(p, $2, "**", $4), "-@"); - } - | tUMINUS_NUM tFLOAT tPOW arg - { - $$ = call_uni_op(p, call_bin_op(p, $2, "**", $4), "-@"); - } - | tUPLUS arg - { - $$ = call_uni_op(p, $2, "+@"); - } - | tUMINUS arg - { - $$ = call_uni_op(p, $2, "-@"); - } - | arg '|' arg - { - $$ = call_bin_op(p, $1, "|", $3); - } - | arg '^' arg - { - $$ = call_bin_op(p, $1, "^", $3); - } - | arg '&' arg - { - $$ = call_bin_op(p, $1, "&", $3); - } - | arg tCMP arg - { - $$ = call_bin_op(p, $1, "<=>", $3); - } - | arg '>' arg - { - $$ = call_bin_op(p, $1, ">", $3); - } - | arg tGEQ arg - { - $$ = call_bin_op(p, $1, ">=", $3); - } - | arg '<' arg - { - $$ = call_bin_op(p, $1, "<", $3); - } - | arg tLEQ arg - { - $$ = call_bin_op(p, $1, "<=", $3); - } - | arg tEQ arg - { - $$ = call_bin_op(p, $1, "==", $3); - } - | arg tEQQ arg - { - $$ = call_bin_op(p, $1, "===", $3); - } - | arg tNEQ arg - { - $$ = call_bin_op(p, $1, "!=", $3); - } - | arg tMATCH arg - { - $$ = call_bin_op(p, $1, "=~", $3); - } - | arg tNMATCH arg - { - $$ = call_bin_op(p, $1, "!~", $3); - } - | '!' arg - { - $$ = call_uni_op(p, cond($2), "!"); - } - | '~' arg - { - $$ = call_uni_op(p, cond($2), "~"); - } - | arg tLSHFT arg - { - $$ = call_bin_op(p, $1, "<<", $3); - } - | arg tRSHFT arg - { - $$ = call_bin_op(p, $1, ">>", $3); - } - | arg tANDOP arg - { - $$ = new_and(p, $1, $3); - } - | arg tOROP arg - { - $$ = new_or(p, $1, $3); - } - | arg '?' arg opt_nl ':' arg - { - $$ = new_if(p, cond($1), $3, $6); - } - | primary - { - $$ = $1; - } - ; - -arg_value : arg - { - $$ = $1; - if (!$$) $$ = new_nil(p); - } - ; - -aref_args : none - | args trailer - { - $$ = $1; - } - | args ',' assocs trailer - { - $$ = push($1, new_hash(p, $3)); - } - | assocs trailer - { - $$ = cons(new_hash(p, $1), 0); - } - ; - -paren_args : '(' opt_call_args rparen - { - $$ = $2; - } - ; - -opt_paren_args : none - | paren_args - ; - -opt_call_args : none - | call_args - | args ',' - { - $$ = cons($1,0); - } - | args ',' assocs ',' - { - $$ = cons(push($1, new_hash(p, $3)), 0); - } - | assocs ',' - { - $$ = cons(list1(new_hash(p, $1)), 0); - } - ; - -call_args : command - { - $$ = cons(list1($1), 0); - } - | args opt_block_arg - { - $$ = cons($1, $2); - } - | assocs opt_block_arg - { - $$ = cons(list1(new_hash(p, $1)), $2); - } - | args ',' assocs opt_block_arg - { - $$ = cons(push($1, new_hash(p, $3)), $4); - } - | block_arg - { - $$ = cons(0, $1); - } - ; - -command_args : { - $<stack>$ = p->cmdarg_stack; - CMDARG_PUSH(1); - } - call_args - { - p->cmdarg_stack = $<stack>1; - $$ = $2; - } - ; - -block_arg : tAMPER arg_value - { - $$ = new_block_arg(p, $2); - } - ; - -opt_block_arg : ',' block_arg - { - $$ = $2; - } - | none - { - $$ = 0; - } - ; - -args : arg_value - { - $$ = cons($1, 0); - } - | tSTAR arg_value - { - $$ = cons(new_splat(p, $2), 0); - } - | args ',' arg_value - { - $$ = push($1, $3); - } - | args ',' tSTAR arg_value - { - $$ = push($1, new_splat(p, $4)); - } - | args ',' heredoc_bodies arg_value - { - $$ = push($1, $4); - } - | args ',' heredoc_bodies tSTAR arg_value - { - $$ = push($1, new_splat(p, $5)); - } - ; - -mrhs : args ',' arg_value - { - $$ = push($1, $3); - } - | args ',' tSTAR arg_value - { - $$ = push($1, new_splat(p, $4)); - } - | tSTAR arg_value - { - $$ = list1(new_splat(p, $2)); - } - ; - -primary : literal - | string - | xstring - | regexp - | heredoc - | var_ref - | backref - | tFID - { - $$ = new_fcall(p, $1, 0); - } - | keyword_begin - { - $<stack>1 = p->cmdarg_stack; - p->cmdarg_stack = 0; - } - bodystmt - keyword_end - { - p->cmdarg_stack = $<stack>1; - $$ = $3; - } - | tLPAREN_ARG expr {p->lstate = EXPR_ENDARG;} rparen - { - $$ = $2; - } - | tLPAREN_ARG {p->lstate = EXPR_ENDARG;} rparen - { - $$ = 0; - } - | tLPAREN compstmt ')' - { - $$ = $2; - } - | primary_value tCOLON2 tCONSTANT - { - $$ = new_colon2(p, $1, $3); - } - | tCOLON3 tCONSTANT - { - $$ = new_colon3(p, $2); - } - | tLBRACK aref_args ']' - { - $$ = new_array(p, $2); - } - | tLBRACE assoc_list '}' - { - $$ = new_hash(p, $2); - } - | keyword_return - { - $$ = new_return(p, 0); - } - | keyword_yield '(' call_args rparen - { - $$ = new_yield(p, $3); - } - | keyword_yield '(' rparen - { - $$ = new_yield(p, 0); - } - | keyword_yield - { - $$ = new_yield(p, 0); - } - | keyword_not '(' expr rparen - { - $$ = call_uni_op(p, cond($3), "!"); - } - | keyword_not '(' rparen - { - $$ = call_uni_op(p, new_nil(p), "!"); - } - | operation brace_block - { - $$ = new_fcall(p, $1, cons(0, $2)); - } - | method_call - | method_call brace_block - { - call_with_block(p, $1, $2); - $$ = $1; - } - | tLAMBDA - { - local_nest(p); - $<num>$ = p->lpar_beg; - p->lpar_beg = ++p->paren_nest; - } - f_larglist - lambda_body - { - p->lpar_beg = $<num>2; - $$ = new_lambda(p, $3, $4); - local_unnest(p); - } - | keyword_if expr_value then - compstmt - if_tail - keyword_end - { - $$ = new_if(p, cond($2), $4, $5); - } - | keyword_unless expr_value then - compstmt - opt_else - keyword_end - { - $$ = new_unless(p, cond($2), $4, $5); - } - | keyword_while {COND_PUSH(1);} expr_value do {COND_POP();} - compstmt - keyword_end - { - $$ = new_while(p, cond($3), $6); - } - | keyword_until {COND_PUSH(1);} expr_value do {COND_POP();} - compstmt - keyword_end - { - $$ = new_until(p, cond($3), $6); - } - | keyword_case expr_value opt_terms - case_body - keyword_end - { - $$ = new_case(p, $2, $4); - } - | keyword_case opt_terms case_body keyword_end - { - $$ = new_case(p, 0, $3); - } - | keyword_for for_var keyword_in - {COND_PUSH(1);} - expr_value do - {COND_POP();} - compstmt - keyword_end - { - $$ = new_for(p, $2, $5, $8); - } - | keyword_class cpath superclass - { - if (p->in_def || p->in_single) - yyerror(p, "class definition in method body"); - $<nd>$ = local_switch(p); - } - bodystmt - keyword_end - { - $$ = new_class(p, $2, $3, $5); - local_resume(p, $<nd>4); - } - | keyword_class tLSHFT expr - { - $<num>$ = p->in_def; - p->in_def = 0; - } - term - { - $<nd>$ = cons(local_switch(p), (node*)(intptr_t)p->in_single); - p->in_single = 0; - } - bodystmt - keyword_end - { - $$ = new_sclass(p, $3, $7); - local_resume(p, $<nd>6->car); - p->in_def = $<num>4; - p->in_single = (int)(intptr_t)$<nd>6->cdr; - } - | keyword_module cpath - { - if (p->in_def || p->in_single) - yyerror(p, "module definition in method body"); - $<nd>$ = local_switch(p); - } - bodystmt - keyword_end - { - $$ = new_module(p, $2, $4); - local_resume(p, $<nd>3); - } - | keyword_def fname - { - p->in_def++; - $<nd>$ = local_switch(p); - } - f_arglist - bodystmt - keyword_end - { - $$ = new_def(p, $2, $4, $5); - local_resume(p, $<nd>3); - p->in_def--; - } - | keyword_def singleton dot_or_colon {p->lstate = EXPR_FNAME;} fname - { - p->in_single++; - p->lstate = EXPR_ENDFN; /* force for args */ - $<nd>$ = local_switch(p); - } - f_arglist - bodystmt - keyword_end - { - $$ = new_sdef(p, $2, $5, $7, $8); - local_resume(p, $<nd>6); - p->in_single--; - } - | keyword_break - { - $$ = new_break(p, 0); - } - | keyword_next - { - $$ = new_next(p, 0); - } - | keyword_redo - { - $$ = new_redo(p); - } - | keyword_retry - { - $$ = new_retry(p); - } - ; - -primary_value : primary - { - $$ = $1; - if (!$$) $$ = new_nil(p); - } - ; - -then : term - | keyword_then - | term keyword_then - ; - -do : term - | keyword_do_cond - ; - -if_tail : opt_else - | keyword_elsif expr_value then - compstmt - if_tail - { - $$ = new_if(p, cond($2), $4, $5); - } - ; - -opt_else : none - | keyword_else compstmt - { - $$ = $2; - } - ; - -for_var : lhs - { - $$ = list1(list1($1)); - } - | mlhs - ; - -f_marg : f_norm_arg - { - $$ = new_arg(p, $1); - } - | tLPAREN f_margs rparen - { - $$ = new_masgn(p, $2, 0); - } - ; - -f_marg_list : f_marg - { - $$ = list1($1); - } - | f_marg_list ',' f_marg - { - $$ = push($1, $3); - } - ; - -f_margs : f_marg_list - { - $$ = list3($1,0,0); - } - | f_marg_list ',' tSTAR f_norm_arg - { - $$ = list3($1, new_arg(p, $4), 0); - } - | f_marg_list ',' tSTAR f_norm_arg ',' f_marg_list - { - $$ = list3($1, new_arg(p, $4), $6); - } - | f_marg_list ',' tSTAR - { - $$ = list3($1, (node*)-1, 0); - } - | f_marg_list ',' tSTAR ',' f_marg_list - { - $$ = list3($1, (node*)-1, $5); - } - | tSTAR f_norm_arg - { - $$ = list3(0, new_arg(p, $2), 0); - } - | tSTAR f_norm_arg ',' f_marg_list - { - $$ = list3(0, new_arg(p, $2), $4); - } - | tSTAR - { - $$ = list3(0, (node*)-1, 0); - } - | tSTAR ',' f_marg_list - { - $$ = list3(0, (node*)-1, $3); - } - ; - -block_param : f_arg ',' f_block_optarg ',' f_rest_arg opt_f_block_arg - { - $$ = new_args(p, $1, $3, $5, 0, $6); - } - | f_arg ',' f_block_optarg ',' f_rest_arg ',' f_arg opt_f_block_arg - { - $$ = new_args(p, $1, $3, $5, $7, $8); - } - | f_arg ',' f_block_optarg opt_f_block_arg - { - $$ = new_args(p, $1, $3, 0, 0, $4); - } - | f_arg ',' f_block_optarg ',' f_arg opt_f_block_arg - { - $$ = new_args(p, $1, $3, 0, $5, $6); - } - | f_arg ',' f_rest_arg opt_f_block_arg - { - $$ = new_args(p, $1, 0, $3, 0, $4); - } - | f_arg ',' - { - $$ = new_args(p, $1, 0, 1, 0, 0); - } - | f_arg ',' f_rest_arg ',' f_arg opt_f_block_arg - { - $$ = new_args(p, $1, 0, $3, $5, $6); - } - | f_arg opt_f_block_arg - { - $$ = new_args(p, $1, 0, 0, 0, $2); - } - | f_block_optarg ',' f_rest_arg opt_f_block_arg - { - $$ = new_args(p, 0, $1, $3, 0, $4); - } - | f_block_optarg ',' f_rest_arg ',' f_arg opt_f_block_arg - { - $$ = new_args(p, 0, $1, $3, $5, $6); - } - | f_block_optarg opt_f_block_arg - { - $$ = new_args(p, 0, $1, 0, 0, $2); - } - | f_block_optarg ',' f_arg opt_f_block_arg - { - $$ = new_args(p, 0, $1, 0, $3, $4); - } - | f_rest_arg opt_f_block_arg - { - $$ = new_args(p, 0, 0, $1, 0, $2); - } - | f_rest_arg ',' f_arg opt_f_block_arg - { - $$ = new_args(p, 0, 0, $1, $3, $4); - } - | f_block_arg - { - $$ = new_args(p, 0, 0, 0, 0, $1); - } - ; - -opt_block_param : none - | block_param_def - { - p->cmd_start = TRUE; - $$ = $1; - } - ; - -block_param_def : '|' opt_bv_decl '|' - { - local_add_f(p, 0); - $$ = 0; - } - | tOROP - { - local_add_f(p, 0); - $$ = 0; - } - | '|' block_param opt_bv_decl '|' - { - $$ = $2; - } - ; - - -opt_bv_decl : opt_nl - { - $$ = 0; - } - | opt_nl ';' bv_decls opt_nl - { - $$ = 0; - } - ; - -bv_decls : bvar - | bv_decls ',' bvar - ; - -bvar : tIDENTIFIER - { - local_add_f(p, $1); - new_bv(p, $1); - } - | f_bad_arg - ; - -f_larglist : '(' f_args opt_bv_decl ')' - { - $$ = $2; - } - | f_args - { - $$ = $1; - } - ; - -lambda_body : tLAMBEG compstmt '}' - { - $$ = $2; - } - | keyword_do_LAMBDA compstmt keyword_end - { - $$ = $2; - } - ; - -do_block : keyword_do_block - { - local_nest(p); - } - opt_block_param - compstmt - keyword_end - { - $$ = new_block(p,$3,$4); - local_unnest(p); - } - ; - -block_call : command do_block - { - if ($1->car == (node*)NODE_YIELD) { - yyerror(p, "block given to yield"); - } - else { - call_with_block(p, $1, $2); - } - $$ = $1; - } - | block_call dot_or_colon operation2 opt_paren_args - { - $$ = new_call(p, $1, $3, $4); - } - | block_call dot_or_colon operation2 opt_paren_args brace_block - { - $$ = new_call(p, $1, $3, $4); - call_with_block(p, $$, $5); - } - | block_call dot_or_colon operation2 command_args do_block - { - $$ = new_call(p, $1, $3, $4); - call_with_block(p, $$, $5); - } - ; - -method_call : operation paren_args - { - $$ = new_fcall(p, $1, $2); - } - | primary_value '.' operation2 opt_paren_args - { - $$ = new_call(p, $1, $3, $4); - } - | primary_value tCOLON2 operation2 paren_args - { - $$ = new_call(p, $1, $3, $4); - } - | primary_value tCOLON2 operation3 - { - $$ = new_call(p, $1, $3, 0); - } - | primary_value '.' paren_args - { - $$ = new_call(p, $1, intern2("call",4), $3); - } - | primary_value tCOLON2 paren_args - { - $$ = new_call(p, $1, intern2("call",4), $3); - } - | keyword_super paren_args - { - $$ = new_super(p, $2); - } - | keyword_super - { - $$ = new_zsuper(p); - } - | primary_value '[' opt_call_args rbracket - { - $$ = new_call(p, $1, intern2("[]",2), $3); - } - ; - -brace_block : '{' - { - local_nest(p); - } - opt_block_param - compstmt '}' - { - $$ = new_block(p,$3,$4); - local_unnest(p); - } - | keyword_do - { - local_nest(p); - } - opt_block_param - compstmt keyword_end - { - $$ = new_block(p,$3,$4); - local_unnest(p); - } - ; - -case_body : keyword_when args then - compstmt - cases - { - $$ = cons(cons($2, $4), $5); - } - ; - -cases : opt_else - { - if ($1) { - $$ = cons(cons(0, $1), 0); - } - else { - $$ = 0; - } - } - | case_body - ; - -opt_rescue : keyword_rescue exc_list exc_var then - compstmt - opt_rescue - { - $$ = list1(list3($2, $3, $5)); - if ($6) $$ = append($$, $6); - } - | none - ; - -exc_list : arg_value - { - $$ = list1($1); - } - | mrhs - | none - ; - -exc_var : tASSOC lhs - { - $$ = $2; - } - | none - ; - -opt_ensure : keyword_ensure compstmt - { - $$ = $2; - } - | none - ; - -literal : numeric - | symbol - | words - | symbols - ; - -string : tCHAR - | tSTRING - | tSTRING_BEG tSTRING - { - $$ = $2; - } - | tSTRING_BEG string_rep tSTRING - { - $$ = new_dstr(p, push($2, $3)); - } - ; +program : { + p->lstate = EXPR_BEG; + if (!p->locals) p->locals = cons(0,0); + } + top_compstmt + { + p->tree = new_scope(p, $2); + } + ; + +top_compstmt : top_stmts opt_terms + { + $$ = $1; + } + ; + +top_stmts : none + { + $$ = new_begin(p, 0); + } + | top_stmt + { + $$ = new_begin(p, $1); + } + | top_stmts terms top_stmt + { + $$ = push($1, newline_node($3)); + } + | error top_stmt + { + $$ = new_begin(p, 0); + } + ; + +top_stmt : stmt + | keyword_BEGIN + { + $<nd>$ = local_switch(p); + } + '{' top_compstmt '}' + { + yyerror(p, "BEGIN not supported"); + local_resume(p, $<nd>2); + $$ = 0; + } + ; + +bodystmt : compstmt + opt_rescue + opt_else + opt_ensure + { + if ($2) { + $$ = new_rescue(p, $1, $2, $3); + } + else if ($3) { + yywarn(p, "else without rescue is useless"); + $$ = push($1, $3); + } + else { + $$ = $1; + } + if ($4) { + if ($$) { + $$ = new_ensure(p, $$, $4); + } + else { + $$ = push($4, new_nil(p)); + } + } + } + ; + +compstmt : stmts opt_terms + { + $$ = $1; + } + ; + +stmts : none + { + $$ = new_begin(p, 0); + } + | stmt + { + $$ = new_begin(p, $1); + } + | stmts terms stmt + { + $$ = push($1, newline_node($3)); + } + | error stmt + { + $$ = new_begin(p, $2); + } + ; + +stmt : keyword_alias fsym {p->lstate = EXPR_FNAME;} fsym + { + $$ = new_alias(p, $2, $4); + } + | keyword_undef undef_list + { + $$ = $2; + } + | stmt modifier_if expr_value + { + $$ = new_if(p, cond($3), $1, 0); + } + | stmt modifier_unless expr_value + { + $$ = new_unless(p, cond($3), $1, 0); + } + | stmt modifier_while expr_value + { + $$ = new_while(p, cond($3), $1); + } + | stmt modifier_until expr_value + { + $$ = new_until(p, cond($3), $1); + } + | stmt modifier_rescue stmt + { + $$ = new_rescue(p, $1, list1(list3(0, 0, $3)), 0); + } + | keyword_END '{' compstmt '}' + { + yyerror(p, "END not suported"); + $$ = new_postexe(p, $3); + } + | command_asgn + | mlhs '=' command_call + { + $$ = new_masgn(p, $1, $3); + } + | var_lhs tOP_ASGN command_call + { + $$ = new_op_asgn(p, $1, $2, $3); + } + | primary_value '[' opt_call_args rbracket tOP_ASGN command_call + { + $$ = new_op_asgn(p, new_call(p, $1, intern("[]",2), $3), $5, $6); + } + | primary_value '.' tIDENTIFIER tOP_ASGN command_call + { + $$ = new_op_asgn(p, new_call(p, $1, $3, 0), $4, $5); + } + | primary_value '.' tCONSTANT tOP_ASGN command_call + { + $$ = new_op_asgn(p, new_call(p, $1, $3, 0), $4, $5); + } + | primary_value tCOLON2 tCONSTANT tOP_ASGN command_call + { + yyerror(p, "constant re-assignment"); + $$ = 0; + } + | primary_value tCOLON2 tIDENTIFIER tOP_ASGN command_call + { + $$ = new_op_asgn(p, new_call(p, $1, $3, 0), $4, $5); + } + | backref tOP_ASGN command_call + { + backref_error(p, $1); + $$ = new_begin(p, 0); + } + | lhs '=' mrhs + { + $$ = new_asgn(p, $1, new_array(p, $3)); + } + | mlhs '=' arg_value + { + $$ = new_masgn(p, $1, $3); + } + | mlhs '=' mrhs + { + $$ = new_masgn(p, $1, new_array(p, $3)); + } + | expr + ; + +command_asgn : lhs '=' command_call + { + $$ = new_asgn(p, $1, $3); + } + | lhs '=' command_asgn + { + $$ = new_asgn(p, $1, $3); + } + ; + + +expr : command_call + | expr keyword_and expr + { + $$ = new_and(p, $1, $3); + } + | expr keyword_or expr + { + $$ = new_or(p, $1, $3); + } + | keyword_not opt_nl expr + { + $$ = call_uni_op(p, cond($3), "!"); + } + | '!' command_call + { + $$ = call_uni_op(p, cond($2), "!"); + } + | arg + ; + +expr_value : expr + { + if (!$1) $$ = new_nil(p); + else $$ = $1; + } + ; + +command_call : command + | block_command + ; + +block_command : block_call + | block_call dot_or_colon operation2 command_args + ; + +cmd_brace_block : tLBRACE_ARG + { + local_nest(p); + } + opt_block_param + compstmt + '}' + { + $$ = new_block(p, $3, $4); + local_unnest(p); + } + ; + +command : operation command_args %prec tLOWEST + { + $$ = new_fcall(p, $1, $2); + } + | operation command_args cmd_brace_block + { + args_with_block(p, $2, $3); + $$ = new_fcall(p, $1, $2); + } + | primary_value '.' operation2 command_args %prec tLOWEST + { + $$ = new_call(p, $1, $3, $4); + } + | primary_value '.' operation2 command_args cmd_brace_block + { + args_with_block(p, $4, $5); + $$ = new_call(p, $1, $3, $4); + } + | primary_value tCOLON2 operation2 command_args %prec tLOWEST + { + $$ = new_call(p, $1, $3, $4); + } + | primary_value tCOLON2 operation2 command_args cmd_brace_block + { + args_with_block(p, $4, $5); + $$ = new_call(p, $1, $3, $4); + } + | keyword_super command_args + { + $$ = new_super(p, $2); + } + | keyword_yield command_args + { + $$ = new_yield(p, $2); + } + | keyword_return call_args + { + $$ = new_return(p, ret_args(p, $2)); + } + | keyword_break call_args + { + $$ = new_break(p, ret_args(p, $2)); + } + | keyword_next call_args + { + $$ = new_next(p, ret_args(p, $2)); + } + ; + +mlhs : mlhs_basic + { + $$ = $1; + } + | tLPAREN mlhs_inner rparen + { + $$ = $2; + } + ; + +mlhs_inner : mlhs_basic + | tLPAREN mlhs_inner rparen + { + $$ = list1($2); + } + ; + +mlhs_basic : mlhs_list + { + $$ = list1($1); + } + | mlhs_list mlhs_item + { + $$ = list1(push($1,$2)); + } + | mlhs_list tSTAR mlhs_node + { + $$ = list2($1, $3); + } + | mlhs_list tSTAR mlhs_node ',' mlhs_post + { + $$ = list3($1, $3, $5); + } + | mlhs_list tSTAR + { + $$ = list2($1, new_nil(p)); + } + | mlhs_list tSTAR ',' mlhs_post + { + $$ = list3($1, new_nil(p), $4); + } + | tSTAR mlhs_node + { + $$ = list2(0, $2); + } + | tSTAR mlhs_node ',' mlhs_post + { + $$ = list3(0, $2, $4); + } + | tSTAR + { + $$ = list2(0, new_nil(p)); + } + | tSTAR ',' mlhs_post + { + $$ = list3(0, new_nil(p), $3); + } + ; + +mlhs_item : mlhs_node + | tLPAREN mlhs_inner rparen + { + $$ = $2; + } + ; + +mlhs_list : mlhs_item ',' + { + $$ = list1($1); + } + | mlhs_list mlhs_item ',' + { + $$ = push($1, $2); + } + ; + +mlhs_post : mlhs_item + { + $$ = list1($1); + } + | mlhs_list mlhs_item + { + $$ = push($1, $2); + } + ; + +mlhs_node : variable + { + assignable(p, $1); + } + | primary_value '[' opt_call_args rbracket + { + $$ = new_call(p, $1, intern("[]",2), $3); + } + | primary_value '.' tIDENTIFIER + { + $$ = new_call(p, $1, $3, 0); + } + | primary_value tCOLON2 tIDENTIFIER + { + $$ = new_call(p, $1, $3, 0); + } + | primary_value '.' tCONSTANT + { + $$ = new_call(p, $1, $3, 0); + } + | primary_value tCOLON2 tCONSTANT + { + if (p->in_def || p->in_single) + yyerror(p, "dynamic constant assignment"); + $$ = new_colon2(p, $1, $3); + } + | tCOLON3 tCONSTANT + { + if (p->in_def || p->in_single) + yyerror(p, "dynamic constant assignment"); + $$ = new_colon3(p, $2); + } + | backref + { + backref_error(p, $1); + $$ = 0; + } + ; + +lhs : variable + { + assignable(p, $1); + } + | primary_value '[' opt_call_args rbracket + { + $$ = new_call(p, $1, intern("[]",2), $3); + } + | primary_value '.' tIDENTIFIER + { + $$ = new_call(p, $1, $3, 0); + } + | primary_value tCOLON2 tIDENTIFIER + { + $$ = new_call(p, $1, $3, 0); + } + | primary_value '.' tCONSTANT + { + $$ = new_call(p, $1, $3, 0); + } + | primary_value tCOLON2 tCONSTANT + { + if (p->in_def || p->in_single) + yyerror(p, "dynamic constant assignment"); + $$ = new_colon2(p, $1, $3); + } + | tCOLON3 tCONSTANT + { + if (p->in_def || p->in_single) + yyerror(p, "dynamic constant assignment"); + $$ = new_colon3(p, $2); + } + | backref + { + backref_error(p, $1); + $$ = 0; + } + ; + +cname : tIDENTIFIER + { + yyerror(p, "class/module name must be CONSTANT"); + } + | tCONSTANT + ; + +cpath : tCOLON3 cname + { + $$ = cons((node*)1, nsym($2)); + } + | cname + { + $$ = cons((node*)0, nsym($1)); + } + | primary_value tCOLON2 cname + { + $$ = cons($1, nsym($3)); + } + ; + +fname : tIDENTIFIER + | tCONSTANT + | tFID + | op + { + p->lstate = EXPR_ENDFN; + $$ = $1; + } + | reswords + { + p->lstate = EXPR_ENDFN; + $$ = $<id>1; + } + ; + +fsym : fname + | basic_symbol + ; + +undef_list : fsym + { + $$ = new_undef(p, $1); + } + | undef_list ',' {p->lstate = EXPR_FNAME;} fsym + { + $$ = push($1, nsym($4)); + } + ; + +op : '|' { $$ = intern_c('|'); } + | '^' { $$ = intern_c('^'); } + | '&' { $$ = intern_c('&'); } + | tCMP { $$ = intern("<=>",3); } + | tEQ { $$ = intern("==",2); } + | tEQQ { $$ = intern("===",3); } + | tMATCH { $$ = intern("=~",2); } + | tNMATCH { $$ = intern("!~",2); } + | '>' { $$ = intern_c('>'); } + | tGEQ { $$ = intern(">=",2); } + | '<' { $$ = intern_c('<'); } + | tLEQ { $$ = intern("<=",2); } + | tNEQ { $$ = intern("!=",2); } + | tLSHFT { $$ = intern("<<",2); } + | tRSHFT { $$ = intern(">>",2); } + | '+' { $$ = intern_c('+'); } + | '-' { $$ = intern_c('-'); } + | '*' { $$ = intern_c('*'); } + | tSTAR { $$ = intern_c('*'); } + | '/' { $$ = intern_c('/'); } + | '%' { $$ = intern_c('%'); } + | tPOW { $$ = intern("**",2); } + | '!' { $$ = intern_c('!'); } + | '~' { $$ = intern_c('~'); } + | tUPLUS { $$ = intern("+@",2); } + | tUMINUS { $$ = intern("-@",2); } + | tAREF { $$ = intern("[]",2); } + | tASET { $$ = intern("[]=",3); } + | '`' { $$ = intern_c('`'); } + ; + +reswords : keyword__LINE__ | keyword__FILE__ | keyword__ENCODING__ + | keyword_BEGIN | keyword_END + | keyword_alias | keyword_and | keyword_begin + | keyword_break | keyword_case | keyword_class | keyword_def + | keyword_do | keyword_else | keyword_elsif + | keyword_end | keyword_ensure | keyword_false + | keyword_for | keyword_in | keyword_module | keyword_next + | keyword_nil | keyword_not | keyword_or | keyword_redo + | keyword_rescue | keyword_retry | keyword_return | keyword_self + | keyword_super | keyword_then | keyword_true | keyword_undef + | keyword_when | keyword_yield | keyword_if | keyword_unless + | keyword_while | keyword_until + ; + +arg : lhs '=' arg + { + $$ = new_asgn(p, $1, $3); + } + | lhs '=' arg modifier_rescue arg + { + $$ = new_asgn(p, $1, new_rescue(p, $3, list1(list3(0, 0, $5)), 0)); + } + | var_lhs tOP_ASGN arg + { + $$ = new_op_asgn(p, $1, $2, $3); + } + | var_lhs tOP_ASGN arg modifier_rescue arg + { + $$ = new_op_asgn(p, $1, $2, new_rescue(p, $3, list1(list3(0, 0, $5)), 0)); + } + | primary_value '[' opt_call_args rbracket tOP_ASGN arg + { + $$ = new_op_asgn(p, new_call(p, $1, intern("[]",2), $3), $5, $6); + } + | primary_value '.' tIDENTIFIER tOP_ASGN arg + { + $$ = new_op_asgn(p, new_call(p, $1, $3, 0), $4, $5); + } + | primary_value '.' tCONSTANT tOP_ASGN arg + { + $$ = new_op_asgn(p, new_call(p, $1, $3, 0), $4, $5); + } + | primary_value tCOLON2 tIDENTIFIER tOP_ASGN arg + { + $$ = new_op_asgn(p, new_call(p, $1, $3, 0), $4, $5); + } + | primary_value tCOLON2 tCONSTANT tOP_ASGN arg + { + yyerror(p, "constant re-assignment"); + $$ = new_begin(p, 0); + } + | tCOLON3 tCONSTANT tOP_ASGN arg + { + yyerror(p, "constant re-assignment"); + $$ = new_begin(p, 0); + } + | backref tOP_ASGN arg + { + backref_error(p, $1); + $$ = new_begin(p, 0); + } + | arg tDOT2 arg + { + $$ = new_dot2(p, $1, $3); + } + | arg tDOT3 arg + { + $$ = new_dot3(p, $1, $3); + } + | arg '+' arg + { + $$ = call_bin_op(p, $1, "+", $3); + } + | arg '-' arg + { + $$ = call_bin_op(p, $1, "-", $3); + } + | arg '*' arg + { + $$ = call_bin_op(p, $1, "*", $3); + } + | arg '/' arg + { + $$ = call_bin_op(p, $1, "/", $3); + } + | arg '%' arg + { + $$ = call_bin_op(p, $1, "%", $3); + } + | arg tPOW arg + { + $$ = call_bin_op(p, $1, "**", $3); + } + | tUMINUS_NUM tINTEGER tPOW arg + { + $$ = call_uni_op(p, call_bin_op(p, $2, "**", $4), "-@"); + } + | tUMINUS_NUM tFLOAT tPOW arg + { + $$ = call_uni_op(p, call_bin_op(p, $2, "**", $4), "-@"); + } + | tUPLUS arg + { + $$ = call_uni_op(p, $2, "+@"); + } + | tUMINUS arg + { + $$ = call_uni_op(p, $2, "-@"); + } + | arg '|' arg + { + $$ = call_bin_op(p, $1, "|", $3); + } + | arg '^' arg + { + $$ = call_bin_op(p, $1, "^", $3); + } + | arg '&' arg + { + $$ = call_bin_op(p, $1, "&", $3); + } + | arg tCMP arg + { + $$ = call_bin_op(p, $1, "<=>", $3); + } + | arg '>' arg + { + $$ = call_bin_op(p, $1, ">", $3); + } + | arg tGEQ arg + { + $$ = call_bin_op(p, $1, ">=", $3); + } + | arg '<' arg + { + $$ = call_bin_op(p, $1, "<", $3); + } + | arg tLEQ arg + { + $$ = call_bin_op(p, $1, "<=", $3); + } + | arg tEQ arg + { + $$ = call_bin_op(p, $1, "==", $3); + } + | arg tEQQ arg + { + $$ = call_bin_op(p, $1, "===", $3); + } + | arg tNEQ arg + { + $$ = call_bin_op(p, $1, "!=", $3); + } + | arg tMATCH arg + { + $$ = call_bin_op(p, $1, "=~", $3); + } + | arg tNMATCH arg + { + $$ = call_bin_op(p, $1, "!~", $3); + } + | '!' arg + { + $$ = call_uni_op(p, cond($2), "!"); + } + | '~' arg + { + $$ = call_uni_op(p, cond($2), "~"); + } + | arg tLSHFT arg + { + $$ = call_bin_op(p, $1, "<<", $3); + } + | arg tRSHFT arg + { + $$ = call_bin_op(p, $1, ">>", $3); + } + | arg tANDOP arg + { + $$ = new_and(p, $1, $3); + } + | arg tOROP arg + { + $$ = new_or(p, $1, $3); + } + | arg '?' arg opt_nl ':' arg + { + $$ = new_if(p, cond($1), $3, $6); + } + | primary + { + $$ = $1; + } + ; + +arg_value : arg + { + $$ = $1; + if (!$$) $$ = new_nil(p); + } + ; + +aref_args : none + | args trailer + { + $$ = $1; + } + | args ',' assocs trailer + { + $$ = push($1, new_hash(p, $3)); + } + | assocs trailer + { + $$ = cons(new_hash(p, $1), 0); + } + ; + +paren_args : '(' opt_call_args rparen + { + $$ = $2; + } + ; + +opt_paren_args : none + | paren_args + ; + +opt_call_args : none + | call_args + | args ',' + { + $$ = cons($1,0); + } + | args ',' assocs ',' + { + $$ = cons(push($1, new_hash(p, $3)), 0); + } + | assocs ',' + { + $$ = cons(list1(new_hash(p, $1)), 0); + } + ; + +call_args : command + { + $$ = cons(list1($1), 0); + } + | args opt_block_arg + { + $$ = cons($1, $2); + } + | assocs opt_block_arg + { + $$ = cons(list1(new_hash(p, $1)), $2); + } + | args ',' assocs opt_block_arg + { + $$ = cons(push($1, new_hash(p, $3)), $4); + } + | block_arg + { + $$ = cons(0, $1); + } + ; + +command_args : { + $<stack>$ = p->cmdarg_stack; + CMDARG_PUSH(1); + } + call_args + { + p->cmdarg_stack = $<stack>1; + $$ = $2; + } + ; + +block_arg : tAMPER arg_value + { + $$ = new_block_arg(p, $2); + } + ; + +opt_block_arg : ',' block_arg + { + $$ = $2; + } + | none + { + $$ = 0; + } + ; + +args : arg_value + { + $$ = cons($1, 0); + } + | tSTAR arg_value + { + $$ = cons(new_splat(p, $2), 0); + } + | args ',' arg_value + { + $$ = push($1, $3); + } + | args ',' tSTAR arg_value + { + $$ = push($1, new_splat(p, $4)); + } + | args ',' heredoc_bodies arg_value + { + $$ = push($1, $4); + } + | args ',' heredoc_bodies tSTAR arg_value + { + $$ = push($1, new_splat(p, $5)); + } + ; + +mrhs : args ',' arg_value + { + $$ = push($1, $3); + } + | args ',' tSTAR arg_value + { + $$ = push($1, new_splat(p, $4)); + } + | tSTAR arg_value + { + $$ = list1(new_splat(p, $2)); + } + ; + +primary : literal + | string + | xstring + | regexp + | heredoc + | var_ref + | backref + | tFID + { + $$ = new_fcall(p, $1, 0); + } + | keyword_begin + { + $<stack>1 = p->cmdarg_stack; + p->cmdarg_stack = 0; + } + bodystmt + keyword_end + { + p->cmdarg_stack = $<stack>1; + $$ = $3; + } + | tLPAREN_ARG expr {p->lstate = EXPR_ENDARG;} rparen + { + $$ = $2; + } + | tLPAREN_ARG {p->lstate = EXPR_ENDARG;} rparen + { + $$ = 0; + } + | tLPAREN compstmt ')' + { + $$ = $2; + } + | primary_value tCOLON2 tCONSTANT + { + $$ = new_colon2(p, $1, $3); + } + | tCOLON3 tCONSTANT + { + $$ = new_colon3(p, $2); + } + | tLBRACK aref_args ']' + { + $$ = new_array(p, $2); + } + | tLBRACE assoc_list '}' + { + $$ = new_hash(p, $2); + } + | keyword_return + { + $$ = new_return(p, 0); + } + | keyword_yield '(' call_args rparen + { + $$ = new_yield(p, $3); + } + | keyword_yield '(' rparen + { + $$ = new_yield(p, 0); + } + | keyword_yield + { + $$ = new_yield(p, 0); + } + | keyword_not '(' expr rparen + { + $$ = call_uni_op(p, cond($3), "!"); + } + | keyword_not '(' rparen + { + $$ = call_uni_op(p, new_nil(p), "!"); + } + | operation brace_block + { + $$ = new_fcall(p, $1, cons(0, $2)); + } + | method_call + | method_call brace_block + { + call_with_block(p, $1, $2); + $$ = $1; + } + | tLAMBDA + { + local_nest(p); + $<num>$ = p->lpar_beg; + p->lpar_beg = ++p->paren_nest; + } + f_larglist + lambda_body + { + p->lpar_beg = $<num>2; + $$ = new_lambda(p, $3, $4); + local_unnest(p); + } + | keyword_if expr_value then + compstmt + if_tail + keyword_end + { + $$ = new_if(p, cond($2), $4, $5); + } + | keyword_unless expr_value then + compstmt + opt_else + keyword_end + { + $$ = new_unless(p, cond($2), $4, $5); + } + | keyword_while {COND_PUSH(1);} expr_value do {COND_POP();} + compstmt + keyword_end + { + $$ = new_while(p, cond($3), $6); + } + | keyword_until {COND_PUSH(1);} expr_value do {COND_POP();} + compstmt + keyword_end + { + $$ = new_until(p, cond($3), $6); + } + | keyword_case expr_value opt_terms + case_body + keyword_end + { + $$ = new_case(p, $2, $4); + } + | keyword_case opt_terms case_body keyword_end + { + $$ = new_case(p, 0, $3); + } + | keyword_for for_var keyword_in + {COND_PUSH(1);} + expr_value do + {COND_POP();} + compstmt + keyword_end + { + $$ = new_for(p, $2, $5, $8); + } + | keyword_class + { + $<num>$ = p->lineno; + } + cpath superclass + { + if (p->in_def || p->in_single) + yyerror(p, "class definition in method body"); + $<nd>$ = local_switch(p); + } + bodystmt + keyword_end + { + $$ = new_class(p, $3, $4, $6); + SET_LINENO($$, $<num>2); + local_resume(p, $<nd>5); + } + | keyword_class + { + $<num>$ = p->lineno; + } + tLSHFT expr + { + $<num>$ = p->in_def; + p->in_def = 0; + } + term + { + $<nd>$ = cons(local_switch(p), (node*)(intptr_t)p->in_single); + p->in_single = 0; + } + bodystmt + keyword_end + { + $$ = new_sclass(p, $4, $8); + SET_LINENO($$, $<num>2); + local_resume(p, $<nd>7->car); + p->in_def = $<num>5; + p->in_single = (int)(intptr_t)$<nd>7->cdr; + } + | keyword_module + { + $<num>$ = p->lineno; + } + cpath + { + if (p->in_def || p->in_single) + yyerror(p, "module definition in method body"); + $<nd>$ = local_switch(p); + } + bodystmt + keyword_end + { + $$ = new_module(p, $3, $5); + SET_LINENO($$, $<num>2); + local_resume(p, $<nd>4); + } + | keyword_def fname + { + p->in_def++; + $<nd>$ = local_switch(p); + } + f_arglist + bodystmt + keyword_end + { + $$ = new_def(p, $2, $4, $5); + local_resume(p, $<nd>3); + p->in_def--; + } + | keyword_def singleton dot_or_colon {p->lstate = EXPR_FNAME;} fname + { + p->in_single++; + p->lstate = EXPR_ENDFN; /* force for args */ + $<nd>$ = local_switch(p); + } + f_arglist + bodystmt + keyword_end + { + $$ = new_sdef(p, $2, $5, $7, $8); + local_resume(p, $<nd>6); + p->in_single--; + } + | keyword_break + { + $$ = new_break(p, 0); + } + | keyword_next + { + $$ = new_next(p, 0); + } + | keyword_redo + { + $$ = new_redo(p); + } + | keyword_retry + { + $$ = new_retry(p); + } + ; + +primary_value : primary + { + $$ = $1; + if (!$$) $$ = new_nil(p); + } + ; + +then : term + | keyword_then + | term keyword_then + ; + +do : term + | keyword_do_cond + ; + +if_tail : opt_else + | keyword_elsif expr_value then + compstmt + if_tail + { + $$ = new_if(p, cond($2), $4, $5); + } + ; + +opt_else : none + | keyword_else compstmt + { + $$ = $2; + } + ; + +for_var : lhs + { + $$ = list1(list1($1)); + } + | mlhs + ; + +f_marg : f_norm_arg + { + $$ = new_arg(p, $1); + } + | tLPAREN f_margs rparen + { + $$ = new_masgn(p, $2, 0); + } + ; + +f_marg_list : f_marg + { + $$ = list1($1); + } + | f_marg_list ',' f_marg + { + $$ = push($1, $3); + } + ; + +f_margs : f_marg_list + { + $$ = list3($1,0,0); + } + | f_marg_list ',' tSTAR f_norm_arg + { + $$ = list3($1, new_arg(p, $4), 0); + } + | f_marg_list ',' tSTAR f_norm_arg ',' f_marg_list + { + $$ = list3($1, new_arg(p, $4), $6); + } + | f_marg_list ',' tSTAR + { + $$ = list3($1, (node*)-1, 0); + } + | f_marg_list ',' tSTAR ',' f_marg_list + { + $$ = list3($1, (node*)-1, $5); + } + | tSTAR f_norm_arg + { + $$ = list3(0, new_arg(p, $2), 0); + } + | tSTAR f_norm_arg ',' f_marg_list + { + $$ = list3(0, new_arg(p, $2), $4); + } + | tSTAR + { + $$ = list3(0, (node*)-1, 0); + } + | tSTAR ',' f_marg_list + { + $$ = list3(0, (node*)-1, $3); + } + ; + +block_param : f_arg ',' f_block_optarg ',' f_rest_arg opt_f_block_arg + { + $$ = new_args(p, $1, $3, $5, 0, $6); + } + | f_arg ',' f_block_optarg ',' f_rest_arg ',' f_arg opt_f_block_arg + { + $$ = new_args(p, $1, $3, $5, $7, $8); + } + | f_arg ',' f_block_optarg opt_f_block_arg + { + $$ = new_args(p, $1, $3, 0, 0, $4); + } + | f_arg ',' f_block_optarg ',' f_arg opt_f_block_arg + { + $$ = new_args(p, $1, $3, 0, $5, $6); + } + | f_arg ',' f_rest_arg opt_f_block_arg + { + $$ = new_args(p, $1, 0, $3, 0, $4); + } + | f_arg ',' + { + $$ = new_args(p, $1, 0, 1, 0, 0); + } + | f_arg ',' f_rest_arg ',' f_arg opt_f_block_arg + { + $$ = new_args(p, $1, 0, $3, $5, $6); + } + | f_arg opt_f_block_arg + { + $$ = new_args(p, $1, 0, 0, 0, $2); + } + | f_block_optarg ',' f_rest_arg opt_f_block_arg + { + $$ = new_args(p, 0, $1, $3, 0, $4); + } + | f_block_optarg ',' f_rest_arg ',' f_arg opt_f_block_arg + { + $$ = new_args(p, 0, $1, $3, $5, $6); + } + | f_block_optarg opt_f_block_arg + { + $$ = new_args(p, 0, $1, 0, 0, $2); + } + | f_block_optarg ',' f_arg opt_f_block_arg + { + $$ = new_args(p, 0, $1, 0, $3, $4); + } + | f_rest_arg opt_f_block_arg + { + $$ = new_args(p, 0, 0, $1, 0, $2); + } + | f_rest_arg ',' f_arg opt_f_block_arg + { + $$ = new_args(p, 0, 0, $1, $3, $4); + } + | f_block_arg + { + $$ = new_args(p, 0, 0, 0, 0, $1); + } + ; + +opt_block_param : none + | block_param_def + { + p->cmd_start = TRUE; + $$ = $1; + } + ; + +block_param_def : '|' opt_bv_decl '|' + { + local_add_f(p, 0); + $$ = 0; + } + | tOROP + { + local_add_f(p, 0); + $$ = 0; + } + | '|' block_param opt_bv_decl '|' + { + $$ = $2; + } + ; + + +opt_bv_decl : opt_nl + { + $$ = 0; + } + | opt_nl ';' bv_decls opt_nl + { + $$ = 0; + } + ; + +bv_decls : bvar + | bv_decls ',' bvar + ; + +bvar : tIDENTIFIER + { + local_add_f(p, $1); + new_bv(p, $1); + } + | f_bad_arg + ; + +f_larglist : '(' f_args opt_bv_decl ')' + { + $$ = $2; + } + | f_args + { + $$ = $1; + } + ; + +lambda_body : tLAMBEG compstmt '}' + { + $$ = $2; + } + | keyword_do_LAMBDA compstmt keyword_end + { + $$ = $2; + } + ; + +do_block : keyword_do_block + { + local_nest(p); + } + opt_block_param + compstmt + keyword_end + { + $$ = new_block(p,$3,$4); + local_unnest(p); + } + ; + +block_call : command do_block + { + if ($1->car == (node*)NODE_YIELD) { + yyerror(p, "block given to yield"); + } + else { + call_with_block(p, $1, $2); + } + $$ = $1; + } + | block_call dot_or_colon operation2 opt_paren_args + { + $$ = new_call(p, $1, $3, $4); + } + | block_call dot_or_colon operation2 opt_paren_args brace_block + { + $$ = new_call(p, $1, $3, $4); + call_with_block(p, $$, $5); + } + | block_call dot_or_colon operation2 command_args do_block + { + $$ = new_call(p, $1, $3, $4); + call_with_block(p, $$, $5); + } + ; + +method_call : operation paren_args + { + $$ = new_fcall(p, $1, $2); + } + | primary_value '.' operation2 opt_paren_args + { + $$ = new_call(p, $1, $3, $4); + } + | primary_value tCOLON2 operation2 paren_args + { + $$ = new_call(p, $1, $3, $4); + } + | primary_value tCOLON2 operation3 + { + $$ = new_call(p, $1, $3, 0); + } + | primary_value '.' paren_args + { + $$ = new_call(p, $1, intern("call",4), $3); + } + | primary_value tCOLON2 paren_args + { + $$ = new_call(p, $1, intern("call",4), $3); + } + | keyword_super paren_args + { + $$ = new_super(p, $2); + } + | keyword_super + { + $$ = new_zsuper(p); + } + | primary_value '[' opt_call_args rbracket + { + $$ = new_call(p, $1, intern("[]",2), $3); + } + ; + +brace_block : '{' + { + local_nest(p); + $<num>$ = p->lineno; + } + opt_block_param + compstmt '}' + { + $$ = new_block(p,$3,$4); + SET_LINENO($$, $<num>2); + local_unnest(p); + } + | keyword_do + { + local_nest(p); + $<num>$ = p->lineno; + } + opt_block_param + compstmt keyword_end + { + $$ = new_block(p,$3,$4); + SET_LINENO($$, $<num>2); + local_unnest(p); + } + ; + +case_body : keyword_when args then + compstmt + cases + { + $$ = cons(cons($2, $4), $5); + } + ; + +cases : opt_else + { + if ($1) { + $$ = cons(cons(0, $1), 0); + } + else { + $$ = 0; + } + } + | case_body + ; + +opt_rescue : keyword_rescue exc_list exc_var then + compstmt + opt_rescue + { + $$ = list1(list3($2, $3, $5)); + if ($6) $$ = append($$, $6); + } + | none + ; + +exc_list : arg_value + { + $$ = list1($1); + } + | mrhs + | none + ; + +exc_var : tASSOC lhs + { + $$ = $2; + } + | none + ; + +opt_ensure : keyword_ensure compstmt + { + $$ = $2; + } + | none + ; + +literal : numeric + | symbol + | words + | symbols + ; + +string : tCHAR + | tSTRING + | tSTRING_BEG tSTRING + { + $$ = $2; + } + | tSTRING_BEG string_rep tSTRING + { + $$ = new_dstr(p, push($2, $3)); + } + ; string_rep : string_interp - | string_rep string_interp - { - $$ = append($1, $2); - } - ; - -string_interp : tSTRING_MID - { - $$ = list1($1); - } - | tSTRING_PART - { - $<nd>$ = p->lex_strterm; - p->lex_strterm = NULL; - } - compstmt - '}' - { - p->lex_strterm = $<nd>2; - $$ = list2($1, $3); - } - | tLITERAL_DELIM - { - $$ = list1(new_literal_delim(p)); - } - | tHD_LITERAL_DELIM heredoc_bodies - { - $$ = list1(new_literal_delim(p)); - } - ; - -xstring : tXSTRING_BEG tXSTRING - { - $$ = $2; - } - | tXSTRING_BEG string_rep tXSTRING - { - $$ = new_dxstr(p, push($2, $3)); - } - ; - -regexp : tREGEXP_BEG tREGEXP - { - $$ = $2; - } - | tREGEXP_BEG string_rep tREGEXP - { - $$ = new_dregx(p, $2, $3); - } - ; - -heredoc : tHEREDOC_BEG - ; + | string_rep string_interp + { + $$ = append($1, $2); + } + ; + +string_interp : tSTRING_MID + { + $$ = list1($1); + } + | tSTRING_PART + { + $<nd>$ = p->lex_strterm; + p->lex_strterm = NULL; + } + compstmt + '}' + { + p->lex_strterm = $<nd>2; + $$ = list2($1, $3); + } + | tLITERAL_DELIM + { + $$ = list1(new_literal_delim(p)); + } + | tHD_LITERAL_DELIM heredoc_bodies + { + $$ = list1(new_literal_delim(p)); + } + ; + +xstring : tXSTRING_BEG tXSTRING + { + $$ = $2; + } + | tXSTRING_BEG string_rep tXSTRING + { + $$ = new_dxstr(p, push($2, $3)); + } + ; + +regexp : tREGEXP_BEG tREGEXP + { + $$ = $2; + } + | tREGEXP_BEG string_rep tREGEXP + { + $$ = new_dregx(p, $2, $3); + } + ; + +heredoc : tHEREDOC_BEG + ; opt_heredoc_bodies : /* none */ - | heredoc_bodies - ; - -heredoc_bodies : heredoc_body - | heredoc_bodies heredoc_body - ; - -heredoc_body : tHEREDOC_END - { - parser_heredoc_info * inf = parsing_heredoc_inf(p); - inf->doc = push(inf->doc, new_str(p, "", 0)); - heredoc_end(p); - } - | heredoc_string_rep tHEREDOC_END - { - heredoc_end(p); - } - ; + | heredoc_bodies + ; + +heredoc_bodies : heredoc_body + | heredoc_bodies heredoc_body + ; + +heredoc_body : tHEREDOC_END + { + parser_heredoc_info * inf = parsing_heredoc_inf(p); + inf->doc = push(inf->doc, new_str(p, "", 0)); + heredoc_end(p); + } + | heredoc_string_rep tHEREDOC_END + { + heredoc_end(p); + } + ; heredoc_string_rep : heredoc_string_interp - | heredoc_string_rep heredoc_string_interp - ; + | heredoc_string_rep heredoc_string_interp + ; heredoc_string_interp : tHD_STRING_MID - { - parser_heredoc_info * inf = parsing_heredoc_inf(p); - inf->doc = push(inf->doc, $1); - heredoc_treat_nextline(p); - } - | tHD_STRING_PART - { - $<nd>$ = p->lex_strterm; - p->lex_strterm = NULL; - } - compstmt - '}' - { - parser_heredoc_info * inf = parsing_heredoc_inf(p); - p->lex_strterm = $<nd>2; - inf->doc = push(push(inf->doc, $1), $3); - } - ; - -words : tWORDS_BEG tSTRING - { - $$ = new_words(p, list1($2)); - } - | tWORDS_BEG string_rep tSTRING - { - $$ = new_words(p, push($2, $3)); - } - ; - - -symbol : basic_symbol - { - $$ = new_sym(p, $1); - } - | tSYMBEG tSTRING_BEG string_interp tSTRING - { - p->lstate = EXPR_END; - $$ = new_dsym(p, push($3, $4)); - } - ; - -basic_symbol : tSYMBEG sym - { - p->lstate = EXPR_END; - $$ = $2; - } - ; - -sym : fname - | tIVAR - | tGVAR - | tCVAR - | tSTRING - { - $$ = new_strsym(p, $1); - } - | tSTRING_BEG tSTRING - { - $$ = new_strsym(p, $2); - } - ; - -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 - { - $$ = negate_lit(p, $2); - } - | tUMINUS_NUM tFLOAT %prec tLOWEST - { - $$ = negate_lit(p, $2); - } - ; - -variable : tIDENTIFIER - { - $$ = new_lvar(p, $1); - } - | tIVAR - { - $$ = new_ivar(p, $1); - } - | tGVAR - { - $$ = new_gvar(p, $1); - } - | tCVAR - { - $$ = new_cvar(p, $1); - } - | tCONSTANT - { - $$ = new_const(p, $1); - } - ; - -var_lhs : variable - { - assignable(p, $1); - } - ; - -var_ref : variable - { - $$ = var_reference(p, $1); - } - | keyword_nil - { - $$ = new_nil(p); - } - | keyword_self - { - $$ = new_self(p); - } - | keyword_true - { - $$ = new_true(p); - } - | keyword_false - { - $$ = new_false(p); - } - | keyword__FILE__ - { - if (!p->filename) { - p->filename = "(null)"; - } - $$ = new_str(p, p->filename, strlen(p->filename)); - } - | keyword__LINE__ - { - char buf[16]; - - snprintf(buf, sizeof(buf), "%d", p->lineno); - $$ = new_int(p, buf, 10); - } - ; - -backref : tNTH_REF - | tBACK_REF - ; - -superclass : term - { - $$ = 0; - } - | '<' - { - p->lstate = EXPR_BEG; - p->cmd_start = TRUE; - } - expr_value term - { - $$ = $3; - } - | error term - { - yyerrok; - $$ = 0; - } - ; - -f_arglist : '(' f_args rparen - { - $$ = $2; - p->lstate = EXPR_BEG; - p->cmd_start = TRUE; - } - | f_args term - { - $$ = $1; - } - ; - -f_args : f_arg ',' f_optarg ',' f_rest_arg opt_f_block_arg - { - $$ = new_args(p, $1, $3, $5, 0, $6); - } - | f_arg ',' f_optarg ',' f_rest_arg ',' f_arg opt_f_block_arg - { - $$ = new_args(p, $1, $3, $5, $7, $8); - } - | f_arg ',' f_optarg opt_f_block_arg - { - $$ = new_args(p, $1, $3, 0, 0, $4); - } - | f_arg ',' f_optarg ',' f_arg opt_f_block_arg - { - $$ = new_args(p, $1, $3, 0, $5, $6); - } - | f_arg ',' f_rest_arg opt_f_block_arg - { - $$ = new_args(p, $1, 0, $3, 0, $4); - } - | f_arg ',' f_rest_arg ',' f_arg opt_f_block_arg - { - $$ = new_args(p, $1, 0, $3, $5, $6); - } - | f_arg opt_f_block_arg - { - $$ = new_args(p, $1, 0, 0, 0, $2); - } - | f_optarg ',' f_rest_arg opt_f_block_arg - { - $$ = new_args(p, 0, $1, $3, 0, $4); - } - | f_optarg ',' f_rest_arg ',' f_arg opt_f_block_arg - { - $$ = new_args(p, 0, $1, $3, $5, $6); - } - | f_optarg opt_f_block_arg - { - $$ = new_args(p, 0, $1, 0, 0, $2); - } - | f_optarg ',' f_arg opt_f_block_arg - { - $$ = new_args(p, 0, $1, 0, $3, $4); - } - | f_rest_arg opt_f_block_arg - { - $$ = new_args(p, 0, 0, $1, 0, $2); - } - | f_rest_arg ',' f_arg opt_f_block_arg - { - $$ = new_args(p, 0, 0, $1, $3, $4); - } - | f_block_arg - { - $$ = new_args(p, 0, 0, 0, 0, $1); - } - | /* none */ - { - local_add_f(p, 0); - $$ = new_args(p, 0, 0, 0, 0, 0); - } - ; - -f_bad_arg : tCONSTANT - { - yyerror(p, "formal argument cannot be a constant"); - $$ = 0; - } - | tIVAR - { - yyerror(p, "formal argument cannot be an instance variable"); - $$ = 0; - } - | tGVAR - { - yyerror(p, "formal argument cannot be a global variable"); - $$ = 0; - } - | tCVAR - { - yyerror(p, "formal argument cannot be a class variable"); - $$ = 0; - } - ; - -f_norm_arg : f_bad_arg - { - $$ = 0; - } - | tIDENTIFIER - { - local_add_f(p, $1); - $$ = $1; - } - ; - -f_arg_item : f_norm_arg - { - $$ = new_arg(p, $1); - } - | tLPAREN f_margs rparen - { - $$ = new_masgn(p, $2, 0); - } - ; - -f_arg : f_arg_item - { - $$ = list1($1); - } - | f_arg ',' f_arg_item - { - $$ = push($1, $3); - } - ; - -f_opt : tIDENTIFIER '=' arg_value - { - local_add_f(p, $1); - $$ = cons(nsym($1), $3); - } - ; - -f_block_opt : tIDENTIFIER '=' primary_value - { - local_add_f(p, $1); - $$ = cons(nsym($1), $3); - } - ; - -f_block_optarg : f_block_opt - { - $$ = list1($1); - } - | f_block_optarg ',' f_block_opt - { - $$ = push($1, $3); - } - ; - -f_optarg : f_opt - { - $$ = list1($1); - } - | f_optarg ',' f_opt - { - $$ = push($1, $3); - } - ; - -restarg_mark : '*' - | tSTAR - ; - -f_rest_arg : restarg_mark tIDENTIFIER - { - local_add_f(p, $2); - $$ = $2; - } - | restarg_mark - { - local_add_f(p, 0); - $$ = -1; - } - ; - -blkarg_mark : '&' - | tAMPER - ; - -f_block_arg : blkarg_mark tIDENTIFIER - { - local_add_f(p, $2); - $$ = $2; - } - ; - -opt_f_block_arg : ',' f_block_arg - { - $$ = $2; - } - | none - { - local_add_f(p, 0); - $$ = 0; - } - ; - -singleton : var_ref - { - $$ = $1; - if (!$$) $$ = new_nil(p); - } - | '(' {p->lstate = EXPR_BEG;} expr rparen - { - if ($3 == 0) { - yyerror(p, "can't define singleton method for ()."); - } - else { - 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: - case NODE_ARRAY: - case NODE_HEREDOC: - yyerror(p, "can't define singleton method for literals"); - default: - break; - } - } - $$ = $3; - } - ; - -assoc_list : none - | assocs trailer - { - $$ = $1; - } - ; - -assocs : assoc - { - $$ = list1($1); - } - | assocs ',' assoc - { - $$ = push($1, $3); - } - ; - -assoc : arg_value tASSOC arg_value - { - $$ = cons($1, $3); - } - | tLABEL arg_value - { - $$ = cons(new_sym(p, $1), $2); - } - ; - -operation : tIDENTIFIER - | tCONSTANT - | tFID - ; - -operation2 : tIDENTIFIER - | tCONSTANT - | tFID - | op - ; - -operation3 : tIDENTIFIER - | tFID - | op - ; - -dot_or_colon : '.' - | tCOLON2 - ; - -opt_terms : /* none */ - | terms - ; - -opt_nl : /* none */ - | nl - ; - -rparen : opt_nl ')' - ; - -rbracket : opt_nl ']' - ; - -trailer : /* none */ - | nl - | ',' - ; - -term : ';' {yyerrok;} - | nl - ; - -nl : '\n' - { - p->lineno++; - p->column = 0; - } - opt_heredoc_bodies - -terms : term - | terms ';' {yyerrok;} - ; - -none : /* none */ - { - $$ = 0; - } - ; + { + parser_heredoc_info * inf = parsing_heredoc_inf(p); + inf->doc = push(inf->doc, $1); + heredoc_treat_nextline(p); + } + | tHD_STRING_PART + { + $<nd>$ = p->lex_strterm; + p->lex_strterm = NULL; + } + compstmt + '}' + { + parser_heredoc_info * inf = parsing_heredoc_inf(p); + p->lex_strterm = $<nd>2; + inf->doc = push(push(inf->doc, $1), $3); + } + ; + +words : tWORDS_BEG tSTRING + { + $$ = new_words(p, list1($2)); + } + | tWORDS_BEG string_rep tSTRING + { + $$ = new_words(p, push($2, $3)); + } + ; + + +symbol : basic_symbol + { + $$ = new_sym(p, $1); + } + | tSYMBEG tSTRING_BEG string_interp tSTRING + { + p->lstate = EXPR_END; + $$ = new_dsym(p, push($3, $4)); + } + ; + +basic_symbol : tSYMBEG sym + { + p->lstate = EXPR_END; + $$ = $2; + } + ; + +sym : fname + | tIVAR + | tGVAR + | tCVAR + | tSTRING + { + $$ = new_strsym(p, $1); + } + | tSTRING_BEG tSTRING + { + $$ = new_strsym(p, $2); + } + ; + +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 + { + $$ = negate_lit(p, $2); + } + | tUMINUS_NUM tFLOAT %prec tLOWEST + { + $$ = negate_lit(p, $2); + } + ; + +variable : tIDENTIFIER + { + $$ = new_lvar(p, $1); + } + | tIVAR + { + $$ = new_ivar(p, $1); + } + | tGVAR + { + $$ = new_gvar(p, $1); + } + | tCVAR + { + $$ = new_cvar(p, $1); + } + | tCONSTANT + { + $$ = new_const(p, $1); + } + ; + +var_lhs : variable + { + assignable(p, $1); + } + ; + +var_ref : variable + { + $$ = var_reference(p, $1); + } + | keyword_nil + { + $$ = new_nil(p); + } + | keyword_self + { + $$ = new_self(p); + } + | keyword_true + { + $$ = new_true(p); + } + | keyword_false + { + $$ = new_false(p); + } + | keyword__FILE__ + { + if (!p->filename) { + p->filename = "(null)"; + } + $$ = new_str(p, p->filename, strlen(p->filename)); + } + | keyword__LINE__ + { + char buf[16]; + + snprintf(buf, sizeof(buf), "%d", p->lineno); + $$ = new_int(p, buf, 10); + } + ; + +backref : tNTH_REF + | tBACK_REF + ; + +superclass : term + { + $$ = 0; + } + | '<' + { + p->lstate = EXPR_BEG; + p->cmd_start = TRUE; + } + expr_value term + { + $$ = $3; + } + | error term + { + yyerrok; + $$ = 0; + } + ; + +f_arglist : '(' f_args rparen + { + $$ = $2; + p->lstate = EXPR_BEG; + p->cmd_start = TRUE; + } + | f_args term + { + $$ = $1; + } + ; + +f_args : f_arg ',' f_optarg ',' f_rest_arg opt_f_block_arg + { + $$ = new_args(p, $1, $3, $5, 0, $6); + } + | f_arg ',' f_optarg ',' f_rest_arg ',' f_arg opt_f_block_arg + { + $$ = new_args(p, $1, $3, $5, $7, $8); + } + | f_arg ',' f_optarg opt_f_block_arg + { + $$ = new_args(p, $1, $3, 0, 0, $4); + } + | f_arg ',' f_optarg ',' f_arg opt_f_block_arg + { + $$ = new_args(p, $1, $3, 0, $5, $6); + } + | f_arg ',' f_rest_arg opt_f_block_arg + { + $$ = new_args(p, $1, 0, $3, 0, $4); + } + | f_arg ',' f_rest_arg ',' f_arg opt_f_block_arg + { + $$ = new_args(p, $1, 0, $3, $5, $6); + } + | f_arg opt_f_block_arg + { + $$ = new_args(p, $1, 0, 0, 0, $2); + } + | f_optarg ',' f_rest_arg opt_f_block_arg + { + $$ = new_args(p, 0, $1, $3, 0, $4); + } + | f_optarg ',' f_rest_arg ',' f_arg opt_f_block_arg + { + $$ = new_args(p, 0, $1, $3, $5, $6); + } + | f_optarg opt_f_block_arg + { + $$ = new_args(p, 0, $1, 0, 0, $2); + } + | f_optarg ',' f_arg opt_f_block_arg + { + $$ = new_args(p, 0, $1, 0, $3, $4); + } + | f_rest_arg opt_f_block_arg + { + $$ = new_args(p, 0, 0, $1, 0, $2); + } + | f_rest_arg ',' f_arg opt_f_block_arg + { + $$ = new_args(p, 0, 0, $1, $3, $4); + } + | f_block_arg + { + $$ = new_args(p, 0, 0, 0, 0, $1); + } + | /* none */ + { + local_add_f(p, 0); + $$ = new_args(p, 0, 0, 0, 0, 0); + } + ; + +f_bad_arg : tCONSTANT + { + yyerror(p, "formal argument cannot be a constant"); + $$ = 0; + } + | tIVAR + { + yyerror(p, "formal argument cannot be an instance variable"); + $$ = 0; + } + | tGVAR + { + yyerror(p, "formal argument cannot be a global variable"); + $$ = 0; + } + | tCVAR + { + yyerror(p, "formal argument cannot be a class variable"); + $$ = 0; + } + ; + +f_norm_arg : f_bad_arg + { + $$ = 0; + } + | tIDENTIFIER + { + local_add_f(p, $1); + $$ = $1; + } + ; + +f_arg_item : f_norm_arg + { + $$ = new_arg(p, $1); + } + | tLPAREN f_margs rparen + { + $$ = new_masgn(p, $2, 0); + } + ; + +f_arg : f_arg_item + { + $$ = list1($1); + } + | f_arg ',' f_arg_item + { + $$ = push($1, $3); + } + ; + +f_opt : tIDENTIFIER '=' arg_value + { + local_add_f(p, $1); + $$ = cons(nsym($1), $3); + } + ; + +f_block_opt : tIDENTIFIER '=' primary_value + { + local_add_f(p, $1); + $$ = cons(nsym($1), $3); + } + ; + +f_block_optarg : f_block_opt + { + $$ = list1($1); + } + | f_block_optarg ',' f_block_opt + { + $$ = push($1, $3); + } + ; + +f_optarg : f_opt + { + $$ = list1($1); + } + | f_optarg ',' f_opt + { + $$ = push($1, $3); + } + ; + +restarg_mark : '*' + | tSTAR + ; + +f_rest_arg : restarg_mark tIDENTIFIER + { + local_add_f(p, $2); + $$ = $2; + } + | restarg_mark + { + local_add_f(p, 0); + $$ = -1; + } + ; + +blkarg_mark : '&' + | tAMPER + ; + +f_block_arg : blkarg_mark tIDENTIFIER + { + local_add_f(p, $2); + $$ = $2; + } + ; + +opt_f_block_arg : ',' f_block_arg + { + $$ = $2; + } + | none + { + local_add_f(p, 0); + $$ = 0; + } + ; + +singleton : var_ref + { + $$ = $1; + if (!$$) $$ = new_nil(p); + } + | '(' {p->lstate = EXPR_BEG;} expr rparen + { + if ($3 == 0) { + yyerror(p, "can't define singleton method for ()."); + } + else { + 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: + case NODE_ARRAY: + case NODE_HEREDOC: + yyerror(p, "can't define singleton method for literals"); + default: + break; + } + } + $$ = $3; + } + ; + +assoc_list : none + | assocs trailer + { + $$ = $1; + } + ; + +assocs : assoc + { + $$ = list1($1); + } + | assocs ',' assoc + { + $$ = push($1, $3); + } + ; + +assoc : arg_value tASSOC arg_value + { + $$ = cons($1, $3); + } + | tLABEL arg_value + { + $$ = cons(new_sym(p, $1), $2); + } + ; + +operation : tIDENTIFIER + | tCONSTANT + | tFID + ; + +operation2 : tIDENTIFIER + | tCONSTANT + | tFID + | op + ; + +operation3 : tIDENTIFIER + | tFID + | op + ; + +dot_or_colon : '.' + | tCOLON2 + ; + +opt_terms : /* none */ + | terms + ; + +opt_nl : /* none */ + | nl + ; + +rparen : opt_nl ')' + ; + +rbracket : opt_nl ']' + ; + +trailer : /* none */ + | nl + | ',' + ; + +term : ';' {yyerrok;} + | nl + ; + +nl : '\n' + { + p->lineno++; + p->column = 0; + } + opt_heredoc_bodies + +terms : term + | terms ';' {yyerrok;} + ; + +none : /* none */ + { + $$ = 0; + } + ; %% #define yylval (*((YYSTYPE*)(p->ylval))) @@ -3297,8 +3319,8 @@ backref_error(parser_state *p, node *n) } } -static int peeks(parser_state *p, const char *s); -static int skips(parser_state *p, const char *s); +static mrb_bool peeks(parser_state *p, const char *s); +static mrb_bool skips(parser_state *p, const char *s); static inline int nextc(parser_state *p) @@ -3322,26 +3344,22 @@ nextc(parser_state *p) } else #endif - if (!p->s || p->s >= p->send) { - goto eof; - } - else { - c = (unsigned char)*p->s++; - } + if (!p->s || p->s >= p->send) { + goto eof; + } + else { + c = (unsigned char)*p->s++; + } } p->column++; return c; - eof: + eof: if (!p->cxt) return -1; else { - mrbc_context *cxt = p->cxt; - - if (cxt->partial_hook(p) < 0) return -1; - c = '\n'; - p->lineno = 1; - p->cxt = cxt; - return c; + if (p->cxt->partial_hook(p) < 0) + return -1; + return -2; } } @@ -3365,7 +3383,7 @@ skip(parser_state *p, char term) } } -static int +static mrb_bool peek_n(parser_state *p, int c, int n) { node *list = 0; @@ -3387,7 +3405,7 @@ peek_n(parser_state *p, int c, int n) } #define peek(p,c) peek_n((p), (c), 0) -static int +static mrb_bool peeks(parser_state *p, const char *s) { int len = strlen(s); @@ -3402,13 +3420,13 @@ peeks(parser_state *p, const char *s) } else #endif - if (p->s && p->s + len >= p->send) { - if (memcmp(p->s, s, len) == 0) return TRUE; - } + if (p->s && p->s + len >= p->send) { + if (memcmp(p->s, s, len) == 0) return TRUE; + } return FALSE; } -static int +static mrb_bool skips(parser_state *p, const char *s) { int c; @@ -3425,11 +3443,11 @@ skips(parser_state *p, const char *s) int len = strlen(s); while (len--) { - nextc(p); + nextc(p); } return TRUE; } - else{ + else{ s--; } } @@ -3527,74 +3545,74 @@ read_escape(parser_state *p) int c; switch (c = nextc(p)) { - case '\\': /* Backslash */ + case '\\':/* Backslash */ return c; - case 'n': /* newline */ + case 'n':/* newline */ return '\n'; - case 't': /* horizontal tab */ + case 't':/* horizontal tab */ return '\t'; - case 'r': /* carriage-return */ + case 'r':/* carriage-return */ return '\r'; - case 'f': /* form-feed */ + case 'f':/* form-feed */ return '\f'; - case 'v': /* vertical tab */ + case 'v':/* vertical tab */ return '\13'; - case 'a': /* alarm(bell) */ + case 'a':/* alarm(bell) */ return '\007'; - case 'e': /* escape */ + case 'e':/* escape */ return 033; case '0': case '1': case '2': case '3': /* octal constant */ case '4': case '5': case '6': case '7': - { - int buf[3]; - int 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; - } + { + int buf[3]; + int i; + + buf[0] = c; + for (i=1; i<3; i++) { + buf[i] = nextc(p); + if (buf[i] < 0) goto eof; + if (buf[i] < '0' || '7' < buf[i]) { + pushback(p, buf[i]); + break; } - c = scan_oct(buf, i, &i); } - return c; + c = scan_oct(buf, i, &i); + } + return c; - case 'x': /* hex constant */ - { - int buf[2]; - 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; - } - } - c = scan_hex(buf, i, &i); - if (i == 0) { - yyerror(p, "Invalid escape character syntax"); - return 0; + case 'x': /* hex constant */ + { + int buf[2]; + int i; + + for (i=0; i<2; i++) { + buf[i] = nextc(p); + if (buf[i] < 0) goto eof; + if (!ISXDIGIT(buf[i])) { + pushback(p, buf[i]); + break; } } - return c; + c = scan_hex(buf, i, &i); + if (i == 0) { + yyerror(p, "Invalid escape character syntax"); + return 0; + } + } + return c; - case 'b': /* backspace */ + case 'b':/* backspace */ return '\010'; - case 's': /* space */ + case 's':/* space */ return ' '; case 'M': @@ -3606,7 +3624,7 @@ read_escape(parser_state *p) if ((c = nextc(p)) == '\\') { return read_escape(p) | 0x80; } - else if (c == -1) goto eof; + else if (c < 0) goto eof; else { return ((c & 0xff) | 0x80); } @@ -3623,11 +3641,12 @@ read_escape(parser_state *p) } else if (c == '?') return 0177; - else if (c == -1) goto eof; + else if (c < 0) goto eof; return c & 0x9f; - eof: + eof: case -1: + case -2: yyerror(p, "Invalid escape character syntax"); return '\0'; @@ -3649,7 +3668,7 @@ parse_string(parser_state *p) newtok(p); while ((c = nextc(p)) != end || nest_level != 0) { - if (hinf && (c == '\n' || c == -1)) { + if (hinf && (c == '\n' || c < 0)) { int line_head; tokadd(p, '\n'); tokfix(p); @@ -3658,29 +3677,29 @@ parse_string(parser_state *p) 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; - } + /* 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 heredoc delimiter \"%s\" anywhere before EOF", hinf->term); - yyerror(p, buf); - return 0; + if (c < 0) { + char buf[256]; + snprintf(buf, sizeof(buf), "can't find heredoc delimiter \"%s\" anywhere before EOF", hinf->term); + yyerror(p, buf); + return 0; } yylval.nd = new_str(p, tok(p), toklen(p)); return tHD_STRING_MID; } - if (c == -1) { + if (c < 0) { yyerror(p, "unterminated string meets end of file"); return 0; } @@ -3695,58 +3714,58 @@ parse_string(parser_state *p) else if (c == '\\') { c = nextc(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 { - if (type & STR_FUNC_REGEXP) { - tokadd(p, '\\'); - if (c != -1) - tokadd(p, c); - } else { - pushback(p, c); - tokadd(p, read_escape(p)); - } - if (hinf) - hinf->line_head = FALSE; - } + 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 { + if (type & STR_FUNC_REGEXP) { + tokadd(p, '\\'); + if (c >= 0) + tokadd(p, c); + } else { + pushback(p, c); + 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); + 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; } else if ((c == '#') && (type & STR_FUNC_EXPAND)) { c = nextc(p); if (c == '{') { - 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 tHD_STRING_PART; - } - 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 tHD_STRING_PART; + } + return tSTRING_PART; } tokadd(p, '#'); pushback(p, c); @@ -3754,23 +3773,23 @@ parse_string(parser_state *p) } if ((type & STR_FUNC_ARRAY) && ISSPACE(c)) { if (toklen(p) == 0) { - do { - if (c == '\n') { - p->lineno++; - p->column = 0; - heredoc_treat_nextline(p); - if (p->parsing_heredoc != NULL) { - return tHD_LITERAL_DELIM; - } - } - } while (ISSPACE(c = nextc(p))); - pushback(p, c); - return tLITERAL_DELIM; + do { + if (c == '\n') { + p->lineno++; + p->column = 0; + heredoc_treat_nextline(p); + if (p->parsing_heredoc != NULL) { + return tHD_LITERAL_DELIM; + } + } + } 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; + pushback(p, c); + tokfix(p); + yylval.nd = new_str(p, tok(p), toklen(p)); + return tSTRING_MID; } } @@ -3796,7 +3815,7 @@ parse_string(parser_state *p) char *dup; newtok(p); - while (c = nextc(p), c != -1 && ISALPHA(c)) { + while (c = nextc(p), c >= 0 && ISALPHA(c)) { switch (c) { case 'i': f |= 1; break; case 'x': f |= 2; break; @@ -3809,7 +3828,7 @@ parse_string(parser_state *p) 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 != 0) { @@ -3836,8 +3855,8 @@ heredoc_identifier(parser_state *p) { int c; int type = str_heredoc; - int indent = FALSE; - int quote = FALSE; + mrb_bool indent = FALSE; + mrb_bool quote = FALSE; node *newnode; parser_heredoc_info *info; @@ -3855,19 +3874,19 @@ heredoc_identifier(parser_state *p) if (c == '\'') quote = TRUE; newtok(p); - while ((c = nextc(p)) != -1 && c != term) { + while ((c = nextc(p)) >= 0 && c != term) { if (c == '\n') { - c = -1; - break; + c = -1; + break; } tokadd(p, c); } - if (c == -1) { + if (c < 0) { yyerror(p, "unterminated here document identifier"); return 0; } } else { - if (c == -1) { + if (c < 0) { return 0; /* missing here document identifier */ } if (! identchar(c)) { @@ -3878,7 +3897,7 @@ heredoc_identifier(parser_state *p) newtok(p); do { tokadd(p, c); - } while ((c = nextc(p)) != -1 && identchar(c)); + } while ((c = nextc(p)) >= 0 && identchar(c)); pushback(p, c); } tokfix(p); @@ -3920,14 +3939,14 @@ parser_yylex(parser_state *p) if (p->lex_strterm) { if (is_strterm_type(p, STR_FUNC_HEREDOC)) { if (p->parsing_heredoc != NULL) - return parse_string(p); + return parse_string(p); } else return parse_string(p); } cmd_state = p->cmd_start; p->cmd_start = FALSE; - retry: + retry: last_state = p->lstate; switch (c = nextc(p)) { case '\0': /* NUL */ @@ -3947,78 +3966,80 @@ parser_yylex(parser_state *p) case '#': /* it's a comment */ skip(p, '\n'); - /* fall through */ + /* fall through */ + case -2: /* end of partial script. */ case '\n': - maybe_heredoc: + maybe_heredoc: heredoc_treat_nextline(p); - switch (p->lstate) { - case EXPR_BEG: - case EXPR_FNAME: - case EXPR_DOT: - case EXPR_CLASS: - case EXPR_VALUE: - p->lineno++; - p->column = 0; - if (p->parsing_heredoc != NULL) { - return parse_string(p); - } - goto retry; - default: - break; - } + switch (p->lstate) { + case EXPR_BEG: + case EXPR_FNAME: + case EXPR_DOT: + case EXPR_CLASS: + case EXPR_VALUE: + p->lineno++; + p->column = 0; if (p->parsing_heredoc != NULL) { - return '\n'; + return parse_string(p); } - while ((c = nextc(p))) { - switch (c) { - case ' ': case '\t': case '\f': case '\r': - case '\13': /* '\v' */ - space_seen = 1; - break; - case '.': - if ((c = nextc(p)) != '.') { - pushback(p, c); - pushback(p, '.'); - goto retry; - } - case -1: /* EOF */ - goto normal_newline; - default: - pushback(p, c); - goto normal_newline; + goto retry; + default: + break; + } + if (p->parsing_heredoc != NULL) { + return '\n'; + } + while ((c = nextc(p))) { + switch (c) { + case ' ': case '\t': case '\f': case '\r': + case '\13': /* '\v' */ + space_seen = 1; + break; + case '.': + if ((c = nextc(p)) != '.') { + pushback(p, c); + pushback(p, '.'); + goto retry; } + case -1: /* EOF */ + case -2: /* end of partial script */ + goto normal_newline; + default: + pushback(p, c); + goto normal_newline; } + } normal_newline: - p->cmd_start = TRUE; - p->lstate = EXPR_BEG; - return '\n'; + p->cmd_start = TRUE; + p->lstate = EXPR_BEG; + return '\n'; case '*': if ((c = nextc(p)) == '*') { if ((c = nextc(p)) == '=') { - yylval.id = intern2("**",2); - p->lstate = EXPR_BEG; - return tOP_ASGN; + yylval.id = intern("**",2); + p->lstate = EXPR_BEG; + return tOP_ASGN; } pushback(p, c); c = tPOW; } else { if (c == '=') { - yylval.id = intern_c('*'); - 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) { @@ -4033,7 +4054,7 @@ parser_yylex(parser_state *p) if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) { p->lstate = EXPR_ARG; if (c == '@') { - return '!'; + return '!'; } } else { @@ -4051,8 +4072,8 @@ parser_yylex(parser_state *p) case '=': if (p->column == 1) { if (peeks(p, "begin\n")) { - skips(p, "\n=end\n"); - goto retry; + skips(p, "\n=end\n"); + goto retry; } } if (p->lstate == EXPR_FNAME || p->lstate == EXPR_DOT) { @@ -4062,7 +4083,7 @@ parser_yylex(parser_state *p) } if ((c = nextc(p)) == '=') { if ((c = nextc(p)) == '=') { - return tEQQ; + return tEQQ; } pushback(p, c); return tEQ; @@ -4080,34 +4101,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)) { + p->lstate != EXPR_DOT && + p->lstate != EXPR_CLASS && + !IS_END() && + (!IS_ARG() || space_seen)) { int token = heredoc_identifier(p); if (token) - return 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 = intern2("<<",2); - p->lstate = EXPR_BEG; - return tOP_ASGN; + yylval.id = intern("<<",2); + p->lstate = EXPR_BEG; + return tOP_ASGN; } pushback(p, c); return tLSHFT; @@ -4126,9 +4147,9 @@ parser_yylex(parser_state *p) } if (c == '>') { if ((c = nextc(p)) == '=') { - yylval.id = intern2(">>",2); - p->lstate = EXPR_BEG; - return tOP_ASGN; + yylval.id = intern(">>",2); + p->lstate = EXPR_BEG; + return tOP_ASGN; } pushback(p, c); return tRSHFT; @@ -4151,9 +4172,9 @@ parser_yylex(parser_state *p) } if (p->lstate == EXPR_DOT) { if (cmd_state) - p->lstate = EXPR_CMDARG; + p->lstate = EXPR_CMDARG; else - p->lstate = EXPR_ARG; + p->lstate = EXPR_ARG; return '`'; } p->lex_strterm = new_strterm(p, str_xquote, '`', 0); @@ -4165,43 +4186,43 @@ parser_yylex(parser_state *p) return '?'; } c = nextc(p); - if (c == -1) { + if (c < 0) { yyerror(p, "incomplete character syntax"); return 0; } 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: + ternary: pushback(p, c); p->lstate = EXPR_VALUE; return '?'; @@ -4212,20 +4233,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 { @@ -4240,9 +4261,9 @@ parser_yylex(parser_state *p) if ((c = nextc(p)) == '&') { p->lstate = EXPR_BEG; if ((c = nextc(p)) == '=') { - yylval.id = intern2("&&",2); - p->lstate = EXPR_BEG; - return tOP_ASGN; + yylval.id = intern("&&",2); + p->lstate = EXPR_BEG; + return tOP_ASGN; } pushback(p, c); return tANDOP; @@ -4274,9 +4295,9 @@ parser_yylex(parser_state *p) if ((c = nextc(p)) == '|') { p->lstate = EXPR_BEG; if ((c = nextc(p)) == '=') { - yylval.id = intern2("||",2); - p->lstate = EXPR_BEG; - return tOP_ASGN; + yylval.id = intern("||",2); + p->lstate = EXPR_BEG; + return tOP_ASGN; } pushback(p, c); return tOROP; @@ -4300,7 +4321,7 @@ 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 '+'; @@ -4313,9 +4334,9 @@ parser_yylex(parser_state *p) if (IS_BEG() || (IS_SPCARG(c) && arg_ambiguous(p))) { p->lstate = EXPR_BEG; pushback(p, c); - if (c != -1 && ISDIGIT(c)) { - c = '+'; - goto start_num; + if (c >= 0 && ISDIGIT(c)) { + c = '+'; + goto start_num; } return tUPLUS; } @@ -4328,7 +4349,7 @@ 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 '-'; @@ -4345,8 +4366,8 @@ parser_yylex(parser_state *p) if (IS_BEG() || (IS_SPCARG(c) && arg_ambiguous(p))) { p->lstate = EXPR_BEG; pushback(p, c); - if (c != -1 && ISDIGIT(c)) { - return tUMINUS_NUM; + if (c >= 0 && ISDIGIT(c)) { + return tUMINUS_NUM; } return tUMINUS; } @@ -4358,244 +4379,244 @@ 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; } pushback(p, c); - if (c != -1 && ISDIGIT(c)) { + if (c >= 0 && ISDIGIT(c)) { yyerror(p, "no .<digit> floating literal anymore; put 0 before dot"); } p->lstate = EXPR_DOT; return '.'; - start_num: + start_num: case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': - { - int is_float, seen_point, seen_e, nondigit; + { + int is_float, seen_point, seen_e, nondigit; - is_float = seen_point = seen_e = nondigit = 0; - p->lstate = EXPR_END; - token_column = newtok(p); - if (c == '-' || c == '+') { - tokadd(p, c); - c = nextc(p); - } - if (c == '0') { + is_float = seen_point = seen_e = nondigit = 0; + p->lstate = EXPR_END; + token_column = newtok(p); + if (c == '-' || c == '+') { + 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 >= 0 && 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)) >= 0); + } + 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)) >= 0); + } + 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 >= 0 && ISDIGIT(c)) { + do { + if (c == '_') { + if (nondigit) break; + nondigit = c; + continue; + } + if (!ISDIGIT(c)) break; + nondigit = 0; + tokadd(p, c); + } while ((c = nextc(p)) >= 0); + } + 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 < 0 || 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)) >= 0); + + 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); + 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 < 0 || !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) { + 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)); } - 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; + else if (errno == ERANGE) { + yywarning_s(p, "float %s out of range", tok(p)); + errno = 0; } - yylval.nd = new_int(p, tok(p), 10); - return tINTEGER; + yylval.nd = new_float(p, tok(p)); + return tFLOAT; } + yylval.nd = new_int(p, tok(p), 10); + return tINTEGER; + } case ')': case ']': @@ -4613,8 +4634,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; @@ -4675,7 +4696,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; } @@ -4702,11 +4723,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 '['; @@ -4759,21 +4780,21 @@ parser_yylex(parser_state *p) int paren; c = nextc(p); - quotation: - if (c == -1 || !ISALNUM(c)) { - term = c; - c = 'Q'; + quotation: + if (c < 0 || !ISALNUM(c)) { + term = c; + c = 'Q'; } else { - 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; + if (c < 0 || term < 0) { + yyerror(p, "unterminated quoted string meets end of file"); + return 0; } paren = term; if (term == '(') term = ')'; @@ -4784,44 +4805,44 @@ parser_yylex(parser_state *p) switch (c) { case 'Q': - p->lex_strterm = new_strterm(p, str_dquote, term, paren); - return tSTRING_BEG; + p->lex_strterm = new_strterm(p, str_dquote, term, paren); + return tSTRING_BEG; case 'q': - p->lex_strterm = new_strterm(p, str_squote, term, paren); - return parse_string(p); + p->lex_strterm = new_strterm(p, str_squote, term, paren); + return parse_string(p); case 'W': - p->lex_strterm = new_strterm(p, str_dword, term, paren); - return tWORDS_BEG; + p->lex_strterm = new_strterm(p, str_dword, term, paren); + return tWORDS_BEG; case 'w': - p->lex_strterm = new_strterm(p, str_sword, term, paren); - return tWORDS_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; + p->lex_strterm = new_strterm(p, str_xquote, term, paren); + return tXSTRING_BEG; case 'r': - p->lex_strterm = new_strterm(p, str_regexp, term, paren); - return tREGEXP_BEG; + p->lex_strterm = new_strterm(p, str_regexp, term, paren); + return tREGEXP_BEG; case 's': - p->lex_strterm = new_strterm(p, str_ssym, term, paren); - 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; + 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; + 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)) == '=') { @@ -4844,17 +4865,17 @@ parser_yylex(parser_state *p) p->lstate = EXPR_END; token_column = newtok(p); c = nextc(p); - if (c == -1) { + if (c < 0) { yyerror(p, "incomplete global variable syntax"); return 0; } switch (c) { case '_': /* $_: last read line string */ c = nextc(p); - if (c != -1 && identchar(c)) { /* if there is more after _ it is a variable */ - tokadd(p, '$'); - tokadd(p, c); - break; + if (c >= 0 && identchar(c)) { /* if there is more after _ it is a variable */ + tokadd(p, '$'); + tokadd(p, c); + break; } pushback(p, c); c = '_'; @@ -4878,7 +4899,7 @@ parser_yylex(parser_state *p) tokadd(p, '$'); tokadd(p, c); tokfix(p); - yylval.id = intern(tok(p)); + yylval.id = intern_cstr(tok(p)); return tGVAR; case '-': @@ -4886,9 +4907,9 @@ parser_yylex(parser_state *p) tokadd(p, c); c = nextc(p); pushback(p, c); - gvar: + gvar: tokfix(p); - yylval.id = intern(tok(p)); + yylval.id = intern_cstr(tok(p)); return tGVAR; case '&': /* $&: last match */ @@ -4896,9 +4917,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; @@ -4907,9 +4928,9 @@ parser_yylex(parser_state *p) case '4': case '5': case '6': case '7': case '8': case '9': do { - tokadd(p, c); - c = nextc(p); - } while (c != -1 && isdigit(c)); + tokadd(p, c); + c = nextc(p); + } while (c >= 0 && isdigit(c)); pushback(p, c); if (last_state == EXPR_FNAME) goto gvar; tokfix(p); @@ -4918,58 +4939,58 @@ parser_yylex(parser_state *p) default: if (!identchar(c)) { - pushback(p, c); - return '$'; + pushback(p, c); + return '$'; } case '0': tokadd(p, '$'); } break; - case '@': - c = nextc(p); - token_column = newtok(p); - tokadd(p, '@'); - if (c == '@') { - tokadd(p, '@'); + case '@': c = nextc(p); - } - if (c == -1) { - if (p->bidx == 1) { - yyerror(p, "incomplete instance variable syntax"); + token_column = newtok(p); + tokadd(p, '@'); + if (c == '@') { + tokadd(p, '@'); + c = nextc(p); } - else { - yyerror(p, "incomplete class variable syntax"); + if (c < 0) { + if (p->bidx == 1) { + yyerror(p, "incomplete instance variable syntax"); + } + else { + yyerror(p, "incomplete class variable syntax"); + } + return 0; } - return 0; - } - else if (isdigit(c)) { - if (p->bidx == 1) { - yyerror_i(p, "`@%c' is not allowed as an instance variable name", c); + else if (isdigit(c)) { + if (p->bidx == 1) { + 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); + } + return 0; } - else { - yyerror_i(p, "`@@%c' is not allowed as a class variable name", c); + if (!identchar(c)) { + pushback(p, c); + return '@'; } - return 0; - } - if (!identchar(c)) { - pushback(p, c); - return '@'; - } - break; + break; - case '_': - token_column = newtok(p); - break; + case '_': + token_column = newtok(p); + break; - default: - if (!identchar(c)) { - yyerror_i(p, "Invalid char `\\x%02X' in expression", c); - goto retry; - } + default: + if (!identchar(c)) { + yyerror_i(p, "Invalid char `\\x%02X' in expression", c); + goto retry; + } - token_column = newtok(p); - break; + token_column = newtok(p); + break; } do { @@ -5006,104 +5027,104 @@ 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)(unsigned char)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)(unsigned char)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_cstr(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_cstr(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; } } { - mrb_sym ident = intern(tok(p)); + mrb_sym ident = intern_cstr(tok(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 } @@ -5162,8 +5183,8 @@ parser_update_cxt(parser_state *p, mrbc_context *cxt) } } -void codedump_all(mrb_state*, struct RProc*); -void parser_dump(mrb_state *mrb, node *tree, int offset); +void mrb_codedump_all(mrb_state*, struct RProc*); +void mrb_parser_dump(mrb_state *mrb, node *tree, int offset); void mrb_parser_parse(parser_state *p, mrbc_context *c) @@ -5176,7 +5197,7 @@ mrb_parser_parse(parser_state *p, mrbc_context *c) } p->cmd_start = TRUE; - p->in_def = p->in_single = FALSE; + p->in_def = p->in_single = 0; p->nerr = p->nwarn = 0; p->lex_strterm = NULL; @@ -5187,7 +5208,7 @@ mrb_parser_parse(parser_state *p, mrbc_context *c) } parser_update_cxt(p, c); if (c && c->dump_result) { - parser_dump(p->mrb, p->tree, 0); + mrb_parser_dump(p->mrb, p->tree, 0); } } @@ -5206,7 +5227,6 @@ mrb_parser_new(mrb_state *mrb) *p = parser_state_zero; p->mrb = mrb; p->pool = pool; - p->in_def = p->in_single = 0; p->s = p->send = NULL; #ifdef ENABLE_STDIO @@ -5214,9 +5234,9 @@ mrb_parser_new(mrb_state *mrb) #endif p->cmd_start = TRUE; - p->in_def = p->in_single = FALSE; + p->in_def = p->in_single = 0; - p->capture_errors = 0; + p->capture_errors = FALSE; p->lineno = 1; p->column = 0; #if defined(PARSER_TEST) || defined(PARSER_DEBUG) @@ -5286,7 +5306,7 @@ mrb_parser_set_filename(struct mrb_parser_state *p, const char *f) sym = mrb_intern_cstr(p->mrb, f); p->filename = mrb_sym2name_len(p->mrb, sym, &len); p->lineno = (p->filename_table_length > 0)? 0 : 1; - + for(i = 0; i < p->filename_table_length; ++i) { if(p->filename_table[i] == sym) { p->current_filename_index = i; @@ -5364,7 +5384,7 @@ load_exec(mrb_state *mrb, parser_state *p, mrbc_context *c) int n; n = snprintf(buf, sizeof(buf), "line %d: %s\n", - p->error_buffer[0].lineno, p->error_buffer[0].message); + p->error_buffer[0].lineno, p->error_buffer[0].message); mrb->exc = mrb_obj_ptr(mrb_exc_new(mrb, E_SYNTAX_ERROR, buf, n)); mrb_parser_free(p); return mrb_undef_value(); @@ -5384,7 +5404,7 @@ load_exec(mrb_state *mrb, parser_state *p, mrbc_context *c) return mrb_undef_value(); } if (c) { - if (c->dump_result) codedump_all(mrb, proc); + if (c->dump_result) mrb_codedump_all(mrb, proc); if (c->no_exec) return mrb_obj_value(proc); if (c->target_class) { target = c->target_class; @@ -5452,7 +5472,7 @@ static void dump_recur(mrb_state *mrb, node *tree, int offset) { while (tree) { - parser_dump(mrb, tree->car, offset); + mrb_parser_dump(mrb, tree->car, offset); tree = tree->cdr; } } @@ -5460,13 +5480,13 @@ dump_recur(mrb_state *mrb, node *tree, int offset) #endif void -parser_dump(mrb_state *mrb, node *tree, int offset) +mrb_parser_dump(mrb_state *mrb, node *tree, int offset) { #ifdef ENABLE_STDIO int n; if (!tree) return; - again: + again: dump_prefix(offset); n = (int)(intptr_t)tree->car; tree = tree->cdr; @@ -5481,7 +5501,7 @@ parser_dump(mrb_state *mrb, node *tree, int offset) if (tree->car) { dump_prefix(offset+1); printf("body:\n"); - parser_dump(mrb, tree->car, offset+2); + mrb_parser_dump(mrb, tree->car, offset+2); } tree = tree->cdr; if (tree->car) { @@ -5490,30 +5510,30 @@ 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"); + mrb_parser_dump(mrb, n3->cdr->car, offset+3); + } + if (n3->cdr->cdr->car) { + dump_prefix(offset+2); + printf("rescue body:\n"); + mrb_parser_dump(mrb, n3->cdr->cdr->car, offset+3); + } + n2 = n2->cdr; } } tree = tree->cdr; if (tree->car) { dump_prefix(offset+1); printf("else:\n"); - parser_dump(mrb, tree->car, offset+2); + mrb_parser_dump(mrb, tree->car, offset+2); } break; @@ -5521,10 +5541,10 @@ parser_dump(mrb_state *mrb, node *tree, int offset) printf("NODE_ENSURE:\n"); dump_prefix(offset+1); printf("body:\n"); - parser_dump(mrb, tree->car, offset+2); + mrb_parser_dump(mrb, tree->car, offset+2); dump_prefix(offset+1); printf("ensure:\n"); - parser_dump(mrb, tree->cdr->cdr, offset+2); + mrb_parser_dump(mrb, tree->cdr->cdr, offset+2); break; case NODE_LAMBDA: @@ -5532,85 +5552,85 @@ parser_dump(mrb_state *mrb, node *tree, int offset) goto block; case NODE_BLOCK: - block: + block: printf("NODE_BLOCK:\n"); - tree = tree->cdr; - if (tree->car) { - node *n = tree->car; + tree = tree->cdr; + if (tree->car) { + node *n = tree->car; - if (n->car) { - 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; - } - } - } - n = n->cdr; - if (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); - } - n = n->cdr; - if (n) { - dump_prefix(offset+1); - printf("blk=&%s\n", mrb_sym2name(mrb, sym(n))); + if (n->car) { + 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))); + mrb_parser_dump(mrb, n2->car->cdr, 0); + n2 = n2->cdr; + } } } - dump_prefix(offset+1); - printf("body:\n"); - parser_dump(mrb, tree->cdr->car, offset+2); - break; + n = n->cdr; + if (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); + } + n = n->cdr; + if (n) { + dump_prefix(offset+1); + printf("blk=&%s\n", mrb_sym2name(mrb, sym(n))); + } + } + dump_prefix(offset+1); + printf("body:\n"); + mrb_parser_dump(mrb, tree->cdr->car, offset+2); + break; case NODE_IF: printf("NODE_IF:\n"); dump_prefix(offset+1); printf("cond:\n"); - parser_dump(mrb, tree->car, offset+2); + mrb_parser_dump(mrb, tree->car, offset+2); dump_prefix(offset+1); printf("then:\n"); - parser_dump(mrb, tree->cdr->car, offset+2); + mrb_parser_dump(mrb, tree->cdr->car, offset+2); if (tree->cdr->cdr->car) { dump_prefix(offset+1); printf("else:\n"); - parser_dump(mrb, tree->cdr->cdr->car, offset+2); + mrb_parser_dump(mrb, tree->cdr->cdr->car, offset+2); } break; case NODE_AND: printf("NODE_AND:\n"); - parser_dump(mrb, tree->car, offset+1); - parser_dump(mrb, tree->cdr, offset+1); + mrb_parser_dump(mrb, tree->car, offset+1); + mrb_parser_dump(mrb, tree->cdr, offset+1); break; case NODE_OR: printf("NODE_OR:\n"); - parser_dump(mrb, tree->car, offset+1); - parser_dump(mrb, tree->cdr, offset+1); + mrb_parser_dump(mrb, tree->car, offset+1); + mrb_parser_dump(mrb, tree->cdr, offset+1); break; case NODE_CASE: printf("NODE_CASE:\n"); if (tree->car) { - parser_dump(mrb, tree->car, offset+1); + mrb_parser_dump(mrb, tree->car, offset+1); } tree = tree->cdr; while (tree) { @@ -5619,7 +5639,7 @@ parser_dump(mrb_state *mrb, node *tree, int offset) dump_recur(mrb, tree->car->car, offset+2); dump_prefix(offset+1); printf("body:\n"); - parser_dump(mrb, tree->car->cdr, offset+2); + mrb_parser_dump(mrb, tree->car->cdr, offset+2); tree = tree->cdr; } break; @@ -5628,20 +5648,20 @@ parser_dump(mrb_state *mrb, node *tree, int offset) printf("NODE_WHILE:\n"); dump_prefix(offset+1); printf("cond:\n"); - parser_dump(mrb, tree->car, offset+2); + mrb_parser_dump(mrb, tree->car, offset+2); dump_prefix(offset+1); printf("body:\n"); - parser_dump(mrb, tree->cdr, offset+2); + mrb_parser_dump(mrb, tree->cdr, offset+2); break; case NODE_UNTIL: printf("NODE_UNTIL:\n"); dump_prefix(offset+1); printf("cond:\n"); - parser_dump(mrb, tree->car, offset+2); + mrb_parser_dump(mrb, tree->car, offset+2); dump_prefix(offset+1); printf("body:\n"); - parser_dump(mrb, tree->cdr, offset+2); + mrb_parser_dump(mrb, tree->cdr, offset+2); break; case NODE_FOR: @@ -5652,35 +5672,35 @@ 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"); + mrb_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; dump_prefix(offset+1); printf("in:\n"); - parser_dump(mrb, tree->car, offset+2); + mrb_parser_dump(mrb, tree->car, offset+2); tree = tree->cdr; dump_prefix(offset+1); printf("do:\n"); - parser_dump(mrb, tree->car, offset+2); + mrb_parser_dump(mrb, tree->car, offset+2); break; case NODE_SCOPE: @@ -5689,17 +5709,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; @@ -5709,39 +5729,39 @@ parser_dump(mrb_state *mrb, node *tree, int offset) case NODE_FCALL: case NODE_CALL: printf("NODE_CALL:\n"); - parser_dump(mrb, tree->car, offset+1); + mrb_parser_dump(mrb, tree->car, offset+1); dump_prefix(offset+1); printf("method='%s' (%d)\n", - mrb_sym2name(mrb, sym(tree->cdr->car)), - (int)(intptr_t)tree->cdr->car); + mrb_sym2name(mrb, sym(tree->cdr->car)), + (int)(intptr_t)tree->cdr->car); tree = tree->cdr->cdr->car; if (tree) { dump_prefix(offset+1); 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"); + mrb_parser_dump(mrb, tree->cdr, offset+2); } } break; case NODE_DOT2: printf("NODE_DOT2:\n"); - parser_dump(mrb, tree->car, offset+1); - parser_dump(mrb, tree->cdr, offset+1); + mrb_parser_dump(mrb, tree->car, offset+1); + mrb_parser_dump(mrb, tree->cdr, offset+1); break; case NODE_DOT3: printf("NODE_DOT3:\n"); - parser_dump(mrb, tree->car, offset+1); - parser_dump(mrb, tree->cdr, offset+1); + mrb_parser_dump(mrb, tree->car, offset+1); + mrb_parser_dump(mrb, tree->cdr, offset+1); break; case NODE_COLON2: printf("NODE_COLON2:\n"); - parser_dump(mrb, tree->car, offset+1); + mrb_parser_dump(mrb, tree->car, offset+1); dump_prefix(offset+1); printf("::%s\n", mrb_sym2name(mrb, sym(tree->cdr))); break; @@ -5762,27 +5782,27 @@ parser_dump(mrb_state *mrb, node *tree, int offset) while (tree) { dump_prefix(offset+1); printf("key:\n"); - parser_dump(mrb, tree->car->car, offset+2); + mrb_parser_dump(mrb, tree->car->car, offset+2); dump_prefix(offset+1); printf("value:\n"); - parser_dump(mrb, tree->car->cdr, offset+2); + mrb_parser_dump(mrb, tree->car->cdr, offset+2); tree = tree->cdr; } break; case NODE_SPLAT: printf("NODE_SPLAT:\n"); - parser_dump(mrb, tree, offset+1); + mrb_parser_dump(mrb, tree, offset+1); break; case NODE_ASGN: printf("NODE_ASGN:\n"); dump_prefix(offset+1); printf("lhs:\n"); - parser_dump(mrb, tree->car, offset+2); + mrb_parser_dump(mrb, tree->car, offset+2); dump_prefix(offset+1); printf("rhs:\n"); - parser_dump(mrb, tree->cdr, offset+2); + mrb_parser_dump(mrb, tree->cdr, offset+2); break; case NODE_MASGN: @@ -5793,48 +5813,48 @@ 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 { + mrb_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); printf("rhs:\n"); - parser_dump(mrb, tree->cdr, offset+2); + mrb_parser_dump(mrb, tree->cdr, offset+2); break; case NODE_OP_ASGN: printf("NODE_OP_ASGN:\n"); dump_prefix(offset+1); printf("lhs:\n"); - parser_dump(mrb, tree->car, offset+2); + mrb_parser_dump(mrb, tree->car, offset+2); tree = tree->cdr; dump_prefix(offset+1); printf("op='%s' (%d)\n", mrb_sym2name(mrb, sym(tree->car)), (int)(intptr_t)tree->car); tree = tree->cdr; - parser_dump(mrb, tree->car, offset+1); + mrb_parser_dump(mrb, tree->car, offset+1); break; case NODE_SUPER: @@ -5844,9 +5864,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"); + mrb_parser_dump(mrb, tree->cdr, offset+2); } } break; @@ -5857,7 +5877,7 @@ parser_dump(mrb_state *mrb, node *tree, int offset) case NODE_RETURN: printf("NODE_RETURN:\n"); - parser_dump(mrb, tree, offset+1); + mrb_parser_dump(mrb, tree, offset+1); break; case NODE_YIELD: @@ -5867,12 +5887,12 @@ parser_dump(mrb_state *mrb, node *tree, int offset) case NODE_BREAK: printf("NODE_BREAK:\n"); - parser_dump(mrb, tree, offset+1); + mrb_parser_dump(mrb, tree, offset+1); break; case NODE_NEXT: printf("NODE_NEXT:\n"); - parser_dump(mrb, tree, offset+1); + mrb_parser_dump(mrb, tree, offset+1); break; case NODE_REDO: @@ -5907,10 +5927,10 @@ parser_dump(mrb_state *mrb, node *tree, int offset) printf("NODE_MATCH:\n"); dump_prefix(offset + 1); printf("lhs:\n"); - parser_dump(mrb, tree->car, offset + 2); + mrb_parser_dump(mrb, tree->car, offset + 2); dump_prefix(offset + 1); printf("rhs:\n"); - parser_dump(mrb, tree->cdr, offset + 2); + mrb_parser_dump(mrb, tree->cdr, offset + 2); break; case NODE_BACK_REF: @@ -5927,7 +5947,7 @@ parser_dump(mrb_state *mrb, node *tree, int offset) case NODE_BLOCK_ARG: printf("NODE_BLOCK_ARG:\n"); - parser_dump(mrb, tree, offset+1); + mrb_parser_dump(mrb, tree, offset+1); break; case NODE_INT: @@ -5940,7 +5960,7 @@ parser_dump(mrb_state *mrb, node *tree, int offset) case NODE_NEGATE: printf("NODE_NEGATE\n"); - parser_dump(mrb, tree, offset+1); + mrb_parser_dump(mrb, tree, offset+1); break; case NODE_STR: @@ -5996,8 +6016,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: @@ -6005,8 +6025,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"); @@ -6023,18 +6043,18 @@ parser_dump(mrb_state *mrb, node *tree, int offset) printf("::%s\n", mrb_sym2name(mrb, sym(tree->car->cdr))); } else { - parser_dump(mrb, tree->car->car, offset+1); + mrb_parser_dump(mrb, tree->car->car, offset+1); dump_prefix(offset+1); printf("::%s\n", mrb_sym2name(mrb, sym(tree->car->cdr))); } if (tree->cdr->car) { dump_prefix(offset+1); printf("super:\n"); - parser_dump(mrb, tree->cdr->car, offset+2); + mrb_parser_dump(mrb, tree->cdr->car, offset+2); } dump_prefix(offset+1); printf("body:\n"); - parser_dump(mrb, tree->cdr->cdr->car->cdr, offset+2); + mrb_parser_dump(mrb, tree->cdr->cdr->car->cdr, offset+2); break; case NODE_MODULE: @@ -6048,21 +6068,21 @@ parser_dump(mrb_state *mrb, node *tree, int offset) printf("::%s\n", mrb_sym2name(mrb, sym(tree->car->cdr))); } else { - parser_dump(mrb, tree->car->car, offset+1); + mrb_parser_dump(mrb, tree->car->car, offset+1); dump_prefix(offset+1); printf("::%s\n", mrb_sym2name(mrb, sym(tree->car->cdr))); } dump_prefix(offset+1); printf("body:\n"); - parser_dump(mrb, tree->cdr->car->cdr, offset+2); + mrb_parser_dump(mrb, tree->cdr->car->cdr, offset+2); break; case NODE_SCLASS: printf("NODE_SCLASS:\n"); - parser_dump(mrb, tree->car, offset+1); + mrb_parser_dump(mrb, tree->car, offset+1); dump_prefix(offset+1); printf("body:\n"); - parser_dump(mrb, tree->cdr->car->cdr, offset+2); + mrb_parser_dump(mrb, tree->cdr->car->cdr, offset+2); break; case NODE_DEF: @@ -6074,17 +6094,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; @@ -6092,48 +6112,48 @@ 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))); + mrb_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); + mrb_parser_dump(mrb, tree->cdr->car, offset+1); break; case NODE_SDEF: printf("NODE_SDEF:\n"); - parser_dump(mrb, tree->car, offset+1); + mrb_parser_dump(mrb, tree->car, offset+1); tree = tree->cdr; dump_prefix(offset+1); printf(":%s\n", mrb_sym2name(mrb, sym(tree->car))); @@ -6142,54 +6162,54 @@ 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))); + mrb_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; - parser_dump(mrb, tree->car, offset+1); + mrb_parser_dump(mrb, tree->car, offset+1); break; case NODE_POSTEXE: printf("NODE_POSTEXE:\n"); - parser_dump(mrb, tree, offset+1); + mrb_parser_dump(mrb, tree, offset+1); break; case NODE_HEREDOC: printf("NODE_HEREDOC:\n"); - parser_dump(mrb, ((parser_heredoc_info*)tree)->doc, offset+1); + mrb_parser_dump(mrb, ((parser_heredoc_info*)tree)->doc, offset+1); break; default: diff --git a/src/print.c b/src/print.c index 01c9b3cd0..9d59aa4ff 100644 --- a/src/print.c +++ b/src/print.c @@ -6,6 +6,7 @@ #include "mruby.h" #include "mruby/string.h" +#include "mruby/variable.h" static void printstr(mrb_state *mrb, mrb_value obj) @@ -53,19 +54,19 @@ mrb_print_error(mrb_state *mrb) void mrb_show_version(mrb_state *mrb) { - static const char version_msg[] = "mruby - Embeddable Ruby Copyright (c) 2010-2013 mruby developers\n"; mrb_value msg; - msg = mrb_str_new(mrb, version_msg, sizeof(version_msg) - 1); + msg = mrb_const_get(mrb, mrb_obj_value(mrb->object_class), mrb_intern_lit(mrb, "MRUBY_DESCRIPTION")); printstr(mrb, msg); + printstr(mrb, mrb_str_new_lit(mrb, "\n")); } void mrb_show_copyright(mrb_state *mrb) { - static const char copyright_msg[] = "mruby - Copyright (c) 2010-2013 mruby developers\n"; mrb_value msg; - msg = mrb_str_new(mrb, copyright_msg, sizeof(copyright_msg) - 1); + msg = mrb_const_get(mrb, mrb_obj_value(mrb->object_class), mrb_intern_lit(mrb, "MRUBY_COPYRIGHT")); printstr(mrb, msg); + printstr(mrb, mrb_str_new_lit(mrb, "\n")); } diff --git a/src/proc.c b/src/proc.c index cfb677f0a..1ae1d495e 100644 --- a/src/proc.c +++ b/src/proc.c @@ -17,9 +17,16 @@ struct RProc * mrb_proc_new(mrb_state *mrb, mrb_irep *irep) { struct RProc *p; + mrb_callinfo *ci = mrb->c->ci; p = (struct RProc*)mrb_obj_alloc(mrb, MRB_TT_PROC, mrb->proc_class); - p->target_class = (mrb->c->ci) ? mrb->c->ci->target_class : 0; + p->target_class = 0; + if (ci) { + if (ci->proc) + p->target_class = ci->proc->target_class; + if (!p->target_class) + p->target_class = ci->target_class; + } p->body.irep = irep; p->env = 0; mrb_irep_incref(mrb, irep); @@ -204,8 +211,8 @@ mrb_init_proc(mrb_state *mrb) mrb_define_method(mrb, mrb->proc_class, "arity", mrb_proc_arity, MRB_ARGS_NONE()); m = mrb_proc_new(mrb, call_irep); - mrb_define_method_raw(mrb, mrb->proc_class, mrb_intern2(mrb, "call", 4), m); - mrb_define_method_raw(mrb, mrb->proc_class, mrb_intern2(mrb, "[]", 2), m); + mrb_define_method_raw(mrb, mrb->proc_class, mrb_intern_lit(mrb, "call"), m); + mrb_define_method_raw(mrb, mrb->proc_class, mrb_intern_lit(mrb, "[]"), m); mrb_define_class_method(mrb, mrb->kernel_module, "lambda", proc_lambda, MRB_ARGS_NONE()); /* 15.3.1.2.6 */ mrb_define_method(mrb, mrb->kernel_module, "lambda", proc_lambda, MRB_ARGS_NONE()); /* 15.3.1.3.27 */ diff --git a/src/range.c b/src/range.c index a27ced4cb..171387a8d 100644 --- a/src/range.c +++ b/src/range.c @@ -176,7 +176,7 @@ r_le(mrb_state *mrb, mrb_value a, mrb_value b) mrb_value r = mrb_funcall(mrb, a, "<=>", 1, b); /* compare result */ /* output :a < b => -1, a = b => 0, a > b => +1 */ - if (mrb_type(r) == MRB_TT_FIXNUM) { + if (mrb_fixnum_p(r)) { mrb_int c = mrb_fixnum(r); if (c == 0 || c == -1) return TRUE; } @@ -190,11 +190,7 @@ r_gt(mrb_state *mrb, mrb_value a, mrb_value b) mrb_value r = mrb_funcall(mrb, a, "<=>", 1, b); /* output :a < b => -1, a = b => 0, a > b => +1 */ - if (mrb_type(r) == MRB_TT_FIXNUM) { - if (mrb_fixnum(r) == 1) return TRUE; - } - - return FALSE; + return mrb_fixnum_p(r) && mrb_fixnum(r) == 1; } static mrb_bool @@ -203,7 +199,7 @@ r_ge(mrb_state *mrb, mrb_value a, mrb_value b) mrb_value r = mrb_funcall(mrb, a, "<=>", 1, b); /* compare result */ /* output :a < b => -1, a = b => 0, a > b => +1 */ - if (mrb_type(r) == MRB_TT_FIXNUM) { + if (mrb_fixnum_p(r)) { mrb_int c = mrb_fixnum(r); if (c == 0 || c == 1) return TRUE; } @@ -261,7 +257,7 @@ mrb_range_each(mrb_state *mrb, mrb_value range) return range; } -mrb_int +mrb_bool mrb_range_beg_len(mrb_state *mrb, mrb_value range, mrb_int *begp, mrb_int *lenp, mrb_int len) { mrb_int beg, end, b, e; @@ -380,7 +376,7 @@ range_eql(mrb_state *mrb, mrb_value range) } /* 15.2.14.4.15(x) */ -mrb_value +static mrb_value range_initialize_copy(mrb_state *mrb, mrb_value copy) { mrb_value src; @@ -407,8 +403,6 @@ mrb_init_range(mrb_state *mrb) r = mrb_define_class(mrb, "Range", mrb->object_class); MRB_SET_INSTANCE_TT(r, MRB_TT_RANGE); - mrb_include_module(mrb, r, mrb_class_get(mrb, "Enumerable")); - mrb_define_method(mrb, r, "begin", mrb_range_beg, MRB_ARGS_NONE()); /* 15.2.14.4.3 */ mrb_define_method(mrb, r, "end", mrb_range_end, MRB_ARGS_NONE()); /* 15.2.14.4.5 */ mrb_define_method(mrb, r, "==", mrb_range_eq, MRB_ARGS_REQ(1)); /* 15.2.14.4.1 */ @@ -8,6 +8,5 @@ #define RE_H #define REGEXP_CLASS "Regexp" -#define REGEXP_CLASS_CSTR_LEN 6 #endif diff --git a/src/state.c b/src/state.c index 9ec96068e..620ed7d77 100644 --- a/src/state.c +++ b/src/state.c @@ -7,10 +7,10 @@ #include <stdlib.h> #include <string.h> #include "mruby.h" -#include "mruby/class.h" #include "mruby/irep.h" #include "mruby/variable.h" #include "mruby/debug.h" +#include "mruby/string.h" void mrb_init_heap(mrb_state*); void mrb_init_core(mrb_state*); @@ -19,7 +19,7 @@ void mrb_final_core(mrb_state*); static mrb_value inspect_main(mrb_state *mrb, mrb_value mod) { - return mrb_str_new(mrb, "main", 4); + return mrb_str_new_lit(mrb, "main"); } mrb_state* @@ -41,6 +41,11 @@ mrb_open_allocf(mrb_allocf f, void *ud) mrb->allocf = f; mrb->current_white_part = MRB_GC_WHITE_A; +#ifndef MRB_GC_FIXED_ARENA + mrb->arena = (struct RBasic**)mrb_malloc(mrb, sizeof(struct RBasic*)*MRB_GC_ARENA_SIZE); + mrb->arena_capa = MRB_GC_ARENA_SIZE; +#endif + mrb_init_heap(mrb); mrb->c = (struct mrb_context*)mrb_malloc(mrb, sizeof(struct mrb_context)); *mrb->c = mrb_context_zero; @@ -129,8 +134,17 @@ mrb_irep_free(mrb_state *mrb, mrb_irep *irep) if (!(irep->flags & MRB_ISEQ_NO_FREE)) mrb_free(mrb, irep->iseq); for (i=0; i<irep->plen; i++) { - if (irep->pool[i].type == IREP_TT_STRING) - mrb_free(mrb, irep->pool[i].value.s); + if (mrb_type(irep->pool[i]) == MRB_TT_STRING) { + if ((mrb_str_ptr(irep->pool[i])->flags & MRB_STR_NOFREE) == 0) { + mrb_free(mrb, mrb_str_ptr(irep->pool[i])->ptr); + } + mrb_free(mrb, mrb_obj_ptr(irep->pool[i])); + } +#ifdef MRB_WORD_BOXING + else if (mrb_type(irep->pool[i]) == MRB_TT_FLOAT) { + mrb_free(mrb, mrb_obj_ptr(irep->pool[i])); + } +#endif } mrb_free(mrb, irep->pool); mrb_free(mrb, irep->syms); @@ -144,6 +158,33 @@ mrb_irep_free(mrb_state *mrb, mrb_irep *irep) mrb_free(mrb, irep); } +mrb_value +mrb_str_pool(mrb_state *mrb, mrb_value str) +{ + struct RString *s = mrb_str_ptr(str); + struct RString *ns; + mrb_int len; + + ns = (struct RString *)mrb_malloc(mrb, sizeof(struct RString)); + ns->tt = MRB_TT_STRING; + ns->c = mrb->string_class; + + len = s->len; + ns->len = len; + if (s->flags & MRB_STR_NOFREE) { + ns->ptr = s->ptr; + ns->flags = MRB_STR_NOFREE; + } + else { + ns->ptr = (char *)mrb_malloc(mrb, (size_t)len+1); + if (s->ptr) { + memcpy(ns->ptr, s->ptr, len); + } + ns->ptr[len] = '\0'; + } + return mrb_obj_value(ns); +} + void mrb_free_context(mrb_state *mrb, struct mrb_context *c) { @@ -166,13 +207,12 @@ mrb_close(mrb_state *mrb) mrb_free_symtbl(mrb); mrb_free_heap(mrb); mrb_alloca_free(mrb); +#ifndef MRB_GC_FIXED_ARENA + mrb_free(mrb, mrb->arena); +#endif mrb_free(mrb, mrb); } -#ifndef MRB_IREP_ARRAY_INIT_SIZE -# define MRB_IREP_ARRAY_INIT_SIZE (256u) -#endif - mrb_irep* mrb_add_irep(mrb_state *mrb) { diff --git a/src/string.c b/src/string.c index af70e8e45..c880fbe48 100644 --- a/src/string.c +++ b/src/string.c @@ -5,12 +5,7 @@ */ #include <ctype.h> -#ifndef SIZE_MAX - /* Some versions of VC++ - * has SIZE_MAX in stdint.h - */ -# include <limits.h> -#endif +#include <limits.h> #include <stddef.h> #include <stdlib.h> #include <string.h> @@ -30,9 +25,6 @@ typedef struct mrb_shared_string { mrb_int len; } mrb_shared_string; -#define MRB_STR_SHARED 1 -#define MRB_STR_NOFREE 2 - 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, mrb_int beg, mrb_int len); @@ -92,6 +84,7 @@ mrb_str_modify(mrb_state *mrb, struct RString *s) } s->ptr[s->len] = '\0'; s->aux.capa = s->len; + s->flags &= ~MRB_STR_NOFREE; return; } } @@ -114,16 +107,6 @@ mrb_str_resize(mrb_state *mrb, mrb_value str, mrb_int len) return str; } -static inline void -str_mod_check(mrb_state *mrb, mrb_value str, char *p, mrb_int len) -{ - struct RString *s = mrb_str_ptr(str); - - if (s->ptr != p || s->len != len) { - mrb_raise(mrb, E_RUNTIME_ERROR, "string modified"); - } -} - #define mrb_obj_alloc_string(mrb) ((struct RString*)mrb_obj_alloc((mrb), MRB_TT_STRING, (mrb)->string_class)) /* char offset to byte offset */ @@ -149,7 +132,7 @@ str_new(mrb_state *mrb, const char *p, mrb_int len) return s; } -void +static void str_with_class(mrb_state *mrb, struct RString *s, mrb_value obj) { s->c = mrb_str_ptr(obj)->c; @@ -546,10 +529,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_intern2(mrb, "to_s", 4))) { + if (!mrb_respond_to(mrb, str2, mrb_intern_lit(mrb, "to_s"))) { return mrb_nil_value(); } - else if (!mrb_respond_to(mrb, str2, mrb_intern2(mrb, "<=>", 3))) { + else if (!mrb_respond_to(mrb, str2, mrb_intern_lit(mrb, "<=>"))) { return mrb_nil_value(); } else { @@ -585,7 +568,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_intern2(mrb, "to_str", 6))) { + if (!mrb_respond_to(mrb, str2, mrb_intern_lit(mrb, "to_str"))) { return FALSE; } str2 = mrb_funcall(mrb, str2, "to_str", 0); @@ -758,12 +741,10 @@ num_index: /* check if indx is Range */ { mrb_int beg, len; - mrb_value tmp; len = RSTRING_LEN(str); if (mrb_range_beg_len(mrb, indx, &beg, &len, len)) { - tmp = mrb_str_subseq(mrb, str, beg, len); - return tmp; + return mrb_str_subseq(mrb, str, beg, len); } else { return mrb_nil_value(); @@ -1250,7 +1231,7 @@ mrb_str_include(mrb_state *mrb, mrb_value self) mrb_bool include_p; mrb_get_args(mrb, "o", &str2); - if (mrb_type(str2) == MRB_TT_FIXNUM) { + if (mrb_fixnum_p(str2)) { include_p = (memchr(RSTRING_PTR(self), mrb_fixnum(str2), RSTRING_LEN(self)) != NULL); } else { @@ -2024,7 +2005,7 @@ mrb_string_value_cstr(mrb_state *mrb, mrb_value *ptr) } mrb_value -mrb_str_to_inum(mrb_state *mrb, mrb_value str, int base, int badcheck) +mrb_str_to_inum(mrb_state *mrb, mrb_value str, int base, mrb_bool badcheck) { char *s; int len; @@ -2087,7 +2068,7 @@ mrb_str_to_i(mrb_state *mrb, mrb_value self) } double -mrb_cstr_to_dbl(mrb_state *mrb, const char * p, int badcheck) +mrb_cstr_to_dbl(mrb_state *mrb, const char * p, mrb_bool badcheck) { char *end; double d; @@ -2156,7 +2137,7 @@ bad: } double -mrb_str_to_dbl(mrb_state *mrb, mrb_value str, int badcheck) +mrb_str_to_dbl(mrb_state *mrb, mrb_value str, mrb_bool badcheck) { char *s; int len; @@ -2429,7 +2410,7 @@ mrb_str_inspect(mrb_state *mrb, mrb_value str) p = RSTRING_PTR(str); pend = RSTRING_END(str); for (;p < pend; p++) { - unsigned int c, cc; + unsigned char c, cc; c = *p; if (c == '"'|| c == '\\' || (c == '#' && IS_EVSTR(p, pend))) { @@ -2504,8 +2485,6 @@ mrb_init_string(mrb_state *mrb) s = mrb->string_class = mrb_define_class(mrb, "String", mrb->object_class); MRB_SET_INSTANCE_TT(s, MRB_TT_STRING); - mrb_include_module(mrb, s, mrb_class_get(mrb, "Comparable")); - mrb_define_method(mrb, s, "bytesize", mrb_str_bytesize, MRB_ARGS_NONE()); diff --git a/src/symbol.c b/src/symbol.c index e49462e27..b311551c0 100644 --- a/src/symbol.c +++ b/src/symbol.c @@ -5,7 +5,6 @@ */ #include <ctype.h> -#include <limits.h> #include <string.h> #include "mruby.h" #include "mruby/khash.h" @@ -13,7 +12,8 @@ /* ------------------------------------------------------ */ typedef struct symbol_name { - size_t len; + mrb_bool lit; + uint16_t len; const char *name; } symbol_name; @@ -34,8 +34,8 @@ sym_hash_func(mrb_state *mrb, const symbol_name s) 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, size_t len) +static mrb_sym +sym_intern(mrb_state *mrb, const char *name, size_t len, int lit) { khash_t(n2s) *h = mrb->name2sym; symbol_name sname; @@ -43,33 +43,54 @@ mrb_intern2(mrb_state *mrb, const char *name, size_t len) mrb_sym sym; char *p; + if (len > UINT16_MAX) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "symbol length too long"); + } + sname.lit = lit; sname.len = len; sname.name = name; - k = kh_get(n2s, h, sname); + k = kh_get(n2s, mrb, h, sname); if (k != kh_end(h)) return kh_value(h, k); sym = ++mrb->symidx; - p = (char *)mrb_malloc(mrb, len+1); - memcpy(p, name, len); - p[len] = 0; - sname.name = (const char*)p; - k = kh_put(n2s, h, sname); + if (lit) { + sname.name = name; + } + else { + p = (char *)mrb_malloc(mrb, len+1); + memcpy(p, name, len); + p[len] = 0; + sname.name = (const char*)p; + } + k = kh_put(n2s, mrb, h, sname); kh_value(h, k) = sym; return sym; } mrb_sym +mrb_intern(mrb_state *mrb, const char *name, size_t len) +{ + return sym_intern(mrb, name, len, 0); +} + +mrb_sym +mrb_intern_static(mrb_state *mrb, const char *name, size_t len) +{ + return sym_intern(mrb, name, len, 1); +} + +mrb_sym mrb_intern_cstr(mrb_state *mrb, const char *name) { - return mrb_intern2(mrb, name, strlen(name)); + return mrb_intern(mrb, name, strlen(name)); } mrb_sym mrb_intern_str(mrb_state *mrb, mrb_value str) { - return mrb_intern2(mrb, RSTRING_PTR(str), RSTRING_LEN(str)); + return mrb_intern(mrb, RSTRING_PTR(str), RSTRING_LEN(str)); } mrb_value @@ -79,10 +100,13 @@ mrb_check_intern(mrb_state *mrb, const char *name, size_t len) symbol_name sname; khiter_t k; + if (len > UINT16_MAX) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "symbol length too long"); + } sname.len = len; sname.name = name; - k = kh_get(n2s, h, sname); + k = kh_get(n2s, mrb, h, sname); if (k != kh_end(h)) { return mrb_symbol_value(kh_value(h, k)); } @@ -129,8 +153,14 @@ mrb_free_symtbl(mrb_state *mrb) khiter_t k; for (k = kh_begin(h); k != kh_end(h); k++) - if (kh_exist(h, k)) mrb_free(mrb, (char*)kh_key(h, k).name); - kh_destroy(n2s,mrb->name2sym); + if (kh_exist(h, k)) { + symbol_name s = kh_key(h, k); + + if (!s.lit) { + mrb_free(mrb, (char*)s.name); + } + } + kh_destroy(n2s, mrb, mrb->name2sym); } void @@ -278,7 +308,7 @@ static mrb_bool symname_p(const char *name) { const char *m = name; - int localid = FALSE; + mrb_bool localid = FALSE; if (!m) return FALSE; switch (*m) { @@ -381,14 +411,9 @@ mrb_sym2str(mrb_state *mrb, mrb_sym sym) { size_t len; const char *name = mrb_sym2name_len(mrb, sym, &len); - mrb_value str; if (!name) return mrb_undef_value(); /* can't happen */ - str = mrb_str_new_static(mrb, name, len); - if (symname_p(name) && strlen(name) == len) { - return str; - } - return mrb_str_dump(mrb, str); + return mrb_str_new_static(mrb, name, len); } const char* diff --git a/src/variable.c b/src/variable.c index ffad3dad3..de56c3ce6 100644 --- a/src/variable.c +++ b/src/variable.c @@ -4,14 +4,12 @@ ** See Copyright Notice in mruby.h */ +#include <ctype.h> #include "mruby.h" #include "mruby/array.h" #include "mruby/class.h" #include "mruby/proc.h" #include "mruby/string.h" -#include "mruby/variable.h" -#include "error.h" -#include <ctype.h> typedef int (iv_foreach_func)(mrb_state*,mrb_sym,mrb_value,void*); @@ -311,7 +309,7 @@ iv_put(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value val) khash_t(iv) *h = &t->h; khiter_t k; - k = kh_put(iv, h, sym); + k = kh_put(iv, mrb, h, sym); kh_value(h, k) = val; } @@ -321,7 +319,7 @@ iv_get(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp) khash_t(iv) *h = &t->h; khiter_t k; - k = kh_get(iv, h, sym); + k = kh_get(iv, mrb, h, sym); if (k != kh_end(h)) { if (vp) *vp = kh_value(h, k); return TRUE; @@ -336,10 +334,10 @@ iv_del(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp) khiter_t k; if (h) { - k = kh_get(iv, h, sym); + k = kh_get(iv, mrb, h, sym); if (k != kh_end(h)) { mrb_value val = kh_value(h, k); - kh_del(iv, h, k); + kh_del(iv, mrb, h, k); if (vp) *vp = val; return TRUE; } @@ -360,7 +358,7 @@ iv_foreach(mrb_state *mrb, iv_tbl *t, iv_foreach_func *func, void *p) n = (*func)(mrb, kh_key(h, k), kh_value(h, k), p); if (n > 0) return FALSE; if (n < 0) { - kh_del(iv, h, k); + kh_del(iv, mrb, h, k); } } } @@ -386,7 +384,7 @@ iv_copy(mrb_state *mrb, iv_tbl *t) static void iv_free(mrb_state *mrb, iv_tbl *t) { - kh_destroy(iv, &t->h); + kh_destroy(iv, mrb, &t->h); } #endif @@ -563,6 +561,7 @@ inspect_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p) mrb_value str = *(mrb_value*)p; const char *s; size_t len; + mrb_value ins; /* need not to show internal data */ if (RSTRING_PTR(str)[0] == '-') { /* first element */ @@ -575,7 +574,13 @@ inspect_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p) s = mrb_sym2name_len(mrb, sym, &len); mrb_str_cat(mrb, str, s, len); mrb_str_cat(mrb, str, "=", 1); - mrb_str_append(mrb, str, mrb_inspect(mrb, v)); + if (mrb_type(v) == MRB_TT_OBJECT) { + ins = mrb_any_to_s(mrb, v); + } + else { + ins = mrb_inspect(mrb, v); + } + mrb_str_append(mrb, str, ins); return 0; } @@ -749,7 +754,7 @@ mrb_cv_get(mrb_state *mrb, mrb_value mod, mrb_sym sym) } void -mrb_mod_cv_set(mrb_state *mrb, struct RClass * c, mrb_sym sym, mrb_value v) +mrb_mod_cv_set(mrb_state *mrb, struct RClass *c, mrb_sym sym, mrb_value v) { struct RClass * cls = c; @@ -816,24 +821,7 @@ mrb_vm_cv_set(mrb_state *mrb, mrb_sym sym, mrb_value v) struct RClass *c = mrb->c->ci->proc->target_class; if (!c) c = mrb->c->ci->target_class; - while (c) { - if (c->iv) { - iv_tbl *t = c->iv; - - if (iv_get(mrb, t, sym, NULL)) { - mrb_write_barrier(mrb, (struct RBasic*)c); - iv_put(mrb, t, sym, v); - return; - } - } - c = c->super; - } - c = mrb->c->ci->target_class; - if (!c->iv) { - c->iv = iv_new(mrb); - } - mrb_write_barrier(mrb, (struct RBasic*)c); - iv_put(mrb, c->iv, sym, v); + mrb_mod_cv_set(mrb, c, sym, v); } mrb_bool @@ -884,7 +872,7 @@ L_RETRY: goto L_RETRY; } name = mrb_symbol_value(sym); - return mrb_funcall_argv(mrb, mrb_obj_value(base), mrb_intern2(mrb, "const_missing", 13), 1, &name); + return mrb_funcall_argv(mrb, mrb_obj_value(base), mrb_intern_lit(mrb, "const_missing"), 1, &name); } mrb_value @@ -963,7 +951,7 @@ const_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p) ary = *(mrb_value*)p; s = mrb_sym2name_len(mrb, sym, &len); - if (len > 1 && ISUPPER(s[0])) { + if (len >= 1 && ISUPPER(s[0])) { mrb_ary_push(mrb, ary, mrb_symbol_value(sym)); } return 0; @@ -1064,7 +1052,7 @@ mrb_f_global_variables(mrb_state *mrb, mrb_value self) buf[2] = 0; for (i = 1; i <= 9; ++i) { buf[1] = (char)(i + '0'); - mrb_ary_push(mrb, ary, mrb_symbol_value(mrb_intern2(mrb, buf, 2))); + mrb_ary_push(mrb, ary, mrb_symbol_value(mrb_intern(mrb, buf, 2))); } return ary; } @@ -1127,7 +1115,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_intern2(mrb, "__classid__", 11)); + name = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern_lit(mrb, "__classid__")); if (mrb_nil_p(name)) { if (!outer) return 0; diff --git a/src/version.c b/src/version.c new file mode 100644 index 000000000..4d57ed93e --- /dev/null +++ b/src/version.c @@ -0,0 +1,13 @@ +#include "mruby.h" +#include "mruby/variable.h" +#include "mruby/version.h" + +void +mrb_init_version(mrb_state* mrb) +{ + mrb_define_global_const(mrb, "RUBY_VERSION", mrb_str_new_lit(mrb, MRUBY_RUBY_VERSION)); + mrb_define_global_const(mrb, "MRUBY_VERSION", mrb_str_new_lit(mrb, MRUBY_VERSION)); + mrb_define_global_const(mrb, "MRUBY_RELEASE_DATE", mrb_str_new_lit(mrb, MRUBY_RELEASE_DATE)); + mrb_define_global_const(mrb, "MRUBY_DESCRIPTION", mrb_str_new_lit(mrb, MRUBY_DESCRIPTION)); + mrb_define_global_const(mrb, "MRUBY_COPYRIGHT", mrb_str_new_lit(mrb, MRUBY_COPYRIGHT)); +} @@ -4,7 +4,6 @@ ** See Copyright Notice in mruby.h */ -#include <string.h> #include <setjmp.h> #include <stddef.h> #include <stdarg.h> @@ -13,7 +12,6 @@ #include "mruby/class.h" #include "mruby/hash.h" #include "mruby/irep.h" -#include "mruby/numeric.h" #include "mruby/proc.h" #include "mruby/range.h" #include "mruby/string.h" @@ -69,6 +67,8 @@ The value below allows about 60000 recursive calls in the simplest case. */ #define TO_STR(x) TO_STR_(x) #define TO_STR_(x) #x +#define ARENA_RESTORE(mrb,ai) (mrb)->arena_idx = (ai) + static inline void stack_clear(mrb_value *from, size_t count) { @@ -109,6 +109,7 @@ stack_init(mrb_state *mrb) c->ciend = c->cibase + CALLINFO_INIT_SIZE; c->ci = c->cibase; c->ci->target_class = mrb->object_class; + c->ci->stackent = c->stack; } static inline void @@ -116,6 +117,7 @@ envadjust(mrb_state *mrb, mrb_value *oldbase, mrb_value *newbase) { mrb_callinfo *ci = mrb->c->cibase; + if (newbase == oldbase) return; while (ci <= mrb->c->ci) { struct REnv *e = ci->env; if (e && e->cioff >= 0) { @@ -123,6 +125,7 @@ envadjust(mrb_state *mrb, mrb_value *oldbase, mrb_value *newbase) e->stack = newbase + off; } + ci->stackent = newbase + (ci->stackent - oldbase); ci++; } } @@ -130,39 +133,39 @@ envadjust(mrb_state *mrb, mrb_value *oldbase, mrb_value *newbase) /** def rec ; $deep =+ 1 ; if $deep > 1000 ; return 0 ; end ; rec ; end */ static void +stack_extend_alloc(mrb_state *mrb, int room) +{ + mrb_value *oldbase = mrb->c->stbase; + int size = mrb->c->stend - mrb->c->stbase; + int off = mrb->c->stack - mrb->c->stbase; + + /* Use linear stack growth. + It is slightly slower than doubling the stack space, + but it saves memory on small devices. */ + if (room <= size) + size += MRB_STACK_GROWTH; + else + size += room; + + mrb->c->stbase = (mrb_value *)mrb_realloc(mrb, mrb->c->stbase, sizeof(mrb_value) * size); + mrb->c->stack = mrb->c->stbase + off; + mrb->c->stend = mrb->c->stbase + size; + envadjust(mrb, oldbase, mrb->c->stbase); + /* Raise an exception if the new stack size will be too large, + to prevent infinite recursion. However, do this only after resizing the stack, so mrb_raise has stack space to work with. */ + if (size > MRB_STACK_MAX) { + mrb_raise(mrb, E_RUNTIME_ERROR, "stack level too deep. (limit=" TO_STR(MRB_STACK_MAX) ")"); + } +} + +static inline void stack_extend(mrb_state *mrb, int room, int keep) { if (mrb->c->stack + room >= mrb->c->stend) { - int size, off; - - mrb_value *oldbase = mrb->c->stbase; - - size = mrb->c->stend - mrb->c->stbase; - off = mrb->c->stack - mrb->c->stbase; - - /* do not leave uninitialized malloc region */ - if (keep > size) keep = size; - - /* Use linear stack growth. - It is slightly slower than doubling thestack space, - but it saves memory on small devices. */ - if (room <= size) - size += MRB_STACK_GROWTH; - else - size += room; - - mrb->c->stbase = (mrb_value *)mrb_realloc(mrb, mrb->c->stbase, sizeof(mrb_value) * size); - mrb->c->stack = mrb->c->stbase + off; - mrb->c->stend = mrb->c->stbase + size; - envadjust(mrb, oldbase, mrb->c->stbase); - /* Raise an exception if the new stack size will be too large, - to prevent infinite recursion. However, do this only after resizing the stack, so mrb_raise has stack space to work with. */ - if (size > MRB_STACK_MAX) { - mrb_raise(mrb, E_RUNTIME_ERROR, "stack level too deep. (limit=" TO_STR(MRB_STACK_MAX) ")"); - } + stack_extend_alloc(mrb, room); } - if (room > keep) { + /* do not leave uninitialized malloc region */ stack_clear(&(mrb->c->stack[keep]), room - keep); } } @@ -229,6 +232,7 @@ cipush(mrb_state *mrb) ci->ridx = ridx; ci->env = 0; ci->pc = 0; + ci->err = 0; return ci; } @@ -261,8 +265,10 @@ ecall(mrb_state *mrb, int i) p = mrb->c->ensure[i]; if (!p) return; + if (mrb->c->ci->eidx > i) + mrb->c->ci->eidx = i; ci = cipush(mrb); - ci->stackidx = mrb->c->stack - mrb->c->stbase; + ci->stackent = mrb->c->stack; ci->mid = ci[-1].mid; ci->acc = CI_ACC_SKIP; ci->argc = 0; @@ -326,7 +332,7 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, int argc, mr if (setjmp(c_jmp) != 0) { /* error */ while (old_ci != mrb->c->ci) { - mrb->c->stack = mrb->c->stbase + mrb->c->ci->stackidx; + mrb->c->stack = mrb->c->ci->stackent; cipop(mrb); } mrb->jmp = 0; @@ -357,14 +363,14 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, int argc, mr p = mrb_method_search_vm(mrb, &c, mid); if (!p) { undef = mid; - mid = mrb_intern2(mrb, "method_missing", 14); + mid = mrb_intern_lit(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->c->stack - mrb->c->stbase; + ci->stackent = mrb->c->stack; ci->argc = argc; ci->target_class = c; if (MRB_PROC_CFUNC_P(p)) { @@ -391,7 +397,7 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, int argc, mr ci->acc = CI_ACC_DIRECT; val = p->body.func(mrb, self); - mrb->c->stack = mrb->c->stbase + mrb->c->ci->stackidx; + mrb->c->stack = mrb->c->ci->stackent; cipop(mrb); mrb_gc_arena_restore(mrb, ai); } @@ -426,7 +432,7 @@ mrb_yield_internal(mrb_state *mrb, mrb_value b, int argc, mrb_value *argv, mrb_v ci = cipush(mrb); ci->mid = mid; ci->proc = p; - ci->stackidx = mrb->c->stack - mrb->c->stbase; + ci->stackent = mrb->c->stack; ci->argc = argc; ci->target_class = c; if (MRB_PROC_CFUNC_P(p)) { @@ -447,7 +453,7 @@ mrb_yield_internal(mrb_state *mrb, mrb_value b, int argc, mrb_value *argv, mrb_v if (MRB_PROC_CFUNC_P(p)) { val = p->body.func(mrb, self); - mrb->c->stack = mrb->c->stbase + mrb->c->ci->stackidx; + mrb->c->stack = mrb->c->ci->stackent; cipop(mrb); } else { @@ -490,7 +496,7 @@ localjump_error(mrb_state *mrb, localjump_error_kind kind) msg = mrb_str_buf_new(mrb, sizeof(lead) + 7); 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); + exc = mrb_exc_new_str(mrb, E_LOCALJUMP_ERROR, msg); mrb->exc = mrb_obj_ptr(exc); } @@ -509,11 +515,12 @@ argnum_error(mrb_state *mrb, int num) str = mrb_format(mrb, "wrong number of arguments (%S for %S)", mrb_fixnum_value(mrb->c->ci->argc), mrb_fixnum_value(num)); } - exc = mrb_exc_new3(mrb, E_ARGUMENT_ERROR, str); + exc = mrb_exc_new_str(mrb, E_ARGUMENT_ERROR, str); mrb->exc = mrb_obj_ptr(exc); } -#define ERR_PC_HOOK(mrb, pc) mrb->c->ci->err = pc; +#define ERR_PC_SET(mrb, pc) mrb->c->ci->err = pc; +#define ERR_PC_CLR(mrb) mrb->c->ci->err = 0; #ifdef ENABLE_DEBUG #define CODE_FETCH_HOOK(mrb, irep, pc, regs) if ((mrb)->code_fetch_hook) (mrb)->code_fetch_hook((mrb), (irep), (pc), (regs)); #else @@ -554,7 +561,7 @@ mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int /* mrb_assert(mrb_proc_cfunc_p(proc)) */ mrb_irep *irep = proc->body.irep; mrb_code *pc = irep->iseq; - struct irep_pool *pool = irep->pool; + mrb_value *pool = irep->pool; mrb_sym *syms = irep->syms; mrb_value *regs = NULL; mrb_code i; @@ -598,7 +605,6 @@ mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int stack_init(mrb); } stack_extend(mrb, irep->nregs, stack_keep); - mrb->c->ci->err = pc; mrb->c->ci->proc = proc; mrb->c->ci->nregs = irep->nregs + 1; regs = mrb->c->stack; @@ -618,10 +624,7 @@ mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int CASE(OP_LOADL) { /* A Bx R(A) := Pool(Bx) */ - if (pool[GETARG_Bx(i)].type == IREP_TT_FLOAT) - SET_FLT_VALUE(mrb, regs[GETARG_A(i)], pool[GETARG_Bx(i)].value.f); - else - SET_INT_VALUE(regs[GETARG_A(i)], pool[GETARG_Bx(i)].value.i); + regs[GETARG_A(i)] = pool[GETARG_Bx(i)]; NEXT; } @@ -693,8 +696,9 @@ mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int CASE(OP_GETCV) { /* A B R(A) := ivget(Sym(B)) */ - ERR_PC_HOOK(mrb, pc); + ERR_PC_SET(mrb, pc); regs[GETARG_A(i)] = mrb_vm_cv_get(mrb, syms[GETARG_Bx(i)]); + ERR_PC_CLR(mrb); NEXT; } @@ -708,8 +712,9 @@ mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int /* A B R(A) := constget(Sym(B)) */ mrb_value val; - ERR_PC_HOOK(mrb, pc); + ERR_PC_SET(mrb, pc); val = mrb_vm_const_get(mrb, syms[GETARG_Bx(i)]); + ERR_PC_CLR(mrb); regs = mrb->c->stack; regs[GETARG_A(i)] = val; NEXT; @@ -726,8 +731,9 @@ mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int mrb_value val; int a = GETARG_A(i); - ERR_PC_HOOK(mrb, pc); + ERR_PC_SET(mrb, pc); val = mrb_const_get(mrb, regs[a], syms[GETARG_Bx(i)]); + ERR_PC_CLR(mrb); regs = mrb->c->stack; regs[a] = val; NEXT; @@ -843,19 +849,20 @@ mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int mrb->c->ensure = (struct RProc **)mrb_realloc(mrb, mrb->c->ensure, sizeof(struct RProc*) * mrb->c->esize); } mrb->c->ensure[mrb->c->ci->eidx++] = p; - mrb_gc_arena_restore(mrb, ai); + ARENA_RESTORE(mrb, ai); NEXT; } CASE(OP_EPOP) { /* A A.times{ensure_pop().call} */ - int n; int a = GETARG_A(i); + mrb_callinfo *ci = mrb->c->ci; + int n, eidx = ci->eidx; - for (n=0; n<a; n++) { - ecall(mrb, --mrb->c->ci->eidx); + for (n=0; n<a && eidx > ci[-1].eidx; n++) { + ecall(mrb, --eidx); + ARENA_RESTORE(mrb, ai); } - mrb_gc_arena_restore(mrb, ai); NEXT; } @@ -896,7 +903,7 @@ mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int if (!m) { mrb_value sym = mrb_symbol_value(mid); - mid = mrb_intern2(mrb, "method_missing", 14); + mid = mrb_intern_lit(mrb, "method_missing"); m = mrb_method_search_vm(mrb, &c, mid); if (n == CALL_MAXARGS) { mrb_ary_unshift(mrb, regs[a+1], sym); @@ -911,7 +918,7 @@ mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int ci = cipush(mrb); ci->mid = mid; ci->proc = m; - ci->stackidx = mrb->c->stack - mrb->c->stbase; + ci->stackent = mrb->c->stack; if (n == CALL_MAXARGS) { ci->argc = -1; } @@ -951,7 +958,7 @@ mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int syms = irep->syms; } } - regs = mrb->c->stack = mrb->c->stbase + ci->stackidx; + regs = mrb->c->stack = ci->stackent; pc = ci->pc; cipop(mrb); JUMP; @@ -1006,7 +1013,7 @@ mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int if (mrb->exc) goto L_RAISE; /* pop stackpos */ ci = mrb->c->ci; - regs = mrb->c->stack = mrb->c->stbase + ci->stackidx; + regs = mrb->c->stack = ci->stackent; regs[ci->acc] = recv; pc = ci->pc; cipop(mrb); @@ -1053,7 +1060,7 @@ mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int c = mrb->c->ci->target_class->super; m = mrb_method_search_vm(mrb, &c, mid); if (!m) { - mid = mrb_intern2(mrb, "method_missing", 14); + mid = mrb_intern_lit(mrb, "method_missing"); m = mrb_method_search_vm(mrb, &c, mid); if (n == CALL_MAXARGS) { mrb_ary_unshift(mrb, regs[a+1], mrb_symbol_value(ci->mid)); @@ -1068,7 +1075,7 @@ mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int ci = cipush(mrb); ci->mid = mid; ci->proc = m; - ci->stackidx = mrb->c->stack - mrb->c->stbase; + ci->stackent = mrb->c->stack; if (n == CALL_MAXARGS) { ci->argc = -1; } @@ -1087,7 +1094,7 @@ mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int mrb_gc_arena_restore(mrb, ai); if (mrb->exc) goto L_RAISE; /* pop stackpos */ - regs = mrb->c->stack = mrb->c->stbase + mrb->c->ci->stackidx; + regs = mrb->c->stack = mrb->c->ci->stackent; cipop(mrb); NEXT; } @@ -1161,7 +1168,7 @@ mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int rest->len = m1+len+m2; } regs[a+1] = stack[m1+r+m2]; - mrb_gc_arena_restore(mrb, ai); + ARENA_RESTORE(mrb, ai); NEXT; } @@ -1266,8 +1273,8 @@ mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int L_RAISE: ci = mrb->c->ci; - mrb_obj_iv_ifnone(mrb, mrb->exc, mrb_intern2(mrb, "lastpc", 6), mrb_cptr_value(mrb, pc)); - mrb_obj_iv_ifnone(mrb, mrb->exc, mrb_intern2(mrb, "ciidx", 5), mrb_fixnum_value(ci - mrb->c->cibase)); + mrb_obj_iv_ifnone(mrb, mrb->exc, mrb_intern_lit(mrb, "lastpc"), mrb_cptr_value(mrb, pc)); + mrb_obj_iv_ifnone(mrb, mrb->exc, mrb_intern_lit(mrb, "ciidx"), mrb_fixnum_value(ci - mrb->c->cibase)); eidx = ci->eidx; if (ci == mrb->c->cibase) { if (ci->ridx == 0) goto L_STOP; @@ -1279,15 +1286,17 @@ mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int while (ci[0].ridx == ci[-1].ridx) { cipop(mrb); ci = mrb->c->ci; - mrb->c->stack = mrb->c->stbase + ci[1].stackidx; + mrb->c->stack = ci[1].stackent; if (ci[1].acc == CI_ACC_SKIP && prev_jmp) { mrb->jmp = prev_jmp; mrb_longjmp(mrb); } - while (eidx > ci->eidx) { - ecall(mrb, --eidx); + if (ci > mrb->c->cibase) { + while (eidx > ci[-1].eidx) { + ecall(mrb, --eidx); + } } - if (ci == mrb->c->cibase) { + else if (ci == mrb->c->cibase) { if (ci->ridx == 0) { regs = mrb->c->stack = mrb->c->stbase; goto L_STOP; @@ -1299,7 +1308,7 @@ mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int irep = ci->proc->body.irep; pool = irep->pool; syms = irep->syms; - regs = mrb->c->stack = mrb->c->stbase + ci[1].stackidx; + regs = mrb->c->stack = ci[1].stackent; pc = mrb->c->rescue[--ci->ridx]; } else { @@ -1332,7 +1341,7 @@ mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int goto L_RAISE; } if (mrb->c->prev->ci == mrb->c->prev->cibase) { - mrb_value exc = mrb_exc_new3(mrb, E_RUNTIME_ERROR, mrb_str_new(mrb, "double resume", 13)); + mrb_value exc = mrb_exc_new_str(mrb, E_RUNTIME_ERROR, mrb_str_new(mrb, "double resume", 13)); mrb->exc = mrb_obj_ptr(exc); goto L_RAISE; } @@ -1344,7 +1353,7 @@ mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int ci = mrb->c->ci; break; case OP_R_BREAK: - if (proc->env->cioff < 0) { + if (!proc->env || proc->env->cioff < 0) { localjump_error(mrb, LOCALJUMP_ERROR_BREAK); goto L_RAISE; } @@ -1360,7 +1369,7 @@ mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int cipop(mrb); acc = ci->acc; pc = ci->pc; - regs = mrb->c->stack = mrb->c->stbase + ci->stackidx; + regs = mrb->c->stack = ci->stackent; if (acc == CI_ACC_SKIP) { mrb->jmp = prev_jmp; return v; @@ -1392,7 +1401,7 @@ mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int if (!m) { mrb_value sym = mrb_symbol_value(mid); - mid = mrb_intern2(mrb, "method_missing", 14); + mid = mrb_intern_lit(mrb, "method_missing"); m = mrb_method_search_vm(mrb, &c, mid); if (n == CALL_MAXARGS) { mrb_ary_unshift(mrb, regs[a+1], sym); @@ -1536,7 +1545,7 @@ mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int default: goto L_SEND; } - mrb_gc_arena_restore(mrb, ai); + ARENA_RESTORE(mrb, ai); NEXT; } @@ -1853,7 +1862,7 @@ mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int CASE(OP_ARRAY) { /* A B C R(A) := ary_new(R(B),R(B+1)..R(B+C)) */ regs[GETARG_A(i)] = mrb_ary_new_from_values(mrb, GETARG_C(i), ®s[GETARG_B(i)]); - mrb_gc_arena_restore(mrb, ai); + ARENA_RESTORE(mrb, ai); NEXT; } @@ -1861,7 +1870,7 @@ mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int /* A B mrb_ary_concat(R(A),R(B)) */ mrb_ary_concat(mrb, regs[GETARG_A(i)], mrb_ary_splat(mrb, regs[GETARG_B(i)])); - mrb_gc_arena_restore(mrb, ai); + ARENA_RESTORE(mrb, ai); NEXT; } @@ -1933,14 +1942,14 @@ mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int } } } - mrb_gc_arena_restore(mrb, ai); + ARENA_RESTORE(mrb, ai); NEXT; } CASE(OP_STRING) { /* A Bx R(A) := str_new(Lit(Bx)) */ - regs[GETARG_A(i)] = mrb_str_new(mrb, pool[GETARG_Bx(i)].value.s->buf, pool[GETARG_Bx(i)].value.s->len); - mrb_gc_arena_restore(mrb, ai); + regs[GETARG_A(i)] = mrb_str_dup(mrb, pool[GETARG_Bx(i)]); + ARENA_RESTORE(mrb, ai); NEXT; } @@ -1962,7 +1971,7 @@ mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int b+=2; } regs[GETARG_A(i)] = hash; - mrb_gc_arena_restore(mrb, ai); + ARENA_RESTORE(mrb, ai); NEXT; } @@ -1979,7 +1988,7 @@ mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int } if (c & OP_L_STRICT) p->flags |= MRB_PROC_STRICT; regs[GETARG_A(i)] = mrb_obj_value(p); - mrb_gc_arena_restore(mrb, ai); + ARENA_RESTORE(mrb, ai); NEXT; } @@ -2003,7 +2012,7 @@ mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int } c = mrb_vm_define_class(mrb, base, super, id); regs[a] = mrb_obj_value(c); - mrb_gc_arena_restore(mrb, ai); + ARENA_RESTORE(mrb, ai); NEXT; } @@ -2020,7 +2029,7 @@ mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int } c = mrb_vm_define_module(mrb, base, id); regs[a] = mrb_obj_value(c); - mrb_gc_arena_restore(mrb, ai); + ARENA_RESTORE(mrb, ai); NEXT; } @@ -2036,7 +2045,7 @@ mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int ci->pc = pc + 1; ci->acc = a; ci->mid = 0; - ci->stackidx = mrb->c->stack - mrb->c->stbase; + ci->stackent = mrb->c->stack; ci->argc = 0; ci->target_class = mrb_class_ptr(recv); @@ -2052,7 +2061,7 @@ mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int mrb_gc_arena_restore(mrb, ai); if (mrb->exc) goto L_RAISE; /* pop stackpos */ - regs = mrb->c->stack = mrb->c->stbase + mrb->c->ci->stackidx; + regs = mrb->c->stack = mrb->c->ci->stackent; cipop(mrb); NEXT; } @@ -2074,14 +2083,14 @@ mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int struct RClass *c = mrb_class_ptr(regs[a]); mrb_define_method_vm(mrb, c, syms[GETARG_B(i)], regs[a+1]); - mrb_gc_arena_restore(mrb, ai); + ARENA_RESTORE(mrb, ai); NEXT; } CASE(OP_SCLASS) { /* A B R(A) := R(B).singleton_class */ regs[GETARG_A(i)] = mrb_singleton_class(mrb, regs[GETARG_B(i)]); - mrb_gc_arena_restore(mrb, ai); + ARENA_RESTORE(mrb, ai); NEXT; } @@ -2101,17 +2110,21 @@ mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int /* A B C R(A) := range_new(R(B),R(B+1),C) */ int b = GETARG_B(i); regs[GETARG_A(i)] = mrb_range_new(mrb, regs[b], regs[b+1], GETARG_C(i)); - mrb_gc_arena_restore(mrb, ai); + ARENA_RESTORE(mrb, ai); NEXT; } CASE(OP_DEBUG) { /* A debug print R(A),R(B),R(C) */ +#ifdef ENABLE_DEBUG + mrb->debug_op_hook(mrb, irep, pc, regs); +#else #ifdef ENABLE_STDIO printf("OP_DEBUG %d %d %d\n", GETARG_A(i), GETARG_B(i), GETARG_C(i)); #else abort(); #endif +#endif NEXT; } @@ -2125,6 +2138,7 @@ mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int ecall(mrb, n); } } + ERR_PC_CLR(mrb); mrb->jmp = prev_jmp; if (mrb->exc) { return mrb_obj_value(mrb->exc); @@ -2134,14 +2148,14 @@ mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int CASE(OP_ERR) { /* Bx raise RuntimeError with message Lit(Bx) */ - mrb_value msg = mrb_str_new(mrb, pool[GETARG_Bx(i)].value.s->buf, pool[GETARG_Bx(i)].value.s->len); + mrb_value msg = mrb_str_dup(mrb, pool[GETARG_Bx(i)]); mrb_value exc; if (GETARG_A(i) == 0) { - exc = mrb_exc_new3(mrb, E_RUNTIME_ERROR, msg); + exc = mrb_exc_new_str(mrb, E_RUNTIME_ERROR, msg); } else { - exc = mrb_exc_new3(mrb, E_LOCALJUMP_ERROR, msg); + exc = mrb_exc_new_str(mrb, E_LOCALJUMP_ERROR, msg); } mrb->exc = mrb_obj_ptr(exc); goto L_RAISE; |
