package me.august.lumen.compile.parser.ast; import me.august.lumen.common.ModifierSet; import me.august.lumen.compile.analyze.ASTVisitor; import me.august.lumen.compile.analyze.VisitorConsumer; import me.august.lumen.compile.codegen.BuildContext; import me.august.lumen.compile.codegen.ClassCodeGen; import me.august.lumen.compile.parser.ast.stmt.Body; import me.august.lumen.compile.resolve.type.UnresolvedType; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; import java.util.List; public class MethodNode extends Typed implements VisitorConsumer, ClassCodeGen { private String name; private ModifierSet modifiers; private List<Parameter> parameters; private Body body; public MethodNode(String name, UnresolvedType returnType, List<Parameter> parameters, ModifierSet modifiers) { super(returnType); this.name = name; this.parameters = parameters; this.modifiers = modifiers; } @Override public void accept(ASTVisitor visitor) { visitor.visitMethod(this); body.accept(visitor); visitor.visitMethodEnd(this); } @Override public void generate(ClassVisitor visitor, BuildContext context) { Type returnType = getResolvedType(); Type[] paramTypes = parameters.stream().map(Parameter::getResolvedType).toArray(Type[]::new); MethodVisitor method = visitor.visitMethod( modifiers.getValue(), name, // access modifier Type.getMethodType(returnType, paramTypes).getDescriptor(), // method descriptor null, null // signature (generics), exceptions ); method.visitCode(); body.generate(method, context); if (getResolvedType().getSort() == Type.VOID) method.visitInsn(Opcodes.RETURN); // TODO *actually* compute maxs method.visitMaxs(10, 10); method.visitEnd(); } public boolean isStatic() { return modifiers.isStatic(); } @Override public void setResolvedType(Type resolvedType) { super.setResolvedType(resolvedType == null ? Type.VOID_TYPE : resolvedType); } public List<Parameter> getParameters() { return parameters; } public void setParameters(List<Parameter> parameters) { this.parameters = parameters; } public String getName() { return name; } public void setName(String name) { this.name = name; } public ModifierSet getModifiers() { return modifiers; } public void setModifiers(ModifierSet modifiers) { this.modifiers = modifiers; } public Body getBody() { return body; } public void setBody(Body body) { this.body = body; } public boolean hasBody() { return body != null; } @Override public String toString() { return super.toString(); } }