自己动手设计并实现一个动态类型编程语言

背景

前几年主要在搞"编译优化"相关的事情(热修框架、字节码hook框架、字节码优化之类的)不过其实严格来说做的这些跟"编译"没啥关系,只是熟悉Java字节码以及对asm、javassist这类库的api比较熟而已,只是叫"编译优化"听起来高大上一些😂

当时也想着去写一个真正的"编译器",看了一点"龙书"、"编译器设计"之类比较有名的书籍,发现连实现一个词法分析器似乎都很困难,直接就劝退了。

后来因为业务需要,开发了一个javac的插件:javac 编译器插件在代码迁移中的简单应用,插件本身实现比较简单,当时搞这个的时候顺带看了下javac的代码,似乎并不算太复杂。于是就仿照他也写个自己的Java编译器,实现了部分的语法,不过没有坚持写下去,部分原因是我当时的实现方案无法实现apt之类的机制。

虽然只实现了很小的一部分,但对我而言收益还是不小的,比如:

  1. 这是我实现的第一个手写的词法分析器,语法分析器,算是迈出了编译器开发的第一步
  2. 此外还让我发现了一个多年来都未曾注意到的Java语法:java里面返回多维数组的时候,数组的维度可以分别写在函数声明的左右两边,维度是两边之和,所以下面的三个声明是等效的,都是返回一个二维数组,虽然知道这个没啥价值,但若不是尝试写这个小编译器我可能一直不会知道这一点。
java 复制代码
private static int[][] f() {...}
private static int[] f()[] {...}
private static int f()[][] {...}

近期在搞一些稳定性相关的事情,有些时候需要通过hook来定位或者修复问题,不免要看看虚拟机的代码,不考虑各种优化,就解释执行而言似乎也不是特别复杂,又临近五一假期,就想着实现个动态类型的编程语言,这样编译器、虚拟机开发就都能体验一遍,于是就有了这个项目--charon

charon

目前实现的特性如下:

  1. 支持的类型:bool、long、double、string、function、class
  2. 函数可以赋值给变量、类的字段、作为参数或者返回值(method跟function不同,不是first-class类型,不能赋值给变量,类字段,也不能作为函数、方法的参数或者返回值)
  3. 支持常见的语言结构,比如:if-elseif-else,while-break-continue
  4. 支持定义类、方法,方法中可以通过'this'访问当前实例的字段
  5. 支持简单的ffi机制,用于实现charon做不到的事情,比如打印输出: __print, __println

具体的语法&语意后面预计会在"语法介绍&语法分析器实现"的文章中提一下,比如在charon中类似于rust:变量是可以重定义的,赋值是语句而不是表达式,if的'then'是block而不是一般的语句等。

代码仓库&构建

代码仓库:github.com/0x264/charo...

构建:

  1. 需要先安装rust,如果之前未安装过,可以先按rust官网的指示去安装一下
  2. clone一下代码仓库
  3. cd 到 charon 项目根目录
  4. 执行:cargo build --release

执行完上面的步骤后,会在target/release目录下生成3个可执行程序:

  1. charonc: charon 的编译器,会将代码编译成字节码,文件后缀:.charonbc,字节码格式类似于Java字节码
  2. charonp: 反汇编charonc生成的字节码文件.charonbc,功能类似于javap
  3. charon: 虚拟机可执行程序,可以传入charon源代码,也可以传入charonc编译生成的字节码

代码示例

工程根目录下有个examples,里面有一些示例代码可以参考。

下面用charon构建一棵二叉树,并进行中序遍历作为一个例子:

ini 复制代码
#!/usr/bin/env charon

// 调用createBinaryTree创建一棵二叉树,然后通过inOrder进行中序遍历
inOrder(createBinaryTree());

class Node {}

