JavaPatternMatching/src/de/dhbwstuttgart/syntaxtree/Class.java
2015-06-17 12:03:54 +02:00

1364 lines
48 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 org.apache.bcel.generic.ClassGen;
import org.apache.bcel.generic.ConstantPoolGen;
import org.apache.bcel.generic.InstructionFactory;
import org.apache.bcel.generic.InstructionHandle;
import org.apache.bcel.generic.InstructionList;
import org.apache.bcel.generic.MethodGen;
import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.logger.Logger;
import de.dhbwstuttgart.logger.Section;
import de.dhbwstuttgart.logger.SectionLogger;
import de.dhbwstuttgart.core.AClassOrInterface;
import de.dhbwstuttgart.core.IItemWithOffset;
import de.dhbwstuttgart.parser.JavaClassName;
import de.dhbwstuttgart.syntaxtree.misc.UsedId;
import de.dhbwstuttgart.syntaxtree.modifier.Modifiers;
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.FC_TTO;
import de.dhbwstuttgart.typeinference.unify.Unify;
import org.apache.bcel.generic.*;
import org.apache.bcel.classfile.*;
import org.apache.bcel.*;
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;
//For ByteCode Construction
private InstructionFactory _factory;
private ConstantPoolGen _cp;
private ClassGen _cg;
//Method created with BCEL to generate ByteCode
public ByteCodeResult genByteCode() throws IOException {
SectionLogger logger = Logger.getSectionLogger(this.getClass().getName(), Section.CODEGEN);
logger.debug("Test");
if(pkgName != null)throw new NotImplementedException();
_cg = new ClassGen(name, superClass.get_Name(), name + ".java", Constants.ACC_PUBLIC , new String[] { }); //new String necessary?
_cp = _cg.getConstantPool();
_factory = new InstructionFactory(_cg, _cp);
for(Field field : this.fielddecl){
field.genByteCode(_cg);
}
ByteCodeResult code = new ByteCodeResult(_cg);
return code;
//ByteCodeResult bc = new ByteCodeResult();
//_cg = new ClassGen(pkgName.get_Name() + "/" + name, superClass.get_Name(), name + ".java", Constants.ACC_PUBLIC , new String[] { });
//_cg zur<75>ckgeben
//bc.append(BCELByteCodeOutput);
//return _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 Type 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"))//Alle Klassen außer Object erben von Object:
this.superClass = new Class("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(String gname : supertypeGenPara){
GenericTypeVar newGTV=new GenericTypeVar(gname,this,0);
gtvs.add(newGTV);
}
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("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,(Type)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 Type 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,
Type 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);
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;
}
// 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
/////////////////////////////////////////////////////////////////////////
// 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(FC_TTO supportData, TypeAssumptions globalAssumptions)
// ino.end
// ino.method.TRProg.23110.body
{
/*
*/
//////////////////////////////
// Und los geht's:
//////////////////////////////
inferencelog.info("Rufe TRStart()...", Section.TYPEINFERENCE);
typinferenzLog.debug("Erstellte FiniteClosure: "+supportData, 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);
this.superClass = this.superClass.TYPE(assumptions, this);
for(Field f:this.getFields()){
oderConstraints.add(f.TYPE(assumptions));
}
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 M�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 m�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);
// F�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());
// F�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);
// F�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);
// F�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 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;
}
/*
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 fü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 R�ckgabetyp f�r die �bergebene Methode zur�ck.<br/>
* (siehe Algorithmus RetType, Martin Pl�micke)
* <br/>Author: J�rg B�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
* @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);
}
/*
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
* 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 ");
//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(" ");
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)){
Method method = (Method)f;
if(method.get_Method_Name().equals(this.getName().toString()) ){
tempFields.add(new Constructor(method));
}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));
//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(){
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 Type getSuperClass(){
return this.superClass;
}
@Override
public boolean isClass() {
return true;
}
}
// ino.end