Package wyvern.targets.java

Source Code of wyvern.targets.java.GenerationContext

package wyvern.targets.java;

import org.objectweb.asm.signature.SignatureWriter;
import org.javatuples.*;
import org.junit.Test;
import org.objectweb.asm.signature.SignatureVisitor;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import sun.reflect.generics.tree.ClassSignature;
import wyvern.tools.types.extensions.*;
import wyvern.tools.types.extensions.Tuple;
import wyvern.tools.types.extensions.Unit;

import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.IntFunction;
import java.util.function.Supplier;

public class GenerationContext {
  private HashMap<String, byte[]> classes = new HashMap<>();
  private HashMap<wyvern.tools.types.Type, String> names = new HashMap<>();
  private HashSet<String> takenNames = new HashSet<>();
  public void getSignature(wyvern.tools.types.Type type, SignatureVisitor sig, boolean baseAllowed) {
    if (type instanceof Arrow) {
      wyvern.tools.types.Type argument = ((Arrow) type).getArgument();
      if (argument instanceof Unit) {
        sig.visitClassType(Type.getInternalName(Supplier.class));
        SignatureVisitor sw2 = sig.visitTypeArgument('=');
        getSignature(((Arrow) type).getResult(), sw2, true);
        sw2.visitEnd();
        return;
      }
      if (argument instanceof Tuple) {
        wyvern.tools.types.Type[] types = ((Tuple) argument).getTypeArray();
        if (types.length == 2) {
          sig.visitClassType(Type.getInternalName(BiFunction.class));
          SignatureVisitor sw2 = sig.visitTypeArgument('=');
          getSignature(types[0], sw2, false);
          getSignature(types[1], sw2, false);
          getSignature(((Arrow) type).getResult(), sw2, false);
          sw2.visitEnd();
          return;
        }
      }
      if (argument instanceof Int) {
        sig.visitClassType(Type.getInternalName(IntFunction.class));
        SignatureVisitor sw2 = sig.visitTypeArgument('=');
        getSignature(((Arrow) type).getResult(), sw2, true);
        sw2.visitEnd();
        return;
      }
      sig.visitClassType(Type.getInternalName(Function.class));
      SignatureVisitor sw2 = sig.visitTypeArgument('=');
      getSignature(argument, sw2, false);
      getSignature(((Arrow) type).getResult(), sw2, false);
      sw2.visitEnd();
    } else if (type instanceof Tuple) {
      Class genTgt = null;
      switch (((Tuple) type).getTypeArray().length) {
        case 0: genTgt = null; break;
        case 1: genTgt = null; break;
        case 2: genTgt = Pair.class; break;
        case 3: genTgt = Triplet.class; break;
        case 4: genTgt = Quartet.class; break;
        case 5: genTgt = Quintet.class; break;
        case 6: genTgt = Sextet.class; break;
        case 7: genTgt = Septet.class; break;
        case 8: genTgt = Octet.class; break;
        case 9: genTgt = Ennead.class; break;
        case 10: genTgt = Decade.class; break;
        default: throw new RuntimeException();
      }
      sig.visitClassType(Type.getInternalName(genTgt));
      SignatureVisitor sw2 = sig.visitTypeArgument('=');
      for (wyvern.tools.types.Type tpe : ((Tuple) type).getTypeArray())
        getSignature(tpe, sw2, false);
      sw2.visitEnd();
      return;
    } else {
      Type rType = getType(type, baseAllowed);
      if (rType.getClassName() != null) {
        sig.visitClassType(rType.getClassName());
        sig.visitEnd();
      }
      sig.visitBaseType(rType.getDescriptor().charAt(0));
    }
  }

  @Test
  public void testSig1() {
    SignatureWriter sw = new SignatureWriter();
    wyvern.tools.types.Type toGen = new Arrow(new Tuple(new wyvern.tools.types.Type[] {Int.getInstance(), Int.getInstance(), Bool.getInstance()}), Bool.getInstance());
    getSignature(toGen, sw, true);
    String res = sw.toString();
    ClassSignature mts = sun.reflect.generics.parser.SignatureParser.make().parseClassSig(res);
  }

  public Type getType(wyvern.tools.types.Type type, boolean baseAllowed) {
    if (type instanceof Bool) {
      if (baseAllowed)
        return Type.getType(Boolean.TYPE);
      else
        return Type.getType(Boolean.class);
    } else if (type instanceof Int) {
      if (baseAllowed)
        return Type.getType(Integer.TYPE);
      else
        return Type.getType(Integer.class);
    } else if (type instanceof Str) {
      return Type.getType(String.class);
    } else if (type instanceof ClassType) {
      return Type.getType(names.get(type));
    }

    return null;
  }

  public Type[] getTypes(wyvern.tools.types.Type type) {
    if (type instanceof Tuple) {
      return Arrays.asList(((Tuple) type).getTypeArray()).stream().map(tpe -> getType(tpe,false)).toArray(Type[]::new);
    }
    if (type instanceof Unit) {
      return new Type[0];
    }
    return new Type[] {getType(type,false)};
  }

  public ClassVisitor newClass(String rootClassname) {
    if (classes.containsKey(rootClassname))
      throw new RuntimeException();

    final ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);

    return new ClassVisitor(Opcodes.V1_7, writer) {
      @Override
      public void visitEnd() {
        super.visitEnd();
        classes.put(rootClassname, writer.toByteArray());
      }
    };
  }

  public void registerTypename(wyvern.tools.types.Type inT, String wantName) {
    if (takenNames.contains(wantName)) {
      int step = 0;
      while (takenNames.contains("L$"+step+"$"+wantName+";"))
        step++;
      names.put(inT, "L$"+step+"$"+wantName+";");
    }
    names.put(inT, wantName);
  }
}
TOP

Related Classes of wyvern.targets.java.GenerationContext

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.