最近的两篇关于 Rubinius 的文章中的第一篇是 Giles Bowkett 所撰写的, Giles 在尝试开始参与Rubinius 编译器的开发。Rubinius 编译器通过遍历 Ruby 抽象语法树(Abstract Syntax Tree,AST)进行工作,AST 使用 ParseTree 的 s 表达式(s-expressions)以树状形式展现 Ruby 的源码。这意味着它是一个使用符号来描述数据的数组。例如,它可能看上去如同:
[:call, [:lit, 1], :+, [:array, [:lit, 1]]]
字面量(Literal)看上去像这样:
[:lit, 42]
为了遍历 AST,ParseTree 使用了 SexpProcessor 库,这个库可以方便访问者的创建。为了分析一个 Ruby AST 的所有的节点类型,需要建立一个具有 process_XXX 方法的 SexpProcessor 的子类,XXX 须是节点的名字。例如,要处理的是:alias
节点,就得定义:
def process_alias(node)<br></br> cur = node.shift<br></br> nw = node.shift<br></br> # ...<br></br>end
Ruby 到 Rubinius 字节码编译器正是基于此方式构建的。例如,一个 Ruby 的alias
调用被分析成[:alias, :old_name, :new_name]
,编译器会做如下处理:
def process_alias(x)<br></br> cur = x.shift<br></br> nw = x.shift<br></br> add "push :#{cur}"<br></br> add "push :#{nw}"<br></br> add "push self"<br></br> add "send alias_method 2"<br></br>end
编译器获取到旧的名字(对应cur
变量值)和新的名字(对应nw
变量值),建立实现功能所必需的字节码指令(使用字符串),既而转换成由 Rubinius 解释器执行的二进制字节码。
拥有用 Ruby 写成的编译器让我们更加容易洞悉其内部工作机理并做出实验性的修改。有用的场景可能包括对生成的代码进行操作或者以低耗方式来搜集有关于被编译代码的统计数据。
想要浏览 Rubinius 的源代码,可以参阅InfoQ 上关于Rubinius 开发入门的文章,或者查看 Rubinius 的在线源代码,例如 Rubinius 当前版本的字节码编译器。
对 Rubinius 而言,编译器不是其仅有的必要条件,一个完善的标准库也是必不可少的。Red Artisan 的 Marus Crafter 提供了一个教程,教大家如何向Rubinius 添加类库功能。这个教程讲解了如何使用Rubinius 的外来函数接口( foreign function interface,ffi)访问本地类库调用(native library calls)。这可以用来实现一些缺失的类库功能,在这个教程中实现类库功能是 POSIX 的link
调用。
查看英文原文: Rubinius: Inside the Bytecode Compiler and Foreign Function Interface - - - - - -
译者简介:孙向晖,儿子小名“豆豆”,常被人称为“豆豆他爹”。1998 年开始步入 IT 行业,现任浪潮软件质保中心副主任。专注于研究和实践 MDA/UP/UML/SCM 等相关技术在团队中的大规模应用,对产品化的软件项目管理、需求管理和配置管理略有心得。他的博客为 http://blog.csdn.net/xiaosun/ 。参与 InfoQ 中文站内容建设,请邮件至 china-editorial[at]infoq.com 。
评论