Merge branch 'unifyOptimierung' into plugin

fixed	test/javFiles/Matrix.jav
This commit is contained in:
Martin Plümicke 2018-05-24 16:43:31 +02:00
commit 704415ae3b
40 changed files with 596 additions and 194 deletions

View File

@ -0,0 +1,30 @@
package de.dhbwstuttgart.bytecode;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import de.dhbwstuttgart.syntaxtree.statement.BinaryExpr;
import de.dhbwstuttgart.syntaxtree.statement.Expression;
public abstract class AStatement implements IStatement {
protected Expression expr;
public AStatement(Expression expr) {
this.expr = expr;
}
@Override
public boolean isExprBinary() {
return (expr instanceof BinaryExpr);
}
@Override
public void genBCForRelOp(MethodVisitor mv,Label branchLabel, Label endLabel, BytecodeGenMethod bytecodeGenMethod) {
mv.visitInsn(Opcodes.ICONST_1);
mv.visitJumpInsn(Opcodes.GOTO, endLabel);
mv.visitLabel(branchLabel);
mv.visitInsn(Opcodes.ICONST_0);
mv.visitLabel(endLabel);
}
}

View File

@ -0,0 +1,11 @@
package de.dhbwstuttgart.bytecode;
import de.dhbwstuttgart.syntaxtree.statement.Expression;
public class ArgumentExpr extends AStatement {
public ArgumentExpr(Expression expr) {
super(expr);
}
}

View File

@ -0,0 +1,11 @@
package de.dhbwstuttgart.bytecode;
import de.dhbwstuttgart.syntaxtree.statement.Expression;
public class AssignStmt extends AStatement {
public AssignStmt(Expression rightSide) {
super(rightSide);
}
}

View File

