查看Ruby Under a Microscope的源代码
←
Ruby Under a Microscope
跳转到:
导航
、
搜索
因为以下原因,你没有权限编辑本页:
您刚才请求的操作只有这个用户组中的用户才能使用:
用户
您可以查看并复制此页面的源代码:
== 控制结构和方法调度 == * if 语句本质上是使用 branchunless 或者 branchif 根据 test 的计算结果为 true/false 来决定跳转到哪个代码分支继续执行。 * 跨作用域的跳转(比如 break 跳转到父作用域),则是使用 throw 指令 + 捕获表实现,向下找到最近的捕获表的 break 指针,然后充值 pc 和 ep 指针,从指针后的代码开始执行。rescue、ensure、retry、redo 和 next 的实现与此类似。 * for 只是 each 的封装,查看 <pre> code = <<END for i in 0..5 puts i end END puts RubyVM::InstructionSequence.compile(code).disasm </pre> 输出: <pre> == disasm: #<ISeq:<compiled>@<compiled>>================================ == catch table | catch type: break st: 0002 ed: 0008 sp: 0000 cont: 0008 |------------------------------------------------------------------------ local table (size: 2, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1]) [ 2] i 0000 trace 1 ( 1) 0002 putobject 0..5 0004 send <callinfo!mid:each, argc:0>, <callcache>, block in <compiled> 0008 leave == disasm: #<ISeq:block in <compiled>@<compiled>>======================= == catch table | catch type: redo st: 0006 ed: 0014 sp: 0000 cont: 0006 | catch type: next st: 0006 ed: 0014 sp: 0000 cont: 0014 |------------------------------------------------------------------------ local table (size: 2, argc: 1 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1]) [ 2] ?<Arg> 0000 getlocal_OP__WC__0 2 ( 3) 0002 setlocal_OP__WC__1 2 ( 1) 0004 trace 256 0006 trace 1 ( 2) 0008 putself 0009 getlocal_OP__WC__1 2 0011 opt_send_without_block <callinfo!mid:puts, argc:1, FCALL|ARGS_SIMPLE>, <callcache> 0014 trace 512 ( 3) 0016 leave </pre> 可以看到是调用了 0..5 的 each 方法,然后将 block 参数拷贝给了局部变量 i。 * send 是最核心和最复杂的控制结构, ruby 有 11 种方法类型 * ISEQ 是普通方法, CFUNC 是 c 语言编写的代码,都是 ruby 的内部实现。ATTRSET 是 attr_writer, IVAR 是 attr_reader, BMETHOD 表示 define_method 传入的 proc 对象定义的方法,UNDEF 用于移除方法, MISSING 是方法不存在的时候调用,其他等等。 * 对于 attr_reader 和 attr_writer, ruby 内部做了优化,不会创建新的栈帧,因为方法非常简短并且不会出错,也就需要错误的堆栈信息。内部使用 c 语言实现的 vm_setivar 和 vm_getivar 快速调用。 * 命名参数本质是创建了一个 hash 来包装,如果 hash.key? 返回 false,也就是不存在,就使用默认值。具体可以看下面这段代码的输出: <pre> code = <<END def add_two(a: 2, b: 3) a + b end puts add_two(1, 1) END puts RubyVM::InstructionSequence.compile(code).disasm </pre>
返回到
Ruby Under a Microscope
。
个人工具
登录
名字空间
页面
讨论
变换
查看
阅读
查看源代码
查看历史
操作
搜索
导航
首页
社区专页
新闻动态
最近更改
随机页面
帮助
工具箱
链入页面
相关更改
特殊页面