diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/array.c | 176 | ||||
| -rw-r--r-- | src/backtrace.c | 28 | ||||
| -rw-r--r-- | src/class.c | 14 | ||||
| -rw-r--r-- | src/codegen.c | 23 | ||||
| -rw-r--r-- | src/dump.c | 11 | ||||
| -rw-r--r-- | src/error.c | 11 | ||||
| -rw-r--r-- | src/error.h | 2 | ||||
| -rw-r--r-- | src/etc.c | 47 | ||||
| -rw-r--r-- | src/gc.c | 33 | ||||
| -rw-r--r-- | src/hash.c | 6 | ||||
| -rw-r--r-- | src/kernel.c | 38 | ||||
| -rw-r--r-- | src/numeric.c | 13 | ||||
| -rw-r--r-- | src/object.c | 8 | ||||
| -rw-r--r-- | src/parse.y | 5991 | ||||
| -rw-r--r-- | src/print.c | 21 | ||||
| -rw-r--r-- | src/proc.c | 9 | ||||
| -rw-r--r-- | src/range.c | 2 | ||||
| -rw-r--r-- | src/state.c | 3 | ||||
| -rw-r--r-- | src/string.c | 18 | ||||
| -rw-r--r-- | src/symbol.c | 1 | ||||
| -rw-r--r-- | src/variable.c | 25 | ||||
| -rw-r--r-- | src/vm.c | 23 |
22 files changed, 3298 insertions, 3205 deletions
diff --git a/src/array.c b/src/array.c index ec2465be1..ffb76f88e 100644 --- a/src/array.c +++ b/src/array.c @@ -4,11 +4,11 @@ ** See Copyright Notice in mruby.h */ -#include <limits.h> #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 @@ -678,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_fixnum_p(argv[0])) { - 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 @@ -849,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); } @@ -911,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, "[...]"); } } @@ -954,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)); } diff --git a/src/backtrace.c b/src/backtrace.c index 25a08bb12..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,9 +62,8 @@ 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_intern_lit(mrb, "ciidx"))); if (ciidx >= mrb->c->ciend - mrb->c->cibase) ciidx = 10; /* ciidx is broken... */ @@ -72,7 +71,7 @@ mrb_output_backtrace(mrb_state *mrb, struct RObject *exc, output_stream_func fun 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; @@ -91,9 +90,9 @@ mrb_output_backtrace(mrb_state *mrb, struct RObject *exc, output_stream_func fun 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 d29089253..4b5a014d9 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" @@ -866,7 +866,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 +902,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); @@ -1226,7 +1226,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 +1253,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); } @@ -1378,7 +1378,7 @@ mrb_mod_to_s(mrb_state *mrb, mrb_value klass) if (mrb_type(klass) == MRB_TT_SCLASS) { 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: diff --git a/src/codegen.c b/src/codegen.c index d0ec12bac..80cdb6ef1 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; @@ -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_intern_lit(s->mrb, "===")), 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(); @@ -2729,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)); @@ -2840,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)); @@ -2849,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)); @@ -2893,7 +2902,7 @@ 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) { codedump_recur(mrb, proc->body.irep); } diff --git a/src/dump.c b/src/dump.c index f1fc56d8e..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" @@ -595,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; } @@ -606,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; @@ -624,9 +626,6 @@ write_section_debug(mrb_state *mrb, mrb_irep *irep, uint8_t *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 diff --git a/src/error.c b/src/error.c index ced50e3e1..c18f492e1 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" @@ -347,20 +345,13 @@ 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_intern_lit(mrb, "status")); - 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 +static mrb_value make_exception(mrb_state *mrb, int argc, mrb_value *argv, int isstr) { mrb_value mesg; diff --git a/src/error.h b/src/error.h index 4d120e989..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_new_str(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_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) { @@ -4,7 +4,6 @@ ** See Copyright Notice in mruby.h */ -#include <limits.h> #include <string.h> #include <stdlib.h> #include "mruby.h" @@ -1282,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; + 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); - } - - 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 @@ -1339,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); @@ -1381,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)); @@ -1430,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); @@ -1463,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 d1e2aa538..3bfffc0f7 100644 --- a/src/hash.c +++ b/src/hash.c @@ -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); } diff --git a/src/kernel.c b/src/kernel.c index 15567a65f..b17977052 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -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: @@ -739,7 +749,7 @@ method_entry_loop(mrb_state *mrb, struct RClass* klass, khash_t(st)* set) } 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; @@ -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); } @@ -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; @@ -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,6 +1176,7 @@ 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_intern_lit(mrb, "dup"), mrb_intern_lit(mrb, "clone")); diff --git a/src/numeric.c b/src/numeric.c index 75f5313e7..709a8e1e3 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -118,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 { @@ -612,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 * @@ -1331,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 daa76a03f..18524e958 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 diff --git a/src/parse.y b/src/parse.y index 106076911..163c3ea55 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,6 +63,8 @@ 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)) @@ -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, 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 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, 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); - } - 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))) @@ -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; } } @@ -3402,9 +3420,9 @@ 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; } @@ -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) { @@ -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 = intern("**",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 = intern("<<",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 = intern(">>",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 = intern("&&",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 = intern("||",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 = '_'; @@ -4886,7 +4907,7 @@ parser_yylex(parser_state *p) tokadd(p, c); c = nextc(p); pushback(p, c); - gvar: + gvar: tokfix(p); yylval.id = intern_cstr(tok(p)); return tGVAR; @@ -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,95 +5027,95 @@ parser_yylex(parser_state *p) case '@': p->lstate = EXPR_END; if (tok(p)[1] == '@') - result = tCVAR; + result = tCVAR; else - result = tIVAR; + result = tIVAR; break; default: if (toklast(p) == '!' || toklast(p) == '?') { - result = tFID; + result = tFID; } else { - if (p->lstate == EXPR_FNAME) { - if ((c = nextc(p)) == '=' && !peek(p, '~') && !peek(p, '>') && - (!peek(p, '=') || (peek_n(p, '>', 1)))) { - result = tIDENTIFIER; - tokadd(p, c); - tokfix(p); - } - else { - pushback(p, c); - } - } - if (result == 0 && isupper((int)(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_cstr(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_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]; - } - } + 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; } } { @@ -5103,7 +5124,7 @@ parser_yylex(parser_state *p) yylval.id = ident; #if 0 if (last_state != EXPR_DOT && islower(tok(p)[0]) && lvar_defined(ident)) { - p->lstate = EXPR_END; + p->lstate = EXPR_END; } #endif } @@ -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) @@ -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); } } @@ -5286,7 +5307,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 +5385,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 +5405,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 +5473,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 +5481,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 +5502,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 +5511,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 +5542,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 +5553,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 +5640,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 +5649,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 +5673,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 +5710,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 +5730,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 +5783,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 +5814,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 +5865,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 +5878,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 +5888,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 +5928,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 +5948,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 +5961,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 +6017,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 +6026,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 +6044,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 +6069,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 +6095,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 +6113,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 +6163,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..94250ddce 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,31 @@ 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"; + static const char version_msg[] = "mruby - Embeddable Ruby Copyright (c) 2010-2014 mruby developers\n"; mrb_value msg; - msg = mrb_str_new(mrb, version_msg, sizeof(version_msg) - 1); + if (mrb_const_defined(mrb, mrb_obj_value(mrb->object_class), mrb_intern_lit(mrb, "MRUBY_DESCRIPTION"))) { + msg = mrb_const_get(mrb, mrb_obj_value(mrb->object_class), mrb_intern_lit(mrb, "MRUBY_DESCRIPTION")); + msg = mrb_funcall(mrb, msg, "+", 1, mrb_str_new_lit(mrb, "\n")); + } + else { + msg = mrb_str_new_lit(mrb, version_msg); + } printstr(mrb, msg); } void mrb_show_copyright(mrb_state *mrb) { - static const char copyright_msg[] = "mruby - Copyright (c) 2010-2013 mruby developers\n"; + static const char copyright_msg[] = "mruby - Copyright (c) 2010-2014 mruby developers\n"; mrb_value msg; - msg = mrb_str_new(mrb, copyright_msg, sizeof(copyright_msg) - 1); + if (mrb_const_defined(mrb, mrb_obj_value(mrb->object_class), mrb_intern_lit(mrb, "MRUBY_COPYRIGHT"))) { + msg = mrb_const_get(mrb, mrb_obj_value(mrb->object_class), mrb_intern_lit(mrb, "MRUBY_COPYRIGHT")); + msg = mrb_funcall(mrb, msg, "+", 1, mrb_str_new_lit(mrb, "\n")); + } + else { + msg = mrb_str_new_lit(mrb, copyright_msg); + } printstr(mrb, msg); } diff --git a/src/proc.c b/src/proc.c index b2bbe2453..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); diff --git a/src/range.c b/src/range.c index 0eacc83d5..7b3807865 100644 --- a/src/range.c +++ b/src/range.c @@ -376,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; diff --git a/src/state.c b/src/state.c index f25d8c8bf..620ed7d77 100644 --- a/src/state.c +++ b/src/state.c @@ -7,7 +7,6 @@ #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" @@ -20,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* diff --git a/src/string.c b/src/string.c index e8c37180d..96a625802 100644 --- a/src/string.c +++ b/src/string.c @@ -107,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 */ @@ -142,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; @@ -751,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(); @@ -2422,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))) { diff --git a/src/symbol.c b/src/symbol.c index 4e78ade66..4d6a8eb7a 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" diff --git a/src/variable.c b/src/variable.c index c66e7fe89..5ced2dfbd 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*); @@ -756,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; @@ -823,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 @@ -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" @@ -231,6 +229,7 @@ cipush(mrb_state *mrb) ci->ridx = ridx; ci->env = 0; ci->pc = 0; + ci->err = 0; return ci; } @@ -263,6 +262,8 @@ 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->mid = ci[-1].mid; @@ -601,7 +602,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; @@ -852,13 +852,14 @@ mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int 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); } - ARENA_RESTORE(mrb, ai); NEXT; } @@ -1349,7 +1350,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; } @@ -2112,11 +2113,15 @@ mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int 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; } @@ -2130,7 +2135,7 @@ mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int ecall(mrb, n); } } - mrb->c->ci->err = 0; + ERR_PC_CLR(mrb); mrb->jmp = prev_jmp; if (mrb->exc) { return mrb_obj_value(mrb->exc); |
