Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
61a9025274
BIN
Compilerbau Klassendiagramm.pdf
Normal file
BIN
Compilerbau Klassendiagramm.pdf
Normal file
Binary file not shown.
125
Source/Decaf.g4
Normal file
125
Source/Decaf.g4
Normal file
@ -0,0 +1,125 @@
|
||||
grammar Decaf;
|
||||
|
||||
program: classdecl+;
|
||||
|
||||
//class identifier{...}
|
||||
classdecl: (AccessModifierPrivate|AccessModifierPublic|AccessModifierProtected)? 'class' Identifier OpenCurlyBracket (constuctorDecl|fieldDecl|methodDecl)* ClosedCurlyBracket;
|
||||
constuctorDecl: (AccessModifierPrivate|AccessModifierPublic|AccessModifierProtected)? Identifier OpenRoundBracket parameterList? ClosedRoundBracket block; //Maybe not needed
|
||||
|
||||
//Method and FieldVar
|
||||
methodDecl: MainMethodDecl block | (AccessModifierPrivate|AccessModifierPublic|AccessModifierProtected)? (type | Void) Identifier OpenRoundBracket parameterList? ClosedRoundBracket block;
|
||||
fieldDecl: (AccessModifierPrivate|AccessModifierPublic|AccessModifierProtected)? type Identifier Semicolon;
|
||||
|
||||
//Parameters
|
||||
parameterList: parameter(Comma parameter)*;
|
||||
parameter: type Identifier;
|
||||
|
||||
//property, object.a, 3+1, a = 3
|
||||
expression: subExpression | binaryExpr;
|
||||
//subExpression to dissolve left-recusion
|
||||
subExpression: This | Identifier | instVar | value | stmtExpr | notExpr | OpenRoundBracket expression ClosedRoundBracket;
|
||||
notExpr: Not expression;
|
||||
assignableExpr: Identifier | instVar;
|
||||
instVar: This Dot Identifier | (This Dot)? (Identifier Dot)+ Identifier;
|
||||
|
||||
//.trim().toLength().toLowerCase().count ...
|
||||
methodCall: receiver? receivingMethod* Identifier OpenRoundBracket argumentList ClosedRoundBracket;
|
||||
argumentList: expression? | expression (Comma expression)*?;
|
||||
|
||||
binaryExpr: calcExpr | nonCalcExpr;
|
||||
|
||||
calcExpr: calcExpr LineOperator dotExpr | dotExpr;
|
||||
dotExpr: dotExpr DotOperator dotSubExpr | dotSubExpr;
|
||||
dotSubExpr: IntValue | Identifier | instVar | methodCall | OpenRoundBracket calcExpr ClosedRoundBracket;
|
||||
nonCalcExpr: subExpression nonCalcOperator expression;
|
||||
nonCalcOperator: LogicalOpertor | ComparisonOperator;
|
||||
|
||||
//Statement but also expression
|
||||
//a = expr, new Object(), method(param1)
|
||||
stmtExpr: assign | newDecl | methodCall;
|
||||
|
||||
//Statements
|
||||
//int a, {...}, while(a > 10){...}, if(...){...} else if{...} else{...}
|
||||
statement: returnStmt Semicolon | localVarDecl Semicolon | block | whileStmt | ifElseStmt | stmtExpr Semicolon;
|
||||
returnStmt: Return (expression)?;
|
||||
localVarDecl: type Identifier (Assign expression)?;
|
||||
block: OpenCurlyBracket statement* ClosedCurlyBracket;
|
||||
whileStmt: While OpenRoundBracket expression ClosedRoundBracket block;
|
||||
ifElseStmt: ifStmt elseStmt?;
|
||||
ifStmt: If OpenRoundBracket expression ClosedRoundBracket statement;
|
||||
elseStmt: Else statement;
|
||||
assign: assignableExpr Assign expression;
|
||||
newDecl: New Identifier OpenRoundBracket argumentList ClosedRoundBracket;
|
||||
receiver: ((This | instVar | newDecl | Identifier) Dot);
|
||||
receivingMethod: Identifier OpenRoundBracket argumentList ClosedRoundBracket Dot;
|
||||
type: Int | Boolean | Char | Identifier;
|
||||
value: IntValue | BooleanValue | CharValue | NullValue;
|
||||
|
||||
//Access modifier
|
||||
AccessModifierPublic : 'public' ;
|
||||
AccessModifierPrivate : 'private';
|
||||
AccessModifierProtected : 'protected';
|
||||
MainMethodDecl : 'public static void main(String[] args)';
|
||||
|
||||
//Types
|
||||
Void : 'void';
|
||||
Int : 'int';
|
||||
Boolean : 'bool';
|
||||
Char : 'char';
|
||||
|
||||
//Operators
|
||||
DotOperator : Multipilkation | Division | Modulo;
|
||||
LineOperator : Plus | Minus;
|
||||
ComparisonOperator : Greater | Less | GreaterEqual | LessEqual | Equal | NotEqual;
|
||||
LogicalOpertor : And | Or;
|
||||
|
||||
Assign : '=';
|
||||
Minus : '-';
|
||||
Plus : '+';
|
||||
Multipilkation : '*';
|
||||
Division : '/';
|
||||
Modulo : '%';
|
||||
Greater : '>';
|
||||
Less : '<';
|
||||
GreaterEqual : '>=';
|
||||
LessEqual : '<=';
|
||||
Equal : '==';
|
||||
NotEqual : '!=';
|
||||
Not : '!';
|
||||
And : '&&';
|
||||
Or : '||';
|
||||
|
||||
//Symbols
|
||||
Dot : '.';
|
||||
OpenRoundBracket : '(';
|
||||
ClosedRoundBracket : ')';
|
||||
OpenCurlyBracket : '{';
|
||||
ClosedCurlyBracket : '}';
|
||||
Semicolon : ';';
|
||||
Comma : ',';
|
||||
|
||||
//Keywords
|
||||
Class : 'class';
|
||||
This : 'this';
|
||||
While : 'while';
|
||||
If : 'if';
|
||||
Else : 'else';
|
||||
For : 'for';
|
||||
Return : 'return';
|
||||
New : 'new';
|
||||
|
||||
//Identifier
|
||||
fragment Alpabetic : [a-zA-Z];
|
||||
fragment Numeric: [0-9];
|
||||
fragment ValidIdentSymbols : Alpabetic|Numeric|'$'|'_';
|
||||
Identifier: Alpabetic ValidIdentSymbols*;
|
||||
|
||||
//Values
|
||||
IntValue : ('+'|'-')*[0-9]+;
|
||||
CharValue: '\''~[\r\n]?'\'';
|
||||
BooleanValue: 'true'|'false';
|
||||
NullValue: 'null';
|
||||
|
||||
//Whitespace? Right into the trash it gooeesss
|
||||
WS : [ \t\r\n] -> skip;
|
||||
|
@ -2,6 +2,7 @@ package abstractSyntaxTree.Datatype;
|
||||
|
||||
import TypeCheck.AbstractType;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import org.objectweb.asm.*;
|
||||
|
||||
public class BoolDatatype extends AbstractType implements IDatatype{
|
||||
boolean value;
|
||||
@ -14,4 +15,13 @@ public class BoolDatatype extends AbstractType implements IDatatype{
|
||||
setTypeCheckResult(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.TypeCheckResult;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
|
||||
public class CharDatatype extends AbstractType implements IDatatype{
|
||||
char value;
|
||||
@ -14,4 +15,13 @@ public class CharDatatype extends AbstractType implements IDatatype{
|
||||
setTypeCheckResult(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;
|
||||
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
|
||||
public interface IDatatype {
|
||||
// typeCheck method
|
||||
TypeCheckResult typeCheck() throws Exception;
|
||||
|
||||
// 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.TypeCheckResult;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
public class IntDatatype extends AbstractType implements IDatatype{
|
||||
int value;
|
||||
@ -14,4 +16,19 @@ public class IntDatatype extends AbstractType implements IDatatype{
|
||||
setTypeCheckResult(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 abstractSyntaxTree.Class.FieldDecl;
|
||||
import abstractSyntaxTree.Class.MethodDecl;
|
||||
import jdk.jshell.spi.ExecutionControl;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -30,4 +32,13 @@ public class RefType extends AbstractType implements IDatatype {
|
||||
setTypeCheckResult(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.TypeCheckHelper;
|
||||
import TypeCheck.AbstractType;
|
||||
import org.objectweb.asm.*;
|
||||
|
||||
import java.beans.Expression;
|
||||
import java.util.Objects;
|
||||
|
||||
public class BinaryExpression extends AbstractType implements IExpression{
|
||||
@ -54,4 +56,115 @@ public class BinaryExpression extends AbstractType implements IExpression{
|
||||
setTypeCheckResult(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;
|
||||
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
|
||||
public interface IExpression {
|
||||
// typeCheck method
|
||||
TypeCheckResult typeCheck() throws Exception;
|
||||
|
||||
// visit method for code generation
|
||||
void CodeGen(MethodVisitor mv) throws Exception;
|
||||
}
|
||||
|
@ -1,10 +1,32 @@
|
||||
package abstractSyntaxTree.Expression;
|
||||
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import abstractSyntaxTree.Datatype.RefType;
|
||||
import jdk.jshell.spi.ExecutionControl;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
|
||||
public class InstVarExpression implements IExpression{
|
||||
|
||||
//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
|
||||
private RefType classRef;
|
||||
private String fieldName;
|
||||
|
||||
/* public InstVarExpression(RefType classRef, String fieldName){
|
||||
this.classRef = classRef;
|
||||
this.fieldName = fieldName;
|
||||
}*/
|
||||
@Override
|
||||
public TypeCheckResult typeCheck() throws Exception {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void CodeGen(MethodVisitor mv) throws Exception {
|
||||
throw new ExecutionControl.NotImplementedException("CodeGen not implemented for InstVarExpression");
|
||||
|
||||
//ALOAD the index of the var
|
||||
//GETFIELD the field
|
||||
//visitFieldInsn(Opcodes.GETFIELD, "class reference", "field name", type);
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,8 @@ import TypeCheck.AbstractType;
|
||||
import TypeCheck.TypeCheckHelper;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import abstractSyntaxTree.Datatype.IDatatype;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@ -38,4 +40,26 @@ public class UnaryExpression extends AbstractType implements IExpression{
|
||||
setTypeCheckResult(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void CodeGen(MethodVisitor mv) throws Exception {
|
||||
|
||||
operand.CodeGen(mv);
|
||||
|
||||
switch (operator) {
|
||||
case "!":
|
||||
//XOR with 1 to get the negation
|
||||
mv.visitInsn(Opcodes.ICONST_1);
|
||||
mv.visitInsn(Opcodes.IXOR);
|
||||
break;
|
||||
case "-":
|
||||
mv.visitInsn(Opcodes.INEG);
|
||||
break;
|
||||
case "+":
|
||||
break;
|
||||
|
||||
default: throw new Exception("Unknown operator :" + operator);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,23 @@
|
||||
package abstractSyntaxTree.Expression;
|
||||
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class VarRefExpression implements IExpression{
|
||||
|
||||
//Parameters that are needed here
|
||||
private String varName;
|
||||
private Map<String, Integer> localVars;
|
||||
|
||||
@Override
|
||||
public TypeCheckResult typeCheck() throws Exception {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void CodeGen(MethodVisitor mv) throws Exception {
|
||||
throw new Exception("CodeGen not implemented for VarRefExpression");
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,10 @@
|
||||
package abstractSyntaxTree.Modifier;
|
||||
|
||||
public interface IModifier {
|
||||
|
||||
//TODO: Maybe we can just use an enum for the Modifier
|
||||
// if there is no typeCheck and no CodeGen
|
||||
|
||||
// not type or type check
|
||||
|
||||
// visit method for code generation
|
||||
|
@ -3,10 +3,13 @@ package abstractSyntaxTree.Statement;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import TypeCheck.AbstractType;
|
||||
import abstractSyntaxTree.Expression.IExpression;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class BlockStatement extends AbstractType implements IStatement{
|
||||
|
||||
//We will need a parameter which holds the symbol table
|
||||
List<IStatement> statements;
|
||||
public BlockStatement(List<IStatement> statements){
|
||||
this.statements = statements;
|
||||
@ -31,4 +34,11 @@ public class BlockStatement extends AbstractType implements IStatement{
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void CodeGen(MethodVisitor mv) throws Exception {
|
||||
for (IStatement statement : statements) {
|
||||
statement.CodeGen(mv); //TODO: I think we need to pass the symbol table here
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package abstractSyntaxTree.Statement;
|
||||
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import TypeCheck.AbstractType;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
|
||||
public class EmptyStatement extends AbstractType implements IStatement{
|
||||
@Override
|
||||
@ -10,4 +11,9 @@ public class EmptyStatement extends AbstractType implements IStatement{
|
||||
result.type = "void";
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void CodeGen(MethodVisitor mv) throws Exception {
|
||||
//An empty statement does not generate any code
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,11 @@
|
||||
package abstractSyntaxTree.Statement;
|
||||
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
|
||||
public interface IStatement {
|
||||
|
||||
TypeCheckResult typeCheck() throws Exception;
|
||||
|
||||
// visit method for code generation
|
||||
void CodeGen(MethodVisitor mv) throws Exception;
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package abstractSyntaxTree.Statement;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import TypeCheck.AbstractType;
|
||||
import abstractSyntaxTree.Expression.IExpression;
|
||||
import org.objectweb.asm.*;
|
||||
|
||||
public class IfElseStatement extends AbstractType implements IStatement{
|
||||
IExpression condition;
|
||||
@ -35,4 +36,23 @@ public class IfElseStatement extends AbstractType implements IStatement{
|
||||
result.type = elseStatementType.type;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void CodeGen(MethodVisitor mv) throws Exception {
|
||||
|
||||
Label conditionFalse = new Label();
|
||||
Label statementEnd = new Label();
|
||||
|
||||
condition.CodeGen(mv);
|
||||
|
||||
mv.visitJumpInsn(Opcodes.IFEQ, conditionFalse); //Checks if the condition is false (0)
|
||||
ifStatement.CodeGen(mv); //If the condition is true, execute the ifBlock
|
||||
mv.visitJumpInsn(Opcodes.GOTO, statementEnd); //Jump to the end of the if-else statement
|
||||
|
||||
mv.visitLabel(conditionFalse);
|
||||
elseStatement.CodeGen(mv); //If the condition is false, execute the elseBlock
|
||||
|
||||
mv.visitLabel(statementEnd); //End of the if-else statement
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -3,9 +3,12 @@ package abstractSyntaxTree.Statement;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import TypeCheck.AbstractType;
|
||||
import abstractSyntaxTree.Expression.IExpression;
|
||||
import org.objectweb.asm.*;
|
||||
|
||||
public class IfStatement extends AbstractType implements IStatement{
|
||||
IExpression condition;
|
||||
|
||||
//Do we need a block statement here?
|
||||
IStatement ifStatement;
|
||||
|
||||
public IfStatement(IExpression condition, IStatement ifStatement) {
|
||||
@ -27,6 +30,18 @@ public class IfStatement extends AbstractType implements IStatement{
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void CodeGen(MethodVisitor mv) throws Exception {
|
||||
|
||||
Label conditionFalse = new Label();
|
||||
|
||||
condition.CodeGen(mv);
|
||||
|
||||
mv.visitJumpInsn(Opcodes.IFEQ, conditionFalse); //Checks if the condition is false (0)
|
||||
ifStatement.CodeGen(mv);
|
||||
|
||||
mv.visitLabel(conditionFalse); // If the condition is false, the Statements in the ifBlock will not be executed
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -3,6 +3,7 @@ package abstractSyntaxTree.Statement;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import TypeCheck.AbstractType;
|
||||
import abstractSyntaxTree.Expression.IExpression;
|
||||
import org.objectweb.asm.*;
|
||||
|
||||
public class ReturnStatement extends AbstractType implements IStatement{
|
||||
IExpression expression;
|
||||
@ -24,4 +25,27 @@ public class ReturnStatement extends AbstractType implements IStatement{
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
//TODO: We do not differentiate between primitive types and reference types
|
||||
// This is a problem at "BinaryExpression" and here because we need to know the type to return
|
||||
// At this point in time we can either return reference types or have an error message
|
||||
@Override
|
||||
public void CodeGen(MethodVisitor mv) throws Exception {
|
||||
|
||||
if (expression != null) {
|
||||
expression.CodeGen(mv);
|
||||
//Get the Type of the expression
|
||||
String type = expression.typeCheck().type;
|
||||
|
||||
if (type.equals("int") || type.equals("bool")) {
|
||||
mv.visitInsn(Opcodes.IRETURN);
|
||||
} else {
|
||||
mv.visitInsn(Opcodes.ARETURN);
|
||||
|
||||
}
|
||||
} else {
|
||||
mv.visitInsn(Opcodes.RETURN);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,14 +3,17 @@ package abstractSyntaxTree.Statement;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import TypeCheck.AbstractType;
|
||||
import abstractSyntaxTree.Expression.IExpression;
|
||||
import org.objectweb.asm.*;
|
||||
|
||||
public class WhileStatement extends AbstractType implements IStatement{
|
||||
public class WhileStatement extends AbstractType implements IStatement {
|
||||
IExpression condition;
|
||||
IStatement statement;
|
||||
|
||||
public WhileStatement(IExpression condition, IStatement statement) {
|
||||
this.condition = condition;
|
||||
this.statement = statement;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult typeCheck() throws Exception {
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
@ -26,4 +29,22 @@ public class WhileStatement extends AbstractType implements IStatement{
|
||||
result.type = statementType.type;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void CodeGen(MethodVisitor mv) throws Exception {
|
||||
Label conditionFalse = new Label();
|
||||
Label LoopStart = new Label();
|
||||
|
||||
mv.visitLabel(LoopStart);
|
||||
|
||||
condition.CodeGen(mv);
|
||||
mv.visitJumpInsn(Opcodes.IFEQ, conditionFalse); // Checks if the condition is false (0)
|
||||
|
||||
statement.CodeGen(mv);
|
||||
//TODO: If the block ends with a return statement, we might have to pop it from the stack
|
||||
// So the next iteration starts with a clean stack
|
||||
mv.visitJumpInsn(Opcodes.GOTO, LoopStart); // Jump to the start of the while loop
|
||||
|
||||
mv.visitLabel(conditionFalse);
|
||||
}
|
||||
}
|
@ -4,7 +4,10 @@ import TypeCheck.AbstractType;
|
||||
import TypeCheck.TypeCheckHelper;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import abstractSyntaxTree.Expression.IExpression;
|
||||
import abstractSyntaxTree.Expression.InstVarExpression;
|
||||
import abstractSyntaxTree.Expression.VarRefExpression;
|
||||
import abstractSyntaxTree.Statement.IStatement;
|
||||
import org.objectweb.asm.*;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@ -28,4 +31,20 @@ public class AssignStatementExpression extends AbstractType implements IExpressi
|
||||
setTypeCheckResult(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void CodeGen(MethodVisitor mv) throws Exception {
|
||||
left.CodeGen(mv);
|
||||
right.CodeGen(mv);
|
||||
|
||||
if (left instanceof VarRefExpression varRef) {
|
||||
//TODO: Implement the handling of a variable reference --> I need a lis of local variables
|
||||
// for that to determine if the variable is a local or field variable
|
||||
} else if (left instanceof InstVarExpression instVar) {
|
||||
mv.visitInsn(Opcodes.DUP_X1);
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,8 @@ import abstractSyntaxTree.Class.MethodDecl;
|
||||
import abstractSyntaxTree.Datatype.RefType;
|
||||
import abstractSyntaxTree.Expression.IExpression;
|
||||
import abstractSyntaxTree.Statement.IStatement;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -39,4 +41,22 @@ public class MethodCallStatementExpression extends AbstractType implements IExpr
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void CodeGen(MethodVisitor mv) throws Exception {
|
||||
//Generate Bytecode for the receiver
|
||||
if(classThatHasTheMethodIfNotThis != null){
|
||||
classThatHasTheMethodIfNotThis.CodeGen(mv);
|
||||
} else {
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
||||
}
|
||||
|
||||
for (IExpression argument : arguments) {
|
||||
argument.CodeGen(mv);
|
||||
}
|
||||
|
||||
//We need the class reference and the return type of the method
|
||||
//mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, thisClass.name, methodName, return type);
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -4,10 +4,16 @@ import TypeCheck.AbstractType;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import abstractSyntaxTree.Expression.IExpression;
|
||||
import abstractSyntaxTree.Statement.IStatement;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
|
||||
public class NewStatementExpression extends AbstractType implements IExpression, IStatement {
|
||||
@Override
|
||||
public TypeCheckResult typeCheck() throws Exception {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void CodeGen(MethodVisitor mv) throws Exception {
|
||||
throw new Exception("CodeGen not implemented for NewStatementExpression");
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user