From: Rocky Bernstein Date: 2008-03-14T11:45:34+09:00 Subject: Re: Ruby 1.8.6 binding value after "if" expression evaluation ------=_Part_1060_16353499.1205462743859 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Content-Disposition: inline A slightly shorter patch by sinking common code: Index: eval.c =================================================================== --- eval.c (revision 15769) +++ eval.c (working copy) @@ -3038,15 +3038,15 @@ RETURN(Qfalse); case NODE_IF: - EXEC_EVENT_HOOK(RUBY_EVENT_LINE, node, self, - ruby_frame->last_func, - ruby_frame->last_class); if (RTEST(rb_eval(self, node->nd_cond))) { node = node->nd_body; } else { node = node->nd_else; } + EXEC_EVENT_HOOK(RUBY_EVENT_LINE, node, self, + ruby_frame->last_func, + ruby_frame->last_class); goto again; case NODE_WHEN: On Thu, Mar 13, 2008 at 10:13 PM, Rocky Bernstein wrote: > I think I've found why this is happening. The trace hook for NODE_IF is > getting called a before the expression evaluation occurs when it should be > called afterwards. Attached is a patch. I will also update #18722with this information. > > Thanks. > > On Thu, Mar 13, 2008 at 2:32 PM, Rocky Bernstein < > rocky.bernstein@gmail.com> wrote: > > > Thanks. The output you report matches what I get in 1.8.6 and suggests > > where to start looking for a bug. I'm not sure this is strictly related to > > blocks. In particular try this: > > > > x = 6.2*1 if > > x=6.1 > > > > The line break after the "if" is intentional since it more clearly shows > > which part gets run when. In this code, > > first there are two stops on the x=6.1 presumably before and after the > > assignment. But by the time of the c-call to multiply 6.2*1, the value > > of x is 6.1. It is like some sort of register flushing that is going > > before the c-call, but again that's pure guess. > > > > On Thu, Mar 13, 2008 at 12:59 PM, Yemi I. D. Bedu > > wrote: > > > > > Hello, > > > > > > I tried this and it has to do with implicit / explicit block. Also I > > > expanded example: > > > > > > > > > > > > p RUBY_VERSION > > > > > > > > > > > > def trace_func(event, file, line, id, binding, klass, *) > > > > > > printf("%s:%d (%s) x=%s\n", file, line, event, eval("x", binding)) > > > > > > end > > > > > > > > > > > > set_trace_func method(:trace_func).to_proc > > > > > > > > > > > > x=2 > > > > > > (x=3.2) if x=3.1 > > > > > > begin x=4.2 end if x=4.1 > > > > > > x=5.2 if x=5.1 > > > > > > x=6.2*1 if x=6.1*1 > > > > > > if x=7.1 then x=7.2 end > > > > > > x=8 > > > > > > x=9 > > > > > > > > > > > > My Results were: > > > > > > > > > > > > "1.8.2" > > > > > > > > > > > > tt.rb:9 (line) x= > > > > > > > > > > > > tt.rb:10 (line) x=2 > > > > > > tt.rb:10 (line) x=2 > > > > > > tt.rb:10 (line) x=3.1 > > > > > > > > > > > > tt.rb:11 (line) x=3.2 > > > > > > tt.rb:11 (line) x=3.2 > > > > > > tt.rb:11 (line) x=4.1 > > > > > > > > > > > > tt.rb:12 (line) x=4.2 > > > > > > tt.rb:12 (line) x=4.2 > > > > > > > > > > > > tt.rb:13 (line) x=5.2 > > > > > > tt.rb:13 (line) x=5.2 > > > > > > tt.rb:13 (c-call) x=5.2 > > > > > > tt.rb:13 (c-return) x=5.2 > > > > > > tt.rb:13 (c-call) x=6.1 > > > > > > tt.rb:13 (c-return) x=6.1 > > > > > > > > > > > > tt.rb:14 (line) x=6.2 > > > > > > tt.rb:14 (line) x=6.2 > > > > > > tt.rb:14 (line) x=7.1 > > > > > > > > > > > > tt.rb:15 (line) x=7.2 > > > > > > > > > > > > tt.rb:16 (line) x=8 > > > > > > > > > > > > You would need to either have parens, explicit block or use the other > > > if form to get that last firing from the trace. It seems to token out each > > > expression unit on a line and then call eval to get the previous lines > > > value. I don't know if you can confirm this on your 1.8.6 install. The > > > lines with the multiply do func calls so they eval before going into the new > > > env and when the come back. You might want to have a more complex expression > > > execute like a list comprehension or a map. Good day. > > > > > > Yemi Bedu > > > > > > P&R Fasteners, Inc. > > > P&R Castings, LLC. > > > 325 Pierce St > > > Somerset, NJ 08873 > > > (T) 732-302-3600 > > > (F) 732-302-3636 > > > ------------------------------ > > > > > > *From:* Rocky Bernstein [mailto:rocky.bernstein@gmail.com] > > > *Sent:* Wednesday, March 12, 2008 11:21 PM > > > *To:* ruby-core@ruby-lang.org > > > *Subject:* Ruby 1.8.6 binding value after "if" expression evaluation > > > > > > > > > > > > Here's another trace hook weirdness that I've encountered. > > > > > > Consider this program and its output: > > > > > > def trace_func(event, file, line, id, binding, klass, *) > > > printf("%s:%d (%s) x=%s\n", file, line, event, eval("x", binding)) > > > end > > > set_trace_func method(:trace_func).to_proc > > > x=5 > > > x=6.2 if x=6.1 > > > x=7 > > > > > > > > > $ ruby bug2.rb > > > bug2.rb:6: warning: found = in conditional, should be == > > > bug2.rb:5 (line) x= > > > bug2.rb:6 (line) x=5 > > > bug2.rb:6 (line) x=5 > > > bug2.rb:7 (line) x=6.2 > > > > > > Why does x appear to have value 5 the second time on line 7 rather > > > than 6.1? > > > > > > Looking at eval.c what's supposed to happen (I think) is that the > > > trace hook is called before the expression (x=6.1) is evaluated and > > > then called before the assignment "x=6.2" in which case it should have > > > value 6.1, not 5. > > > > > > Can anyone explain why this happens? > > > > > > Again this is ruby 1.8.6 > > > > > > > > ------=_Part_1060_16353499.1205462743859 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Content-Disposition: inline A slightly shorter patch by sinking common code:

