diff --git a/src/de/dhbwstuttgart/bytecode/BytecodeGen.java b/src/de/dhbwstuttgart/bytecode/BytecodeGen.java index f54c6779..399abd47 100644 --- a/src/de/dhbwstuttgart/bytecode/BytecodeGen.java +++ b/src/de/dhbwstuttgart/bytecode/BytecodeGen.java @@ -2,7 +2,9 @@ package de.dhbwstuttgart.bytecode; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; +import java.util.LinkedList; import java.util.List; import de.dhbwstuttgart.exceptions.NotImplementedException; @@ -13,6 +15,9 @@ import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; +import de.dhbwstuttgart.bytecode.constraint.ExtendsConstraint; +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint; +import de.dhbwstuttgart.bytecode.constraint.TPHConstraint.Relation; import de.dhbwstuttgart.bytecode.descriptor.DescriptorToString; import de.dhbwstuttgart.bytecode.descriptor.TypeToDescriptor; import de.dhbwstuttgart.bytecode.signature.Signature; @@ -175,8 +180,28 @@ public class BytecodeGen implements ASTVisitor { @Override public void visit(Constructor field) { + System.out.println("ResultSet: "); + resultSet.results.forEach(a->{ + System.out.println(a.getLeft().toString() + " = " + a.getRight().toString()); + }); + System.out.println("---------------"); field.getParameterList().accept(this); + String methParamTypes = field.name+"%%"; + + Iterator itr = field.getParameterList().iterator(); + while(itr.hasNext()) { + FormalParameter fp = itr.next(); + methParamTypes += resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToDescriptor())+";"; +// methParamTypes += resultSet.resolveType(fp.getType()).resolvedType.acceptTV(new TypeToSignature())+";"; + } + + if(methodNameAndParamsT.contains(methParamTypes)) { + return; + } + methodNameAndParamsT.add(methParamTypes); + System.out.println("Method: "+field.name +" , paramsType: "+methParamTypes); + String desc = null; boolean hasGen = false; @@ -190,7 +215,7 @@ public class BytecodeGen implements ASTVisitor { } String sig = null; if(hasGen) { - ArrayList pairs = simplifyPairs(field.name,tphExtractor.allPairs); + ArrayList pairs = simplifyPairs(field.name,tphExtractor.allPairs, tphExtractor.allCons); Signature signature = new Signature(field, genericsAndBounds,methodParamsAndTypes,resultSet,pairs); sig = signature.toString(); } @@ -259,7 +284,11 @@ public class BytecodeGen implements ASTVisitor { /* if method has generics or return type is TPH, create signature */ // zwite operand muss weggelassen werden if(hasGen||resultSet.resolveType(method.getReturnType()).resolvedType.acceptTV(new TypeToString()).equals("TPH")) { - ArrayList pairs = simplifyPairs(method.name,tphExtractor.allPairs); + System.out.println("ALL CONST: " + tphExtractor.allCons.size()); + tphExtractor.allCons.forEach(c->System.out.println(c.toString())); + System.out.println("----------------"); + HashMap> constraints = simplifyPairs(method.name,tphExtractor.allCons); + ArrayList pairs = simplifyPairs(method.name,tphExtractor.allPairs,tphExtractor.allCons); System.out.println(method.name + " => Simplified Pairs: "); pairs.forEach(p->System.out.println(p.TA1.getName() + " -> "+p.TA2.getName())); Signature signature = new Signature(method, genericsAndBoundsMethod, genericsAndBounds,methodParamsAndTypes,resultSet, pairs); @@ -280,9 +309,263 @@ public class BytecodeGen implements ASTVisitor { mv.visitEnd(); } - private ArrayList simplifyPairs(String methodName, ArrayList allPairs) { + private HashMap> simplifyPairs(String name, ArrayList allCons) { + // 1. check if there are any cycles like L set L=R and: + // * remove both constraints + // * substitute L with R in all constraint + // b)no => go to next step + // 2. check the result of step 1 if there are any equal-constraints like L=R, M=R .. + // a) yes => put all such TPhs in a map and define "key-Cons" + // -- key-Cons = TPH < Object -- + // put this Constraint and the + // b) no + // 3. is + ArrayList consToRemove = new ArrayList<>(); + // step 1: + for(TPHConstraint c : allCons) { + + String left = c.getLeft(); + String right = c.getRight(); + if(c.getRel() == Relation.EXTENDS) { + TPHConstraint revCon = getReverseConstraint(allCons,left,right); + if(revCon != null) { + revCon.setRel(Relation.EQUAL); + consToRemove.add(revCon); + c.setRel(Relation.EQUAL); + substituteTPH(allCons,left, right); + } + } + } + System.out.println(); + System.out.println("NEW ALL CONST: " + allCons.size()); + allCons.forEach(c->System.out.println(c.toString())); + System.out.println("----------------"); + allCons.removeAll(consToRemove); + consToRemove = new ArrayList<>(); + + int size = allCons.size(); + + System.out.println("AFTER DELETE ALL CONST: " + allCons.size()); + allCons.forEach(c->System.out.println(c.toString())); + System.out.println("----------------"); + HashMap> result = new HashMap<>(); + + for(TPHConstraint c : allCons) { + if(c.getRel()==Relation.EQUAL) { + HashSet equalTPHs = getEqualsTPHs(result, c); + TPHConstraint constraint = getKeyConstraint(result,c); + equalTPHs.add(c.getLeft()); + equalTPHs.add(c.getRight()); + result.put(constraint, equalTPHs); + consToRemove.add(c); + size--; + } + } + System.out.println("Step 2 Result: "); + result.forEach((c,hs)->{ + System.out.print(c.toString() + " -> "); + hs.forEach(s->{ + System.out.print(s + ", "); + }); + System.out.println(); + }); + System.out.println("----------------"); + allCons.removeAll(consToRemove); + allCons.addAll(result.keySet()); + + if(!allCons.isEmpty() && allCons.size()<2) { + + if(!result.containsKey(allCons.get(0))) + result.put(allCons.get(0), null); + + return result; + } + + size += result.keySet().size(); + + for(TPHConstraint c : allCons) { + if(c.getRight().equals(Type.getInternalName(Object.class))) + size--; + } + + ArrayList methodTphs = new ArrayList<>(); + for(MethodAndTPH m : tphExtractor.ListOfMethodsAndTph) { + if(m.getName().equals(name)) { + methodTphs = m.getTphs(); + break; + } + } + + HashMap subAndSuper = new HashMap<>(); + for(TPHConstraint c : allCons) { + if(subAndSuper.containsKey(c.getLeft())) { + LinkedList all = new LinkedList<>(); + all.add(c.getLeft()); + String sup =c.getRight(); + all.add(sup); + HashMap ss = new HashMap<>(); + for(TPHConstraint constr : allCons) { + ss.put(constr.getLeft(), constr.getRight()); + } + while(ss.containsKey(sup)) { + sup = ss.get(sup); + all.add(sup); + } + if(!containTPH(methodTphs, all.getLast())) + continue; + } + subAndSuper.put(c.getLeft(), c.getRight()); + } + + int numOfVisitedPairs = 0; + for(String sub : subAndSuper.keySet()) { + if(isTPHInConstraint(result,sub)) + continue; + + if(!containTPH(methodTphs,sub)) + continue; + + if(numOfVisitedPairs>=size) + break; + LinkedList tphInRel = new LinkedList<>(); + tphInRel.add(sub); + String superT = subAndSuper.get(sub); + tphInRel.add(superT); + + numOfVisitedPairs++; + boolean isCycle = false; + while(subAndSuper.containsKey(superT)) { + superT = subAndSuper.get(superT); + if(tphInRel.contains(superT)) { + isCycle = true; + break; + } + tphInRel.add(superT); + numOfVisitedPairs++; + } + + // Subtype + String subTphRes = tphInRel.getFirst(); + // Die größte Supertype + String superTphRes = tphInRel.getLast(); + + while(subAndSuper.containsValue(subTphRes)) { + for(String tph : subAndSuper.keySet()) { + if(containTPH(methodTphs,tph) && subAndSuper.get(tph).equals(subTphRes)) { + subTphRes = tph; + break; + } + } + if(subTphRes.equals(tphInRel.getFirst())) { + break; + } + tphInRel.addFirst(subTphRes); + numOfVisitedPairs++; + } + + subTphRes = tphInRel.getFirst(); + + int i = 2; + while(!containTPH(methodTphs,superTphRes) && (tphInRel.size()-i) >0) { + superTphRes = tphInRel.get(tphInRel.size()-i); + i++; + } + + if(!containTPH(methodTphs, superTphRes)) { + result.put(new ExtendsConstraint(subTphRes, Type.getInternalName(Object.class), Relation.EXTENDS), null); + } else { + result.put(new ExtendsConstraint(subTphRes, superTphRes, Relation.EXTENDS), null); + result.put(new ExtendsConstraint(superTphRes, Type.getInternalName(Object.class), Relation.EXTENDS), null); + } + } + System.out.println("ZwischenResult: "); + result.forEach((c,hs)->{ + if(c!=null) { + System.out.print(c.toString() + " -> "); + if(hs == null) { + System.out.print(" [] "); + }else { + hs.forEach(s->{ + System.out.print(s + ", "); + }); + } + } + + + System.out.println(); + }); + System.out.println("----------------"); + return result; + } + + private boolean isTPHInConstraint(HashMap> result, String sub) { + for(TPHConstraint c : result.keySet()) { + if(c.getLeft().equals(sub)) + return true; + } + return false; + } + + private boolean containTPH(ArrayList methodTphs, String sub) { + for(TypePlaceholder tph : methodTphs) { + if(tph.getName().equals(sub)) + return true; + } + return false; + } + + private TPHConstraint getKeyConstraint(HashMap> result, TPHConstraint toFind) { + for(TPHConstraint c : result.keySet()) { + if(c.containTPH(toFind.getLeft()) || c.containTPH(toFind.getRight())) + return c; + } + return new ExtendsConstraint(toFind.getRight(), Type.getInternalName(Object.class), Relation.EXTENDS); + } + + private HashSet getEqualsTPHs(HashMap> result, TPHConstraint toFind) { + for(TPHConstraint c : result.keySet()) { + if(c.containTPH(toFind.getLeft()) || c.containTPH(toFind.getRight())) + return result.get(c); + } + return new HashSet<>(); + } + + private ArrayList simplifyPairs(String methodName, ArrayList allPairs, ArrayList allCons) { allPairs.forEach(p->System.out.print(p.TA1 + " < "+ p.TA2+ " ; ")); + // 1. check if there are any cycles like L set L=R and: + // * remove both constraints + // * substitute L with R in all constraint + // b)no => go to next step + // 2. check the result of step 1 if there are any equal-constraints like L=R, M=R .. + // a) yes + // b) no + ArrayList consToRemove = new ArrayList<>(); + // step 1: + for(TPHConstraint c : allCons) { + + String left = c.getLeft(); + String right = c.getRight(); + if(c.getRel() == Relation.EXTENDS) { + TPHConstraint revCon = getReverseConstraint(allCons,left,right); + if(revCon != null) { + revCon.setRel(Relation.EQUAL); + consToRemove.add(revCon); + c.setRel(Relation.EQUAL); + substituteTPH(allCons,left, right); + } + } + } + System.out.println(); + System.out.println("NEW ALL CONST: " + allCons.size()); + allCons.forEach(c->System.out.println(c.toString())); + System.out.println("----------------"); + allCons.removeAll(consToRemove); + System.out.println("AFTER DELETE ALL CONST: " + allCons.size()); + allCons.forEach(c->System.out.println(c.toString())); + System.out.println("----------------"); if(allPairs.size() < 2) return allPairs; @@ -410,6 +693,26 @@ public class BytecodeGen implements ASTVisitor { return simplifiedPairs; } + private void substituteTPH(ArrayList allCons,String left ,String right) { + allCons.forEach(c->{ + if(c.getRel() == Relation.EXTENDS) { + if(c.getLeft().equals(left)) + c.setLeft(right); + if(c.getRight().equals(left)) + c.setRight(right); + } + }); + } + + private TPHConstraint getReverseConstraint(ArrayList allCons, String left, String right) { + for(TPHConstraint c : allCons) { + if(c.getLeft().equals(right) && c.getRight().equals(left)){ + return c; + } + } + return null; + } + private void removePair(ArrayList simplifiedPairs, TypePlaceholder typePlaceholder, TypePlaceholder typePlaceholder2) { for(GenericInsertPair p : simplifiedPairs) { if(p.TA1.equals(typePlaceholder) && p.TA2.equals(typePlaceholder2)) { @@ -471,16 +774,16 @@ public class BytecodeGen implements ASTVisitor { // ?? @Override public void visit(FieldVar fieldVar) { + System.out.println("In FieldVar ---"); // cw.newField(fieldVar.receiver.toString(), fieldVar.fieldVarName.toString(), fieldVar.getType().toString()); FieldVisitor fv = cw.visitField(Opcodes.ACC_PRIVATE, fieldVar.fieldVarName, "L"+fieldVar.getType()+";", null, null); fv.visitEnd(); } - // access flages?? modifiers @Override public void visit(Field field) { - FieldVisitor fv = cw.visitField(Opcodes.ACC_PRIVATE, field.getName(), "L"+field.getType().toString().replace(".", "/")+";", null, null); - fv.visitEnd(); + System.out.println("In Field ---"); + cw.visitField(field.modifier, field.getName(),resultSet.resolveType(field.getType()).resolvedType.acceptTV(new TypeToSignature()), null, null); } @Override @@ -669,6 +972,7 @@ public class BytecodeGen implements ASTVisitor { Boolean inMethod = false; final ArrayList ListOfMethodsAndTph = new ArrayList<>(); final ArrayList allPairs = new ArrayList<>(); + final ArrayList allCons = new ArrayList<>(); @Override public void visit(TypePlaceholder tph) { @@ -683,6 +987,8 @@ public class BytecodeGen implements ASTVisitor { if(inMethod) methodAndTph.getPairs().add(ag); allPairs.add(ag); + TPHConstraint con = new ExtendsConstraint(ag.TA1.getName(), ag.TA2.getName(), Relation.EXTENDS); + allCons.add(con); } }); } diff --git a/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java b/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java index e35127ed..50ff9b0d 100644 --- a/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java +++ b/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java @@ -71,6 +71,7 @@ public class BytecodeGenMethod implements StatementVisitor { private SourceFile sf; private IStatement statement = null; private boolean isReturnStmt = false; + private boolean isParentBinary = false; private boolean needDUP = false; @@ -211,7 +212,7 @@ public class BytecodeGenMethod implements StatementVisitor { @Override public void visit(BinaryExpr binary) { - + isParentBinary = true; String lexpType = getResolvedType(binary.lexpr.getType()); String rexpType = getResolvedType(binary.rexpr.getType()); @@ -242,12 +243,14 @@ public class BytecodeGenMethod implements StatementVisitor { needDUP = true; binary.rexpr.accept(this); - + + isParentBinary = false; + if (!lexpType.equals(rexpType) && !rexpType.equals(largerType)) doCast(rexpType, largerType); Operator op = binary.operation; - + switch (op) { case ADD: doVisitAddOpInsn(largerType); @@ -665,6 +668,7 @@ public class BytecodeGenMethod implements StatementVisitor { @Override public void visit(MethodCall methodCall) { + boolean parentBinary = isParentBinary; System.out.println("In MethodCall = " + methodCall.name); String receiverName = getResolvedType(methodCall.receiver.getType()); System.out.println("Methods of " + receiverName + " "); @@ -681,7 +685,7 @@ public class BytecodeGenMethod implements StatementVisitor { java.lang.reflect.Method[] methods = cLoader.loadClass(clazz).getMethods(); System.out.println("Methods of " + receiverName + " "); - methodRefl = getMethod(methodCall.name,methods); + methodRefl = getMethod(methodCall.name,methodCall.arglist.getArguments().size(),methods); } catch (Exception e) { // try { @@ -736,16 +740,19 @@ public class BytecodeGenMethod implements StatementVisitor { System.out.println("Methodcall type : " + resultSet.resolveType(methodCall.getType()).resolvedType.acceptTV(new TypeToDescriptor())); String mDesc = ""; List argListMethCall = new LinkedList<>(); + String receiverRefl=""; if(methodRefl == null) { MethodFromMethodCall method = new MethodFromMethodCall(methodCall.arglist, methodCall.getType(), receiverName, genericsAndBoundsMethod, genericsAndBounds); mDesc = method.accept(new DescriptorToString(resultSet)); methodCall.arglist.accept(this); } else { + receiverRefl = methodRefl.getAnnotatedReceiverType().getType().toString(); for(Parameter p:methodRefl.getParameters()) { System.out.println(p.getName() + " und is Primitive = " + p.getType().isPrimitive()); argListMethCall.add(p.getType().isPrimitive()); } + System.out.println("Receiver = " + methodRefl.getAnnotatedReceiverType().getType().toString()); mDesc = getMethodDesc(methodRefl); for (Expression al : methodCall.arglist.getArguments()) { statement = new ArgumentExpr(al); @@ -761,7 +768,7 @@ public class BytecodeGenMethod implements StatementVisitor { // methodCall.arglist.accept(this); // is methodCall.receiver functional Interface)? - if (varsFunInterface.contains(methodCall.receiver.getType())) { + if (varsFunInterface.contains(methodCall.receiver.getType()) || (methodRefl!= null && receiverRefl.contains("interface"))) { mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, clazz.replace(".", "/"), methodCall.name, mDesc, true); } else { @@ -780,8 +787,8 @@ public class BytecodeGenMethod implements StatementVisitor { if(isBinaryExp) doUnboxing(getResolvedType(methodCall.getType())); } - - if(methodRefl == null/* && !isReturnStmt*/) { + System.out.println("ISParent Binary = "+isParentBinary +" -> " + parentBinary); + if(methodRefl == null && (parentBinary || !isReturnStmt)) { if(isBinaryExp) doUnboxing(getResolvedType(methodCall.getType())); } @@ -790,12 +797,13 @@ public class BytecodeGenMethod implements StatementVisitor { /** * @param name name of a method + * @param i number of parameters * @param methods all methods of a class * @return the method in the class file which its name equals the given methode name */ - private java.lang.reflect.Method getMethod(String name, java.lang.reflect.Method[] methods) { + private java.lang.reflect.Method getMethod(String name, int i, java.lang.reflect.Method[] methods) { for(java.lang.reflect.Method m : methods) { - if(name.equals(m.getName())) { + if(name.equals(m.getName()) && i == m.getParameterCount()) { return m; } } @@ -1087,13 +1095,16 @@ public class BytecodeGenMethod implements StatementVisitor { visitIntegerLiteral(((Integer) value).intValue(), false); break; case "java/lang/Long": - visitLongLiteral(((Double) value).longValue(), true); + visitLongLiteral(((Integer) value).longValue(), true); break; case "java/lang/Float": visitFloatLiteral(((Double) value).floatValue()); break; case "java/lang/Double": - visitDoubleLiteral((Double) value); + if(value instanceof Double) + visitDoubleLiteral((Double) value); + if(value instanceof Integer) + visitDoubleLiteral(((Integer) value).doubleValue()); break; case "java/lang/Character": visitCharLiteral((Character) value); @@ -1252,8 +1263,9 @@ public class BytecodeGenMethod implements StatementVisitor { // array slot onto the top of the operand stack. assignLeftSide.field.receiver.accept(this); this.rightSideTemp.accept(this); + System.out.println("Receiver = " + getResolvedType(assignLeftSide.field.receiver.getType())); mv.visitFieldInsn(Opcodes.PUTFIELD, getResolvedType(assignLeftSide.field.receiver.getType()), - assignLeftSide.field.fieldVarName, getResolvedType(assignLeftSide.field.getType())); + assignLeftSide.field.fieldVarName, "L"+getResolvedType(assignLeftSide.field.getType())+";"); } @Override diff --git a/src/de/dhbwstuttgart/bytecode/constraint/EqualConstraint.java b/src/de/dhbwstuttgart/bytecode/constraint/EqualConstraint.java new file mode 100644 index 00000000..fb6cae20 --- /dev/null +++ b/src/de/dhbwstuttgart/bytecode/constraint/EqualConstraint.java @@ -0,0 +1,9 @@ +package de.dhbwstuttgart.bytecode.constraint; + +public class EqualConstraint extends TPHConstraint { + + public EqualConstraint(String left, String right, Relation rel) { + super(left, right, rel); + } + +} diff --git a/src/de/dhbwstuttgart/bytecode/constraint/ExtendsConstraint.java b/src/de/dhbwstuttgart/bytecode/constraint/ExtendsConstraint.java new file mode 100644 index 00000000..6f28e24f --- /dev/null +++ b/src/de/dhbwstuttgart/bytecode/constraint/ExtendsConstraint.java @@ -0,0 +1,9 @@ +package de.dhbwstuttgart.bytecode.constraint; + +public class ExtendsConstraint extends TPHConstraint { + + public ExtendsConstraint(String left, String right, Relation rel) { + super(left, right, rel); + } + +} diff --git a/src/de/dhbwstuttgart/bytecode/constraint/TPHConstraint.java b/src/de/dhbwstuttgart/bytecode/constraint/TPHConstraint.java new file mode 100644 index 00000000..e0f3b4c0 --- /dev/null +++ b/src/de/dhbwstuttgart/bytecode/constraint/TPHConstraint.java @@ -0,0 +1,55 @@ +package de.dhbwstuttgart.bytecode.constraint; + +public class TPHConstraint { + protected String left; + protected String right; + protected Relation rel; + public enum Relation{ + EXTENDS, EQUAL + } + + public TPHConstraint(String left, String right, Relation rel) { + this.left = left; + this.right = right; + this.rel = rel; + } + + public String getLeft() { + return left; + } + + + public String getRight() { + return right; + } + + + public Relation getRel() { + return rel; + } + + public void setLeft(String left) { + this.left = left; + } + + public void setRight(String right) { + this.right = right; + } + + public void setRel(Relation rel) { + this.rel = rel; + } + + public boolean containTPH(String tph) { + return left.equals(tph)||right.equals(tph); + } + + @Override + public String toString() { + if(rel == Relation.EXTENDS) { + return left + " < " + right; + }else { + return left + " = " + right; + } + } +} diff --git a/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java b/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java index 49e83aae..067430e2 100644 --- a/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java +++ b/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java @@ -21,12 +21,14 @@ import java.util.*; public class StatementGenerator { private JavaClassRegistry reg; + private Map fields; //PL 2018-11-01 fields eingefuegt, damit die fields immer die gleiche TPH bekommen private Map localVars; private GenericsRegistry generics; - public StatementGenerator(JavaClassRegistry reg, GenericsRegistry generics, Map localVars){ + public StatementGenerator(JavaClassRegistry reg, GenericsRegistry generics, Map fields, Map localVars){ this.reg = reg; this.generics = generics; + this.fields = fields; this.localVars = localVars; } @@ -238,9 +240,14 @@ public class StatementGenerator { if(localVars.get(expression) != null){ return new LocalVar(expression, localVars.get(expression), offset); }else{ + if(fields.get(expression) != null){//PL 2018-11-01 fields eingefuegt, damit die fields immer die gleiche TPH bekommen + return new FieldVar(new This(offset), expression, fields.get(expression), offset); + + } else { + //kann eigentlich nicht vorkommen //Dann Muss es ein Feld sein! return new FieldVar(new This(offset), expression, TypePlaceholder.fresh(offset), offset); - } + }} } return generateFieldVarOrClassname(expression, offset); } @@ -896,7 +903,7 @@ public class StatementGenerator { for(FormalParameter param : params.getFormalparalist()){ lambdaLocals.put(param.getName(), param.getType()); } - StatementGenerator lambdaGenerator = new StatementGenerator(reg, generics, lambdaLocals); + StatementGenerator lambdaGenerator = new StatementGenerator(reg, generics, fields, lambdaLocals); Block block; if(expression.lambdaBody().expression() != null){ diff --git a/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java b/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java index 73b0e55f..b0331a00 100644 --- a/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java +++ b/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java @@ -33,6 +33,7 @@ public class SyntaxTreeGenerator{ private final GenericsRegistry globalGenerics; private String pkgName = ""; Set imports = new HashSet(); + private Map fields = new HashMap<>(); //PL 2018-11-01 fields eingefuegt, damit die fields immer die gleiche TPH bekommen List fieldInitializations = new ArrayList<>(); @@ -122,7 +123,7 @@ public class SyntaxTreeGenerator{ private Method convert(int modifiers, Java8Parser.MethodHeaderContext header, Java8Parser.MethodBodyContext body, JavaClassName parentClass, RefType superClass, GenericsRegistry localGenerics) { - StatementGenerator stmtGen = new StatementGenerator(reg, localGenerics, new HashMap<>()); + StatementGenerator stmtGen = new StatementGenerator(reg, localGenerics, fields, new HashMap<>()); String name = header.methodDeclarator().Identifier().getText(); GenericDeclarationList gtvDeclarations = new GenericDeclarationList(new ArrayList<>(), header.getStart()); @@ -346,6 +347,7 @@ public class SyntaxTreeGenerator{ } for(Java8Parser.VariableDeclaratorContext varCtx : fieldDeclarationContext.variableDeclaratorList().variableDeclarator()){ String fieldName = convert(varCtx.variableDeclaratorId()); + fields.put(fieldName, fieldType); if(varCtx.variableInitializer() != null){ initializeField(varCtx, fieldType, generics); } @@ -360,7 +362,7 @@ public class SyntaxTreeGenerator{ // Initialize a field by creating implicit constructor. private void initializeField(Java8Parser.VariableDeclaratorContext ctx, RefTypeOrTPHOrWildcardOrGeneric typeOfField, GenericsRegistry generics){ - StatementGenerator statementGenerator = new StatementGenerator(reg, generics, new HashMap<>()); + StatementGenerator statementGenerator = new StatementGenerator(reg, generics, fields, new HashMap<>()); fieldInitializations.add(statementGenerator.generateFieldAssignment(ctx, typeOfField)); } diff --git a/src/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java b/src/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java index 5a9085cd..609600cd 100644 --- a/src/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java +++ b/src/de/dhbwstuttgart/typeinference/typeAlgo/TYPEStmt.java @@ -4,6 +4,7 @@ import de.dhbwstuttgart.exceptions.NotImplementedException; import de.dhbwstuttgart.exceptions.TypeinferenceException; import de.dhbwstuttgart.parser.NullToken; import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal; +import de.dhbwstuttgart.parser.scope.JavaClassName; import de.dhbwstuttgart.syntaxtree.*; import de.dhbwstuttgart.syntaxtree.factory.ASTFactory; import de.dhbwstuttgart.syntaxtree.factory.NameGenerator; @@ -18,6 +19,7 @@ import de.dhbwstuttgart.typeinference.unify.model.PairOperator; import java.util.*; import java.util.stream.Collectors; +import java.util.stream.Stream; public class TYPEStmt implements StatementVisitor{ @@ -370,25 +372,60 @@ public class TYPEStmt implements StatementVisitor{ //PL 2018-06-23 Sie haben einen Typ. Der muesste hier eingefuegt werden //wie hier fuer double gezeigt. Im Momment auskommentiert, weil zu wenige Literaltypen //funktionieren + if (literal.value instanceof Short) { + constraintsSet.addUndConstraint(new Pair(literal.getType(), shortt, PairOperator.EQUALSDOT)); + return; + } + if (literal.value instanceof Byte) { + constraintsSet.addUndConstraint(new Pair(literal.getType(), bytee, PairOperator.EQUALSDOT)); + return; + } + if (literal.value instanceof Float) { + constraintsSet.addUndConstraint(new Pair(literal.getType(), floatt, PairOperator.EQUALSDOT)); + return; + } if (literal.value instanceof Double) { constraintsSet.addUndConstraint(new Pair(literal.getType(), doublee, PairOperator.EQUALSDOT)); return; } - if (literal.value instanceof Double) { + if (literal.value instanceof Long) { constraintsSet.addUndConstraint(new Pair(literal.getType(), longg, PairOperator.EQUALSDOT)); return; } if (literal.value instanceof Integer) { //constraintsSet.addUndConstraint(new Pair(literal.getType(),integer, PairOperator.EQUALSDOT)); // /* + HashSet clNames = info.getAvailableClasses().stream().map(x -> x.getClassName()).collect(Collectors.toCollection(HashSet::new)); Set oderConstraints = new HashSet<>(); Constraint constraint = new Constraint(); constraint.add(new Pair(literal.getType(), integer, PairOperator.EQUALSDOT)); oderConstraints.add(constraint); - constraint = new Constraint(); - constraint.add(new Pair(literal.getType(), doublee, PairOperator.EQUALSDOT)); - oderConstraints.add(constraint); - constraintsSet.addOderConstraint(oderConstraints); + if (clNames.stream().filter(x -> x.toString().equals("java.lang.Double")).findAny().isPresent()) { + constraint = new Constraint(); + constraint.add(new Pair(literal.getType(), doublee, PairOperator.EQUALSDOT)); + oderConstraints.add(constraint); + } + if (clNames.stream().filter(x -> x.toString().equals("java.lang.Long")).findAny().isPresent()) { + constraint = new Constraint(); + constraint.add(new Pair(literal.getType(), longg, PairOperator.EQUALSDOT)); + oderConstraints.add(constraint); + } + if (clNames.stream().filter(x -> x.toString().equals("java.lang.Float")).findAny().isPresent()) { + constraint = new Constraint(); + constraint.add(new Pair(literal.getType(), floatt, PairOperator.EQUALSDOT)); + oderConstraints.add(constraint); + } + if (clNames.stream().filter(x -> x.toString().equals("java.lang.Short")).findAny().isPresent()) { + constraint = new Constraint(); + constraint.add(new Pair(literal.getType(), shortt, PairOperator.EQUALSDOT)); + oderConstraints.add(constraint); + } + if (clNames.stream().filter(x -> x.toString().equals("java.lang.Byte")).findAny().isPresent()) { + constraint = new Constraint(); + constraint.add(new Pair(literal.getType(), bytee, PairOperator.EQUALSDOT)); + oderConstraints.add(constraint); + } + constraintsSet.addOderConstraint(oderConstraints); // */ return; } @@ -484,6 +521,8 @@ public class TYPEStmt implements StatementVisitor{ @Override public void visit(AssignToField assignLeftSide) { //Hier ist kein Code nötig. Es werden keine extra Constraints generiert + //HIER muss Code rein PL 2018-10-24 + assignLeftSide.field.accept(this); } @Override @@ -513,8 +552,10 @@ public class TYPEStmt implements StatementVisitor{ RefTypeOrTPHOrWildcardOrGeneric receiverType = new RefType(assumption.getReceiver().getClassName(), params, forMethod.getOffset()); */ - methodConstraint.add(new Pair(forMethod.receiver.getType(), assumption.getReceiverType(resolver), - PairOperator.SMALLERDOT)); + + RefTypeOrTPHOrWildcardOrGeneric retType = assumption.getReceiverType(resolver); + methodConstraint.add(new Pair(forMethod.receiver.getType(), retType, + PairOperator.SMALLERDOT)); methodConstraint.add(new Pair(assumption.getReturnType(resolver), forMethod.getType(), PairOperator.EQUALSDOT)); methodConstraint.addAll(generateParameterConstraints(forMethod, assumption, info, resolver)); diff --git a/src/de/dhbwstuttgart/typeinference/unify/RuleSet.java b/src/de/dhbwstuttgart/typeinference/unify/RuleSet.java index a48b7db2..d4e6b551 100644 --- a/src/de/dhbwstuttgart/typeinference/unify/RuleSet.java +++ b/src/de/dhbwstuttgart/typeinference/unify/RuleSet.java @@ -782,16 +782,31 @@ public class RuleSet implements IRuleSet{ return Optional.empty(); Set result = new HashSet(); - - result.add(new UnifyPair(funNLhsType.getTypeParams().get(funNLhsType.getTypeParams().size()-1), funNRhsType.getTypeParams().get(funNRhsType.getTypeParams().size()-1), PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair())); - for(int i = 0; i < funNLhsType.getTypeParams().size()-1; i++) { - result.add(new UnifyPair(funNRhsType.getTypeParams().get(i), funNLhsType.getTypeParams().get(i), PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair())); + if (pair.getPairOp() == PairOperator.SMALLERDOT) { + result.add(new UnifyPair(funNLhsType.getTypeParams().get(funNLhsType.getTypeParams().size()-1), funNRhsType.getTypeParams().get(funNRhsType.getTypeParams().size()-1), PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair())); + for(int i = 0; i < funNLhsType.getTypeParams().size()-1; i++) { + result.add(new UnifyPair(funNRhsType.getTypeParams().get(i), funNLhsType.getTypeParams().get(i), PairOperator.SMALLERDOT, pair.getSubstitution(), pair.getBasePair())); + } + } + else {// pair.getPairOp() == PairOperator.EQUALDOT + result.add(new UnifyPair(funNLhsType.getTypeParams().get(funNLhsType.getTypeParams().size()-1), funNRhsType.getTypeParams().get(funNRhsType.getTypeParams().size()-1), PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair())); + for(int i = 0; i < funNLhsType.getTypeParams().size()-1; i++) { + result.add(new UnifyPair(funNRhsType.getTypeParams().get(i), funNLhsType.getTypeParams().get(i), PairOperator.EQUALSDOT, pair.getSubstitution(), pair.getBasePair())); + } } result.stream().forEach(x -> { UnifyType l = x.getLhsType(); if (l instanceof PlaceholderType) { ((PlaceholderType)l).disableWildcardtable(); } UnifyType r = x.getRhsType(); if (r instanceof PlaceholderType) { ((PlaceholderType)r).disableWildcardtable(); } } ); + try { + logFile.write("FUNgreater: " + pair + "\n"); + logFile.write("FUNred: " + result + "\n"); + logFile.flush(); + } + catch (IOException e) { + System.out.println("logFile-Error"); + } return Optional.of(result); } @@ -834,6 +849,14 @@ public class RuleSet implements IRuleSet{ UnifyType r = x.getRhsType(); if (r instanceof PlaceholderType) { ((PlaceholderType)r).disableWildcardtable(); } } ); + try { + logFile.write("FUNgreater: " + pair + "\n"); + logFile.write("FUNgreater: " + result + "\n"); + logFile.flush(); + } + catch (IOException e) { + System.out.println("lofFile-Error"); + } return Optional.of(result); } @@ -876,6 +899,14 @@ public class RuleSet implements IRuleSet{ UnifyType r = x.getRhsType(); if (r instanceof PlaceholderType) { ((PlaceholderType)r).disableWildcardtable(); } } ); + try { + logFile.write("FUNgreater: " + pair + "\n"); + logFile.write("FUNsmaller: " + result + "\n"); + logFile.flush(); + } + catch (IOException e) { + System.out.println("lofFile-Error"); + } return Optional.of(result); } diff --git a/test/bytecode/FieldTest.java b/test/bytecode/FieldTest.java new file mode 100644 index 00000000..a5528b00 --- /dev/null +++ b/test/bytecode/FieldTest.java @@ -0,0 +1,43 @@ +package bytecode; + +import static org.junit.Assert.*; + +import java.io.File; +import java.lang.reflect.Field; + +import org.junit.BeforeClass; +import org.junit.Test; +import java.net.URL; +import java.net.URLClassLoader; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class FieldTest { + + 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/Field.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(System.getProperty("user.dir")+"/testBytecode/generatedBC/"); + pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("Field"); + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + } + + @Test + public void test() { + Field[] fields = classToTest.getFields(); + assertEquals(1, fields.length); + } + +} diff --git a/test/bytecode/MatrixOpTest.java b/test/bytecode/MatrixOpTest.java index 178aa43e..8fe538aa 100644 --- a/test/bytecode/MatrixOpTest.java +++ b/test/bytecode/MatrixOpTest.java @@ -32,9 +32,9 @@ public class MatrixOpTest { fileToTest = new File(path); compiler = new JavaTXCompiler(fileToTest); pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; - compiler.generateBytecode(pathToClassFile); - loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); - classToTest = loader.loadClass("MatrixOP"); +// compiler.generateBytecode(pathToClassFile); +// loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); +// classToTest = loader.loadClass("MatrixOP"); /* Vector> vv = new Vector>(); Vector v1 = new Vector (); diff --git a/test/bytecode/OverloadingSortingTest.java b/test/bytecode/OverloadingSortingTest.java index a781280f..c6df11cd 100644 --- a/test/bytecode/OverloadingSortingTest.java +++ b/test/bytecode/OverloadingSortingTest.java @@ -24,28 +24,28 @@ public class OverloadingSortingTest { private static Class classOL2; private static Object instanceOfClassOL2; - @BeforeClass - public static void setUpBeforeClass() throws Exception { + @Test + public void generateBC() throws Exception { path = System.getProperty("user.dir")+"/test/bytecode/javFiles/Sorting.jav"; fileToTest = new File(path); compiler = new JavaTXCompiler(fileToTest); pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; compiler.generateBytecode(pathToClassFile); - loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); - classToTest = loader.loadClass("Sorting"); - instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); +// loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); +// classToTest = loader.loadClass("Sorting"); +// instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); } - @Test - public void test() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { - Method meth = classToTest.getDeclaredMethod("merge", classToTest); - } - - @Test - public void test2() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { - Method meth = classToTest.getDeclaredMethod("test", classOL2); - String res = (String) meth.invoke(instanceOfClass, instanceOfClassOL2); - assertEquals("Overloading2", res); - } +// @Test +// public void test() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { +// Method meth = classToTest.getDeclaredMethod("merge", classToTest); +// } +// +// @Test +// public void test2() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { +// Method meth = classToTest.getDeclaredMethod("test", classOL2); +// String res = (String) meth.invoke(instanceOfClass, instanceOfClassOL2); +// assertEquals("Overloading2", res); +// } } diff --git a/test/bytecode/YTest.java b/test/bytecode/YTest.java new file mode 100644 index 00000000..80d37c6a --- /dev/null +++ b/test/bytecode/YTest.java @@ -0,0 +1,52 @@ +package bytecode; + +import static org.junit.Assert.assertEquals; + +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.Test; + +import de.dhbwstuttgart.core.JavaTXCompiler; + +public class YTest { + 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; + + @Test + public void generateBC() throws Exception { + path = System.getProperty("user.dir")+"/test/bytecode/javFiles/Y.jav"; + fileToTest = new File(path); + compiler = new JavaTXCompiler(fileToTest); + compiler.generateBytecode(System.getProperty("user.dir")+"/testBytecode/generatedBC/"); + pathToClassFile = System.getProperty("user.dir")+"/testBytecode/generatedBC/"; + loader = new URLClassLoader(new URL[] {new URL("file://"+pathToClassFile)}); + classToTest = loader.loadClass("Y"); + /* + instanceOfClass = classToTest.getDeclaredConstructor().newInstance(); + + Method m = classToTest.getDeclaredMethod("m"); + Class lambda = m.invoke(instanceOfClass).getClass(); + Method apply = lambda.getMethod("apply", Object.class); + + // Damit man auf die Methode zugreifen kann + apply.setAccessible(true); + + Integer i = 77; + + Integer result = (Integer) apply.invoke(m.invoke(instanceOfClass), i); + + assertEquals(77, result); + */ + } + + +} diff --git a/test/bytecode/javFiles/Field.jav b/test/bytecode/javFiles/Field.jav new file mode 100644 index 00000000..b19b2308 --- /dev/null +++ b/test/bytecode/javFiles/Field.jav @@ -0,0 +1,9 @@ +import java.lang.Integer; + +public class Field { + public Integer x = 5; + + m(){ + return x; + } +} \ No newline at end of file diff --git a/test/bytecode/javFiles/Matrix.jav b/test/bytecode/javFiles/Matrix.jav index b3857744..f2073b26 100644 --- a/test/bytecode/javFiles/Matrix.jav +++ b/test/bytecode/javFiles/Matrix.jav @@ -1,5 +1,6 @@ import java.util.Vector; import java.lang.Integer; +//import java.lang.Float; //import java.lang.Byte; import java.lang.Boolean; diff --git a/test/bytecode/javFiles/Sorting.jav b/test/bytecode/javFiles/Sorting.jav index 0c76fa2e..341a1a6b 100644 --- a/test/bytecode/javFiles/Sorting.jav +++ b/test/bytecode/javFiles/Sorting.jav @@ -2,7 +2,7 @@ import java.util.List; import java.util.ArrayList; import java.lang.String; -class Sorting{ +public class Sorting{ merge(a, b){ a.addAll(b); return a; diff --git a/test/bytecode/javFiles/Tph.jav b/test/bytecode/javFiles/Tph.jav index 1160e1a5..9faa570c 100644 --- a/test/bytecode/javFiles/Tph.jav +++ b/test/bytecode/javFiles/Tph.jav @@ -2,7 +2,7 @@ public class Tph { m(a,b){ var c = m2(b); - return c; + return a; // return m2(b); } diff --git a/test/bytecode/javFiles/Y.jav b/test/bytecode/javFiles/Y.jav new file mode 100644 index 00000000..3c3e204d --- /dev/null +++ b/test/bytecode/javFiles/Y.jav @@ -0,0 +1,28 @@ +import java.lang.Integer; + +class Y { + y; + //factorial; + + Y() { + y = f -> t -> f.apply(y.apply(f)).apply(t); + //factorial = y.apply(f -> n -> { if (n == 0) return 1; else return n * f.apply(n - 1); }); + } +} + +/* +ergibt Parse-Error +class fac1 { + factorial; + + fac1() { + var y; + y = new Y<>().y; + factorial = y.apply(f -> n -> { if (n == 0) return 1; else return n * f.apply(n - 1); }); + } + public static void main(String args[]) { + System.out.println(new fac1().factorial.apply(3)); + } + +} +*/ \ No newline at end of file