Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
7e8c297d9a
BIN
Fakultaet.class
BIN
Fakultaet.class
Binary file not shown.
20
src/Fakultaet.java
Normal file
20
src/Fakultaet.java
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
class Fakultaet {
|
||||||
|
public int fak(int number) {
|
||||||
|
if (number < 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
int factorial = 1;
|
||||||
|
int i = 1;
|
||||||
|
while(i <= number){
|
||||||
|
factorial = factorial * i;
|
||||||
|
i = i + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return factorial;
|
||||||
|
}
|
||||||
|
public static void main(String[] args) {
|
||||||
|
Fakultaet f = new Fakultaet();
|
||||||
|
int result = f.fak(5);
|
||||||
|
print(result);
|
||||||
|
}
|
||||||
|
}
|
@ -114,7 +114,7 @@ New : 'new';
|
|||||||
|
|
||||||
|
|
||||||
//Values
|
//Values
|
||||||
IntValue : ('+'|'-')*[0-9]+;
|
IntValue : ('+'|'-')?[0-9]+;
|
||||||
CharValue: '\''~[\r\n]?'\'';
|
CharValue: '\''~[\r\n]?'\'';
|
||||||
|
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ import java.util.Objects;
|
|||||||
public class BinaryExpression extends AbstractType implements IExpression{
|
public class BinaryExpression extends AbstractType implements IExpression{
|
||||||
|
|
||||||
public String operator;
|
public String operator;
|
||||||
public IExpression left;
|
public IExpression left; // This needs TypeCheckResult
|
||||||
public IExpression right;
|
public IExpression right;
|
||||||
|
|
||||||
public BinaryExpression(String operator, IExpression left, IExpression right) {
|
public BinaryExpression(String operator, IExpression left, IExpression right) {
|
||||||
|
@ -16,14 +16,14 @@ import java.util.LinkedHashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public class InstVarExpression extends AbstractType implements IExpression{
|
public class InstVarExpression extends AbstractType implements IExpression {
|
||||||
|
|
||||||
public String thisClass;
|
public String thisClass;
|
||||||
public List<SubReceiver> receivers;
|
public List<SubReceiver> receivers;
|
||||||
public List<ReceivingMethod> receivingMethods;
|
public List<ReceivingMethod> receivingMethods;
|
||||||
public String fieldName;
|
public String fieldName;
|
||||||
|
|
||||||
public InstVarExpression(List<SubReceiver> receivers, List<ReceivingMethod> receivingMethods, String fieldName){
|
public InstVarExpression(List<SubReceiver> receivers, List<ReceivingMethod> receivingMethods, String fieldName) {
|
||||||
this.receivers = receivers;
|
this.receivers = receivers;
|
||||||
this.receivingMethods = receivingMethods;
|
this.receivingMethods = receivingMethods;
|
||||||
this.fieldName = fieldName;
|
this.fieldName = fieldName;
|
||||||
@ -32,7 +32,7 @@ public class InstVarExpression extends AbstractType implements IExpression{
|
|||||||
@Override
|
@Override
|
||||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws TypeCheckException {
|
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws TypeCheckException {
|
||||||
String typeOfSubreceiver = "";
|
String typeOfSubreceiver = "";
|
||||||
if(receivers.get(0).identifier != null) {
|
if (receivers.get(0).identifier != null) {
|
||||||
String subreceiver = receivers.get(0).identifier;
|
String subreceiver = receivers.get(0).identifier;
|
||||||
typeOfSubreceiver = localVars.get(subreceiver);
|
typeOfSubreceiver = localVars.get(subreceiver);
|
||||||
if (typeOfSubreceiver == null)
|
if (typeOfSubreceiver == null)
|
||||||
@ -45,7 +45,7 @@ public class InstVarExpression extends AbstractType implements IExpression{
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}else {
|
} else {
|
||||||
typeOfSubreceiver = thisClass;
|
typeOfSubreceiver = thisClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,34 +63,161 @@ public class InstVarExpression extends AbstractType implements IExpression{
|
|||||||
// typeContext: (ClassName, (FieldName, FieldType))
|
// typeContext: (ClassName, (FieldName, FieldType))
|
||||||
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 {
|
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 "this" onto the stack
|
// Load "this" onto the stack
|
||||||
|
String typeOfReciever = "";
|
||||||
|
String descriptor = "";
|
||||||
|
String classOfField = "";
|
||||||
|
|
||||||
// Determine if the reference is this or not
|
// Determine if the reference is this or not
|
||||||
if (this.receivers.get(0).identifier != null) {
|
if (this.receivers.get(0).identifier != null) {
|
||||||
|
|
||||||
|
for (int i = 0; i < receivers.size(); i++) {
|
||||||
|
|
||||||
|
if (i == 0) {
|
||||||
|
// Load the local variable onto the stack
|
||||||
|
int index = -1;
|
||||||
|
int counter = 0;
|
||||||
|
for (String key : localVars.keySet()) {
|
||||||
|
if (key.equals(this.receivers.get(i).identifier)) {
|
||||||
|
index = counter + 1; // +1 because the first local variable is at index 1, 0 is used for "this"
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index == -1) {
|
||||||
|
if (typeContext.get(thisClass).get(this.receivers.get(i).identifier) != null) {
|
||||||
|
|
||||||
|
classOfField = typeOfReciever;
|
||||||
|
|
||||||
|
typeOfReciever = typeContext.get(typeOfReciever).get(this.receivers.get(i).identifier);
|
||||||
|
|
||||||
|
descriptor = getFieldDescriptor(typeContext, typeOfReciever);
|
||||||
|
|
||||||
|
// Load the variable onto the stack
|
||||||
|
mv.visitFieldInsn(Opcodes.GETFIELD, classOfField, receivers.get(i).identifier, descriptor);
|
||||||
|
continue;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
throw new Exception("Variable " + this.receivers.get(i).identifier + " not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
mv.visitVarInsn(Opcodes.ALOAD, index);
|
||||||
|
|
||||||
|
|
||||||
|
// Get the class of the receiver
|
||||||
|
typeOfReciever = localVars.get(this.receivers.get(i).identifier);
|
||||||
|
/*
|
||||||
|
descriptor = getFieldDescriptor(typeContext, typeOfReciever, typeOfReciever);
|
||||||
|
|
||||||
|
mv.visitFieldInsn(Opcodes.GETFIELD, thisClass, fieldName, descriptor);
|
||||||
|
*/
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Not the first receiver
|
||||||
|
else {
|
||||||
|
|
||||||
|
// Load the local variable onto the stack
|
||||||
|
int index = -1;
|
||||||
|
int counter = 0;
|
||||||
|
for (String key : localVars.keySet()) {
|
||||||
|
if (key.equals(this.receivers.get(i).identifier)) {
|
||||||
|
index = counter + 1; // +1 because the first local variable is at index 1, 0 is used for "this"
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index == -1) {
|
||||||
|
if (typeContext.get(typeOfReciever).get(this.receivers.get(i).identifier) != null) {
|
||||||
|
|
||||||
|
classOfField = typeOfReciever;
|
||||||
|
|
||||||
|
typeOfReciever = typeContext.get(typeOfReciever).get(this.receivers.get(i).identifier);
|
||||||
|
|
||||||
|
descriptor = getFieldDescriptor(typeContext, typeOfReciever);
|
||||||
|
|
||||||
|
// Load the variable onto the stack
|
||||||
|
mv.visitFieldInsn(Opcodes.GETFIELD, classOfField, receivers.get(i).identifier, descriptor);
|
||||||
|
continue;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
throw new Exception("Variable " + this.receivers.get(i).identifier + " not found");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
typeOfReciever = localVars.get(this.receivers.get(i).identifier);
|
||||||
|
|
||||||
|
descriptor = getFieldDescriptor(typeContext, typeOfReciever);
|
||||||
|
|
||||||
|
mv.visitFieldInsn(Opcodes.GETFIELD, typeOfReciever, fieldName, descriptor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Load the field in fieldName
|
||||||
|
|
||||||
// Load the local variable onto the stack
|
// Load the local variable onto the stack
|
||||||
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(this.receivers.get(0).identifier)){
|
if (key.equals(fieldName)) {
|
||||||
index = counter+1; // +1 because the first local variable is at index 1, 0 is used for "this"
|
index = counter + 1; // +1 because the first local variable is at index 1, 0 is used for "this"
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
counter++;
|
counter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index == -1){
|
if (index == -1) {
|
||||||
throw new Exception("Variable " + this.receivers.get(0).identifier + " not found");
|
if (typeContext.get(typeOfReciever).get(fieldName) != null) {
|
||||||
|
|
||||||
|
classOfField = typeOfReciever;
|
||||||
|
|
||||||
|
typeOfReciever = typeContext.get(typeOfReciever).get(fieldName);
|
||||||
|
|
||||||
|
descriptor = getFieldDescriptor(typeContext, typeOfReciever);
|
||||||
|
|
||||||
|
// Load the variable onto the stack
|
||||||
|
mv.visitFieldInsn(Opcodes.GETFIELD, classOfField, fieldName, descriptor);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
throw new Exception("Variable " + fieldName + " not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
typeOfReciever = localVars.get(fieldName);
|
||||||
|
|
||||||
|
descriptor = getFieldDescriptor(typeContext, typeOfReciever);
|
||||||
|
|
||||||
|
mv.visitFieldInsn(Opcodes.GETFIELD, typeOfReciever, fieldName, descriptor);
|
||||||
|
}
|
||||||
|
} else if (receivers.get(0).thisExpression) {
|
||||||
|
// Load the local variable or instVar of this onto the stack
|
||||||
|
int index = -1;
|
||||||
|
int counter = 0;
|
||||||
|
for (String key : localVars.keySet()) {
|
||||||
|
if (key.equals(fieldName)) {
|
||||||
|
index = counter + 1; // +1 because the first local variable is at index 1, 0 is used for "this"
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
counter++;
|
||||||
}
|
}
|
||||||
mv.visitVarInsn(Opcodes.ALOAD, index);
|
|
||||||
|
|
||||||
} else {
|
if (index == -1) {
|
||||||
// Load "this" onto the stack
|
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
||||||
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
|
||||||
|
} else {
|
||||||
|
mv.visitVarInsn(Opcodes.ALOAD, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
String fieldType = typeContext.get(thisClass).get(fieldName);
|
||||||
|
descriptor = getFieldDescriptor(typeContext, fieldType);
|
||||||
|
|
||||||
|
//Load the field onto the stack
|
||||||
|
mv.visitFieldInsn(Opcodes.GETFIELD, thisClass, fieldName, descriptor);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//Get the field information
|
private String getFieldDescriptor(HashMap<String, HashMap<String, String>> typeContext, String fieldType) {
|
||||||
String fieldType = typeContext.get(thisClass).get(fieldName);
|
|
||||||
|
|
||||||
StringBuilder descriptor = new StringBuilder();
|
StringBuilder descriptor = new StringBuilder();
|
||||||
|
|
||||||
|
|
||||||
@ -105,16 +232,13 @@ public class InstVarExpression extends AbstractType implements IExpression{
|
|||||||
descriptor.append("C");
|
descriptor.append("C");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
String fullReturnType = typeContext.get(thisClass).get(fieldName);
|
String fullReturnType = fieldType;
|
||||||
|
|
||||||
// If it is a class reference replace the "." with "/" and return it
|
// If it is a class reference replace the "." with "/" and return it
|
||||||
if (fieldType.contains(".")) fullReturnType = fullReturnType.replaceAll("\\.", "/");
|
if (fieldType.contains(".")) fullReturnType = fullReturnType.replaceAll("\\.", "/");
|
||||||
if (fullReturnType != null) descriptor.append("L").append(fullReturnType).append(";");
|
if (fullReturnType != null) descriptor.append("L").append(fullReturnType).append(";");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
return descriptor.toString();
|
||||||
// Load the variable onto the stack
|
|
||||||
mv.visitFieldInsn(Opcodes.GETFIELD, thisClass, fieldName, descriptor.toString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -134,4 +258,4 @@ public class InstVarExpression extends AbstractType implements IExpression{
|
|||||||
public TypeCheckResult getTypeCheckResult() {
|
public TypeCheckResult getTypeCheckResult() {
|
||||||
return super.getTypeCheckResult();
|
return super.getTypeCheckResult();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -8,6 +8,7 @@ import abstractSyntaxTree.Parameter.Parameter;
|
|||||||
import abstractSyntaxTree.Parameter.ParameterList;
|
import abstractSyntaxTree.Parameter.ParameterList;
|
||||||
import abstractSyntaxTree.StatementExpression.AssignStatementExpression;
|
import abstractSyntaxTree.StatementExpression.AssignStatementExpression;
|
||||||
import abstractSyntaxTree.StatementExpression.MethodCallStatementExpression;
|
import abstractSyntaxTree.StatementExpression.MethodCallStatementExpression;
|
||||||
|
import abstractSyntaxTree.StatementExpression.NewStatementExpression;
|
||||||
import org.objectweb.asm.*;
|
import org.objectweb.asm.*;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -66,6 +67,9 @@ public class BlockStatement extends AbstractType implements IStatement {
|
|||||||
if (statement instanceof ReturnStatement returnStatement) {
|
if (statement instanceof ReturnStatement returnStatement) {
|
||||||
returnStatement.thisClass = thisClass;
|
returnStatement.thisClass = thisClass;
|
||||||
}
|
}
|
||||||
|
if (statement instanceof NewStatementExpression newStatementExpression) {
|
||||||
|
newStatementExpression.thisClass = thisClass;
|
||||||
|
}
|
||||||
|
|
||||||
TypeCheckResult typeOfCurrentStatement = statement.typeCheck(methodContext, typeContext, localVars);
|
TypeCheckResult typeOfCurrentStatement = statement.typeCheck(methodContext, typeContext, localVars);
|
||||||
if(statement instanceof MethodCallStatementExpression methodCall){
|
if(statement instanceof MethodCallStatementExpression methodCall){
|
||||||
|
@ -9,6 +9,7 @@ import abstractSyntaxTree.Expression.LocalVarIdentifier;
|
|||||||
import abstractSyntaxTree.Parameter.ParameterList;
|
import abstractSyntaxTree.Parameter.ParameterList;
|
||||||
import abstractSyntaxTree.StatementExpression.AssignStatementExpression;
|
import abstractSyntaxTree.StatementExpression.AssignStatementExpression;
|
||||||
import abstractSyntaxTree.StatementExpression.MethodCallStatementExpression;
|
import abstractSyntaxTree.StatementExpression.MethodCallStatementExpression;
|
||||||
|
import abstractSyntaxTree.StatementExpression.NewStatementExpression;
|
||||||
import org.objectweb.asm.MethodVisitor;
|
import org.objectweb.asm.MethodVisitor;
|
||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
@ -36,11 +37,14 @@ public class LocalVarDecl extends AbstractType implements IStatement{
|
|||||||
if(expression instanceof MethodCallStatementExpression){
|
if(expression instanceof MethodCallStatementExpression){
|
||||||
MethodCallStatementExpression methodCall = (MethodCallStatementExpression) expression;
|
MethodCallStatementExpression methodCall = (MethodCallStatementExpression) expression;
|
||||||
methodCall.thisClass = this.thisClass;
|
methodCall.thisClass = this.thisClass;
|
||||||
|
|
||||||
}
|
}
|
||||||
if(expression instanceof LocalVarIdentifier localVarIdentifier){
|
if(expression instanceof LocalVarIdentifier localVarIdentifier){
|
||||||
localVarIdentifier.thisClass = thisClass;
|
localVarIdentifier.thisClass = thisClass;
|
||||||
}
|
}
|
||||||
|
if (expression instanceof NewStatementExpression newStatementExpression){
|
||||||
|
newStatementExpression.thisClass = thisClass;
|
||||||
|
}
|
||||||
|
|
||||||
expression.typeCheck(methodContext, typeContext, localVars);
|
expression.typeCheck(methodContext, typeContext, localVars);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,9 +60,13 @@ public class PrintStatement extends AbstractType implements IStatement {
|
|||||||
}
|
}
|
||||||
counter++;
|
counter++;
|
||||||
}
|
}
|
||||||
|
// If not a localVar, maybe a class field of this class
|
||||||
if (index == -1){
|
if (index == -1){
|
||||||
throw new Exception("Variable " + variableName + " not found");
|
String typeOfField = typeContext.get(thisClass).get(variableName);
|
||||||
|
if (typeOfField == null){
|
||||||
|
throw new Exception("Variable " + variableName + " not found in local variables or class fields.");
|
||||||
|
}
|
||||||
|
mv.visitFieldInsn(Opcodes.GETSTATIC, thisClass, variableName, "I");
|
||||||
}
|
}
|
||||||
|
|
||||||
mv.visitVarInsn(Opcodes.ILOAD, index);
|
mv.visitVarInsn(Opcodes.ILOAD, index);
|
||||||
|
@ -15,7 +15,7 @@ import java.util.List;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public class ReturnStatement extends AbstractType implements IStatement{
|
public class ReturnStatement extends AbstractType implements IStatement{
|
||||||
IExpression expression;
|
IExpression expression; // Needs typeCheckResult
|
||||||
public String thisClass;
|
public String thisClass;
|
||||||
|
|
||||||
public ReturnStatement(IExpression expression) {
|
public ReturnStatement(IExpression expression) {
|
||||||
|
@ -18,7 +18,7 @@ import java.util.*;
|
|||||||
public class MethodCallStatementExpression extends AbstractType implements IExpression, IStatement {
|
public class MethodCallStatementExpression extends AbstractType implements IExpression, IStatement {
|
||||||
String methodName;
|
String methodName;
|
||||||
List<IExpression> arguments;
|
List<IExpression> arguments;
|
||||||
Receiver receiver;
|
Receiver receiver; // Braucht typecheckResult
|
||||||
List<ReceivingMethod> receivingMethods;
|
List<ReceivingMethod> receivingMethods;
|
||||||
public String thisClass;
|
public String thisClass;
|
||||||
|
|
||||||
@ -139,7 +139,7 @@ public class MethodCallStatementExpression extends AbstractType implements IExpr
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Invoke the current method
|
// Invoke the current method
|
||||||
String descriptor = getMethodDescriptor(receivingMethod.methodName, localVars, methodContext, receivingMethod.arguments, returnOfPreviousMethod);
|
String descriptor = getMethodDescriptor(receivingMethod.methodName, localVars, methodContext, receivingMethod.arguments, returnOfPreviousMethod, owner);
|
||||||
returnOfPreviousMethod = methodContext.get(owner).get(receivingMethod.methodName).keySet().toArray()[0].toString();
|
returnOfPreviousMethod = methodContext.get(owner).get(receivingMethod.methodName).keySet().toArray()[0].toString();
|
||||||
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, receivingMethod.methodName, descriptor, false);
|
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, receivingMethod.methodName, descriptor, false);
|
||||||
}
|
}
|
||||||
@ -151,13 +151,18 @@ public class MethodCallStatementExpression extends AbstractType implements IExpr
|
|||||||
argument.codeGen(mv, localVars, typeContext, methodContext);
|
argument.codeGen(mv, localVars, typeContext, methodContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
String descriptor = getMethodDescriptor(methodName, localVars, methodContext, arguments, returnOfPreviousMethod);
|
if (returnOfPreviousMethod != null) {
|
||||||
|
owner = returnOfPreviousMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String descriptor = getMethodDescriptor(methodName, localVars, methodContext, arguments, returnOfPreviousMethod, owner);
|
||||||
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, methodName, descriptor, false);
|
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, methodName, descriptor, false);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ()I
|
// ()I
|
||||||
private String getMethodDescriptor(String methodName, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, List<IExpression> arguments, String returnOfPreviousMethod) {
|
private String getMethodDescriptor(String methodName, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, List<IExpression> arguments, String returnOfPreviousMethod, String owner) {
|
||||||
StringBuilder descriptor = new StringBuilder("(");
|
StringBuilder descriptor = new StringBuilder("(");
|
||||||
|
|
||||||
for (IExpression argument : arguments) {
|
for (IExpression argument : arguments) {
|
||||||
@ -189,12 +194,20 @@ public class MethodCallStatementExpression extends AbstractType implements IExpr
|
|||||||
String classToSearchMethodIn;
|
String classToSearchMethodIn;
|
||||||
//Return Type
|
//Return Type
|
||||||
if (receiver != null) {
|
if (receiver != null) {
|
||||||
classToSearchMethodIn = localVars.get(receiver.identifier);
|
if (receiver.identifier != null) {
|
||||||
if (classToSearchMethodIn == null) {
|
classToSearchMethodIn = localVars.get(receiver.identifier);
|
||||||
classToSearchMethodIn = returnOfPreviousMethod;
|
if (classToSearchMethodIn == null) {
|
||||||
}
|
classToSearchMethodIn = returnOfPreviousMethod;
|
||||||
if (classToSearchMethodIn == null) {
|
}
|
||||||
classToSearchMethodIn = thisClass;
|
if (classToSearchMethodIn == null) {
|
||||||
|
classToSearchMethodIn = thisClass;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (receiver.instVarExpression != null && returnOfPreviousMethod != null) {
|
||||||
|
classToSearchMethodIn = returnOfPreviousMethod;
|
||||||
|
} else {
|
||||||
|
classToSearchMethodIn = owner;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
classToSearchMethodIn = thisClass;
|
classToSearchMethodIn = thisClass;
|
||||||
|
@ -5,6 +5,7 @@ import TypeCheck.TypeCheckException;
|
|||||||
import TypeCheck.TypeCheckHelper;
|
import TypeCheck.TypeCheckHelper;
|
||||||
import TypeCheck.TypeCheckResult;
|
import TypeCheck.TypeCheckResult;
|
||||||
import abstractSyntaxTree.Expression.IExpression;
|
import abstractSyntaxTree.Expression.IExpression;
|
||||||
|
import abstractSyntaxTree.Expression.InstVarExpression;
|
||||||
import abstractSyntaxTree.Parameter.Parameter;
|
import abstractSyntaxTree.Parameter.Parameter;
|
||||||
import abstractSyntaxTree.Parameter.ParameterList;
|
import abstractSyntaxTree.Parameter.ParameterList;
|
||||||
import abstractSyntaxTree.Statement.IStatement;
|
import abstractSyntaxTree.Statement.IStatement;
|
||||||
@ -18,8 +19,9 @@ import java.util.List;
|
|||||||
|
|
||||||
public class NewStatementExpression extends AbstractType implements IExpression, IStatement {
|
public class NewStatementExpression extends AbstractType implements IExpression, IStatement {
|
||||||
|
|
||||||
|
public String thisClass;
|
||||||
private String className;
|
private String className;
|
||||||
private List<IExpression> arguments;
|
private List<IExpression> arguments; //These need to have a TypeCheckResult
|
||||||
|
|
||||||
public NewStatementExpression(String className, List<IExpression> arguments) {
|
public NewStatementExpression(String className, List<IExpression> arguments) {
|
||||||
this.className = className;
|
this.className = className;
|
||||||
@ -31,6 +33,13 @@ public class NewStatementExpression extends AbstractType implements IExpression,
|
|||||||
if(!TypeCheckHelper.typeExists(className, new ArrayList<>(typeContext.keySet()))){
|
if(!TypeCheckHelper.typeExists(className, new ArrayList<>(typeContext.keySet()))){
|
||||||
throw new TypeCheckException("An instance of " + className + " is created, but the type does not exist.");
|
throw new TypeCheckException("An instance of " + className + " is created, but the type does not exist.");
|
||||||
}
|
}
|
||||||
|
for (IExpression argument : arguments) {
|
||||||
|
if (argument instanceof InstVarExpression instVarExpression) {
|
||||||
|
instVarExpression.thisClass = this.thisClass;
|
||||||
|
}
|
||||||
|
argument.typeCheck(methodContext, typeContext, localVars);
|
||||||
|
}
|
||||||
|
|
||||||
TypeCheckResult result = new TypeCheckResult();
|
TypeCheckResult result = new TypeCheckResult();
|
||||||
|
|
||||||
result.type = className;
|
result.type = className;
|
||||||
|
@ -32,27 +32,27 @@ public class ASTGenerator extends DecafBaseVisitor<Node> {
|
|||||||
List<FieldDecl> fieldDecls = new ArrayList<>();
|
List<FieldDecl> fieldDecls = new ArrayList<>();
|
||||||
List<MethodDecl> methodDecls = new ArrayList<>();
|
List<MethodDecl> methodDecls = new ArrayList<>();
|
||||||
boolean hasMain;
|
boolean hasMain;
|
||||||
if(ctx.MainMethodDecl() != null) {
|
if (ctx.MainMethodDecl() != null) {
|
||||||
hasMain = true;
|
hasMain = true;
|
||||||
MethodDecl mainMethod = new MethodDecl(name, "void", "main", new ParameterList(new ArrayList<>()),(BlockStatement) visitBlock(ctx.block()));
|
MethodDecl mainMethod = new MethodDecl(name, "void", "main", new ParameterList(new ArrayList<>()), (BlockStatement) visitBlock(ctx.block()));
|
||||||
methodDecls.add(mainMethod);
|
methodDecls.add(mainMethod);
|
||||||
} else {
|
} else {
|
||||||
hasMain = false;
|
hasMain = false;
|
||||||
}
|
}
|
||||||
for (DecafParser.LocalVarDeclContext fieldDecl: ctx.localVarDecl()) {
|
for (DecafParser.LocalVarDeclContext fieldDecl : ctx.localVarDecl()) {
|
||||||
fieldDecls.add((FieldDecl) generateFieldDecl(fieldDecl));
|
fieldDecls.add((FieldDecl) generateFieldDecl(fieldDecl));
|
||||||
}
|
}
|
||||||
for (DecafParser.ConstuctorDeclContext constDecl: ctx.constuctorDecl()) {
|
for (DecafParser.ConstuctorDeclContext constDecl : ctx.constuctorDecl()) {
|
||||||
MethodDecl constructor = ((MethodDecl) visit(constDecl));
|
MethodDecl constructor = ((MethodDecl) visit(constDecl));
|
||||||
constructor.classThatContainsMethod = name;
|
constructor.classThatContainsMethod = name;
|
||||||
methodDecls.add(constructor);
|
methodDecls.add(constructor);
|
||||||
}
|
}
|
||||||
for (DecafParser.MethodDeclContext methodDecl: ctx.methodDecl()) {
|
for (DecafParser.MethodDeclContext methodDecl : ctx.methodDecl()) {
|
||||||
MethodDecl method = (MethodDecl) visit(methodDecl);
|
MethodDecl method = (MethodDecl) visit(methodDecl);
|
||||||
method.classThatContainsMethod = name;
|
method.classThatContainsMethod = name;
|
||||||
methodDecls.add(method);
|
methodDecls.add(method);
|
||||||
}
|
}
|
||||||
return new RefType(name,fieldDecls, methodDecls, hasMain);
|
return new RefType(name, fieldDecls, methodDecls, hasMain);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Node generateFieldDecl(DecafParser.LocalVarDeclContext ctx) {
|
public Node generateFieldDecl(DecafParser.LocalVarDeclContext ctx) {
|
||||||
@ -68,10 +68,10 @@ public class ASTGenerator extends DecafBaseVisitor<Node> {
|
|||||||
public Node visitLocalVarDecl(DecafParser.LocalVarDeclContext ctx) {
|
public Node visitLocalVarDecl(DecafParser.LocalVarDeclContext ctx) {
|
||||||
if (ctx.expression() != null) {
|
if (ctx.expression() != null) {
|
||||||
IExpression expression = (IExpression) visit(ctx.expression());
|
IExpression expression = (IExpression) visit(ctx.expression());
|
||||||
return new LocalVarDecl(ctx.type().getText(), ctx.Identifier().getText(), expression);
|
return new LocalVarDecl(ctx.type().getText(), ctx.Identifier().getText(), expression);
|
||||||
} else {
|
} else {
|
||||||
return new LocalVarDecl(ctx.type().getText(), ctx.Identifier().getText(), null);
|
return new LocalVarDecl(ctx.type().getText(), ctx.Identifier().getText(), null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -99,7 +99,7 @@ public class ASTGenerator extends DecafBaseVisitor<Node> {
|
|||||||
} else {
|
} else {
|
||||||
type = ctx.type().getText();
|
type = ctx.type().getText();
|
||||||
}
|
}
|
||||||
return new MethodDecl("", type , name, parameterList, block);
|
return new MethodDecl("", type, name, parameterList, block);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -110,7 +110,7 @@ public class ASTGenerator extends DecafBaseVisitor<Node> {
|
|||||||
@Override
|
@Override
|
||||||
public Node visitParameterList(DecafParser.ParameterListContext ctx) {
|
public Node visitParameterList(DecafParser.ParameterListContext ctx) {
|
||||||
List<Parameter> parameters = new ArrayList<>();
|
List<Parameter> parameters = new ArrayList<>();
|
||||||
for (DecafParser.ParameterContext parameter: ctx.parameter()) {
|
for (DecafParser.ParameterContext parameter : ctx.parameter()) {
|
||||||
parameters.add((Parameter) visit(parameter));
|
parameters.add((Parameter) visit(parameter));
|
||||||
}
|
}
|
||||||
return new ParameterList(parameters);
|
return new ParameterList(parameters);
|
||||||
@ -151,7 +151,7 @@ public class ASTGenerator extends DecafBaseVisitor<Node> {
|
|||||||
@Override
|
@Override
|
||||||
public Node visitBlock(DecafParser.BlockContext ctx) {
|
public Node visitBlock(DecafParser.BlockContext ctx) {
|
||||||
List<IStatement> stmts = new ArrayList<>();
|
List<IStatement> stmts = new ArrayList<>();
|
||||||
for (DecafParser.StatementContext stmt: ctx.statement()) {
|
for (DecafParser.StatementContext stmt : ctx.statement()) {
|
||||||
Node statement = visitStatement(stmt);
|
Node statement = visitStatement(stmt);
|
||||||
stmts.add((IStatement) statement);
|
stmts.add((IStatement) statement);
|
||||||
}
|
}
|
||||||
@ -199,7 +199,7 @@ public class ASTGenerator extends DecafBaseVisitor<Node> {
|
|||||||
} else if (ctx.newDecl() != null) {
|
} else if (ctx.newDecl() != null) {
|
||||||
return visitNewDecl(ctx.newDecl());
|
return visitNewDecl(ctx.newDecl());
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -211,7 +211,7 @@ public class ASTGenerator extends DecafBaseVisitor<Node> {
|
|||||||
public Node visitAssign(DecafParser.AssignContext ctx) {
|
public Node visitAssign(DecafParser.AssignContext ctx) {
|
||||||
Node right = visitExpression(ctx.expression());
|
Node right = visitExpression(ctx.expression());
|
||||||
Node left = visitAssignableExpr(ctx.assignableExpr());
|
Node left = visitAssignableExpr(ctx.assignableExpr());
|
||||||
return new AssignStatementExpression(ctx.Assign().getText(),(IExpression) left, (IExpression) right);
|
return new AssignStatementExpression(ctx.Assign().getText(), (IExpression) left, (IExpression) right);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -219,7 +219,7 @@ public class ASTGenerator extends DecafBaseVisitor<Node> {
|
|||||||
String methodName = ctx.Identifier().getText();
|
String methodName = ctx.Identifier().getText();
|
||||||
List<IExpression> arguments = generateExpressions(ctx.argumentList());
|
List<IExpression> arguments = generateExpressions(ctx.argumentList());
|
||||||
List<ReceivingMethod> receivingMethods = new ArrayList<>();
|
List<ReceivingMethod> receivingMethods = new ArrayList<>();
|
||||||
for(DecafParser.ReceivingMethodContext receivingMethod: ctx.receivingMethod()) {
|
for (DecafParser.ReceivingMethodContext receivingMethod : ctx.receivingMethod()) {
|
||||||
receivingMethods.add((ReceivingMethod) visit(receivingMethod));
|
receivingMethods.add((ReceivingMethod) visit(receivingMethod));
|
||||||
}
|
}
|
||||||
if (ctx.receiver() != null) {
|
if (ctx.receiver() != null) {
|
||||||
@ -320,14 +320,14 @@ public class ASTGenerator extends DecafBaseVisitor<Node> {
|
|||||||
if (ctx.IntValue() != null) {
|
if (ctx.IntValue() != null) {
|
||||||
int value = Integer.parseInt(ctx.IntValue().getText());
|
int value = Integer.parseInt(ctx.IntValue().getText());
|
||||||
return new IntConstantExpression(value);
|
return new IntConstantExpression(value);
|
||||||
} else if(ctx.Identifier() != null) {
|
} else if (ctx.Identifier() != null) {
|
||||||
String identifier = ctx.Identifier().getText();
|
String identifier = ctx.Identifier().getText();
|
||||||
return new LocalVarIdentifier(identifier);
|
return new LocalVarIdentifier(identifier);
|
||||||
} else if(ctx.instVar() != null) {
|
} else if (ctx.instVar() != null) {
|
||||||
return visitInstVar(ctx.instVar());
|
return visitInstVar(ctx.instVar());
|
||||||
} else if(ctx.methodCall() != null) {
|
} else if (ctx.methodCall() != null) {
|
||||||
return visitMethodCall(ctx.methodCall());
|
return visitMethodCall(ctx.methodCall());
|
||||||
} else if(ctx.calcExpr() != null) {
|
} else if (ctx.calcExpr() != null) {
|
||||||
return visitCalcExpr(ctx.calcExpr());
|
return visitCalcExpr(ctx.calcExpr());
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@ -336,7 +336,7 @@ public class ASTGenerator extends DecafBaseVisitor<Node> {
|
|||||||
@Override
|
@Override
|
||||||
public Node visitNonCalcExpr(DecafParser.NonCalcExprContext ctx) {
|
public Node visitNonCalcExpr(DecafParser.NonCalcExprContext ctx) {
|
||||||
String operator;
|
String operator;
|
||||||
if(ctx.nonCalcOperator().LogicalOpertor() != null) {
|
if (ctx.nonCalcOperator().LogicalOpertor() != null) {
|
||||||
operator = ctx.nonCalcOperator().LogicalOpertor().getText();
|
operator = ctx.nonCalcOperator().LogicalOpertor().getText();
|
||||||
} else {
|
} else {
|
||||||
operator = ctx.nonCalcOperator().ComparisonOperator().getText();
|
operator = ctx.nonCalcOperator().ComparisonOperator().getText();
|
||||||
@ -373,10 +373,10 @@ public class ASTGenerator extends DecafBaseVisitor<Node> {
|
|||||||
List<SubReceiver> receivers = new ArrayList<>();
|
List<SubReceiver> receivers = new ArrayList<>();
|
||||||
List<ReceivingMethod> receivingMethods = new ArrayList<>();
|
List<ReceivingMethod> receivingMethods = new ArrayList<>();
|
||||||
String fieldName = ctx.Identifier().getText();
|
String fieldName = ctx.Identifier().getText();
|
||||||
for(DecafParser.SubReceiverContext subReceiver : ctx.subReceiver()) {
|
for (DecafParser.SubReceiverContext subReceiver : ctx.subReceiver()) {
|
||||||
receivers.add((SubReceiver) visit(subReceiver));
|
receivers.add((SubReceiver) visit(subReceiver));
|
||||||
}
|
}
|
||||||
for(DecafParser.ReceivingMethodContext receivingMethod: ctx.receivingMethod()) {
|
for (DecafParser.ReceivingMethodContext receivingMethod : ctx.receivingMethod()) {
|
||||||
receivingMethods.add((ReceivingMethod) visit(receivingMethod));
|
receivingMethods.add((ReceivingMethod) visit(receivingMethod));
|
||||||
}
|
}
|
||||||
return new InstVarExpression(receivers, receivingMethods, fieldName);
|
return new InstVarExpression(receivers, receivingMethods, fieldName);
|
||||||
|
@ -46,14 +46,14 @@ public class testAll {
|
|||||||
testAst(ast, pathToCode);
|
testAst(ast, pathToCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
@Test
|
@Test
|
||||||
public void testDivideByZero(){
|
public void testDivideByZero(){
|
||||||
Program ast = AssignWrongTypeAST.getProgram();
|
Program ast = DivideByZeroAST.getProgram();
|
||||||
String pathToCode = "failTests/DivideByzero.java";
|
String pathToCode = "failTests/DivideByzero.java";
|
||||||
testAst(ast, pathToCode);
|
testAst(ast, pathToCode);
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
@Test
|
@Test
|
||||||
public void testcharArgument(){
|
public void testcharArgument(){
|
||||||
Program ast = CharArgumentAST.getProgram();
|
Program ast = CharArgumentAST.getProgram();
|
||||||
|
@ -3,28 +3,48 @@ package ASTs;
|
|||||||
import abstractSyntaxTree.Class.FieldDecl;
|
import abstractSyntaxTree.Class.FieldDecl;
|
||||||
import abstractSyntaxTree.Class.MethodDecl;
|
import abstractSyntaxTree.Class.MethodDecl;
|
||||||
import abstractSyntaxTree.Class.RefType;
|
import abstractSyntaxTree.Class.RefType;
|
||||||
|
import abstractSyntaxTree.Expression.BinaryExpression;
|
||||||
|
import abstractSyntaxTree.Expression.IntConstantExpression;
|
||||||
import abstractSyntaxTree.Parameter.Parameter;
|
import abstractSyntaxTree.Parameter.Parameter;
|
||||||
import abstractSyntaxTree.Parameter.ParameterList;
|
import abstractSyntaxTree.Parameter.ParameterList;
|
||||||
|
import abstractSyntaxTree.Program;
|
||||||
import abstractSyntaxTree.Statement.BlockStatement;
|
import abstractSyntaxTree.Statement.BlockStatement;
|
||||||
|
import abstractSyntaxTree.Statement.IStatement;
|
||||||
|
import abstractSyntaxTree.Statement.LocalVarDecl;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class DivideByZeroAST {
|
public class DivideByZeroAST {
|
||||||
/*
|
|
||||||
|
public static Program getProgram() {
|
||||||
|
List<RefType> refTypeList = new ArrayList<>();
|
||||||
|
refTypeList.add(getRefType());
|
||||||
|
Program program = new Program(refTypeList);
|
||||||
|
|
||||||
|
return program;
|
||||||
|
}
|
||||||
|
|
||||||
public static RefType getRefType(){
|
public static RefType getRefType(){
|
||||||
List<FieldDecl> fieldDeclList = new ArrayList<>();
|
List<FieldDecl> fieldDeclList = new ArrayList<>();
|
||||||
List<MethodDecl> methodDeclList = new ArrayList<>();
|
List<MethodDecl> methodDeclList = new ArrayList<>();
|
||||||
RefType refType = new RefType("DivideByZero", fieldDeclList, methodDeclList, false);
|
methodDeclList.add(method0());
|
||||||
|
RefType refType = new RefType("DivideByZero", fieldDeclList, methodDeclList, true);
|
||||||
|
|
||||||
return refType;
|
return refType;
|
||||||
}
|
}
|
||||||
public static MethodDecl method0(){
|
public static MethodDecl method0(){
|
||||||
|
|
||||||
BlockStatement blockStatement = new BlockStatement();
|
BinaryExpression binaryExpression00 = new BinaryExpression("/", new IntConstantExpression(1), new IntConstantExpression(0));
|
||||||
List<Parameter> parameterList = new ArrayList<>();
|
LocalVarDecl localVarDecl00 = new LocalVarDecl("int", "a", binaryExpression00);
|
||||||
ParameterList parameterListObj = new ParameterList(parameterList);
|
List<IStatement> iStatementList = new ArrayList<>();
|
||||||
MethodDecl methodDecl = new MethodDecl("DivideByZero", "int", "test",
|
iStatementList.add(localVarDecl00);
|
||||||
|
BlockStatement blockStatement = new BlockStatement(iStatementList, null);
|
||||||
|
|
||||||
|
MethodDecl methodDecl = new MethodDecl("DivideByZero", "void", "main",
|
||||||
|
new ParameterList(new ArrayList<>()), blockStatement
|
||||||
);
|
);
|
||||||
}*/
|
|
||||||
|
return methodDecl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,69 @@
|
|||||||
package ASTs;
|
package ASTs;
|
||||||
|
|
||||||
|
import TypeCheck.TypeCheckResult;
|
||||||
|
import Typecheck.TypingHelper;
|
||||||
|
import abstractSyntaxTree.Class.FieldDecl;
|
||||||
|
import abstractSyntaxTree.Class.MethodDecl;
|
||||||
|
import abstractSyntaxTree.Class.RefType;
|
||||||
|
import abstractSyntaxTree.Expression.BinaryExpression;
|
||||||
|
import abstractSyntaxTree.Expression.IntConstantExpression;
|
||||||
|
import abstractSyntaxTree.Parameter.ParameterList;
|
||||||
|
import abstractSyntaxTree.Program;
|
||||||
|
import abstractSyntaxTree.Statement.BlockStatement;
|
||||||
|
import abstractSyntaxTree.Statement.IStatement;
|
||||||
|
import abstractSyntaxTree.Statement.LocalVarDecl;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class DivideByZeroASTTyped {
|
public class DivideByZeroASTTyped {
|
||||||
|
|
||||||
|
public static Program getProgram() {
|
||||||
|
List<RefType> refTypeList = new ArrayList<>();
|
||||||
|
refTypeList.add(getRefType());
|
||||||
|
Program program = new Program(refTypeList);
|
||||||
|
addTyping(program);
|
||||||
|
|
||||||
|
return program;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static RefType getRefType(){
|
||||||
|
List<FieldDecl> fieldDeclList = new ArrayList<>();
|
||||||
|
List<MethodDecl> methodDeclList = new ArrayList<>();
|
||||||
|
methodDeclList.add(method0());
|
||||||
|
RefType refType = new RefType("DivideByZero", fieldDeclList, methodDeclList, true);
|
||||||
|
|
||||||
|
return refType;
|
||||||
|
}
|
||||||
|
public static MethodDecl method0(){
|
||||||
|
|
||||||
|
IntConstantExpression intConstantExpression0 = new IntConstantExpression(1);
|
||||||
|
intConstantExpression0.setTypeCheckResult(new TypeCheckResult("int"));
|
||||||
|
BinaryExpression binaryExpression00 = new BinaryExpression("/", intConstantExpression0, new IntConstantExpression(0));
|
||||||
|
LocalVarDecl localVarDecl00 = new LocalVarDecl("int", "a", binaryExpression00);
|
||||||
|
List<IStatement> iStatementList = new ArrayList<>();
|
||||||
|
iStatementList.add(localVarDecl00);
|
||||||
|
BlockStatement blockStatement = new BlockStatement(iStatementList, "void");
|
||||||
|
|
||||||
|
MethodDecl methodDecl = new MethodDecl("DivideByZero", "void", "main",
|
||||||
|
new ParameterList(new ArrayList<>()), blockStatement
|
||||||
|
);
|
||||||
|
|
||||||
|
return methodDecl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void addTyping(Program program) {
|
||||||
|
//Type Context
|
||||||
|
TypingHelper.addTypeContext(program, "DivideByZero", new HashMap<>());
|
||||||
|
|
||||||
|
|
||||||
|
//Method Context
|
||||||
|
HashMap<String, ParameterList> method0 = new HashMap<>();
|
||||||
|
method0.put("void", new ParameterList(new ArrayList<>()));
|
||||||
|
HashMap<String, HashMap<String, ParameterList>> methods = new HashMap<>();
|
||||||
|
methods.put("main", method0);
|
||||||
|
TypingHelper.addMethodContext(program, "DivideByZero", methods);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -76,18 +76,24 @@ public class FakultaetAST {
|
|||||||
|
|
||||||
iStmtList0.add(localVarExpr0);
|
iStmtList0.add(localVarExpr0);
|
||||||
// Expression 2
|
// Expression 2
|
||||||
IntConstantExpression intConst1 = new IntConstantExpression(0);
|
IntConstantExpression intConst1 = new IntConstantExpression(1);
|
||||||
LocalVarDecl localVarExpr1 = new LocalVarDecl("int", "i", intConst1);
|
LocalVarDecl localVarExpr1 = new LocalVarDecl("int", "i", intConst1);
|
||||||
|
|
||||||
iStmtList0.add(localVarExpr1);
|
iStmtList0.add(localVarExpr1);
|
||||||
|
|
||||||
//While Statement
|
//While Statement
|
||||||
BinaryExpression whileCondition = new BinaryExpression("<", new LocalVarIdentifier("i"), new LocalVarIdentifier("number"));
|
BinaryExpression whileCondition = new BinaryExpression("<=", new LocalVarIdentifier("i"), new LocalVarIdentifier("number"));
|
||||||
|
|
||||||
BinaryExpression whileBinExpr = new BinaryExpression("*", new LocalVarIdentifier("factorial"), new LocalVarIdentifier("i"));
|
BinaryExpression whileBinExpr = new BinaryExpression("*", new LocalVarIdentifier("factorial"), new LocalVarIdentifier("i"));
|
||||||
AssignStatementExpression assignStatementExpression0 = new AssignStatementExpression("=", new LocalVarIdentifier("factorial"), whileBinExpr);
|
AssignStatementExpression assignStatementExpression0 = new AssignStatementExpression("=", new LocalVarIdentifier("factorial"), whileBinExpr);
|
||||||
List<IStatement> whileBlockStmts = new ArrayList<>();
|
List<IStatement> whileBlockStmts = new ArrayList<>();
|
||||||
|
|
||||||
|
LocalVarIdentifier identifierI = new LocalVarIdentifier("i");
|
||||||
|
BinaryExpression rightAssign1 = new BinaryExpression("+", identifierI, new IntConstantExpression(1));
|
||||||
|
AssignStatementExpression assignStatementExpression1 = new AssignStatementExpression("=", identifierI, rightAssign1);
|
||||||
|
|
||||||
whileBlockStmts.add(assignStatementExpression0);
|
whileBlockStmts.add(assignStatementExpression0);
|
||||||
|
whileBlockStmts.add(assignStatementExpression1);
|
||||||
BlockStatement whileBlock = new BlockStatement( whileBlockStmts, null);
|
BlockStatement whileBlock = new BlockStatement( whileBlockStmts, null);
|
||||||
|
|
||||||
WhileStatement whileStatement0 = new WhileStatement(whileCondition, whileBlock);
|
WhileStatement whileStatement0 = new WhileStatement(whileCondition, whileBlock);
|
||||||
|
@ -61,8 +61,14 @@ public class FakultaetASTTyped {
|
|||||||
// If Statament
|
// If Statament
|
||||||
//condition
|
//condition
|
||||||
LocalVarIdentifier binExprIdentifier = new LocalVarIdentifier("number");
|
LocalVarIdentifier binExprIdentifier = new LocalVarIdentifier("number");
|
||||||
|
TypeCheckResult typeCheckResultbinExprIdentifier = new TypeCheckResult();
|
||||||
|
typeCheckResultbinExprIdentifier.type = "int";
|
||||||
|
binExprIdentifier.setTypeCheckResult(typeCheckResultbinExprIdentifier);
|
||||||
IntConstantExpression binExprIntConst = new IntConstantExpression(0);
|
IntConstantExpression binExprIntConst = new IntConstantExpression(0);
|
||||||
BinaryExpression binExpr = new BinaryExpression("<", binExprIdentifier, binExprIntConst);
|
BinaryExpression binExpr = new BinaryExpression("<", binExprIdentifier, binExprIntConst);
|
||||||
|
TypeCheckResult typeCheckResultbinExpr = new TypeCheckResult();
|
||||||
|
typeCheckResultbinExpr.type = "boolean";
|
||||||
|
binExpr.setTypeCheckResult(typeCheckResultbinExpr);
|
||||||
|
|
||||||
IntConstantExpression return0Expr0 = new IntConstantExpression(1);
|
IntConstantExpression return0Expr0 = new IntConstantExpression(1);
|
||||||
TypeCheckResult typeCheckResult1 = new TypeCheckResult();
|
TypeCheckResult typeCheckResult1 = new TypeCheckResult();
|
||||||
@ -88,12 +94,19 @@ public class FakultaetASTTyped {
|
|||||||
iStmtList0.add(localVarExpr1);
|
iStmtList0.add(localVarExpr1);
|
||||||
|
|
||||||
//While Statement
|
//While Statement
|
||||||
BinaryExpression whileCondition = new BinaryExpression("<", new LocalVarIdentifier("i"), new LocalVarIdentifier("number"));
|
BinaryExpression whileCondition = new BinaryExpression("<=", new LocalVarIdentifier("i"), new LocalVarIdentifier("number"));
|
||||||
|
whileCondition.setTypeCheckResult(new TypeCheckResult("void"));
|
||||||
|
|
||||||
BinaryExpression whileBinExpr = new BinaryExpression("*", new LocalVarIdentifier("factorial"), new LocalVarIdentifier("i"));
|
BinaryExpression whileBinExpr = new BinaryExpression("*", new LocalVarIdentifier("factorial"), new LocalVarIdentifier("i"));
|
||||||
AssignStatementExpression assignStatementExpression0 = new AssignStatementExpression("=", new LocalVarIdentifier("factorial"), whileBinExpr);
|
AssignStatementExpression assignStatementExpression0 = new AssignStatementExpression("=", new LocalVarIdentifier("factorial"), whileBinExpr);
|
||||||
List<IStatement> whileBlockStmts = new ArrayList<>();
|
List<IStatement> whileBlockStmts = new ArrayList<>();
|
||||||
|
|
||||||
|
LocalVarIdentifier identifierI = new LocalVarIdentifier("i");
|
||||||
|
BinaryExpression rightAssign1 = new BinaryExpression("+", identifierI, new IntConstantExpression(1));
|
||||||
|
AssignStatementExpression assignStatementExpression1 = new AssignStatementExpression("=", identifierI, rightAssign1);
|
||||||
|
|
||||||
whileBlockStmts.add(assignStatementExpression0);
|
whileBlockStmts.add(assignStatementExpression0);
|
||||||
|
whileBlockStmts.add(assignStatementExpression1);
|
||||||
BlockStatement whileBlock = new BlockStatement( whileBlockStmts, "void");
|
BlockStatement whileBlock = new BlockStatement( whileBlockStmts, "void");
|
||||||
|
|
||||||
WhileStatement whileStatement0 = new WhileStatement(whileCondition, whileBlock);
|
WhileStatement whileStatement0 = new WhileStatement(whileCondition, whileBlock);
|
||||||
|
@ -23,49 +23,32 @@ public class ByteCodeTester {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testByteCodeFromAst(String correctClassFilePath, Program abstractSyntaxTree, String className) {
|
public void testByteCodeFromAst(String correctClassFilePath, Program abstractSyntaxTree, String className) {
|
||||||
testClassFile(false, className, abstractSyntaxTree, correctClassFilePath, null);
|
typeCheckWithoutmain(abstractSyntaxTree);
|
||||||
|
generateCode(abstractSyntaxTree);
|
||||||
|
testAST(correctClassFilePath, className);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testByteCodeFromTypedAst(String correctClassFilePath, Program abstractSyntaxTree, String className) {
|
||||||
|
generateCode(abstractSyntaxTree);
|
||||||
|
testAST(correctClassFilePath, className);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testClassFileFromScratch(String correctClassFilePath, String fileToComparePath, String className) {
|
public void testClassFileFromScratch(String correctClassFilePath, String fileToComparePath, String className) {
|
||||||
testClassFile(true, className, null, correctClassFilePath, fileToComparePath);
|
Program abstractSyntaxTree = generateAST(fileToComparePath);
|
||||||
|
typeCheckWithoutmain(abstractSyntaxTree);
|
||||||
|
generateCode(abstractSyntaxTree);
|
||||||
|
testAST(correctClassFilePath, className);
|
||||||
}
|
}
|
||||||
public void testClassFile(boolean generateAST, String className, Program abstractSyntaxTree,
|
|
||||||
String correctClassFilePath, String fileToComparePath) {
|
|
||||||
|
|
||||||
if(generateAST){
|
private void typeCheckWithoutmain(Program abstractSyntaxTree){
|
||||||
String content = "";
|
try {
|
||||||
try {
|
abstractSyntaxTree.typeCheckWithoutMain();
|
||||||
System.out.println("Classpath: " + Path.of(fileToComparePath));
|
} catch (Exception e){
|
||||||
content = Files.readString(Path.of(fileToComparePath));
|
System.out.println("Le Exception in le type-check");
|
||||||
} catch (IOException e) {
|
|
||||||
System.out.println("File not found!");
|
|
||||||
fail();
|
|
||||||
}
|
|
||||||
|
|
||||||
CharStream codeCharStream = CharStreams.fromString(content);
|
|
||||||
DecafLexer lexer = new DecafLexer(codeCharStream);
|
|
||||||
CommonTokenStream tokens = new CommonTokenStream(lexer);
|
|
||||||
|
|
||||||
tokens.fill();
|
|
||||||
|
|
||||||
DecafParser parser = new DecafParser(tokens);
|
|
||||||
|
|
||||||
ParseTree tree = parser.program();
|
|
||||||
|
|
||||||
ASTGenerator generator = new ASTGenerator();
|
|
||||||
abstractSyntaxTree = (Program) generator.visit(tree);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(generateAST){
|
private void generateCode(Program abstractSyntaxTree){
|
||||||
try {
|
|
||||||
abstractSyntaxTree.typeCheckWithoutMain();
|
|
||||||
} catch (Exception e){
|
|
||||||
System.out.println("Le Exception in le type-check");
|
|
||||||
//fail();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
abstractSyntaxTree.codeGen();
|
abstractSyntaxTree.codeGen();
|
||||||
} catch (Exception e){
|
} catch (Exception e){
|
||||||
@ -73,7 +56,9 @@ public class ByteCodeTester {
|
|||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
fail();
|
fail();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void testAST(String correctClassFilePath, String className) {
|
||||||
try {
|
try {
|
||||||
ClassFileLoader classLoader1 = new ClassFileLoader(correctClassFilePath);
|
ClassFileLoader classLoader1 = new ClassFileLoader(correctClassFilePath);
|
||||||
ClassFileLoader classLoader2 = new ClassFileLoader(className+ ".class");
|
ClassFileLoader classLoader2 = new ClassFileLoader(className+ ".class");
|
||||||
@ -89,6 +74,31 @@ public class ByteCodeTester {
|
|||||||
fail();
|
fail();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
private Program generateAST(String pathToJavaFile){
|
||||||
|
String content = "";
|
||||||
|
try {
|
||||||
|
System.out.println("Classpath: " + Path.of(pathToJavaFile));
|
||||||
|
content = Files.readString(Path.of(pathToJavaFile));
|
||||||
|
} catch (IOException e) {
|
||||||
|
System.out.println("File not found!");
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
|
||||||
|
CharStream codeCharStream = CharStreams.fromString(content);
|
||||||
|
DecafLexer lexer = new DecafLexer(codeCharStream);
|
||||||
|
CommonTokenStream tokens = new CommonTokenStream(lexer);
|
||||||
|
|
||||||
|
tokens.fill();
|
||||||
|
|
||||||
|
DecafParser parser = new DecafParser(tokens);
|
||||||
|
|
||||||
|
ParseTree tree = parser.program();
|
||||||
|
|
||||||
|
ASTGenerator generator = new ASTGenerator();
|
||||||
|
Program abstractSyntaxTree = (Program) generator.visit(tree);
|
||||||
|
|
||||||
|
return abstractSyntaxTree;
|
||||||
|
}
|
||||||
|
|
||||||
public void compareJarFilesFromAST(Program abstractSyntaxTree, String jarPath, String[] classNames){
|
public void compareJarFilesFromAST(Program abstractSyntaxTree, String jarPath, String[] classNames){
|
||||||
try {
|
try {
|
||||||
|
@ -38,6 +38,14 @@ public class CompareByteCodeBehaviour {
|
|||||||
Method[] methods1 = class1.getDeclaredMethods();
|
Method[] methods1 = class1.getDeclaredMethods();
|
||||||
Method[] methods2 = class2.getDeclaredMethods();
|
Method[] methods2 = class2.getDeclaredMethods();
|
||||||
|
|
||||||
|
/*
|
||||||
|
for(int i = 0; i < methods1.length; i++) {
|
||||||
|
System.out.println("Method1[" + i + "]: " + methods1[i]);
|
||||||
|
System.out.println("Method2[" + i + "]: " + methods2[i]);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
for (Method method1 : methods1) {
|
for (Method method1 : methods1) {
|
||||||
for (Method method2 : methods2) {
|
for (Method method2 : methods2) {
|
||||||
if (compareMethod(method1, method2)) {
|
if (compareMethod(method1, method2)) {
|
||||||
@ -49,6 +57,12 @@ public class CompareByteCodeBehaviour {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
for(int i = 0; i < this.methodArray1.size(); i++){
|
||||||
|
System.out.println("Method1[" + i + "]: " + methodArray1.get(i));
|
||||||
|
System.out.println("Method2[" + i + "]: " + methodArray2.get(i));
|
||||||
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean compareMethodBehaviour(Class<?> class1, Class<?> class2){
|
public boolean compareMethodBehaviour(Class<?> class1, Class<?> class2){
|
||||||
@ -72,12 +86,23 @@ public class CompareByteCodeBehaviour {
|
|||||||
Method[] methods2 = new Method[this.methodArray2.size()];
|
Method[] methods2 = new Method[this.methodArray2.size()];
|
||||||
methods2 = this.methodArray2.toArray(methods2);
|
methods2 = this.methodArray2.toArray(methods2);
|
||||||
|
|
||||||
|
/*
|
||||||
|
for(int i = 0; i < methods1.length; i++) {
|
||||||
|
System.out.println("MethodArray1 [" + i + "]: " + methods1[i]);
|
||||||
|
System.out.println("MethodArray2 [" + i + "]: " + methods2[i]);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
System.out.println("length: " + methods1.length);
|
||||||
// Compare methods
|
// Compare methods
|
||||||
for (int i = 0; i < methods1.length; i++) {
|
for (int i = 0; i < methods1.length; i++) {
|
||||||
|
System.out.println("i: " + i);
|
||||||
Method method1 = methods1[i];
|
Method method1 = methods1[i];
|
||||||
Method method2 = methods2[i];
|
Method method2 = methods2[i];
|
||||||
|
|
||||||
|
System.out.println(method1);
|
||||||
|
System.out.println(method2);
|
||||||
|
|
||||||
method1.setAccessible(true);
|
method1.setAccessible(true);
|
||||||
method2.setAccessible(true);
|
method2.setAccessible(true);
|
||||||
|
|
||||||
@ -88,16 +113,19 @@ public class CompareByteCodeBehaviour {
|
|||||||
Object result1 = method1.invoke(obj1, testInputs);
|
Object result1 = method1.invoke(obj1, testInputs);
|
||||||
Object result2 = method2.invoke(obj2, testInputs);
|
Object result2 = method2.invoke(obj2, testInputs);
|
||||||
|
|
||||||
if( (result1 == null) && (result2 == null)) {
|
System.out.println("Result method 1: " + result1);
|
||||||
return true;
|
System.out.println("Result method 2: " + result2);
|
||||||
}
|
|
||||||
if(( result1 == null) || (result2 == null) ) {
|
if( !((result1 == null) && (result2 == null))) {
|
||||||
return false;
|
if(( result1 == null) || (result2 == null) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!result1.equals(result2)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!result1.equals(result2)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (InstantiationException | IllegalAccessException |
|
} catch (InstantiationException | IllegalAccessException |
|
||||||
|
@ -18,18 +18,28 @@ public class TestAll {
|
|||||||
Program ast = emptyClassASTTyped.getEmptyProgramm();
|
Program ast = emptyClassASTTyped.getEmptyProgramm();
|
||||||
String className = "emptyClass";
|
String className = "emptyClass";
|
||||||
String javacode = "src/test/resources/basicClasses/emptyClass.java";
|
String javacode = "src/test/resources/basicClasses/emptyClass.java";
|
||||||
//byteCodeTester.testByteCodeFromAst(classPath, ast ,className);
|
byteCodeTester.testByteCodeFromTypedAst(classPath, ast ,className);
|
||||||
byteCodeTester.testClassFileFromScratch(classPath, javacode, className);
|
//byteCodeTester.testClassFileFromScratch(classPath, javacode, className);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEmptyClassWithConstructor() {
|
||||||
|
String classPath = "src/test/resources/basicClasses/EmptyClassWithConstructor.class";
|
||||||
|
Program ast = EmptyClassWithConstructorASTTyped.getProgram();
|
||||||
|
String className = "EmptyClassWithConstructor";
|
||||||
|
String javacode = "src/test/resources/basicClasses/emptyClass.java";
|
||||||
|
byteCodeTester.testByteCodeFromTypedAst(classPath, ast ,className);
|
||||||
|
//byteCodeTester.testClassFileFromScratch(classPath, javacode, className);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFakultaet() {
|
public void testFakultaet() {
|
||||||
String classPath = "src/test/resources/basicClasses/Fakultaet.class";
|
String classPath = "src/test/resources/basicClasses/Fakultaet.class";
|
||||||
Program ast = FakultaetASTTyped.getProgram();
|
Program ast = FakultaetAST.getProgram();
|
||||||
String className = "Fakultaet";
|
String className = "Fakultaet";
|
||||||
String javacode = "src/test/resources/basicClasses/Fakultaet.java";
|
String javacode = "src/test/resources/basicClasses/Fakultaet.java";
|
||||||
//byteCodeTester.testByteCodeFromAst(classPath, ast ,className);
|
byteCodeTester.testByteCodeFromAst(classPath, ast ,className);
|
||||||
byteCodeTester.testClassFileFromScratch(classPath, javacode, className);
|
//byteCodeTester.testClassFileFromScratch(classPath, javacode, className);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -38,17 +48,17 @@ public class TestAll {
|
|||||||
Program ast = ClassWithMainASTTyped.getProgram();
|
Program ast = ClassWithMainASTTyped.getProgram();
|
||||||
String className = "classWithMain";
|
String className = "classWithMain";
|
||||||
String javacode = "src/test/resources/basicClasses/classWithMain.java";
|
String javacode = "src/test/resources/basicClasses/classWithMain.java";
|
||||||
//testByteCodeFromAst(classPath, ast ,className);
|
byteCodeTester.testByteCodeFromTypedAst(classPath, ast ,className);
|
||||||
byteCodeTester.testClassFileFromScratch(classPath, javacode, className);
|
//byteCodeTester.testClassFileFromScratch(classPath, javacode, className);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCharArgument() {
|
public void testCharArgument() {
|
||||||
String classPath = "src/test/resources/SimpleTests/CharArgument.class";
|
String classPath = "src/test/resources/SimpleTests/CharArgument.class";
|
||||||
//Program ast = ClassWithMainASTTyped.getProgram();
|
Program ast = CharArgumentAST.getProgram();
|
||||||
String className = "CharArgument";
|
String className = "CharArgument";
|
||||||
String javacode = "src/test/resources/SimpleTests/CharArgument.java";
|
String javacode = "src/test/resources/SimpleTests/CharArgument.java";
|
||||||
//testByteCodeFromAst(classPath, ast ,className);
|
byteCodeTester.testByteCodeFromAst(classPath, ast ,className);
|
||||||
byteCodeTester.testClassFileFromScratch(classPath, javacode, className);
|
byteCodeTester.testClassFileFromScratch(classPath, javacode, className);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,6 +101,14 @@ public class TestAll {
|
|||||||
testTypeCheck(fakultaet, correctAST, expectedResult);
|
testTypeCheck(fakultaet, correctAST, expectedResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDivideByZero(){
|
||||||
|
Program fakultaet = DivideByZeroAST.getProgram();
|
||||||
|
Program correctAST = DivideByZeroASTTyped.getProgram();
|
||||||
|
boolean expectedResult = true;
|
||||||
|
testTypeCheck(fakultaet, correctAST, expectedResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void testTypeCheckWM(Program abstractSyntaxTree, Program correctAST, boolean expectedResult){
|
public void testTypeCheckWM(Program abstractSyntaxTree, Program correctAST, boolean expectedResult){
|
||||||
abstractSyntaxTree.classes.add(ClassWithMainASTTyped.getRefType());
|
abstractSyntaxTree.classes.add(ClassWithMainASTTyped.getRefType());
|
||||||
|
Binary file not shown.
@ -4,9 +4,10 @@ class Fakultaet {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
int factorial = 1;
|
int factorial = 1;
|
||||||
int i = 0;
|
int i = 1;
|
||||||
while(i < number){
|
while(i <= number){
|
||||||
factorial = factorial * i;
|
factorial = factorial * i;
|
||||||
|
i = i + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return factorial;
|
return factorial;
|
||||||
|
Loading…
Reference in New Issue
Block a user