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 ;
2015-06-16 12:58:27 +00:00
import org.apache.bcel.generic.ClassGen ;
import de.dhbwstuttgart.typeinference.Menge ;
2014-09-04 14:35:44 +00:00
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-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 ;
2015-03-10 11:33:52 +00:00
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 ;
2015-03-12 11:27:43 +00:00
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 ;
2015-03-12 11:27:43 +00:00
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 ;
2014-09-05 09:49:31 +00:00
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 ) {
2014-04-23 13:19:56 +00:00
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 wandleRefTypeAttributes2GenericAttributes (
2015-04-22 19:40:22 +00:00
Menge < Type > paralist ,
Menge < GenericTypeVar > genericMethodParameters ) {
2014-03-27 15:43:07 +00:00
Block block = this . method_body ;
// Zuerst Returntype untersuchen
Type returnType = getType ( ) ;
2014-04-14 16:05:24 +00:00
Type pendantReturnType = null ;
if ( returnType instanceof RefType )
2015-04-22 19:40:22 +00:00
pendantReturnType = ( ( RefType ) returnType ) . findGenericType ( paralist , new Menge < GenericTypeVar > ( ) ) ;
2014-04-14 16:05:24 +00:00
//GenericTypeVar pendantReturnType=ClassHelper.findGenericType(returnType, paralist,genericMethodParameters);
2014-03-27 15:43:07 +00:00
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
2014-04-14 16:05:24 +00:00
Type pendantPara = null ;
if ( fpType instanceof RefType )
2015-04-22 19:40:22 +00:00
pendantPara = ( ( RefType ) fpType ) . findGenericType ( paralist , new Menge < GenericTypeVar > ( ) ) ;
2014-04-14 16:05:24 +00:00
//GenericTypeVar pendantPara=ClassHelper.findGenericType(fpType,paralist,genericMethodParameters);
2014-03-27 15:43:07 +00:00
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 }
2015-05-12 17:49:27 +00:00
* ( exprt : rty , ConS ) = TYPEExpr ( Ass à ¢  ª AssArgs , expr )
2013-10-18 11:33:46 +00:00
* | ( stmtt : rty , ConS ) = TYPEStmt ( Ass u AssArgs , stmt )
* in
* ( Lambda ( ( x1 : a1 , . . . , xN : aN ) , exprt : rty | stmtt : rty ) : a ,
2015-05-12 17:49:27 +00:00
* ConS à ¢  ª { ( FunN < rty , a1 , . . . , aN > a ) } ) ,
2013-10-18 11:33:46 +00:00
* where a is a fresh type variable
* /
@Override
public ConstraintsSet TYPEExpr ( TypeAssumptions assumptions ) {
ConstraintsSet ret = new ConstraintsSet ( ) ;
2015-05-12 17:49:27 +00:00
//Die Assumptions fà ¼r die Parameter der LambdaExpression
2014-03-18 19:18:57 +00:00
TypeAssumptions ArgumentAssumptions = new TypeAssumptions ( this . getParentClass ( ) . getName ( ) ) ;
2015-04-22 19:40:22 +00:00
Menge < Type > paramTypes = new Menge < Type > ( ) ;
2013-10-18 11:33:46 +00:00
for ( FormalParameter param : params . formalparameter ) {
2014-02-11 15:30:38 +00:00
if ( param . getType ( ) = = null ) param . setType ( TypePlaceholder . fresh ( this ) ) ;
2013-10-18 11:33:46 +00:00
int offset = 0 ;
2015-05-12 17:49:27 +00:00
//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 ) ) ;
2014-02-11 15:30:38 +00:00
paramTypes . add ( param . getType ( ) ) ;
2013-10-18 11:33:46 +00:00
}
2014-02-11 15:30:38 +00:00
this . setType ( TypePlaceholder . fresh ( this ) ) ;
2015-05-12 17:49:27 +00:00
//ArgumentAssumptions + assumptions ergeben die Assumptions fà ¼r die Statements innerhalb des Lambda-Bodys:
2013-10-18 11:33:46 +00:00
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
2015-05-12 17:49:27 +00:00
//Die Constraints fà ¼r ParameterTypen und Ret Typ erstellen:
2015-04-22 19:40:22 +00:00
Menge < Type > modifiedParamTypes = new Menge < > ( ) ;
2015-01-04 18:30:37 +00:00
for ( Type pT : paramTypes ) {
2015-03-12 11:27:43 +00:00
if ( pT instanceof WildcardType ) {
2015-03-31 10:37:45 +00:00
//Auf Typfehler kontrollieren. Siehe Bug #12 Kommentar 3
if ( pT instanceof ExtendsWildcardType ) {
throw new TypeinferenceException ( " Typfehler von Parametertyp " + pT , this ) ;
} else {
modifiedParamTypes . add ( pT ) ;
}
2015-03-12 11:27:43 +00:00
} else {
2015-03-31 10:37:45 +00:00
modifiedParamTypes . add ( new SuperWildcardType ( ( ObjectType ) pT ) ) ;
2015-03-12 11:27:43 +00:00
}
2015-01-04 18:30:37 +00:00
}
2014-12-05 16:11:22 +00:00
Type retType = method_body . getType ( ) ;
2015-03-11 11:39:08 +00:00
// PN < TPH PN
2015-03-12 11:27:43 +00:00
if ( retType instanceof WildcardType ) {
2015-03-31 10:37:45 +00:00
//Auf Typfehler kontrollieren. Siehe Bug #12 Kommentar 3
if ( retType instanceof SuperWildcardType ) {
throw new TypeinferenceException ( " Typfehler von Parametertyp " + retType , this ) ;
} else {
2015-05-12 17:49:27 +00:00
//retType bleibt unverà ¤ndert
2015-03-31 10:37:45 +00:00
}
} else {
retType = new ExtendsWildcardType ( ( ObjectType ) retType ) ;
2015-03-12 11:27:43 +00:00
}
2015-01-04 18:30:37 +00:00
2015-03-31 10:37:45 +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 ( ) {
2014-02-11 15:30:38 +00:00
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
2015-04-22 19:40:22 +00:00
public Menge < SyntaxTreeNode > getChildren ( ) {
Menge < SyntaxTreeNode > ret = new Menge < SyntaxTreeNode > ( ) ;
2014-02-22 03:58:49 +00:00
ret . add ( this . method_body ) ;
2014-04-16 14:02:16 +00:00
for ( FormalParameter fp : this . params ) ret . add ( fp ) ;
2014-02-22 03:58:49 +00:00
return ret ;
}
2015-06-16 12:58:27 +00:00
@Override
public void genByteCode ( ClassGen _cg ) {
// TODO Auto-generated method stub
}
2013-10-18 11:33:46 +00:00
}