Implemented CodeGen for Assign and MethodCall. But MethodCall is not working at the moment
This commit is contained in:
parent
108b8f63ea
commit
b91174eeee
@ -36,10 +36,6 @@ public class FieldDecl extends AbstractType implements Node {
|
|||||||
//write field table
|
//write field table
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, List<String>>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, List<MethodDecl> fieldsOrMethods) throws Exception {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void codeGen(ClassWriter cw) {
|
public void codeGen(ClassWriter cw) {
|
||||||
//TODO: Do we have fields with initial values? --> No dont think so --> assign
|
//TODO: Do we have fields with initial values? --> No dont think so --> assign
|
||||||
FieldVisitor fv = cw.visitField(Opcodes.ACC_PUBLIC, identifier, getFieldDescriptor(), null, null);
|
FieldVisitor fv = cw.visitField(Opcodes.ACC_PUBLIC, identifier, getFieldDescriptor(), null, null);
|
||||||
@ -47,11 +43,10 @@ public class FieldDecl extends AbstractType implements Node {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private String getFieldDescriptor() {
|
private String getFieldDescriptor() {
|
||||||
//TODO: Maybe we have to check for arrays?
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "int":
|
case "int":
|
||||||
return "I";
|
return "I";
|
||||||
case "bool":
|
case "boolean":
|
||||||
return "Z";
|
return "Z";
|
||||||
case "char":
|
case "char":
|
||||||
return "C";
|
return "C";
|
||||||
|
@ -22,7 +22,8 @@ public class MethodDecl implements Node {
|
|||||||
public String returnType;
|
public String returnType;
|
||||||
public BlockStatement codeBlock;
|
public BlockStatement codeBlock;
|
||||||
|
|
||||||
public HashMap<String, String> localVars;
|
//TODO: Can this be a linked hash map? --> need it to be to get the index of local variables
|
||||||
|
public LinkedHashMap<String, String> localVars;
|
||||||
|
|
||||||
public MethodDecl(String classThatContainsMethod, String returnType, String name, ParameterList parameters, BlockStatement codeBlock){
|
public MethodDecl(String classThatContainsMethod, String returnType, String name, ParameterList parameters, BlockStatement codeBlock){
|
||||||
this.classThatContainsMethod = classThatContainsMethod;
|
this.classThatContainsMethod = classThatContainsMethod;
|
||||||
@ -30,7 +31,7 @@ public class MethodDecl implements Node {
|
|||||||
this.name = name;
|
this.name = name;
|
||||||
this.parameters = parameters;
|
this.parameters = parameters;
|
||||||
this.codeBlock = codeBlock;
|
this.codeBlock = codeBlock;
|
||||||
this.localVars = new HashMap<>();
|
this.localVars = new LinkedHashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext) throws Exception {
|
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext) throws Exception {
|
||||||
|
@ -8,6 +8,7 @@ import org.objectweb.asm.*;
|
|||||||
|
|
||||||
import java.beans.Expression;
|
import java.beans.Expression;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public class BinaryExpression extends AbstractType implements IExpression{
|
public class BinaryExpression extends AbstractType implements IExpression{
|
||||||
@ -66,7 +67,7 @@ public class BinaryExpression extends AbstractType implements IExpression{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodVisitor mv) throws Exception {
|
public void codeGen(MethodVisitor mv, HashMap<String, HashMap<String, String>> typeContext, LinkedHashMap<String, String> localVars) throws Exception {
|
||||||
// Label for the jump instruction
|
// Label for the jump instruction
|
||||||
Label operationFalse = new Label(); //Operation is false
|
Label operationFalse = new Label(); //Operation is false
|
||||||
Label operationTrue = new Label(); //Operation is true
|
Label operationTrue = new Label(); //Operation is true
|
||||||
@ -76,88 +77,88 @@ public class BinaryExpression extends AbstractType implements IExpression{
|
|||||||
// Bytecode for the binary operation
|
// Bytecode for the binary operation
|
||||||
switch (operator) {
|
switch (operator) {
|
||||||
case "&&":
|
case "&&":
|
||||||
left.codeGen(mv);
|
left.codeGen(mv, typeContext, localVars);
|
||||||
mv.visitJumpInsn(Opcodes.IFEQ, operationFalse); // IFEQ --> "if equals to zero" (false) --> if left exp is false
|
mv.visitJumpInsn(Opcodes.IFEQ, operationFalse); // IFEQ --> "if equals to zero" (false) --> if left exp is false
|
||||||
|
|
||||||
right.codeGen(mv);
|
right.codeGen(mv, typeContext, localVars);
|
||||||
mv.visitJumpInsn(Opcodes.IFEQ, operationFalse); // If right exp is false, jump to the end of the whole expression
|
mv.visitJumpInsn(Opcodes.IFEQ, operationFalse); // If right exp is false, jump to the end of the whole expression
|
||||||
|
|
||||||
mv.visitJumpInsn(Opcodes.GOTO, operationTrue); // If it reaches this point, the right exp is true
|
mv.visitJumpInsn(Opcodes.GOTO, operationTrue); // If it reaches this point, the right exp is true
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "||":
|
case "||":
|
||||||
left.codeGen(mv);
|
left.codeGen(mv, typeContext, localVars);
|
||||||
mv.visitJumpInsn(Opcodes.IFNE, operationTrue); // IFNE --> "if not equals to zero" (true) --> if left exp is true
|
mv.visitJumpInsn(Opcodes.IFNE, operationTrue); // IFNE --> "if not equals to zero" (true) --> if left exp is true
|
||||||
|
|
||||||
right.codeGen(mv);
|
right.codeGen(mv, typeContext, localVars);
|
||||||
mv.visitJumpInsn(Opcodes.IFNE, operationTrue);
|
mv.visitJumpInsn(Opcodes.IFNE, operationTrue);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "==":
|
case "==":
|
||||||
// Keep in mind that only primitive types are allowed in this case (at this time)
|
// Keep in mind that only primitive types are allowed in this case (at this time)
|
||||||
|
|
||||||
left.codeGen(mv);
|
left.codeGen(mv, typeContext, localVars);
|
||||||
right.codeGen(mv);
|
right.codeGen(mv, typeContext, localVars);
|
||||||
|
|
||||||
mv.visitJumpInsn(Opcodes.IF_ICMPEQ, operationTrue); // If the two values are equal, jump to the end of the expression
|
mv.visitJumpInsn(Opcodes.IF_ICMPEQ, operationTrue); // If the two values are equal, jump to the end of the expression
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "<":
|
case "<":
|
||||||
left.codeGen(mv);
|
left.codeGen(mv, typeContext, localVars);
|
||||||
right.codeGen(mv);
|
right.codeGen(mv, typeContext, localVars);
|
||||||
|
|
||||||
mv.visitJumpInsn(Opcodes.IF_ICMPLT, operationTrue); // Checks only on less than, not equal
|
mv.visitJumpInsn(Opcodes.IF_ICMPLT, operationTrue); // Checks only on less than, not equal
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ">":
|
case ">":
|
||||||
left.codeGen(mv);
|
left.codeGen(mv, typeContext, localVars);
|
||||||
right.codeGen(mv);
|
right.codeGen(mv, typeContext, localVars);
|
||||||
|
|
||||||
mv.visitJumpInsn(Opcodes.IF_ICMPGT, operationTrue); // Checks only on greater than, not equal
|
mv.visitJumpInsn(Opcodes.IF_ICMPGT, operationTrue); // Checks only on greater than, not equal
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "<=":
|
case "<=":
|
||||||
left.codeGen(mv);
|
left.codeGen(mv, typeContext, localVars);
|
||||||
right.codeGen(mv);
|
right.codeGen(mv, typeContext, localVars);
|
||||||
|
|
||||||
mv.visitJumpInsn(Opcodes.IF_ICMPLE, operationTrue); // Checks on less than OR equal
|
mv.visitJumpInsn(Opcodes.IF_ICMPLE, operationTrue); // Checks on less than OR equal
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ">=":
|
case ">=":
|
||||||
left.codeGen(mv);
|
left.codeGen(mv, typeContext, localVars);
|
||||||
right.codeGen(mv);
|
right.codeGen(mv, typeContext, localVars);
|
||||||
|
|
||||||
mv.visitJumpInsn(Opcodes.IF_ICMPGE, operationTrue); // Checks on greater than OR equal
|
mv.visitJumpInsn(Opcodes.IF_ICMPGE, operationTrue); // Checks on greater than OR equal
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "!=":
|
case "!=":
|
||||||
left.codeGen(mv);
|
left.codeGen(mv, typeContext, localVars);
|
||||||
right.codeGen(mv);
|
right.codeGen(mv, typeContext, localVars);
|
||||||
|
|
||||||
mv.visitJumpInsn(Opcodes.IF_ICMPNE, operationTrue); // Checks on not equal
|
mv.visitJumpInsn(Opcodes.IF_ICMPNE, operationTrue); // Checks on not equal
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "+":
|
case "+":
|
||||||
left.codeGen(mv);
|
left.codeGen(mv, typeContext, localVars);
|
||||||
right.codeGen(mv);
|
right.codeGen(mv, typeContext, localVars);
|
||||||
mv.visitInsn(Opcodes.IADD);
|
mv.visitInsn(Opcodes.IADD);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "-":
|
case "-":
|
||||||
left.codeGen(mv);
|
left.codeGen(mv, typeContext, localVars);
|
||||||
right.codeGen(mv);
|
right.codeGen(mv, typeContext, localVars);
|
||||||
mv.visitInsn(Opcodes.ISUB);
|
mv.visitInsn(Opcodes.ISUB);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "*":
|
case "*":
|
||||||
left.codeGen(mv);
|
left.codeGen(mv, typeContext, localVars);
|
||||||
right.codeGen(mv);
|
right.codeGen(mv, typeContext, localVars);
|
||||||
mv.visitInsn(Opcodes.IMUL);
|
mv.visitInsn(Opcodes.IMUL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "/":
|
case "/":
|
||||||
left.codeGen(mv);
|
left.codeGen(mv, typeContext, localVars);
|
||||||
right.codeGen(mv);
|
right.codeGen(mv, typeContext, localVars);
|
||||||
mv.visitInsn(Opcodes.IDIV);
|
mv.visitInsn(Opcodes.IDIV);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ import abstractSyntaxTree.Parameter.ParameterList;
|
|||||||
import org.objectweb.asm.MethodVisitor;
|
import org.objectweb.asm.MethodVisitor;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
|
||||||
public interface IExpression {
|
public interface IExpression {
|
||||||
// typeCheck method
|
// typeCheck method
|
||||||
@ -12,5 +13,5 @@ public interface IExpression {
|
|||||||
TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception;
|
TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception;
|
||||||
|
|
||||||
// visit method for code generation
|
// visit method for code generation
|
||||||
void codeGen(MethodVisitor mv) throws Exception;
|
void codeGen(MethodVisitor mv, HashMap<String, HashMap<String, String>> typeContext, LinkedHashMap<String, String> localVars) throws Exception;
|
||||||
}
|
}
|
||||||
|
@ -5,15 +5,17 @@ import abstractSyntaxTree.Class.RefType;
|
|||||||
import abstractSyntaxTree.Parameter.ParameterList;
|
import abstractSyntaxTree.Parameter.ParameterList;
|
||||||
import jdk.jshell.spi.ExecutionControl;
|
import jdk.jshell.spi.ExecutionControl;
|
||||||
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;
|
||||||
|
|
||||||
public class InstVarExpression implements IExpression{
|
public class InstVarExpression implements IExpression{
|
||||||
|
|
||||||
//TODO: We have to decide upon more parameters and where they come from, for
|
//TODO: We have to decide upon more parameters and where they come from, for
|
||||||
// example here we need the index of the field, the class reference and the field name
|
// example here we need the index of the field, the class reference and the field name
|
||||||
private RefType classRef;
|
public RefType classRef;
|
||||||
private String fieldName;
|
public String fieldName;
|
||||||
|
|
||||||
public InstVarExpression(RefType classRef, String fieldName){
|
public InstVarExpression(RefType classRef, String fieldName){
|
||||||
this.classRef = classRef;
|
this.classRef = classRef;
|
||||||
@ -29,11 +31,33 @@ public class InstVarExpression implements IExpression{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodVisitor mv) throws Exception {
|
// typeContext: (ClassName, (FieldName, FieldType))
|
||||||
throw new ExecutionControl.NotImplementedException("CodeGen not implemented for InstVarExpression");
|
public void codeGen(MethodVisitor mv, HashMap<String, HashMap<String, String>> typeContext, LinkedHashMap<String, String> localVars) throws Exception {
|
||||||
|
// Load "this" onto the stack
|
||||||
|
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
||||||
|
|
||||||
//ALOAD the index of the var
|
//Get the field information
|
||||||
//GETFIELD the field
|
String fieldType = typeContext.get(classRef.name).get(fieldName);
|
||||||
//visitFieldInsn(Opcodes.GETFIELD, "class reference", "field name", type);
|
|
||||||
|
String fieldDescriptor;
|
||||||
|
|
||||||
|
switch (fieldType) {
|
||||||
|
case "int":
|
||||||
|
fieldDescriptor = "I";
|
||||||
|
break;
|
||||||
|
case "boolean":
|
||||||
|
fieldDescriptor = "Z";
|
||||||
|
break;
|
||||||
|
case "char":
|
||||||
|
fieldDescriptor = "C";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
//TODO: We need the fully qualified name of the class here in field type
|
||||||
|
fieldDescriptor = "L" + fieldType + ";";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load the variable onto the stack
|
||||||
|
mv.visitFieldInsn(Opcodes.GETFIELD, classRef.name, fieldName, fieldDescriptor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,10 @@ package abstractSyntaxTree.Expression;
|
|||||||
|
|
||||||
import TypeCheck.TypeCheckHelper;
|
import TypeCheck.TypeCheckHelper;
|
||||||
import TypeCheck.TypeCheckResult;
|
import TypeCheck.TypeCheckResult;
|
||||||
import org.objectweb.asm.MethodVisitor;
|
import org.objectweb.asm.*;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
|
||||||
public class LocalVarIdentifier implements IExpression{
|
public class LocalVarIdentifier implements IExpression{
|
||||||
|
|
||||||
@ -21,7 +24,41 @@ public class LocalVarIdentifier implements IExpression{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodVisitor mv) throws Exception {
|
public void codeGen(MethodVisitor mv, HashMap<String, HashMap<String, String>> typeContext, LinkedHashMap<String, String> localVars) throws Exception {
|
||||||
|
// Check if the variable is in the list of local variables
|
||||||
|
String type = localVars.get(identifier);
|
||||||
|
if (type == null){
|
||||||
|
throw new Exception("Variable " + identifier + " not declared");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load the variable onto the stack
|
||||||
|
int index = -1;
|
||||||
|
int counter = 0;
|
||||||
|
for (String key : localVars.keySet()){
|
||||||
|
if (key.equals(identifier)){
|
||||||
|
index = counter;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index == -1){
|
||||||
|
throw new Exception("Variable " + identifier + " not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load the variable onto the stack
|
||||||
|
switch (type){
|
||||||
|
case "int":
|
||||||
|
mv.visitVarInsn(Opcodes.ILOAD, index);
|
||||||
|
break;
|
||||||
|
case "bool":
|
||||||
|
mv.visitVarInsn(Opcodes.ILOAD, index);
|
||||||
|
break;
|
||||||
|
case "void":
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
mv.visitVarInsn(Opcodes.ALOAD, index);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,8 @@ import abstractSyntaxTree.Datatype.IDatatype;
|
|||||||
import org.objectweb.asm.MethodVisitor;
|
import org.objectweb.asm.MethodVisitor;
|
||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public class UnaryExpression extends AbstractType implements IExpression{
|
public class UnaryExpression extends AbstractType implements IExpression{
|
||||||
@ -47,7 +49,7 @@ public class UnaryExpression extends AbstractType implements IExpression{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodVisitor mv) throws Exception {
|
public void codeGen(MethodVisitor mv, HashMap<String, HashMap<String, String>> typeContext, LinkedHashMap<String, String> localVars) throws Exception {
|
||||||
|
|
||||||
operand.codeGen(mv);
|
operand.codeGen(mv);
|
||||||
|
|
||||||
|
@ -6,11 +6,14 @@ import abstractSyntaxTree.Parameter.ParameterList;
|
|||||||
import org.objectweb.asm.MethodVisitor;
|
import org.objectweb.asm.MethodVisitor;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public interface IStatement extends Node {
|
public interface IStatement extends Node {
|
||||||
|
|
||||||
TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception;
|
TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception;
|
||||||
|
|
||||||
void codeGen(MethodVisitor mv, HashMap<String, String> localVars) throws Exception;
|
void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars) throws Exception;
|
||||||
|
|
||||||
|
void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) throws Exception;
|
||||||
}
|
}
|
||||||
|
@ -32,5 +32,24 @@ public class LocalVarDecl implements IStatement{
|
|||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodVisitor mv, HashMap<String, String> localVars) throws Exception {
|
public void codeGen(MethodVisitor mv, HashMap<String, String> localVars) throws Exception {
|
||||||
localVars.put(identifier, type);
|
localVars.put(identifier, type);
|
||||||
|
|
||||||
|
// Set a default value for the variable --> less problems
|
||||||
|
int index = localVars.size()-1;
|
||||||
|
|
||||||
|
switch (type){
|
||||||
|
case "int":
|
||||||
|
mv.visitInsn(Opcodes.ICONST_0);
|
||||||
|
mv.visitVarInsn(Opcodes.ISTORE, index);
|
||||||
|
break;
|
||||||
|
case "bool":
|
||||||
|
mv.visitInsn(Opcodes.ICONST_0);
|
||||||
|
mv.visitVarInsn(Opcodes.ISTORE, index);
|
||||||
|
break;
|
||||||
|
case "void":
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
mv.visitInsn(Opcodes.ACONST_NULL);
|
||||||
|
mv.visitVarInsn(Opcodes.ASTORE, index);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,16 +8,16 @@ 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.LocalVarDecl;
|
|
||||||
import org.objectweb.asm.*;
|
import org.objectweb.asm.*;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Objects;
|
import java.util.LinkedHashMap;
|
||||||
|
|
||||||
public class AssignStatementExpression extends AbstractType implements IExpression, IStatement {
|
public class AssignStatementExpression extends AbstractType implements IExpression, IStatement {
|
||||||
public String operator;
|
public String operator;
|
||||||
public IExpression left;
|
public IExpression left;
|
||||||
public IExpression right;
|
public IExpression right;
|
||||||
|
private InstVarExpression instVar;
|
||||||
|
|
||||||
public AssignStatementExpression(String operator, IExpression leftExpression, IExpression rightExpression){
|
public AssignStatementExpression(String operator, IExpression leftExpression, IExpression rightExpression){
|
||||||
this.operator = operator;
|
this.operator = operator;
|
||||||
@ -50,37 +50,70 @@ public class AssignStatementExpression extends AbstractType implements IExpressi
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void codeGen(MethodVisitor mv, HashMap<String, String> localVars) throws Exception {
|
|
||||||
if (left instanceof LocalVarIdentifier) {
|
|
||||||
LocalVarIdentifier localVar = (LocalVarIdentifier) left;
|
|
||||||
String varName = localVar.getIdentifier();
|
|
||||||
|
|
||||||
//Get the index of the local variable
|
|
||||||
int varIndex = localVars.get(varName)
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public TypeCheckResult typeCheck() throws Exception {
|
public TypeCheckResult typeCheck() throws Exception {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodVisitor mv) throws Exception {
|
public void codeGen(MethodVisitor mv, HashMap<String, HashMap<String, String>> typeContext, LinkedHashMap<String, String> localVars) throws Exception {
|
||||||
left.codeGen(mv);
|
//TODO: Do we need the value on the stack after assigning it?
|
||||||
right.codeGen(mv);
|
//TODO: WE do not differentiate between InstanceVar and FieldVar
|
||||||
|
|
||||||
// if (left instanceof VarRefExpression varRef) {
|
// Call the codeGen on the right expression which will push the value of the right expression onto the stack
|
||||||
// //TODO: Implement the handling of a variable reference --> I need a list of local variables
|
right.codeGen(mv, typeContext, localVars);
|
||||||
// // for that to determine if the variable is a local or field variable
|
|
||||||
// } else if (left instanceof InstVarExpression instVar) {
|
if (left instanceof LocalVarIdentifier) {
|
||||||
// mv.visitInsn(Opcodes.DUP_X1);
|
LocalVarIdentifier localVar = (LocalVarIdentifier) left;
|
||||||
//
|
String varName = localVar.getIdentifier();
|
||||||
// // We now again need the owner (class reference), name (of the Field in the owner) and type of the field
|
|
||||||
// //mv.visitFieldInsn(Opcodes.PUTFIELD, instVar.className, instVar.varName, instVar.type);
|
//Get the index of the local variable
|
||||||
// }
|
int index = -1;
|
||||||
|
int counter = 0;
|
||||||
|
for (String key : localVars.keySet()){
|
||||||
|
if (key.equals(varName)){
|
||||||
|
index = counter;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index == -1){
|
||||||
|
throw new Exception("Variable " + varName + " not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
String type = localVars.get(localVar.getIdentifier());
|
||||||
|
switch (type) {
|
||||||
|
case "int":
|
||||||
|
case "bool":
|
||||||
|
mv.visitVarInsn(Opcodes.ISTORE, index);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
mv.visitVarInsn(Opcodes.ASTORE, index);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (left instanceof InstVarExpression){
|
||||||
|
instVar = (InstVarExpression) left;
|
||||||
|
|
||||||
|
// Load "this" onto the stack
|
||||||
|
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
||||||
|
|
||||||
|
String fieldType = typeContext.get(instVar.classRef.name).get(instVar.fieldName);
|
||||||
|
|
||||||
|
String fieldDescriptor;
|
||||||
|
switch (fieldType) {
|
||||||
|
case "int":
|
||||||
|
fieldDescriptor = "I";
|
||||||
|
break;
|
||||||
|
case "boolean":
|
||||||
|
fieldDescriptor = "Z";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
//TODO: We need the fully qualified name of the class here in field type
|
||||||
|
fieldDescriptor = "L" + fieldType + ";";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
mv.visitFieldInsn(Opcodes.PUTFIELD, instVar.classRef.name, instVar.fieldName, fieldDescriptor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ import org.objectweb.asm.MethodVisitor;
|
|||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class MethodCallStatementExpression extends AbstractType implements IExpression, IStatement {
|
public class MethodCallStatementExpression extends AbstractType implements IExpression, IStatement {
|
||||||
@ -50,27 +51,44 @@ public class MethodCallStatementExpression extends AbstractType implements IExpr
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void codeGen(MethodVisitor mv, HashMap<String, String> localVars) throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//Errors occur due to the change in parameter in the RefType class
|
//Errors occur due to the change in parameter in the RefType class
|
||||||
|
// I need the methodContext here to get the method descriptor
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodVisitor mv) throws Exception {
|
public void codeGen(MethodVisitor mv, HashMap<String, HashMap<String, String>> typeContext, LinkedHashMap<String, String> localVars) throws Exception {
|
||||||
//Generate Bytecode for the receiver
|
//Generate Bytecode for the receiver
|
||||||
if(classThatHasTheMethodIfNotThis != null){
|
if(classThatHasTheMethodIfNotThis != null){
|
||||||
// classThatHasTheMethodIfNotThis.codeGen(new ClassWriter(ClassWriter.COMPUTE_FRAMES));
|
//TODO: classThatHasTheMethodIfNotThis must be an object --> instance of the class not the class itself
|
||||||
|
//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 {
|
} else {
|
||||||
|
// Load this onto the stack
|
||||||
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (IExpression argument : arguments) {
|
for (IExpression argument : arguments) {
|
||||||
argument.codeGen(mv);
|
argument.codeGen(mv, typeContext, localVars);
|
||||||
}
|
}
|
||||||
|
|
||||||
//We need the class reference and the return type of the method
|
// Get the method descriptor
|
||||||
//mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, thisClass.name, methodName, return type);
|
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, thisClass.name, methodName, descriptor, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user