[前][次][番号順一覧][スレッド一覧][生データ]

yarv-diff:186

From: ko1 atdot.net
Date: 30 Dec 2005 10:19:19 -0000
Subject: [yarv-diff:186] r344 - in trunk: . benchmark yarvtest

Author: ko1
Date: 2005-12-30 19:19:18 +0900 (Fri, 30 Dec 2005)
New Revision: 344

Modified:
   trunk/ChangeLog
   trunk/benchmark/bmx_temp.rb
   trunk/eval.c
   trunk/eval_intern.h
   trunk/eval_proc.c
   trunk/test.rb
   trunk/yarvcore.c
   trunk/yarvcore.h
   trunk/yarvtest/test_eval.rb
Log:
	* yarvcore.c, yarvcore.h, eval.c, eval_proc.c : support
	Ruby's Binding

	* yarvcore.c : support TOPLEVEL_BINDING

	* yarvtest/test_eval.rb : add tests for above



Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog	2005-12-30 04:13:33 UTC (rev 343)
+++ trunk/ChangeLog	2005-12-30 10:19:18 UTC (rev 344)
@@ -4,6 +4,16 @@
 #  from Mon, 03 May 2004 01:24:19 +0900
 #
 
+2005-12-30(Fri) 19:07:51 +0900  Koichi Sasada  <ko1 atdot.net>
+
+	* yarvcore.c, yarvcore.h, eval.c, eval_proc.c : support
+	Ruby's Binding
+
+	* yarvcore.c : support TOPLEVEL_BINDING
+
+	* yarvtest/test_eval.rb : add tests for above
+
+
 2005-12-30(Fri) 13:12:28 +0900  Minero Aoki  <aamine loveruby.net>
 
 	* test/ruby/test_eval.rb: more tests for

Modified: trunk/benchmark/bmx_temp.rb
===================================================================
--- trunk/benchmark/bmx_temp.rb	2005-12-30 04:13:33 UTC (rev 343)
+++ trunk/benchmark/bmx_temp.rb	2005-12-30 10:19:18 UTC (rev 344)
@@ -1,9 +1,4 @@
-i=0
-while i<100000
-  begin
-    raise
-  rescue
-    
-  end
-  i+=1
-end
+require 'erb'
+50000.times{|e|
+  ERB.new('<%= e %>').result(binding)
+}

Modified: trunk/eval.c
===================================================================
--- trunk/eval.c	2005-12-30 04:13:33 UTC (rev 343)
+++ trunk/eval.c	2005-12-30 10:19:18 UTC (rev 344)
@@ -1141,7 +1141,7 @@
 {
   yarv_thread_t *th = GET_THREAD();
   yarv_control_frame_t *cfp = th->cfp;
-  cfp = YARV_PREVIOUS_CONTROL_FRAME(cfp);
+  cfp = th_get_ruby_level_cfp(th, YARV_PREVIOUS_CONTROL_FRAME(cfp));
   if(GC_GUARDED_PTR_REF(cfp->lfp[0])){
     return Qtrue;
   }
@@ -1894,12 +1894,15 @@
   return th_get_sourceline(th->cfp);
 }
 
