JavaPatternMatching/src/de/dhbwstuttgart/syntaxtree/statement/LambdaExpression.java

221 lines
8.1 KiB
Java
Raw Normal View History

2014-09-02 08:33:54 +00:00
package de.dhbwstuttgart.syntaxtree.statement;
2013-10-18 11:33:46 +00:00
import java.util.Hashtable;
import java.util.Vector;
2014-09-04 14:35:44 +00:00
import de.dhbwstuttgart.bytecode.ClassFile;
import de.dhbwstuttgart.bytecode.CodeAttribute;
import de.dhbwstuttgart.myexception.CTypeReconstructionException;
import de.dhbwstuttgart.myexception.JVMCodeException;
import de.dhbwstuttgart.myexception.SCStatementException;
2014-09-02 08:33:54 +00:00
import de.dhbwstuttgart.syntaxtree.Class;
import de.dhbwstuttgart.syntaxtree.ClassHelper;
import de.dhbwstuttgart.syntaxtree.FormalParameter;
import de.dhbwstuttgart.syntaxtree.Method;
import de.dhbwstuttgart.syntaxtree.ParameterList;
2014-09-04 14:35:44 +00:00
import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode;
2014-09-02 08:33:54 +00:00
import de.dhbwstuttgart.syntaxtree.type.DoubleType;
2014-12-05 16:11:22 +00:00
import de.dhbwstuttgart.syntaxtree.type.ExtendsWildcardType;
2014-09-02 08:33:54 +00:00
import de.dhbwstuttgart.syntaxtree.type.GenericTypeVar;
import de.dhbwstuttgart.syntaxtree.type.ObjectType;
2014-09-02 08:33:54 +00:00
import de.dhbwstuttgart.syntaxtree.type.RefType;
2015-01-04 18:30:37 +00:00
import de.dhbwstuttgart.syntaxtree.type.SuperWildcardType;
2014-09-02 08:33:54 +00:00
import de.dhbwstuttgart.syntaxtree.type.Type;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.syntaxtree.type.WildcardType;
2014-09-02 08:33:54 +00:00
import de.dhbwstuttgart.typeinference.ConstraintsSet;
import de.dhbwstuttgart.typeinference.FunN;
import de.dhbwstuttgart.typeinference.JavaCodeResult;
import de.dhbwstuttgart.typeinference.OderConstraint;
2014-09-02 08:33:54 +00:00
import de.dhbwstuttgart.typeinference.ResultSet;
import de.dhbwstuttgart.typeinference.SingleConstraint;
import de.dhbwstuttgart.typeinference.Typeable;
import de.dhbwstuttgart.typeinference.assumptions.ParameterAssumption;
import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions;
import de.dhbwstuttgart.typeinference.exceptions.TypeinferenceException;
import de.dhbwstuttgart.typeinference.unify.CSubstitutionSet;
2013-10-18 11:33:46 +00:00
/**
* @author A10023 - Andreas Stadelmeier
* Momentan erweitert LambdaExpression noch Expr und erbt dadurch auch von ExprStatement ist also auch ein Statement
*
* LambdaExpression Aufbau:
* ( ParameterList ) -> { method_body };
*/
public class LambdaExpression extends Expr{
private Block method_body;
private ParameterList params;
public LambdaExpression(int offset, int variableLength) {
super(offset, variableLength);
setParameterList(new ParameterList());//default is empty parameterlist
}
public void setBody(Block block){
method_body = block;
}
public void setExpr(Expr expression){
Block bl = new Block();
Return returnStmt = new Return(0, 0);
returnStmt.retexpr = expression;
bl.set_Statement(returnStmt);
this.setBody(bl);
}
public void setParameterList(ParameterList params){
ParameterList lambdaParameter = new ParameterList();
for(FormalParameter fp : params){
lambdaParameter.formalparameter.add(new LambdaParameter(fp));
}
this.params = lambdaParameter;
2013-10-18 11:33:46 +00:00
}
@Override
public void codegen(ClassFile classfile, CodeAttribute code, Vector paralist)
throws JVMCodeException {
// TODO Auto-generated method stub
}
@Override
public void wandleRefTypeAttributes2GenericAttributes(
Vector<Type> paralist,
Vector<GenericTypeVar> genericMethodParameters) {
Block block = this.method_body;
// Zuerst Returntype untersuchen
Type returnType=getType();
Type pendantReturnType = null;
if(returnType instanceof RefType)
pendantReturnType = ((RefType)returnType).findGenericType(paralist, new Vector<GenericTypeVar>());
//GenericTypeVar pendantReturnType=ClassHelper.findGenericType(returnType, paralist,genericMethodParameters);
if(pendantReturnType!=null){ //Wenn generisch, dann modifizieren
setType(pendantReturnType);
}
// Dann parameterlist untersuchen
for(FormalParameter fp : params){
Type fpType=fp.getType();
// Nur wenn es sich um ein RefType-Field handelt
Type pendantPara = null;
if(fpType instanceof RefType)
pendantPara = ((RefType)fpType).findGenericType(paralist, new Vector<GenericTypeVar>());
//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);
}
2013-10-18 11:33:46 +00:00
}
@Override
public String get_Name() {
// TODO Auto-generated method stub
return null;
}
/**
* Spezifikation:
*
* TYPEExpr( Ass, Lambda( (x1 , . . . , xN ), expr|stmt ) ) =
* let
* AssArgs = { xi : ai | ai fresh type variables }
* (exprt : rty, ConS) = TYPEExpr( Ass AssArgs, expr )
* | (stmtt : rty, ConS) = TYPEStmt( Ass u AssArgs, stmt )
* in
* (Lambda( (x1 : a1 , . . . , xN : aN ), exprt : rty|stmtt : rty ) : a,
* ConS { (FunN<rty, a1 , . . . , aN > a) }),
* where a is a fresh type variable
*/
@Override
public ConstraintsSet TYPEExpr(TypeAssumptions assumptions) {
ConstraintsSet ret = new ConstraintsSet();
//Die Assumptions für die Parameter der LambdaExpression
2014-03-18 19:18:57 +00:00
TypeAssumptions ArgumentAssumptions = new TypeAssumptions(this.getParentClass().getName());
2013-10-18 11:33:46 +00:00
Vector<Type> paramTypes = new Vector<Type>();
for(FormalParameter param : params.formalparameter){
if(param.getType()==null)param.setType(TypePlaceholder.fresh(this));
2013-10-18 11:33:46 +00:00
int offset = 0;
//Jeder Parameter der LambdaExpression wird als CParaTypeAssumption der Assumption liste hinzugefügt:
2014-04-09 12:12:55 +00:00
ArgumentAssumptions.addAssumption(new ParameterAssumption(param));
paramTypes.add(param.getType());
2013-10-18 11:33:46 +00:00
}
this.setType(TypePlaceholder.fresh(this));
2013-10-18 11:33:46 +00:00
//ArgumentAssumptions + assumptions ergeben die Assumptions für die Statements innerhalb des Lambda-Bodys:
ret.add(method_body.TYPEStmt(ArgumentAssumptions.add(assumptions))); //Es gibt die LambdaExpression nur mit einem Block als Method Body, nicht mit einer einzelnen Expression
2014-12-05 16:11:22 +00:00
//Die Constraints für ParameterTypen und Ret Typ erstellen:
Vector<Type> modifiedParamTypes = new Vector<>();
2015-01-04 18:30:37 +00:00
for(Type pT : paramTypes){
if(pT instanceof WildcardType){
//Auf Typfehler kontrollieren. Siehe Bug #12 Kommentar 3
if(pT instanceof ExtendsWildcardType){
throw new TypeinferenceException("Typfehler von Parametertyp "+pT,this);
}else{
modifiedParamTypes.add(pT);
}
}else{
modifiedParamTypes.add(new SuperWildcardType((ObjectType) pT));
}
2015-01-04 18:30:37 +00:00
}
2014-12-05 16:11:22 +00:00
Type retType = method_body.getType();
// PN < TPH PN
if(retType instanceof WildcardType){
//Auf Typfehler kontrollieren. Siehe Bug #12 Kommentar 3
if(retType instanceof SuperWildcardType){
throw new TypeinferenceException("Typfehler von Parametertyp "+retType,this);
}else{
//retType bleibt unverändert
}
}else{
retType = new ExtendsWildcardType((ObjectType) retType);
}
2015-01-04 18:30:37 +00:00
ret.add(new SingleConstraint(new FunN(retType, modifiedParamTypes).TYPE(assumptions, this),this.getType().TYPE(assumptions, this)));
2013-10-18 11:33:46 +00:00
return ret;
}
@Override
public ConstraintsSet TYPEStmt(TypeAssumptions ass){
2014-04-15 12:56:20 +00:00
throw new TypeinferenceException("Eine LambdaExpression darf nicht als Statement verwendet werden.", this);
2013-10-18 11:33:46 +00:00
}
@Override
public String getTypeInformation(){
return this.getType().toString()+" :: ("+this.params.getTypeInformation()+ ") -> " +this.method_body.getTypeInformation();
2013-10-18 11:33:46 +00:00
}
@Override
public String toString(){
//return "LambdaExpression, Parameter: "+this.params+ ", Body: " +this.method_body;
return this.getType() + " (("+this.params+ ") -> "+this.method_body + ")";
}
@Override
public JavaCodeResult printJavaCode(ResultSet resultSet){
JavaCodeResult ret = new JavaCodeResult();
ret.attach( "(").attach(this.params.printJavaCode(resultSet)).attach(")");
ret.attach( " -> ").attach( this.method_body.printJavaCode(resultSet));
return ret;
}
2014-02-22 03:58:49 +00:00
@Override
public Vector<SyntaxTreeNode> getChildren() {
Vector<SyntaxTreeNode> ret = new Vector<SyntaxTreeNode>();
ret.add(this.method_body);
for(FormalParameter fp : this.params)ret.add(fp);
2014-02-22 03:58:49 +00:00
return ret;
}
2013-10-18 11:33:46 +00:00
}