读书笔记:显微镜下的Ruby(一)

  1. Ruby代码的运行

在1.9及以后版本的Ruby中,原代码运行要经过好几个步骤:
分词:得到词条
解析:得到抽象语法树(AST)
编译:使用YARV从AST转化到字节码

  1. 关于分词
    可以使用Ripper查看Ruby分词的结果:
require 'ripper'

code = <
[[[1, 0], :on_int, "10"],
 [[1, 2], :on_period, "."],
 [[1, 3], :on_ident, "times"],
 [[1, 8], :on_sp, " "],
 [[1, 9], :on_kw, "do"],
 [[1, 11], :on_sp, " "],
 [[1, 12], :on_op, "|"],
 [[1, 13], :on_ident, "n"],
 [[1, 14], :on_op, "|"],
 [[1, 15], :on_ignored_nl, "\n"],
 [[2, 0], :on_sp, "  "],
 [[2, 2], :on_ident, "puts"],
 [[2, 6], :on_sp, " "],
 [[2, 7], :on_ident, "n"],
 [[2, 8], :on_nl, "\n"],
 [[3, 0], :on_kw, "end"],
 [[3, 3], :on_nl, "\n"]]

  1. 关于解析
    Ruby使用Bison,在构建过程中创建解析器。
    LALR算法:向前查看反向最右推导
    解析后的结果是AST语法树,可以通过Ripper查看:
require 'ripper'
require 'pp'

code = <

[:program,
 [[:binary,
   [:@int, "2", [1, 0]],
   :+,
   [:binary, [:@int, "2", [1, 4]], :*, [:@int, "3", [1, 8]]]]]]
=> [:program, [[:binary, [:@int, "2", [1, 0]], :+, [:binary, [:@int, "2", [1, 4]], :*, [:@int, "3", [1, 8]]]]]]

  1. 关于编译
    RubyVM::InstructionSequence可以帮助显示Ruby编译后的YARV指令。
code = <

== disasm: #@>================================
== catch table
| catch type: break  st: 0002 ed: 0008 sp: 0000 cont: 0008
|------------------------------------------------------------------------
0000 trace            1                                               (   1)
0002 putobject        10
0004 send             , , block in 
0008 leave            
== disasm: #@>=======================
== catch table
| catch type: redo   st: 0002 ed: 0010 sp: 0000 cont: 0002
| catch type: next   st: 0002 ed: 0010 sp: 0000 cont: 0010
|------------------------------------------------------------------------
local table (size: 2, argc: 1 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1])
[ 2] n     
0000 trace            256                                             (   1)
0002 trace            1                                               (   2)
0004 putself          
0005 getlocal_OP__WC__0 2
0007 opt_send_without_block , 
0010 trace            512                                             (   3)
0012 leave                                                            (   2)

这段代码里有个do...end块,所以在YARV指令里可以看到本地表(local table)的存在。

你可能感兴趣的:(读书笔记:显微镜下的Ruby(一))