您的位置:首页 > 其它

从零开始开发JVM语言(八)从类型定义开始的语义分析

2016-06-11 00:00 211 查看
摘要: 编译器 语义分析

目录戳这里

语义分析的结果会被送去字节码生成器,所以该结果必须接近字节码。而字节码格式是以类为单位的,所以语义分析的结果也应当是“类”。

这里的类不光是
class
,还包括了
interface
。在字节码和标准库的反射中,并不对两者做区分,只是将interface作为一个“修饰符”而已。同样的还有annotation(由于
Latte-lang
不支持定义注解,注解需要用java定义然后在
Latte
中使用。所以结果中不包括注解)。在语言层面,类和接口区别非常大,所以在这里还是将两者做了区分。

由于语义分析没有统一的算法,各个语言的特性也不同,所以下文将直接以Latte-lang实现的语义分析为模板进行描述,不会具有普遍性。但是对于类java语言完全可以照搬这一套实现方式。若是Lisp系之类与java相差非常大的,看一看也无妨。因为这一套结构实际上是对字节码的一种“封装”,毕竟JVM语言总是需要转为字节码的。

由于我定下的语义分析输出是接近字节码的表示,那么语义分析就必须输出一个个类型而不是单个的语句。而且任何值都会包含类型,所以总是需要先解析类型的。

#步骤
我将语义分析分为4步

注:为了本系列文章前后连贯且不受更新影响,所有链接都指向曾经版本的一个
tag
。代码结构与最新版是一致的,不过有些具体实现会变更(已知方法重写和方法寻找逻辑有问题并已在后续版本做了修复)

recording 记录所有等待解析的类型。记录类型名称和类型的种类(类、接口),记录下每个文件对应的
import


signatures 记录父类,接口,对类型填入构造函数、方法、字段,以及以上所有位置的注解。这个步骤会完成继承树的构建,方法、构造函数签名的完成(方法名、参数类型),但是实际的指令或值只会很有限的解析出来(例如默认参数)。

validate 验证有效性。检查以下:

循环继承

方法重写

abstract方法 非abstract类是否重载了所有的abstract方法。

注解 一些注解的检查,例如@Override/@FunctionalInterface/@FunctionalAbstractClass

data class data class必要方法的生成。

parse 最重要的步骤:对方法、注解填入各种指令和值

前三步的代码量相对还是比较少的。

#第一步
第一步,对于类型需要建立一个
Map<String,STypeDef> types
用于记录即可。这个Map不光需要记录“待解析”的类型,还需要记录已经编译完成的类型。对于
import
需要建立一个
Map<String,List<Import>> fileNameToImport
,表示文件名到
import
的映射。
首先找出当前的
package
命名空间,然后这个文件中所有的类都在这个命名空间下,遇到类/接口时也可以方便的构造完整类名。
然后找出所有的
Import
并记录在List中。当寻找结束时就可以存入
fileNameToImport
映射中了。
最后一次遍历,找出所有的类型定义,并获得完整类名,记录在
types
映射中。

#第二步

第二步就开始“恶心”了。个人建议构造一个
STypeDef getTypeWithName(String name,LineCol lineCol)
函数(点击这里看源码)。接收名称和行号信息,并返回找到的类型。 这个函数需要保证类的内容是“懒加载”的,否则会出现无限循环。例如:

class X
method():X

也就是说,类为
X
,其中有一个方法的返回类型也是
X
。若在构造这个类型时就试图将方法解析出来,则会不断尝试获取
X
类型,从而陷入无限循环。
正确做法是将那些不存在循环的内容先解析出来,然后记录这个类型,最后再解析那些可能造成循环的内容。

要获取已编译的类信息,可以解析字节码,也可以直接使用反射库。用反射好处在于动态加载的字节码也可以获取到,而解析字节码可以保证取得一切信息,包括非标准的Attribute以及运行时不可见注解。

这一步最关键的一点是统一。已编译的类型和未编译的类型的来源是不一致的,但它们必须变为统一且一致的结构。这实际上也算是设计语言时需要考虑到的一步。

例如,为了与java完美互通,
Latte-lang
没有实现null值检查。因为若是要加上,那么所有java类库实际上都是
nullable
的,编码时会加上无数不必要的null check。

下一篇单独描述一下第三步的做法。第三步里包含了一个值得思考和提升的算法(方法重写检查算法、是否重写了所有abstract方法的检查)。

最后,希望看官能够关注我的编译器哦~Latte
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: