Added Bytecode generation Logic for datatypes and binary expressions
This commit is contained in:
parent
261cf2f6fa
commit
bd3988004c
@ -2,6 +2,7 @@ package abstractSyntaxTree.Datatype;
|
|||||||
|
|
||||||
import TypeCheck.AbstractType;
|
import TypeCheck.AbstractType;
|
||||||
import TypeCheck.TypeCheckResult;
|
import TypeCheck.TypeCheckResult;
|
||||||
|
import org.objectweb.asm.*;
|
||||||
|
|
||||||
public class BoolDatatype extends AbstractType implements IDatatype{
|
public class BoolDatatype extends AbstractType implements IDatatype{
|
||||||
boolean value;
|
boolean value;
|
||||||
@ -14,4 +15,13 @@ public class BoolDatatype extends AbstractType implements IDatatype{
|
|||||||
setTypeCheckResult(result);
|
setTypeCheckResult(result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void CodeGen(MethodVisitor mv) throws Exception {
|
||||||
|
if(value) {
|
||||||
|
mv.visitInsn(Opcodes.ICONST_1); // Pushes the int 1 on the stack (true)
|
||||||
|
} else {
|
||||||
|
mv.visitInsn(Opcodes.ICONST_0); // 0 for false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package abstractSyntaxTree.Datatype;
|
|||||||
|
|
||||||
import TypeCheck.AbstractType;
|
import TypeCheck.AbstractType;
|
||||||
import TypeCheck.TypeCheckResult;
|
import TypeCheck.TypeCheckResult;
|
||||||
|
import org.objectweb.asm.MethodVisitor;
|
||||||
|
|
||||||
public class CharDatatype extends AbstractType implements IDatatype{
|
public class CharDatatype extends AbstractType implements IDatatype{
|
||||||
char value;
|
char value;
|
||||||
@ -14,4 +15,13 @@ public class CharDatatype extends AbstractType implements IDatatype{
|
|||||||
setTypeCheckResult(result);
|
setTypeCheckResult(result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void CodeGen(MethodVisitor mv) throws Exception {
|
||||||
|
|
||||||
|
// Possible use of BIPUSH and SIPUSH if the value is small enough
|
||||||
|
//This saves space in the bytecode which is not very relevant at this point, but could be implemented anyway
|
||||||
|
|
||||||
|
mv.visitLdcInsn((int)value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,15 @@
|
|||||||
package abstractSyntaxTree.Datatype;
|
package abstractSyntaxTree.Datatype;
|
||||||
|
|
||||||
import TypeCheck.TypeCheckResult;
|
import TypeCheck.TypeCheckResult;
|
||||||
|
import org.objectweb.asm.MethodVisitor;
|
||||||
|
|
||||||
public interface IDatatype {
|
public interface IDatatype {
|
||||||
// typeCheck method
|
// typeCheck method
|
||||||
TypeCheckResult typeCheck() throws Exception;
|
TypeCheckResult typeCheck() throws Exception;
|
||||||
|
|
||||||
// visit method for code generation
|
// visit method for code generation
|
||||||
|
|
||||||
|
void CodeGen(MethodVisitor mv) throws Exception;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO: Check if we need to differentiate between primitive types and reference types --> for example in "=="
|
@ -2,6 +2,8 @@ package abstractSyntaxTree.Datatype;
|
|||||||
|
|
||||||
import TypeCheck.AbstractType;
|
import TypeCheck.AbstractType;
|
||||||
import TypeCheck.TypeCheckResult;
|
import TypeCheck.TypeCheckResult;
|
||||||
|
import org.objectweb.asm.MethodVisitor;
|
||||||
|
import org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
public class IntDatatype extends AbstractType implements IDatatype{
|
public class IntDatatype extends AbstractType implements IDatatype{
|
||||||
int value;
|
int value;
|
||||||
@ -14,4 +16,19 @@ public class IntDatatype extends AbstractType implements IDatatype{
|
|||||||
setTypeCheckResult(result);
|
setTypeCheckResult(result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// visit method for code generation
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
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)
|
||||||
|
mv.visitIntInsn(Opcodes.BIPUSH, value);
|
||||||
|
else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE)
|
||||||
|
mv.visitIntInsn(Opcodes.SIPUSH, value);
|
||||||
|
else
|
||||||
|
mv.visitLdcInsn(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,8 @@ import TypeCheck.AbstractType;
|
|||||||
import TypeCheck.TypeCheckResult;
|
import TypeCheck.TypeCheckResult;
|
||||||
import abstractSyntaxTree.Class.FieldDecl;
|
import abstractSyntaxTree.Class.FieldDecl;
|
||||||
import abstractSyntaxTree.Class.MethodDecl;
|
import abstractSyntaxTree.Class.MethodDecl;
|
||||||
|
import jdk.jshell.spi.ExecutionControl;
|
||||||
|
import org.objectweb.asm.MethodVisitor;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -31,4 +33,13 @@ public class RefType extends AbstractType implements IDatatype {
|
|||||||
setTypeCheckResult(result);
|
setTypeCheckResult(result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Method for code generation which iterates over all the field declarations
|
||||||
|
// and method declarations and calls their CodeGen methods
|
||||||
|
@Override
|
||||||
|
public void CodeGen(MethodVisitor mv) throws Exception {
|
||||||
|
throw new ExecutionControl.NotImplementedException("CodeGen not implemented for RefType");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,9 @@ package abstractSyntaxTree.Expression;
|
|||||||
import TypeCheck.TypeCheckResult;
|
import TypeCheck.TypeCheckResult;
|
||||||
import TypeCheck.TypeCheckHelper;
|
import TypeCheck.TypeCheckHelper;
|
||||||
import TypeCheck.AbstractType;
|
import TypeCheck.AbstractType;
|
||||||
|
import org.objectweb.asm.*;
|
||||||
|
|
||||||
|
import java.beans.Expression;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public class BinaryExpression extends AbstractType implements IExpression{
|
public class BinaryExpression extends AbstractType implements IExpression{
|
||||||
@ -54,4 +56,115 @@ public class BinaryExpression extends AbstractType implements IExpression{
|
|||||||
setTypeCheckResult(result);
|
setTypeCheckResult(result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void CodeGen(MethodVisitor mv) throws Exception {
|
||||||
|
// Label for the jump instruction
|
||||||
|
Label operationFalse = new Label(); //Operation is false
|
||||||
|
Label operationTrue = new Label(); //Operation is true
|
||||||
|
// Labels are placed at the end of this method
|
||||||
|
Label expressionEnd = new Label(); //End of the whole expression
|
||||||
|
|
||||||
|
// Bytecode for the binary operation
|
||||||
|
switch (operator) {
|
||||||
|
case "&&":
|
||||||
|
left.CodeGen(mv);
|
||||||
|
mv.visitJumpInsn(Opcodes.IFEQ, operationFalse); // IFEQ --> "if equals to zero" (false) --> if left exp is false
|
||||||
|
|
||||||
|
right.CodeGen(mv);
|
||||||
|
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
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "||":
|
||||||
|
left.CodeGen(mv);
|
||||||
|
mv.visitJumpInsn(Opcodes.IFNE, operationTrue); // IFNE --> "if not equals to zero" (true) --> if left exp is true
|
||||||
|
|
||||||
|
right.CodeGen(mv);
|
||||||
|
mv.visitJumpInsn(Opcodes.IFNE, operationTrue);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "==":
|
||||||
|
// Keep in mind that only primitive types are allowed in this case (at this time)
|
||||||
|
|
||||||
|
left.CodeGen(mv);
|
||||||
|
right.CodeGen(mv);
|
||||||
|
|
||||||
|
mv.visitJumpInsn(Opcodes.IF_ICMPEQ, operationTrue); // If the two values are equal, jump to the end of the expression
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "<":
|
||||||
|
left.CodeGen(mv);
|
||||||
|
right.CodeGen(mv);
|
||||||
|
|
||||||
|
mv.visitJumpInsn(Opcodes.IF_ICMPLT, operationTrue); // Checks only on less than, not equal
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ">":
|
||||||
|
left.CodeGen(mv);
|
||||||
|
right.CodeGen(mv);
|
||||||
|
|
||||||
|
mv.visitJumpInsn(Opcodes.IF_ICMPGT, operationTrue); // Checks only on greater than, not equal
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "<=":
|
||||||
|
left.CodeGen(mv);
|
||||||
|
right.CodeGen(mv);
|
||||||
|
|
||||||
|
mv.visitJumpInsn(Opcodes.IF_ICMPLE, operationTrue); // Checks on less than OR equal
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ">=":
|
||||||
|
left.CodeGen(mv);
|
||||||
|
right.CodeGen(mv);
|
||||||
|
|
||||||
|
mv.visitJumpInsn(Opcodes.IF_ICMPGE, operationTrue); // Checks on greater than OR equal
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "!=":
|
||||||
|
left.CodeGen(mv);
|
||||||
|
right.CodeGen(mv);
|
||||||
|
|
||||||
|
mv.visitJumpInsn(Opcodes.IF_ICMPNE, operationTrue); // Checks on not equal
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "+":
|
||||||
|
left.CodeGen(mv);
|
||||||
|
right.CodeGen(mv);
|
||||||
|
mv.visitInsn(Opcodes.IADD);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "-":
|
||||||
|
left.CodeGen(mv);
|
||||||
|
right.CodeGen(mv);
|
||||||
|
mv.visitInsn(Opcodes.ISUB);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "*":
|
||||||
|
left.CodeGen(mv);
|
||||||
|
right.CodeGen(mv);
|
||||||
|
mv.visitInsn(Opcodes.IMUL);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "/":
|
||||||
|
left.CodeGen(mv);
|
||||||
|
right.CodeGen(mv);
|
||||||
|
mv.visitInsn(Opcodes.IDIV);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new Exception("Unknown operator: " + operator);
|
||||||
|
}
|
||||||
|
|
||||||
|
mv.visitLabel(operationFalse);
|
||||||
|
mv.visitInsn(Opcodes.ICONST_0); // Push false on the stack
|
||||||
|
mv.visitJumpInsn(Opcodes.GOTO, expressionEnd); // Jump to the end of the expression (skip the true push)
|
||||||
|
|
||||||
|
mv.visitLabel(operationTrue);
|
||||||
|
mv.visitInsn(Opcodes.ICONST_1); // Push true on the stack
|
||||||
|
|
||||||
|
mv.visitLabel(expressionEnd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
package abstractSyntaxTree.Expression;
|
package abstractSyntaxTree.Expression;
|
||||||
|
|
||||||
import TypeCheck.TypeCheckResult;
|
import TypeCheck.TypeCheckResult;
|
||||||
|
import org.objectweb.asm.MethodVisitor;
|
||||||
|
|
||||||
public interface IExpression {
|
public interface IExpression {
|
||||||
// typeCheck method
|
// typeCheck method
|
||||||
TypeCheckResult typeCheck() throws Exception;
|
TypeCheckResult typeCheck() throws Exception;
|
||||||
|
|
||||||
// visit method for code generation
|
// visit method for code generation
|
||||||
|
void CodeGen(MethodVisitor mv) throws Exception;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user