forked from JavaTX/JavaCompilerCore
262 lines
9.0 KiB
Java
Executable File
262 lines
9.0 KiB
Java
Executable File
package de.dhbwstuttgart.syntaxtree;
|
||
|
||
import de.dhbwstuttgart.logger.Logger;
|
||
import de.dhbwstuttgart.logger.Section;
|
||
import de.dhbwstuttgart.core.IItemWithOffset;
|
||
import de.dhbwstuttgart.typecheck.JavaClassName;
|
||
import de.dhbwstuttgart.syntaxtree.modifier.Modifiers;
|
||
import de.dhbwstuttgart.syntaxtree.statement.Block;
|
||
import de.dhbwstuttgart.syntaxtree.statement.Expr;
|
||
import de.dhbwstuttgart.syntaxtree.type.GenericTypeVar;
|
||
import de.dhbwstuttgart.syntaxtree.type.RefType;
|
||
import de.dhbwstuttgart.syntaxtree.type.Type;
|
||
import de.dhbwstuttgart.typeinference.*;
|
||
import de.dhbwstuttgart.typeinference.assumptions.ClassAssumption;
|
||
import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions;
|
||
|
||
import java.util.ArrayList;
|
||
import java.util.List;
|
||
|
||
/**
|
||
* Stellt jede Art von Klasse dar. Auch abstrakte Klassen und Interfaces
|
||
*/
|
||
public class Class extends GTVDeclarationContext implements IItemWithOffset, Generic, GenericTypeInsertable
|
||
{
|
||
/**
|
||
* Loggerinstanzen
|
||
*/
|
||
protected static Logger inferencelog = Logger.getLogger("inference");
|
||
protected static Logger codegenlog = Logger.getLogger("codegen");
|
||
protected static Logger parserlog = Logger.getLogger("parser");
|
||
protected Logger typinferenzLog = Logger.getLogger(Class.class.getName());
|
||
|
||
protected Modifiers modifiers;
|
||
protected JavaClassName name;
|
||
private Block class_block;
|
||
private List<Field> fielddecl = new ArrayList<>();
|
||
private GenericDeclarationList genericClassParameters;
|
||
private int offset;
|
||
private RefType superClass;
|
||
protected boolean isInterface;
|
||
private List<RefType> implementedInterfaces;
|
||
|
||
/////////////////////////////////////////////////////////////////////////
|
||
// TypeReconstructionAlgorithmus
|
||
/////////////////////////////////////////////////////////////////////////
|
||
/**
|
||
* 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
|
||
*/
|
||
public ConstraintsSet typeReconstruction(TypeAssumptions globalAssumptions)
|
||
{
|
||
//////////////////////////////
|
||
// 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);
|
||
|
||
//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());
|
||
|
||
for(Field field : this.getFields()){
|
||
if(!field.isPublic())assumptions.add(field.createTypeAssumptions(this));
|
||
}
|
||
|
||
this.typeAssumptions = assumptions; //Diese müssen anschlieÃend nicht wieder generiert werden.
|
||
return assumptions;
|
||
}
|
||
|
||
/**
|
||
* <br/>Author: Martin Pl�micke
|
||
* @return
|
||
*/
|
||
public String toString()
|
||
{
|
||
return name.toString();
|
||
}
|
||
|
||
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 JavaCodeResult printJavaCode(ResultSet reconstructionResult){
|
||
JavaCodeResult ret = new JavaCodeResult("class ");
|
||
|
||
JavaCodeResult classBodyCode = new JavaCodeResult();
|
||
if(this.modifiers!=null)classBodyCode.attach(this.modifiers.printJavaCode(reconstructionResult)).attach(" ");
|
||
|
||
classBodyCode.attach(this.name + " extends ").attach(this.superClass.printJavaCode(reconstructionResult)).attach("\n");
|
||
|
||
JavaCodeResult bodyString = new JavaCodeResult("{\n");
|
||
for(Field field : this.fielddecl)bodyString.attach( field.printJavaCode(reconstructionResult) ).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));
|
||
if(it.hasNext())ret.attach(", ");
|
||
}
|
||
ret.attach(">");
|
||
}
|
||
|
||
String stringReturn = ret.attach(classBodyCode).toString();
|
||
|
||
return new JavaCodeResult(stringReturn);
|
||
}
|
||
|
||
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() {
|
||
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 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 GenericDeclarationList getGenericParameter() {
|
||
return this.genericClassParameters;
|
||
}
|
||
|
||
@Override
|
||
public String getDescription(){
|
||
return "class "+this.getName();
|
||
}
|
||
|
||
@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 isInterface;
|
||
}
|
||
}
|