Added bytecodeGeneration for PrintStatement and fixed basic MethodCall
This commit is contained in:
parent
194ff3fcf7
commit
07552e704e
@ -54,7 +54,7 @@ public class MethodDecl implements Node {
|
||||
}
|
||||
|
||||
//Need to get the returnType of the method if it is an object
|
||||
// methodContext (class, (returnType, (identifier, parameter)))
|
||||
// methodContext (class, (identifier, (returnType, parameter)))
|
||||
// typeContext (class, (type, identifier))
|
||||
public void codeGen(ClassWriter cw, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, List<FieldDecl> fieldDecls) throws Exception {
|
||||
|
||||
@ -75,6 +75,7 @@ public class MethodDecl implements Node {
|
||||
|
||||
HashMap<String, String> classFields = typeContext.get(classThatContainsMethod);
|
||||
|
||||
//Set the fields of the class
|
||||
for (Map.Entry<String, String> entry : classFields.entrySet()) {
|
||||
String fieldName = entry.getKey();
|
||||
for (FieldDecl field : fieldDecls) {
|
||||
|
@ -5,6 +5,7 @@ import TypeCheck.TypeCheckException;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
@ -34,6 +35,28 @@ public class PrintStatement extends AbstractType implements IStatement {
|
||||
|
||||
@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 {
|
||||
// Load System.out onto the stack
|
||||
mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
|
||||
|
||||
// Load the value of the variable onto the stack
|
||||
int index = -1;
|
||||
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 (index == -1){
|
||||
throw new Exception("Variable " + variableName + " not found");
|
||||
}
|
||||
|
||||
mv.visitVarInsn(Opcodes.ILOAD, index);
|
||||
|
||||
// Call the println method
|
||||
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(I)V", false);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -105,7 +105,7 @@ public class MethodCallStatementExpression extends AbstractType implements IExpr
|
||||
mv.visitFieldInsn(Opcodes.GETFIELD, thisClass, receiver.identifier, "L" + type + ";"); // Load the field onto the stack
|
||||
} else {
|
||||
// It's a local variable
|
||||
int index = localVars.keySet().stream().toList().indexOf(receiver.identifier);
|
||||
int index = localVars.keySet().stream().toList().indexOf(receiver.identifier)+1; // +1 because the first local variable is at index 1, 0 is used for "this"
|
||||
int opcode = type.equals("int") ? Opcodes.ILOAD : Opcodes.ALOAD;
|
||||
mv.visitVarInsn(opcode, index); // Load local variable onto the stack
|
||||
}
|
||||
@ -134,12 +134,12 @@ public class MethodCallStatementExpression extends AbstractType implements IExpr
|
||||
}
|
||||
|
||||
// Invoke the method
|
||||
String descriptor = getMethodDescriptor();
|
||||
String descriptor = getMethodDescriptor(localVars, methodContext);
|
||||
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, methodName, descriptor, false);
|
||||
|
||||
}
|
||||
|
||||
private String getMethodDescriptor() {
|
||||
// ()I
|
||||
private String getMethodDescriptor(LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext) {
|
||||
StringBuilder descriptor = new StringBuilder("(");
|
||||
|
||||
for (IExpression argument : arguments) {
|
||||
@ -166,7 +166,36 @@ public class MethodCallStatementExpression extends AbstractType implements IExpr
|
||||
break;
|
||||
}
|
||||
}
|
||||
descriptor.append(")"); // Methods always return void
|
||||
descriptor.append(")");
|
||||
|
||||
//Return Type
|
||||
String classToSearchMethodIn = localVars.get(receiver.identifier);
|
||||
if (classToSearchMethodIn == null)
|
||||
classToSearchMethodIn = thisClass;
|
||||
|
||||
String returnType = methodContext.get(classToSearchMethodIn).get(methodName).keySet().toArray()[0].toString();
|
||||
|
||||
switch (returnType) {
|
||||
case "int":
|
||||
descriptor.append("I");
|
||||
break;
|
||||
case "boolean":
|
||||
descriptor.append("Z");
|
||||
break;
|
||||
case "char":
|
||||
descriptor.append("C");
|
||||
break;
|
||||
case "void":
|
||||
descriptor.append("V");
|
||||
break;
|
||||
default:
|
||||
// If it is a class reference replace the "." with "/" and return it
|
||||
if (returnType.contains(".")) returnType = returnType.replaceAll("\\.", "/");
|
||||
descriptor.append("L").append(returnType).append(";");
|
||||
break;
|
||||
}
|
||||
System.out.println("Descriptor: " + descriptor.toString());
|
||||
|
||||
return descriptor.toString();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user