Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
7daece9b8f
@ -28,7 +28,7 @@ public class Compiler {
|
|||||||
|
|
||||||
public static void main(String[] args) throws Exception{
|
public static void main(String[] args) throws Exception{
|
||||||
|
|
||||||
Path filePath = Paths.get("src/main/java/Input.java");
|
Path filePath = Paths.get("src/main/java/InputTest.java");
|
||||||
|
|
||||||
|
|
||||||
// todo remove this debug info
|
// todo remove this debug info
|
||||||
|
@ -24,7 +24,7 @@ public class TypeCheckHelper {
|
|||||||
}
|
}
|
||||||
public static boolean typeExists(String type, List<String> customTypeslist) {
|
public static boolean typeExists(String type, List<String> customTypeslist) {
|
||||||
|
|
||||||
if(type.equals("int") || type.equals("bool") || type.equals("char")){
|
if(type.equals("int") || type.equals("boolean") || type.equals("char")){
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return customTypeslist.contains(type);
|
return customTypeslist.contains(type);
|
||||||
|
@ -125,7 +125,7 @@ public class MethodDecl implements Node {
|
|||||||
for (Parameter param : parameters.parameterList) {
|
for (Parameter param : parameters.parameterList) {
|
||||||
switch (param.type) {
|
switch (param.type) {
|
||||||
case "int" -> descriptor.append("I");
|
case "int" -> descriptor.append("I");
|
||||||
case "bool" -> descriptor.append("Z");
|
case "boolean" -> descriptor.append("Z");
|
||||||
case "char" -> descriptor.append("C");
|
case "char" -> descriptor.append("C");
|
||||||
case "void" -> descriptor.append("V");
|
case "void" -> descriptor.append("V");
|
||||||
default -> {
|
default -> {
|
||||||
@ -144,11 +144,12 @@ public class MethodDecl implements Node {
|
|||||||
} else {
|
} else {
|
||||||
switch (returnType) {
|
switch (returnType) {
|
||||||
case "int" -> descriptor.append("I");
|
case "int" -> descriptor.append("I");
|
||||||
case "bool" -> descriptor.append("Z");
|
case "boolean" -> descriptor.append("Z");
|
||||||
case "char" -> descriptor.append("C");
|
case "char" -> descriptor.append("C");
|
||||||
case "void" -> descriptor.append("V");
|
case "void" -> descriptor.append("V");
|
||||||
default -> {
|
default -> {
|
||||||
// object
|
// object
|
||||||
|
// methodContext (class, (returnType, (identifier, parameter)))
|
||||||
HashMap<String, HashMap<String, ParameterList>> classMethods = methodContext.get(classThatContainsMethod);
|
HashMap<String, HashMap<String, ParameterList>> classMethods = methodContext.get(classThatContainsMethod);
|
||||||
HashMap<String, ParameterList> methodDetails = classMethods.get(name);
|
HashMap<String, ParameterList> methodDetails = classMethods.get(name);
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ import TypeCheck.TypeCheckException;
|
|||||||
import TypeCheck.TypeCheckResult;
|
import TypeCheck.TypeCheckResult;
|
||||||
import abstractSyntaxTree.Parameter.ParameterList;
|
import abstractSyntaxTree.Parameter.ParameterList;
|
||||||
import org.objectweb.asm.MethodVisitor;
|
import org.objectweb.asm.MethodVisitor;
|
||||||
|
import org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
@ -26,7 +27,11 @@ public class BooleanConstantExpression extends AbstractType implements IExpressi
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) throws Exception {
|
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) throws Exception {
|
||||||
|
if (value){
|
||||||
|
mv.visitInsn(Opcodes.ICONST_1);
|
||||||
|
} else {
|
||||||
|
mv.visitInsn(Opcodes.ICONST_0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public TypeCheckResult getTypeCheckResult() {
|
public TypeCheckResult getTypeCheckResult() {
|
||||||
|
@ -4,6 +4,7 @@ import TypeCheck.AbstractType;
|
|||||||
import TypeCheck.TypeCheckResult;
|
import TypeCheck.TypeCheckResult;
|
||||||
import abstractSyntaxTree.Parameter.ParameterList;
|
import abstractSyntaxTree.Parameter.ParameterList;
|
||||||
import org.objectweb.asm.MethodVisitor;
|
import org.objectweb.asm.MethodVisitor;
|
||||||
|
import org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
@ -25,7 +26,7 @@ public class CharConstantExpression extends AbstractType implements IExpression{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) throws Exception {
|
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) throws Exception {
|
||||||
|
mv.visitIntInsn(Opcodes.BIPUSH, (int) value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -4,6 +4,7 @@ import TypeCheck.AbstractType;
|
|||||||
import TypeCheck.TypeCheckResult;
|
import TypeCheck.TypeCheckResult;
|
||||||
import abstractSyntaxTree.Parameter.ParameterList;
|
import abstractSyntaxTree.Parameter.ParameterList;
|
||||||
import org.objectweb.asm.MethodVisitor;
|
import org.objectweb.asm.MethodVisitor;
|
||||||
|
import org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
@ -27,7 +28,8 @@ public class IntConstantExpression extends AbstractType implements IExpression{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) throws Exception {
|
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) throws Exception {
|
||||||
|
//TODO: When we are finished this can be done more efficiently
|
||||||
|
mv.visitLdcInsn(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -45,12 +45,12 @@ public class LocalVarIdentifier extends AbstractType implements IExpression{
|
|||||||
throw new Exception("Variable " + identifier + " not declared");
|
throw new Exception("Variable " + identifier + " not declared");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load the variable onto the stack
|
// Find the index of the variable
|
||||||
int index = -1;
|
int index = -1;
|
||||||
int counter = 0;
|
int counter = 0;
|
||||||
for (String key : localVars.keySet()){
|
for (String key : localVars.keySet()){
|
||||||
if (key.equals(identifier)){
|
if (key.equals(identifier)){
|
||||||
index = counter;
|
index = counter+1; // +1 because the first local variable is at index 1, 0 is used for "this"
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
counter++;
|
counter++;
|
||||||
@ -65,7 +65,7 @@ public class LocalVarIdentifier extends AbstractType implements IExpression{
|
|||||||
case "int":
|
case "int":
|
||||||
mv.visitVarInsn(Opcodes.ILOAD, index);
|
mv.visitVarInsn(Opcodes.ILOAD, index);
|
||||||
break;
|
break;
|
||||||
case "bool":
|
case "boolean":
|
||||||
mv.visitVarInsn(Opcodes.ILOAD, index);
|
mv.visitVarInsn(Opcodes.ILOAD, index);
|
||||||
break;
|
break;
|
||||||
case "void":
|
case "void":
|
||||||
|
@ -43,15 +43,16 @@ public class LocalVarDecl extends AbstractType implements IStatement{
|
|||||||
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) throws Exception {
|
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) throws Exception {
|
||||||
localVars.put(identifier, type);
|
localVars.put(identifier, type);
|
||||||
|
|
||||||
// Set a default value for the variable --> less problems
|
|
||||||
int index = localVars.size()-1;
|
int index = localVars.size()-1;
|
||||||
|
|
||||||
|
// Set a default value for the variable --> less problems
|
||||||
switch (type){
|
switch (type){
|
||||||
case "int":
|
case "int":
|
||||||
mv.visitInsn(Opcodes.ICONST_0);
|
mv.visitInsn(Opcodes.ICONST_0);
|
||||||
mv.visitVarInsn(Opcodes.ISTORE, index);
|
mv.visitVarInsn(Opcodes.ISTORE, index);
|
||||||
break;
|
break;
|
||||||
case "bool":
|
case "boolean":
|
||||||
mv.visitInsn(Opcodes.ICONST_0);
|
mv.visitInsn(Opcodes.ICONST_0);
|
||||||
mv.visitVarInsn(Opcodes.ISTORE, index);
|
mv.visitVarInsn(Opcodes.ISTORE, index);
|
||||||
break;
|
break;
|
||||||
|
@ -50,7 +50,6 @@ public class ReturnStatement extends AbstractType implements IStatement{
|
|||||||
mv.visitInsn(Opcodes.IRETURN);
|
mv.visitInsn(Opcodes.IRETURN);
|
||||||
} else {
|
} else {
|
||||||
mv.visitInsn(Opcodes.ARETURN);
|
mv.visitInsn(Opcodes.ARETURN);
|
||||||
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
mv.visitInsn(Opcodes.RETURN);
|
mv.visitInsn(Opcodes.RETURN);
|
||||||
|
@ -46,7 +46,7 @@ public class AssignStatementExpression extends AbstractType implements IExpressi
|
|||||||
|
|
||||||
String upperbound = TypeCheckHelper.upperBound(leftType.type, rightType.type);
|
String upperbound = TypeCheckHelper.upperBound(leftType.type, rightType.type);
|
||||||
if(Objects.equals(leftType.type, "boolean"))
|
if(Objects.equals(leftType.type, "boolean"))
|
||||||
leftType.type = "bool";
|
leftType.type = "boolean";
|
||||||
if (!Objects.equals(upperbound, leftType.type)) {
|
if (!Objects.equals(upperbound, leftType.type)) {
|
||||||
throw new TypeCheckException("The upper bound of assignment is not the left type.");
|
throw new TypeCheckException("The upper bound of assignment is not the left type.");
|
||||||
}
|
}
|
||||||
@ -77,7 +77,7 @@ public class AssignStatementExpression extends AbstractType implements IExpressi
|
|||||||
int counter = 0;
|
int counter = 0;
|
||||||
for (String key : localVars.keySet()) {
|
for (String key : localVars.keySet()) {
|
||||||
if (key.equals(varName)) {
|
if (key.equals(varName)) {
|
||||||
index = counter;
|
index = counter+1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
counter++;
|
counter++;
|
||||||
@ -89,8 +89,7 @@ public class AssignStatementExpression extends AbstractType implements IExpressi
|
|||||||
|
|
||||||
String type = localVars.get(localVar.getIdentifier());
|
String type = localVars.get(localVar.getIdentifier());
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "int":
|
case "int", "char", "boolean":
|
||||||
case "bool":
|
|
||||||
mv.visitVarInsn(Opcodes.ISTORE, index);
|
mv.visitVarInsn(Opcodes.ISTORE, index);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -116,7 +115,7 @@ public class AssignStatementExpression extends AbstractType implements IExpressi
|
|||||||
case "int":
|
case "int":
|
||||||
descriptor.append("I");
|
descriptor.append("I");
|
||||||
break;
|
break;
|
||||||
case "bool":
|
case "boolean":
|
||||||
descriptor.append("Z");
|
descriptor.append("Z");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -65,41 +65,45 @@ public class MethodCallStatementExpression extends AbstractType implements IExpr
|
|||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) throws Exception {
|
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) throws Exception {
|
||||||
//Generate Bytecode for the receiver
|
//Generate Bytecode for the receiver
|
||||||
if (classThatHasTheMethodIfNotThis != null) {
|
if (receiver.thisExpression) {
|
||||||
//TODO: classThatHasTheMethodIfNotThis must be an object --> instance of the class not the class itself
|
// If the receiver is "this" then load "this" onto the stack
|
||||||
// This is not finished
|
|
||||||
// Need to call codeGen so it pushes the instance onto the stack, which will be popped of
|
|
||||||
//classThatHasTheMethodIfNotThis.codeGen();
|
|
||||||
|
|
||||||
String descriptor;
|
|
||||||
List<MethodDecl> methodDecls = thisClass.methodDecls;
|
|
||||||
for (MethodDecl methodDecl : methodDecls) {
|
|
||||||
if (methodDecl.name.equals(methodName)) {
|
|
||||||
//Get the method descriptor
|
|
||||||
// descriptor = methodDecl.getMethodDescriptor(methodContext);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, classThatHasTheMethodIfNotThis.name, methodName, descriptor, false);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// Load this onto the stack
|
|
||||||
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
||||||
|
} else if (receiver.instVarExpression != null) {
|
||||||
|
receiver.instVarExpression.codeGen(mv, localVars, typeContext);
|
||||||
|
|
||||||
for (IExpression argument : arguments) {
|
} else if (receiver.newStatementExpression != null) {
|
||||||
argument.codeGen(mv, localVars, typeContext);
|
receiver.newStatementExpression.codeGen(mv, localVars, typeContext);
|
||||||
}
|
|
||||||
|
|
||||||
// Get the method descriptor
|
// Not sure about this part
|
||||||
String descriptor;
|
} else if (receiver.identifier != null) {
|
||||||
List<MethodDecl> methodDecls = thisClass.methodDecls;
|
// Load local variable onto the stack
|
||||||
for (MethodDecl methodDecl : methodDecls) {
|
for (String key : localVars.keySet()) {
|
||||||
if (methodDecl.name.equals(methodName)) {
|
if (key.equals(receiver.identifier)) {
|
||||||
//Get the method descriptor
|
String type = localVars.get(key);
|
||||||
//descriptor = methodDecl.getMethodDescriptor(methodContext);
|
int opcode = type.equals("int") ? Opcodes.ILOAD : Opcodes.ALOAD;
|
||||||
|
mv.visitVarInsn(opcode, Integer.parseInt(key));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, thisClass.name, methodName, descriptor, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Generate Bytecode for the arguments
|
||||||
|
for (IExpression argument : arguments) {
|
||||||
|
argument.codeGen(mv, localVars, typeContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String descriptor;
|
||||||
|
List<MethodDecl> methodDecls = thisClass.methodDecls;
|
||||||
|
for (MethodDecl methodDecl : methodDecls) {
|
||||||
|
if (methodDecl.name.equals(methodName)) {
|
||||||
|
//Get the method descriptor
|
||||||
|
//descriptor = methodDecl.getMethodDescriptor(methodContext); //methodContext is missing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Invoke the method
|
||||||
|
String className = classThatHasTheMethodIfNotThis != null ? classThatHasTheMethodIfNotThis.name : thisClass.name;
|
||||||
|
//mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, className, methodName, descriptor, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -53,6 +53,9 @@ public class NewStatementExpression extends AbstractType implements IExpression,
|
|||||||
|
|
||||||
//Call the constructor
|
//Call the constructor
|
||||||
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, className, "<init>", descriptor, false);
|
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, className, "<init>", descriptor, false);
|
||||||
|
|
||||||
|
// One instance of the class remains now on the stack
|
||||||
|
// Which will then be used in an assignment or method call
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getConstructorDescriptor() {
|
private String getConstructorDescriptor() {
|
||||||
@ -66,7 +69,7 @@ public class NewStatementExpression extends AbstractType implements IExpression,
|
|||||||
case "int":
|
case "int":
|
||||||
descriptor.append("I");
|
descriptor.append("I");
|
||||||
break;
|
break;
|
||||||
case "bool":
|
case "boolean":
|
||||||
descriptor.append("Z");
|
descriptor.append("Z");
|
||||||
break;
|
break;
|
||||||
case "char":
|
case "char":
|
||||||
|
Loading…
Reference in New Issue
Block a user