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

ruby-changes:15083

From: mame <ko1@a...>
Date: Wed, 17 Mar 2010 02:40:25 +0900 (JST)
Subject: [ruby-changes:15083] Ruby:r26959 (trunk): * compile.c, iseq.c, ruby.c, vm.c, vm_core.h, vm_eval.c: add absolute

mame	2010-03-17 02:40:00 +0900 (Wed, 17 Mar 2010)

  New Revision: 26959

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=26959

  Log:
    * compile.c, iseq.c, ruby.c, vm.c, vm_core.h, vm_eval.c: add absolute
      path field into rb_iseq_t.  The field contains a string representing
      a path to corresponding source file. or nil when the iseq is created
      from -e, stdin, eval, etc.  This field is used for require_relative.
      [ruby-dev:40004]
    
    * load.c (rb_f_require_relative): add C implementation of
      require_relative.
    
    * prelude.rb (require_relative): get rid of Ruby implementation of
      require_relative.

  Modified files:
    trunk/ChangeLog
    trunk/compile.c
    trunk/file.c
    trunk/iseq.c
    trunk/load.c
    trunk/prelude.rb
    trunk/ruby.c
    trunk/vm.c
    trunk/vm_core.h
    trunk/vm_eval.c

Index: prelude.rb
===================================================================
--- prelude.rb	(revision 26958)
+++ prelude.rb	(revision 26959)
@@ -22,17 +22,3 @@
     }
   end
 end
