2014-09-02 08:33:54 +00:00
|
|
|
package de.dhbwstuttgart.syntaxtree;
|
2014-02-11 01:47:39 +00:00
|
|
|
|
2016-07-21 14:36:33 +00:00
|
|
|
import org.apache.bcel.generic.FieldGen;
|
|
|
|
import org.apache.bcel.generic.FieldInstruction;
|
|
|
|
import org.apache.bcel.generic.InstructionList;
|
|
|
|
import org.apache.bcel.generic.ObjectType;
|
|
|
|
import org.apache.bcel.Const;
|
|
|
|
import org.apache.bcel.generic.ClassGen;
|
2014-02-11 01:47:39 +00:00
|
|
|
|
2015-05-27 13:57:15 +00:00
|
|
|
import de.dhbwstuttgart.typeinference.Menge;
|
2015-09-02 15:11:32 +00:00
|
|
|
import de.dhbwstuttgart.bytecode.ClassGenerator;
|
2014-09-02 08:33:54 +00:00
|
|
|
import de.dhbwstuttgart.syntaxtree.statement.Expr;
|
2015-09-02 15:11:32 +00:00
|
|
|
import de.dhbwstuttgart.syntaxtree.statement.This;
|
2014-09-02 08:33:54 +00:00
|
|
|
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.OderConstraint;
|
|
|
|
import de.dhbwstuttgart.typeinference.ResultSet;
|
2015-11-27 15:10:35 +00:00
|
|
|
import de.dhbwstuttgart.typeinference.TypeinferenceResultSet;
|
2016-04-01 14:12:30 +00:00
|
|
|
import de.dhbwstuttgart.typeinference.UndConstraint;
|
2014-09-02 08:33:54 +00:00
|
|
|
import de.dhbwstuttgart.typeinference.assumptions.FieldAssumption;
|
|
|
|
import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions;
|
|
|
|
import de.dhbwstuttgart.typeinference.exceptions.TypeinferenceException;
|
2014-02-11 01:47:39 +00:00
|
|
|
|
2014-02-12 01:12:12 +00:00
|
|
|
/**
|
2015-05-12 17:49:27 +00:00
|
|
|
* Eine Feldinitialisation steht für eine Felddeklaration mit gleichzeitiger Wertzuweisung
|
2014-02-12 01:12:12 +00:00
|
|
|
* Beispiel: 'public Feld FeldVar = FeldWert;'
|
|
|
|
* @author janulrich
|
|
|
|
*
|
|
|
|
*/
|
2014-02-11 01:47:39 +00:00
|
|
|
public class FieldDeclaration extends Field{
|
|
|
|
|
2014-02-12 01:12:12 +00:00
|
|
|
private Expr wert;
|
2016-09-09 22:40:17 +00:00
|
|
|
private String name;
|
2014-02-11 01:47:39 +00:00
|
|
|
//private Type type;
|
2015-04-22 19:40:22 +00:00
|
|
|
//private Menge<GenericTypeVar> parameter;
|
2014-02-11 01:47:39 +00:00
|
|
|
|
2014-04-03 08:35:25 +00:00
|
|
|
/**
|
2015-05-12 17:49:27 +00:00
|
|
|
* Dieser Konstruktor der FieldDeclaration erstellt den Syntaxknoten vollständig.
|
|
|
|
* Kein nachträgliches hinzfügen von Informationen oder aufrufen von parserPostProcessing ist notwendig.
|
2014-04-03 08:35:25 +00:00
|
|
|
*/
|
|
|
|
public FieldDeclaration(String name, Type typ){
|
|
|
|
super(0);//Dieser Deklarator wird nicht vom Parser aufgerufen. Dadurch gibt es auch keinen Offset
|
2016-09-09 22:40:17 +00:00
|
|
|
this.typ = typ;
|
|
|
|
this.name = name;
|
2014-04-03 08:35:25 +00:00
|
|
|
}
|
|
|
|
|
2014-03-09 11:10:03 +00:00
|
|
|
public FieldDeclaration(int offset){
|
|
|
|
super(offset);
|
|
|
|
}
|
|
|
|
|
2014-02-11 01:47:39 +00:00
|
|
|
public void setWert(Expr initialExpression){
|
|
|
|
this.wert = initialExpression;
|
|
|
|
}
|
|
|
|
public Expr getWert(){
|
|
|
|
return this.wert;
|
|
|
|
}
|
|
|
|
|
2014-02-19 04:20:54 +00:00
|
|
|
public String getIdentifier(){
|
2016-09-09 22:40:17 +00:00
|
|
|
return name;
|
2014-02-11 01:47:39 +00:00
|
|
|
}
|
|
|
|
|
2014-02-12 01:12:12 +00:00
|
|
|
|
2014-02-11 01:47:39 +00:00
|
|
|
@Override
|
2014-02-12 01:12:12 +00:00
|
|
|
public String toString()
|
|
|
|
{
|
2014-03-17 16:55:55 +00:00
|
|
|
if(getWert()!=null)return super.toString() + "=" + getWert().toString();
|
|
|
|
return super.toString();
|
2014-02-12 01:12:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public JavaCodeResult printJavaCode(ResultSet resultSet) {
|
|
|
|
JavaCodeResult ret = new JavaCodeResult();
|
2014-02-19 04:20:54 +00:00
|
|
|
JavaCodeResult toAttach = this.getType().printJavaCode(resultSet).attach(" ").attach( this.getIdentifier());
|
2014-02-12 21:10:33 +00:00
|
|
|
if(this.wert!=null)toAttach.attach(" = ").attach(this.getWert().printJavaCode(resultSet) );
|
|
|
|
toAttach.attach( ";");
|
|
|
|
ret.attach(toAttach);
|
2014-02-12 01:12:12 +00:00
|
|
|
return ret;
|
2014-02-11 01:47:39 +00:00
|
|
|
}
|
2014-02-12 01:12:12 +00:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public TypeAssumptions createTypeAssumptions(Class classmember) {
|
|
|
|
//////////////////////////////
|
|
|
|
//Felder:
|
|
|
|
//////////////////////////////
|
|
|
|
TypeAssumptions assumptions = new TypeAssumptions();
|
|
|
|
/*
|
2015-05-12 17:49:27 +00:00
|
|
|
* Der Feld-Assumption muss ein TPH als Typ hinzugefügt werden, falls er Typlos initialisiert wurde. Dies kann auch der Type-Algorithmus der Inst/FieldVar - Klasse machen.
|
2014-02-12 01:12:12 +00:00
|
|
|
* Wird das Feld mit einem Typ initialisiert so muss dieser auch in die Assumptions.
|
|
|
|
*/
|
2014-04-15 12:56:20 +00:00
|
|
|
if(this.getType() == null)throw new TypeinferenceException("Der Typ eines Feldes darf nicht null sein", this);
|
2014-02-19 04:20:54 +00:00
|
|
|
//assumptions.add(TypeAssumptions.createFieldVarAssumption(classmember.getName(), this.getName(), this.getType()));
|
2014-04-09 12:12:55 +00:00
|
|
|
assumptions.addAssumption(new FieldAssumption(this,classmember));
|
2014-02-12 01:12:12 +00:00
|
|
|
return assumptions;
|
|
|
|
}
|
|
|
|
|
2014-02-11 01:47:39 +00:00
|
|
|
@Override
|
2015-04-22 19:40:22 +00:00
|
|
|
public Menge<SyntaxTreeNode> getChildren() {
|
|
|
|
Menge<SyntaxTreeNode> ret = super.getChildren();
|
2014-02-12 21:10:33 +00:00
|
|
|
if(this.wert!=null)ret.add(this.wert);
|
2014-02-12 01:12:12 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2014-02-12 21:10:33 +00:00
|
|
|
public int getVariableLength()
|
|
|
|
{
|
2016-09-09 22:40:17 +00:00
|
|
|
return name.length();
|
2014-02-12 21:10:33 +00:00
|
|
|
}
|
2016-09-09 22:40:17 +00:00
|
|
|
|
2014-02-12 21:10:33 +00:00
|
|
|
@Override
|
|
|
|
public ConstraintsSet TYPE(TypeAssumptions publicAssumptions) {
|
2014-08-28 16:42:40 +00:00
|
|
|
if(this.wert == null && (this.getType() == null || this.getType() instanceof TypePlaceholder))
|
2015-05-12 17:49:27 +00:00
|
|
|
throw new TypeinferenceException("Typlose Felder müssen mit Wert initialisiert werden", this);
|
2014-02-12 21:10:33 +00:00
|
|
|
ConstraintsSet ret = new ConstraintsSet();
|
2014-07-16 16:38:55 +00:00
|
|
|
TypeAssumptions localAssumptions = publicAssumptions.clone();
|
|
|
|
|
|
|
|
for(GenericTypeVar gp : this.getGenericParameter()){
|
|
|
|
localAssumptions.add(gp.createAssumptions());
|
|
|
|
}
|
|
|
|
|
|
|
|
for(GenericTypeVar gp : this.getGenericParameter()){
|
|
|
|
gp.TYPE(localAssumptions);
|
|
|
|
}
|
2014-04-15 12:56:20 +00:00
|
|
|
|
|
|
|
//TypeCheck, falls es sich um einen RefType handelt:
|
2016-09-09 22:40:17 +00:00
|
|
|
Type thisType = this.getType();
|
2014-04-15 12:56:20 +00:00
|
|
|
|
2016-04-01 14:12:30 +00:00
|
|
|
UndConstraint c1 = ConstraintsSet.createSingleConstraint(thisType, thisType);
|
2014-02-12 21:10:33 +00:00
|
|
|
ret.add(c1); //Damit die TypVariable des Felds in den Constraints auftaucht
|
|
|
|
|
|
|
|
if(this.wert!=null){
|
2015-05-12 17:49:27 +00:00
|
|
|
//Falls bei der Deklaration ein Wert zugewiesen wird, verhält sich das Constraintserzeugen wie bei dem Assign-Statement:
|
2014-07-16 16:38:55 +00:00
|
|
|
ret.add(this.wert.TYPEExpr(localAssumptions));
|
2016-04-01 14:12:30 +00:00
|
|
|
ret.add(ConstraintsSet.createSingleConstraint(this.wert.getType().TYPE(localAssumptions,this), thisType));
|
2014-02-12 21:10:33 +00:00
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
2014-02-11 01:47:39 +00:00
|
|
|
|
2015-09-02 15:11:32 +00:00
|
|
|
/**
|
|
|
|
* Das besondere bei genByteCode einer FieldDeclaration ist, dass ein InstructionList zurückgegeben wird.
|
|
|
|
* Dieser muss in jeden Konstruktor eingefügt werden um das Feld zu initialisieren.
|
|
|
|
* @param cg
|
|
|
|
* @return - Die InstructionList, welche das Feld initialisiert
|
|
|
|
*/
|
2015-11-27 15:10:35 +00:00
|
|
|
public InstructionList genByteCode(ClassGenerator cg, TypeinferenceResultSet rs) {
|
2015-09-02 15:11:32 +00:00
|
|
|
//Das Feld an die Klasse anfügen:
|
2016-04-07 12:53:29 +00:00
|
|
|
FieldGen field = new FieldGen(0, this.getType().getBytecodeType(cg, rs), this.getDescription(), cg.getConstantPool());
|
2015-11-27 15:10:35 +00:00
|
|
|
field.addAttribute(cg.getInstructionFactory().createSignatureAttribute(this.getType().getBytecodeSignature(cg, rs)));
|
2015-09-02 15:11:32 +00:00
|
|
|
cg.addField(field.getField());
|
2015-09-23 13:30:35 +00:00
|
|
|
|
|
|
|
//Die Felddekleration an den Konstruktor anhängen:
|
2015-09-02 15:11:32 +00:00
|
|
|
InstructionList il = new InstructionList();
|
2015-11-27 15:10:35 +00:00
|
|
|
il.append(new This(this).genByteCode(cg, rs));
|
2016-03-30 08:14:05 +00:00
|
|
|
|
|
|
|
if(wert != null){
|
|
|
|
il.append(this.wert.genByteCode(cg, rs));
|
|
|
|
}
|
|
|
|
|
2015-09-02 15:11:32 +00:00
|
|
|
FieldInstruction putFieldInstruction =
|
2016-09-16 11:25:20 +00:00
|
|
|
cg.getInstructionFactory().createFieldAccess(cg.getClassName(),
|
2016-06-22 18:29:16 +00:00
|
|
|
this.getDescription(), this.getType().getBytecodeType(cg, rs), Const.PUTFIELD);
|
2015-09-23 13:30:35 +00:00
|
|
|
il.append(putFieldInstruction );
|
2015-09-02 15:11:32 +00:00
|
|
|
return il;
|
2015-05-27 13:57:15 +00:00
|
|
|
}
|
2016-03-30 08:09:17 +00:00
|
|
|
|
2015-06-16 09:55:15 +00:00
|
|
|
/*@Override
|
|
|
|
public void genByteCode(ClassGen cg) {
|
|
|
|
// TODO Auto-generated method stub
|
|
|
|
|
|
|
|
}*/
|
|
|
|
|
2014-02-11 01:47:39 +00:00
|
|
|
}
|