generateBytecode von Class gibt eine Menge an ByteCodeResults zurück, wird benötigt um zusätzliche Klassen anzulegen

This commit is contained in:
Enrico Schrödter 2015-10-16 10:39:34 +02:00
parent 3a18088801
commit 1a07c186a6
11 changed files with 61 additions and 383 deletions

View File

@ -860,10 +860,10 @@ public class MyCompiler implements MyCompilerAPI
}
@Override
public Menge<ByteCodeResult> generateBytecode(TypeinferenceResultSet typeinferenceResult) {
public Menge<Menge<ByteCodeResult>> generateBytecode(TypeinferenceResultSet typeinferenceResult) {
//SourceFile parsedFile = this.m_AbstractSyntaxTree.firstElement();
//Class parsedClass = parsedFile.KlassenVektor.firstElement();
Menge<ByteCodeResult> ret = new Menge<>();
Menge<Menge<ByteCodeResult>> ret = new Menge<>();
for(SourceFile sf : this.m_AbstractSyntaxTree){
ret.addAll(sf.generateBytecode(typeinferenceResult));
}

View File

@ -127,6 +127,6 @@ public interface MyCompilerAPI
* Dafür müssen die Schritte Parsen und typeReconstruction ausgeführt werden.
* @return
*/
public Menge<ByteCodeResult> generateBytecode(TypeinferenceResultSet rs);
public Menge<Menge<ByteCodeResult>> generateBytecode(TypeinferenceResultSet rs);
}
// ino.end

View File

@ -15,7 +15,6 @@ import org.apache.commons.bcel6.generic.InstructionHandle;
import org.apache.commons.bcel6.generic.InstructionList;
import org.apache.commons.bcel6.generic.MethodGen;
import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.logger.Logger;
import de.dhbwstuttgart.logger.Section;
import de.dhbwstuttgart.logger.SectionLogger;
@ -75,11 +74,13 @@ public class Class extends GTVDeclarationContext implements AClassOrInterface, I
* @param resultSet - Fehlende Typen im Syntaxbaum werden nach diesem ResultSet aufgelöst
* @return
*/
public ByteCodeResult genByteCode(TypeinferenceResultSet resultSet) {
public Menge<ByteCodeResult> genByteCode(TypeinferenceResultSet resultSet) {
InstructionFactory _factory;
DHBWConstantPoolGen _cp;
ClassGenerator _cg;
Menge<ByteCodeResult> results = new Menge<ByteCodeResult>();
SectionLogger logger = Logger.getSectionLogger(this.getClass().getName(), Section.CODEGEN);
logger.debug("Test");
@ -112,10 +113,14 @@ public class Class extends GTVDeclarationContext implements AClassOrInterface, I
}
ByteCodeResult code = new ByteCodeResult(_cg);
return code;
results.add(code);
results.addAll(getGenericClasses(_cg));
return results;
}
private Menge<Type> superif = new Menge<Type>();
private Menge<Type> superif = new Menge<Type>();
public UsedId getPackageName()
{
@ -593,112 +598,6 @@ public class Class extends GTVDeclarationContext implements AClassOrInterface, I
{
return this.parahash;
}
// ino.end
/*static void string_rec(Hashtable ht){
String record="";
boolean isError=false;
record=record.concat("[");
for(Enumeration e=ht.elements(),k=ht.keys();e.hasMoreElements();){
String s = (String)k.nextElement();
Object o = e.nextElement();
record=record.concat(" "+s);
if(o instanceof Type){
record=record.concat(" = "+((Type)o).getName());
} else if(o instanceof Hashtable){
record=record.concat("= ");
string_rec((Hashtable)o);
if(e.hasMoreElements())
record=record.concat(", ");
} else if(o instanceof String){
record=record.concat(" = "+o);
if(e.hasMoreElements())
record=record.concat(", ");
}
else {
record=("[FEHLER: string_rec: unbekannter Typ!!!!!!");
isError=true;
}
}
record=record.concat("]");
if(isError){
parserlog.error(record);
}else{
parserlog.debug(record);
}
}*/
/*static void string_rec(Menge v){
String record=("{");
for(Enumeration e=v.elements();e.hasMoreElements();){
Type t = (Type)e.nextElement();
record=record.concat(" "+t.getName());
if(e.hasMoreElements())
record=record.concat(",");
}
record=record.concat("}");
parserlog.debug(record);
}*/
/*static void string_rec(String st, Hashtable ht){
String record=(st);
boolean isError=false;
record=record.concat("[");
for(Enumeration e=ht.elements(),k=ht.keys();e.hasMoreElements();){
String s = (String)k.nextElement();
Object o = e.nextElement();
record=record.concat(" "+s);
if(o instanceof Type){
record=record.concat(" = "+((Type)o).getName());
}
else if(o instanceof Hashtable){
record=record.concat("= ");
string_rec((Hashtable)o);
if(e.hasMoreElements())
record=record.concat(", ");
}
else if(o instanceof String){
record=record.concat(" = "+o);
if(e.hasMoreElements())
record=record.concat(", ");
}
else {
record=("[FEHLER: string_rec: unbekannter Typ!!!!!! " +o);
isError = true;
}
}
record=record.concat("]");
if(isError){
parserlog.error(record);
}else{
parserlog.debug(record);
}
}*/
/*static void string_rec(String st,Menge v)
{
String record=(st);
record=record.concat("{");
for(Enumeration e=v.elements();e.hasMoreElements();)
{
Type t = (Type)e.nextElement();
record=record.concat(" "+t.getName());
if(e.hasMoreElements())
{
record=record.concat(", ");
}
}
record=record.concat("}");
parserlog.debug(record);
}*/
/////////////////////////////////////////////////////////////////////////
// TypeReconstructionAlgorithmus
@ -771,165 +670,7 @@ public class Class extends GTVDeclarationContext implements AClassOrInterface, I
typinferenzLog.debug("Erstellte Constraints: "+oderConstraints, Section.TYPEINFERENCE);
return oderConstraints;
/*
CReconstructionTupleSet retTupleSet = this.TRStart(methodList, V, V_fields_methods, supportData);
inferencelog.debug("Bin aus TRStart() zur�ck in TRProg().");
//////////////////////////////
// Neu Ergebnismenge A aller
// Typannahmen erzeugen:
//////////////////////////////
inferencelog.debug("Erstelle Ergebnismenge...");
Menge<CTypeReconstructionResult> newA = new Menge<CTypeReconstructionResult>();
// Alle bisherigen ¯Â¿Â½glichkeiten an Typkombinationen durchgehen:
Menge<CTypeReconstructionResult> oldA = supportData.getA();
for(int i=0; i<oldA.size(); i++){
CTypeReconstructionResult oneReconResult = oldA.elementAt(i);
// Und mit den neuen ¯Â¿Â½glichen Typkombinationen vereinigen:
Iterator<CReconstructionTuple> retTupleIt = retTupleSet.getIterator();
while(retTupleIt.hasNext()){
CReconstructionTuple possibleTuple = retTupleIt.next();
this.clear(possibleTuple.getAssumSet(), rememberLocals);
// Neue Typinformationen mit alten Typinformationen vereinigen:
CTypeReconstructionResult newReconResult = oneReconResult.shallowCopy();
newReconResult.addDataFromTupel(possibleTuple);
//PL 05-08-02 eingefuegt
//Fuegt Klassen und GenericTypeVars zu A hinzu
newReconResult.addClassName(this.getName());
Menge<GenericTypeVar> genericsList = new Menge<GenericTypeVar>();
for(int ii =0; ii<this.get_ParaList().size(); ii++){
Type para = (Type)this.get_ParaList().elementAt(ii);
if(para instanceof GenericTypeVar){
genericsList.addElement((GenericTypeVar)para);
}
}
newReconResult.addGenericTypeVars(this.getName(), genericsList);
//Hinzuf�gen:
newA.addElement(newReconResult);
}
}
return newA;
*/
}
// ino.end
/**
* @return Eine Liste mit allen Methoden dieser Klasse
private Menge<Method> getMethodList() {
if(this.methodList != null) return this.methodList;
//TODO: UnnÃtige Berechnungen im folgenden Code rauskürzen:
//////////////////////////////
// Die Eingabedaten bauen:
//////////////////////////////
inferencelog.debug("Baue Eingabedaten...");
TypeAssumptions V_fields_methods = new TypeAssumptions(this.getName());
Menge<Method> methodList = new Menge<Method>();
Menge<CTypeAssumptionSet> V = new Menge<CTypeAssumptionSet>();
Menge<CTypeAssumption> rememberLocals = new Menge<CTypeAssumption>();
//////////////////////////////
// Alle Felder durchgehen:
// Zuerst alle Attribute, dann Methoden
// ge�ndert: hoth 06.04.2006
//////////////////////////////
for(Field field : this.getFields())
{
//////////////////////////////
// Attribut:
//////////////////////////////
}
for(Field field : this.getFields())
{
//////////////////////////////
// Methode:
//////////////////////////////
if(field instanceof Method){
Method method = (Method)field;
//if(method.get_Method_Name().equals(this.getName()) && ((method.getReturnType().equals(new mycompiler.mytype.Void(0))) || method.getReturnType() instanceof TypePlaceholder)){
if(method.get_Method_Name().equals(this.getName()) ){
method.set_Method_Name("<init>");
}
//hoth: 06.04.2006
//durchlaufe Block und suche nach Objektvariablen fuer Offset-Markierung
Iterator<CTypeAssumption> fieldVarIterator = V_fields_methods.iterator();
while (fieldVarIterator.hasNext())
{
//Wenn ObjektVariable
CTypeAssumption dieAssum = fieldVarIterator.next();
if(dieAssum instanceof CInstVarTypeAssumption)
{
Class.isFirstLocalVarDecl=false;
if(method.get_Block() != null)
method.get_Block().addOffsetsToAssumption(dieAssum,dieAssum.getIdentifier(),true);
}
}
methodList.addElement(method);
// ¯Â¿Â½r V_fields_methods:
CMethodTypeAssumption methodAssum = new CMethodTypeAssumption(this.getType(), method.get_Method_Name(), method.getReturnType(), method.getParameterCount(),method.getLineNumber(),method.getOffset(),new Menge<Integer>(),method.getGenericMethodParameters()); // Typannahme bauen...
// Methode in V_Fields_methods ablegen
// Dabei wird die OverloadedMethodID ermittelt !!
// => Method setzenuct
V_fields_methods.add(methodAssum);
method.setOverloadedID(methodAssum.getHashSetKey().getOverloadedMethodID());
// ¯Â¿Â½r die V_i:
CTypeAssumptionSet localAssum = new CTypeAssumptionSet();
// Bauen...
ParameterList parameterList = method.getParameterList();
if(parameterList!=null){
for(int i=0; i<parameterList.sc_get_Formalparalist().size(); i++){
FormalParameter para = parameterList.sc_get_Formalparalist().elementAt(i);
// ¯Â¿Â½r V_fields_methods:
CParaTypeAssumption paraAssum = new CParaTypeAssumption(this.getName(), method.get_Method_Name(), method.getParameterCount(), method.getOverloadedID(),para.getIdentifier(), para.getType(), para.getLineNumber(),para.getOffset(),new Menge<Integer>());
//fuege Offsets fuer Parameter hinzu, hoth: 06.04.2006
Class.isFirstLocalVarDecl=false;
if(method.get_Block() != null)
method.get_Block().addOffsetsToAssumption(paraAssum,paraAssum.getIdentifier(),true);
methodAssum.addParaAssumption(paraAssum);
// ¯Â¿Â½r die V_i:
CLocalVarTypeAssumption varAssum = new CLocalVarTypeAssumption(this.getName(), method.get_Method_Name(), method.getParameterCount(), method.getOverloadedID(),"1", para.getIdentifier(),para.getType(), para.getLineNumber(),para.getOffset(),new Menge<Integer>());
localAssum.addElement(varAssum);
rememberLocals.addElement(varAssum);
}
}
// ...und hinzuf�gen:
V.addElement(localAssum);
}
}
this.methodList = methodList;
return methodList;
}
*/
/**
* Ermittelt alle privaten Felder und Methoden der Klasse und Erstellt eine Assumption ¼r diese.
@ -957,49 +698,8 @@ public class Class extends GTVDeclarationContext implements AClassOrInterface, I
this.typeAssumptions = assumptions; //Diese ¼ssen anschließend nicht wieder generiert werden.
return assumptions;
}
/*
public ConstraintsSet TYPE(Menge<Method> methodList, Menge<Expr> fielddeclarationList, TypeAssumptions assumptions){
ConstraintsSet ret = new ConstraintsSet();
// Die Felddeklarationen werden zu den Assumptions hinzugefügt und gelten danach ¼r jede Methode.
//TypeAssumptions assumptionsPlusFieldAssumptions = new TypeAssumptions(assumptions);
for(Expr expr : fielddeclarationList){
//ret.add(expr.TYPEStmt(assumptionsPlusFieldAssumptions));
ret.add(expr.TYPEStmt(assumptions));
}
for(Method methode : methodList){
//ret.add(methode.TYPE(assumptionsPlusFieldAssumptions));
ret.add(methode.TYPE(assumptions));
}
return ret;
}
*/
}
// ino.method.RetType.23119.defdescription type=javadoc
/**
* Liefert den berechneten ¯Â¿Â½ckgabetyp ¯Â¿Â½r die �bergebene Methode zur�ck.<br/>
* (siehe Algorithmus RetType, Martin Pl�micke)
* <br/>Author: ¯Â¿Â½rg ¯Â¿Â½uerle
* @param me
* @param V
* @return
// ino.end
// ino.method.RetType.23119.definition
private Type RetType(Method me, CTypeAssumptionSet V)
// ino.end
// ino.method.RetType.23119.body
{
CTypeAssumption assum = V.getElement(new CMethodKey(this.getName(), me.get_Method_Name(), me.getParameterCount(),me.getOverloadedID()));
if(assum instanceof CMethodTypeAssumption){
return ((CMethodTypeAssumption)assum).getAssumedType();
}
else return null;
}
// ino.end
*/
// ino.method.toString.23125.defdescription type=javadoc
/**
* <br/>Author: Martin Pl�micke
@ -1037,48 +737,8 @@ public class Class extends GTVDeclarationContext implements AClassOrInterface, I
for(Field f : this.getFields()){
//f.wandleRefTypeAttributes2GenericAttributes(paralist);
}
/*
Menge fieldsAndMethods=this.getFields();
// Alle Methoden und Instanzvariablen durchgehen
for(int i=0;i<fieldsAndMethods.size();i++){
// Ist es eine Methode?
if(fieldsAndMethods.get(i) instanceof Method){
Method method=(Method)fieldsAndMethods.get(i);
method.wandleRefTypeAttributes2GenericAttributes(paralist);
}// Ist es eine InstanzVariable?
*//*
else if(fieldsAndMethods.get(i) instanceof InstVarDecl){
InstVarDecl instVar=(InstVarDecl)fieldsAndMethods.get(i);
Type type=instVar.getType();
// Nur wenn es sich um ein RefType-Field handelt
if(type instanceof RefType){
GenericTypeVar pendant=ClassHelper.findGenericType((RefType)type,paralist,null);
if(pendant!=null){ //Wenn generisch, dann modifizieren
instVar.setType(pendant);
}
}
}
}*/
}
// ino.end
// private void removeOldLocalVars(CTypeAssumptionSet V_i, CTypeAssumptionSet V_last){
// Enumeration<IHashSetKey> enumer = V_last.getHashtable().keys();
// while(enumer.hasMoreElements()){
// CTypeAssumption currentAssum = V_last.getElement(enumer.nextElement());
// if(currentAssum instanceof CLocalVarTypeAssumption){
// V_i.removeElement(currentAssum);
// }
// }
//
// }
// ino.method.getSimpleName.23140.defdescription type=javadoc
/**
* HOTI
* Liefert bei Klassen die fullyQualified angegeben wurden
@ -1115,18 +775,6 @@ public class Class extends GTVDeclarationContext implements AClassOrInterface, I
*/
public String printJavaCode(TypeinferenceResultSet reconstructionResult){
JavaCodeResult ret = new JavaCodeResult("class ");
//Generiere JavaCode der extends-Typen:
/*
String containedTypesJavaCode = "";
for(Type containedType : containedTypes){
containedTypesJavaCode += containedType.printJavaCode(resultSet)+ ", ";
}
if(containedTypesJavaCode.length()>1)containedTypesJavaCode = containedTypesJavaCode.substring(0, containedTypesJavaCode.length() -2);
*/
JavaCodeResult classBodyCode = new JavaCodeResult();
if(this.modifiers!=null)classBodyCode.attach(this.modifiers.printJavaCode(reconstructionResult.getUnifiedConstraints())).attach(" ");
@ -1382,5 +1030,22 @@ public class Class extends GTVDeclarationContext implements AClassOrInterface, I
public boolean isInterface(){
return false;
}
private Collection<? extends ByteCodeResult> getGenericClasses(ClassGenerator _cg) {
Collection<ByteCodeResult> results = new Menge<>();
//Super Klasse
String name = "java/util/Vectorjava/lang/String"; //getParentClass().getType().getBytecodeSignature(_cg);
Type superClass = new Class("java/util/Vector",-1).getType();
_cg = new ClassGenerator(name, superClass, name + ".java", Constants.ACC_PUBLIC , new String[] { }, new TypeinferenceResultSet(null, null, null));
ByteCodeResult code = new ByteCodeResult(_cg);
results.add(code);
return results;
}
}
// ino.end

