返回值

返回语句的定义我们目前基本和java 设定的一样,即:

  • 可以返回某个引用,如一个变量
  • 可以返回某个值,如一个数字
  • 函数也可以不进行返回值得操作,但是要求函数本身是Void 函数

语法的定义非常简单

returnStatement: RETURN expression;
expression : variableReference #VarReference
| value #ValueExpr
;

返回语句的定义也很简单,它只维护一个表达式,这个表达式可以是一个值,也可以是一个变量的引用

@Data
public class ReturnStatement implements Statement {
Expression expression;
}

主要还是在字节码的生成这里,目前是将其分为了两个部分,一个是变量引用方式的处理,一个是值的处理

public class ReturnStatementGenerator extends AbstractByteGenerator {
private final MethodVisitor methodVisitor;
public ReturnStatementGenerator(MethodVisitor methodVisitor) {
this.methodVisitor = methodVisitor;
}
public void generate(ReturnStatement returnStatement) {
Expression expression = returnStatement.getExpression();
if(expression instanceof LocalVariableReference) {
final Type type = expression.getType();
final int id = Scope.getLocalVariableIndex(((LocalVariableReference)expression).getVariable().getName());
if (type == Type.INT) {
methodVisitor.visitVarInsn(ILOAD, id);
methodVisitor.visitInsn(IRETURN);
} else if (type == Type.STRING) {
methodVisitor.visitVarInsn(ALOAD, id);
methodVisitor.visitInsn(ARETURN);
}
}
if(expression instanceof Value) {
String value = ((Value) expression).getValue();
final Type type = expression.getType();
if(type == Type.INT) {
int val = Integer.parseInt(value);
methodVisitor.visitIntInsn(SIPUSH,val);
methodVisitor.visitInsn(IRETURN);
} else if(type == Type.STRING) {
methodVisitor.visitLdcInsn(value);
methodVisitor.visitInsn(ARETURN);
}
}
}
}

另外因为方法可能没有返回值,所以在方法的字节码生成中,还需要额外的补充一个判断

public class MethodGenerator extends AbstractByteGenerator {
...
/**
* 生成字节码
* 维护的实际是classWriter
* * @param method
*/
public void generate(MethodDeclaration method) {
MethodVisitor mv = classWriter.visitMethod(method.getAccess(), method.getName(), method.getDescriptor(), null, null);
mv.visitCode();
StatementGenerator statementScopeGenerator = new StatementGenerator(mv);
method.getStatements().stream().forEach(stmt ->
statementScopeGenerator.generate(stmt)
);
// 如果没有返回语句
if (!(method.getStatements().get(method.getStatements().size() - 1) instanceof ReturnStatement)) {
mv.visitInsn(RETURN);
}
mv.visitMaxs(-1, -1);
mv.visitEnd();
}
}