Merge branch 'master' of https://gitea.hb.dhbw-stuttgart.de/i22022/NichtHaskell
This commit is contained in:
commit
0593d988b4
6
.idea/misc.xml
generated
6
.idea/misc.xml
generated
@ -24,7 +24,11 @@
|
|||||||
</list>
|
</list>
|
||||||
</option>
|
</option>
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_X" default="true" project-jdk-name="openjdk-22" project-jdk-type="JavaSDK">
|
<component name="PWA">
|
||||||
|
<option name="enabled" value="true" />
|
||||||
|
<option name="wasEnabledAtLeastOnce" value="true" />
|
||||||
|
</component>
|
||||||
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_22" default="true" project-jdk-name="openjdk-22" project-jdk-type="JavaSDK">
|
||||||
<output url="file://$PROJECT_DIR$/target" />
|
<output url="file://$PROJECT_DIR$/target" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
BIN
Documentation/DokumentationNichtHaskell.pdf
Normal file
BIN
Documentation/DokumentationNichtHaskell.pdf
Normal file
Binary file not shown.
@ -1,3 +1,3 @@
|
|||||||
Dies ist das Repository des Mini-Java-Compiler-Bauprojekt der Gruppe NichtHaskell für das 4. Semester Informatik der Dualen Hochschule Baden-Württemberg in Stuttgart (Horb).
|
Dies ist das Repository des Mini-Java-Compiler-Bauprojekt der Gruppe NichtHaskell für das 4. Semester Informatik der Dualen Hochschule Baden-Württemberg in Stuttgart (Horb).
|
||||||
|
|
||||||
Alles Weitere ist in der Dokumentation (///verlinken////) unter ///////pfad////// zu finden.
|
Alles weitere ist in der Dokumentation DokumentationNichtHaskell.pdf unter `/Documentation/DokumentationNichtHaskell.pdf` zu finden.
|
BIN
jar/NichtHaskell.jar
Normal file
BIN
jar/NichtHaskell.jar
Normal file
Binary file not shown.
BIN
jar/NichtHaskellCompiler-jar-with-dependencies.jar
Normal file
BIN
jar/NichtHaskellCompiler-jar-with-dependencies.jar
Normal file
Binary file not shown.
1
pom.xml
1
pom.xml
@ -26,6 +26,7 @@
|
|||||||
<mainClass>Compiler</mainClass>
|
<mainClass>Compiler</mainClass>
|
||||||
</manifest>
|
</manifest>
|
||||||
</archive>
|
</archive>
|
||||||
|
<finalName>NichtHaskellCompiler</finalName>
|
||||||
<descriptorRefs>
|
<descriptorRefs>
|
||||||
<descriptorRef>jar-with-dependencies</descriptorRef>
|
<descriptorRef>jar-with-dependencies</descriptorRef>
|
||||||
</descriptorRefs>
|
</descriptorRefs>
|
||||||
|
33
src/main/java/CodeGen/CodeGenHelper.java
Normal file
33
src/main/java/CodeGen/CodeGenHelper.java
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
package CodeGen;
|
||||||
|
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
|
||||||
|
public class CodeGenHelper {
|
||||||
|
|
||||||
|
public static String getFieldDescriptor(String type) {
|
||||||
|
switch (type) {
|
||||||
|
case "int":
|
||||||
|
return "I";
|
||||||
|
case "boolean":
|
||||||
|
return "Z";
|
||||||
|
case "char":
|
||||||
|
return "C";
|
||||||
|
default:
|
||||||
|
return "L" + type + ";";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int GetLocalVarIndex(LinkedHashMap<String, String> localVars, String varToSearchFor) {
|
||||||
|
int index = -1;
|
||||||
|
int counter = 0;
|
||||||
|
for (String key : localVars.keySet()) {
|
||||||
|
if (key.equals(varToSearchFor)) {
|
||||||
|
index = counter + 1; // +1 because the first local variable is at index 1, 0 is used for "this"
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -22,10 +22,11 @@ public class Compiler {
|
|||||||
|
|
||||||
if (args.length < 1) {
|
if (args.length < 1) {
|
||||||
System.out.println("Usage: java -jar Compiler.jar <file_path> [--suppress-details]");
|
System.out.println("Usage: java -jar Compiler.jar <file_path> [--suppress-details]");
|
||||||
return;
|
//return;
|
||||||
}
|
}
|
||||||
|
|
||||||
String filePath = args[0];
|
//String filePath = args[0];
|
||||||
|
String filePath = "src/CharArgument.java";
|
||||||
|
|
||||||
boolean suppressDetails = false;
|
boolean suppressDetails = false;
|
||||||
|
|
||||||
@ -101,6 +102,7 @@ public class Compiler {
|
|||||||
System.out.println("No TypeCheck errors found.");
|
System.out.println("No TypeCheck errors found.");
|
||||||
|
|
||||||
abstractSyntaxTree.codeGen();//todo remove
|
abstractSyntaxTree.codeGen();//todo remove
|
||||||
|
|
||||||
try {
|
try {
|
||||||
abstractSyntaxTree.codeGen();
|
abstractSyntaxTree.codeGen();
|
||||||
}catch (Exception e){
|
}catch (Exception e){
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
class EmptyClass {
|
|
||||||
|
|
||||||
}
|
|
@ -1,40 +0,0 @@
|
|||||||
class FieldAccessAndMethodCalls {
|
|
||||||
public static void main(String[] args) {
|
|
||||||
Class1 c1 = new Class1();
|
|
||||||
int i = c1.c2.c3.m3(1).m2().m1();
|
|
||||||
System.out.println(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Class1{
|
|
||||||
int i1;
|
|
||||||
Class2 c2;
|
|
||||||
public Class1() {
|
|
||||||
this.c2 = new Class2();
|
|
||||||
}
|
|
||||||
public int m1(){
|
|
||||||
return i1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Class2{
|
|
||||||
int i2;
|
|
||||||
Class3 c3;
|
|
||||||
public Class2(){
|
|
||||||
this.c3 = new Class3();
|
|
||||||
}
|
|
||||||
public Class1 m2(){
|
|
||||||
Class1 c1 = new Class1();
|
|
||||||
c1.i1 = i2;
|
|
||||||
return c1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Class3{
|
|
||||||
int i3;
|
|
||||||
public Class2 m3(int i){
|
|
||||||
Class2 c2 = new Class2();
|
|
||||||
c2.i2 = i;
|
|
||||||
return c2;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,12 +1,12 @@
|
|||||||
package abstractSyntaxTree.Class;
|
package abstractSyntaxTree.Class;
|
||||||
|
|
||||||
|
import CodeGen.CodeGenHelper;
|
||||||
import TypeCheck.AbstractType;
|
import TypeCheck.AbstractType;
|
||||||
import TypeCheck.TypeCheckException;
|
import TypeCheck.TypeCheckException;
|
||||||
import TypeCheck.TypeCheckHelper;
|
import TypeCheck.TypeCheckHelper;
|
||||||
import TypeCheck.TypeCheckResult;
|
import TypeCheck.TypeCheckResult;
|
||||||
import abstractSyntaxTree.Expression.IExpression;
|
import abstractSyntaxTree.Expression.IExpression;
|
||||||
import abstractSyntaxTree.Node;
|
import abstractSyntaxTree.Node;
|
||||||
import abstractSyntaxTree.Program;
|
|
||||||
import org.objectweb.asm.ClassWriter;
|
import org.objectweb.asm.ClassWriter;
|
||||||
import org.objectweb.asm.FieldVisitor;
|
import org.objectweb.asm.FieldVisitor;
|
||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
@ -47,23 +47,11 @@ public class FieldDecl extends AbstractType implements Node {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void codeGen(ClassWriter cw) {
|
public void codeGen(ClassWriter cw) {
|
||||||
FieldVisitor fv = cw.visitField(Opcodes.ACC_PUBLIC, identifier, getFieldDescriptor(), null, null);
|
String descriptor = CodeGenHelper.getFieldDescriptor(type);
|
||||||
|
FieldVisitor fv = cw.visitField(Opcodes.ACC_PUBLIC, identifier, descriptor, null, null);
|
||||||
fv.visitEnd();
|
fv.visitEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getFieldDescriptor() {
|
|
||||||
switch (type) {
|
|
||||||
case "int":
|
|
||||||
return "I";
|
|
||||||
case "boolean":
|
|
||||||
return "Z";
|
|
||||||
case "char":
|
|
||||||
return "C";
|
|
||||||
default:
|
|
||||||
return "L" + type + ";";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
|
@ -1,13 +1,12 @@
|
|||||||
package abstractSyntaxTree.Class;
|
package abstractSyntaxTree.Class;
|
||||||
|
|
||||||
|
import CodeGen.CodeGenHelper;
|
||||||
import TypeCheck.TypeCheckException;
|
import TypeCheck.TypeCheckException;
|
||||||
import TypeCheck.TypeCheckResult;
|
import TypeCheck.TypeCheckResult;
|
||||||
import abstractSyntaxTree.Node;
|
import abstractSyntaxTree.Node;
|
||||||
import abstractSyntaxTree.Parameter.Parameter;
|
import abstractSyntaxTree.Parameter.Parameter;
|
||||||
import abstractSyntaxTree.Parameter.ParameterList;
|
import abstractSyntaxTree.Parameter.ParameterList;
|
||||||
import abstractSyntaxTree.Program;
|
|
||||||
import abstractSyntaxTree.Statement.BlockStatement;
|
import abstractSyntaxTree.Statement.BlockStatement;
|
||||||
import abstractSyntaxTree.Statement.IStatement;
|
|
||||||
import org.objectweb.asm.*;
|
import org.objectweb.asm.*;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
@ -91,7 +90,7 @@ public class MethodDecl implements Node {
|
|||||||
default -> mv.visitInsn(Opcodes.ACONST_NULL);
|
default -> mv.visitInsn(Opcodes.ACONST_NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
descriptor = getFieldDescriptor(field.type);
|
descriptor = CodeGenHelper.getFieldDescriptor(field.type);
|
||||||
mv.visitFieldInsn(Opcodes.PUTFIELD, classThatContainsMethod, fieldName, descriptor);
|
mv.visitFieldInsn(Opcodes.PUTFIELD, classThatContainsMethod, fieldName, descriptor);
|
||||||
fieldFound = true;
|
fieldFound = true;
|
||||||
break;
|
break;
|
||||||
@ -215,19 +214,6 @@ public class MethodDecl implements Node {
|
|||||||
return descriptor.toString();
|
return descriptor.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getFieldDescriptor(String type) {
|
|
||||||
switch (type) {
|
|
||||||
case "int":
|
|
||||||
return "I";
|
|
||||||
case "boolean":
|
|
||||||
return "Z";
|
|
||||||
case "char":
|
|
||||||
return "C";
|
|
||||||
default:
|
|
||||||
return "L" + type + ";";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
|
@ -3,7 +3,6 @@ package abstractSyntaxTree.Class;
|
|||||||
import TypeCheck.AbstractType;
|
import TypeCheck.AbstractType;
|
||||||
import TypeCheck.TypeCheckException;
|
import TypeCheck.TypeCheckException;
|
||||||
import TypeCheck.TypeCheckResult;
|
import TypeCheck.TypeCheckResult;
|
||||||
import abstractSyntaxTree.Expression.IExpression;
|
|
||||||
import abstractSyntaxTree.Node;
|
import abstractSyntaxTree.Node;
|
||||||
import abstractSyntaxTree.Parameter.ParameterList;
|
import abstractSyntaxTree.Parameter.ParameterList;
|
||||||
import abstractSyntaxTree.Statement.BlockStatement;
|
import abstractSyntaxTree.Statement.BlockStatement;
|
||||||
|
@ -2,7 +2,6 @@ package abstractSyntaxTree.Datatype;
|
|||||||
|
|
||||||
import TypeCheck.AbstractType;
|
import TypeCheck.AbstractType;
|
||||||
import TypeCheck.TypeCheckResult;
|
import TypeCheck.TypeCheckResult;
|
||||||
import abstractSyntaxTree.Class.RefType;
|
|
||||||
import org.objectweb.asm.*;
|
import org.objectweb.asm.*;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
@ -3,6 +3,7 @@ package abstractSyntaxTree.Datatype;
|
|||||||
import TypeCheck.AbstractType;
|
import TypeCheck.AbstractType;
|
||||||
import TypeCheck.TypeCheckResult;
|
import TypeCheck.TypeCheckResult;
|
||||||
import org.objectweb.asm.MethodVisitor;
|
import org.objectweb.asm.MethodVisitor;
|
||||||
|
import org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
@ -21,11 +22,13 @@ public class CharDatatype extends AbstractType implements IDatatype{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodVisitor mv) throws Exception {
|
public void codeGen(MethodVisitor mv) throws Exception {
|
||||||
|
if (value <= 5) {
|
||||||
// Possible use of BIPUSH and SIPUSH if the value is small enough
|
mv.visitInsn(Opcodes.ICONST_0 + value);
|
||||||
//This saves space in the bytecode which is not very relevant at this point, but could be implemented anyway
|
} else if (value <= Byte.MAX_VALUE) {
|
||||||
|
mv.visitIntInsn(Opcodes.BIPUSH, value);
|
||||||
mv.visitLdcInsn((int)value);
|
} else {
|
||||||
|
mv.visitIntInsn(Opcodes.SIPUSH, value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
|
@ -21,8 +21,6 @@ public class IntDatatype extends AbstractType implements IDatatype{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodVisitor mv) throws Exception {
|
public void codeGen(MethodVisitor mv) throws Exception {
|
||||||
|
|
||||||
//Example of using BIPUSH and SIPUSH for optimizing bytecode size
|
|
||||||
if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE)
|
if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE)
|
||||||
mv.visitIntInsn(Opcodes.BIPUSH, value);
|
mv.visitIntInsn(Opcodes.BIPUSH, value);
|
||||||
else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE)
|
else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE)
|
||||||
|
@ -7,7 +7,6 @@ import TypeCheck.AbstractType;
|
|||||||
import abstractSyntaxTree.Parameter.ParameterList;
|
import abstractSyntaxTree.Parameter.ParameterList;
|
||||||
import org.objectweb.asm.*;
|
import org.objectweb.asm.*;
|
||||||
|
|
||||||
import java.beans.Expression;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
@ -15,8 +14,9 @@ import java.util.Objects;
|
|||||||
public class BinaryExpression extends AbstractType implements IExpression{
|
public class BinaryExpression extends AbstractType implements IExpression{
|
||||||
|
|
||||||
public String operator;
|
public String operator;
|
||||||
public IExpression left; // This needs TypeCheckResult
|
public IExpression left;
|
||||||
public IExpression right;
|
public IExpression right;
|
||||||
|
public String thisClass;
|
||||||
|
|
||||||
public BinaryExpression(String operator, IExpression left, IExpression right) {
|
public BinaryExpression(String operator, IExpression left, IExpression right) {
|
||||||
this.operator = operator;
|
this.operator = operator;
|
||||||
@ -28,6 +28,10 @@ public class BinaryExpression extends AbstractType implements IExpression{
|
|||||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws TypeCheckException {
|
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws TypeCheckException {
|
||||||
TypeCheckResult result = new TypeCheckResult();
|
TypeCheckResult result = new TypeCheckResult();
|
||||||
|
|
||||||
|
if(left instanceof LocalVarIdentifier localVarIdentifier)
|
||||||
|
localVarIdentifier.thisClass = this.thisClass;
|
||||||
|
if(right instanceof LocalVarIdentifier localVarIdentifier)
|
||||||
|
localVarIdentifier.thisClass = this.thisClass;
|
||||||
TypeCheckResult leftType = left.typeCheck(methodContext, typeContext, localVars);
|
TypeCheckResult leftType = left.typeCheck(methodContext, typeContext, localVars);
|
||||||
TypeCheckResult rightType = right.typeCheck(methodContext, typeContext, localVars);
|
TypeCheckResult rightType = right.typeCheck(methodContext, typeContext, localVars);
|
||||||
|
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
package abstractSyntaxTree.Expression;
|
package abstractSyntaxTree.Expression;
|
||||||
|
|
||||||
import TypeCheck.AbstractType;
|
import TypeCheck.AbstractType;
|
||||||
import TypeCheck.TypeCheckException;
|
|
||||||
import TypeCheck.TypeCheckResult;
|
import TypeCheck.TypeCheckResult;
|
||||||
import abstractSyntaxTree.Datatype.BoolDatatype;
|
|
||||||
import abstractSyntaxTree.Parameter.ParameterList;
|
import abstractSyntaxTree.Parameter.ParameterList;
|
||||||
import org.objectweb.asm.MethodVisitor;
|
import org.objectweb.asm.MethodVisitor;
|
||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
|
@ -27,7 +27,13 @@ public class CharConstantExpression extends AbstractType implements IExpression{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext) throws Exception {
|
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext) throws Exception {
|
||||||
mv.visitIntInsn(Opcodes.BIPUSH, (int) value);
|
if (value <= 5) {
|
||||||
|
mv.visitInsn(Opcodes.ICONST_0 + value);
|
||||||
|
} else if (value <= Byte.MAX_VALUE) {
|
||||||
|
mv.visitIntInsn(Opcodes.BIPUSH, value);
|
||||||
|
} else {
|
||||||
|
mv.visitIntInsn(Opcodes.SIPUSH, value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1,13 +1,11 @@
|
|||||||
package abstractSyntaxTree.Expression;
|
package abstractSyntaxTree.Expression;
|
||||||
|
|
||||||
|
import CodeGen.CodeGenHelper;
|
||||||
import TypeCheck.AbstractType;
|
import TypeCheck.AbstractType;
|
||||||
import TypeCheck.TypeCheckException;
|
import TypeCheck.TypeCheckException;
|
||||||
import TypeCheck.TypeCheckResult;
|
import TypeCheck.TypeCheckResult;
|
||||||
import abstractSyntaxTree.Class.RefType;
|
|
||||||
import abstractSyntaxTree.Parameter.ParameterList;
|
import abstractSyntaxTree.Parameter.ParameterList;
|
||||||
import abstractSyntaxTree.StatementExpression.ReceivingMethod;
|
import abstractSyntaxTree.StatementExpression.ReceivingMethod;
|
||||||
import gen.DecafParser;
|
|
||||||
import jdk.jshell.spi.ExecutionControl;
|
|
||||||
import org.objectweb.asm.MethodVisitor;
|
import org.objectweb.asm.MethodVisitor;
|
||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
@ -74,15 +72,7 @@ public class InstVarExpression extends AbstractType implements IExpression {
|
|||||||
|
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
// Load the local variable onto the stack
|
// Load the local variable onto the stack
|
||||||
int index = -1;
|
int index = CodeGenHelper.GetLocalVarIndex(localVars, this.receivers.get(i).identifier);
|
||||||
int counter = 0;
|
|
||||||
for (String key : localVars.keySet()) {
|
|
||||||
if (key.equals(this.receivers.get(i).identifier)) {
|
|
||||||
index = counter + 1; // +1 because the first local variable is at index 1, 0 is used for "this"
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
counter++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (index == -1) {
|
if (index == -1) {
|
||||||
if (typeContext.get(thisClass).get(this.receivers.get(i).identifier) != null) {
|
if (typeContext.get(thisClass).get(this.receivers.get(i).identifier) != null) {
|
||||||
@ -91,7 +81,7 @@ public class InstVarExpression extends AbstractType implements IExpression {
|
|||||||
|
|
||||||
typeOfReciever = typeContext.get(typeOfReciever).get(this.receivers.get(i).identifier);
|
typeOfReciever = typeContext.get(typeOfReciever).get(this.receivers.get(i).identifier);
|
||||||
|
|
||||||
descriptor = getFieldDescriptor(typeContext, typeOfReciever);
|
descriptor = getFieldDescriptor(typeOfReciever);
|
||||||
|
|
||||||
// Load the variable onto the stack
|
// Load the variable onto the stack
|
||||||
mv.visitFieldInsn(Opcodes.GETFIELD, classOfField, receivers.get(i).identifier, descriptor);
|
mv.visitFieldInsn(Opcodes.GETFIELD, classOfField, receivers.get(i).identifier, descriptor);
|
||||||
@ -107,27 +97,13 @@ public class InstVarExpression extends AbstractType implements IExpression {
|
|||||||
|
|
||||||
// Get the class of the receiver
|
// Get the class of the receiver
|
||||||
typeOfReciever = localVars.get(this.receivers.get(i).identifier);
|
typeOfReciever = localVars.get(this.receivers.get(i).identifier);
|
||||||
/*
|
|
||||||
descriptor = getFieldDescriptor(typeContext, typeOfReciever, typeOfReciever);
|
|
||||||
|
|
||||||
mv.visitFieldInsn(Opcodes.GETFIELD, thisClass, fieldName, descriptor);
|
|
||||||
*/
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Not the first receiver
|
// Not the first receiver
|
||||||
else {
|
else {
|
||||||
|
|
||||||
// Load the local variable onto the stack
|
// Load the local variable onto the stack
|
||||||
int index = -1;
|
int index = CodeGenHelper.GetLocalVarIndex(localVars, this.receivers.get(i).identifier);
|
||||||
int counter = 0;
|
|
||||||
for (String key : localVars.keySet()) {
|
|
||||||
if (key.equals(this.receivers.get(i).identifier)) {
|
|
||||||
index = counter + 1; // +1 because the first local variable is at index 1, 0 is used for "this"
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
counter++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (index == -1) {
|
if (index == -1) {
|
||||||
if (typeContext.get(typeOfReciever).get(this.receivers.get(i).identifier) != null) {
|
if (typeContext.get(typeOfReciever).get(this.receivers.get(i).identifier) != null) {
|
||||||
@ -136,7 +112,7 @@ public class InstVarExpression extends AbstractType implements IExpression {
|
|||||||
|
|
||||||
typeOfReciever = typeContext.get(typeOfReciever).get(this.receivers.get(i).identifier);
|
typeOfReciever = typeContext.get(typeOfReciever).get(this.receivers.get(i).identifier);
|
||||||
|
|
||||||
descriptor = getFieldDescriptor(typeContext, typeOfReciever);
|
descriptor = getFieldDescriptor(typeOfReciever);
|
||||||
|
|
||||||
// Load the variable onto the stack
|
// Load the variable onto the stack
|
||||||
mv.visitFieldInsn(Opcodes.GETFIELD, classOfField, receivers.get(i).identifier, descriptor);
|
mv.visitFieldInsn(Opcodes.GETFIELD, classOfField, receivers.get(i).identifier, descriptor);
|
||||||
@ -148,7 +124,7 @@ public class InstVarExpression extends AbstractType implements IExpression {
|
|||||||
} else {
|
} else {
|
||||||
typeOfReciever = localVars.get(this.receivers.get(i).identifier);
|
typeOfReciever = localVars.get(this.receivers.get(i).identifier);
|
||||||
|
|
||||||
descriptor = getFieldDescriptor(typeContext, typeOfReciever);
|
descriptor = getFieldDescriptor(typeOfReciever);
|
||||||
|
|
||||||
mv.visitFieldInsn(Opcodes.GETFIELD, typeOfReciever, fieldName, descriptor);
|
mv.visitFieldInsn(Opcodes.GETFIELD, typeOfReciever, fieldName, descriptor);
|
||||||
}
|
}
|
||||||
@ -157,15 +133,7 @@ public class InstVarExpression extends AbstractType implements IExpression {
|
|||||||
// Load the field in fieldName
|
// Load the field in fieldName
|
||||||
|
|
||||||
// Load the local variable onto the stack
|
// Load the local variable onto the stack
|
||||||
int index = -1;
|
int index = CodeGenHelper.GetLocalVarIndex(localVars, fieldName);
|
||||||
int counter = 0;
|
|
||||||
for (String key : localVars.keySet()) {
|
|
||||||
if (key.equals(fieldName)) {
|
|
||||||
index = counter + 1; // +1 because the first local variable is at index 1, 0 is used for "this"
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
counter++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (index == -1) {
|
if (index == -1) {
|
||||||
if (typeContext.get(typeOfReciever).get(fieldName) != null) {
|
if (typeContext.get(typeOfReciever).get(fieldName) != null) {
|
||||||
@ -174,7 +142,7 @@ public class InstVarExpression extends AbstractType implements IExpression {
|
|||||||
|
|
||||||
typeOfReciever = typeContext.get(typeOfReciever).get(fieldName);
|
typeOfReciever = typeContext.get(typeOfReciever).get(fieldName);
|
||||||
|
|
||||||
descriptor = getFieldDescriptor(typeContext, typeOfReciever);
|
descriptor = getFieldDescriptor(typeOfReciever);
|
||||||
|
|
||||||
// Load the variable onto the stack
|
// Load the variable onto the stack
|
||||||
mv.visitFieldInsn(Opcodes.GETFIELD, classOfField, fieldName, descriptor);
|
mv.visitFieldInsn(Opcodes.GETFIELD, classOfField, fieldName, descriptor);
|
||||||
@ -186,21 +154,13 @@ public class InstVarExpression extends AbstractType implements IExpression {
|
|||||||
} else {
|
} else {
|
||||||
typeOfReciever = localVars.get(fieldName);
|
typeOfReciever = localVars.get(fieldName);
|
||||||
|
|
||||||
descriptor = getFieldDescriptor(typeContext, typeOfReciever);
|
descriptor = getFieldDescriptor(typeOfReciever);
|
||||||
|
|
||||||
mv.visitFieldInsn(Opcodes.GETFIELD, typeOfReciever, fieldName, descriptor);
|
mv.visitFieldInsn(Opcodes.GETFIELD, typeOfReciever, fieldName, descriptor);
|
||||||
}
|
}
|
||||||
} else if (receivers.get(0).thisExpression) {
|
} else if (receivers.get(0).thisExpression) {
|
||||||
// Load the local variable or instVar of this onto the stack
|
// Load the local variable or instVar of this onto the stack
|
||||||
int index = -1;
|
int index = CodeGenHelper.GetLocalVarIndex(localVars, fieldName);
|
||||||
int counter = 0;
|
|
||||||
for (String key : localVars.keySet()) {
|
|
||||||
if (key.equals(fieldName)) {
|
|
||||||
index = counter + 1; // +1 because the first local variable is at index 1, 0 is used for "this"
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
counter++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (index == -1) {
|
if (index == -1) {
|
||||||
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
||||||
@ -210,14 +170,14 @@ public class InstVarExpression extends AbstractType implements IExpression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String fieldType = typeContext.get(thisClass).get(fieldName);
|
String fieldType = typeContext.get(thisClass).get(fieldName);
|
||||||
descriptor = getFieldDescriptor(typeContext, fieldType);
|
descriptor = getFieldDescriptor(fieldType);
|
||||||
|
|
||||||
//Load the field onto the stack
|
//Load the field onto the stack
|
||||||
mv.visitFieldInsn(Opcodes.GETFIELD, thisClass, fieldName, descriptor);
|
mv.visitFieldInsn(Opcodes.GETFIELD, thisClass, fieldName, descriptor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getFieldDescriptor(HashMap<String, HashMap<String, String>> typeContext, String fieldType) {
|
private String getFieldDescriptor(String fieldType) {
|
||||||
StringBuilder descriptor = new StringBuilder();
|
StringBuilder descriptor = new StringBuilder();
|
||||||
|
|
||||||
|
|
||||||
|
@ -28,8 +28,15 @@ public class IntConstantExpression extends AbstractType implements IExpression{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext) throws Exception {
|
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext) throws Exception {
|
||||||
//TODO: When we are finished this can be done more efficiently
|
if (value >= -1 && value <= 5) {
|
||||||
mv.visitLdcInsn(value);
|
mv.visitInsn(Opcodes.ICONST_0 + value);
|
||||||
|
} else if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE) {
|
||||||
|
mv.visitIntInsn(Opcodes.BIPUSH, value);
|
||||||
|
} else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE) {
|
||||||
|
mv.visitIntInsn(Opcodes.SIPUSH, value);
|
||||||
|
} else {
|
||||||
|
mv.visitLdcInsn(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package abstractSyntaxTree.Expression;
|
package abstractSyntaxTree.Expression;
|
||||||
|
|
||||||
|
import CodeGen.CodeGenHelper;
|
||||||
import TypeCheck.AbstractType;
|
import TypeCheck.AbstractType;
|
||||||
import TypeCheck.TypeCheckException;
|
import TypeCheck.TypeCheckException;
|
||||||
import TypeCheck.TypeCheckHelper;
|
|
||||||
import TypeCheck.TypeCheckResult;
|
import TypeCheck.TypeCheckResult;
|
||||||
import org.objectweb.asm.*;
|
import org.objectweb.asm.*;
|
||||||
|
|
||||||
@ -11,7 +11,6 @@ import java.util.LinkedHashMap;
|
|||||||
import abstractSyntaxTree.Parameter.ParameterList;
|
import abstractSyntaxTree.Parameter.ParameterList;
|
||||||
import org.objectweb.asm.MethodVisitor;
|
import org.objectweb.asm.MethodVisitor;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public class LocalVarIdentifier extends AbstractType implements IExpression{
|
public class LocalVarIdentifier extends AbstractType implements IExpression{
|
||||||
@ -52,15 +51,7 @@ public class LocalVarIdentifier extends AbstractType implements IExpression{
|
|||||||
if (localVars.containsKey(identifier)) {
|
if (localVars.containsKey(identifier)) {
|
||||||
type = localVars.get(identifier);
|
type = localVars.get(identifier);
|
||||||
// Find the index of the variable
|
// Find the index of the variable
|
||||||
int index = -1;
|
int index = CodeGenHelper.GetLocalVarIndex(localVars, identifier);
|
||||||
int counter = 0;
|
|
||||||
for (String key : localVars.keySet()) {
|
|
||||||
if (key.equals(identifier)) {
|
|
||||||
index = counter + 1; // +1 because the first local variable is at index 1, 0 is used for "this"
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
counter++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (index == -1) {
|
if (index == -1) {
|
||||||
throw new Exception("Variable " + identifier + " not found");
|
throw new Exception("Variable " + identifier + " not found");
|
||||||
@ -84,25 +75,13 @@ public class LocalVarIdentifier extends AbstractType implements IExpression{
|
|||||||
// Load "this" onto the stack
|
// Load "this" onto the stack
|
||||||
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
||||||
// Get the field from "this"
|
// Get the field from "this"
|
||||||
mv.visitFieldInsn(Opcodes.GETFIELD, thisClass, identifier, getFieldDescriptor(type));
|
String descriptor = CodeGenHelper.getFieldDescriptor(type);
|
||||||
|
|
||||||
|
mv.visitFieldInsn(Opcodes.GETFIELD, thisClass, identifier, descriptor);
|
||||||
} else
|
} else
|
||||||
throw new Exception("Variable " + identifier + " not found");
|
throw new Exception("Variable " + identifier + " not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO move this to a helper class and remove the doubled code in MethodDecl and in other places
|
|
||||||
private String getFieldDescriptor(String type) {
|
|
||||||
switch (type) {
|
|
||||||
case "int":
|
|
||||||
return "I";
|
|
||||||
case "boolean":
|
|
||||||
return "Z";
|
|
||||||
case "char":
|
|
||||||
return "C";
|
|
||||||
default:
|
|
||||||
return "L" + type + ";";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypeCheckResult getTypeCheckResult() {
|
public TypeCheckResult getTypeCheckResult() {
|
||||||
return super.getTypeCheckResult();
|
return super.getTypeCheckResult();
|
||||||
|
@ -2,9 +2,7 @@ package abstractSyntaxTree.Expression;
|
|||||||
|
|
||||||
import TypeCheck.AbstractType;
|
import TypeCheck.AbstractType;
|
||||||
import TypeCheck.TypeCheckException;
|
import TypeCheck.TypeCheckException;
|
||||||
import TypeCheck.TypeCheckHelper;
|
|
||||||
import TypeCheck.TypeCheckResult;
|
import TypeCheck.TypeCheckResult;
|
||||||
import abstractSyntaxTree.Datatype.IDatatype;
|
|
||||||
import abstractSyntaxTree.Parameter.ParameterList;
|
import abstractSyntaxTree.Parameter.ParameterList;
|
||||||
import org.objectweb.asm.MethodVisitor;
|
import org.objectweb.asm.MethodVisitor;
|
||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
|
@ -3,8 +3,6 @@ package abstractSyntaxTree.Statement;
|
|||||||
import TypeCheck.TypeCheckException;
|
import TypeCheck.TypeCheckException;
|
||||||
import TypeCheck.TypeCheckResult;
|
import TypeCheck.TypeCheckResult;
|
||||||
import TypeCheck.AbstractType;
|
import TypeCheck.AbstractType;
|
||||||
import abstractSyntaxTree.Class.FieldDecl;
|
|
||||||
import abstractSyntaxTree.Parameter.Parameter;
|
|
||||||
import abstractSyntaxTree.Parameter.ParameterList;
|
import abstractSyntaxTree.Parameter.ParameterList;
|
||||||
import abstractSyntaxTree.StatementExpression.AssignStatementExpression;
|
import abstractSyntaxTree.StatementExpression.AssignStatementExpression;
|
||||||
import abstractSyntaxTree.StatementExpression.MethodCallStatementExpression;
|
import abstractSyntaxTree.StatementExpression.MethodCallStatementExpression;
|
||||||
@ -77,7 +75,7 @@ public class BlockStatement extends AbstractType implements IStatement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (typeOfCurrentStatement.type.contains(",")) {
|
if (typeOfCurrentStatement.type.contains(",")) {
|
||||||
// else if has 2 returns, all code paths must retrun a value.
|
// else if has 2 returns, all code paths must return a value.
|
||||||
String[] substrings = typeOfCurrentStatement.type.split(",");
|
String[] substrings = typeOfCurrentStatement.type.split(",");
|
||||||
|
|
||||||
String firstType = substrings[0];
|
String firstType = substrings[0];
|
||||||
|
@ -7,8 +7,7 @@ import org.objectweb.asm.MethodVisitor;
|
|||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
public class EmptyStatement extends AbstractType implements IStatement{
|
public class EmptyStatement extends AbstractType implements IStatement{
|
||||||
|
|
||||||
|
@ -9,7 +9,6 @@ import org.objectweb.asm.*;
|
|||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public class IfElseStatement extends AbstractType implements IStatement{
|
public class IfElseStatement extends AbstractType implements IStatement{
|
||||||
@ -54,9 +53,6 @@ public class IfElseStatement extends AbstractType implements IStatement{
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//TODO: There are 2 NOPs and one athrow on the stack between the if-Block and else-Block execution --> I have no idea why
|
|
||||||
// I think they are generated because of the jump operations below and can not be eliminated
|
|
||||||
// as they do not negatively impact the execution of the code logic wise we can ignore them
|
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext) throws Exception {
|
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext) throws Exception {
|
||||||
|
|
||||||
|
@ -9,7 +9,6 @@ import org.objectweb.asm.*;
|
|||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public class IfStatement extends AbstractType implements IStatement{
|
public class IfStatement extends AbstractType implements IStatement{
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package abstractSyntaxTree.Statement;
|
package abstractSyntaxTree.Statement;
|
||||||
|
|
||||||
|
import CodeGen.CodeGenHelper;
|
||||||
import TypeCheck.AbstractType;
|
import TypeCheck.AbstractType;
|
||||||
import TypeCheck.TypeCheckException;
|
import TypeCheck.TypeCheckException;
|
||||||
import TypeCheck.TypeCheckHelper;
|
import TypeCheck.TypeCheckHelper;
|
||||||
@ -7,7 +8,6 @@ import TypeCheck.TypeCheckResult;
|
|||||||
import abstractSyntaxTree.Expression.IExpression;
|
import abstractSyntaxTree.Expression.IExpression;
|
||||||
import abstractSyntaxTree.Expression.LocalVarIdentifier;
|
import abstractSyntaxTree.Expression.LocalVarIdentifier;
|
||||||
import abstractSyntaxTree.Parameter.ParameterList;
|
import abstractSyntaxTree.Parameter.ParameterList;
|
||||||
import abstractSyntaxTree.StatementExpression.AssignStatementExpression;
|
|
||||||
import abstractSyntaxTree.StatementExpression.MethodCallStatementExpression;
|
import abstractSyntaxTree.StatementExpression.MethodCallStatementExpression;
|
||||||
import abstractSyntaxTree.StatementExpression.NewStatementExpression;
|
import abstractSyntaxTree.StatementExpression.NewStatementExpression;
|
||||||
import org.objectweb.asm.MethodVisitor;
|
import org.objectweb.asm.MethodVisitor;
|
||||||
@ -59,15 +59,8 @@ public class LocalVarDecl extends AbstractType implements IStatement{
|
|||||||
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext) throws Exception {
|
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext) throws Exception {
|
||||||
localVars.put(identifier, type);
|
localVars.put(identifier, type);
|
||||||
|
|
||||||
int index = -1;
|
|
||||||
int counter = 0;
|
int index = CodeGenHelper.GetLocalVarIndex(localVars, identifier);
|
||||||
for (String key : localVars.keySet()){
|
|
||||||
if (key.equals(identifier)){
|
|
||||||
index = counter+1; // +1 because the first local variable is at index 1, 0 is used for "this"
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
counter++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (index == -1){
|
if (index == -1){
|
||||||
throw new Exception("Variable " + identifier + " not found");
|
throw new Exception("Variable " + identifier + " not found");
|
||||||
@ -86,7 +79,7 @@ public class LocalVarDecl extends AbstractType implements IStatement{
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// Set a default value for the variable --> less problems
|
// Set a default value for the variable --> fewer problems
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "int", "boolean", "char":
|
case "int", "boolean", "char":
|
||||||
mv.visitInsn(Opcodes.ICONST_0);
|
mv.visitInsn(Opcodes.ICONST_0);
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package abstractSyntaxTree.Statement;
|
package abstractSyntaxTree.Statement;
|
||||||
|
|
||||||
|
import CodeGen.CodeGenHelper;
|
||||||
import TypeCheck.AbstractType;
|
import TypeCheck.AbstractType;
|
||||||
import TypeCheck.TypeCheckException;
|
import TypeCheck.TypeCheckException;
|
||||||
import TypeCheck.TypeCheckResult;
|
import TypeCheck.TypeCheckResult;
|
||||||
@ -51,15 +52,8 @@ public class PrintStatement extends AbstractType implements IStatement {
|
|||||||
mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
|
mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
|
||||||
|
|
||||||
// Load the value of the variable onto the stack
|
// Load the value of the variable onto the stack
|
||||||
int index = -1;
|
int index = CodeGenHelper.GetLocalVarIndex(localVars, variableName);
|
||||||
int counter = 0;
|
|
||||||
for (String key : localVars.keySet()){
|
|
||||||
if (key.equals(variableName)){
|
|
||||||
index = counter+1; // +1 because the first local variable is at index 1, 0 is used for "this"
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
counter++;
|
|
||||||
}
|
|
||||||
// If not a localVar, maybe a class field of this class
|
// If not a localVar, maybe a class field of this class
|
||||||
if (index == -1){
|
if (index == -1){
|
||||||
String typeOfField = typeContext.get(thisClass).get(variableName);
|
String typeOfField = typeContext.get(thisClass).get(variableName);
|
||||||
|
@ -12,7 +12,6 @@ import org.objectweb.asm.*;
|
|||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public class ReturnStatement extends AbstractType implements IStatement{
|
public class ReturnStatement extends AbstractType implements IStatement{
|
||||||
|
@ -9,7 +9,6 @@ import org.objectweb.asm.*;
|
|||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public class WhileStatement extends AbstractType implements IStatement {
|
public class WhileStatement extends AbstractType implements IStatement {
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
package abstractSyntaxTree.StatementExpression;
|
package abstractSyntaxTree.StatementExpression;
|
||||||
|
|
||||||
|
import CodeGen.CodeGenHelper;
|
||||||
import TypeCheck.AbstractType;
|
import TypeCheck.AbstractType;
|
||||||
import TypeCheck.TypeCheckException;
|
import TypeCheck.TypeCheckException;
|
||||||
import TypeCheck.TypeCheckHelper;
|
import TypeCheck.TypeCheckHelper;
|
||||||
import TypeCheck.TypeCheckResult;
|
import TypeCheck.TypeCheckResult;
|
||||||
|
import abstractSyntaxTree.Expression.BinaryExpression;
|
||||||
import abstractSyntaxTree.Expression.IExpression;
|
import abstractSyntaxTree.Expression.IExpression;
|
||||||
import abstractSyntaxTree.Expression.InstVarExpression;
|
import abstractSyntaxTree.Expression.InstVarExpression;
|
||||||
import abstractSyntaxTree.Expression.LocalVarIdentifier;
|
import abstractSyntaxTree.Expression.LocalVarIdentifier;
|
||||||
import abstractSyntaxTree.Parameter.ParameterList;
|
import abstractSyntaxTree.Parameter.ParameterList;
|
||||||
import abstractSyntaxTree.Statement.IStatement;
|
import abstractSyntaxTree.Statement.IStatement;
|
||||||
import abstractSyntaxTree.Statement.WhileStatement;
|
|
||||||
import org.objectweb.asm.*;
|
import org.objectweb.asm.*;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -41,7 +42,7 @@ public class AssignStatementExpression extends AbstractType implements IExpressi
|
|||||||
String identifier = localVarIdentifier.getIdentifier();
|
String identifier = localVarIdentifier.getIdentifier();
|
||||||
leftType.type = localVars.get(identifier);
|
leftType.type = localVars.get(identifier);
|
||||||
|
|
||||||
// local var may be actually instvar of this
|
// local var may be actually instVar of this
|
||||||
if(leftType.type == null){
|
if(leftType.type == null){
|
||||||
leftType.type = typeContext.get(thisClass).get(identifier);
|
leftType.type = typeContext.get(thisClass).get(identifier);
|
||||||
}
|
}
|
||||||
@ -54,6 +55,8 @@ public class AssignStatementExpression extends AbstractType implements IExpressi
|
|||||||
methodCallStatementExpression.thisClass = this.thisClass;
|
methodCallStatementExpression.thisClass = this.thisClass;
|
||||||
if(right instanceof LocalVarIdentifier localVarIdentifierRight)
|
if(right instanceof LocalVarIdentifier localVarIdentifierRight)
|
||||||
localVarIdentifierRight.thisClass = this.thisClass;
|
localVarIdentifierRight.thisClass = this.thisClass;
|
||||||
|
if(right instanceof BinaryExpression binaryExpression)
|
||||||
|
binaryExpression.thisClass = this.thisClass;
|
||||||
|
|
||||||
TypeCheckResult rightType = right.typeCheck(methodContext, typeContext, localVars);
|
TypeCheckResult rightType = right.typeCheck(methodContext, typeContext, localVars);
|
||||||
|
|
||||||
@ -81,15 +84,7 @@ public class AssignStatementExpression extends AbstractType implements IExpressi
|
|||||||
String varName = localVar.getIdentifier();
|
String varName = localVar.getIdentifier();
|
||||||
|
|
||||||
//Get the index of the local variable
|
//Get the index of the local variable
|
||||||
int index = -1;
|
int index = CodeGenHelper.GetLocalVarIndex(localVars, varName);
|
||||||
int counter = 0;
|
|
||||||
for (String key : localVars.keySet()) {
|
|
||||||
if (key.equals(varName)) {
|
|
||||||
index = counter + 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
counter++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (index == -1) {
|
if (index == -1) {
|
||||||
String fieldType = typeContext.get(thisClass).get(varName);
|
String fieldType = typeContext.get(thisClass).get(varName);
|
||||||
@ -129,15 +124,8 @@ public class AssignStatementExpression extends AbstractType implements IExpressi
|
|||||||
// Determine if the reference is this or another object
|
// Determine if the reference is this or another object
|
||||||
if (instVar.receivers.get(0).identifier != null) {
|
if (instVar.receivers.get(0).identifier != null) {
|
||||||
// Load the local variable (another object) onto the stack
|
// Load the local variable (another object) onto the stack
|
||||||
int index = -1;
|
int index = CodeGenHelper.GetLocalVarIndex(localVars, instVar.receivers.get(0).identifier);
|
||||||
int counter = 0;
|
|
||||||
for (String key : localVars.keySet()) {
|
|
||||||
if (key.equals(instVar.receivers.get(0).identifier)) {
|
|
||||||
index = counter + 1; // Local variables start at index 1, 0 is "this"
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
counter++;
|
|
||||||
}
|
|
||||||
if (index == -1) {
|
if (index == -1) {
|
||||||
throw new Exception("Variable " + instVar.receivers.get(0).identifier + " not found");
|
throw new Exception("Variable " + instVar.receivers.get(0).identifier + " not found");
|
||||||
}
|
}
|
||||||
@ -149,10 +137,6 @@ public class AssignStatementExpression extends AbstractType implements IExpressi
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call the codeGen on the right expression which will push the value of the right expression onto the stack
|
|
||||||
//right.codeGen(mv, localVars, typeContext, methodContext);
|
|
||||||
|
|
||||||
|
|
||||||
//Now that the base ref is on the stack, I need to get the next field(s) and store the value in the last field
|
//Now that the base ref is on the stack, I need to get the next field(s) and store the value in the last field
|
||||||
|
|
||||||
String typeOfPrevious = "";
|
String typeOfPrevious = "";
|
||||||
@ -182,7 +166,7 @@ public class AssignStatementExpression extends AbstractType implements IExpressi
|
|||||||
|
|
||||||
currentType = typeContext.get(typeOfPrevious).get(instVar.fieldName);
|
currentType = typeContext.get(typeOfPrevious).get(instVar.fieldName);
|
||||||
|
|
||||||
String descriptor = getFieldDescriptor(currentType, typeContext, instVar.fieldName, thisClass);
|
String descriptor = getFieldDescriptor(currentType, typeContext, instVar.fieldName, typeOfPrevious);
|
||||||
mv.visitFieldInsn(Opcodes.PUTFIELD, typeOfPrevious, instVar.fieldName, descriptor);
|
mv.visitFieldInsn(Opcodes.PUTFIELD, typeOfPrevious, instVar.fieldName, descriptor);
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
@ -202,9 +186,6 @@ public class AssignStatementExpression extends AbstractType implements IExpressi
|
|||||||
//Now we have to implement the logic for the following fields in the chain as the above code
|
//Now we have to implement the logic for the following fields in the chain as the above code
|
||||||
// only handles the first field in the chain
|
// only handles the first field in the chain
|
||||||
|
|
||||||
// For the following fields I only have to call GETFIELD so I load the next reference onto the stack
|
|
||||||
// The fields must be present in "typeOfPrevious"
|
|
||||||
|
|
||||||
currentType = typeContext.get(typeOfPrevious).get(instVar.receivers.get(i).identifier);
|
currentType = typeContext.get(typeOfPrevious).get(instVar.receivers.get(i).identifier);
|
||||||
String descriptor = getFieldDescriptor(currentType, typeContext, instVar.receivers.get(i).identifier, typeOfPrevious);
|
String descriptor = getFieldDescriptor(currentType, typeContext, instVar.receivers.get(i).identifier, typeOfPrevious);
|
||||||
mv.visitFieldInsn(Opcodes.GETFIELD, typeOfPrevious, instVar.receivers.get(i).identifier, descriptor);
|
mv.visitFieldInsn(Opcodes.GETFIELD, typeOfPrevious, instVar.receivers.get(i).identifier, descriptor);
|
||||||
@ -222,8 +203,7 @@ public class AssignStatementExpression extends AbstractType implements IExpressi
|
|||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
//This is finished and right
|
// When a field is accessed directly and without a "this."
|
||||||
// It's for when a field is accessed directly and without a "this."
|
|
||||||
|
|
||||||
//Load the value of the right expression on the stack
|
//Load the value of the right expression on the stack
|
||||||
right.codeGen(mv, localVars, typeContext, methodContext);
|
right.codeGen(mv, localVars, typeContext, methodContext);
|
||||||
@ -240,59 +220,6 @@ public class AssignStatementExpression extends AbstractType implements IExpressi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
// Field is called with "this.xxx"
|
|
||||||
if (instVar.receivers.get(0).thisExpression) {
|
|
||||||
|
|
||||||
// If the chain is only 1 long we can directly store the value in the field
|
|
||||||
// If not we have to load the reference of the field on the stack
|
|
||||||
if(instVar.receivers.size() > 1) {
|
|
||||||
// If first receiver is not this check local then fields of thisClass
|
|
||||||
if (isLocal) {
|
|
||||||
currentType = localVars.get(instVar.receivers.get(i).identifier);
|
|
||||||
} else {
|
|
||||||
currentType = typeContext.get(thisClass).get(instVar.receivers.get(i).identifier);
|
|
||||||
}
|
|
||||||
|
|
||||||
currentType = typeContext.get(thisClass).get(instVar.fieldName);
|
|
||||||
String descriptor = getFieldDescriptor(currentType, typeContext, instVar.fieldName, thisClass);
|
|
||||||
mv.visitFieldInsn(Opcodes.GETFIELD, thisClass, instVar.fieldName, descriptor);
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
// Chain is only 1 long, so we can call PUTFIELD directly
|
|
||||||
|
|
||||||
//Load the value of the right expression on the stack
|
|
||||||
right.codeGen(mv, localVars, typeContext, methodContext);
|
|
||||||
|
|
||||||
currentType = typeContext.get(thisClass).get(instVar.fieldName);
|
|
||||||
String descriptor = getFieldDescriptor(currentType, typeContext, instVar.fieldName, thisClass);
|
|
||||||
mv.visitFieldInsn(Opcodes.PUTFIELD, thisClass, instVar.fieldName, descriptor);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// If first receiver is not this check local then fields of thisClass
|
|
||||||
if (isLocal) {
|
|
||||||
currentType = localVars.get(instVar.receivers.get(i).identifier);
|
|
||||||
} else {
|
|
||||||
currentType = typeContext.get(thisClass).get(instVar.receivers.get(i).identifier);
|
|
||||||
}
|
|
||||||
|
|
||||||
currentType = typeContext.get(typeOfPrevious).get(instVar.fieldName);
|
|
||||||
String descriptor = getFieldDescriptor(currentType, typeContext, instVar.fieldName, typeOfPrevious);
|
|
||||||
mv.visitFieldInsn(Opcodes.GETFIELD, thisClass, instVar.fieldName, descriptor);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
currentType = typeContext.get(typeOfPrevious).get(instVar.receivers.get(i).identifier);
|
|
||||||
String descriptor = getFieldDescriptor(currentType, typeContext, instVar.receivers.get(i).identifier, typeOfPrevious);
|
|
||||||
mv.visitFieldInsn(Opcodes.GETFIELD, typeOfPrevious, instVar.receivers.get(i).identifier, descriptor);
|
|
||||||
typeOfPrevious = currentType;
|
|
||||||
} */
|
|
||||||
|
|
||||||
|
|
||||||
private String getFieldDescriptor(String type, HashMap<String, HashMap<String, String>> typeContext, String varName, String classToSearchFieldIn) {
|
private String getFieldDescriptor(String type, HashMap<String, HashMap<String, String>> typeContext, String varName, String classToSearchFieldIn) {
|
||||||
StringBuilder descriptor = new StringBuilder();
|
StringBuilder descriptor = new StringBuilder();
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
@ -3,13 +3,10 @@ package abstractSyntaxTree.StatementExpression;
|
|||||||
import TypeCheck.AbstractType;
|
import TypeCheck.AbstractType;
|
||||||
import TypeCheck.TypeCheckException;
|
import TypeCheck.TypeCheckException;
|
||||||
import TypeCheck.TypeCheckResult;
|
import TypeCheck.TypeCheckResult;
|
||||||
import abstractSyntaxTree.Class.MethodDecl;
|
|
||||||
import abstractSyntaxTree.Class.RefType;
|
|
||||||
import abstractSyntaxTree.Expression.IExpression;
|
import abstractSyntaxTree.Expression.IExpression;
|
||||||
import abstractSyntaxTree.Parameter.ParameterList;
|
import abstractSyntaxTree.Parameter.ParameterList;
|
||||||
import abstractSyntaxTree.Statement.IStatement;
|
import abstractSyntaxTree.Statement.IStatement;
|
||||||
import jdk.jshell.spi.ExecutionControl;
|
import jdk.jshell.spi.ExecutionControl;
|
||||||
import org.objectweb.asm.ClassWriter;
|
|
||||||
import org.objectweb.asm.MethodVisitor;
|
import org.objectweb.asm.MethodVisitor;
|
||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
@ -17,8 +14,8 @@ import java.util.*;
|
|||||||
|
|
||||||
public class MethodCallStatementExpression extends AbstractType implements IExpression, IStatement {
|
public class MethodCallStatementExpression extends AbstractType implements IExpression, IStatement {
|
||||||
String methodName;
|
String methodName;
|
||||||
List<IExpression> arguments; // Need typecheckresults
|
List<IExpression> arguments;
|
||||||
Receiver receiver; // InstVarExpression und NewStatementExpression Braucht typecheckResult
|
Receiver receiver;
|
||||||
List<ReceivingMethod> receivingMethods;
|
List<ReceivingMethod> receivingMethods;
|
||||||
public String thisClass;
|
public String thisClass;
|
||||||
|
|
||||||
@ -44,7 +41,7 @@ public class MethodCallStatementExpression extends AbstractType implements IExpr
|
|||||||
|
|
||||||
String currentType = "";
|
String currentType = "";
|
||||||
|
|
||||||
// receiver is instvar
|
// receiver is instVar
|
||||||
if (receiver != null) {
|
if (receiver != null) {
|
||||||
if (receiver.instVarExpression != null) {
|
if (receiver.instVarExpression != null) {
|
||||||
receiver.instVarExpression.thisClass = this.thisClass;
|
receiver.instVarExpression.thisClass = this.thisClass;
|
||||||
@ -145,13 +142,11 @@ public class MethodCallStatementExpression extends AbstractType implements IExpr
|
|||||||
owner = returnOfPreviousMethod;
|
owner = returnOfPreviousMethod;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
String descriptor = getMethodDescriptor(methodName, localVars, methodContext, arguments, returnOfPreviousMethod, owner);
|
String descriptor = getMethodDescriptor(methodName, localVars, methodContext, arguments, returnOfPreviousMethod, owner);
|
||||||
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, methodName, descriptor, false);
|
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, methodName, descriptor, false);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ()I
|
|
||||||
private String getMethodDescriptor(String methodName, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, List<IExpression> arguments, String returnOfPreviousMethod, String owner) {
|
private String getMethodDescriptor(String methodName, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, List<IExpression> arguments, String returnOfPreviousMethod, String owner) {
|
||||||
StringBuilder descriptor = new StringBuilder("(");
|
StringBuilder descriptor = new StringBuilder("(");
|
||||||
|
|
||||||
|
@ -6,10 +6,8 @@ import TypeCheck.TypeCheckHelper;
|
|||||||
import TypeCheck.TypeCheckResult;
|
import TypeCheck.TypeCheckResult;
|
||||||
import abstractSyntaxTree.Expression.IExpression;
|
import abstractSyntaxTree.Expression.IExpression;
|
||||||
import abstractSyntaxTree.Expression.InstVarExpression;
|
import abstractSyntaxTree.Expression.InstVarExpression;
|
||||||
import abstractSyntaxTree.Parameter.Parameter;
|
|
||||||
import abstractSyntaxTree.Parameter.ParameterList;
|
import abstractSyntaxTree.Parameter.ParameterList;
|
||||||
import abstractSyntaxTree.Statement.IStatement;
|
import abstractSyntaxTree.Statement.IStatement;
|
||||||
import abstractSyntaxTree.Statement.WhileStatement;
|
|
||||||
import org.objectweb.asm.MethodVisitor;
|
import org.objectweb.asm.MethodVisitor;
|
||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
|
@ -1,16 +1,9 @@
|
|||||||
package abstractSyntaxTree.StatementExpression;
|
package abstractSyntaxTree.StatementExpression;
|
||||||
|
|
||||||
import TypeCheck.TypeCheckException;
|
|
||||||
import TypeCheck.TypeCheckResult;
|
|
||||||
import abstractSyntaxTree.Expression.IExpression;
|
|
||||||
import abstractSyntaxTree.Expression.InstVarExpression;
|
import abstractSyntaxTree.Expression.InstVarExpression;
|
||||||
import abstractSyntaxTree.Node;
|
import abstractSyntaxTree.Node;
|
||||||
import abstractSyntaxTree.Parameter.ParameterList;
|
|
||||||
import abstractSyntaxTree.Statement.IStatement;
|
|
||||||
import org.objectweb.asm.MethodVisitor;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public class Receiver implements Node {
|
public class Receiver implements Node {
|
||||||
|
@ -5,7 +5,6 @@ import abstractSyntaxTree.Expression.IExpression;
|
|||||||
import abstractSyntaxTree.Expression.LocalVarIdentifier;
|
import abstractSyntaxTree.Expression.LocalVarIdentifier;
|
||||||
import abstractSyntaxTree.Node;
|
import abstractSyntaxTree.Node;
|
||||||
import abstractSyntaxTree.Parameter.ParameterList;
|
import abstractSyntaxTree.Parameter.ParameterList;
|
||||||
import abstractSyntaxTree.Statement.LocalVarDecl;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
package abstractSyntaxTree.StatementExpression;
|
|
||||||
|
|
||||||
import abstractSyntaxTree.Expression.IExpression;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class SuperStatementExpression extends MethodCallStatementExpression{
|
|
||||||
public SuperStatementExpression(String methodName, List<IExpression> arguments, List<ReceivingMethod> receivingMethods, Receiver receiver) {
|
|
||||||
super(methodName, receiver, receivingMethods, arguments);
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user