package de.dhbwstuttgart.syntaxtree; import org.apache.commons.bcel6.generic.ClassGen; import de.dhbwstuttgart.typeinference.Menge; import de.dhbwstuttgart.bytecode.ClassGenerator; import de.dhbwstuttgart.core.IItemWithOffset; import de.dhbwstuttgart.syntaxtree.type.GenericTypeVar; import de.dhbwstuttgart.syntaxtree.type.Type; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; import de.dhbwstuttgart.typeinference.Pair; import de.dhbwstuttgart.typeinference.ResultSet; import de.dhbwstuttgart.typeinference.TypeInsertable; import de.dhbwstuttgart.typeinference.TypeinferenceResultSet; import de.dhbwstuttgart.typeinference.exceptions.DebugException; import de.dhbwstuttgart.typeinference.exceptions.TypeinferenceException; import de.dhbwstuttgart.typeinference.typedeployment.GenericTypeInsertPoint; import de.dhbwstuttgart.typeinference.typedeployment.TypeInsertPoint; import de.dhbwstuttgart.typeinference.typedeployment.TypeInsertSet; public abstract class SyntaxTreeNode implements IItemWithOffset{ protected SyntaxTreeNode parent; /** * Wird nach dem Parsen aufgerufen. * Erfüllt folgenden Aufgaben: * 1. Füllt fehlende Typangaben mit TPHs auf. * 2. Verknüpft die Knoten des Syntaxbaums. (setzt Parent) * 3. Wechselt RefTypes gegebenenfalls mit GenericTypeVars aus. * 4. Führt einen Teil des Syntaxckecks durch. * */ public void parserPostProcessing(SyntaxTreeNode parent) { if(parent == null)throw new NullPointerException(); this.parent = parent; for(SyntaxTreeNode node : this.getChildren()) if(node!=null)node.parserPostProcessing(this); } public SyntaxTreeNode getParent() { //if(this.parent == null)throw new NullPointerException(); return this.parent; } public abstract Menge getChildren(); public Class getParentClass(){ SyntaxTreeNode parent = this.getParent(); if(parent instanceof Class)return (Class)parent; if(parent == null) throw new DebugException("Das Wurzelelement eines Syntaxbaumes muss Class sein"); return parent.getParentClass(); } /** * Eine Beschreibung/Name des SyntaxTree-Nodes * Hat nichts mit der Description im Bytecode zu tun, * wird für die Anzeige des AST im Plugin verwendet * @return */ public String getDescription(){ return this.toString(); } @Override public boolean equals(Object object){ if(!(object instanceof SyntaxTreeNode))return false; SyntaxTreeNode equal = (SyntaxTreeNode)object; if(!equal.getDescription().equals(this.getDescription()))return false; if(this.getParent()!=null) if(!this.getParent().equals(equal.getParent()))return false; //auch das Elternelement überprüfen. return true; } /** * Methode zur Generierung der TypeInsertPoints * @param insertSet - Generierte InsertPoints werden dem insertSet angefügt * @param result - Das ResultSet auf dessen Basis die InsertPoints generiert werden */ public void addTypeInsertPoints(TypeInsertSet insertSet,ResultSet result) { for(SyntaxTreeNode node : this.getChildren()){ node.addTypeInsertPoints(insertSet, result); } TypeInsertPoint tip = null; //Der TypInsertPoint für diesen Knoten //Fall der Knoten ein TypeInsertable ist, kann direkt der TypeInsertPoint generiert werden. if(this instanceof TypeInsertable){ TypeInsertable that = (TypeInsertable)this; Type t = that.getType(); if(t instanceof TypePlaceholder){ tip = that.createTypeInsertPoint((TypePlaceholder) t, result); insertSet.add(tip);//ret.addAll(((TypePlaceholder)t).getTypeInsertPoints(result)); } /* //Für den Fall, dass dieser Knoten Generische Variablen halten kann. if(that instanceof Generic && that.getOffset()>=0){ //Alle unresolvedTPHs ermitteln und GenericTypeVarInsertPoints bilden: Menge uTPHs = insertSet.getUnresolvedTPHs(); if(uTPHs.size()>0){//Nur wenn es auch unresolvedTPHs gibt: Menge gPairs = result.getConstraintsFor(uTPHs); if(gPairs.size()>0){ GenericTypeInsertPoint genericTIP = new GenericTypeInsertPoint(that,gPairs,result); insertSet.add(genericTIP); } } } */ } } public boolean seesType(Type tA2) { //TODO: Implementieren. Hier sollte ein Lookup in die Assumptions dieses Knotens erfolgen return false; } public SyntaxTreeNode getMatchingParentNode(SyntaxTreeNode inNode) { SyntaxTreeNode node = inNode; while(node!=null){ if(node.equals(this))return this; node = inNode.getParent(); } if(this.getParent()!=null)return this.getParent().getMatchingParentNode(inNode); return null; } public GTVDeclarationContext getGTVDeclarationContext(){ if(this.getParent()==null) throw new NullPointerException();//throw new DebugException("getGTVDeclarationContext auf unzulässiger Klasse aufgerufen"); return this.getParent().getGTVDeclarationContext(); } }