+VALUE th_set_eval_stack(yarv_thread_t *, VALUE iseq);
+
 static VALUE
 eval(VALUE self, VALUE src, VALUE scope, char *file, int line)
 {
   volatile int safe = ruby_safe_level;
   int state;
   VALUE result;
+  yarv_binding_t *bind = 0;
 
   if (file == 0) {
     ruby_set_current_source();
@@ -1911,11 +1914,13 @@
   if((state = EXEC_TAG()) == 0){
     yarv_thread_t *th = GET_THREAD();
     yarv_iseq_t *iseq;
+    VALUE iseqval;
 
     if(scope != Qnil){
       yarv_env_t *env;
-      if(CLASS_OF(scope) == cYarvEnv){
-        /* do nothing */
+      if(CLASS_OF(scope) == cYarvBinding){
+        GetBindingVal(scope, bind);
+        scope = bind->env;
       }
       else if(CLASS_OF(scope) == cYarvProc){
         yarv_proc_t *proc;
@@ -1930,17 +1935,28 @@
       th->base_block = &env->block;
     }
     else{
-      
       yarv_control_frame_t *cfp =
         th_get_ruby_level_cfp(th, YARV_PREVIOUS_CONTROL_FRAME(th->cfp));
       th->base_block = GET_BLOCK_PTR_IN_CFP(cfp);
       th->base_block->iseq = cfp->iseq;
     }
-    
+
+    /* make eval iseq */
     iseq = th->base_block->iseq->local_iseq;
     th->base_local_tbl  = iseq->local_tbl;
     th->base_local_size = iseq->local_size;
-    result = yarvcore_eval(0, src, rb_str_new2(file), INT2FIX(line));
+    iseqval = th_compile(th, src, rb_str_new2(file), INT2FIX(line));
+    th_set_eval_stack(th, iseqval);
+    th->base_block = 0;
+
+    /* save new env */
+    GetISeqVal(iseqval, iseq);
+    if(bind && iseq->local_size > 0){
+      bind->env = th_make_env_object(th, th->cfp);
+    }
+
+    /* kick */
+    result = th_eval_body(th);
   }
   POP_TAG();
 
@@ -2714,7 +2730,8 @@
 {
   VALUE ary = rb_ary_new();
   yarv_thread_t *th = GET_THREAD();
-  yarv_control_frame_t *cfp = YARV_PREVIOUS_CONTROL_FRAME(th->cfp);
+  yarv_control_frame_t *cfp =
+    th_get_ruby_level_cfp(th, YARV_PREVIOUS_CONTROL_FRAME(th->cfp));
   int i;
   
   while(1){
@@ -2909,7 +2926,8 @@
 }
 
 int
-rb_dvar_current(){
+rb_dvar_current()
+{
   yarv_thread_t *th = GET_THREAD();
   if(th->base_block){
     return 1;

Modified: trunk/eval_intern.h
===================================================================
--- trunk/eval_intern.h	2005-12-30 04:13:33 UTC (rev 343)
+++ trunk/eval_intern.h	2005-12-30 10:19:18 UTC (rev 344)
@@ -286,8 +286,8 @@
 NORETURN(void print_undef _((VALUE, ID)));
 
 rb_thread_t rb_vm_curr_thread();
+VALUE th_compile(yarv_thread_t *th, VALUE str, VALUE file, VALUE line);
 
-
 VALUE th_get_cref(yarv_thread_t *th, yarv_iseq_t *iseq, yarv_control_frame_t *cfp);
 
 static yarv_control_frame_t *

Modified: trunk/eval_proc.c
===================================================================
--- trunk/eval_proc.c	2005-12-30 04:13:33 UTC (rev 343)
+++ trunk/eval_proc.c	2005-12-30 10:19:18 UTC (rev 344)
@@ -59,11 +59,17 @@
  */
 
 VALUE
-rb_f_binding(self)
-    VALUE self;
+rb_f_binding(VALUE self)
 {
-  return th_make_env_object(GET_THREAD(),
-                            YARV_PREVIOUS_CONTROL_FRAME(GET_THREAD()->cfp));
+  yarv_thread_t *th = GET_THREAD();
+  yarv_control_frame_t *cfp =
+    th_get_ruby_level_cfp(th, th->cfp);
+  VALUE bindval = rb_obj_alloc(cYarvBinding);
+  yarv_binding_t *bind;
+  
+  GetBindingVal(bindval, bind);
+  bind->env = th_make_env_object(th, cfp);
+  return bindval;
 }
 
 /*
@@ -150,11 +156,13 @@
       rb_raise(rb_eArgError, "tried to create Proc object without a block");
     }
   }
-  cfp = YARV_PREVIOUS_CONTROL_FRAME(cfp);
+  cfp = th_get_ruby_level_cfp(th, YARV_PREVIOUS_CONTROL_FRAME(cfp));
   procval = th_make_proc(th, cfp, block);
   
   if(is_lambda){
-    // TODO: lambda or proc
+    yarv_proc_t *proc;
+    GetProcVal(procval, proc);
+    proc->is_lambda = Qtrue;
   }
   return procval;
 }

Modified: trunk/test.rb
===================================================================
--- trunk/test.rb	2005-12-30 04:13:33 UTC (rev 343)
+++ trunk/test.rb	2005-12-30 10:19:18 UTC (rev 344)
@@ -1,5 +1,108 @@
+class C
+  def m
+    self.class.class_eval %q{
+      module M
+        a = 1
+        $b = binding
+      end
+    }
+  end
+end
+C.new.m
+p eval('a', $b)
 
+
+__END__
+Const = :top
 class C
+  Const = :C
+  def m
+    binding
+  end
+end
+
+eval('Const', C.new.m)
+__END__
+$ans = []
+      def m
+        $b = binding
+      end
+      m
+      $ans << eval(%q{
+        $ans << eval(%q{
+          a
+        }, $b)
+        a = 1
+      }, $b)
+p      $ans
+
+__END__
+
+class C
+  @@cvar = 1
+end
+
+C.new.instance_eval %{
+  p @@cvar
+}
+__END__
+class Fixnum
+  @@cvar = 1
+end
+
+1.instance_eval %{
+  p @@cvar
+}
+__END__
+
+class Base
+  def initialize(p1, p2 = 1)
+    p [p1, p2]
+  end
+end
+
+class Derived < Base
+  def initialize(p1, p2 = 2)
+    super
+  end
+end
+
+Derived.new(0)
+__END__
+require 'erb'
+
+ERB.new(<<EOS).run(binding)
+<% 3.times do |n| %>
+% n = 0
+* <%= n%>
+<% end %>
+EOS
+
+__END__
+
+
+class C
+end
+
+class D
+  C.class_eval{
+    def m1
+      p :OK
+    end
+    eval %{
+      def m2
+        p :OK
+      end
+    }
+  }
+end
+
+C.new.m1 #=> :OK
+#D.new.m2 #=> :OK
+C.new.m2 #=> NoMethodError
+
+__END__
+class C
 #  private
   $pr = proc{
     def m

Modified: trunk/yarvcore.c
===================================================================
--- trunk/yarvcore.c	2005-12-30 04:13:33 UTC (rev 343)
+++ trunk/yarvcore.c	2005-12-30 10:19:18 UTC (rev 344)
@@ -22,6 +22,7 @@
 VALUE mYarvInsns;
 VALUE cYarvEnv;
 VALUE cYarvProc;
+VALUE cYarvBinding;
 
 VALUE symIFUNC;
 VALUE symCFUNC;
@@ -109,6 +110,7 @@
 
 VALUE yarv_new_iseqval(VALUE node, VALUE name, VALUE file,
                        VALUE parent, VALUE type, VALUE opt);
+static VALUE th_eval(yarv_thread_t *th, VALUE iseq);
 
 /************/
 /* YARVCore */
@@ -183,8 +185,6 @@
 RUBY_EXTERN int ruby_nerrs;
 RUBY_EXTERN NODE* ruby_eval_tree;
 
-static VALUE vm_eval(VALUE self, VALUE iseq);
-
 VALUE
 yarv_load(char *file)
 {
@@ -209,7 +209,7 @@
   iseq = yarv_new_iseqval((VALUE)node, rb_str_new2("<top (required)>"),
                           rb_str_new2(file), Qfalse, ISEQ_TYPE_TOP, Qfalse);
 
-  vm_eval(GET_VM()->self, iseq);
+  th_eval(GET_THREAD(), iseq);
   return 0;
 }
 
@@ -256,7 +256,6 @@
   *var = val;
 }
 
-
 static VALUE
 compile_string(VALUE str, VALUE file, VALUE line)
 {
@@ -271,34 +270,41 @@
   return (VALUE)node;
 }
 
-
 static VALUE
 yarvcore_eval_iseq(VALUE iseq)
 {
-  VALUE vm;
-  VALUE ret;
-  vm = GET_VM()->self;
-  ret = vm_eval(vm, iseq);
-  return ret;
+  return th_eval(GET_THREAD(), iseq);
 }
 
-VALUE
-yarvcore_eval_parsed(VALUE node, VALUE file)
+static VALUE
+th_compile_from_node(yarv_thread_t *th, NODE *node, VALUE file)
 {
-
   VALUE iseq;
-
-  if(GET_THREAD()->base_block){
-    iseq = yarv_new_iseqval(node,
-                            GET_THREAD()->base_block->iseq->name,
+  if(th->base_block){
+    iseq = yarv_new_iseqval((VALUE)node,
+                            th->base_block->iseq->name,
                             file,
-                            GET_THREAD()->base_block->iseq->self,
+                            th->base_block->iseq->self,
                             ISEQ_TYPE_EVAL, Qfalse);
   }
   else{
-    iseq = yarv_new_iseqval(node, rb_str_new2("<main>"), file,
+    iseq = yarv_new_iseqval((VALUE)node, rb_str_new2("<main>"), file,
                             Qfalse, ISEQ_TYPE_TOP, Qfalse);
   }
+  return iseq;
+}
+
+VALUE
+th_compile(yarv_thread_t *th, VALUE str, VALUE file, VALUE line)
+{
+  NODE *node = (NODE*)compile_string(str, file, line);
+  return th_compile_from_node(th, (NODE *)node, file);
+}
+
+VALUE
+yarvcore_eval_parsed(VALUE node, VALUE file)
+{
+  VALUE iseq = th_compile_from_node(GET_THREAD(), (NODE*)node, file);
   return yarvcore_eval_iseq(iseq);
 }
 
@@ -588,16 +594,10 @@
   return self;
 }
 
-static VALUE thread_eval(VALUE self, VALUE iseq);
-
 static VALUE
 vm_eval(VALUE self, VALUE iseq)
 {
-  yarv_vm_t *vm;
-  VALUE val;
-  GetVMVal(self, vm);
-  val = thread_eval(vm->main_thread, iseq);
-  return val;
+  return th_eval(GET_THREAD(), iseq);
 }
 
 
@@ -737,26 +737,28 @@
 
 VALUE th_eval_body(yarv_thread_t *th);
 VALUE th_set_top_stack(yarv_thread_t *, VALUE iseq);
-VALUE th_set_eval_stack(yarv_thread_t *, VALUE iseq);
 
-static VALUE thread_eval(VALUE self, VALUE iseq){
+static VALUE
+th_eval(yarv_thread_t *th, VALUE iseq)
+{
   VALUE val;
-  yarv_thread_t *th;
-  GetThreadVal(self, th);
-
-  if(th->base_block){
-    th_set_eval_stack(th, iseq);
-    th->base_block = 0;
+  th_set_top_stack(th, iseq);
+  if(!rb_const_defined(rb_cObject, rb_intern("TOPLEVEL_BINDING"))){
+    rb_define_global_const("TOPLEVEL_BINDING", rb_f_binding(Qnil));
   }
-  else{
-    th_set_top_stack(th, iseq);
-  }
   val = th_eval_body(th);
-  
   return val;
 }
 
+static VALUE
+thread_eval(VALUE self, VALUE iseq)
+{
+  yarv_thread_t *th;
+  GetThreadVal(self, th);
+  return th_eval(th, iseq);
+}
 
+
 /***************/
 /* YarvEnv     */
 /***************/
@@ -843,9 +845,9 @@
     MARK_UNLESS_NULL(proc->envval);
     //GC_INFO("blockval\n");
     MARK_UNLESS_NULL(proc->blockprocval);
-
+    MARK_UNLESS_NULL(proc->cref_stack);
     //GC_INFO("iseq\n");
-    if(proc->block.iseq && BUILTIN_TYPE(proc->block.iseq) == T_NODE){
+    if(proc->block.iseq && YARV_IFUNC_P(proc->block.iseq)){
       MARK_UNLESS_NULL((VALUE)(proc->block.iseq));
     }
   }
@@ -862,6 +864,7 @@
   proc->envval = 0;
   proc->blockprocval = 0;
   proc->block.iseq = 0;
+  proc->is_lambda = 0;
   return obj;
 }
 
@@ -919,6 +922,48 @@
     return INT2FIX(-1);
   }
 }
+
+
+/***************/
+/* YarvBinding */
+/***************/
+
+static void
+binding_free(void *ptr)
+{
+  yarv_binding_t *bind;
+  FREE_REPORT("-> binding");
+  if(ptr){
+    bind = ptr;
+    ruby_xfree(ptr);
+  }
+  FREE_REPORT("<- binding");
+}
+
+static void
+binding_mark(void *ptr)
+{
+  yarv_binding_t *bind;
+  MARK_REPORT("-> binding", 1);
+  if(ptr){
+    bind = ptr;
+    MARK_UNLESS_NULL(bind->env);
+    MARK_UNLESS_NULL(bind->cref_stack);
+  }
+  MARK_REPORT("<- binding", 0);
+}
+
+static VALUE
+binding_alloc(VALUE klass)
+{
+  VALUE obj;
+  yarv_binding_t *bind;
+  obj = Data_Make_Struct(klass, yarv_binding_t,
+                         binding_mark, binding_free, bind);
+  return obj;
+}
+
+
 /********************************************************************/
 
 static VALUE yarv_once(){
@@ -1042,6 +1087,10 @@
   rb_define_method(cYarvProc, "arity", proc_arity, 0);
   rb_define_singleton_method(cYarvProc, "new", rb_proc_s_new, -1);
 
+  /* declare YARVCore::VM::Binding */
+  cYarvBinding = rb_define_class_under(cYarvVM, "Binding", rb_cObject);
+  rb_define_alloc_func(cYarvBinding, binding_alloc);
+  
   /* misc */
   
   

Modified: trunk/yarvcore.h
===================================================================
--- trunk/yarvcore.h	2005-12-30 04:13:33 UTC (rev 343)
+++ trunk/yarvcore.h	2005-12-30 10:19:18 UTC (rev 344)
@@ -88,6 +88,7 @@
 extern VALUE mYarvInsns;
 extern VALUE cYarvEnv;
 extern VALUE cYarvProc;
+extern VALUE cYarvBinding;
 
 extern VALUE symIFUNC;
 extern VALUE symCFUNC;
@@ -421,13 +422,15 @@
   yarv_block_t block;
   VALUE envval;       /* for GC mark */
   VALUE blockprocval;
+  VALUE cref_stack;
   int safe_level;
+  int is_lambda;
+  int visibility;
 } yarv_proc_t;
 
 #define GetEnvVal(obj, iobj) \
   Data_Get_Struct(obj, yarv_env_t, iobj)
 
-
 typedef struct{
   VALUE *env;
   int    env_size;
@@ -436,7 +439,15 @@
   yarv_block_t block;
 } yarv_env_t;
 
+#define GetBindingVal(obj, iobj) \
+  Data_Get_Struct(obj, yarv_binding_t, iobj)
 
+typedef struct{
+  VALUE env;
+  VALUE cref_stack;
+} yarv_binding_t;
+
+
 /* used by compile time and send insn */
 #define VM_CALL_ARGS_SPLAT_BIT     0x01
 #define VM_CALL_ARGS_BLOCKARG_BIT  0x02

Modified: trunk/yarvtest/test_eval.rb
===================================================================
--- trunk/yarvtest/test_eval.rb	2005-12-30 04:13:33 UTC (rev 343)
+++ trunk/yarvtest/test_eval.rb	2005-12-30 10:19:18 UTC (rev 344)
@@ -106,7 +106,7 @@
         $ans << Const
         C.module_eval %{
           $ans << Const
-          Boo = false
+          Boo = false unless defined? Boo
           unless $nest
             $nest = true
             m
@@ -135,5 +135,60 @@
       $ans
     }
   end
+
+  def test_binding
+    ae %q{
+      def m
+        a = :ok
+        $b = binding
+      end
+      m
+      eval('a', $b)
+    }
+    ae %q{
+      def m
+        a = :ok
+        $b = binding
+      end
+      m
+      eval('b = :ok2', $b)
+      eval('[a, b]', $b)
+    }
+    ae %q{
+      $ans = []
+      def m
+        $b = binding
+      end
+      m
+      $ans << eval(%q{
+        $ans << eval(%q{
+          a
+        }, $b)
+        a = 1
+      }, $b)
+      $ans
+    }
+    ae %q{
+      Const = :top
+      class C
+        Const = :C
+        def m
+          binding
+        end
+      end
+      eval('Const', C.new.m)
+    }
+    ae %q{
+      Const = :top
+      a = 1
+      class C
+        Const = :C
+        def m
+          eval('Const', TOPLEVEL_BINDING)
+        end
+      end
+      C.new.m
+    }
+  end
 end
 


-- 
ML: yarv-diff quickml.atdot.net
Info: http://www.atdot.net/~ko1/quickml

[前][次][番号順一覧][スレッド一覧][生データ]