diff --git a/pom.xml b/pom.xml index 934e9931..28946931 100644 --- a/pom.xml +++ b/pom.xml @@ -54,8 +54,8 @@ http://maven.apache.org/maven-v4_0_0.xsd"> 3.11.0 --enable-preview - 21 - 21 + 22 + 22 diff --git a/resources/bytecode/javFiles/Assign.jav b/resources/bytecode/javFiles/Assign.jav new file mode 100644 index 00000000..06f9a5d6 --- /dev/null +++ b/resources/bytecode/javFiles/Assign.jav @@ -0,0 +1,15 @@ +import java.lang.Integer; + +public class Assign { + public x = 10; + public y = this; + + public call() { + return this; + } + + public m() { + this.call().call().y.x = 20; + return x; + } +} \ No newline at end of file diff --git a/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java b/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java index 72e22284..183292ab 100644 --- a/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java +++ b/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java @@ -14,6 +14,7 @@ import de.dhbwstuttgart.core.JavaTXCompiler; import de.dhbwstuttgart.syntaxtree.*; import de.dhbwstuttgart.syntaxtree.statement.*; import de.dhbwstuttgart.syntaxtree.type.Void; +import de.dhbwstuttgart.target.tree.expression.TargetUnaryOp; import org.antlr.v4.runtime.Token; import de.dhbwstuttgart.exceptions.NotImplementedException; @@ -101,7 +102,6 @@ import de.dhbwstuttgart.parser.scope.JavaClassRegistry; import de.dhbwstuttgart.syntaxtree.type.RefType; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; -import org.stringtemplate.v4.ST; public class StatementGenerator { @@ -586,7 +586,7 @@ public class StatementGenerator { initValue = convert(varDecl.variableInitializer().expression()); } var fieldEntry = fields.get(name.getText()); - return (new Assign(new AssignToField(new FieldVar(new This(varDecl.getStart()), (fieldEntry.modifiers() & Modifier.STATIC) != 0, name.getText(), type, varDecl.getStart())), initValue, name.getStart())); + return (new Assign(new AssignToField(new FieldVar(new This(varDecl.getStart()), name.getText(), type, varDecl.getStart())), initValue, name.getStart())); } private Statement convert(Java17Parser.BreakstmtContext stmt) { @@ -700,8 +700,7 @@ public class StatementGenerator { if (!Objects.isNull(expr.methodCall())) { return convert(expr.methodCall(), expr.expression(), offset); } else if (!Objects.isNull(expr.identifier())) { - // FIXME This is not the right way of handling any of this - return generateLocalOrFieldVarOrClassName(expr.getText(), offset); + return new FieldVar(convert(expr.expression()), expr.identifier().getText(), TypePlaceholder.fresh(expr.identifier().start), offset); } else { // Für alle anderen Optionen, wie Feldzugriff, Aufrufe von super oder explizite // generische Invokationen @@ -777,64 +776,25 @@ public class StatementGenerator { /** * Der Parser kann nicht zwischen einer lokalen Variable, einem Feldzugriff und einer Klassenangabe unterscheiden. - * + * * @param expression * @param offset * @return */ private Expression generateLocalOrFieldVarOrClassName(String expression, Token offset) { - // FIXME Why does this take a String argument??? - String[] parts = expression.split("\\."); - if (parts.length < 2) { - // Check for localVar: - 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 - var field = fields.get(expression); - return new FieldVar(new This(offset), Modifier.isStatic(field.modifiers()), expression, fields.get(expression).type(), offset); - } else if (reg.contains(expression)) { - return generateStaticClassName(expression, offset); - } else { - // lokale Variable wurde ohne "var"-Keyword deklariert und direkt mit Wert versehen - localVars.put(expression, TypePlaceholder.fresh(offset)); - return new LocalVar(expression, localVars.get(expression), offset); - } - } - return generateFieldVarOrClassname(expression, offset); - } - - private Expression generateFieldVarOrClassname(String expression, Token offset) { - String[] parts = expression.split("\\."); - String whole = ""; - Expression receiver = null; - for (String part : parts) { - whole += part; - // Check for Classname: - if (reg.contains(whole)) { - receiver = generateStaticClassName(whole, offset); - break; - } - whole += "."; - } - var fieldName = parts[parts.length - 1]; - - var isStatic = false; - if (parts.length < 2 || parts[0].contentEquals("this")) { - receiver = new This(offset); - isStatic = Modifier.isStatic(fields.get(fieldName).modifiers()); - } else if (parts[0].contentEquals("super")) { - receiver = new Super(TypePlaceholder.fresh(offset), offset); - isStatic = Modifier.isStatic(compiler.getClass(new JavaClassName(superClass.getName().toString())).getField(fieldName).orElseThrow().modifier); - } else if (receiver == null) { // Handelt es sich um keinen Statischen Klassennamen: - String part = expression.substring(0, expression.length() - (1 + parts[parts.length - 1].length())); - receiver = generateLocalOrFieldVarOrClassName(part, offset); + // Check for localVar: + 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).type(), offset); + } else if (reg.contains(expression)) { + return generateStaticClassName(expression, offset); } else { - StaticClassName cname = (StaticClassName) receiver; - var javaClassName = reg.getName(cname.getType().toString()); - isStatic = Modifier.isStatic(compiler.getClass(javaClassName).getField(fieldName).orElseThrow().modifier); + // lokale Variable wurde ohne "var"-Keyword deklariert und direkt mit Wert versehen + localVars.put(expression, TypePlaceholder.fresh(offset)); + return new LocalVar(expression, localVars.get(expression), offset); } - return new FieldVar(receiver, isStatic, fieldName, TypePlaceholder.fresh(offset), offset); } private Expression convert(Java17Parser.ArrayaccessexpressionContext arrayaccess) { @@ -870,10 +830,8 @@ public class StatementGenerator { private Statement convert(AssignexpressionContext expr) { switch (expr.bop.getText()) { case "=": - ExpressionContext leftside = expr.expression(0); - AssignLeftSide leftHandSide = convert(leftside.getText(), leftside.getStart()); - Statement ret = new Assign(leftHandSide, convert(expr.expression(1)), expr.getStart()); - return ret; + AssignLeftSide leftHandSide = convertAssignLHS(convert(expr.expression(0))); + return new Assign(leftHandSide, convert(expr.expression(1)), expr.getStart()); case "+=": case "-=": case "*=": @@ -890,8 +848,8 @@ public class StatementGenerator { } } - private AssignLeftSide convert(String leftHandSide, Token start) { - Expression leftSide = generateLocalOrFieldVarOrClassName(leftHandSide, start); + private AssignLeftSide convertAssignLHS(Expression expr) { + Expression leftSide = expr; if (leftSide instanceof FieldVar) return new AssignToField((FieldVar) leftSide); else if (leftSide instanceof LocalVar) diff --git a/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java b/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java index 78f956ad..40ddafa5 100644 --- a/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java +++ b/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java @@ -269,7 +269,7 @@ public class SyntaxTreeGenerator { } fielddecl.add(new Field(fieldname, fieldtype, fieldmodifiers, fieldoffset)); constructorParameters.add(new FormalParameter(fieldname, fieldtype, fieldoffset)); - FieldVar fieldvar = new FieldVar(new This(offset), false, fieldname, fieldtype, fieldoffset); + FieldVar fieldvar = new FieldVar(new This(offset), fieldname, fieldtype, fieldoffset); constructorStatements.add(new Assign(new AssignToField(fieldvar), new LocalVar(fieldname, fieldtype, fieldoffset), offset)); Statement returnStatement = new Return(fieldvar, offset); methods.add(new Method(allmodifiers.get("public"), fieldname, fieldtype, new ParameterList(new ArrayList<>(), offset), new Block(Arrays.asList(returnStatement), offset), new GenericDeclarationList(new ArrayList<>(), offset), offset)); diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/statement/FieldVar.java b/src/main/java/de/dhbwstuttgart/syntaxtree/statement/FieldVar.java index cb98da4f..9380e951 100644 --- a/src/main/java/de/dhbwstuttgart/syntaxtree/statement/FieldVar.java +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/statement/FieldVar.java @@ -17,13 +17,11 @@ public class FieldVar extends Expression { public final String fieldVarName; public final Expression receiver; - public final boolean isStatic; - public FieldVar(Expression receiver, boolean isStatic, String fieldVarName, RefTypeOrTPHOrWildcardOrGeneric type, Token offset) { + public FieldVar(Expression receiver, String fieldVarName, RefTypeOrTPHOrWildcardOrGeneric type, Token offset) { super(type, offset); this.fieldVarName = fieldVarName; this.receiver = receiver; - this.isStatic = isStatic; } @Override diff --git a/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java b/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java index cedf3a85..60f71f7a 100644 --- a/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java +++ b/src/main/java/de/dhbwstuttgart/target/generate/StatementToTargetExpression.java @@ -1,5 +1,6 @@ package de.dhbwstuttgart.target.generate; +import de.dhbwstuttgart.core.JavaTXCompiler; import de.dhbwstuttgart.exceptions.DebugException; import de.dhbwstuttgart.exceptions.NotImplementedException; import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal; @@ -139,7 +140,11 @@ public class StatementToTargetExpression implements ASTVisitor { @Override public void visit(FieldVar fieldVar) { - result = new TargetFieldVar(converter.convert(fieldVar.getType()), converter.convert(fieldVar.receiver.getType()), fieldVar.isStatic, converter.convert(fieldVar.receiver), fieldVar.fieldVarName); + var isStatic = false; + var type = converter.convert(fieldVar.receiver.getType()); + var clazz = converter.compiler.getClass(new JavaClassName(type.name())); + var field = clazz.getField(fieldVar.fieldVarName).orElseThrow(); + result = new TargetFieldVar(converter.convert(fieldVar.getType()), type, Modifier.isStatic(field.modifier), converter.convert(fieldVar.receiver), fieldVar.fieldVarName); } @Override diff --git a/src/test/java/TestComplete.java b/src/test/java/TestComplete.java index 8f58d93d..2fea6961 100644 --- a/src/test/java/TestComplete.java +++ b/src/test/java/TestComplete.java @@ -1084,6 +1084,15 @@ public class TestComplete { var instance = clazz.getDeclaredConstructor().newInstance(); } + @Test + public void testAssign() throws Exception { + var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Assign.jav"); + var clazz = classFiles.get("Assign"); + var instance = clazz.getDeclaredConstructor().newInstance(); + var m = clazz.getDeclaredMethod("m"); + assertEquals(m.invoke(instance), 20); + } + @Test public void testBug122() throws Exception { var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Bug122.jav");