forked from JavaTX/JavaCompilerCore
189 lines
6.4 KiB
Java
189 lines
6.4 KiB
Java
package de.dhbwstuttgart.bytecode;
|
|
|
|
import java.util.Arrays;
|
|
import java.util.HashMap;
|
|
import java.util.Iterator;
|
|
import java.util.LinkedList;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Vector;
|
|
|
|
import org.apache.commons.bcel6.classfile.BootstrapMethod;
|
|
import org.apache.commons.bcel6.classfile.BootstrapMethods;
|
|
import org.apache.commons.bcel6.classfile.ConstantPool;
|
|
import org.apache.commons.bcel6.classfile.InnerClass;
|
|
import org.apache.commons.bcel6.classfile.InnerClasses;
|
|
import org.apache.commons.bcel6.classfile.JavaClass;
|
|
import org.apache.commons.bcel6.classfile.Method;
|
|
import org.apache.commons.bcel6.classfile.Signature;
|
|
import org.apache.commons.bcel6.generic.ClassGen;
|
|
import org.apache.commons.bcel6.generic.ConstantPoolGen;
|
|
|
|
import de.dhbwstuttgart.syntaxtree.type.RefType;
|
|
import de.dhbwstuttgart.syntaxtree.type.Type;
|
|
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
|
|
import de.dhbwstuttgart.typeinference.Menge;
|
|
import de.dhbwstuttgart.typeinference.ResultSet;
|
|
import de.dhbwstuttgart.typeinference.TypeinferenceResultSet;
|
|
import de.dhbwstuttgart.typeinference.TypeinferenceResults;
|
|
import de.dhbwstuttgart.typeinference.exceptions.DebugException;
|
|
|
|
public class ClassGenerator extends ClassGen{
|
|
|
|
private DHBWConstantPoolGen cp;
|
|
private DHBWInstructionFactory factory;
|
|
private TypeinferenceResults tiResult;
|
|
private int lambdaMethodeNr = 0;
|
|
private Type superClass;
|
|
|
|
private Menge<TypePlaceholder> usedTPHs = new Menge<>();
|
|
|
|
private Map<String, ClassGenerator> extraClasses = new HashMap<>();
|
|
private List<String> methodsNamesAndTypes = new LinkedList<>();
|
|
|
|
public ClassGenerator(String name, Type superClass, String string, short accessflags, String[] strings, TypeinferenceResults typeinferenceResults) {
|
|
super(name,superClass.get_Name(),string,accessflags,strings, new DHBWConstantPoolGen());
|
|
this.tiResult = typeinferenceResults;
|
|
this.superClass = superClass;
|
|
|
|
cp = (DHBWConstantPoolGen) super.getConstantPool();
|
|
factory = new DHBWInstructionFactory(this, cp);
|
|
this.setMajor(52); //Java 8 Version 52.0
|
|
this.setMinor(0);
|
|
}
|
|
|
|
public DHBWInstructionFactory getInstructionFactory() {
|
|
return factory ;
|
|
}
|
|
|
|
/**
|
|
* Versucht einen Type zu finden von dem dieser TPH ein Subtyp sein muss.
|
|
* @param toTPH
|
|
* @return Es gilt dann "toTPH extends Type"
|
|
*/
|
|
public org.apache.commons.bcel6.generic.Type getNearestUsedType(Type t, Menge<TypePlaceholder> usedTypes){
|
|
if(t == null){
|
|
return this.getInstructionFactory().createObjectType();
|
|
}else if(t instanceof TypePlaceholder){ //Es muss sich in diesem Fall um einen TPH handeln:
|
|
//return getNearestType((TypePlaceholder) t);
|
|
return new TypePlaceholderType((TypePlaceholder) t);
|
|
}else{
|
|
return t.getBytecodeType(this, getTypeinferenceResults().getTypeReconstructions().firstElement());
|
|
}
|
|
}
|
|
public org.apache.commons.bcel6.generic.Type getNearestUsedType(TypePlaceholder toTPH){
|
|
return this.getNearestUsedType(toTPH, null);
|
|
}
|
|
|
|
public String createLambdaMethodName() {
|
|
return "lambda$methode$"+(lambdaMethodeNr++);
|
|
}
|
|
|
|
@Override
|
|
public DHBWConstantPoolGen getConstantPool(){
|
|
return this.cp;
|
|
}
|
|
|
|
@Override
|
|
public void setConstantPool(ConstantPoolGen gen){
|
|
throw new DebugException("Ungültige Operation. ClassGenerator muss ein DHBWConstantPool besitzen");
|
|
}
|
|
|
|
/**
|
|
* Anmerkung: Kann in diesem Zustand nur einmal aufgerufen werden.
|
|
* @param innerClassAttribute
|
|
*/
|
|
public void addInnerClass(InnerClass innerClassAttribute) {
|
|
//TODO: Muss vor dem ausführen von getJavaClass ausgeführt werden. getJavaClass überschreiben!
|
|
int numberOfInnerClasses = 1;
|
|
InnerClass[] innerClasses = new InnerClass[numberOfInnerClasses];
|
|
innerClasses[numberOfInnerClasses-1] = innerClassAttribute;
|
|
int innerClassesUTF8 = this.getConstantPool().addUtf8("InnerClasses");
|
|
this.addAttribute(new InnerClasses(innerClassesUTF8,numberOfInnerClasses*8+2,innerClasses,this.getConstantPool().getConstantPool()));
|
|
}
|
|
|
|
public int addBootstrapMethod(BootstrapMethod bMethod) {
|
|
int numberOfBootstrapMethods = 1;
|
|
int name_index = this.getConstantPool().addUtf8("BootstrapMethods");
|
|
int length = 2 + numberOfBootstrapMethods * 4 + bMethod.getNumBootstrapArguments() * 2;
|
|
BootstrapMethod[] bootstrap_methods = new BootstrapMethod[numberOfBootstrapMethods];
|
|
bootstrap_methods[numberOfBootstrapMethods-1] = bMethod;
|
|
BootstrapMethods bootstrapAttribute = new BootstrapMethods(name_index, length, bootstrap_methods, this.getConstantPool().getConstantPool());
|
|
this.addAttribute(bootstrapAttribute);
|
|
return numberOfBootstrapMethods-1;
|
|
}
|
|
|
|
public void addUsedTPH(TypePlaceholder tph){
|
|
if(! this.getUsedTPH().contains(tph, (a, b)->{
|
|
return a.get_Name().equals(b.get_Name()); //Vergleich auf Namensgleichheit. Was anderes zählt im Bytecode nicht
|
|
}))
|
|
{ //Nur wenn noch nicht vorhanden anfügen:
|
|
this.usedTPHs.add(tph);
|
|
}
|
|
}
|
|
|
|
public Menge<TypePlaceholder> getUsedTPH() {
|
|
return usedTPHs;
|
|
}
|
|
|
|
@Override
|
|
public JavaClass getJavaClass() {
|
|
//Hier werden die letzten Schritte vor der Klassengenerierung ausgeführt:
|
|
|
|
//Signatur setzen:
|
|
String typeParameters = this.generateParameterSignature();
|
|
String superClassSignature = this.superClass.getBytecodeSignature(this, null);
|
|
String classSignature = typeParameters + superClassSignature;
|
|
if(classSignature.length()>0){
|
|
this.addAttribute(new Signature(cp.addUtf8("Signature"),2,cp.addUtf8(classSignature),cp.getConstantPool()));
|
|
}
|
|
|
|
return super.getJavaClass();
|
|
}
|
|
|
|
private String generateParameterSignature(){
|
|
String ret = "";
|
|
if(this.getUsedTPH().size()>0){
|
|
ret += "<";
|
|
Iterator<TypePlaceholder> it = ((Menge<TypePlaceholder>)this.getUsedTPH().clone()).iterator();
|
|
while(it.hasNext()){
|
|
TypePlaceholder tph = it.next();
|
|
//ret += tph.getBytecodeMethodSignature(this);
|
|
//ret += ":";
|
|
ret += tph.getClassSignature(this, getTypeinferenceResults().getTypeReconstructions().firstElement());
|
|
}
|
|
ret += ">";
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
public void addExtraClass(ClassGenerator cg){
|
|
extraClasses.put(cg.getClassName(), cg);
|
|
}
|
|
|
|
public Map<String, ClassGenerator> getExtraClasses() {
|
|
return extraClasses;
|
|
}
|
|
|
|
public TypeinferenceResults getTypeinferenceResults() {
|
|
return tiResult;
|
|
}
|
|
|
|
@Override
|
|
public void addMethod(Method m) {
|
|
String methodNameAndTypes = m.getName()+Arrays.toString(m.getArgumentTypes());
|
|
|
|
if(methodsNamesAndTypes.contains(methodNameAndTypes)){
|
|
return;
|
|
}
|
|
|
|
methodsNamesAndTypes.add(methodNameAndTypes);
|
|
super.addMethod(m);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|