这个项目的源码可以从Github仓库中进行克隆。
迄今为止,Enkel只支持整型和字符串类型。是时候该添加其他原子类型了。这一步对于即将添加的面向对象功能的编译器来说也十分有必要(到目前为止,不能创建除String之外的其他对象)。
有许多字节码指令,它们之间的区别仅在于类型。让我们以返回指令为例:
- return - 从函数中返回
- ireturn - 从函数中返回整型值(从栈顶弹出)
- freturn - 返回单精度浮点值
- dreturn - 返回双精度浮点值
- lreturn - 返回长整型
- areturn - 返回引用类型
在介绍字节码指令的每个章节中为每种类型添加示例可能会很诱人(tempting),但是,这会造成糟糕的论断(awful ifology)- 我们不希望这样,因此我决定创建一个TypeSpecificOpcodes
枚举,该枚举分别存储每种类型的操作码,并且可由Type
枚举访问:
public enum TypeSpecificOpcodes {
INT (ILOAD, ISTORE, IRETURN,IADD,ISUB,IMUL,IDIV), //values (-127,127) - one byte.
LONG (LLOAD, LSTORE, LRETURN,LADD,LSUB,LMUL,LDIV),
FLOAT (FLOAD, FSTORE, FRETURN,FADD,FSUB,FMUL,FDIV),
DOUBLE (DLOAD, DSTORE, DRETURN,DADD,DSUB,DMUL,DDIV),
VOID(ALOAD, ASTORE, RETURN,0,0,0,0),
OBJECT (ALOAD,ASTORE,ARETURN,0,0,0,0);
TypeSpecificOpcodes(int load, int store, int ret, int add, int sub, int mul, int div) {
//assign each parameter to the field
}
//getters
}
到目前为止,使用的指令为:
- load - 加载变量
- store - 存储变量
- ret - 返回值
- add - 将栈顶的两个值相加
- sub - 将栈顶的两个值相减
- mul - 将栈顶的两个值相乘
- div - 将栈顶的两个值相除
TypeSpecificOpcodes
在BultInType
枚举中使用:
public enum BultInType implements Type {
BOOLEAN("bool",boolean.class,"Z", TypeSpecificOpcodes.INT),
//other members
BultInType(String name, Class<?> typeClass, String descriptor, TypeSpecificOpcodes opcodes) {
//assign to fields
}
@Override
public int getMultiplyOpcode() {
return opcodes.getMultiply();
}
}
当两个值相乘时,不需要为表达式类型查找指定的操作码 - Type
枚举已经知道了。方法很简单:
public void generate(Multiplication expression) {
evaluateArthimeticComponents(expression);
Type type = expression.getType();
methodVisitor.visitInsn(type.getMultiplyOpcode());
}
下面的Enkel类:
main(string[] args) {
var stringVar = "str"
var booleanVar = true
var integerVar = 2745 + 33
var doubleVar = 2343.05
var sumOfDoubleVars = 23.0 + doubleVar
}
编译后生成的字节码如下:
kuba@kuba-laptop:~/repos/Enkel-JVM-language$ javap -c AllPrimitiveTypes.class
public 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
}
如你所见,指令的操作码与与语句/表达式预期的类型相对应。