JavaPatternMatching/src/de/dhbwstuttgart/syntaxtree/Class.java
2016-03-31 11:50:53 +02:00

1107 lines
40 KiB
Java
Executable File
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// ino.module.Class.8553.package
package de.dhbwstuttgart.syntaxtree;
// ino.end
// ino.module.Class.8553.import
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import javax.lang.model.element.Modifier;
import org.apache.commons.bcel6.generic.ClassGen;
import org.apache.commons.bcel6.generic.ConstantPoolGen;
import org.apache.commons.bcel6.generic.InstructionFactory;
import org.apache.commons.bcel6.generic.InstructionHandle;
import org.apache.commons.bcel6.generic.InstructionList;
import org.apache.commons.bcel6.generic.MethodGen;
import de.dhbwstuttgart.logger.Logger;
import de.dhbwstuttgart.logger.Section;
import de.dhbwstuttgart.logger.SectionLogger;
import de.dhbwstuttgart.bytecode.ClassGenerator;
import de.dhbwstuttgart.bytecode.DHBWConstantPoolGen;
import de.dhbwstuttgart.bytecode.DHBWInstructionFactory;
import de.dhbwstuttgart.core.AClassOrInterface;
import de.dhbwstuttgart.core.IItemWithOffset;
import de.dhbwstuttgart.parser.JavaClassName;
import de.dhbwstuttgart.syntaxtree.misc.DeclId;
import de.dhbwstuttgart.syntaxtree.misc.UsedId;
import de.dhbwstuttgart.syntaxtree.modifier.Modifiers;
import de.dhbwstuttgart.syntaxtree.modifier.Static;
import de.dhbwstuttgart.syntaxtree.statement.Block;
import de.dhbwstuttgart.syntaxtree.statement.Expr;
import de.dhbwstuttgart.syntaxtree.statement.Statement;
import de.dhbwstuttgart.syntaxtree.statement.SuperCall;
import de.dhbwstuttgart.syntaxtree.type.GenericTypeVar;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.SuperWildcardType;
import de.dhbwstuttgart.syntaxtree.type.Type;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.syntaxtree.type.WildcardType;
import de.dhbwstuttgart.typeinference.*;
import de.dhbwstuttgart.typeinference.assumptions.ClassAssumption;
import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions;
import de.dhbwstuttgart.typeinference.exceptions.DebugException;
import de.dhbwstuttgart.typeinference.exceptions.NotImplementedException;
import de.dhbwstuttgart.typeinference.exceptions.TypeinferenceException;
import de.dhbwstuttgart.typeinference.typedeployment.TypeInsertPoint;
import de.dhbwstuttgart.typeinference.unify.Unify;
import org.apache.commons.bcel6.generic.*;
import org.apache.commons.bcel6.classfile.*;
import org.apache.commons.bcel6.*;
import java.io.*;
// ino.class.Class.23010.declaration
public class Class extends GTVDeclarationContext implements AClassOrInterface, IItemWithOffset, Generic, GenericTypeInsertable
// ino.end
// ino.class.Class.23010.body
{
/**
* Log4j - Loggerinstanzen
*/
protected static Logger inferencelog = Logger.getLogger("inference");
protected static Logger codegenlog = Logger.getLogger("codegen");
protected static Logger parserlog = Logger.getLogger("parser");
protected UsedId pkgName;
protected Modifiers modifiers;
protected String name;
/**
*
* @param resultSet - Fehlende Typen im Syntaxbaum werden nach diesem ResultSet aufgelöst
* @return
*/
public ByteCodeResult genByteCode(TypeinferenceResults typeinferenceResults) {
InstructionFactory _factory;
DHBWConstantPoolGen _cp;
ClassGenerator _cg;
Menge<ByteCodeResult> results = new Menge<ByteCodeResult>();
SectionLogger logger = Logger.getSectionLogger(this.getClass().getName(), Section.CODEGEN);
logger.debug("Test");
if(pkgName != null)throw new NotImplementedException();
short constants = Constants.ACC_PUBLIC; //Per Definition ist jede Methode public
_cg = new ClassGenerator(name, this.getSuperClass(), name + ".java", constants , new String[] { }, typeinferenceResults); //letzter Parameter sind implementierte Interfaces
_cp = _cg.getConstantPool();
_factory = new DHBWInstructionFactory(_cg, _cp);
//Die Felder in Methoden Felder und Konstruktoren aufteilen:
Menge<FieldDeclaration> fieldDeclarations = new Menge<>();
Menge<Constructor> constructors = new Menge<>();
Menge<Method> methods = new Menge<>();
for(Field field : this.fielddecl){
if(field instanceof Constructor)constructors.add((Constructor)field);
if(field instanceof Method && ! (field instanceof Constructor))methods.add((Method)field);
if(field instanceof FieldDeclaration)fieldDeclarations.add((FieldDeclaration)field);
//field.genByteCode(_cg);
}
//Zuerst die Methoden und Felder abarbeiten:
for(Method m : methods){
m.genByteCode(_cg, this);
}
InstructionList fieldInitializations = new InstructionList();
for(FieldDeclaration f : fieldDeclarations){
fieldInitializations.append(f.genByteCode(_cg, typeinferenceResults.getTypeReconstructions().firstElement()));
}
//Die Konstruktoren müssen die Feld initialisierungswerte beinhalten:
for(Constructor c : constructors){
c.genByteCode(_cg, fieldInitializations);
}
return new ByteCodeResult(_cg);
}
private Menge<Type> superif = new Menge<Type>();
public UsedId getPackageName()
{
return pkgName;
}
public void setPackageName(UsedId pkgName)
{
this.pkgName = pkgName;
}
public JavaClassName getName()
{
return new JavaClassName((this.pkgName!=null ? this.pkgName.toString() +"." : "") +this.name);
}
public void setName(String strName)
{
name = strName;
}
public void setModifiers(Modifiers mod)
{
this.modifiers = mod;
}
public Modifiers getModifiers()
{
return this.modifiers;
}
/**
* Liefert die AccessFlags fuer den Bytecode zurueck.
*/
public short getAccessFlags()
{
short ret = 0;
if (modifiers != null) {
ret = modifiers.calculate_access_flags();
}
return ret;
}
public Menge<Type> getSuperInterfaces()
{
return superif;
}
@Override
public void setSuperInterfaces(Menge<Type> superif)
{
this.superif = superif;
}
// ino.attribute.superclassid.23014.decldescription type=line
// private Status status;
// ino.end
// ino.attribute.superclassid.23014.declaration
public UsedId superclassid = (SourceFile.READ_OBJECT_SUPERCLASSES_FROM_JRE?UsedId.createFromQualifiedName("Object",-1):null);
// ino.end
// ino.attribute.class_block.23020.decldescription type=line
// private Class java;
// ino.end
// ino.attribute.class_block.23020.declaration
private Block class_block;
// ino.end
// ino.attribute.paralist.23023.declaration
//private Menge<Type> paralist = new Menge<Type>(); // Parameterliste 'class xy<para1, para2,...>{}' wird gespeichert
// ino.end
// ino.attribute.parahash.23026.declaration
private Hashtable<String,String> parahash = new Hashtable<String,String>(); // parametrisierten Attrib. werden mit den Paramet.aus paralist verk.
// ino.end
// ino.attribute.isFirstLocalVarDecl.23029.declaration
public static boolean isFirstLocalVarDecl; //Hilfsvariable fuer Offsets, hoth
// ino.end
//private Menge<GenericTypeVar> genericClassParameters=new Menge<GenericTypeVar>();
// ino.attribute.containedTypes.23032.decldescription type=line
// PL 05-07-30 eingefuegt. Vektor aller Typdeklarationen, die in der Klasse
// vorkommen. Wird in der Studienarbeit von Andreas Stadelmeier nur für Verifizierung der Tests eingesetzt.
// ino.end
// ino.attribute.containedTypes.23032.declaration
private Menge<Type> containedTypes = new Menge<Type>();
// ino.end
// ino.attribute.usedIdsToCheck.23035.declaration
private Menge<UsedId> usedIdsToCheck = new Menge<UsedId>();
// ino.end
private TypeAssumptions typeAssumptions = null;//muss mit null Initialisiert werden. Darf nur über getTypeAssumptions abgerufen werden.
// ino.attribute.parserlog.23038.declaration
//protected Logger parselog = Logger.getLogger("parser");
// ino.end
protected Logger typinferenzLog = Logger.getLogger(Class.class.getName());
private SyntaxTreeNode parent;
private Menge<Field> fielddecl = new Menge<Field>();
private GenericDeclarationList genericClassParameters;
private int offset;
private RefType superClass;
// ino.method.Class.23041.definition
public Class(String name, int offset)
// ino.end
// ino.method.Class.23041.body
{
this.name = name;
if(name.equals("java.lang.Object")){
superclassid=null;
}
this.offset = offset;
if(!name.equals("Object") && !name.equals("java.lang.Object"))//Alle Klassen außer Object erben von Object:
this.superClass = new Class("java.lang.Object", -1).getType();
}
// ino.end
/**
* Erstellt eine Klasse, welche nur für die Assumptions verwendet wird.
* Sie enthält keine unnötigen Informationen, wie Offset oder ClassBody.
* @param name
* @param superClass
* @param modifiers
* @param supertypeGenPara - Eine Liste von Namen, welche die Generischen Parameter der Klasse darstellen.
*/
public Class(String name, RefType superClass, Modifiers modifiers, Menge<String> supertypeGenPara) {
this(name,superClass,modifiers,0);
if(supertypeGenPara == null)return;
Menge<GenericTypeVar> gtvs = new Menge<>();
for(Object gname : supertypeGenPara){
if(gname instanceof String){
GenericTypeVar newGTV=new GenericTypeVar((String)gname,this,0);
gtvs.add(newGTV);
}else if(gname instanceof GenericTypeVar){
gtvs.add((GenericTypeVar) gname);
}else{
GenericTypeVar newGTV=new GenericTypeVar(gname.toString(),this,0);
gtvs.add(newGTV);
throw new RuntimeException(gname.toString());
}
}
this.setGenericParameter(new GenericDeclarationList(gtvs,0));
}
public Class(String name, RefType superClass, Modifiers mod, int offset){
this(name,mod,offset);
if(superClass == null)this.superClass = new Class("java.lang.Object",-1).getType();
else this.superClass = superClass;
}
// ino.method.Class.23044.definition
public Class(String name, Modifiers mod, int offset)
// ino.end
// ino.method.Class.23044.body
{
this(name, offset);
this.modifiers = mod;
}
// ino.end
public Class(String name, Modifiers mod, ClassBody cb, Menge<Type> ct, Menge<UsedId> usedIdsToCheck,
UsedId superclass, Menge<UsedId> superif, Menge<Type> paralist, int offset){
this(name, mod, cb, ct, usedIdToRefType(superclass),usedIdToRefType(superif),paralist,offset);
}
public Class(String name, ClassBody cb, Menge<Type> ct,
UsedId superclass, Menge<Type> superif, Menge<Type> paralist, int offset) {
this(name,null,cb,ct,usedIdToRefType(superclass),superif,paralist,offset);
}
public Class(String name2, Modifiers modifiers2, ClassBody classBody,
Menge<Type> containedTypes2, UsedId usedId,
Menge<Type> typeMenge, Menge<Type> paraMenge, int offset2) {
this(name2, modifiers2, classBody, containedTypes2, usedIdToRefType(usedId),typeMenge, paraMenge, offset2);
}
public Class(String name2, Modifiers object, ClassBody classBody,
Menge<Type> containedTypes2, Menge<Type> typeMenge,
Menge<Type> paraMenge, int offset2) {
this(name2, object, classBody, containedTypes2,(RefType)null, typeMenge, paraMenge, offset2);
}
private static Menge<Type> usedIdToRefType(Menge<UsedId> superif2) {
Menge<Type> ret = new Menge<>();
for(UsedId id : superif2)ret.add(usedIdToRefType(id));
return ret;
}
private static RefType usedIdToRefType(UsedId superclass2) {
RefType ret = new RefType(superclass2.getSimpleName(), null, superclass2.getOffset());
ret.set_ParaList(superclass2.get_ParaList());
return ret;
}
// ino.method.Class.23047.defdescription type=javadoc
/**
* Konstruktor, der die Angabe aller Parameter ermoeglicht.
* Zur Uebersichtlichkeit in der Grammatik.
*/
// ino.end
// ino.method.Class.23047.definition
public Class(String name, Modifiers mod, ClassBody cb, Menge<Type> ct,
RefType superclass, Menge<Type> Menge, Menge<? extends Type> paralist, int offset)
// ino.end
// ino.method.Class.23047.body
{
this(name,offset);
this.modifiers = mod;
if (cb != null) set_ClassBody(cb);
if (ct != null) setContainedTypes(ct);
if (superclass != null){
this.superClass = superclass;
}
if (Menge != null) setSuperInterfaces(Menge);
if (paralist != null && !paralist.isEmpty()){
Type lastPara = paralist.lastElement();
Integer lastItemOffset = lastPara.getOffset() + lastPara.get_Name().length();
this.setGenericParameter(new GenericDeclarationList((Menge<GenericTypeVar>)paralist, lastItemOffset));
/*
//this.set_ParaList(paralist);
Menge<GenericTypeVar> gtvList = new Menge<>();
int lastItemOffset = 0;
for(Type paraT : paralist){
GenericTypeVar gtv = new GenericTypeVar(paraT.get_Name(),this, paraT.getOffset());
gtvList.add(gtv);
lastItemOffset = paraT.getOffset() + paraT.get_Name().length();
}
this.genericClassParameters = new GenericDeclarationList(gtvList, lastItemOffset);
*/
}
if(usedIdsToCheck!=null) this.usedIdsToCheck=usedIdsToCheck;
// HOTI 10.5.06
// Object darf natuerlich nicht Object als Superklasse haben
// Sonst gibt es eine endlosaufloesung
if(name.equals("java.lang.Object")){
superclassid=null;
}
//parserlog.debug("Neue Klasse: " + name);
}
// ino.end
public Menge<Field> getFields()
{
return fielddecl;
}
/**
* @author Andreas Stadelmeier, a10023
* Fügt der Klasse eine Feld hinzu.
* Prüft dabei, ob es sich um einen Constructor handelt und wandelt diesen direkt um.
* @param feld
*/
public void addField(Field i)
{
fielddecl.addElement(i);
}
// ino.method.getUsedIdsToCheck.23050.definition
public Menge<UsedId> getUsedIdsToCheck()
// ino.end
// ino.method.getUsedIdsToCheck.23050.body
{
return usedIdsToCheck;
}
// ino.end
// ino.method.setContainedTypes.23053.definition
public void setContainedTypes(Menge<Type> containedTypes)
// ino.end
// ino.method.setContainedTypes.23053.body
{
this.containedTypes = containedTypes;
}
// ino.end
// ino.method.getContainedTypes.23056.definition
public Menge<Type> getContainedTypes()
// ino.end
// ino.method.getContainedTypes.23056.body
{
return containedTypes;
}
// ino.end
/*
// ino.method.complete_paralist.23062.definition
public Menge<Type> complete_paralist(boolean ext)
// ino.end
// ino.method.complete_paralist.23062.body
{
//Diese Funktion vervollt�ndigt die Parameterliste f�r vererbte Klassen
Menge<Type> child = paralist;
paralist = (Menge<Type>)superclassid.get_ParaList();
for(Enumeration<Type> e = child.elements();e.hasMoreElements();){
paralist.addElement(e.nextElement());
}
return this.paralist;
}
// ino.end
*/
/**
* Generiert die ClassFile für diese Klasse.
* @param typeinferenceResult - Das ResultSet einer Typinferierung oder null, falls alle Typen eindeutig feststehen.
* @return
* @throws JVMCodeException
// ino.method.codegen.23071.definition
public ClassFile codegen(ResultSet typeinferenceResult)
throws JVMCodeException
// ino.end
// ino.method.codegen.23071.body
{
ClassFile classfile = new ClassFile();
String superClass;
// Handling der Superklasse
if(superclassid != null) {
superClass = superclassid.get_codegen_UsedId();
} else {
superClass = "java/lang/Object";
}
// Handling der Package
//String pkgName = "";
//if (sf.getPackageName() != null) {
// pkgName = sf.getPackageName().get_codegen_UsedId() + "/";
//}
//geändert von Andreas Stadelmeier: pkgName wird nicht mehr aus dem SourceFile ausgelesen:
String packageName = "";
if(pkgName != null) packageName = pkgName.get_Name_1Element();
classfile.add_class(getName(), superClass, getAccessFlags());
// Handling fuer Superinterfaces
classfile.addSuperInterfaces(getSuperInterfaces());
// Generics hinzufuegen - falls erforderlich
classfile.addGenerics(this.paralist,superclassid, this.getSuperInterfaces());
// Body der Classfile generieren
//if(body != null) {
this.codegen(classfile, this.paralist);
//}
// Ueberpruefung, ob Konstruktor generiert
// Falls nicht, default-Konstruktor erzeugen
if(!classfile.get_constructor_founded()) {
classfile.add_method("<init>", "()V", null, null, null, (short)0, this.paralist, false);
}
//classfile.codegen();
codegenlog.info("Compilierung erfolgreich abgeschlossen, "+ getName() + ".class erstellt.");
return classfile;
}
*/
public void set_UsedId (UsedId uid)
// ino.end
// ino.method.set_UsedId.23074.body
{
this.superclassid = uid;
}
// ino.end
/**
* Setzt den ClassBody dieser Klasse. Wird zum Parsen benötigt.
* Der ClassBody enthält sämtliche Felder dieser Klasse.
* Mit dem Aufruf dieser Methode werden alle Felder des ClassBody in diese Class übertragen.
* (Nur einmal während des Parsens aufrufen!)
*/
public void set_ClassBody(ClassBody body)
{
Menge<Field> tempFields=body.getFields();
for(Field f : this.getFields()){
if(f instanceof Method){ //Wenn es sich um eine Methode handelt ist eine zusätzliche Prüfung erfoderlich: (Ist es ein Konstruktor?)
Method m = (Method)f;
/*
* Ermitteln ob es sich bei der Methode um einen Konstruktor handelt:
* (Parser kann nicht zwischen Methode und Konstruktor unterscheiden.
* Denn für einen Konstruktor gelten besondere Regeln:
* -Typ des Blocks eines Konstruktor ist void (kein Return-Statement)
* -Rückgabetyp der Methode/Konstruktors ist der Typ der Klasse
* -Ein Konstruktor kann nicht aufgerufen werden (nur mit new)
*/
if(m.get_Method_Name().equals("<init>"))throw new TypeinferenceException("<init> ist kein gültiger Methodenname", m);
if((m.get_Method_Name().equals(this.getName()))) {
Constructor constructor = new Constructor(m, this);
tempFields.add(constructor); //Den Konstruktor anstatt der Methode anfügen
}else{
//Handelt es sich um keinen Konstruktor, dann die Methode unverändert den Feldern hinzufügen:
tempFields.add(m);
}
}else{
tempFields.add(f); //Ansonsten das Feld anfügen...
}
}
this.fielddecl = tempFields;
}
// ino.method.set_class_block.23080.definition
public void set_class_block(Block block)
// ino.end
// ino.method.set_class_block.23080.body
{
this.class_block = block;
}
// ino.end
// ino.method.get_Superclass_Name.23086.definition
public JavaClassName get_Superclass_Name()
// ino.end
// ino.method.get_Superclass_Name.23086.body
{
if(superclassid!=null)
return superclassid.getQualifiedName();
else
return null;
}
// ino.end
// ino.method.get_class_block.23092.definition
public Block get_class_block()
// ino.end
// ino.method.get_class_block.23092.body
{
return class_block;
}
// ino.end
// ino.method.does_Class_extend.23095.definition
public boolean does_Class_extend()
// ino.end
// ino.method.does_Class_extend.23095.body
{
if(superclassid==null)
return false;
else
return true;
}
// ino.end
/*
// ino.method.set_ParaList.23098.definition
public void set_ParaList(Menge<Type> para)
// ino.end
// ino.method.set_ParaList.23098.body
{
this.paralist = para;
}
// ino.end
*/
// ino.method.get_ParaList.23101.definition
public Menge<? extends Type> get_ParaList()
// ino.end
// ino.method.get_ParaList.23101.body
{
//if(this.paralist == null)return new Menge<Type>();
return this.getGenericParameter();
}
// ino.end
// ino.method.set_ParaHash.23104.definition
public void set_ParaHash(Hashtable<String,String> hash)
// ino.end
// ino.method.set_ParaHash.23104.body
{
this.parahash = hash;
}
// ino.end
// ino.method.get_ParaHash.23107.definition
public Hashtable<String,String> get_ParaHash()
// ino.end
// ino.method.get_ParaHash.23107.body
{
return this.parahash;
}
/////////////////////////////////////////////////////////////////////////
// TypeReconstructionAlgorithmus
/////////////////////////////////////////////////////////////////////////
// ino.method.TRProg.23110.defdescription type=javadoc
/**
* Ausgangspunkt f�r den Typrekonstruktionsalgorithmus. Hier werden zun�chst
* die Mengen von Typannahmen V_fields_methods und V_i erstellt, die als Eingabe
* f�r den Algorithmus dienen.<br/>
* (siehe Algorithmus 5.17 TRProg, Martin Pl�micke)
* <br/>Author: J�rg B�uerle
* @param supportData
* @param globalAssumptions
* @return Liste aller bisher berechneten, m�glichen Typkombinationen
* @throws CTypeReconstructionException
*/
// ino.end
// ino.method.TRProg.23110.definition
public ConstraintsSet typeReconstruction(TypeAssumptions globalAssumptions)
// ino.end
// ino.method.TRProg.23110.body
{
/*
*/
//////////////////////////////
// Und los geht's:
//////////////////////////////
inferencelog.info("Rufe TRStart()...", Section.TYPEINFERENCE);
//////////////////////////////
// Ab hier ...
// @author A10023 - Andreas Stadelmeier:
//////////////////////////////
//Erzeuge Assumptions:
TypeAssumptions assumptions = this.getPrivateFieldAssumptions();
//Globale Assumptions anfügen:
assumptions.add(globalAssumptions);
ConstraintsSet oderConstraints = new ConstraintsSet();
for(Type gparam : this.get_ParaList()){
if(gparam instanceof GenericTypeVar)assumptions.add(((GenericTypeVar)gparam).createAssumptions()); //Constraints für die Generischen Variablen erstellen und diese dem AssumptionsSet hinzufügen
}
for(Type gparam : this.get_ParaList()){
if(gparam instanceof GenericTypeVar)oderConstraints.add(((GenericTypeVar)gparam).TYPE(assumptions)); //Constraints für die Generischen Variablen erstellen und diese dem AssumptionsSet hinzufügen
}
typinferenzLog.debug("Erstellte Assumptions: "+assumptions, Section.TYPEINFERENCE);
/*
//Generiere Liste mit Expressions, welche zur Initialisierung von Feldern verwendet werden.
Menge<Expr> fieldInitializers = new Menge<Expr>();
for(FieldDeclaration field : body.getFieldInitializations()){
Assign fieldAssign = new Assign(0,0);
Expr expr1 = new LocalOrFieldVar(field.getName(), 0);
Expr expr2 = field.getWert();
fieldAssign.set_Expr(expr1, expr2);
fieldInitializers.add(fieldAssign);
}
*/
//ConstraintsSet oderConstraints = this.TYPE(this.getMethodList(), fieldInitializers, assumptions);
//Gibt es hier eine ClassCastException stimmt etwas grundsätzlich nicht!
this.superClass = (RefType)this.superClass.TYPE(assumptions, this);
for(Field f:this.getFields()){
oderConstraints.add(f.TYPE(assumptions));
}
typinferenzLog.debug("Erstellte Constraints: "+oderConstraints, Section.TYPEINFERENCE);
return oderConstraints;
}
/**
* Ermittelt alle privaten Felder und Methoden der Klasse und Erstellt eine Assumption für diese.
* Bemerkung: Momentan werden noch alle Felder dieser Klasse zurückgegeben.
* @return Die erstellten TypeAssumptions
*/
private TypeAssumptions getPrivateFieldAssumptions() {
if(this.typeAssumptions != null)return this.typeAssumptions; //Das sorgt dafür, dass die Assumptions nur einmalig generiert werden.
TypeAssumptions assumptions = new TypeAssumptions(this.getName());
//this.getMethodList(); //Diese Funktion muss zuerst ausgeführt werden.
//Assumption für this, also die aktuelle Klasse: (ist nicht mehr nötig, da jedes AssumptionSet einer Klasse (dem namen einer Klasse) zugewiesen ist.
//CLocalVarTypeAssumption thisAssumption = new CLocalVarTypeAssumption(this.name, name, 0, 0, name, "this", new RefType(name,0), 0, 0, null);
//assumptions.setThisV(thisAssumption);
for(Field field : this.getFields()){
if(!field.isPublic())assumptions.add(field.createTypeAssumptions(this));
}
//Eine Assumption für den Standardkonstruktor:
// (Ein Standardkonstruktor wird immer angefügt, da es momentan keine statischen Klassen gibt)
//auskommentiert, da der Standardkonstruktor beim Parser-Postprocessing angefügt wird.
//if(assumptions.getMethodAssumptions(this.getName(), "<init>").size()==0){ //Falls kein Konstruktor für diese Klasse definiert wurde:
// assumptions.addMethodAssumption(new RefType(this.getName(),0), "<init>", new RefType(this.getName(),0), new Menge<CParaTypeAssumption>());
//}
this.typeAssumptions = assumptions; //Diese müssen anschließend nicht wieder generiert werden.
return assumptions;
}
// ino.method.toString.23125.defdescription type=javadoc
/**
* <br/>Author: Martin Pl�micke
* @return
*/
// ino.end
// ino.method.toString.23125.definition
public String toString()
// ino.end
// ino.method.toString.23125.body
{
//return superclassid.toString() + body.toString();
//geaendert PL 07-07-28
return name;
}
// ino.end
// ino.method.wandleRefTypeAttributes2GenericAttributes.23128.defdescription type=javadoc
/**
* Alle Methoden der Klassen überprüfen, ob sie als
* RefType deklarierte Attribute haben, die aber GenericTypeVars sind
* und ggf. ersetzen
*
* Bsp.:
* bei public E elementAt(i){...} wird E vorerst als RefType erkannt
*
*/
// ino.end
// ino.method.wandleRefTypeAttributes2GenericAttributes.23128.definition
public void wandleRefTypeAttributes2GenericAttributes()
// ino.end
// ino.method.wandleRefTypeAttributes2GenericAttributes.23128.body
{
for(Field f : this.getFields()){
//f.wandleRefTypeAttributes2GenericAttributes(paralist);
}
}
/**
* HOTI
* Liefert bei Klassen die fullyQualified angegeben wurden
* nur den schlussendlichen Bezeichner
* p.ex. de.dhbwstuttgart.typeinference.Menge => Menge
* @return
*/
// ino.end
// ino.method.getSimpleName.23140.definition
public String getSimpleName()
// ino.end
// ino.method.getSimpleName.23140.body
{
return UsedId.createFromQualifiedName(getName().toString(),-1).getSimpleName();
}
// ino.end
public String getTypeInformation(Menge<Method> methodList, Menge<Expr> fieldList){
String ret = this.name+": ";
for(Expr field : fieldList){
ret+=field.getTypeInformation()+"\n";
}
for(Method m : methodList){
ret+=m.getTypeInformation()+"\n";
}
return ret;
}
/**
* Generiert den JavaCode dieser Klasse im Falle für das übergebene resultSet.
* Dem ResultSet entsprechend werden in diesem Java-Code die TypePlaceholder durch die in ResultSet stehenden Typen ersetzt.
* @return Java-Sourcefile
*/
public String printJavaCode(TypeinferenceResultSet reconstructionResult){
JavaCodeResult ret = new JavaCodeResult("class ");
JavaCodeResult classBodyCode = new JavaCodeResult();
if(this.modifiers!=null)classBodyCode.attach(this.modifiers.printJavaCode(reconstructionResult.getUnifiedConstraints())).attach(" ");
classBodyCode.attach(this.name + " extends ").attach(superclassid.printJavaCode(reconstructionResult.getUnifiedConstraints())).attach("\n");
JavaCodeResult bodyString = new JavaCodeResult("{\n");
for(Field field : this.fielddecl)bodyString.attach( field.printJavaCode(reconstructionResult.getUnifiedConstraints()) ).attach( "\n" );
bodyString.attach("}\n");
classBodyCode.attach(bodyString);
//Zuerst die generischen Parameter für diese Klasse berechnen:
//this.createGenericTypeVars(classBodyCode.getUnresolvedTPH());
if(this.genericClassParameters != null && this.genericClassParameters.size()>0){
ret.attach("<");
Iterator<GenericTypeVar> it = this.genericClassParameters.iterator();
while(it.hasNext()){
GenericTypeVar tph = it.next();
ret.attach(tph.printJavaCode(reconstructionResult.getUnifiedConstraints()));
if(it.hasNext())ret.attach(", ");
}
ret.attach(">");
}
String stringReturn = ret.attach(classBodyCode).toString();
return stringReturn;
}
/**
* Errechnet die Generischen Parameter der Klasse für diese Klasse.
* Die berechneten Variablen werden anschließend in die this.genericTypeVars eingesetzt. Dabei werden alte genericTypeVars überschrieben.
* @param tphs : Alle übriggebliebenen TypePLaceholder
private void createGenericTypeVars(Menge<TypePlaceholder> tphs){
this.genericClassParameters = new GenericDeclarationList(new Menge<GenericTypeVar>());
for(TypePlaceholder tph : tphs){
GenericTypeVar toAdd = new GenericTypeVar(tph,this.getOffset());
if(!this.genericClassParameters.contains(toAdd))this.genericClassParameters.add(toAdd);
}
}
*/
/**
* Errechnet die Generischen Parameter der Klasse für diese Klasse.
* Die berechneten Variablen werden anschließend in die this.genericTypeVars eingesetzt. Dabei werden alte genericTypeVars überschrieben.
* @param reconstructionResult
public void createGenericTypeVars(TypeinferenceResultSet reconstructionResult){
this.genericClassParameters = new Menge<GenericTypeVar>();
for(Pair pair : reconstructionResult.getUnifiedConstraints()){
if(pair.TA2 instanceof TypePlaceholder && pair.TA1 instanceof TypePlaceholder){// if(pair.OperatorSmallerExtends() || pair.OperatorSmaller()){
Type ta1=reconstructionResult.getUnifiedConstraints().getTypeEqualTo(pair.TA1);
Type ta2=reconstructionResult.getUnifiedConstraints().getTypeEqualTo(pair.TA2);
this.genericClassParameters.add(new GenericTypeVar(new Pair(ta1,ta2),this.getOffset()));
}
}
for(Pair pair : reconstructionResult.getConstraints()){
if( ! reconstructionResult.getUnifiedConstraints().contains(pair.TA1)){
this.genericClassParameters.add(new GenericTypeVar(pair.TA1,this.getOffset()));
}
if( ! reconstructionResult.getUnifiedConstraints().contains(pair.TA2)){
this.genericClassParameters.add(new GenericTypeVar(pair.TA2, this.getOffset()));
}
}
}
*/
public int getOffset(){
return this.offset;
}
/**
* Erstellt einen RefType, welcher auf diese Klasse verweist
* Ersetzt alle Generischen Variablen in der Parameterliste mit TPH
* @return
*/
public RefType getType() {
/*
Menge<Type> parameter = new Menge<Type>();
for(Type param : this.get_ParaList()){
parameter.add(((GenericTypeVar)param).getTypePlaceHolder());//(TypePlaceholder.fresh()); //Hier ist kein ReplacementListener notwendig. Der Typ soll nie eingesetzt werden. Der TPH wird nur gebraucht, damit das Unifizieren funktioniert.
}
*/
return new RefType(this.getName().toString(), this.get_ParaList(),this, 0);
}
/**
* Ermittelt die Sichtbaren Felder und Methoden der Klasse.
* (Momentan sind im Projekt alle Felder und Methoden "package private", da der Parser keine Access-Modifier einlesen kann.
* @return
*/
public TypeAssumptions getPublicFieldAssumptions() {
TypeAssumptions ret = new TypeAssumptions();//this.getPrivateFieldAssumptions();
ret.addClassAssumption(new ClassAssumption(this));
for(Field f : this.getFields()){
if(f.isPublic())ret.add(f.createTypeAssumptions(this));
}
for(GenericTypeVar gtv : this.getGenericParameter()){
ret.add(gtv.createAssumptions());
}
return ret;
}
@Override
public void parserPostProcessing(SyntaxTreeNode parent) {
//Wenn keine Superklasse, dann erbt die Klasse zwangsweise von Object:
if(superclassid == null || superclassid.get_Name().size()<1){
int superclassidOffset = superclassid == null ? 0 : superclassid.getOffset();
superclassid = new UsedId("Object", superclassidOffset);
}
//Alle Methoden auf Konstruktoren durchsuchen und diese umwandeln:
Menge<Field> tempFields = new Menge<Field>();
for(Field f : this.getFields()){
if(f instanceof Method && !(f instanceof Constructor)){ //Der Check, ob f ein Konstruktor ist eigentlich obsolet, da der Parser keinen Konstruktor generiert
Method method = (Method)f;
if(method.get_Method_Name().equals(this.getName().toString()) ){
tempFields.add(new Constructor(method, this));
}else{
tempFields.add(f);
}
}else{
tempFields.add(f);
}
}
this.fielddecl = tempFields;
//Prüfen ob ein Konstruktor vorhanden ist:
boolean constructorVorhanden = false;
for(Field f : this.getFields()){
if(f instanceof Constructor){
constructorVorhanden = true;
break;
}
}
if(!constructorVorhanden){//Falls kein Konstruktor vorhanden ist, muss noch der Standardkonstruktor angefügt werden:
Block konstruktorBlock = new Block();
konstruktorBlock.statements.add(new SuperCall(konstruktorBlock));
Constructor standardKonstruktor = new Constructor(Method.createEmptyMethod(konstruktorBlock,this.getName().toString(), this), this);
//Constructor standardKonstruktor = new Constructor(Method.createEmptyMethod(this.getName().toString(), this));
this.addField(standardKonstruktor);
}
if(this.genericClassParameters == null)this.setGenericParameter(new GenericDeclarationList(new Menge<GenericTypeVar>(), 0));
/*//Nicht mehr notwendig, Generische Klassenparameter werden nun immer direkt in die genericClassParameters gespeichert.
for(Type t : this.get_ParaList()){
if(t instanceof GenericTypeVar)this.genericClassParameters.add((GenericTypeVar)t);
else this.genericClassParameters.add(new GenericTypeVar(t.get_Name(),this,-1));
}
*/
/*
for(Type t : this.get_ParaList()){
t.parserPostProcessing(this);
}
*/
/*
for(GenericTypeVar gtv : this.getGenericParameter()){
gtv.setParentClass(this);;
}
*/
//TODO: Umwandlung zu RefTypes funktioniert noch nicht richtig. (siehe LambdaTest2)
//Als RefType geparste Generische Variablen umwandeln:
this.wandleRefTypeAttributes2GenericAttributes();
//Erst am Schluss, nachdem Methoden zu Konstruktoren umgewandelt wurden:
super.parserPostProcessing(parent);
}
@Override
public SyntaxTreeNode getParent() {
return this;
}
@Override
public Menge<SyntaxTreeNode> getChildren() {
Menge<SyntaxTreeNode> ret = new Menge<SyntaxTreeNode>();
//for(Field f : this.getFields()){
// ret.add(f);
//}
ret.addAll(this.getFields());
ret.addAll(this.get_ParaList());
ret.addAll(this.getGenericParameter());
return ret;
}
@Override
public boolean equals(Object obj){
if(!(obj instanceof Class))return false;
Class cl = (Class) obj;
if(!(cl.getName().equals(this.getName())))return false;
return true;
}
@Override
public Menge<GenericTypeVar> getGenericParameter() {
if(this.genericClassParameters == null)return new Menge<GenericTypeVar>();
return this.genericClassParameters.getMenge();
}
@Override
public String getDescription(ClassGenerator cg, TypeinferenceResultSet rs){
return "class "+this.getName();
}
@Override
public int getVariableLength() {
// TODO Auto-generated method stub
return 0;
}
@Override
public void setGenericParameter(GenericDeclarationList params) {
this.genericClassParameters = params;
}
@Override
public String getGenericVarDeclarationString(String genericVarDeclaration) {
if(this.genericClassParameters != null){
return ", "+genericVarDeclaration;
}else{
return "<"+genericVarDeclaration+">";
}
}
@Override
public int getGenericVarDeclarationOffset(){
// Falls Generische Parameterliste vorhanden, hier Wert der Liste zurückgegebn
if(this.genericClassParameters != null){
return this.genericClassParameters.getEndOffset();
}else{
return this.offset;
}
}
/**
* Die Super Klasse dieser Klasse.
* @return null für Klasse Object
*/
public RefType getSuperClass(){
return this.superClass;
}
@Override
public boolean isClass() {
return true;
}
public boolean isInterface(){
return false;
}
/*
private Collection<? extends ByteCodeResult> getGenericClasses() {
Collection<ByteCodeResult> results = new Menge<>();
for(Field field : this.fielddecl){
Type type = field.getType();
//Der Type des Feldes
if(type instanceof RefType){
RefType refType = (RefType) type;
if(!refType.getCombinedType(null).equals(refType.get_Name().replace(".", "%"))){
results.addAll(generateGenericClass(refType.getCombinedType(null), new Class("java/util/Vector",-1)));
}
}
if(field instanceof Method){
Method method = (Method) field;
ParameterList parameterList = method.getParameterList();
//Die Typen der Methodenparameter
for(FormalParameter parameter: parameterList){
Type parameterType = parameter.getType();
if(parameterType instanceof RefType){
RefType refType = (RefType) parameterType;
if(!refType.getCombinedType(null).equals(refType.get_Name().replace(".", "%"))){
results.addAll(generateGenericClass(refType.getCombinedType(null), new Class("java/util/Vector",-1)));
}
}
}
}
}
return results;
}
*/
/*
private Menge<ByteCodeResult> generateGenericClass(String name, Class superClass){
//TODO: bytecode -- Generics hinzuf<75>gen
//Type superClassType = superClass.getType();
//TODO: bytecode
//ClassGenerator genericClassGenerator = new ClassGenerator(name, superClassType, name + ".java", Constants.ACC_PUBLIC , new String[] { }, new TypeinferenceResultSet(null, null, null));
//TODO: bytecode -- Namen der neuen Klasse
Class generatedClass = new Class(name, 0);
//TODO: bytecode -- alle Konstruktoren generieren
Block konstruktorBlock = new Block();
konstruktorBlock.setType(new de.dhbwstuttgart.syntaxtree.type.Void(konstruktorBlock, 0));
konstruktorBlock.statements.add(new SuperCall(konstruktorBlock));
Constructor standardKonstruktor = new Constructor(Method.createEmptyMethod(konstruktorBlock, name, superClass), superClass);
standardKonstruktor.parserPostProcessing(generatedClass);
generatedClass.addField(standardKonstruktor);
return generatedClass.genByteCode(new TypeinferenceResultSet(generatedClass, new Menge<>(), new ResultSet()));
}
*/
}
// ino.end