-
-module Kernel
-  module_function
-  def require_relative(relative_feature)
-    c = caller.first
-    e = c.rindex(/:\d+:in /)
-    file = $`
-    if /\A\((.*)\)/ =~ file # eval, etc.
-      raise LoadError, "require_relative is called in #{$1}"
-    end
-    absolute_feature = File.join(File.dirname(File.realpath(file)), relative_feature)
-    require absolute_feature
-  end
-end
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 26958)
+++ ChangeLog	(revision 26959)
@@ -1,3 +1,17 @@
+Wed Mar 17 02:29:46 2010  Yusuke Endoh  <mame@t...>
+
+	* compile.c, iseq.c, ruby.c, vm.c, vm_core.h, vm_eval.c: add absolute
+	  path field into rb_iseq_t.  The field contains a string representing
+	  a path to corresponding source file. or nil when the iseq is created
+	  from -e, stdin, eval, etc.  This field is used for require_relative.
+	  [ruby-dev:40004]
+
+	* load.c (rb_f_require_relative): add C implementation of
+	  require_relative.
+
+	* prelude.rb (require_relative): get rid of Ruby implementation of
+	  require_relative.
+
 Wed Mar 17 01:24:01 2010  Yusuke Endoh  <mame@t...>
 
 	* parse.y (rb_intern3): prohibit Symbol with an invalid encoding.
Index: vm_core.h
===================================================================
--- vm_core.h	(revision 26958)
+++ vm_core.h	(revision 26959)
@@ -155,6 +155,7 @@
     VALUE type;          /* instruction sequence type */
     VALUE name;	         /* String: iseq name */
     VALUE filename;      /* file information where this sequence from */
+    VALUE filepath;      /* real file path or nil */
     VALUE *iseq;         /* iseq (insn number and openrads) */
     VALUE *iseq_encoded; /* encoded iseq */
     unsigned long iseq_size;
@@ -464,11 +465,11 @@
 } rb_thread_t;
 
 /* iseq.c */
-VALUE rb_iseq_new(NODE*, VALUE, VALUE, VALUE, VALUE);
-VALUE rb_iseq_new_top(NODE *node, VALUE name, VALUE filename, VALUE parent);
-VALUE rb_iseq_new_main(NODE *node, VALUE filename);
-VALUE rb_iseq_new_with_bopt(NODE*, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE);
-VALUE rb_iseq_new_with_opt(NODE*, VALUE, VALUE, VALUE, VALUE, VALUE, const rb_compile_option_t*);
+VALUE rb_iseq_new(NODE*, VALUE, VALUE, VALUE, VALUE, VALUE);
+VALUE rb_iseq_new_top(NODE *node, VALUE name, VALUE filename, VALUE filepath, VALUE parent);
+VALUE rb_iseq_new_main(NODE *node, VALUE filename, VALUE filepath);
+VALUE rb_iseq_new_with_bopt(NODE*, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE);
+VALUE rb_iseq_new_with_opt(NODE*, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, const rb_compile_option_t*);
 VALUE rb_iseq_compile(VALUE src, VALUE file, VALUE line);
 VALUE rb_iseq_disasm(VALUE self);
 int rb_iseq_disasm_insn(VALUE str, VALUE *iseqval, size_t pos, rb_iseq_t *iseq, VALUE child);
Index: iseq.c
===================================================================
--- iseq.c	(revision 26958)
+++ iseq.c	(revision 26959)
@@ -98,6 +98,7 @@
 	RUBY_MARK_UNLESS_NULL(iseq->mark_ary);
 	RUBY_MARK_UNLESS_NULL(iseq->name);
 	RUBY_MARK_UNLESS_NULL(iseq->filename);
+	RUBY_MARK_UNLESS_NULL(iseq->filepath);
 	RUBY_MARK_UNLESS_NULL((VALUE)iseq->cref_stack);
 	RUBY_MARK_UNLESS_NULL(iseq->klass);
 	RUBY_MARK_UNLESS_NULL(iseq->coverage);
@@ -207,9 +208,11 @@
     }
 }
 
+VALUE rb_realpath_internal(VALUE basedir, VALUE path, int strict);
+
 static VALUE
 prepare_iseq_build(rb_iseq_t *iseq,
-		   VALUE name, VALUE filename, VALUE line_no,
+		   VALUE name, VALUE filename, VALUE filepath, VALUE line_no,
 		   VALUE parent, VALUE type, VALUE block_opt,
 		   const rb_compile_option_t *option)
 {
@@ -218,6 +221,7 @@
 
     iseq->name = name;
     iseq->filename = filename;
+    iseq->filepath = filepath == Qnil ? Qnil : rb_realpath_internal(Qnil, filepath, 1);
     iseq->line_no = line_no;
     iseq->defined_method_id = 0;
     iseq->mark_ary = rb_ary_tmp_new(3);
@@ -361,31 +365,31 @@
 }
 
 VALUE
-rb_iseq_new(NODE *node, VALUE name, VALUE filename,
+rb_iseq_new(NODE *node, VALUE name, VALUE filename, VALUE filepath,
 	      VALUE parent, VALUE type)
 {
-    return rb_iseq_new_with_opt(node, name, filename, INT2FIX(0), parent, type,
+    return rb_iseq_new_with_opt(node, name, filename, filepath, INT2FIX(0), parent, type,
 				&COMPILE_OPTION_DEFAULT);
 }
 
 VALUE
-rb_iseq_new_top(NODE *node, VALUE name, VALUE filename, VALUE parent)
+rb_iseq_new_top(NODE *node, VALUE name, VALUE filename, VALUE filepath, VALUE parent)
 {
-    return rb_iseq_new_with_opt(node, name, filename, INT2FIX(0), parent, ISEQ_TYPE_TOP,
+    return rb_iseq_new_with_opt(node, name, filename, filepath, INT2FIX(0), parent, ISEQ_TYPE_TOP,
 				&COMPILE_OPTION_DEFAULT);
 }
 
 VALUE
-rb_iseq_new_main(NODE *node, VALUE filename)
+rb_iseq_new_main(NODE *node, VALUE filename, VALUE filepath)
 {
     rb_thread_t *th = GET_THREAD();
     VALUE parent = th->base_block->iseq->self;
-    return rb_iseq_new_with_opt(node, rb_str_new2("<main>"), filename, INT2FIX(0),
+    return rb_iseq_new_with_opt(node, rb_str_new2("<main>"), filename, filepath, INT2FIX(0),
 				parent, ISEQ_TYPE_MAIN, &COMPILE_OPTION_DEFAULT);
 }
 
 static VALUE
-rb_iseq_new_with_bopt_and_opt(NODE *node, VALUE name, VALUE filename, VALUE line_no,
+rb_iseq_new_with_bopt_and_opt(NODE *node, VALUE name, VALUE filename, VALUE filepath, VALUE line_no,
 				VALUE parent, VALUE type, VALUE bopt,
 				const rb_compile_option_t *option)
 {
@@ -395,28 +399,28 @@
     GetISeqPtr(self, iseq);
     iseq->self = self;
 
-    prepare_iseq_build(iseq, name, filename, line_no, parent, type, bopt, option);
+    prepare_iseq_build(iseq, name, filename, filepath, line_no, parent, type, bopt, option);
     rb_iseq_compile_node(self, node);
     cleanup_iseq_build(iseq);
     return self;
 }
 
 VALUE
-rb_iseq_new_with_opt(NODE *node, VALUE name, VALUE filename, VALUE line_no,
+rb_iseq_new_with_opt(NODE *node, VALUE name, VALUE filename, VALUE filepath, VALUE line_no,
 		     VALUE parent, VALUE type,
 		     const rb_compile_option_t *option)
 {
     /* TODO: argument check */
-    return rb_iseq_new_with_bopt_and_opt(node, name, filename, line_no, parent, type,
+    return rb_iseq_new_with_bopt_and_opt(node, name, filename, filepath, line_no, parent, type,
 					   Qfalse, option);
 }
 
 VALUE
-rb_iseq_new_with_bopt(NODE *node, VALUE name, VALUE filename, VALUE line_no,
+rb_iseq_new_with_bopt(NODE *node, VALUE name, VALUE filename, VALUE filepath, VALUE line_no,
 		       VALUE parent, VALUE type, VALUE bopt)
 {
     /* TODO: argument check */
-    return rb_iseq_new_with_bopt_and_opt(node, name, filename, line_no, parent, type,
+    return rb_iseq_new_with_bopt_and_opt(node, name, filename, filepath, line_no, parent, type,
 					   bopt, &COMPILE_OPTION_DEFAULT);
 }
 
@@ -430,7 +434,7 @@
     VALUE iseqval = iseq_alloc(self);
 
     VALUE magic, version1, version2, format_type, misc;
-    VALUE name, filename, line_no;
+    VALUE name, filename, filepath, line_no;
     VALUE type, body, locals, args, exception;
 
     VALUE iseq_type;
@@ -454,6 +458,7 @@
 
     name        = CHECK_STRING(rb_ary_entry(data, i++));
     filename    = CHECK_STRING(rb_ary_entry(data, i++));
+    filepath    = CHECK_STRING(rb_ary_entry(data, i++));
     line_no     = CHECK_INTEGER(rb_ary_entry(data, i++));
 
     type        = CHECK_SYMBOL(rb_ary_entry(data, i++));
@@ -496,7 +501,7 @@
     }
 
     make_compile_option(&option, opt);
-    prepare_iseq_build(iseq, name, filename, line_no,
+    prepare_iseq_build(iseq, name, filename, filepath, line_no,
 		       parent, iseq_type, 0, &option);
 
     rb_iseq_build_from_ary(iseq, locals, args, exception, body);
@@ -533,7 +538,7 @@
 }
 
 VALUE
-rb_iseq_compile_with_option(VALUE src, VALUE file, VALUE line, VALUE opt)
+rb_iseq_compile_with_option(VALUE src, VALUE file, VALUE filepath, VALUE line, VALUE opt)
 {
     rb_compile_option_t option;
     const char *fn = StringValueCStr(file);
@@ -544,11 +549,11 @@
 
     if (th->base_block && th->base_block->iseq) {
 	return rb_iseq_new_with_opt(node, th->base_block->iseq->name,
-				    file, line, th->base_block->iseq->self,
+				    file, filepath, line, th->base_block->iseq->self,
 				    ISEQ_TYPE_EVAL, &option);
     }
     else {
-	return rb_iseq_new_with_opt(node, rb_str_new2("<compiled>"), file, line, Qfalse,
+	return rb_iseq_new_with_opt(node, rb_str_new2("<compiled>"), file, filepath, line, Qfalse,
 				    ISEQ_TYPE_TOP, &option);
     }
 }
@@ -556,21 +561,21 @@
 VALUE
 rb_iseq_compile(VALUE src, VALUE file, VALUE line)
 {
-    return rb_iseq_compile_with_option(src, file, line, Qnil);
+    return rb_iseq_compile_with_option(src, file, Qnil, line, Qnil);
 }
 
 static VALUE
 iseq_s_compile(int argc, VALUE *argv, VALUE self)
 {
-    VALUE src, file = Qnil, line = INT2FIX(1), opt = Qnil;
+    VALUE src, file = Qnil, path = Qnil, line = INT2FIX(1), opt = Qnil;
 
     rb_secure(1);
 
-    rb_scan_args(argc, argv, "13", &src, &file, &line, &opt);
+    rb_scan_args(argc, argv, "13", &src, &file, &path, &line, &opt);
     if (NIL_P(file)) file = rb_str_new2("<compiled>");
     if (NIL_P(line)) line = INT2FIX(1);
 
-    return rb_iseq_compile_with_option(src, file, line, opt);
+    return rb_iseq_compile_with_option(src, file, path, line, opt);
 }
 
 static VALUE
@@ -593,7 +598,7 @@
     parser = rb_parser_new();
     node = rb_parser_compile_file(parser, fname, f, NUM2INT(line));
     make_compile_option(&option, opt);
-    return rb_iseq_new_with_opt(node, rb_str_new2("<main>"), file, line, Qfalse,
+    return rb_iseq_new_with_opt(node, rb_str_new2("<main>"), file, file, line, Qfalse,
 				ISEQ_TYPE_TOP, &option);
 }
 
@@ -1311,7 +1316,7 @@
 
     /*
      * [:magic, :major_version, :minor_version, :format_type, :misc,
-     *  :name, :filename, :line_no, :type, :locals, :args,
+     *  :name, :filename, :filepath, :line_no, :type, :locals, :args,
      *  :catch_table, :bytecode]
      */
     rb_ary_push(val, rb_str_new2("YARVInstructionSequence/SimpleDataFormat"));
@@ -1321,6 +1326,7 @@
     rb_ary_push(val, misc);
     rb_ary_push(val, iseq->name);
     rb_ary_push(val, iseq->filename);
+    rb_ary_push(val, iseq->filepath);
     rb_ary_push(val, iseq->line_no);
     rb_ary_push(val, type);
     rb_ary_push(val, locals);
Index: load.c
===================================================================
--- load.c	(revision 26958)
+++ load.c	(revision 26959)
@@ -297,7 +297,7 @@
 	th->mild_compile_error++;
 	node = (NODE *)rb_load_file(RSTRING_PTR(fname));
 	loaded = TRUE;
-	iseq = rb_iseq_new_top(node, rb_str_new2("<top (required)>"), fname, Qfalse);
+	iseq = rb_iseq_new_top(node, rb_str_new2("<top (required)>"), fname, fname, Qfalse);
 	th->mild_compile_error--;
 	rb_iseq_eval(iseq);
     }
@@ -448,6 +448,19 @@
     return rb_require_safe(fname, rb_safe_level());
 }
 
+VALUE
+rb_f_require_relative(VALUE obj, VALUE fname)
+{
+    VALUE rb_current_realfilepath(void);
+    VALUE rb_file_s_dirname(VALUE klass, VALUE fname);
+    VALUE base = rb_current_realfilepath();
+    if (NIL_P(base)) {
+	rb_raise(rb_eLoadError, "cannot infer basepath");
+    }
+    base = rb_file_s_dirname(rb_cFile, base);
+    return rb_require_safe(rb_file_expand_path(fname, base), rb_safe_level());
+}
+
 static int
 search_required(VALUE fname, volatile VALUE *path, int safe_level)
 {
@@ -743,6 +756,7 @@
 
     rb_define_global_function("load", rb_f_load, -1);
     rb_define_global_function("require", rb_f_require, 1);
+    rb_define_global_function("require_relative", rb_f_require_relative, 1);
     rb_define_method(rb_cModule, "autoload", rb_mod_autoload, 2);
     rb_define_method(rb_cModule, "autoload?", rb_mod_autoload_p, 1);
     rb_define_global_function("autoload", rb_f_autoload, 2);
Index: compile.c
===================================================================
--- compile.c	(revision 26958)
+++ compile.c	(revision 26959)
@@ -169,6 +169,9 @@
 #define iseq_filename(iseq) \
   (((rb_iseq_t*)DATA_PTR(iseq))->filename)
 
+#define iseq_filepath(iseq) \
+  (((rb_iseq_t*)DATA_PTR(iseq))->filepath)
+
 #define NEW_ISEQVAL(node, name, type, line_no)       \
   new_child_iseq(iseq, node, name, 0, type, line_no)
 
@@ -917,7 +920,7 @@
     VALUE ret;
 
     debugs("[new_child_iseq]> ---------------------------------------\n");
-    ret = rb_iseq_new_with_opt(node, name, iseq_filename(iseq->self), INT2FIX(line_no),
+    ret = rb_iseq_new_with_opt(node, name, iseq_filename(iseq->self), iseq_filepath(iseq->self), INT2FIX(line_no),
 			       parent, type, iseq->compile_data->option);
     debugs("[new_child_iseq]< ---------------------------------------\n");
     iseq_add_mark_object(iseq, ret);
Index: vm_eval.c
===================================================================
--- vm_eval.c	(revision 26958)
+++ vm_eval.c	(revision 26959)
@@ -1709,6 +1709,16 @@
     }
 }
 
+VALUE
+rb_current_realfilepath(void)
+{
+    rb_thread_t *th = GET_THREAD();
+    rb_control_frame_t *cfp = th->cfp;
+    cfp = vm_get_ruby_level_caller_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp));
+    if (cfp != 0) return cfp->iseq->filepath;
+    return Qnil;
+}
+
 void
 Init_vm_eval(void)
 {
Index: vm.c
===================================================================
--- vm.c	(revision 26958)
+++ vm.c	(revision 26959)
@@ -1441,7 +1441,7 @@
 {
     rb_thread_t *th = GET_THREAD();
     const rb_control_frame_t *reg_cfp = th->cfp;
-    volatile VALUE iseqval = rb_iseq_new(0, filename, filename, 0, ISEQ_TYPE_TOP);
+    volatile VALUE iseqval = rb_iseq_new(0, filename, filename, filename, 0, ISEQ_TYPE_TOP);
     VALUE val;
 
     vm_push_frame(th, DATA_PTR(iseqval), VM_FRAME_MAGIC_TOP,
@@ -2052,7 +2052,7 @@
 	rb_vm_t *vm = ruby_current_vm;
 	rb_thread_t *th = GET_THREAD();
 	VALUE filename = rb_str_new2("<main>");
-	volatile VALUE iseqval = rb_iseq_new(0, filename, filename, 0, ISEQ_TYPE_TOP);
+	volatile VALUE iseqval = rb_iseq_new(0, filename, filename, Qnil, 0, ISEQ_TYPE_TOP);
         volatile VALUE th_self;
 	rb_iseq_t *iseq;
 
Index: ruby.c
===================================================================
--- ruby.c	(revision 26958)
+++ ruby.c	(revision 26959)
@@ -1454,7 +1454,9 @@
     }
 
     PREPARE_PARSE_MAIN({
-	iseq = rb_iseq_new_main(tree, opt->script_name);
+	VALUE path = Qnil;
+	if (!opt->e_script && strcmp(opt->script, "-")) path = opt->script_name;
+	iseq = rb_iseq_new_main(tree, opt->script_name, path);
     });
 
     if (opt->dump & DUMP_BIT(insns)) {
Index: file.c
===================================================================
--- file.c	(revision 26958)
+++ file.c	(revision 26959)
@@ -3188,8 +3188,8 @@
     }
 }
 
-static VALUE
-realpath_internal(VALUE basedir, VALUE path, int strict)
+VALUE
+rb_realpath_internal(VALUE basedir, VALUE path, int strict)
 {
     long prefixlen;
     VALUE resolved;
@@ -3277,7 +3277,7 @@
 {
     VALUE path, basedir;
     rb_scan_args(argc, argv, "11", &path, &basedir);
-    return realpath_internal(basedir, path, 1);
+    return rb_realpath_internal(basedir, path, 1);
 }
 
 /*
@@ -3297,7 +3297,7 @@
 {
     VALUE path, basedir;
     rb_scan_args(argc, argv, "11", &path, &basedir);
-    return realpath_internal(basedir, path, 0);
+    return rb_realpath_internal(basedir, path, 0);
 }
 
 static size_t
@@ -3429,7 +3429,7 @@
  *     File.dirname("/home/gumby/work/ruby.rb")   #=> "/home/gumby/work"
  */
 
-static VALUE
+VALUE
 rb_file_s_dirname(VALUE klass, VALUE fname)
 {
     const char *name, *root, *p;

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

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