View File

@ -1834,8 +1834,8 @@ public class SourceFile
* Bisher wird nur der Bytecode der Klassen generiert. Nicht der Interfaces.
* @return
*/
public Collection<? extends ByteCodeResult> generateBytecode(TypeinferenceResultSet rs) {
Menge<ByteCodeResult> ret = new Menge<>();
public Menge<Menge<ByteCodeResult>> generateBytecode(TypeinferenceResultSet rs) {
Menge<Menge<ByteCodeResult>> ret = new Menge<>();
for(Class cl : this.KlassenVektor){
ret.add(cl.genByteCode(rs));
}

View File

@ -814,11 +814,12 @@ public class RefType extends ObjectType implements IMatchable
}
public org.apache.commons.bcel6.generic.Type getBytecodeType(ClassGenerator cg) {
return new org.apache.commons.bcel6.generic.ObjectType(this.getBytecodeSignature(cg));
return new org.apache.commons.bcel6.generic.ObjectType(this.get_Name());
}
@Override
public String getBytecodeSignature(ClassGenerator cg) {
/*
//Bsp.: Ljava/util/Vector<Ljava/lang/String;>;
StringBuilder sb = new StringBuilder();
@ -826,12 +827,14 @@ public class RefType extends ObjectType implements IMatchable
if(parameter != null){
for(Type type: parameter){
sb.append("%");
sb.append(""); //TODO: einen geeignete Delemiter suchen
sb.append(type.getBytecodeSignature(cg));
}
}
/*
return sb.toString();
*/
String paramString = "";
if(this.parameter != null && this.parameter.size()>0){
paramString+="<";
@ -847,9 +850,6 @@ public class RefType extends ObjectType implements IMatchable
String typeSignature = this.getBytecodeType(cg).getSignature();
typeSignature = typeSignature.substring(0, typeSignature.length()-1);
return typeSignature+paramString+";";
*/
return sb.toString();
}
}

View File

@ -119,7 +119,7 @@ public class TypeinferenceResultSet
* Dabei wird die codegen-Methode der inferierten Klasse mit diesem ResultSet aufgerufen.
*/
public ByteCodeResult codegen(){
ByteCodeResult res = this.ownerOfResultSet.genByteCode(this);
ByteCodeResult res = this.ownerOfResultSet.genByteCode(this).firstElement();
return res;
}

View File

@ -16,7 +16,7 @@ import org.junit.Test;
public abstract class BytecodeTest extends TestCase{
public String rootDirectory = System.getProperty("user.dir")+"/test/bytecode/";
public String testFile;
public String outputFile;
public String outputDirectory;
protected String testName;
@ -26,9 +26,9 @@ public abstract class BytecodeTest extends TestCase{
if(testName != null){
testFile = testName+".jav";
outputFile = testName+".class";
outputDirectory = "";
SingleClassTester.compileToBytecode(rootDirectory+testFile, rootDirectory+outputFile);
SingleClassTester.compileToBytecode(rootDirectory+testFile, rootDirectory+outputDirectory);
}else{
throw new RuntimeException("rootDirectory, testFile or outputFile is null.");
}

View File

@ -3,6 +3,8 @@ package bytecode;
import java.io.File;
import java.io.IOException;
import org.apache.commons.bcel6.classfile.JavaClass;
import com.google.common.io.Files;
import junit.framework.TestCase;
@ -18,20 +20,28 @@ import de.dhbwstuttgart.typeinference.Menge;
public class SingleClassTester {
public static void compileToBytecode(String inputFile, String outputFile){
public static void compileToBytecode(String inputFile, String outputDirectory){
LoggerConfiguration logConfig = new LoggerConfiguration().setOutput(Section.PARSER, System.out);
MyCompilerAPI compiler = MyCompiler.getAPI(logConfig);
try {
compiler.parse(new File(inputFile));
Menge<ByteCodeResult> bytecode = compiler.generateBytecode(compiler.typeReconstruction().firstElement());
Menge<Menge<ByteCodeResult>> bytecode = compiler.generateBytecode(compiler.typeReconstruction().firstElement());
//System.out.println(bytecode);
bytecode.firstElement().getByteCode().getJavaClass().dump(new File(outputFile));
for(ByteCodeResult result: bytecode.firstElement()){
JavaClass javaClass = result.getByteCode().getJavaClass();
Logger.getLogger("SingleClassTester").error(result.getByteCode().getJavaClass().toString(), Section.CODEGEN);
javaClass.dump(new File(outputDirectory+javaClass.getClassName()+".class"));
}
} catch (IOException | yyException e) {
Logger.getLogger("SingleClassTester").error(e.toString(), Section.CODEGEN);
e.printStackTrace();
TestCase.fail();
}finally{
writeLog(outputFile+".log");
writeLog(outputDirectory+".log");
}
}

View File

@ -1,4 +1,5 @@
import java.util.Vector;
class ExtendsVector extends Vector{
}

View File

@ -1,4 +1,4 @@
import java.util.Stack;
import java.util.Vector;
class TypedVector{
public void method(Vector<String> v) {

View File

@ -9,6 +9,8 @@ import java.util.Vector;
import org.junit.Test;
import bytecode.BytecodeTest;
import de.dhbwstuttgart.logger.Logger;
import de.dhbwstuttgart.logger.Section;
public class TypedVectorTest extends BytecodeTest{
@Override
@ -32,7 +34,7 @@ public class TypedVectorTest extends BytecodeTest{
method.invoke(obj, stringVector);
assertTrue(true);
}catch(Exception e){
e.printStackTrace();
Logger.getLogger("SingleClassTester").error(e.toString(), Section.CODEGEN);
fail();
}
}