这两天上网冲浪的时候,偶然发现一个介绍Truffle这个开发编程语言框架的一个影片:
视频比较有意思的就是使用了Graal VM提供的Truffle语言框架区开发了一个编程语言,实现了一些基本的功能,比如四则运算和函数定义。个人看了看,对于想要了解编译器的入门者还是比较有启发的。
我在网上找了个幻灯片,通过sulong幻灯片的描述,我们能看到Graal这个生态系统的构成时这样的:
Graal编译器是一个用Java开发用来替换Hotspot虚拟机里C2编译器的即使编译器,和SubstrateVM配合起来也可以实现AOT。图中看出,多种编程语言都可以通过GraalVM最终获得多种产物,例如二进制可执行文件,各种数据库,甚至是编程语言本身。而输入方则为各种编程语言,例如本身跑在JVM上的Scala, kotlin, java等等。第二类是不运行在JVM但是也运行在其他虚拟机的语言,比如Js,R(这个应该只是解释器),Ruby,Python(如PyPy)等。第三类是原生编译成机器码的语言,如C, C++, Rust。运行在JVM的语言比较好理解,只要实现一个编译为JVM字节码的前端编译器就行。而像Js这总语言,GraalVM给出了一个Truffle框架,这个框架本质就是一个Java框架,只是它是用来开发编程语言的。用户可以通过这个框架实现AST语法分析树,最终交给Graal编译器编译为二进制,就制造了了一个编程语言。具体而言,我从网上找了个开源项目,类似于:
package nl.node;import com.oracle.truffle.api.TruffleLanguage;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.nodes.NodeInfo;@NodeInfo(shortName = "*")
public abstract class MulExpression extends NumberBinaryExpression {protected MulExpression(TruffleLanguage<?> language) {super(language);}@Specialization(rewriteOn = ArithmeticException.class)protected long doLong(long left, long right) {return Math.multiplyExact(left, right);}@Specialization(rewriteOn = ArithmeticException.class)protected double doDouble(double left, double right) {return left * right;}@Specialization(rewriteOn = ArithmeticException.class)protected double doDoubleLong(double left, long right) {return left * (double) right;}@Specialization(rewriteOn = ArithmeticException.class)protected double doLongDouble(long left, double right) {return (double) left * right;}@Overridepublic String toString() {return getLeft()+"*"+getRight();}
}
去依赖Truffle框架实现一个乘法符号对应的语义。GraalVM官方为了推这个生态,把上述着这些语言都给重新实现了一遍例如:R(FastR),Js(GraalJs),Python(GraalPython),Python(GraalPython),Ruby(TruffleRuby)。这些工作量无疑是巨大的,但是基于Graal生态,就可以用比较小的代价统一使用最优秀的编译器和运行时,是很伟大的突破。
对于C, C++, Rust这种纯编译型语言,路径似乎和运行在虚拟机的语言不同。GraalVM统一它们的方式是借助LLVM,可能由于人力的原因没办法再实现它们一次,就一劳永逸,使用Sulong这个工具,将LLVM字节码转化为Truffle框架里的AST语法分析树,再用Graal编译器编译。最终他们的关系可以用这张图叙述:
之后可以抽空了解一下基于Truffle框架如何实现一个简单的编程语言。