返回值
返回语句的定义我们目前基本和java
设定的一样,即:
- 可以返回某个引用,如一个变量
- 可以返回某个值,如一个数字
- 函数也可以不进行返回值得操作,但是要求函数本身是
Void
函数
语法的定义非常简单
returnStatement: RETURN expression;
expression : variableReference #VarReference | value #ValueExpr ;
返回语句的定义也很简单,它只维护一个表达式,这个表达式可以是一个值,也可以是一个变量的引用
@Datapublic 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(); }}