package de.dhbwstuttgart.syntaxtree; import org.apache.commons.bcel6.Constants; import org.apache.commons.bcel6.classfile.ConstantPool; 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.typeinference.Menge; import de.dhbwstuttgart.bytecode.ClassGenerator; import de.dhbwstuttgart.bytecode.DHBWConstantPoolGen; import de.dhbwstuttgart.bytecode.DHBWInstructionFactory; import de.dhbwstuttgart.myexception.JVMCodeException; 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.SuperCall; 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.assumptions.ConstructorAssumption; import de.dhbwstuttgart.typeinference.assumptions.MethodAssumption; import de.dhbwstuttgart.typeinference.assumptions.ParameterAssumption; import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions; import de.dhbwstuttgart.typeinference.exceptions.DebugException; import de.dhbwstuttgart.typeinference.exceptions.TypeinferenceException; import de.dhbwstuttgart.typeinference.typedeployment.TypeInsertPoint; import de.dhbwstuttgart.typeinference.typedeployment.TypeInsertSet; import de.dhbwstuttgart.syntaxtree.type.Void; public class Constructor extends Method { /** * Parser kann nicht zwischen einem Konstruktor und einer Methode unterscheiden. * Diese Klasse beherbegt den als Methode geparsten Konstruktor und wandelt sein verhalten zu dem eines Konstruktors ab. */ public Constructor(Method methode, Class parent){ super(methode.get_Method_Name(), methode.getType(), methode.getParameterList(),methode.get_Block(), methode.getGenericDeclarationList(), methode.getOffset()); //Sicherstellen, dass das erste Statement in der Methode ein SuperCall ist: if(this.get_Block().get_Statement().size() <1 || ! (this.get_Block().get_Statement().firstElement() instanceof SuperCall)){ this.get_Block().statements.add(0, new SuperCall(this.get_Block())); this.parserPostProcessing(parent); } } @Override public TypeAssumptions createTypeAssumptions(Class classmember) { this.parent = classmember; Class parentClass = this.getParentClass(); TypeAssumptions ret = new TypeAssumptions(); ret.addAssumption(new ConstructorAssumption(this, parentClass)); return ret; } public void genByteCode(ClassGenerator cg, InstructionList fieldInitializations){ DHBWConstantPoolGen _cp = cg.getConstantPool(); InstructionList il = new InstructionList(); //sollte nicht new sein sondern aus Block kommen Class parentClass = this.getParentClass(); //TODO: Alles dynamisch gestalten //init darf nur drin stehen, wenn Konstruktor; this.method = new MethodGen(Constants.ACC_PUBLIC, this.getType().getBytecodeType(cg), org.apache.commons.bcel6.generic.Type.NO_ARGS , new String[] { }, "", parentClass.name, il, _cp); //Iteration �ber Block starten Block block = this.get_Block(); if(block.statements.firstElement() instanceof SuperCall){ block.statements.insertElementAt(new BytecodeInstructionBlock(fieldInitializations), 1); }else{ throw new DebugException("Fehlender SuperCall im Konstruktor"); } InstructionList blockInstructions = block.genByteCode(cg); il.append(blockInstructions); il.append(DHBWInstructionFactory.createReturn( org.apache.commons.bcel6.generic.Type.VOID)); //Konstruktor hat immer VOID Return type this.method.setMaxStack(); //Die Stack Größe automatisch berechnen lassen (erst nach dem alle Instructions angehängt wurden) cg.addMethod(this.method.getMethod()); } /** * Mit dieser Hilfsklasse kann eine beliebige InstructionList in eine vorhandenen Block als Statement eingefügt werden. * Wird für Bytecodegenerierung benötigt. */ private class BytecodeInstructionBlock extends Block{ InstructionList il; BytecodeInstructionBlock(InstructionList toInsert){ il = toInsert; } @Override public InstructionList genByteCode(ClassGenerator cg){ return il; } } @Override public void genByteCode(ClassGenerator cg) { this.genByteCode(cg, new InstructionList()); } // super statement muss drin sein // stmt genByteCode + im block genByteCode implementieren & dann Hierarchie ausprobieren // de.dhbw.systanxtree.stmts supercall // Aufrufhierarchie: Class->Felder->Konstruktor->Methode innerhalb Konstruktor->Block->Statements (in diesem Fall nur super())->hier wird bytecode f�r superaufruf generiert @Override public void parserPostProcessing(SyntaxTreeNode parent){ super.parserPostProcessing(parent); if(this.parameterlist != null){ for(FormalParameter fp : this.parameterlist){ fp.parserPostProcessing(this); } } for(GenericTypeVar gtv : this.getGenericParameter()){ gtv.parserPostProcessing(this); } } @Override public ConstraintsSet TYPE(TypeAssumptions ass) { //super.setType(this.getParentClass().getType()); super.setType(new Void(this, 0)); return super.TYPE(ass); } @Override public void setType(Type t) { super.setType(new Void(this, this.getOffset())); //throw new TypeinferenceException("Einem Konstruktor kann kein Typ zugewiesen werden", this); //this.methode.setType(t); } /*public Constructor(Method methode){ super(methode.getOffset()); this.methode = methode; this.setDeclIdMenge(methode.getDeclIdMenge()); this.methode.setType(this.methode.getParentClass().getType()); }*/ @Override public JavaClassName getTypeName() { return this.getType().getName(); } } /* // ino.class.Constructor.23267.declaration public class Constructor_Backup extends Method // ino.end // ino.class.Constructor.23267.body { // ino.method.Constructor.23271.definition public Constructor_Backup() // ino.end // ino.method.Constructor.23271.body { this.setParameterList(null); // #JB# 04.06.2005 // ########################################################### DeclId decl = new DeclId(); decl.set_Name(""); this.set_DeclId(decl); // ########################################################### } // ino.end // ino.method.get_codegen_Param_Type.23274.definition public String get_codegen_Param_Type(Menge paralist) // ino.end // ino.method.get_codegen_Param_Type.23274.body { String ret = new String(); if(this.getParameterList() == null) { ret += "()"; } else { ret += this.getParameterList().get_codegen_ParameterList(paralist); } ret += "V"; return ret; } // ino.end // ino.method.codegen.23277.definition public void codegen(ClassFile classfile, Menge paralist) throws JVMCodeException // ino.end // ino.method.codegen.23277.body { classfile.set_constructor_founded(true); classfile.add_method("", this.get_codegen_Param_Type(paralist), this.getParameterList(), null, get_Block(), declid.firstElement().get_access_flags(), paralist, false); } // ino.end } */