// ino.module.Method.8564.package package de.dhbwstuttgart.syntaxtree; // ino.end // ino.module.Method.8564.import import java.util.Enumeration; import java.util.Hashtable; import java.util.Iterator; import org.apache.bcel.Constants; 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.core.IItemWithOffset; import de.dhbwstuttgart.core.MyCompiler; import de.dhbwstuttgart.myexception.JVMCodeException; import de.dhbwstuttgart.myexception.SCMethodException; import de.dhbwstuttgart.myexception.SCStatementException; import de.dhbwstuttgart.parser.JavaClassName; import de.dhbwstuttgart.syntaxtree.misc.DeclId; import de.dhbwstuttgart.syntaxtree.modifier.Modifiers; import de.dhbwstuttgart.syntaxtree.statement.Block; import de.dhbwstuttgart.syntaxtree.statement.Return; import de.dhbwstuttgart.syntaxtree.statement.Statement; import de.dhbwstuttgart.syntaxtree.type.GenericTypeVar; import de.dhbwstuttgart.syntaxtree.type.RefType; import de.dhbwstuttgart.syntaxtree.type.Type; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; import de.dhbwstuttgart.typeinference.ConstraintsSet; import de.dhbwstuttgart.typeinference.JavaCodeResult; import de.dhbwstuttgart.typeinference.ResultSet; import de.dhbwstuttgart.typeinference.SingleConstraint; import de.dhbwstuttgart.typeinference.TypeInsertable; import de.dhbwstuttgart.typeinference.assumptions.MethodAssumption; import de.dhbwstuttgart.typeinference.assumptions.ParameterAssumption; import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions; import de.dhbwstuttgart.typeinference.exceptions.TypeinferenceException; import de.dhbwstuttgart.typeinference.typedeployment.TypeInsertPoint; // ino.class.Method.23482.declaration /** * Stellt eine Methode dar. Problem: Parser kann nicht zwischen Methode und * Konstruktor unterscheiden. Daher kann diese Klasse beides sein. Dies wird mit * dem ParserPostProcessing behoben. * * @author janulrich * */ public class Method extends Field implements IItemWithOffset, TypeInsertable // ino.end // ino.class.Method.23482.body { // ino.attribute.block.23488.declaration private Block block; // ino.end // ino.attribute.parameterlist.23491.declaration public ParameterList parameterlist = new ParameterList(); // ino.end // ino.attribute.exceptionlist.23494.declaration private ExceptionList exceptionlist; // ino.end // ino.attribute.returntype.23497.declaration private Type returntype; // ino.end protected MethodGen method; // ino.attribute.genericMethodParameters.23500.decldescription type=javadoc /** * HOTI 4.5.06 Dieser Vektor beinhaltet alle Generischen Typen und v.a. die * F-Bounded-Generics, die die Methode besitzt size()==0, falls es keine * gibt */ // ino.end // ino.attribute.genericMethodParameters.23500.declaration // private Menge genericMethodParameters=new // Menge(); // ino.end // ino.attribute.overloadedID.23503.declaration private int overloadedID; // ino.end // ino.attribute.isAbstract.23506.declaration private boolean isAbstract = false; // ino.end // ino.attribute.types_in_parameterlist.23509.declaration private Menge types_in_parameterlist = new Menge(); // ino.end // ino.attribute.m_LineNumber.23512.declaration private int m_LineNumber = MyCompiler.NO_LINENUMBER; // ino.end private int m_Offset = -1; // hinzugef�gt hoth: 07.04.2006 // ino.attribute.inferencelog.23515.declaration protected static Logger inferencelog = Logger.getLogger("inference"); // ino.end // ino.attribute.parserlog.23518.declaration protected static Logger parserlog = Logger.getLogger("parser"); // ino.end public Method(int offset) { super(offset); } public Method(String name, Type returnType, ParameterList parameterList, Block block, GenericDeclarationList gtvDeclarations, int offset) { this(offset); /* * if(parameterList != null)parameterList.parserPostProcessing(this); * if(block != null)block.parserPostProcessing(this); if(gtvDeclarations * != null)gtvDeclarations.parserPostProcessing(this); */ this.set_Method_Name(name); this.setParameterList(parameterList); this.set_Block(block); this.setGenericParameter(gtvDeclarations); this.setReturnType(returnType); } /* * // ino.method.setGenericMethodParameters.23521.definition public void * setGenericMethodParameters(Menge genericMethodParameters) * // ino.end // ino.method.setGenericMethodParameters.23521.body { * this.genericMethodParameters=genericMethodParameters; } // ino.end // * ino.method.getGenericMethodParameters.23524.definition public * Menge getGenericMethodParameters() // ino.end // * ino.method.getGenericMethodParameters.23524.body { * return(genericMethodParameters); } // ino.end */ /* * // ino.method.sc_init_parameterlist.23530.definition public void * sc_init_parameterlist(boolean ext) // ino.end // * ino.method.sc_init_parameterlist.23530.body { DeclId hilf=null; * Menge list; FormalParameter para; String typeofpara; int * i=1; if(this.getParameterList()!=null) //es gibt Parameter, dann: { * hilf=declid.elementAt(0); if(ext) * parserlog.debug("Semantik-Check hat in Methode " * +hilf.get_Name()+" bergabewerte gefunden:"); * list=this.getParameterList().sc_get_Formalparalist(); //Menge * Formalparalist aus FormalParameterList wird zwischen gesichert * for(Enumeration el2=list.elements(); * el2.hasMoreElements();) { para=el2.nextElement(); * typeofpara=para.getTypeName(); if(ext) * parserlog.debug(" "+i+". Parameter hat Typ "+typeofpara); * types_in_parameterlist.addElement(typeofpara); //Typ der Parameter werden * im Menge abgelegt i++; } } else //keine Parameter vorhanden: { if(ext) { * hilf=declid.elementAt(0); * parserlog.debug("Semantik-Check hat in Methode " * +hilf.get_Name()+" keine bergabewerte gefunden."); } } if(ext) { * parserlog.debug("Semantik-Check hat in Methode "+hilf.get_Name()+" "+ * types_in_parameterlist.size()+" bergabeparameter gefunden."); * parserlog.debug * (" namentlich: "+types_in_parameterlist.toString()); } } // * ino.end */ // ino.method.getTypeName.23533.defdescription type=line // Eine der beiden Funktionen ist ueberflssig. Wer sich daran strt kann die // get_ReturnType() auf eigene Gefahr lschen. // ino.end // ino.method.getTypeName.23533.definition public JavaClassName getTypeName() // ino.end // ino.method.getTypeName.23533.body { if (this.getType() == null) return null; else return this.getType().getName(); } // ino.end // ino.method.get_Block.23536.definition public Block get_Block() // ino.end // ino.method.get_Block.23536.body { return block; } // ino.end // ino.method.setReturnType.23539.defdescription type=javadoc /** *
* Author: Jrg Buerle * * @param type */ // ino.end // ino.method.setReturnType.23539.definition private void setReturnType(Type type) // ino.end // ino.method.setReturnType.23539.body { this.returntype = type; } // ino.end // ino.method.set_Block.23542.definition public void set_Block(Block blo) // ino.end // ino.method.set_Block.23542.body { if (blo.getType() == null) blo.setType(this.returntype); this.block = blo; } // ino.end // ino.method.set_Modifiers.23545.definition public void set_Modifiers(Modifiers modif) // ino.end // ino.method.set_Modifiers.23545.body { declid.firstElement().set_Modifiers(modif); // this.modi = modif; } // ino.end // ino.method.set_ExceptionList.23548.definition public void set_ExceptionList(ExceptionList exlist) // ino.end // ino.method.set_ExceptionList.23548.body { this.exceptionlist = exlist; } // ino.end // ino.method.setParameterList.23551.definition public void setParameterList(ParameterList paralist) // ino.end // ino.method.setParameterList.23551.body { this.parameterlist = paralist; } // ino.end // ino.method.getParameterList.23554.definition public ParameterList getParameterList() // ino.end // ino.method.getParameterList.23554.body { // otth: gibt die Parameterliste zurueck return this.parameterlist; } // ino.end // ino.method.getParameterCount.23557.defdescription type=javadoc /** * Author: Jrg Buerle
* * @return Die Anzahl der Methoden-Paramater */ // ino.end // ino.method.getParameterCount.23557.definition public int getParameterCount() // ino.end // ino.method.getParameterCount.23557.body { if (this.getParameterList() == null) return 0; else return this.getParameterList().getParameterCount(); } // ino.end // ino.method.get_ExceptionList.23560.definition public ExceptionList get_ExceptionList() // ino.end // ino.method.get_ExceptionList.23560.body { // otth: gibt die Exceptionliste zurueck return this.exceptionlist; } // ino.end // ino.method.getOverloadedID.23563.definition public int getOverloadedID() // ino.end // ino.method.getOverloadedID.23563.body { return (overloadedID); } // ino.end // ino.method.setOverloadedID.23566.definition public void setOverloadedID(int overloadedID) // ino.end // ino.method.setOverloadedID.23566.body { this.overloadedID = overloadedID; } // ino.end // ino.method.get_Method_Name.23575.definition public String get_Method_Name() // ino.end // ino.method.get_Method_Name.23575.body { DeclId hilf = declid.elementAt(0); return hilf.get_Name(); } // ino.end // ino.method.get_Type_Paralist.23578.definition public Menge get_Type_Paralist() // ino.end // ino.method.get_Type_Paralist.23578.body { return types_in_parameterlist; } // ino.end // ino.method.getLineNumber.23584.definition public int getLineNumber() // ino.end // ino.method.getLineNumber.23584.body { return m_LineNumber; } // ino.end // ino.method.setLineNumber.23587.definition public void setLineNumber(int lineNumber) // ino.end // ino.method.setLineNumber.23587.body { m_LineNumber = lineNumber; } // ino.end // ino.method.getOffset.23590.defdescription type=line // hinzugef�gt hoth: 07.04.2006 // ino.end // ino.method.getOffset.23590.definition public int getOffset() // ino.end // ino.method.getOffset.23590.body { return m_Offset; } // ino.end // ino.method.getVariableLength.23593.definition public int getVariableLength() // ino.end // ino.method.getVariableLength.23593.body { return get_Method_Name().length(); } // ino.end // ino.method.setOffset.23596.defdescription type=line // hinzugef�gt hoth: 07.04.2006 // ino.end // ino.method.setOffset.23596.definition public void setOffset(int Offset) // ino.end // ino.method.setOffset.23596.body { m_Offset = Offset; } // ino.end // ino.method.getTypeLineNumber.23602.defdescription type=javadoc /** *
* Author: Jrg Buerle * * @return */ // ino.end // ino.method.getTypeLineNumber.23602.definition public int getTypeLineNumber() // ino.end // ino.method.getTypeLineNumber.23602.body { return this.getLineNumber(); } // ino.end // ino.method.toString.23605.defdescription type=javadoc /** *
* Author: Martin Pl�micke * * @return */ // ino.end // ino.method.toString.23605.definition public String toString() // ino.end // ino.method.toString.23605.body { return this.getType() + " " + this.get_Name() + ((block != null) ? block.toString() : ""); } // ino.end // ino.method.setAbstract.23608.defdescription type=javadoc /** * Legt fuer die ByteCodeGen fest, ob Bytecode innerhalb der Methode * generiert wird. */ // ino.end // ino.method.setAbstract.23608.definition public void setAbstract(boolean b) // ino.end // ino.method.setAbstract.23608.body { isAbstract = b; } // ino.end // ino.method.isAbstract.23611.defdescription type=javadoc /** * Gibt zurueck, ob ByteCode innerhabl der Methode generiert wird. */ // ino.end // ino.method.isAbstract.23611.definition public boolean isAbstract() // ino.end // ino.method.isAbstract.23611.body { return isAbstract; } @Override public void wandleRefTypeAttributes2GenericAttributes( Menge classParalist) { /* * Menge paralist = new Menge();//Mit den Generischen Typen * der Methode paralist.addAll(classParalist); * paralist.addAll(this.genericMethodParameters); * * // Zuerst Returntype untersuchen Type returnType=getType(); Type * pendantReturnType = null; if(returnType instanceof * RefType)pendantReturnType = * ((RefType)returnType).findGenericType(paralist, new * Menge()); //GenericTypeVar * pendantReturnType=ClassHelper.findGenericType(returnType, * paralist,genericMethodParameters); if(pendantReturnType!=null){ * //Wenn generisch, dann modifizieren setReturnType(pendantReturnType); * } * * // Dann parameterlist untersuchen for(int * par=0;par()); //GenericTypeVar * pendantPara=ClassHelper.findGenericType * (fpType,paralist,genericMethodParameters); if(pendantPara!=null){ * //Wenn generisch, dann modifizieren fp.setType(pendantPara); } } * * // Zuletzt alle Lokalen Variablendeklarationen durchgehen * if(block!=null){ * block.wandleRefTypeAttributes2GenericAttributes(paralist * ,genericMethodParameters); } */ } public void set_Method_Name(String string) { if (declid.size() == 0) declid.add(0, new DeclId(string)); declid.set(0, new DeclId(string)); } public ConstraintsSet TYPE(TypeAssumptions ass) { ConstraintsSet ret = new ConstraintsSet(); TypeAssumptions localAss = new TypeAssumptions(); localAss.add(ass); // Die globalen Assumptions anhängen // Generische Parameterdeklarationen den Assumptions anfügen: for (GenericTypeVar gtv : this.getGenericParameter()) { localAss.add(gtv.createAssumptions()); } for (GenericTypeVar gtv : this.getGenericParameter()) { ret.add(gtv.TYPE(localAss)); } // TypeCheck, falls es sich um einen RefType handelt: this.returntype = this.returntype.checkTYPE(localAss, this); /* * if(this.returntype!=null && (this.returntype instanceof RefType)&& * !(this.returntype instanceof mycompiler.mytype.Void)){//Sonderfall * der Methode: Ihr Typ darf Void definiert werden. Type replaceType = * null; replaceType = ass.getTypeFor((RefType)this.returntype); * if(replaceType == null)throw new * TypeinferenceException("Der Typ "+this * .getType().getName()+" ist nicht korrekt",this); this.returntype = * replaceType; } */ // Die Parameter zu den Assumptions hinzufügen: if (this.parameterlist != null) for (FormalParameter param : this.parameterlist) { param.setType(param.getType().checkTYPE(localAss, this)); /* * if(param.getType() instanceof RefType) { Type replaceType = * null; replaceType = ass.getTypeFor((RefType)param.getType()); * if(replaceType == null) throw new * TypeinferenceException("Der Typ " * +param.getType().getName()+" ist nicht korrekt",param); * param.setType(replaceType); } */ localAss.addAssumption(new ParameterAssumption(param)); } ret.add(this.block.TYPEStmt(localAss)); // eine Verknüpfung mit der Type Assumption aus dem Assumption Set // und dem ermittelten Typ der Methode: ret.add(new SingleConstraint(this.block.getType().TYPE(localAss, this), this.returntype.TYPE(localAss, this))); return ret; } /** * @author Andreas Stadelmeier, a10023 * @return die TypInformationen der Statements dieser Methode. */ public String getTypeInformation() { if (this.parameterlist != null) return "Methode " + this.get_Name() + " Parameter: " + this.parameterlist.getTypeInformation() + ", Block: " + this.block.getTypeInformation(); return "Methode " + this.get_Name() + " : " + this.getType() + ", Block: " + this.block.getTypeInformation(); } @Override public JavaCodeResult printJavaCode(ResultSet resultSet) { JavaCodeResult ret = new JavaCodeResult(); ret.attach(this.getType().printJavaCode(resultSet)).attach(" ") .attach(this.get_Method_Name()).attach("(") .attach(this.getParameterList().printJavaCode(resultSet)) .attach(")\n"); ret.attach(this.block.printJavaCode(resultSet)); return ret; } /** * Liefert die MethodAssumption zu dieser Methode */ @Override public TypeAssumptions createTypeAssumptions(Class classmember) { Class parentClass = classmember;// this.getParentClass(); TypeAssumptions ret = new TypeAssumptions(); ret.addAssumption(new MethodAssumption(this, parentClass)); return ret; /* * TypeAssumptions assumptions = new TypeAssumptions(); this.assumedType * = null; //if((this.get_Method_Name().equals(classmember.getName()) || * this.get_Method_Name().equals("")) && * ((this.getType().equals(new mycompiler.mytype.Void(0))) || * this.getType() instanceof TypePlaceholder)){ * if((this.get_Method_Name().equals(classmember.getName()) || * this.get_Method_Name().equals(""))) { * this.set_Method_Name(""); this.assumedType = new * RefType(classmember.getName(),0); * this.setReturnType(this.assumedType); this.assumedType = new * RefType("void",0); //Return constructorReturnStatement = new * Return(0,0); //constructorReturnStatement.retexpr = * //this.block.statements.add(constructorReturnStatement); } //hoth: * 06.04.2006 //durchlaufe Block und suche nach Objektvariablen fuer * Offset-Markierung Iterator fieldVarIterator = * assumptions.iterator(); while (fieldVarIterator.hasNext()) { //Wenn * ObjektVariable CTypeAssumption dieAssum = fieldVarIterator.next(); * if(dieAssum instanceof CInstVarTypeAssumption) { * Class.isFirstLocalVarDecl=false; if(this.get_Block() != null) * this.get_Block * ().addOffsetsToAssumption(dieAssum,dieAssum.getIdentifier(),true); } * } * * //methodList.addElement(method); * * //F�r V_fields_methods: CMethodTypeAssumption methodAssum * = new CMethodTypeAssumption(classmember.getType(), * this.get_Method_Name(), this.getType(), * this.getParameterCount(),this.getLineNumber(),this.getOffset(),new * Menge(),this.getGenericMethodParameters()); // Typannahme * bauen... * * * //Methode in V_Fields_methods ablegen //Dabei wird die * OverloadedMethodID ermittelt !! //=> Method setzenuct * * * assumptions.add(methodAssum); * this.setOverloadedID(methodAssum.getHashSetKey * ().getOverloadedMethodID()); * * * //F�r die V_i: CTypeAssumptionSet localAssum = new * CTypeAssumptionSet(); * * //Bauen... ParameterList parameterList = this.getParameterList(); * if(parameterList!=null){ for(int i=0; * i()); //fuege Offsets fuer Parameter hinzu, hoth: * 06.04.2006 Class.isFirstLocalVarDecl=false; * * if(this.get_Block() != null) * this.get_Block().addOffsetsToAssumption(paraAssum * ,paraAssum.getIdentifier(),true); * * methodAssum.addParaAssumption(paraAssum); * * // F�r die V_i: CLocalVarTypeAssumption varAssum = new * CLocalVarTypeAssumption(classmember.getName(), * this.get_Method_Name(), this.getParameterCount(), * this.getOverloadedID(),"1", para.get_Name(),para.getType(), * para.getLineNumber(),para.getOffset(),new Menge()); * localAssum.addElement(varAssum); * //rememberLocals.addElement(varAssum); } } //...und * hinzuf�gen: * * assumptions.add(localAssum);//Assumptions für lokale Variablen den * Assumptions hinzufügen * * //Hier wird der Typ der als Assumption eingetragen wird in die * Variable assumedType dieser Klasse geschrieben: if(this.assumedType * == null) // Falls der Typ nicht schon gesetzt ist. Das ist der Fall, * falls die Methode ein Konstruktor ist this.assumedType = * methodAssum.getAssumedType(); * * return assumptions; */ } @Override public void parserPostProcessing(SyntaxTreeNode parent) { if (this.getType() == null) this.setType(TypePlaceholder.fresh(this)); // Bei dem Elterntyp der Methode darf es sich nur um eine Klasse // handeln, daher Cast ohne Prüfung: // Class parentClass = (Class)parent; if (this.returntype == null) this.returntype = TypePlaceholder.fresh(this); super.parserPostProcessing(parent); /* * this.returntype.parserPostProcessing(this); if(this.parameterlist != * null){ for(FormalParameter fp : this.parameterlist){ * fp.parserPostProcessing(this); } } for(GenericTypeVar gtv : * this.getGenericParameter()){ gtv.parserPostProcessing(this); } */ } @Override public Menge getChildren() { Menge ret = new Menge(); ret.add(this.block); ret.add(this.parameterlist); ret.addAll(this.getGenericParameter()); ret.add(this.returntype); return ret; } @Override public void setType(Type t) { // Methode und Block teilen sich einen ReturnType: // this.block.setType(t); this.returntype = t; this.returntype.parent = this; // TODO: Dieser Hack sollte nicht // nötig sein. (Parser ändern) } /** * Der Typ einer Methode ist ihr Returntype */ @Override public Type getType() { // Methode und Block teilen sich einen ReturnType: return this.returntype; } public static Method createEmptyMethod(Block withBlock, String withSignature, Class parent) { Method ret = Method.createEmptyMethod(withSignature, parent); ret.set_Block(withBlock); return ret; } public static Method createEmptyMethod(String withSignature, Class parent) { Method ret = new Method(0); DeclId DImethod = new DeclId(); DImethod.set_Name(withSignature); ret.set_DeclId(DImethod); Block tempBlock = new Block(); // tempBlock.setType(new RefType(parent.getName(),0)); ret.set_Block(tempBlock); ret.parserPostProcessing(parent); return ret; } @Override public boolean equals(Object obj) { if (!(obj instanceof Method)) return false; Method equals = (Method) obj; if ((this.returntype != null && equals.returntype == null)) return false; if ((this.returntype == null && equals.returntype != null)) return false; if (this.returntype != null && equals.returntype != null) if (!this.returntype.equals(equals.returntype)) return false; if (!this.parameterlist.equals(equals.parameterlist)) return false; return super.equals(obj); } @Override public void genByteCode(ClassGen cg) { /*ConstantPoolGen _cp = cg.getConstantPool(); * InstructionFactory _factory = new InstructionFactory(cg, _cp); * InstructionList il = new InstructionList(); * Class parentClass = this.getParentClass(); */ //oben steht MethodGen method als Variable (Z. 71) // �ber Statements iterieren um Block abzurufen for (Statement statements : block.get_Statement()) { statements.genByteCode(cg); } } } // ino.end