//              10
//            /    \
//           6      14
//         /  \    /  \
//        4    8  12  16
//
func createBinaryTree() {
    var left = Node();
    left.value = 4;

    var right = Node();
    right.value = 8;

    var l = Node();
    l.value = 6;
    l.left = left;
    l.right = right;

    var left = Node();
    left.value = 12;

    var right = Node();
    right.value = 16;

    var r = Node();
    r.value = 14;
    r.left = left;
    r.right = right;

    var root = Node();
    root.value = 10;
    root.left = l;
    root.right = r;

    return root;
}

func inOrder(root) {
    if (root.left) {
        inOrder(root.left);
    }
    __println(root.value);
    if (root.right) {
        inOrder(root.right);
    }
}

上面的代码示例可以有如下几种方法执行:

  1. 直接调用虚拟机执行:

    • charon binary-tree.charon
  2. 先编译成字节码,再交由虚拟机执行

    • charonc binary-tree.charon
    • charon binary-tree.charonbc
  3. charon是支持shebang,因此可以给源码文件加上可执行权限,然后直接执行

    • chmod +x binary-tree.charon
    • ./binary-tree.charon

另外从上面的代码可以看到:

  1. 函数不必提前声明即可使用
  2. 变量可以重定义
  3. 跟很多动态语言一样类的字段不必在类体中定义
  4. 对于未赋值的类字段,读取时将得到null
  5. 像null之类的值在作为bool表达式时会隐式转换为false
  6. ...

后续计划

  • 后面计划整理几篇相关的文档以期加深对编译器&虚拟机相关技术的理解,预计会补充以下几篇文章:

    1. 词法介绍&词法分析器的实现
    2. 语法介绍&语法分析器的实现
    3. 语意分析、字节码设计&字节码生成(charon是基于栈的,也会和基于寄存器的实现简单对比下)
    4. 虚拟机的实现(比如栈帧的布局,对于method 'this'的支持实现和java不太相同,以及ffi的支持,后面会简单讨论一下)
    5. 编译器&虚拟机中的错误处理(编译过程中的行号、列号信息处理、关于错误恢复的讨论,运行时的栈溢出检测等)
  • 虽然是个玩具项目,但开发他还是学到了一些东西:比如之前我一直以为熟悉Java字节码,但对于像max_locals这样的信息是否必要,以及虚拟机如何使用?虚拟机在调用方法,以及调用外部方法的时候如何进行栈帧布局的?等等在此之前我其实并不清楚。不过这个语言还是太小了,而且我也不会真的去用,所以即使加上gc等机制可能也没有test case去测,如果后面有时间的话可能会考虑学习写个简单的jvm😂

受制于能力和时间限制,原本想支持的一些特性,比如类的自定义构造函数等等没来得及搞,原本想支持一个简单的gc的,也没来得及做,并且测试也很少😂,若有大佬发现bug或者有建议,希望帮忙指正~

相关推荐
concisedistinct3 小时前
大数据开发语言 Scala(四):面向对象编程
大数据·开发语言·后端·scala·编程语言·面向对象
RichardNo14 天前
Android应用安装过程
android·编程语言·软件开发·软件开发编程语言
RichardNo14 天前
Android与服务器交互的方式中的对称加密和非对称加密(kotlin)
android·服务器·kotlin·编程语言·软件开发
野老杂谈4 天前
【面试系列】TypeScript高频面试题及详细解答
前端·面试·typescript·编程语言
野老杂谈4 天前
【面试系列】Kotlin 高频面试题及详细解答
面试·职场和发展·kotlin·编程语言
野老杂谈5 天前
【面试系列】Ruby 高频面试题
面试·职场和发展·ruby·编程语言
RichardNo17 天前
探索Android架构设计
编程语言·软件开发·软件开发编程语言
RichardNo17 天前
Android高级面试_8_热修补插件化等
android·面试·职场和发展·编程语言·软件开发
flysnow0108 天前
多版本GCC安装及切换
编译器·gcc·切换版本
野老杂谈8 天前
【面试系列】Swift 高频面试题及详细解答
面试·职场和发展·swift·编程语言