@ -17,6 +17,8 @@ import de.dhbwstuttgart.bytecode.descriptor.DescriptorToString;
import de.dhbwstuttgart.bytecode.descriptor.TypeToDescriptor; import de.dhbwstuttgart.bytecode.descriptor.TypeToDescriptor;
import de.dhbwstuttgart.bytecode.signature.Signature; import de.dhbwstuttgart.bytecode.signature.Signature;
import de.dhbwstuttgart.bytecode.signature.TypeToString; import de.dhbwstuttgart.bytecode.signature.TypeToString;
import de.dhbwstuttgart.bytecode.utilities.NormalConstructor;
import de.dhbwstuttgart.bytecode.utilities.NormalMethod;
import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal; import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal;
import de.dhbwstuttgart.syntaxtree.*; import de.dhbwstuttgart.syntaxtree.*;
import de.dhbwstuttgart.syntaxtree.statement.Literal; import de.dhbwstuttgart.syntaxtree.statement.Literal;
@ -115,7 +117,7 @@ public class BytecodeGen implements ASTVisitor {
boolean isConsWithNoParamsVisited = false; boolean isConsWithNoParamsVisited = false;
for(ResultSet rs : listOfResultSets) { for(ResultSet rs : listOfResultSets) {
resultSet = rs; resultSet = rs;
for(Constructor c : classOrInterface.getConstructors()) { for(Constructor c : classOrInterface.getConstructors()) {
if(!isConsWithNoParamsVisited) if(!isConsWithNoParamsVisited)
c.accept(this); c.accept(this);
@ -189,13 +191,13 @@ public class BytecodeGen implements ASTVisitor {
System.out.println(acc); System.out.println(acc);
/*Prüfe, ob die Rückgabe-Type der Methode eine Type-Variable ist*/ /*Prüfe, ob die Rückgabe-Type der Methode eine Type-Variable ist*/
boolean hasGenInParameterList = genericsAndBounds.containsKey(resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor())); boolean hasGenInParameterList = genericsAndBounds.containsKey(retType) || retType.subSequence(0, 4).equals("TPH ");
/*Wenn die Rückgabe-Type eine Typ-variable ist, erzeuge direkt die Signature, wenn nicht, /*Wenn die Rückgabe-Type eine Typ-variable ist, erzeuge direkt die Signature, wenn nicht,
* prüfe, ob einer der Parameter Typ-Variable als Typ hat*/ * prüfe, ob einer der Parameter Typ-Variable als Typ hat*/
if(!hasGenInParameterList) { if(!hasGenInParameterList) {
for(String paramName : methodParamsAndTypes.keySet()) { for(String paramName : methodParamsAndTypes.keySet()) {
String typeOfParam = methodParamsAndTypes.get(paramName).acceptTV(new TypeToDescriptor()); String typeOfParam = methodParamsAndTypes.get(paramName).acceptTV(new TypeToDescriptor());
if(genericsAndBounds.containsKey(typeOfParam)) { if(genericsAndBounds.containsKey(typeOfParam)||typeOfParam.substring(0, 4).equals("TPH ")) {
hasGenInParameterList = true; hasGenInParameterList = true;
break; break;
} }
@ -211,6 +213,7 @@ public class BytecodeGen implements ASTVisitor {
boolean hasGen = method.getGenerics().iterator().hasNext() || hasGenInParameterList; boolean hasGen = method.getGenerics().iterator().hasNext() || hasGenInParameterList;
/* if method has generics or return type is TPH, create signature */ /* if method has generics or return type is TPH, create signature */
// zwite operand muss weggelassen werden
if(hasGen||method.getReturnType().acceptTV(new TypeToString()).equals("TPH")) { if(hasGen||method.getReturnType().acceptTV(new TypeToString()).equals("TPH")) {
// resultset hier zum testen // resultset hier zum testen
Signature signature = new Signature(method, genericsAndBoundsMethod, methodParamsAndTypes,resultSet); Signature signature = new Signature(method, genericsAndBoundsMethod, methodParamsAndTypes,resultSet);

View File

@ -29,8 +29,10 @@ import org.objectweb.asm.signature.SignatureWriter;
import de.dhbwstuttgart.bytecode.descriptor.DescriptorToString; import de.dhbwstuttgart.bytecode.descriptor.DescriptorToString;
import de.dhbwstuttgart.bytecode.descriptor.TypeToDescriptor; import de.dhbwstuttgart.bytecode.descriptor.TypeToDescriptor;
import de.dhbwstuttgart.bytecode.signature.Signature; import de.dhbwstuttgart.bytecode.signature.Signature;
import de.dhbwstuttgart.bytecode.signature.TypeToSignature; import de.dhbwstuttgart.bytecode.utilities.KindOfLambda;
import de.dhbwstuttgart.bytecode.signature.TypeToString; import de.dhbwstuttgart.bytecode.utilities.Lambda;
import de.dhbwstuttgart.bytecode.utilities.MethodFromMethodCall;
import de.dhbwstuttgart.bytecode.utilities.SamMethod;
import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal; import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal;
import de.dhbwstuttgart.syntaxtree.FormalParameter; import de.dhbwstuttgart.syntaxtree.FormalParameter;
import de.dhbwstuttgart.syntaxtree.Method; import de.dhbwstuttgart.syntaxtree.Method;
@ -52,17 +54,16 @@ public class BytecodeGenMethod implements StatementVisitor {
private HashMap<String, String> genericsAndBounds; private HashMap<String, String> genericsAndBounds;
private boolean isBinaryExp = false; private boolean isBinaryExp = false;
private IStatement statement = null;
// for tests ** // for tests **
private String fieldName; private String fieldName;
private String fieldDesc; private String fieldDesc;
private Expression rightSideTemp; private Expression rightSideTemp;
private boolean isRightSideALambda = false; private boolean isRightSideALambda = false;
private KindOfLambda kindOfLambda; private KindOfLambda kindOfLambda;
private HashMap<String, byte[]> classFiles; private HashMap<String, byte[]> classFiles;
private boolean isAssignStmt = false;
private Statement loopBlock;
private ArrayList<RefTypeOrTPHOrWildcardOrGeneric> varsFunInterface = new ArrayList<>();; private ArrayList<RefTypeOrTPHOrWildcardOrGeneric> varsFunInterface = new ArrayList<>();;
@ -107,7 +108,7 @@ public class BytecodeGenMethod implements StatementVisitor {
private String getResolvedType(RefTypeOrTPHOrWildcardOrGeneric type) { private String getResolvedType(RefTypeOrTPHOrWildcardOrGeneric type) {
return resultSet.resolveType(type).resolvedType.acceptTV(new TypeToDescriptor()); return resultSet.resolveType(type).resolvedType.acceptTV(new TypeToDescriptor());
} }
@Override @Override
public void visit(Block block) { public void visit(Block block) {
for (Statement stmt : block.getStatements()) { for (Statement stmt : block.getStatements()) {
@ -132,7 +133,7 @@ public class BytecodeGenMethod implements StatementVisitor {
mv.visitVarInsn(Opcodes.ALOAD, paramsAndLocals.get(localVar.name)); mv.visitVarInsn(Opcodes.ALOAD, paramsAndLocals.get(localVar.name));
if (isBinaryExp) { if (isBinaryExp) {
getVlaueIns(getResolvedType(localVar.getType())); doUnboxing(getResolvedType(localVar.getType()));
} }
} }
@ -144,8 +145,7 @@ public class BytecodeGenMethod implements StatementVisitor {
@Override @Override
public void visit(Assign assign) { public void visit(Assign assign) {
isAssignStmt = true; statement = new AssignStmt(assign.rightSide);
// if the right side is a lambda => the left side must be a functional interface // if the right side is a lambda => the left side must be a functional interface
if (assign.rightSide instanceof LambdaExpression) { if (assign.rightSide instanceof LambdaExpression) {
isRightSideALambda = true; isRightSideALambda = true;
@ -153,9 +153,7 @@ public class BytecodeGenMethod implements StatementVisitor {
isRightSideALambda = false; isRightSideALambda = false;
} }
if (assign.rightSide instanceof BinaryExpr) isBinaryExp = statement.isExprBinary();
isBinaryExp = true;
if (assign.lefSide instanceof AssignToField) { if (assign.lefSide instanceof AssignToField) {
// load_0, ldc or .. then putfield // load_0, ldc or .. then putfield
@ -165,26 +163,24 @@ public class BytecodeGenMethod implements StatementVisitor {
} }
if (isBinaryExp) { if (isBinaryExp) {
BinaryExpr binary = (BinaryExpr) assign.rightSide; BinaryExpr binary = (BinaryExpr) assign.rightSide;
String lexpType = getResolvedType(binary.lexpr.getType()); String binaryType = getResolvedType(binary.getType());
String rexpType = getResolvedType(binary.rexpr.getType()); doBoxing(binaryType);
getValueOfIns(getLargerType(lexpType, rexpType));
isBinaryExp = false; isBinaryExp = false;
} }
assign.lefSide.accept(this); assign.lefSide.accept(this);
isAssignStmt =false;
}
statement = null;
}
@Override @Override
public void visit(BinaryExpr binary) { public void visit(BinaryExpr binary) {
String lexpType = getResolvedType(binary.lexpr.getType()); String lexpType = getResolvedType(binary.lexpr.getType());
String rexpType = getResolvedType(binary.rexpr.getType()); String rexpType = getResolvedType(binary.rexpr.getType());
String largerType = getLargerType(lexpType,rexpType); String largerType = getLargerType(lexpType, rexpType);
String typeOfBinary = getResolvedType(binary.getType()); String typeOfBinary = getResolvedType(binary.getType());
if (typeOfBinary.equals(Type.getInternalName(String.class))) { if (typeOfBinary.equals(Type.getInternalName(String.class))) {
mv.visitTypeInsn(Opcodes.NEW, Type.getInternalName(StringBuilder.class)); mv.visitTypeInsn(Opcodes.NEW, Type.getInternalName(StringBuilder.class));
mv.visitInsn(Opcodes.DUP); mv.visitInsn(Opcodes.DUP);
@ -194,23 +190,21 @@ public class BytecodeGenMethod implements StatementVisitor {
Label endLabel = new Label(); Label endLabel = new Label();
// this case for while loops // this case for while loops
if(!isAssignStmt) if (statement instanceof LoopStmt)
mv.visitLabel(endLabel); mv.visitLabel(endLabel);
binary.lexpr.accept(this); binary.lexpr.accept(this);
if(!lexpType.equals(rexpType) && if (!lexpType.equals(rexpType) && !lexpType.equals(largerType))
!lexpType.equals(largerType))
doCast(lexpType, largerType); doCast(lexpType, largerType);
binary.rexpr.accept(this); binary.rexpr.accept(this);
if(!lexpType.equals(rexpType) && if (!lexpType.equals(rexpType) && !rexpType.equals(largerType))
!rexpType.equals(largerType))
doCast(rexpType, largerType); doCast(rexpType, largerType);
Operator op = binary.operation; Operator op = binary.operation;
switch (op) { switch (op) {
case ADD: case ADD:
doVisitAddOpInsn(largerType); doVisitAddOpInsn(largerType);
@ -237,28 +231,31 @@ public class BytecodeGenMethod implements StatementVisitor {
case BIGGERTHAN: case BIGGERTHAN:
case BIGGEREQUAL: case BIGGEREQUAL:
Label branchLabel = new Label(); Label branchLabel = new Label();
doVisitRelOpInsn(op,largerType, branchLabel, endLabel); doVisitRelOpInsn(op, largerType, branchLabel, endLabel);
break; break;
default: default:
break; break;
} }
} }
/*
* Diese Methode wird nicht mehr gebraucht, da es jetzt nicht möglich ist, dass
* solche Fälle: Integer -> Integer (OP) Short ,... usw, nicht vorkommen!
*/
private String getLargerType(String lexpType, String rexpType) { private String getLargerType(String lexpType, String rexpType) {
if(lexpType.equals(Type.getInternalName(String.class)) || if (lexpType.equals(Type.getInternalName(String.class))
rexpType.equals(Type.getInternalName(String.class))) { || rexpType.equals(Type.getInternalName(String.class))) {
return Type.getInternalName(String.class); return Type.getInternalName(String.class);
} else } else if (lexpType.equals(Type.getInternalName(Double.class))
if(lexpType.equals(Type.getInternalName(Double.class)) || || rexpType.equals(Type.getInternalName(Double.class))) {
rexpType.equals(Type.getInternalName(Double.class))) {
return Type.getInternalName(Double.class); return Type.getInternalName(Double.class);
} else if(lexpType.equals(Type.getInternalName(Float.class)) || } else if (lexpType.equals(Type.getInternalName(Float.class))
rexpType.equals(Type.getInternalName(Float.class))) { || rexpType.equals(Type.getInternalName(Float.class))) {
return Type.getInternalName(Float.class); return Type.getInternalName(Float.class);
} else if(lexpType.equals(Type.getInternalName(Long.class)) || } else if (lexpType.equals(Type.getInternalName(Long.class))
rexpType.equals(Type.getInternalName(Long.class))) { || rexpType.equals(Type.getInternalName(Long.class))) {
return Type.getInternalName(Long.class); return Type.getInternalName(Long.class);
} else { } else {
return Type.getInternalName(Integer.class); return Type.getInternalName(Integer.class);
@ -270,19 +267,19 @@ public class BytecodeGenMethod implements StatementVisitor {
case "java/lang/Long": case "java/lang/Long":
mv.visitInsn(Opcodes.I2L); mv.visitInsn(Opcodes.I2L);
break; break;
case "java/lang/Double": case "java/lang/Double":
if(sourceType.equals(Type.getInternalName(Long.class))) { if (sourceType.equals(Type.getInternalName(Long.class))) {
mv.visitInsn(Opcodes.L2D); mv.visitInsn(Opcodes.L2D);
} else if(sourceType.equals(Type.getInternalName(Float.class))) { } else if (sourceType.equals(Type.getInternalName(Float.class))) {
mv.visitInsn(Opcodes.F2D); mv.visitInsn(Opcodes.F2D);
} else { } else {
mv.visitInsn(Opcodes.I2D); mv.visitInsn(Opcodes.I2D);
} }
break; break;
case "java/lang/Float": case "java/lang/Float":
if(sourceType.equals(Type.getInternalName(Long.class))) { if (sourceType.equals(Type.getInternalName(Long.class))) {
mv.visitInsn(Opcodes.L2F); mv.visitInsn(Opcodes.L2F);
} else { } else {
mv.visitInsn(Opcodes.I2F); mv.visitInsn(Opcodes.I2F);
@ -290,14 +287,18 @@ public class BytecodeGenMethod implements StatementVisitor {
break; break;
// braucht man eigentlic nicht, muss getestet werden // braucht man eigentlic nicht, muss getestet werden
case "java/lang/String": case "java/lang/String":
if(sourceType.equals(Type.getInternalName(Double.class))) { if (sourceType.equals(Type.getInternalName(Double.class))) {
mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(String.class), "valueOf", "(D)Ljava/lang/String;", false); mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(String.class), "valueOf",
} else if(sourceType.equals(Type.getInternalName(Long.class))) { "(D)Ljava/lang/String;", false);
mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(String.class), "valueOf", "(J)Ljava/lang/String;", false); } else if (sourceType.equals(Type.getInternalName(Long.class))) {
} else if(sourceType.equals(Type.getInternalName(Float.class))) { mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(String.class), "valueOf",
mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(String.class), "valueOf", "(F)Ljava/lang/String;", false); "(J)Ljava/lang/String;", false);
} else if (sourceType.equals(Type.getInternalName(Float.class))) {
mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(String.class), "valueOf",
"(F)Ljava/lang/String;", false);
} else { } else {
mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(String.class), "valueOf", "(I)Ljava/lang/String;", false); mv.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(String.class), "valueOf",
"(I)Ljava/lang/String;", false);
} }
break; break;
default: default:
@ -306,7 +307,7 @@ public class BytecodeGenMethod implements StatementVisitor {
} }
private void doVisitRelOpInsn(Operator op, String typeOfBinary, Label branchLabel, Label endLabel) { private void doVisitRelOpInsn(Operator op, String typeOfBinary, Label branchLabel, Label endLabel) {
switch (typeOfBinary) { switch (typeOfBinary) {
case "java/lang/Long": case "java/lang/Long":
mv.visitInsn(Opcodes.LCMP); mv.visitInsn(Opcodes.LCMP);
@ -337,18 +338,9 @@ public class BytecodeGenMethod implements StatementVisitor {
default: default:
break; break;
} }
if(isAssignStmt) {
mv.visitInsn(Opcodes.ICONST_1); statement.genBCForRelOp(mv, branchLabel, endLabel, this);
mv.visitJumpInsn(Opcodes.GOTO, endLabel);
mv.visitLabel(branchLabel);
mv.visitInsn(Opcodes.ICONST_0);
mv.visitLabel(endLabel);
} else {
loopBlock.accept(this);
mv.visitJumpInsn(Opcodes.GOTO, endLabel);
mv.visitLabel(branchLabel);
}
break; break;
} }
} }
@ -371,19 +363,8 @@ public class BytecodeGenMethod implements StatementVisitor {
default: default:
break; break;
} }
if(isAssignStmt) {
mv.visitInsn(Opcodes.ICONST_1); statement.genBCForRelOp(mv, branchLabel, endLabel, this);
mv.visitJumpInsn(Opcodes.GOTO, endLabel);
mv.visitLabel(branchLabel);
mv.visitInsn(Opcodes.ICONST_0);
mv.visitLabel(endLabel);
} else {
loopBlock.accept(this);
mv.visitJumpInsn(Opcodes.GOTO, endLabel);
mv.visitLabel(branchLabel);
}
} }
private void doVisitModOpInsn(String typeOfBinary) { private void doVisitModOpInsn(String typeOfBinary) {
@ -546,7 +527,7 @@ public class BytecodeGenMethod implements StatementVisitor {
cw.visitInnerClass("java/lang/invoke/MethodHandles$Lookup", "java/lang/invoke/MethodHandles", "Lookup", cw.visitInnerClass("java/lang/invoke/MethodHandles$Lookup", "java/lang/invoke/MethodHandles", "Lookup",
Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC + Opcodes.ACC_FINAL); Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC + Opcodes.ACC_FINAL);
generateBCForFunN(lambdaExpression,typeErasure); generateBCForFunN(lambdaExpression, typeErasure);
} }
private void generateBCForFunN(LambdaExpression lambdaExpression, String methDesc) { private void generateBCForFunN(LambdaExpression lambdaExpression, String methDesc) {
@ -566,7 +547,7 @@ public class BytecodeGenMethod implements StatementVisitor {
methSig.visitReturnType().visitTypeVariable("R"); methSig.visitReturnType().visitTypeVariable("R");
// ")"+lam.getReturn.getBounds // ")"+lam.getReturn.getBounds
Signature sig = new Signature(lambdaExpression, numberOfParams); Signature sig = new Signature(lambdaExpression, numberOfParams);
String name = "Fun" + numberOfParams; String name = "Fun" + numberOfParams + "$$";
classWriter.visit(Opcodes.V1_8, Opcodes.ACC_INTERFACE + Opcodes.ACC_ABSTRACT, name, sig.toString(), classWriter.visit(Opcodes.V1_8, Opcodes.ACC_INTERFACE + Opcodes.ACC_ABSTRACT, name, sig.toString(),
Type.getInternalName(Object.class), null); Type.getInternalName(Object.class), null);
MethodVisitor mvApply = classWriter.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_ABSTRACT, "apply", methDesc, MethodVisitor mvApply = classWriter.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_ABSTRACT, "apply", methDesc,
@ -640,6 +621,7 @@ public class BytecodeGenMethod implements StatementVisitor {
@Override @Override
public void visit(MethodCall methodCall) { public void visit(MethodCall methodCall) {
methodCall.receiver.accept(this); methodCall.receiver.accept(this);
methodCall.arglist.accept(this); methodCall.arglist.accept(this);
@ -647,7 +629,7 @@ public class BytecodeGenMethod implements StatementVisitor {
genericsAndBoundsMethod, genericsAndBounds); genericsAndBoundsMethod, genericsAndBounds);
String mDesc = method.accept(new DescriptorToString(resultSet)); String mDesc = method.accept(new DescriptorToString(resultSet));
// is methodCall.receiver functional Interface)? // is methodCall.receiver functional Interface)?
if (varsFunInterface.contains(methodCall.receiver.getType())) { if (varsFunInterface.contains(methodCall.receiver.getType())) {
mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, getResolvedType(methodCall.receiver.getType()), methodCall.name, mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, getResolvedType(methodCall.receiver.getType()), methodCall.name,
mDesc, false); mDesc, false);
@ -692,40 +674,40 @@ public class BytecodeGenMethod implements StatementVisitor {
public void visit(UnaryExpr unaryExpr) { public void visit(UnaryExpr unaryExpr) {
unaryExpr.expr.accept(this); unaryExpr.expr.accept(this);
Operation op = unaryExpr.operation; Operation op = unaryExpr.operation;
String typeOfUnary = getResolvedType(unaryExpr.getType()); String typeOfUnary = getResolvedType(unaryExpr.getType());
boolean isIncOrDec = false; boolean isIncOrDec = false;
switch (op) { switch (op) {
case POSTDECREMENT: case POSTDECREMENT:
case POSTINCREMENT: case POSTINCREMENT:
if(isAssignStmt) if (statement instanceof AssignStmt)
mv.visitInsn(Opcodes.DUP); mv.visitInsn(Opcodes.DUP);
genBCForIncAndDec(op, typeOfUnary); genBCForIncAndDec(op, typeOfUnary);
getValueOfIns(typeOfUnary); doBoxing(typeOfUnary);
isIncOrDec = true; isIncOrDec = true;
break; break;
case PREDECREMENT: case PREDECREMENT:
case PREINCREMENT: case PREINCREMENT:
genBCForIncAndDec(op, typeOfUnary); genBCForIncAndDec(op, typeOfUnary);
getValueOfIns(typeOfUnary); doBoxing(typeOfUnary);
if(isAssignStmt) if (statement instanceof AssignStmt)
mv.visitInsn(Opcodes.DUP); mv.visitInsn(Opcodes.DUP);
isIncOrDec = true; isIncOrDec = true;
break; break;
case MINUS: case MINUS:
doVisitNegIns(typeOfUnary); doVisitNegIns(typeOfUnary);
break; break;
default: default:
break; break;
} }
// Für Byte und Short muss noch einen Cast geben i2b, i2s // Für Byte und Short muss noch einen Cast geben i2b, i2s
// das wird später gemacht, da bytecode für cast noch nicht erzeugt wird // das wird später gemacht, da bytecode für cast noch nicht erzeugt wird
if(isIncOrDec && (unaryExpr.expr instanceof LocalVar)) { if (isIncOrDec && (unaryExpr.expr instanceof LocalVar)) {
LocalVar local = (LocalVar) unaryExpr.expr; LocalVar local = (LocalVar) unaryExpr.expr;
mv.visitVarInsn(Opcodes.ASTORE, paramsAndLocals.get(local.name)); mv.visitVarInsn(Opcodes.ASTORE, paramsAndLocals.get(local.name));
} }
@ -746,14 +728,14 @@ public class BytecodeGenMethod implements StatementVisitor {
mv.visitInsn(Opcodes.INEG); mv.visitInsn(Opcodes.INEG);
break; break;
} }
} }
private void genBCForIncAndDec(Operation op, String typeOfUnary) { private void genBCForIncAndDec(Operation op, String typeOfUnary) {
getVlaueIns(typeOfUnary); doUnboxing(typeOfUnary);
doAssign(typeOfUnary, 1.0, true); loadValue(typeOfUnary, 1.0, true);
switch (op) { switch (op) {
case POSTDECREMENT: case POSTDECREMENT:
case PREDECREMENT: case PREDECREMENT:
@ -764,7 +746,7 @@ public class BytecodeGenMethod implements StatementVisitor {
case PREINCREMENT: case PREINCREMENT:
doVisitAddOpInsn(typeOfUnary); doVisitAddOpInsn(typeOfUnary);
break; break;
default: default:
break; break;
} }
@ -772,20 +754,19 @@ public class BytecodeGenMethod implements StatementVisitor {
@Override @Override
public void visit(Return aReturn) { public void visit(Return aReturn) {
if(aReturn.retexpr instanceof BinaryExpr) statement = new ReturnStmt(aReturn.retexpr);
isBinaryExp = true; isBinaryExp = statement.isExprBinary();
aReturn.retexpr.accept(this); aReturn.retexpr.accept(this);
if (isBinaryExp) { if (isBinaryExp) {
BinaryExpr binary = (BinaryExpr) aReturn.retexpr; BinaryExpr binary = (BinaryExpr) aReturn.retexpr;
String lexpType = getResolvedType(binary.lexpr.getType()); doBoxing(getResolvedType(binary.getType()));
String rexpType = getResolvedType(binary.rexpr.getType());
getValueOfIns(getLargerType(lexpType, rexpType));
isBinaryExp = false; isBinaryExp = false;
} }
mv.visitInsn(Opcodes.ARETURN); mv.visitInsn(Opcodes.ARETURN);
statement = null;
} }
@Override @Override
@ -798,7 +779,8 @@ public class BytecodeGenMethod implements StatementVisitor {
// mv.visitMethodInsn(Opcodes.INVOKESTATIC, // mv.visitMethodInsn(Opcodes.INVOKESTATIC,
// staticClassName.getType().toString().replace(".", "/"), // staticClassName.getType().toString().replace(".", "/"),
// staticClassName.toString(), staticClassName.getType().toString(), false); // staticClassName.toString(), staticClassName.getType().toString(), false);
//mv.visitFieldInsn(Opcodes.GETSTATIC, getResolvedType(staticClassName.getType()), fieldName, fieldDesc); // mv.visitFieldInsn(Opcodes.GETSTATIC,
// getResolvedType(staticClassName.getType()), fieldName, fieldDesc);
throw new NotImplementedException("Static noch nicht implementiert!"); throw new NotImplementedException("Static noch nicht implementiert!");
} }
@ -814,14 +796,11 @@ public class BytecodeGenMethod implements StatementVisitor {
@Override @Override
public void visit(WhileStmt whileStmt) { public void visit(WhileStmt whileStmt) {
this.loopBlock = whileStmt.loopBlock; statement = new LoopStmt(whileStmt.expr, whileStmt.loopBlock);
isBinaryExp = statement.isExprBinary();
if(whileStmt.expr instanceof BinaryExpr)
isBinaryExp = true;
whileStmt.expr.accept(this); whileStmt.expr.accept(this);
isBinaryExp = false; isBinaryExp = false;
statement = null;
} }
@Override @Override
@ -834,12 +813,13 @@ public class BytecodeGenMethod implements StatementVisitor {
public void visit(Literal literal) { public void visit(Literal literal) {
Object value = literal.value; Object value = literal.value;
String typeOfLiteral = getResolvedType(literal.getType()); String typeOfLiteral = getResolvedType(literal.getType());
// Name der Methode muss geändert werden // Der Wert des Literals wird auf den Stack geladen und
doAssign(typeOfLiteral, value, false); // geboxt, wenn es nötig ist.
loadValue(typeOfLiteral, value, false);
} }
private void getVlaueIns(String type) { // Unboxing: RefType -> prim
private void doUnboxing(String type) {
switch (type) { switch (type) {
case "java/lang/String": case "java/lang/String":
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(StringBuilder.class), "append", mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(StringBuilder.class), "append",
@ -869,11 +849,13 @@ public class BytecodeGenMethod implements StatementVisitor {
case "java/lang/Character": case "java/lang/Character":
break; break;
default: default:
// mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Integer", "intValue",
// "()I", false);
break; break;
} }
} }
private void doAssign(String type, Object value, boolean isOperator) { private void loadValue(String type, Object value, boolean isOperator) {
switch (type) { switch (type) {
case "java/lang/String": case "java/lang/String":
mv.visitLdcInsn(String.valueOf(value)); mv.visitLdcInsn(String.valueOf(value));
@ -904,17 +886,21 @@ public class BytecodeGenMethod implements StatementVisitor {
visitCharLiteral((Character) value); visitCharLiteral((Character) value);
break; break;
default: default:
// wenn die Typ des Literals = Number ist, wird integer-value
// verwendet
// visitIntegerLiteral(((Double) value).intValue(), false);
break; break;
} }
// Boxing
if(!type.equals("java/lang/String")&&!type.equals("java/lang/Boolean")) { if (!type.equals("java/lang/String") && !type.equals("java/lang/Boolean")) {
if (!this.isBinaryExp && !isOperator) if (!this.isBinaryExp && !isOperator)
getValueOfIns(type); doBoxing(type);
} }
} }
private void getValueOfIns(String type) { // Boxing: prim -> RefType
private void doBoxing(String type) {
switch (type) { switch (type) {
case "java/lang/String": case "java/lang/String":
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;", mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;",
@ -952,7 +938,7 @@ public class BytecodeGenMethod implements StatementVisitor {
private void visitCharLiteral(Character value) { private void visitCharLiteral(Character value) {
mv.visitIntInsn(Opcodes.BIPUSH, (int) value); mv.visitIntInsn(Opcodes.BIPUSH, (int) value);
} }
private void visitDoubleLiteral(Double value) { private void visitDoubleLiteral(Double value) {
@ -1026,7 +1012,9 @@ public class BytecodeGenMethod implements StatementVisitor {
@Override @Override
public void visit(ArgumentList argumentList) { public void visit(ArgumentList argumentList) {
for (Expression al : argumentList.getArguments()) { for (Expression al : argumentList.getArguments()) {
statement = new ArgumentExpr(al);
al.accept(this); al.accept(this);
statement = null;
} }
} }
@ -1050,12 +1038,12 @@ public class BytecodeGenMethod implements StatementVisitor {
varsFunInterface.add(assignLeftSide.localVar.getType()); varsFunInterface.add(assignLeftSide.localVar.getType());
int index = paramsAndLocals.size(); int index = paramsAndLocals.size();
String var = assignLeftSide.localVar.name; String var = assignLeftSide.localVar.name;
if(!paramsAndLocals.containsKey(var)) { if (!paramsAndLocals.containsKey(var)) {
paramsAndLocals.put(var, index + 1); paramsAndLocals.put(var, index + 1);
}else { } else {
paramsAndLocals.put(var, index); paramsAndLocals.put(var, index);
} }
mv.visitVarInsn(Opcodes.ASTORE, paramsAndLocals.size()); mv.visitVarInsn(Opcodes.ASTORE, paramsAndLocals.size());
// Debug::: // Debug:::

View File

@ -0,0 +1,9 @@
package de.dhbwstuttgart.bytecode;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
public interface IStatement {
public boolean isExprBinary();
public void genBCForRelOp(MethodVisitor mv, Label branchLabel, Label endLabel, BytecodeGenMethod bytecodeGenMethod);
}

View File

@ -0,0 +1,25 @@
package de.dhbwstuttgart.bytecode;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import de.dhbwstuttgart.syntaxtree.statement.Expression;
import de.dhbwstuttgart.syntaxtree.statement.Statement;
public class LoopStmt extends AStatement {
private Statement loopBlock;
public LoopStmt(Expression expr, Statement loopBlock) {
super(expr);
this.loopBlock = loopBlock;
}
@Override
public void genBCForRelOp(MethodVisitor mv,Label branchLabel, Label endLabel, BytecodeGenMethod bytecodeGenMethod) {
this.loopBlock.accept(bytecodeGenMethod);
mv.visitJumpInsn(Opcodes.GOTO, endLabel);
mv.visitLabel(branchLabel);
}
}

View File

@ -0,0 +1,14 @@
package de.dhbwstuttgart.bytecode;
import org.objectweb.asm.MethodVisitor;
import de.dhbwstuttgart.syntaxtree.statement.BinaryExpr;
import de.dhbwstuttgart.syntaxtree.statement.Expression;
public class ReturnStmt extends AStatement {
public ReturnStmt(Expression retexpr) {
super(retexpr);
}
}

View File

@ -2,12 +2,12 @@ package de.dhbwstuttgart.bytecode.descriptor;
import java.util.Iterator; import java.util.Iterator;
import de.dhbwstuttgart.bytecode.Lambda;
import de.dhbwstuttgart.bytecode.MethodFromMethodCall;
import de.dhbwstuttgart.bytecode.NormalConstructor;
import de.dhbwstuttgart.bytecode.NormalMethod;
import de.dhbwstuttgart.bytecode.SamMethod;
import de.dhbwstuttgart.bytecode.signature.TypeToSignature; import de.dhbwstuttgart.bytecode.signature.TypeToSignature;
import de.dhbwstuttgart.bytecode.utilities.Lambda;
import de.dhbwstuttgart.bytecode.utilities.MethodFromMethodCall;
import de.dhbwstuttgart.bytecode.utilities.NormalConstructor;
import de.dhbwstuttgart.bytecode.utilities.NormalMethod;
import de.dhbwstuttgart.bytecode.utilities.SamMethod;
import de.dhbwstuttgart.syntaxtree.FormalParameter; import de.dhbwstuttgart.syntaxtree.FormalParameter;
import de.dhbwstuttgart.syntaxtree.statement.Expression; import de.dhbwstuttgart.syntaxtree.statement.Expression;
import de.dhbwstuttgart.syntaxtree.type.RefType; import de.dhbwstuttgart.syntaxtree.type.RefType;
@ -46,12 +46,18 @@ public class DescriptorToString implements DescriptorVisitor{
}else if(method.getGenericsAndBounds().containsKey(fpDesc)){ }else if(method.getGenericsAndBounds().containsKey(fpDesc)){
desc += "L"+method.getGenericsAndBounds().get(fpDesc)+ ";"; desc += "L"+method.getGenericsAndBounds().get(fpDesc)+ ";";
}else { }else {
desc += "L"+resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";"; // desc += "L"+resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";";
String resType = resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor());
if(resType.subSequence(0, 4).equals("TPH ")) {
desc += "L"+method.getGenericsAndBoundsMethod().get(resType.substring(4)+"$")+ ";";
} else {
desc += "L"+resType+ ";";
}
} }
} }
//TODO: generate a class java%% ... %% //TODO: generate a class java%% ... %%
else if(resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor()).contains("<")){ else if(resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor()).contains("<")){
desc += "L"+resultSet.resolveType(fp.getType()).resolvedType.toString().replace(".", "%").replace("<", "%%").replace(">", "%%")+ ";"; desc += "L"+resultSet.resolveType(fp.getType()).resolvedType.toString().replace(".", "$$").replace("<", "$$$").replace(">", "$$$")+ ";";
} }
else { else {
desc += "L"+resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";"; desc += "L"+resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";";
@ -68,7 +74,12 @@ public class DescriptorToString implements DescriptorVisitor{
}else if(method.getGenericsAndBounds().containsKey(ret)){ }else if(method.getGenericsAndBounds().containsKey(ret)){
desc += ")L"+method.getGenericsAndBounds().get(ret)+ ";"; desc += ")L"+method.getGenericsAndBounds().get(ret)+ ";";
}else { }else {
desc += ")" + "L"+resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";"; String resType = resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor());
if(resType.subSequence(0, 4).equals("TPH ")) {
desc += ")" + "L"+method.getGenericsAndBoundsMethod().get(resType.substring(4)+"$")+ ";";
} else {
desc += ")" + "L"+resType+ ";";
}
} }
}else { }else {
desc += ")" + "L"+resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";"; desc += ")" + "L"+resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToDescriptor())+ ";";

View File

@ -1,10 +1,10 @@
package de.dhbwstuttgart.bytecode.descriptor; package de.dhbwstuttgart.bytecode.descriptor;
import de.dhbwstuttgart.bytecode.Lambda; import de.dhbwstuttgart.bytecode.utilities.Lambda;
import de.dhbwstuttgart.bytecode.MethodFromMethodCall; import de.dhbwstuttgart.bytecode.utilities.MethodFromMethodCall;
import de.dhbwstuttgart.bytecode.NormalConstructor; import de.dhbwstuttgart.bytecode.utilities.NormalConstructor;
import de.dhbwstuttgart.bytecode.NormalMethod; import de.dhbwstuttgart.bytecode.utilities.NormalMethod;
import de.dhbwstuttgart.bytecode.SamMethod; import de.dhbwstuttgart.bytecode.utilities.SamMethod;
public interface DescriptorVisitor { public interface DescriptorVisitor {
public String visit(NormalMethod method); public String visit(NormalMethod method);

View File

@ -13,6 +13,8 @@ public class TypeToDescriptor implements TypeVisitor<String>{
@Override @Override
public String visit(RefType refType) { public String visit(RefType refType) {
return refType.getName().toString().replace(".", "/"); return refType.getName().toString().replace(".", "/");
// String t = refType.getName().toString().replace(".", "/");
// return t.equals("Fun1")?(t+"$$"):t;
} }
@Override @Override
@ -27,7 +29,8 @@ public class TypeToDescriptor implements TypeVisitor<String>{
@Override @Override
public String visit(ExtendsWildcardType extendsWildcardType) { public String visit(ExtendsWildcardType extendsWildcardType) {
throw new NotImplementedException(); return extendsWildcardType.getInnerType().toString();
//throw new NotImplementedException();
} }
@Override @Override

View File

@ -59,10 +59,7 @@ public class Signature {
private void createSignatureForFunN(LambdaExpression lambdaExpression, int numberOfParams) { private void createSignatureForFunN(LambdaExpression lambdaExpression, int numberOfParams) {
sw.visitFormalTypeParameter("R"); // sw.visitClassBound().visitEnd();
// getBounds vom Return-Type
sw.visitClassBound().visitClassType(Type.getInternalName(Object.class));
sw.visitClassBound().visitEnd();
for(int i = 0;i<numberOfParams;i++) { for(int i = 0;i<numberOfParams;i++) {
int j = i+1; int j = i+1;
sw.visitFormalTypeParameter("T"+ j); sw.visitFormalTypeParameter("T"+ j);
@ -70,6 +67,11 @@ public class Signature {
sw.visitClassBound().visitClassType(Type.getInternalName(Object.class)); sw.visitClassBound().visitClassType(Type.getInternalName(Object.class));
sw.visitClassBound().visitEnd(); sw.visitClassBound().visitEnd();
} }
sw.visitFormalTypeParameter("R");
// getBounds vom Return-Type
sw.visitClassBound().visitClassType(Type.getInternalName(Object.class));
sw.visitClassBound().visitEnd();
// TODO: prüfe ob Return-Type = void, // TODO: prüfe ob Return-Type = void,
sw.visitSuperclass().visitClassType(Type.getInternalName(Object.class));; sw.visitSuperclass().visitClassType(Type.getInternalName(Object.class));;
sw.visitEnd(); sw.visitEnd();
@ -90,7 +92,31 @@ public class Signature {
GenericTypeVar g = itr.next(); GenericTypeVar g = itr.next();
getBoundsOfTypeVar(g,genericsAndBoundsMethod); getBoundsOfTypeVar(g,genericsAndBoundsMethod);
} }
// visits each method-parameter to create the signature // Wenn die RückgabeType eine TPH ist, wird als generic behandelt
// z.B: Type = TPH K => wird eine Formal Type Parameter K$ erzeugt und Bound = Object
String ret = resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToSignature());
if(ret.substring(0,4).equals("TPH ")) {
String g = ret.substring(4)+"$";
sw.visitFormalTypeParameter(g);
sw.visitClassBound().visitClassType(Type.getInternalName(Object.class));
genericsAndBoundsMethod.put(g, Type.getInternalName(Object.class));
sw.visitClassBound().visitEnd();
}
for(String paramName : methodParamsAndTypes.keySet()) {
RefTypeOrTPHOrWildcardOrGeneric t = methodParamsAndTypes.get(paramName);
String pT = t.acceptTV(new TypeToSignature());
// S.o
if(pT.substring(0,4).equals("TPH ") && !genericsAndBoundsMethod.containsKey(pT)) {
String gP = pT.substring(4)+"$";
sw.visitFormalTypeParameter(gP);
sw.visitClassBound().visitClassType(Type.getInternalName(Object.class));
genericsAndBoundsMethod.put(gP, Type.getInternalName(Object.class));
sw.visitClassBound().visitEnd();
}
}
// visit each method-parameter to create the signature
for(String paramName : methodParamsAndTypes.keySet()) { for(String paramName : methodParamsAndTypes.keySet()) {
RefTypeOrTPHOrWildcardOrGeneric t = methodParamsAndTypes.get(paramName); RefTypeOrTPHOrWildcardOrGeneric t = methodParamsAndTypes.get(paramName);
// parameter type deswegen ist true // parameter type deswegen ist true
@ -99,6 +125,15 @@ public class Signature {
if(isConstructor) { if(isConstructor) {
sw.visitReturnType().visitBaseType('V'); sw.visitReturnType().visitBaseType('V');
}else { }else {
// String ret = resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToSignature());
// if(ret.substring(0,4).equals("TPH ")) {
// String g = ret.substring(4);
// if(!genericsAndBoundsMethod.containsKey(g)) {
// genericsAndBoundsMethod.put(g, Type.getInternalName(Object.class));
// } else {
// genericsAndBoundsMethod.put(g+"_", Type.getInternalName(Object.class));
// }
// }
RefTypeOrTPHOrWildcardOrGeneric returnType = method.getReturnType(); RefTypeOrTPHOrWildcardOrGeneric returnType = method.getReturnType();
// return type deswegen ist false // return type deswegen ist false
doVisitParamsOrReturn(returnType, false); doVisitParamsOrReturn(returnType, false);
@ -130,10 +165,16 @@ public class Signature {
break; break;
case "TPH": case "TPH":
RefTypeOrTPHOrWildcardOrGeneric r = resultSet.resolveType(t).resolvedType; RefTypeOrTPHOrWildcardOrGeneric r = resultSet.resolveType(t).resolvedType;
if(!r.acceptTV(new TypeToSignature()).substring(0, 4).equals("TPH ")) // der Fall wenn die Type eine Interface ist, muss betrachtet werden
sv.visitInterface().visitClassType(r.acceptTV(new TypeToSignature())); // Deswegen muss in ResutSet noch enthalten werden, ob die Type eine
// sv.visitClassType(r.acceptTV(new TypeToSignature())); // Interface oder eine Klasse ist.
System.out.println(r.getClass()+" Signature TPH: "+r.acceptTV(new TypeToSignature())); if(!r.acceptTV(new TypeToSignature()).substring(0, 4).equals("TPH ")) {
// sv.visitInterface().visitClassType(r.acceptTV(new TypeToSignature()));
sv.visitClassType(r.acceptTV(new TypeToSignature()));
} else {
System.out.println(r.getClass()+" Signature TPH: "+r.acceptTV(new TypeToSignature()));
sv.visitTypeVariable(r.acceptTV(new TypeToSignature()).substring(4)+"$");
}
break; break;
default: default:
if(!isParameterType) if(!isParameterType)

View File

@ -27,6 +27,8 @@ public class TypeToSignature implements TypeVisitor<String> {
} }
params += ";>"; params += ";>";
} }
// String t = refType.getName().toString().replace(".", "/");
// return t.equals("Fun1")?t+"$$"+params+";":t+params+";";
return refType.getName().toString().replace(".", "/") + params+";"; return refType.getName().toString().replace(".", "/") + params+";";
} }

View File

@ -1,4 +1,4 @@
package de.dhbwstuttgart.bytecode; package de.dhbwstuttgart.bytecode.utilities;
import de.dhbwstuttgart.exceptions.NotImplementedException; import de.dhbwstuttgart.exceptions.NotImplementedException;
import de.dhbwstuttgart.syntaxtree.statement.*; import de.dhbwstuttgart.syntaxtree.statement.*;

View File

@ -1,4 +1,4 @@
package de.dhbwstuttgart.bytecode; package de.dhbwstuttgart.bytecode.utilities;
import de.dhbwstuttgart.bytecode.descriptor.DescriptorVisitor; import de.dhbwstuttgart.bytecode.descriptor.DescriptorVisitor;
import de.dhbwstuttgart.syntaxtree.ParameterList; import de.dhbwstuttgart.syntaxtree.ParameterList;

View File

@ -1,4 +1,4 @@
package de.dhbwstuttgart.bytecode; package de.dhbwstuttgart.bytecode.utilities;
import java.util.HashMap; import java.util.HashMap;

View File

@ -1,4 +1,4 @@
package de.dhbwstuttgart.bytecode; package de.dhbwstuttgart.bytecode.utilities;
import java.util.HashMap; import java.util.HashMap;

View File

@ -1,4 +1,4 @@
package de.dhbwstuttgart.bytecode; package de.dhbwstuttgart.bytecode.utilities;
import java.util.HashMap; import java.util.HashMap;

View File

@ -1,4 +1,4 @@
package de.dhbwstuttgart.bytecode; package de.dhbwstuttgart.bytecode.utilities;
import java.util.List; import java.util.List;

View File

@ -121,8 +121,9 @@ public class JavaTXCompiler {
System.out.println(xConsSet); System.out.println(xConsSet);
Set<String> paraTypeVarNames = allClasses.stream().map(x -> x.getMethods().stream().map(y -> y.getParameterList().getFormalparalist() Set<String> paraTypeVarNames = allClasses.stream().map(x -> x.getMethods().stream().map(y -> y.getParameterList().getFormalparalist()
.stream().filter(z -> z.getType() instanceof TypePlaceholder) .stream().filter(z -> z.getType() instanceof TypePlaceholder)
.map(z -> ((TypePlaceholder)z.getType()).getName()).collect(Collectors.toCollection(HashSet::new))).reduce((a,b) -> { a.addAll(b); return a;} ).get()) .map(z -> ((TypePlaceholder)z.getType()).getName()).collect(Collectors.toCollection(HashSet::new)))
.reduce((a,b) -> { a.addAll(b); return a;} ).get(); .reduce(new HashSet<String>(), (a,b) -> { a.addAll(b); return a;}, (a,b) -> { a.addAll(b); return a;} ) )
.reduce(new HashSet<String>(), (a,b) -> { a.addAll(b); return a;} );
Set<String> returnTypeVarNames = allClasses.stream().map(x -> x.getMethods().stream().filter(y -> y.getReturnType() instanceof TypePlaceholder) Set<String> returnTypeVarNames = allClasses.stream().map(x -> x.getMethods().stream().filter(y -> y.getReturnType() instanceof TypePlaceholder)
.map(z -> ((TypePlaceholder)z.getReturnType()).getName()).collect(Collectors.toCollection(HashSet::new))).reduce((a,b) -> { a.addAll(b); return a;} ).get(); .map(z -> ((TypePlaceholder)z.getReturnType()).getName()).collect(Collectors.toCollection(HashSet::new))).reduce((a,b) -> { a.addAll(b); return a;} ).get();

View File

@ -904,7 +904,7 @@ public class StatementGenerator {
funNParams.add(TypePlaceholder.fresh(expression.getStart()))); funNParams.add(TypePlaceholder.fresh(expression.getStart())));
RefTypeOrTPHOrWildcardOrGeneric lambdaType = TypePlaceholder.fresh(expression.getStart()); RefTypeOrTPHOrWildcardOrGeneric lambdaType = TypePlaceholder.fresh(expression.getStart());
//RefType lambdaType = new RefType(reg.getName("Fun"+params.getFormalparalist().size()), //RefType lambdaType = new RefType(reg.getName("Fun"+params.getFormalparalist().size()),
//funNParams, name.getStart()); //funNParams, name.getStart());
return new LambdaExpression(lambdaType, params, block, expression.getStart()); return new LambdaExpression(lambdaType, params, block, expression.getStart());
} }
} }

View File

@ -51,6 +51,10 @@ public class UnifyTypeFactory {
return new UnifyPair(tl, tr, PairOperator.SMALLERDOT); return new UnifyPair(tl, tr, PairOperator.SMALLERDOT);
} }
public static UnifyPair generateSmallNotEqualDotPair(UnifyType tl, UnifyType tr){
return new UnifyPair(tl, tr, PairOperator.SMALLERNEQDOT);
}
public static UnifyPair generateEqualDotPair(UnifyType tl, UnifyType tr){ public static UnifyPair generateEqualDotPair(UnifyType tl, UnifyType tr){
return new UnifyPair(tl, tr, PairOperator.EQUALSDOT); return new UnifyPair(tl, tr, PairOperator.EQUALSDOT);
} }
@ -152,6 +156,10 @@ public class UnifyTypeFactory {
UnifyPair ret = generateSmallerDotPair(UnifyTypeFactory.convert(p.TA1) UnifyPair ret = generateSmallerDotPair(UnifyTypeFactory.convert(p.TA1)
, UnifyTypeFactory.convert(p.TA2)); , UnifyTypeFactory.convert(p.TA2));
return ret; return ret;
}else if(p.GetOperator().equals(PairOperator.SMALLERNEQDOT)) {
UnifyPair ret = generateSmallNotEqualDotPair(UnifyTypeFactory.convert(p.TA1)
, UnifyTypeFactory.convert(p.TA2));
return ret;
}else if(p.GetOperator().equals(PairOperator.EQUALSDOT)) { }else if(p.GetOperator().equals(PairOperator.EQUALSDOT)) {
UnifyPair ret = generateEqualDotPair(UnifyTypeFactory.convert(p.TA1) UnifyPair ret = generateEqualDotPair(UnifyTypeFactory.convert(p.TA1)
, UnifyTypeFactory.convert(p.TA2)); , UnifyTypeFactory.convert(p.TA2));

View File

@ -42,14 +42,16 @@ public class Pair implements Serializable
if( TA2 != null ) if( TA2 != null )
strElement2 = TA2.toString(); strElement2 = TA2.toString();
/* PL ausskommentiert 2018-05-24
if(OperatorEqual()) if(OperatorEqual())
Operator = "="; Operator = "=";
if(OperatorSmaller()) if(OperatorSmaller())
Operator = "<."; Operator = "<.";
if(OperatorSmallerExtends()) if(OperatorSmallerExtends())
Operator = "<?"; Operator = "<?";
*/
return "\n(" + strElement1 + " " + Operator + " " + strElement2 + ")"; return "\n(" + strElement1 + " " + eOperator.toString() + " " + strElement2 + ")";
/*- Equals: " + bEqual*/ /*- Equals: " + bEqual*/
} }

View File

@ -217,7 +217,7 @@ public class TYPEStmt implements StatementVisitor{
binary.operation.equals(BinaryExpr.Operator.MUL)|| binary.operation.equals(BinaryExpr.Operator.MUL)||
binary.operation.equals(BinaryExpr.Operator.MOD)|| binary.operation.equals(BinaryExpr.Operator.MOD)||
binary.operation.equals(BinaryExpr.Operator.ADD)){ binary.operation.equals(BinaryExpr.Operator.ADD)){
Set<Constraint> numericAdditionOrStringConcatenation = new HashSet<>(); Set<Constraint<Pair>> numericAdditionOrStringConcatenation = new HashSet<>();
//Zuerst der Fall für Numerische AusdrücPairOpnumericeratorke, das sind Mul, Mod und Div immer: //Zuerst der Fall für Numerische AusdrücPairOpnumericeratorke, das sind Mul, Mod und Div immer:
//see: https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.17 //see: https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.17
@ -272,10 +272,54 @@ public class TYPEStmt implements StatementVisitor{
binary.operation.equals(BinaryExpr.Operator.BIGGEREQUAL) || binary.operation.equals(BinaryExpr.Operator.BIGGEREQUAL) ||
binary.operation.equals(BinaryExpr.Operator.BIGGERTHAN) || binary.operation.equals(BinaryExpr.Operator.BIGGERTHAN) ||
binary.operation.equals(BinaryExpr.Operator.LESSTHAN)){ binary.operation.equals(BinaryExpr.Operator.LESSTHAN)){
constraintsSet.addUndConstraint(new Pair(binary.lexpr.getType(), number, PairOperator.SMALLERDOT)); /* //eingefuegt PL 2018-05-24
constraintsSet.addUndConstraint(new Pair(binary.rexpr.getType(), number, PairOperator.SMALLERDOT)); Set<Constraint<Pair>> numericRelationConcatenation = new HashSet<>();
Constraint<Pair> numeric = new Constraint<>();
numeric.add(new Pair(binary.lexpr.getType(), bytee, PairOperator.SMALLERDOT));
numeric.add(new Pair(binary.rexpr.getType(), bytee, PairOperator.SMALLERDOT));
numeric.add(new Pair(binary.getType(), bool, PairOperator.SMALLERDOT));
numericRelationConcatenation.add(numeric);
numeric = new Constraint<>();
numeric.add(new Pair(binary.lexpr.getType(), shortt, PairOperator.SMALLERDOT));
numeric.add(new Pair(binary.rexpr.getType(), shortt, PairOperator.SMALLERDOT));
numeric.add(new Pair(binary.getType(), bool, PairOperator.SMALLERDOT));
numericRelationConcatenation.add(numeric);
numeric = new Constraint<>();
numeric.add(new Pair(binary.lexpr.getType(), integer, PairOperator.SMALLERDOT));
numeric.add(new Pair(binary.rexpr.getType(), integer, PairOperator.SMALLERDOT));
numeric.add(new Pair(binary.getType(), bool, PairOperator.SMALLERDOT));
numericRelationConcatenation.add(numeric);
numeric = new Constraint<>();
numeric.add(new Pair(binary.lexpr.getType(), longg, PairOperator.SMALLERDOT));
numeric.add(new Pair(binary.rexpr.getType(), longg, PairOperator.SMALLERDOT));
numeric.add(new Pair(binary.getType(), bool, PairOperator.SMALLERDOT));
numericRelationConcatenation.add(numeric);
numeric = new Constraint<>();
numeric.add(new Pair(binary.lexpr.getType(), floatt, PairOperator.SMALLERDOT));
numeric.add(new Pair(binary.rexpr.getType(), floatt, PairOperator.SMALLERDOT));
numeric.add(new Pair(binary.getType(), bool, PairOperator.SMALLERDOT));
numericRelationConcatenation.add(numeric);
numeric = new Constraint<>();
numeric.add(new Pair(binary.lexpr.getType(), doublee, PairOperator.SMALLERDOT));
numeric.add(new Pair(binary.rexpr.getType(), doublee, PairOperator.SMALLERDOT));
numeric.add(new Pair(binary.getType(), bool, PairOperator.SMALLERDOT));
numericRelationConcatenation.add(numeric);
//***ACHTUNG: Moeglicherweise oder und und-Contraint falsch
constraintsSet.addOderConstraint(numericRelationConcatenation);
//***ACHTUNG: Moeglicherweise oder und und-Contraint falsch
*/
//Testeise eingefuegt PL 2018-05-24
constraintsSet.addUndConstraint(new Pair(binary.lexpr.getType(), number, PairOperator.SMALLERNEQDOT));
constraintsSet.addUndConstraint(new Pair(binary.rexpr.getType(), number, PairOperator.SMALLERNEQDOT));
//Rückgabetyp ist Boolean //Rückgabetyp ist Boolean
constraintsSet.addUndConstraint(new Pair(bool, binary.getType(), PairOperator.EQUALSDOT)); constraintsSet.addUndConstraint(new Pair(bool, binary.getType(), PairOperator.SMALLERDOT));
//auskommentiert PL 2018-05-24
//constraintsSet.addUndConstraint(new Pair(binary.lexpr.getType(), number, PairOperator.SMALLERDOT));
//constraintsSet.addUndConstraint(new Pair(binary.rexpr.getType(), number, PairOperator.SMALLERDOT));
//Rückgabetyp ist Boolean
//constraintsSet.addUndConstraint(new Pair(bool, binary.getType(), PairOperator.EQUALSDOT));
}else{ }else{
throw new NotImplementedException(); throw new NotImplementedException();
} }

View File

@ -369,9 +369,13 @@ public class RuleSet implements IRuleSet{
@Override @Override
public boolean erase1(UnifyPair pair, IFiniteClosure fc) { public boolean erase1(UnifyPair pair, IFiniteClosure fc) {
if(pair.getPairOp() != PairOperator.SMALLERDOT) if((pair.getPairOp() != PairOperator.SMALLERDOT) && (pair.getPairOp() != PairOperator.SMALLERNEQDOT))
return false; return false;
if ((pair.getPairOp() == PairOperator.SMALLERNEQDOT) && (pair.getLhsType().equals(pair.getRhsType()))) {
return false;
}
UnifyType lhsType = pair.getLhsType(); UnifyType lhsType = pair.getLhsType();
if(!(lhsType instanceof ReferenceType) && !(lhsType instanceof PlaceholderType)) if(!(lhsType instanceof ReferenceType) && !(lhsType instanceof PlaceholderType))
return false; return false;

View File

@ -586,8 +586,13 @@ public class TypeUnifyTask extends RecursiveTask<Set<Set<UnifyPair>>> {
protected boolean isUndefinedPairSet(Set<UnifyPair> s) { protected boolean isUndefinedPairSet(Set<UnifyPair> s) {
if (s.size() >= 1 ) {
Boolean ret = s.stream().map(x -> x.isUndefinedPair()).reduce(true, (x,y)-> (x && y)); Boolean ret = s.stream().map(x -> x.isUndefinedPair()).reduce(true, (x,y)-> (x && y));
return ret; return ret;
}
else {
return false;
}
} }
protected boolean isUndefinedPairSetSet(Set<Set<UnifyPair>> s) { protected boolean isUndefinedPairSetSet(Set<Set<UnifyPair>> s) {
@ -789,10 +794,15 @@ public class TypeUnifyTask extends RecursiveTask<Set<Set<UnifyPair>>> {
UnifyType rhsType = pair.getRhsType(); UnifyType rhsType = pair.getRhsType();
// Case 1: (a <. Theta') // Case 1: (a <. Theta')
if(pairOp == PairOperator.SMALLERDOT && lhsType instanceof PlaceholderType) { if (((pairOp == PairOperator.SMALLERDOT) || (pairOp == PairOperator.SMALLERNEQDOT)) && lhsType instanceof PlaceholderType) {
//System.out.println(pair); //System.out.println(pair);
if (first) { //writeLog(pair.toString()+"\n"); if (first) { //writeLog(pair.toString()+"\n");
Set<Set<UnifyPair>> x1 = unifyCase1(pair, fc); Set<Set<UnifyPair>> x1 = unifyCase1(pair, fc);
if (pairOp == PairOperator.SMALLERNEQDOT) {
Set<UnifyType> remElem = new HashSet<>();
remElem.add(pair.getRhsType());
x1.remove(remElem);
}
//System.out.println(x1); //System.out.println(x1);
result.get(0).add(x1); result.get(0).add(x1);
if (x1.isEmpty()) { if (x1.isEmpty()) {
@ -848,10 +858,15 @@ public class TypeUnifyTask extends RecursiveTask<Set<Set<UnifyPair>>> {
// result.get(3).add(unifyCase4((PlaceholderType) lhsType, rhsType, fc)); // result.get(3).add(unifyCase4((PlaceholderType) lhsType, rhsType, fc));
// Case 5: (Theta <. a) // Case 5: (Theta <. a)
else if(pairOp == PairOperator.SMALLERDOT && rhsType instanceof PlaceholderType) else if (((pairOp == PairOperator.SMALLERDOT) || (pairOp == PairOperator.SMALLERNEQDOT)) && rhsType instanceof PlaceholderType)
if (first) { //writeLog(pair.toString()+"\n"); if (first) { //writeLog(pair.toString()+"\n");
Set<Set<UnifyPair>> x1 = unifyCase5(pair, fc); Set<Set<UnifyPair>> x1 = unifyCase5(pair, fc);
result.get(4).add(x1); result.get(4).add(x1);
if (pairOp == PairOperator.SMALLERNEQDOT) {
Set<UnifyType> remElem = new HashSet<>();
remElem.add(pair.getLhsType());
x1.remove(remElem);
}
if (x1.isEmpty()) { if (x1.isEmpty()) {
undefined.add(pair); //Theta ist nicht im FC undefined.add(pair); //Theta ist nicht im FC
} }

View File

@ -17,6 +17,12 @@ public enum PairOperator {
*/ */
SMALLERDOT, SMALLERDOT,
/**
* The smallernedot operator for arguments (T <!=. P) is the same as SMALLERDOT without
* T == P. It is used for operations + / - / * / < / > / ... with the Supertype Number
*/
SMALLERNEQDOT,
/** /**
* The smallerdot operator for arguments (T <.? P) is used to express that * The smallerdot operator for arguments (T <.? P) is used to express that
* T is an element of smArg(P) (or P is an element of grArg(T)) in a CONSTRAINT * T is an element of smArg(P) (or P is an element of grArg(T)) in a CONSTRAINT
@ -35,6 +41,7 @@ public enum PairOperator {
switch (this) { switch (this) {
case SMALLER: return "<"; case SMALLER: return "<";
case SMALLERDOT: return "<."; case SMALLERDOT: return "<.";
case SMALLERNEQDOT: return "<!=.";
case SMALLERDOTWC: return "<.?"; case SMALLERDOTWC: return "<.?";
default: return "=."; // EQUALSDOT default: return "=."; // EQUALSDOT
} }

View File

@ -149,6 +149,9 @@ public class UnifyPair {
UnifyPair other = (UnifyPair) obj; UnifyPair other = (UnifyPair) obj;
if (isUndefinedPair()) { if (isUndefinedPair()) {
if (other.getBasePair() != basePair || (other.getBasePair() == null && basePair == null)) {
return false;
}
if (!other.getBasePair().equals(basePair) || if (!other.getBasePair().equals(basePair) ||
!other.getAllSubstitutions().equals(getAllSubstitutions())) { !other.getAllSubstitutions().equals(getAllSubstitutions())) {
return false; return false;

View File

@ -0,0 +1,40 @@
package bytecode;
import static org.junit.Assert.*;
import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import org.junit.BeforeClass;
import org.junit.Test;
import de.dhbwstuttgart.core.JavaTXCompiler;
public class BinaryTest {
private static String path;
private static File fileToTest;
private static JavaTXCompiler compiler;
private static ClassLoader loader;
private static Class<?> classToTest;
private static String pathToClassFile;
private static Object instanceOfClass;
@BeforeClass
public static void setUpBeforeClass() throws Exception {
path = System.getProperty("user.dir")+"/test/bytecode/javFiles/BinaryInMeth.jav";
fileToTest = new File(path);
compiler = new JavaTXCompiler(fileToTest);
compiler.generateBytecode();
pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/";
loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)});
classToTest = loader.loadClass("BinaryInMeth");
instanceOfClass = classToTest.getDeclaredConstructor().newInstance();
}
@Test
public void test() {
fail("Not yet implemented");
}
}

View File

@ -0,0 +1,44 @@
package bytecode;
import static org.junit.Assert.*;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import org.junit.BeforeClass;
import org.junit.Test;
import de.dhbwstuttgart.core.JavaTXCompiler;
public class FacTest {
private static String path;
private static File fileToTest;
private static JavaTXCompiler compiler;
private static ClassLoader loader;
private static Class<?> classToTest;
private static String pathToClassFile;
private static Object instanceOfClass;
@BeforeClass
public static void setUpBeforeClass() throws Exception {
path = System.getProperty("user.dir")+"/test/bytecode/javFiles/Fac.jav";
fileToTest = new File(path);
compiler = new JavaTXCompiler(fileToTest);
compiler.generateBytecode();
pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/";
loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)});
classToTest = loader.loadClass("Fac");
instanceOfClass = classToTest.getDeclaredConstructor().newInstance();
}
@Test
public void test() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Method getFac = classToTest.getDeclaredMethod("getFac", Integer.class,Integer.class);
Integer result = (Integer) getFac.invoke(instanceOfClass,3);
assertEquals(result, 6);
}
}

View File

@ -29,7 +29,7 @@ public class PlusTest {
compiler = new JavaTXCompiler(fileToTest); compiler = new JavaTXCompiler(fileToTest);
compiler.generateBytecode(); compiler.generateBytecode();
pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/examples/"; pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/";
loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)});
classToTest = loader.loadClass("Plus"); classToTest = loader.loadClass("Plus");
instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); instanceOfClass = classToTest.getDeclaredConstructor().newInstance();

View File

@ -0,0 +1,44 @@
package bytecode;
import static org.junit.Assert.*;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import org.junit.BeforeClass;
import org.junit.Test;
import de.dhbwstuttgart.core.JavaTXCompiler;
public class RelOpsTest {
private static String path;
private static File fileToTest;
private static JavaTXCompiler compiler;
private static ClassLoader loader;
private static Class<?> classToTest;
private static String pathToClassFile;
private static Object instanceOfClass;
@BeforeClass
public static void setUpBeforeClass() throws Exception {
path = System.getProperty("user.dir")+"/test/bytecode/javFiles/RelOps.jav";
fileToTest = new File(path);
compiler = new JavaTXCompiler(fileToTest);
compiler.generateBytecode();
pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/";
loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)});
classToTest = loader.loadClass("RelOps");
instanceOfClass = classToTest.getDeclaredConstructor().newInstance();
}
@Test
public void test() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Method m = classToTest.getDeclaredMethod("m", Integer.class,Integer.class);
Boolean result = (Boolean) m.invoke(instanceOfClass, 7,3);
assertFalse(result);
}
}

View File

@ -0,0 +1,11 @@
import java.lang.Integer;
public class BinaryInMeth {
m(a){
return ++a;
}
m2(a,b){
return m(a+b);
}
}

View File

@ -0,0 +1,16 @@
import java.lang.Integer;
import java.lang.Long;
import java.lang.Double;
public class Fac {
getFac(n){
var res = 1;
var i = 1;
while(i<=n) {
res = res * i;
i++;
}
return res;
}
}

View File

@ -2,7 +2,7 @@ import java.lang.Integer;
import java.util.Vector; import java.util.Vector;
public class Gen{ public class Gen{
Vector<? extends Integer> m(Vector<Integer> v){ Vector<Integer> m(Vector<Integer> v){
return v; return v;
} }
} }

View File

@ -1,3 +1,4 @@
import java.lang.String;
public class Lambda2 public class Lambda2
{ {
@ -23,10 +24,12 @@ public static <I,O> List<O> map(List<I> input, Function<I,O> func) {
} }
class List<A>{ class List<A>{
A get(); /* A get();
void add(A); void add(A);
*/
} }
/*
class Function<A,B>{ class Function<A,B>{
B apply(A a); B apply(A a);
} }
*/

View File

@ -7,19 +7,19 @@ class Matrix extends Vector<Vector<Integer>> {
var ret = new Matrix(); var ret = new Matrix();
var i = 0; var i = 0;
while(i < size()) { while(i < size()) {
var v1 = this.elementAt(i); // var v1 = this.elementAt(i);
var v2 = new Vector<Integer>(); // var v2 = new Vector<Integer>();
var j = 0; // var j = 0;
while(j < v1.size()) { // while(j < v1.size()) {
var erg = 0; // var erg = 0;
var k = 0; // var k = 0;
while(k < v1.size()) { // while(k < v1.size()) {
erg = erg + v1.elementAt(k) // erg = erg + v1.elementAt(k)
* m.elementAt(k).elementAt(j); // * m.elementAt(k).elementAt(j);
k++; } // k++; }
v2.addElement(new Integer(erg)); // v2.addElement(new Integer(erg));
j++; } // j++; }
ret.addElement(v2); // ret.addElement(v2);
i++; i++;
} }
return ret; return ret;

View File

@ -9,7 +9,7 @@ import java.lang.Byte;
public class Op { public class Op {
Integer m(Integer a, Integer b) { m(a, b) {
//var c = a+b; //var c = a+b;
return a+b; return a+b;
} }

View File

@ -0,0 +1,8 @@
import java.lang.Integer;
import java.lang.Boolean;
public class RelOps {
m(a,b){
return a<b;
}
}

View File

@ -1,4 +1,8 @@
import java.lang.Integer; import java.lang.Integer;
// wenn nur ein Import da steht,wird die Type von
// dem Literal 2 Number berechnet => Deswegen kann
// nicht auf den Stack geladen.
import java.lang.Long;
public class While { public class While {
m(x) { m(x) {