Package wyvern.targets.java

Source Code of wyvern.targets.java.ClassTransformer

package wyvern.targets.java;

import org.objectweb.asm.*;
import static org.objectweb.asm.Opcodes.*;

import org.objectweb.asm.commons.GeneratorAdapter;
import wyvern.targets.Common.wyvernIL.IL.Def.*;
import wyvern.targets.Common.wyvernIL.IL.visitor.DefVisitor;
import wyvern.targets.java.annotations.Val;
import wyvern.targets.java.bindings.FieldBinding;

import java.util.Arrays;

public class ClassTransformer implements DefVisitor {
  private GenerationContext ctx;
  private ClassDef classDef;
  private ClassVisitor output;
  private Type self;
  public String getNameFor(Definition def) {
    String name = getName(def);
    String[] found = classDef.getDefinitions().stream().filter(defin->getName(defin).equals(name)).toArray(String[]::new);
    String postfix = (found[found.length - 1].equals(def))?"" : "$" + Arrays.asList(found).indexOf(def);
    return name + postfix;
  }

  private String getName(Definition defin) {
    if (defin instanceof VarDef)
      return ((VarDef)defin).getName();
    if (defin instanceof ValDef)
      return ((ValDef)defin).getName();
    if (defin instanceof Def)
      return ((Def)defin).getName();
    return "";
  }
  public ClassTransformer(GenerationContext ctx, ClassDef classDef) {
    this.ctx = ctx;
    this.classDef = classDef;
    self = ctx.getType(classDef.getType(), true);
    output = ctx.newClass(classDef.getName());
    output.visit(V1_8, ACC_PUBLIC, classDef.getName(), null, Type.getInternalName(Object.class), new String[]{});
  }

  @Override
  public Object visit(VarDef varDef) {
    Type type = ctx.getType(varDef.getType(), true);
    new FieldBinding(varDef.getName(), type);
    output.visitField(ACC_PUBLIC, varDef.getName(), type.getDescriptor(), null, null);
    return null;
  }

  @Override
  public Object visit(ValDef valDef) {
    Type type = ctx.getType(valDef.getType(), true);
    new FieldBinding(valDef.getName(), type);
    output.visitField(ACC_PRIVATE, valDef.getName(), type.getDescriptor(), null, null);

    String name = "get" + valDef.getName();
    String descriptor = Type.getMethodType(type).getDescriptor();
    MethodVisitor mv = output.visitMethod(ACC_PUBLIC, name, descriptor, null, new String[]{});

    //Generate the val annotation for the getter
    AnnotationVisitor av = mv.visitAnnotation(Type.getDescriptor(Val.class), true);
    av.visit("name", valDef.getName());
    av.visitEnd();

    //Generate the body for the getter
    GeneratorAdapter generator = new GeneratorAdapter(mv, ACC_PUBLIC, name, descriptor);
    generator.loadThis();
    generator.getField(self, valDef.getName(), type);
    generator.returnValue();
    generator.endMethod();

    return null;
  }

  @Override
  public Object visit(Def def) {
    wyvern.tools.types.extensions.Arrow dType = def.getType();
    Type rType = ctx.getType(dType.getResult(), true);

    Type methodType = Type.getMethodType(rType, ctx.getTypes(dType.getArgument()));

    //Externally callable
    MethodVisitor externalFn = output.visitMethod(ACC_PUBLIC, getNameFor(def), methodType.getDescriptor(), null, new String[] {});
    externalFn.visitEnd();


    return null;
  }

  @Override
  public Object visit(TypeDef typeDef) {
    throw new RuntimeException();
  }

  @Override
  public Object visit(ClassDef classDef) {
    throw new RuntimeException();
  }

  @Override
  public Object visit(ImportDef importDef) {
    throw new RuntimeException();
  }

  public void finish() {
    output.visitEnd();
  }
}
TOP

Related Classes of wyvern.targets.java.ClassTransformer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.