package de.dhbwstuttgart.syntaxtree; import org.apache.bcel.Constants; import org.apache.bcel.generic.InstructionList; import de.dhbwstuttgart.bytecode.ClassGenerator; import de.dhbwstuttgart.bytecode.DHBWConstantPoolGen; import de.dhbwstuttgart.bytecode.MethodGenerator; import de.dhbwstuttgart.typecheck.JavaClassName; import de.dhbwstuttgart.syntaxtree.statement.Block; import de.dhbwstuttgart.syntaxtree.statement.SuperCall; import de.dhbwstuttgart.syntaxtree.type.GenericTypeVar; import de.dhbwstuttgart.syntaxtree.type.Type; import de.dhbwstuttgart.typeinference.TypeinferenceResults; import de.dhbwstuttgart.typeinference.assumptions.ConstructorAssumption; import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions; import de.dhbwstuttgart.typeinference.exceptions.DebugException; 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_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().get(0) 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 = classmember; 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 MethodGenerator method = new MethodGenerator(Constants.ACC_PUBLIC, this.getType().getBytecodeType(cg, null), this.parameterlist.getBytecodeTypeList(cg,null) , this.parameterlist.getParameterNameArray(), "", cg.getClassName(), il, _cp); //FieldInitializations an Block anfügen Block block = this.get_Block(); if(! (block.statements.get(0) instanceof SuperCall)){ throw new DebugException("Fehlender SuperCall im Konstruktor"); } //method.setMaxStack(); //Die Stack Größe automatisch berechnen lassen (erst nach dem alle Instructions angehängt wurden) cg.addMethod(method.createMethod(cg, getParameterList(), this.getType(), get_Block(), null)); } @Override public void genByteCode(ClassGenerator cg, Class classObj, TypeinferenceResults resultSets) { 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 JavaClassName getTypeName() { return this.getType().getName(); } }