Index: eval.c
===================================================================
--- eval.c    (revision 15769)
+++ eval.c    (working copy)
@@ -3038,15 +3038,15 @@
     RETURN(Qfalse);
 
       case NODE_IF:
-    EXEC_EVENT_HOOK(RUBY_EVENT_LINE, node, self,
-            ruby_frame->last_func,
-            ruby_frame->last_class);
     if (RTEST(rb_eval(self, node->nd_cond))) {
         node = node->nd_body;
     }
     else {
         node = node->nd_else;
     }
+    EXEC_EVENT_HOOK(RUBY_EVENT_LINE, node, self,
+            ruby_frame->last_func,
+            ruby_frame->last_class);
     goto again;
 
       case NODE_WHEN:


On Thu, Mar 13, 2008 at 10:13 PM, Rocky Bernstein <rocky.bernstein@gmail.com> wrote:
I think I've found why this is happening. The trace hook for NODE_IF is getting called a before the expression evaluation occurs when it should be called afterwards. Attached is a patch. I will also update  #18722 with this information.

Thanks.

On Thu, Mar 13, 2008 at 2:32 PM, Rocky Bernstein <rocky.bernstein@gmail.com> wrote:
Thanks. The output you report matches what I get in 1.8.6 and suggests where to start looking for a bug. I'm not sure this is strictly related to blocks. In particular try this:

x = 6.2*1 if
  x=6.1

The line break after the "if" is intentional since it more clearly shows which part gets run when. In this code,
first there are two stops on the x=6.1 presumably before and after the assignment. But by the time of the c-call to multiply 6.2*1, the value of x is 6.1. It is like some sort of register flushing that is going before the c-call, but again that's pure guess.

On Thu, Mar 13, 2008 at 12:59 PM, Yemi I. D. Bedu <yemi@weldfast.com> wrote:

Hello,

 I tried this and it has to do with implicit / explicit block. Also I expanded example:

 

p RUBY_VERSION

 

def trace_func(event, file, line, id, binding, klass, *)

  printf("%s:%d (%s) x=%s\n", file, line, event, eval("x", binding))

end

 

set_trace_func method(:trace_func).to_proc

 

x=2

(x=3.2) if x=3.1

begin x=4.2 end if x=4.1

x=5.2 if x=5.1

x=6.2*1 if x=6.1*1

if x=7.1 then x=7.2 end

x=8

x=9

 

My Results were:

 

"1.8.2"

 

tt.rb:9 (line) x=

 

tt.rb:10 (line) x=2

tt.rb:10 (line) x=2

tt.rb:10 (line) x=3.1

 

tt.rb:11 (line) x=3.2

tt.rb:11 (line) x=3.2

tt.rb:11 (line) x=4.1

 

tt.rb:12 (line) x=4.2

tt.rb:12 (line) x=4.2

 

tt.rb:13 (line) x=5.2

tt.rb:13 (line) x=5.2

tt.rb:13 (c-call) x=5.2

tt.rb:13 (c-return) x=5.2

tt.rb:13 (c-call) x=6.1

tt.rb:13 (c-return) x=6.1

 

tt.rb:14 (line) x=6.2

tt.rb:14 (line) x=6.2

tt.rb:14 (line) x=7.1

 

tt.rb:15 (line) x=7.2

 

tt.rb:16 (line) x=8

 

You would need to either have parens, explicit block or use the other if form to get that last firing from the trace. It seems to token out each expression unit on a line and then call eval to get the previous lines value. I don't know if you can confirm this on your 1.8.6 install. The lines with the multiply do func calls so they eval before going into the new env and when the come back. You might want to have a more complex expression execute like a list comprehension or a map. Good day.

Yemi Bedu

P&R Fasteners, Inc.
P&R Castings, LLC.
325 Pierce St
Somerset, NJ 08873
(T) 732-302-3600
(F) 732-302-3636


From: Rocky Bernstein [mailto:rocky.bernstein@gmail.com]
Sent: Wednesday, March 12, 2008 11:21 PM
To: ruby-core@ruby-lang.org
Subject: Ruby 1.8.6 binding value after "if" expression evaluation

 

Here's another trace hook weirdness that I've encountered.

Consider this program and its output:

def trace_func(event, file, line, id, binding, klass, *)
  printf("%s:%d (%s) x=%s\n", file, line, event, eval("x", binding))
end
set_trace_func method(:trace_func).to_proc
x=5
x=6.2 if x=6.1
x=7


$ ruby bug2.rb
bug2.rb:6: warning: found = in conditional, should be ==
bug2.rb:5 (line) x=
bug2.rb:6 (line) x=5
bug2.rb:6 (line) x=5
bug2.rb:7 (line) x=6.2

Why does x appear to have value 5 the second time on line 7 rather than 6.1?

Looking at eval.c what's supposed to happen (I think) is that the trace hook is called before the expression (x=6.1) is evaluated and then called before the assignment "x=6.2" in which case it should have value 6.1, not 5.

Can anyone explain why this happens?

Again this is ruby 1.8.6




------=_Part_1060_16353499.1205462743859--