手把手教你实现一门运行在 JVM 上的语言 Enkel, 系列 14
/ / 点击 / 阅读耗时 4 分钟本文系 Creating JVM language 翻译的第 14 篇。
原文中的代码和原文有不一致的地方均在新的代码仓库中更正过,建议参考新的代码仓库。
源码
支持新的类型
目前为止 Enkel 仅支持了整数类型和字符串类型。是时候支持其他的原始类型了。这也是为创建面向对象特性做准备。
指令集的抽象
字节码指令中有很多指令仅仅是在数据类型上有区别,以 return 指令举例:
- return - 方法返回
- ireturn - 返回interger
- freturn - 返回float
- dreturn - 返回double
- lreturn - 返回long
- areturn - 返回引用
字节码生成的时候,我们多写一点 case 语句可以实现,但是很丑陋。因此我用 TypeSpecificOpcodes 枚举存储了所有类型对应的字节码指令:
1 | public enum TypeSpecificOpcodes { |
类型相关的字节码指令,目前我们用到了:
- load - 从局部变量表中加载变量
- store - 存储至局部变量表
- ret - 返回
- add - 操作数栈中两个数相加
- sub - 栈中操作数相减
- mul - 栈中操作数相乘
- div - 栈中操作数相除
TypeSpecificOpcodes 是在 BultInType 类中:
1 | public enum BultInType implements Type { |
无论何时,两个数相乘,只要知道类型就可以了,再也不用查找类型对应的字节码指令:
1 | public void generate(Multiplication expression) { |
示例
如下 Enkel 代码:1
2
3
4
5
6
7main(string[] args) {
var stringVar = "str"
var booleanVar = true
var integerVar = 2745 + 33
var doubleVar = 2343.05
var sumOfDoubleVars = 23.0 + doubleVar
}
编译后的字节码:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19public class AllPrimitiveTypes {
public static void main(java.lang.String[]);
Code:
0: ldc #8 // String str
2: astore_1 //store it variable
3: ldc #9 // int 1 - bool values are represented as ints in JVM
5: istore_2 //store as int
6: ldc #10 // int 2745
8: ldc #11 // int 33
10: iadd // iadd - add integers
11: istore_3 //store result in integer varaible
12: ldc #12 // float 2343.05f
14: fstore 4 //store in float variable
16: ldc #13 // float 23.0f
18: fload 4 //load integer varaible (from index 4)
20: fadd //add float variables
21: fstore 5 //store float result
23: return
}