From: Josh Cheek Date: 2012-06-22T11:39:13+09:00 Subject: Re: Ruby vs Python vs Java bytecode concept --14dae93a149582e00704c30689cb Content-Type: text/plain; charset=KOI8-R Content-Transfer-Encoding: quoted-printable On Wed, Jun 20, 2012 at 8:46 PM, Peter Zotov wro= te: > Daniel Hernandez =D0=C9=D3=C1=CC 20.06.2012 20:03: > > At Wed, 20 Jun 2012 23:56:48 +0900, >> gmspro gmspro wrote: >> >>> >>> Hi, >>> >>> I have a confusion about the process of ruby file. >>> >>> Suppose you have a file named f.rb. >>> To run this file you do: >>> ruby f.rb >>> >>> After this command what does happen? >>> >>> I knew for python, python makes bytecode and java makes .class. Both ar= e >>> not human readable. >>> >>> Is ruby a interpreted language or compiled language? >>> >> >> Maybe it depends on the the system that you use to run ruby. For >> example, YARV (now ruby 1.9) is a bytecode interpreter. I suppose that >> ruby code is converted to a bytecode sintactical tree that is >> interpreted by YARV. This is different to compile C, because the >> output of GCC is a machine code and not a sintactical tree. >> > > Bytecode has nothing to do with syntactical trees. Abstract syntax tree > is a notation used to represent the _source code_, e.g. > > irb> require 'ripper'; require 'pp' > irb> pp Ripper.sexp("puts 1 + 2") > [:program, > [[:command, > [:@ident, "puts", [1, 0]], > [:args_add_block, > [[:binary, [:@int, "1", [1, 5]], :+, [:@int, "2", [1, 9]]]], > false]]]] > > The mentioned structure can be thought of as a tree because it does not > have any loops (if you can't imagine it, try to find inspiration in this > image: http://cs.lmu.edu/~ray/images/**gcdast1.png > ) > > Bytecode is a format used akin to machine code, but for a virtual machine > specialized for a certain language. Nothing (except maybe common sense) > prevents you from creating a very real, silicon processor for the YARV > bytecode; it isn't inherently inferior to x86 machine code. Bytecode > looks like this: > > puts RubyVM::InstructionSequence.**new("puts 1 + 2").disasm >> > =3D=3D disasm: @>=3D= =3D=3D=3D=3D=3D=3D=3D=3D* > *=3D > 0000 trace 1 ( = 1) > 0002 putself > 0003 putobject 1 > 0005 putobject 2 > 0007 opt_plus > 0009 send :puts, 1, nil, 8, > 0015 leave > > As you can see, it's very similar to assembler code, but of a kind > developed specially for Ruby. > > Ruby 1.8 walks each node of the AST and interprets them. This is very slo= w. > Ruby 1.9 first converts the AST to the bytecode and then executes the > bytecode. > This still isn't very fast, but at least it is much faster than walking > the AST. > > >> -- >> Daniel >> > > -- > WBR, Peter Zotov. > > Holy crap, I didn't even know about RubyVM. Is there a way to get at the code from a block passed in? Looking at the docs, it appears both of these take a string, Could I do this sort of analysis and manipulation on ASTs or would I need to drop into C for that? --14dae93a149582e00704c30689cb Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable On Wed, Jun 20, 2012 at 8:46 PM, Peter Zotov <whitequark@whitequa= rk.org> wrote:
Daniel Hernandez =D0=BF=D0=B8=D1=81=D0=B0=D0=BB 20.06.2012 20:03:

At Wed, 20 Jun 2012 23:56:48 +0900,
gmspro gmspro wrote:

Hi,

I have a confusion about the process of ruby file.

Suppose you have a file named f.rb.
To run this file you do:
ruby f.rb

After this command what does happen?

I knew for python, python makes bytecode and java makes .class. Both are not human readable.

Is ruby a interpreted language or compiled language?

Maybe it depends on the the system that you use to run ruby. For
example, YARV (now ruby 1.9) is a bytecode interpreter. I suppose that
ruby code is converted to a bytecode sintactical tree that is
interpreted by YARV. This is different to compile C, because the
output of GCC is a machine code and not a sintactical tree.

Bytecode has nothing to do with syntactical trees. Abstract syntax tree
is a notation used to represent the _source code_, e.g.

irb> require 'ripper'; require 'pp'
irb> pp Ripper.sexp("puts 1 + 2")
[:program,
=C2=A0[[:command,
=C2=A0 [:@ident, "puts", [1, 0]],
=C2=A0 [:args_add_block,
=C2=A0 =C2=A0[[:binary, [:@int, "1", [1, 5]], :+, [:@int, "= 2", [1, 9]]]],
=C2=A0 =C2=A0false]]]]

The mentioned structure can be thought of as a tree because it does not
have any loops (if you can't imagine it, try to find inspiration in thi= s
image: http://cs.lmu.edu/~ray/images/gcdast1.png)

Bytecode is a format used akin to machine code, but for a virtual machine specialized for a certain language. Nothing (except maybe common sense)
prevents you from creating a very real, silicon processor for the YARV
bytecode; it isn't inherently inferior to x86 machine code. Bytecode looks like this:

puts RubyVM::InstructionSequence.new("puts 1 + 2").disasm<= br>
=3D=3D disasm: <RubyVM::InstructionSequence:<compiled>@<= compiled>>=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
0000 trace =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A01 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ( =C2=A0= 1)
0002 putself
0003 putobject =C2=A0 =C2=A0 =C2=A0 =C2=A01
0005 putobject =C2=A0 =C2=A0 =C2=A0 =C2=A02
0007 opt_plus =C2=A0 =C2=A0 =C2=A0 =C2=A0 <ic:2>
0009 send =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 :puts, 1, nil, 8, <i= c:1>
0015 leave

As you can see, it's very similar to assembler code, but of a kind
developed specially for Ruby.

Ruby 1.8 walks each node of the AST and interprets them. This is very slow.=
Ruby 1.9 first converts the AST to the bytecode and then executes the bytec= ode.
This still isn't very fast, but at least it is much faster than walking= the AST.


--
Daniel

--
=C2=A0WBR, Peter Zotov.



Holy crap, I didn&= #39;t even know about RubyVM.

Is there a way to ge= t at the code from a block passed in? Looking at the docs, it appears both = of these take a string, Could I do this sort of analysis and manipulation o= n ASTs or would I need to drop into C for that?
--14dae93a149582e00704c30689cb--