forked from JavaTX/JavaCompilerCore
210 lines
7.5 KiB
Java
210 lines
7.5 KiB
Java
package de.dhbwstuttgart.syntaxtree;
|
||
|
||
import org.apache.bcel.Constants;
|
||
import org.apache.bcel.classfile.ConstantPool;
|
||
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.bytecode.ClassGenerator;
|
||
import de.dhbwstuttgart.bytecode.DHBWConstantPoolGen;
|
||
import de.dhbwstuttgart.bytecode.DHBWInstructionFactory;
|
||
import de.dhbwstuttgart.bytecode.MethodGenerator;
|
||
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.TypeinferenceResultSet;
|
||
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();
|
||
|
||
MethodGenerator method = new MethodGenerator(Constants.ACC_PUBLIC, this.getType().getBytecodeType(cg, null), this.parameterlist.getBytecodeTypeList(cg,null) , this.parameterlist.getParameterNameArray(), "<init>", parentClass.name, il, _cp);
|
||
|
||
//FieldInitializations an Block anfügen
|
||
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");
|
||
}
|
||
|
||
//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));
|
||
}
|
||
|
||
/**
|
||
* 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, TypeinferenceResultSet rs){
|
||
return il;
|
||
}
|
||
}
|
||
|
||
@Override
|
||
public void genByteCode(ClassGenerator cg, Class classObj) {
|
||
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("<init>");
|
||
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("<init>", this.get_codegen_Param_Type(paralist), this.getParameterList(), null, get_Block(), declid.firstElement().get_access_flags(), paralist, false);
|
||
}
|
||
// ino.end
|
||
|
||
}
|
||
*/
|