[前][次][番号順一覧][スレッド一覧]

ruby-changes:42115

From: nobu <ko1@a...>
Date: Sat, 19 Mar 2016 14:46:27 +0900 (JST)
Subject: [ruby-changes:42115] nobu:r54189 (trunk): SyntaxError message at iseq compile

nobu	2016-03-19 14:46:20 +0900 (Sat, 19 Mar 2016)

  New Revision: 54189

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=54189

  Log:
    SyntaxError message at iseq compile
    
    * iseq.c (rb_iseq_compile_with_option): make the parser in mild
      error.
    * load.c (rb_load_internal0): ditto.
    * parse.y (yycompile0): return the error message within the error
      to be raised.  [Feature #11951]
    * parse.y (parser_compile_error): accumulate error messages in the
      error_buffer.

  Modified files:
    trunk/ChangeLog
    trunk/error.c
    trunk/internal.h
    trunk/iseq.c
    trunk/load.c
    trunk/parse.y
    trunk/ruby.c
    trunk/test/ruby/test_iseq.rb
    trunk/vm_core.h
    trunk/vm_eval.c
Index: vm_eval.c
===================================================================
--- vm_eval.c	(revision 54188)
+++ vm_eval.c	(revision 54189)
@@ -1284,7 +1284,6 @@ eval_string_with_cref(VALUE self, VALUE https://github.com/ruby/ruby/blob/trunk/vm_eval.c#L1284
     rb_env_t *env = NULL;
     rb_block_t block, *base_block;
     volatile int parse_in_eval;
-    volatile int mild_compile_error;
     volatile VALUE file;
     volatile int line;
 
@@ -1292,7 +1291,6 @@ eval_string_with_cref(VALUE self, VALUE https://github.com/ruby/ruby/blob/trunk/vm_eval.c#L1291
     line = lineno;
 
     parse_in_eval = th->parse_in_eval;
-    mild_compile_error = th->mild_compile_error;
     TH_PUSH_TAG(th);
     if ((state = TH_EXEC_TAG()) == 0) {
 	rb_cref_t *cref = cref_arg;
@@ -1343,9 +1341,7 @@ eval_string_with_cref(VALUE self, VALUE https://github.com/ruby/ruby/blob/trunk/vm_eval.c#L1341
 
 	/* make eval iseq */
 	th->parse_in_eval++;
-	th->mild_compile_error++;
 	iseq = rb_iseq_compile_with_option(src, fname, absolute_path, INT2FIX(line), base_block, Qnil);
-	th->mild_compile_error--;
 	th->parse_in_eval--;
 
 	if (!cref && base_block->iseq) {
@@ -1373,7 +1369,6 @@ eval_string_with_cref(VALUE self, VALUE https://github.com/ruby/ruby/blob/trunk/vm_eval.c#L1369
 	result = vm_exec(th);
     }
     TH_POP_TAG();
-    th->mild_compile_error = mild_compile_error;
     th->parse_in_eval = parse_in_eval;
 
     if (state) {
Index: error.c
===================================================================
--- error.c	(revision 54188)
+++ error.c	(revision 54189)
@@ -94,88 +94,53 @@ compile_snprintf(rb_encoding *enc, const https://github.com/ruby/ruby/blob/trunk/error.c#L94
     return str;
 }
 
-static void
-compile_err_append(VALUE mesg)
+VALUE
+rb_compile_err_append(VALUE buffer, VALUE mesg)
 {
     rb_thread_t *th = GET_THREAD();
-    VALUE err = th->errinfo;
     rb_block_t *prev_base_block = th->base_block;
     th->base_block = 0;
     /* base_block should be zero while normal Ruby execution */
     /* after this line, any Ruby code *can* run */
 
-    if (th->mild_compile_error) {
-	if (RTEST(err)) {
-	    VALUE str = rb_obj_as_string(err);
-
-	    rb_str_cat2(str, "\n");
-	    rb_str_append(str, mesg);
-	    mesg = str;
-	}
-	err = rb_exc_new3(rb_eSyntaxError, mesg);
-	th->errinfo = err;
-    }
-    else {
-	if (!RTEST(err)) {
-	    err = rb_exc_new2(rb_eSyntaxError, "compile error");
-	    th->errinfo = err;
-	}
+    if (!buffer) {
 	rb_str_cat2(mesg, "\n");
 	rb_write_error_str(mesg);
     }
+    else if (NIL_P(buffer)) {
+	buffer = mesg;
+    }
+    else {
+	rb_str_cat2(buffer, "\n");
+	rb_str_append(buffer, mesg);
+    }
 
     /* returned to the parser world */
     th->base_block = prev_base_block;
+    return buffer;
 }
 
 void
 rb_compile_error_with_enc(const char *file, int line, void *enc, const char *fmt, ...)
 {
-    va_list args;
-    VALUE str;
-
-    va_start(args, fmt);
-    str = compile_snprintf(enc, NULL, file, line, fmt, args);
-    va_end(args);
-    compile_err_append(str);
 }
 
 void
 rb_compile_error(const char *file, int line, const char *fmt, ...)
 {
-    va_list args;
-    VALUE str;
-
-    va_start(args, fmt);
-    str = compile_snprintf(NULL, NULL, file, line, fmt, args);
-    va_end(args);
-    compile_err_append(str);
 }
 
-void
-rb_compile_error_str(VALUE file, int line, void *enc, const char *fmt, ...)
+VALUE
+rb_error_vsprintf(VALUE file, int line, void *enc, const char *fmt, va_list args)
 {
-    va_list args;
-    VALUE str;
-
-    va_start(args, fmt);
-    str = compile_snprintf(enc, NULL,
-			   NIL_P(file) ? NULL : RSTRING_PTR(file), line,
-			   fmt, args);
-    va_end(args);
-    compile_err_append(str);
+    return compile_snprintf(enc, NULL,
+			    NIL_P(file) ? NULL : RSTRING_PTR(file), line,
+			    fmt, args);
 }
 
 void
 rb_compile_error_append(const char *fmt, ...)
 {
-    va_list args;
-    VALUE str;
-
-    va_start(args, fmt);
-    str = rb_vsprintf(fmt, args);
-    va_end(args);
-    compile_err_append(str);
 }
 
 static void
Index: ruby.c
===================================================================
--- ruby.c	(revision 54188)
+++ ruby.c	(revision 54189)
@@ -1948,6 +1948,14 @@ rb_load_file_str(VALUE fname_v) https://github.com/ruby/ruby/blob/trunk/ruby.c#L1948
     return load_file(rb_parser_new(), fname_v, 0, cmdline_options_init(&opt));
 }
 
+void *
+rb_parser_load_file(VALUE parser, VALUE fname_v)
+{
+    struct cmdline_options opt;
+
+    return load_file(parser, fname_v, 0, cmdline_options_init(&opt));
+}
+
 /*
  *  call-seq:
  *     Process.argv0  -> frozen_string
Index: internal.h
===================================================================
--- internal.h	(revision 54188)
+++ internal.h	(revision 54189)
@@ -1074,6 +1074,8 @@ struct RBasicRaw { https://github.com/ruby/ruby/blob/trunk/internal.h#L1074
 #endif
 VALUE rb_parser_get_yydebug(VALUE);
 VALUE rb_parser_set_yydebug(VALUE, VALUE);
+VALUE rb_parser_mild_error(VALUE parser);
+void *rb_parser_load_file(VALUE parser, VALUE name);
 int rb_is_const_name(VALUE name);
 int rb_is_class_name(VALUE name);
 int rb_is_global_name(VALUE name);
Index: iseq.c
===================================================================
--- iseq.c	(revision 54188)
+++ iseq.c	(revision 54189)
@@ -627,11 +627,13 @@ rb_iseq_compile_with_option(VALUE src, V https://github.com/ruby/ruby/blob/trunk/iseq.c#L627
     const INITIALIZED VALUE label = parent ?
 	parent->body->location.label :
 	rb_fstring_cstr("<compiled>");
+    VALUE parser = rb_parser_new();
 
+    rb_parser_mild_error(parser);
     th->base_block = base_block;
     TH_PUSH_TAG(th);
     if ((state = EXEC_TAG()) == 0) {
-	NODE *node = (*parse)(rb_parser_new(), file, src, ln);
+	NODE *node = (*parse)(parser, file, src, ln);
 	if (node) { /* TODO: check err */
 	    iseq = rb_iseq_new_with_opt(node, label, file, absolute_path, line,
 					parent, type, &option);
Index: load.c
===================================================================
--- load.c	(revision 54188)
+++ load.c	(revision 54189)
@@ -583,7 +583,6 @@ rb_load_internal0(rb_thread_t *th, VALUE https://github.com/ruby/ruby/blob/trunk/load.c#L583
     int state;
     volatile VALUE wrapper = th->top_wrapper;
     volatile VALUE self = th->top_self;
-    volatile int mild_compile_error;
 #if !defined __GNUC__
     rb_thread_t *volatile th0 = th;
 #endif
@@ -600,7 +599,6 @@ rb_load_internal0(rb_thread_t *th, VALUE https://github.com/ruby/ruby/blob/trunk/load.c#L599
 	rb_extend_object(th->top_self, th->top_wrapper);
     }
 
-    mild_compile_error = th->mild_compile_error;
     TH_PUSH_TAG(th);
     state = EXEC_TAG();
     if (state == 0) {
@@ -611,10 +609,10 @@ rb_load_internal0(rb_thread_t *th, VALUE https://github.com/ruby/ruby/blob/trunk/load.c#L609
 	    /* OK */
 	}
 	else {
-	    th->mild_compile_error++;
-	    node = (NODE *)rb_load_file_str(fname);
+	    VALUE parser = rb_parser_new();
+	    rb_parser_mild_error(parser);
+	    node = (NODE *)rb_parser_load_file(parser, fname);
 	    iseq = rb_iseq_new_top(node, rb_str_new2("<top (required)>"), fname, rb_realpath_internal(Qnil, fname, 1), NULL);
-	    th->mild_compile_error--;
 	}
 	rb_iseq_eval(iseq);
     }
@@ -624,7 +622,6 @@ rb_load_internal0(rb_thread_t *th, VALUE https://github.com/ruby/ruby/blob/trunk/load.c#L622
     th = th0;
     fname = RB_GC_GUARD(fname);
 #endif
-    th->mild_compile_error = mild_compile_error;
     th->top_self = self;
     th->top_wrapper = wrapper;
 
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 54188)
+++ ChangeLog	(revision 54189)
@@ -1,3 +1,16 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Sat Mar 19 14:46:18 2016  Nobuyoshi Nakada  <nobu@r...>
+
+	* iseq.c (rb_iseq_compile_with_option): make the parser in mild
+	  error.
+
+	* load.c (rb_load_internal0): ditto.
+
+	* parse.y (yycompile0): return the error message within the error
+	  to be raised.  [Feature #11951]
+
+	* parse.y (parser_compile_error): accumulate error messages in the
+	  error_buffer.
+
 Sat Mar 19 03:57:13 2016  NARUSE, Yui  <naruse@r...>
 
 	* time.c (LOCALTIME): organize #ifdefs.
Index: test/ruby/test_iseq.rb
===================================================================
--- test/ruby/test_iseq.rb	(revision 54188)
+++ test/ruby/test_iseq.rb	(revision 54189)
@@ -214,4 +214,25 @@ class TestISeq < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_iseq.rb#L214
       at_exit { assert_equal([:n, :x], Segfault.new.segfault.sort) }
     end;
   end
+
+  def test_syntax_error_message
+    feature11951 = '[Feature #11951]'
+
+    src, line = <<-'end;', __LINE__+1
+      def x@;end
+      def y@;end
+    end;
+    e1 = e2 = nil
+    m1 = EnvUtil.verbose_warning do
+      e1 = assert_raise(SyntaxError) do
+        eval(src, nil, __FILE__, line)
+      end
+    end
+    m2 = EnvUtil.verbose_warning do
+      e2 = assert_raise(SyntaxError) do
+        ISeq.new(src, __FILE__, __FILE__, line)
+      end
+    end
+    assert_equal([m1, e1.message], [m2, e2.message], feature11951)
+  end
 end
Index: vm_core.h
===================================================================
--- vm_core.h	(revision 54188)
+++ vm_core.h	(revision 54189)
@@ -750,12 +750,6 @@ typedef struct rb_thread_struct { https://github.com/ruby/ruby/blob/trunk/vm_core.h#L750
      */
     int parse_in_eval;
 
-    /*! Thread-local state of compiling context.
-     *
-     * If non-zero, the parser does not automatically print error messages to
-     * stderr. */
-    int mild_compile_error;
-
     /* storage */
     st_table *local_storage;
     VALUE local_storage_recursive_hash;
Index: parse.y
===================================================================
--- parse.y	(revision 54188)
+++ parse.y	(revision 54189)
@@ -312,6 +312,7 @@ struct parser_params { https://github.com/ruby/ruby/blob/trunk/parse.y#L312
 
     NODE *eval_tree_begin;
     NODE *eval_tree;
+    VALUE error_buffer;
     VALUE debug_lines;
     VALUE coverage;
 #else
@@ -740,7 +741,6 @@ static ID id_warn, id_warning; https://github.com/ruby/ruby/blob/trunk/parse.y#L741
 # define WARNING_ARGS_L(l, fmt,n) WARNING_ARGS(fmt,n)
 # define WARNING_CALL rb_funcall
 static void ripper_compile_error(struct parser_params*, const char *fmt, ...);
-# define rb_compile_error ripper_compile_error
 # define compile_error ripper_compile_error
 # define PARSER_ARG parser,
 #else
@@ -753,9 +753,9 @@ static void ripper_compile_error(struct https://github.com/ruby/ruby/blob/trunk/parse.y#L753
 # define WARNING_ARGS(fmt,n) WARN_ARGS(fmt,n)
 # define WARNING_ARGS_L(l,fmt,n) WARN_ARGS_L(l,fmt,n)
 # define WARNING_CALL rb_compile_warning
-# define rb_compile_error rb_compile_error_str
-# define compile_error (parser->error_p = 1),rb_compile_error_str
-# define PARSER_ARG ruby_sourcefile_string, ruby_sourceline, (void *)current_enc,
+static void parser_compile_error(struct parser_params*, const char *fmt, ...);
+# define compile_error parser_compile_error
+# define PARSER_ARG parser,
 #endif
 
 /* Older versions of Yacc set YYMAXDEPTH to a very low value by default (150,
@@ -5559,6 +5559,9 @@ yycompile0(VALUE arg) https://github.com/ruby/ruby/blob/trunk/parse.y#L5559
     lex_p = lex_pbeg = lex_pend = 0;
     lex_lastline = lex_nextline = 0;
     if (parser->error_p) {
+	VALUE mesg = parser->error_buffer;
+	if (!mesg) mesg = rb_fstring_cstr("compile error");
+	rb_set_errinfo(rb_exc_new_str(rb_eSyntaxError, mesg));
 	return 0;
     }
     tree = ruby_eval_tree;
@@ -10792,6 +10795,8 @@ parser_initialize(struct parser_params * https://github.com/ruby/ruby/blob/trunk/parse.y#L10795
     parser->delayed = Qnil;
     parser->result = Qnil;
     parser->parsing_thread = Qnil;
+#else
+    parser->error_buffer = Qfalse;
 #endif
     parser->debug_buffer = Qnil;
     parser->enc = rb_utf8_encoding();
@@ -10818,6 +10823,7 @@ parser_mark(void *ptr) https://github.com/ruby/ruby/blob/trunk/parse.y#L10823
     rb_gc_mark((VALUE)ruby_eval_tree);
     rb_gc_mark(ruby_debug_lines);
     rb_gc_mark(parser->compile_option);
+    rb_gc_mark(parser->error_buffer);
 #else
     rb_gc_mark(parser->delayed);
     rb_gc_mark(parser->value);
@@ -10901,6 +10907,16 @@ rb_parser_new(void) https://github.com/ruby/ruby/blob/trunk/parse.y#L10907
     parser_initialize(p);
     return parser;
 }
+
+VALUE
+rb_parser_mild_error(VALUE vparser)
+{
+    struct parser_params *parser;
+
+    TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, parser);
+    parser->error_buffer = Qnil;
+    return vparser;
+}
 #endif
 
 #ifdef RIPPER
@@ -11069,6 +11085,23 @@ rb_parser_printf(struct parser_params *p https://github.com/ruby/ruby/blob/trunk/parse.y#L11085
 	parser->debug_buffer = Qnil;
     }
 }
+
+extern VALUE rb_error_vsprintf(VALUE, int, void *, const char *, va_list);
+extern VALUE rb_compile_err_append(VALUE buffer, VALUE mesg);
+
+static void
+parser_compile_error(struct parser_params *parser, const char *fmt, ...)
+{
+    VALUE str;
+    va_list ap;
+
+    parser->error_p = 1;
+    va_start(ap, fmt);
+    str = rb_error_vsprintf(ruby_sourcefile_string, ruby_sourceline,
+			    (void *)current_enc, fmt, ap);
+    va_end(ap);
+    parser->error_buffer = rb_compile_err_append(parser->error_buffer, str);
+}
 #endif
 
 #ifdef RIPPER

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]