Merge remote-tracking branch 'origin/master'
# Conflicts: # src/main/java/abstractSyntaxTree/Expression/IExpression.java
This commit is contained in:
commit
873d1b7a0a
@ -1,5 +1,14 @@
|
|||||||
import abstractSyntaxTree.Class.RefType;
|
import abstractSyntaxTree.Class.RefType;
|
||||||
|
import abstractSyntaxTree.Datatype.BoolDatatype;
|
||||||
|
import abstractSyntaxTree.Datatype.IntDatatype;
|
||||||
|
import abstractSyntaxTree.Expression.InstVarExpression;
|
||||||
|
import abstractSyntaxTree.Expression.LocalVarIdentifier;
|
||||||
|
import abstractSyntaxTree.Expression.UnaryExpression;
|
||||||
import abstractSyntaxTree.Program;
|
import abstractSyntaxTree.Program;
|
||||||
|
import abstractSyntaxTree.Statement.IStatement;
|
||||||
|
import abstractSyntaxTree.Statement.LocalVarDecl;
|
||||||
|
import abstractSyntaxTree.Statement.ReturnStatement;
|
||||||
|
import abstractSyntaxTree.StatementExpression.AssignStatementExpression;
|
||||||
import astGenerator.ASTGenerator;
|
import astGenerator.ASTGenerator;
|
||||||
import gen.DecafLexer;
|
import gen.DecafLexer;
|
||||||
import gen.DecafParser;
|
import gen.DecafParser;
|
||||||
@ -82,6 +91,16 @@ public class Compiler {
|
|||||||
// System.out.println(refType.name);
|
// System.out.println(refType.name);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
abstractSyntaxTree.classes.get(1).methodDecls.get(0).codeBlock.returnType = "int";
|
||||||
|
List<IStatement> statementsList = abstractSyntaxTree.classes.get(1).methodDecls.get(0).codeBlock.statements;
|
||||||
|
statementsList.remove(0);
|
||||||
|
statementsList.add(new LocalVarDecl("int", "localInt"));
|
||||||
|
statementsList.add(new LocalVarDecl("bool", "localBool"));
|
||||||
|
statementsList.add(new LocalVarDecl("char", "localChar"));
|
||||||
|
statementsList.add(new AssignStatementExpression("=", new LocalVarIdentifier("localInt"), new UnaryExpression("", new IntDatatype())));
|
||||||
|
statementsList.add(new AssignStatementExpression("=", new InstVarExpression(abstractSyntaxTree.classes.get(1), "instVarBool"), new UnaryExpression("instVarBool", new BoolDatatype())));
|
||||||
|
|
||||||
|
abstractSyntaxTree.classes.get(1).methodDecls.get(0).codeBlock.statements.add(new ReturnStatement(new UnaryExpression("", new IntDatatype())));
|
||||||
abstractSyntaxTree.typeCheck();
|
abstractSyntaxTree.typeCheck();
|
||||||
|
|
||||||
abstractSyntaxTree.codeGen();
|
abstractSyntaxTree.codeGen();
|
||||||
|
@ -5,7 +5,7 @@ class Example {
|
|||||||
|
|
||||||
}
|
}
|
||||||
class Example2 {
|
class Example2 {
|
||||||
int i;
|
boolean instVarBool;
|
||||||
boolean j;
|
int m(int n){return 1;}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
6
src/main/java/TestClass.java
Normal file
6
src/main/java/TestClass.java
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
public class TestClass {
|
||||||
|
public static void main(String[] args){
|
||||||
|
new Example();
|
||||||
|
new Example2();
|
||||||
|
}
|
||||||
|
}
|
@ -12,8 +12,9 @@ public class TypeCheckHelper {
|
|||||||
if(type1Primitiv && type2Primitiv){
|
if(type1Primitiv && type2Primitiv){
|
||||||
if(Objects.equals(type1, type2)){
|
if(Objects.equals(type1, type2)){
|
||||||
result = type1;
|
result = type1;
|
||||||
|
}else{
|
||||||
|
throw new Exception("no upper bound");
|
||||||
}
|
}
|
||||||
throw new Exception("no upper bound");
|
|
||||||
}else if(type1Primitiv || type2Primitiv){
|
}else if(type1Primitiv || type2Primitiv){
|
||||||
throw new Exception("no upper bound");
|
throw new Exception("no upper bound");
|
||||||
}else{
|
}else{
|
||||||
|
@ -12,8 +12,9 @@ import org.objectweb.asm.Opcodes;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public class FieldDecl extends AbstractType implements IClass, Node {
|
public class FieldDecl extends AbstractType implements Node {
|
||||||
|
|
||||||
public String type; // from parser
|
public String type; // from parser
|
||||||
public String identifier; // from parser
|
public String identifier; // from parser
|
||||||
@ -35,19 +36,13 @@ public class FieldDecl extends AbstractType implements IClass, Node {
|
|||||||
//write field table
|
//write field table
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, List<String>>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, List<MethodDecl> fieldsOrMethods) throws Exception {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void codeGen(ClassWriter cw) {
|
public void codeGen(ClassWriter cw) {
|
||||||
//TODO: Do we have fields with initial values?
|
//TODO: Do we have fields with initial values? --> No dont think so --> assign
|
||||||
FieldVisitor fv = cw.visitField(Opcodes.ACC_PUBLIC, identifier, getFieldDescriptor(), null, null);
|
FieldVisitor fv = cw.visitField(Opcodes.ACC_PUBLIC, identifier, getFieldDescriptor(), null, null);
|
||||||
fv.visitEnd();
|
fv.visitEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getFieldDescriptor() {
|
private String getFieldDescriptor() {
|
||||||
//TODO: Maybe we have to check for arrays?
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "int":
|
case "int":
|
||||||
return "I";
|
return "I";
|
||||||
@ -59,4 +54,13 @@ public class FieldDecl extends AbstractType implements IClass, Node {
|
|||||||
return "L" + type + ";";
|
return "L" + type + ";";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
FieldDecl fieldDecl = (FieldDecl) o;
|
||||||
|
return ( Objects.equals(type, fieldDecl.type)
|
||||||
|
&& Objects.equals(identifier, fieldDecl.identifier));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,10 +9,7 @@ import abstractSyntaxTree.Statement.BlockStatement;
|
|||||||
import abstractSyntaxTree.Statement.IStatement;
|
import abstractSyntaxTree.Statement.IStatement;
|
||||||
import org.objectweb.asm.*;
|
import org.objectweb.asm.*;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Stack;
|
|
||||||
|
|
||||||
public class MethodDecl implements Node {
|
public class MethodDecl implements Node {
|
||||||
|
|
||||||
@ -25,7 +22,8 @@ public class MethodDecl implements Node {
|
|||||||
public String returnType;
|
public String returnType;
|
||||||
public BlockStatement codeBlock;
|
public BlockStatement codeBlock;
|
||||||
|
|
||||||
public HashMap<String, String> localVars;
|
//TODO: Can this be a linked hash map? --> need it to be to get the index of local variables
|
||||||
|
public LinkedHashMap<String, String> localVars;
|
||||||
|
|
||||||
public MethodDecl(String classThatContainsMethod, String returnType, String name, ParameterList parameters, BlockStatement codeBlock){
|
public MethodDecl(String classThatContainsMethod, String returnType, String name, ParameterList parameters, BlockStatement codeBlock){
|
||||||
this.classThatContainsMethod = classThatContainsMethod;
|
this.classThatContainsMethod = classThatContainsMethod;
|
||||||
@ -33,14 +31,16 @@ public class MethodDecl implements Node {
|
|||||||
this.name = name;
|
this.name = name;
|
||||||
this.parameters = parameters;
|
this.parameters = parameters;
|
||||||
this.codeBlock = codeBlock;
|
this.codeBlock = codeBlock;
|
||||||
this.localVars = new HashMap<>();
|
this.localVars = new LinkedHashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, List<String>>>> methodContext, HashMap<String, HashMap<String, String>> typeContext) throws Exception {
|
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext) throws Exception {
|
||||||
// jede methode als block statement aufrufen und jede neue locale varibale in localvars schreiben
|
// jede methode als block statement aufrufen und jede neue locale varibale in localvars schreiben
|
||||||
|
|
||||||
codeBlock.typeCheck(methodContext, typeContext);
|
TypeCheckResult result = new TypeCheckResult();
|
||||||
return null;
|
codeBlock.typeCheck(methodContext, typeContext, localVars);
|
||||||
|
result.type = codeBlock.returnType;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -117,7 +117,7 @@ public class MethodDecl implements Node {
|
|||||||
for (Parameter param : parameters.parameterList) {
|
for (Parameter param : parameters.parameterList) {
|
||||||
switch (param.type) {
|
switch (param.type) {
|
||||||
case "int" -> descriptor.append("I");
|
case "int" -> descriptor.append("I");
|
||||||
case "boolean" -> descriptor.append("Z");
|
case "bool" -> descriptor.append("Z");
|
||||||
case "char" -> descriptor.append("C");
|
case "char" -> descriptor.append("C");
|
||||||
case "void" -> descriptor.append("V");
|
case "void" -> descriptor.append("V");
|
||||||
default -> {
|
default -> {
|
||||||
@ -137,7 +137,7 @@ public class MethodDecl implements Node {
|
|||||||
} else {
|
} else {
|
||||||
switch (returnType) {
|
switch (returnType) {
|
||||||
case "int" -> descriptor.append("I");
|
case "int" -> descriptor.append("I");
|
||||||
case "boolean" -> descriptor.append("Z");
|
case "bool" -> descriptor.append("Z");
|
||||||
case "char" -> descriptor.append("C");
|
case "char" -> descriptor.append("C");
|
||||||
case "void" -> descriptor.append("V");
|
case "void" -> descriptor.append("V");
|
||||||
default -> {
|
default -> {
|
||||||
@ -158,4 +158,16 @@ public class MethodDecl implements Node {
|
|||||||
}
|
}
|
||||||
return descriptor.toString();
|
return descriptor.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
MethodDecl methodDecl = (MethodDecl) o;
|
||||||
|
return (Objects.equals(name, methodDecl.name)
|
||||||
|
&& Objects.equals(parameters, methodDecl.parameters)
|
||||||
|
&& Objects.equals(returnType, methodDecl.returnType)
|
||||||
|
&& Objects.equals(codeBlock, methodDecl.codeBlock));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ import org.objectweb.asm.Opcodes;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public class RefType extends AbstractType implements Node {
|
public class RefType extends AbstractType implements Node {
|
||||||
|
|
||||||
@ -30,7 +31,7 @@ public class RefType extends AbstractType implements Node {
|
|||||||
this.hasMain = hasMain;
|
this.hasMain = hasMain;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, List<String>>>> methodContext,
|
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext,
|
||||||
HashMap<String, HashMap<String, String>> typeContext) throws Exception {
|
HashMap<String, HashMap<String, String>> typeContext) throws Exception {
|
||||||
TypeCheckResult result = new TypeCheckResult();
|
TypeCheckResult result = new TypeCheckResult();
|
||||||
|
|
||||||
@ -73,7 +74,8 @@ public class RefType extends AbstractType implements Node {
|
|||||||
|
|
||||||
// Method for code generation which iterates over all the field declarations
|
// Method for code generation which iterates over all the field declarations
|
||||||
// and method declarations and calls their CodeGen methods
|
// and method declarations and calls their CodeGen methods
|
||||||
public void codeGen(ClassWriter cw, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext) throws Exception {
|
|
||||||
|
public void codeGen(ClassWriter cw, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext) throws Exception {
|
||||||
|
|
||||||
cw.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, name, null,
|
cw.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, name, null,
|
||||||
"java/lang/Object", null);
|
"java/lang/Object", null);
|
||||||
@ -83,10 +85,21 @@ public class RefType extends AbstractType implements Node {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (MethodDecl method : methodDecls) {
|
for (MethodDecl method : methodDecls) {
|
||||||
method.codeGen(cw, methodContext);
|
method.codeGen(cw, methodContext);
|
||||||
}
|
}
|
||||||
cw.visitEnd();
|
cw.visitEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
System.out.println("Dont forget me ;)");
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
RefType refType = (RefType) o;
|
||||||
|
return ( Objects.equals(name, refType.name)
|
||||||
|
&& Objects.equals(fieldDecls, refType.fieldDecls)
|
||||||
|
&& Objects.equals(methodDecls, refType.methodDecls)
|
||||||
|
&& Objects.equals(hasMain, refType.hasMain));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,12 @@ package abstractSyntaxTree.Expression;
|
|||||||
import TypeCheck.TypeCheckResult;
|
import TypeCheck.TypeCheckResult;
|
||||||
import TypeCheck.TypeCheckHelper;
|
import TypeCheck.TypeCheckHelper;
|
||||||
import TypeCheck.AbstractType;
|
import TypeCheck.AbstractType;
|
||||||
|
import abstractSyntaxTree.Parameter.ParameterList;
|
||||||
import org.objectweb.asm.*;
|
import org.objectweb.asm.*;
|
||||||
|
|
||||||
import java.beans.Expression;
|
import java.beans.Expression;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public class BinaryExpression extends AbstractType implements IExpression{
|
public class BinaryExpression extends AbstractType implements IExpression{
|
||||||
@ -43,7 +46,7 @@ public class BinaryExpression extends AbstractType implements IExpression{
|
|||||||
case "<=":
|
case "<=":
|
||||||
case ">=":
|
case ">=":
|
||||||
case "!=":
|
case "!=":
|
||||||
result.type = helper.upperBound(leftType.type, rightType.type);
|
result.type = helper.upperBound(leftType.type, rightType.type);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "-":
|
case "-":
|
||||||
@ -65,7 +68,12 @@ public class BinaryExpression extends AbstractType implements IExpression{
|
|||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodVisitor mv) throws Exception {
|
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void codeGen(MethodVisitor mv, HashMap<String, HashMap<String, String>> typeContext, LinkedHashMap<String, String> localVars) throws Exception {
|
||||||
// Label for the jump instruction
|
// Label for the jump instruction
|
||||||
Label operationFalse = new Label(); //Operation is false
|
Label operationFalse = new Label(); //Operation is false
|
||||||
Label operationTrue = new Label(); //Operation is true
|
Label operationTrue = new Label(); //Operation is true
|
||||||
@ -75,88 +83,88 @@ public class BinaryExpression extends AbstractType implements IExpression{
|
|||||||
// Bytecode for the binary operation
|
// Bytecode for the binary operation
|
||||||
switch (operator) {
|
switch (operator) {
|
||||||
case "&&":
|
case "&&":
|
||||||
left.codeGen(mv);
|
left.codeGen(mv, typeContext, localVars);
|
||||||
mv.visitJumpInsn(Opcodes.IFEQ, operationFalse); // IFEQ --> "if equals to zero" (false) --> if left exp is false
|
mv.visitJumpInsn(Opcodes.IFEQ, operationFalse); // IFEQ --> "if equals to zero" (false) --> if left exp is false
|
||||||
|
|
||||||
right.codeGen(mv);
|
right.codeGen(mv, typeContext, localVars);
|
||||||
mv.visitJumpInsn(Opcodes.IFEQ, operationFalse); // If right exp is false, jump to the end of the whole expression
|
mv.visitJumpInsn(Opcodes.IFEQ, operationFalse); // If right exp is false, jump to the end of the whole expression
|
||||||
|
|
||||||
mv.visitJumpInsn(Opcodes.GOTO, operationTrue); // If it reaches this point, the right exp is true
|
mv.visitJumpInsn(Opcodes.GOTO, operationTrue); // If it reaches this point, the right exp is true
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "||":
|
case "||":
|
||||||
left.codeGen(mv);
|
left.codeGen(mv, typeContext, localVars);
|
||||||
mv.visitJumpInsn(Opcodes.IFNE, operationTrue); // IFNE --> "if not equals to zero" (true) --> if left exp is true
|
mv.visitJumpInsn(Opcodes.IFNE, operationTrue); // IFNE --> "if not equals to zero" (true) --> if left exp is true
|
||||||
|
|
||||||
right.codeGen(mv);
|
right.codeGen(mv, typeContext, localVars);
|
||||||
mv.visitJumpInsn(Opcodes.IFNE, operationTrue);
|
mv.visitJumpInsn(Opcodes.IFNE, operationTrue);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "==":
|
case "==":
|
||||||
// Keep in mind that only primitive types are allowed in this case (at this time)
|
// Keep in mind that only primitive types are allowed in this case (at this time)
|
||||||
|
|
||||||
left.codeGen(mv);
|
left.codeGen(mv, typeContext, localVars);
|
||||||
right.codeGen(mv);
|
right.codeGen(mv, typeContext, localVars);
|
||||||
|
|
||||||
mv.visitJumpInsn(Opcodes.IF_ICMPEQ, operationTrue); // If the two values are equal, jump to the end of the expression
|
mv.visitJumpInsn(Opcodes.IF_ICMPEQ, operationTrue); // If the two values are equal, jump to the end of the expression
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "<":
|
case "<":
|
||||||
left.codeGen(mv);
|
left.codeGen(mv, typeContext, localVars);
|
||||||
right.codeGen(mv);
|
right.codeGen(mv, typeContext, localVars);
|
||||||
|
|
||||||
mv.visitJumpInsn(Opcodes.IF_ICMPLT, operationTrue); // Checks only on less than, not equal
|
mv.visitJumpInsn(Opcodes.IF_ICMPLT, operationTrue); // Checks only on less than, not equal
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ">":
|
case ">":
|
||||||
left.codeGen(mv);
|
left.codeGen(mv, typeContext, localVars);
|
||||||
right.codeGen(mv);
|
right.codeGen(mv, typeContext, localVars);
|
||||||
|
|
||||||
mv.visitJumpInsn(Opcodes.IF_ICMPGT, operationTrue); // Checks only on greater than, not equal
|
mv.visitJumpInsn(Opcodes.IF_ICMPGT, operationTrue); // Checks only on greater than, not equal
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "<=":
|
case "<=":
|
||||||
left.codeGen(mv);
|
left.codeGen(mv, typeContext, localVars);
|
||||||
right.codeGen(mv);
|
right.codeGen(mv, typeContext, localVars);
|
||||||
|
|
||||||
mv.visitJumpInsn(Opcodes.IF_ICMPLE, operationTrue); // Checks on less than OR equal
|
mv.visitJumpInsn(Opcodes.IF_ICMPLE, operationTrue); // Checks on less than OR equal
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ">=":
|
case ">=":
|
||||||
left.codeGen(mv);
|
left.codeGen(mv, typeContext, localVars);
|
||||||
right.codeGen(mv);
|
right.codeGen(mv, typeContext, localVars);
|
||||||
|
|
||||||
mv.visitJumpInsn(Opcodes.IF_ICMPGE, operationTrue); // Checks on greater than OR equal
|
mv.visitJumpInsn(Opcodes.IF_ICMPGE, operationTrue); // Checks on greater than OR equal
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "!=":
|
case "!=":
|
||||||
left.codeGen(mv);
|
left.codeGen(mv, typeContext, localVars);
|
||||||
right.codeGen(mv);
|
right.codeGen(mv, typeContext, localVars);
|
||||||
|
|
||||||
mv.visitJumpInsn(Opcodes.IF_ICMPNE, operationTrue); // Checks on not equal
|
mv.visitJumpInsn(Opcodes.IF_ICMPNE, operationTrue); // Checks on not equal
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "+":
|
case "+":
|
||||||
left.codeGen(mv);
|
left.codeGen(mv, typeContext, localVars);
|
||||||
right.codeGen(mv);
|
right.codeGen(mv, typeContext, localVars);
|
||||||
mv.visitInsn(Opcodes.IADD);
|
mv.visitInsn(Opcodes.IADD);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "-":
|
case "-":
|
||||||
left.codeGen(mv);
|
left.codeGen(mv, typeContext, localVars);
|
||||||
right.codeGen(mv);
|
right.codeGen(mv, typeContext, localVars);
|
||||||
mv.visitInsn(Opcodes.ISUB);
|
mv.visitInsn(Opcodes.ISUB);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "*":
|
case "*":
|
||||||
left.codeGen(mv);
|
left.codeGen(mv, typeContext, localVars);
|
||||||
right.codeGen(mv);
|
right.codeGen(mv, typeContext, localVars);
|
||||||
mv.visitInsn(Opcodes.IMUL);
|
mv.visitInsn(Opcodes.IMUL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "/":
|
case "/":
|
||||||
left.codeGen(mv);
|
left.codeGen(mv, typeContext, localVars);
|
||||||
right.codeGen(mv);
|
right.codeGen(mv, typeContext, localVars);
|
||||||
mv.visitInsn(Opcodes.IDIV);
|
mv.visitInsn(Opcodes.IDIV);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -173,4 +181,4 @@ public class BinaryExpression extends AbstractType implements IExpression{
|
|||||||
|
|
||||||
mv.visitLabel(expressionEnd);
|
mv.visitLabel(expressionEnd);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,13 +1,17 @@
|
|||||||
package abstractSyntaxTree.Expression;
|
package abstractSyntaxTree.Expression;
|
||||||
|
|
||||||
import TypeCheck.TypeCheckResult;
|
import TypeCheck.TypeCheckResult;
|
||||||
import abstractSyntaxTree.Node;
|
import abstractSyntaxTree.Parameter.ParameterList;
|
||||||
import org.objectweb.asm.MethodVisitor;
|
import org.objectweb.asm.MethodVisitor;
|
||||||
|
|
||||||
public interface IExpression extends Node {
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
|
||||||
|
public interface IExpression {
|
||||||
// typeCheck method
|
// typeCheck method
|
||||||
TypeCheckResult typeCheck() throws Exception;
|
//TypeCheckResult typeCheck() throws Exception;
|
||||||
|
TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception;
|
||||||
|
|
||||||
// visit method for code generation
|
// visit method for code generation
|
||||||
void codeGen(MethodVisitor mv) throws Exception;
|
void codeGen(MethodVisitor mv, HashMap<String, HashMap<String, String>> typeContext, LinkedHashMap<String, String> localVars) throws Exception;
|
||||||
}
|
}
|
||||||
|
@ -2,31 +2,62 @@ package abstractSyntaxTree.Expression;
|
|||||||
|
|
||||||
import TypeCheck.TypeCheckResult;
|
import TypeCheck.TypeCheckResult;
|
||||||
import abstractSyntaxTree.Class.RefType;
|
import abstractSyntaxTree.Class.RefType;
|
||||||
|
import abstractSyntaxTree.Parameter.ParameterList;
|
||||||
import jdk.jshell.spi.ExecutionControl;
|
import jdk.jshell.spi.ExecutionControl;
|
||||||
import org.objectweb.asm.MethodVisitor;
|
import org.objectweb.asm.MethodVisitor;
|
||||||
|
import org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
|
||||||
public class InstVarExpression implements IExpression{
|
public class InstVarExpression implements IExpression{
|
||||||
|
|
||||||
//TODO: We have to decide upon more parameters and where they come from, for
|
//TODO: We have to decide upon more parameters and where they come from, for
|
||||||
// example here we need the index of the field, the class reference and the field name
|
// example here we need the index of the field, the class reference and the field name
|
||||||
private RefType classRef;
|
public RefType classRef;
|
||||||
private String fieldName;
|
public String fieldName;
|
||||||
|
|
||||||
/* public InstVarExpression(RefType classRef, String fieldName){
|
public InstVarExpression(RefType classRef, String fieldName){
|
||||||
this.classRef = classRef;
|
this.classRef = classRef;
|
||||||
this.fieldName = fieldName;
|
this.fieldName = fieldName;
|
||||||
}*/
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypeCheckResult typeCheck() throws Exception {
|
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception {
|
||||||
|
|
||||||
|
//todo
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodVisitor mv) throws Exception {
|
// typeContext: (ClassName, (FieldName, FieldType))
|
||||||
throw new ExecutionControl.NotImplementedException("CodeGen not implemented for InstVarExpression");
|
public void codeGen(MethodVisitor mv, HashMap<String, HashMap<String, String>> typeContext, LinkedHashMap<String, String> localVars) throws Exception {
|
||||||
|
// Load "this" onto the stack
|
||||||
|
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
||||||
|
|
||||||
//ALOAD the index of the var
|
//Get the field information
|
||||||
//GETFIELD the field
|
String fieldType = typeContext.get(classRef.name).get(fieldName);
|
||||||
//visitFieldInsn(Opcodes.GETFIELD, "class reference", "field name", type);
|
|
||||||
|
String fieldDescriptor;
|
||||||
|
|
||||||
|
switch (fieldType) {
|
||||||
|
case "int":
|
||||||
|
fieldDescriptor = "I";
|
||||||
|
break;
|
||||||
|
case "boolean":
|
||||||
|
fieldDescriptor = "Z";
|
||||||
|
break;
|
||||||
|
case "char":
|
||||||
|
fieldDescriptor = "C";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
//TODO: We need the fully qualified name of the class here in field type
|
||||||
|
fieldDescriptor = "L" + fieldType + ";";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load the variable onto the stack
|
||||||
|
mv.visitFieldInsn(Opcodes.GETFIELD, classRef.name, fieldName, fieldDescriptor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,64 @@
|
|||||||
|
package abstractSyntaxTree.Expression;
|
||||||
|
|
||||||
|
import TypeCheck.TypeCheckHelper;
|
||||||
|
import TypeCheck.TypeCheckResult;
|
||||||
|
import org.objectweb.asm.*;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
|
||||||
|
public class LocalVarIdentifier implements IExpression{
|
||||||
|
|
||||||
|
String identifier;
|
||||||
|
public LocalVarIdentifier(String identifier){
|
||||||
|
this.identifier = identifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getIdentifier() {
|
||||||
|
return identifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TypeCheckResult typeCheck() throws Exception {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void codeGen(MethodVisitor mv, HashMap<String, HashMap<String, String>> typeContext, LinkedHashMap<String, String> localVars) throws Exception {
|
||||||
|
// Check if the variable is in the list of local variables
|
||||||
|
String type = localVars.get(identifier);
|
||||||
|
if (type == null){
|
||||||
|
throw new Exception("Variable " + identifier + " not declared");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load the variable onto the stack
|
||||||
|
int index = -1;
|
||||||
|
int counter = 0;
|
||||||
|
for (String key : localVars.keySet()){
|
||||||
|
if (key.equals(identifier)){
|
||||||
|
index = counter;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index == -1){
|
||||||
|
throw new Exception("Variable " + identifier + " not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load the variable onto the stack
|
||||||
|
switch (type){
|
||||||
|
case "int":
|
||||||
|
mv.visitVarInsn(Opcodes.ILOAD, index);
|
||||||
|
break;
|
||||||
|
case "bool":
|
||||||
|
mv.visitVarInsn(Opcodes.ILOAD, index);
|
||||||
|
break;
|
||||||
|
case "void":
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
mv.visitVarInsn(Opcodes.ALOAD, index);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -7,11 +7,17 @@ import abstractSyntaxTree.Datatype.IDatatype;
|
|||||||
import org.objectweb.asm.MethodVisitor;
|
import org.objectweb.asm.MethodVisitor;
|
||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public class UnaryExpression extends AbstractType implements IExpression{
|
public class UnaryExpression extends AbstractType implements IExpression{
|
||||||
public String operator;
|
public String operator;
|
||||||
public IDatatype operand;
|
public IDatatype operand;
|
||||||
|
public UnaryExpression(String operator, IDatatype operand){
|
||||||
|
this.operator = operator;
|
||||||
|
this.operand = operand;
|
||||||
|
}
|
||||||
@Override
|
@Override
|
||||||
public TypeCheckResult typeCheck() throws Exception {
|
public TypeCheckResult typeCheck() throws Exception {
|
||||||
TypeCheckResult result = new TypeCheckResult();
|
TypeCheckResult result = new TypeCheckResult();
|
||||||
@ -29,12 +35,13 @@ public class UnaryExpression extends AbstractType implements IExpression{
|
|||||||
}
|
}
|
||||||
|
|
||||||
case "-":
|
case "-":
|
||||||
case "+":
|
case "":
|
||||||
|
case "+":{
|
||||||
if (Objects.equals(operandType, "int")){
|
if (Objects.equals(operandType, "int")){
|
||||||
result.type = "int";
|
result.type = "int";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setTypeCheckResult(result);
|
setTypeCheckResult(result);
|
||||||
@ -42,7 +49,7 @@ public class UnaryExpression extends AbstractType implements IExpression{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodVisitor mv) throws Exception {
|
public void codeGen(MethodVisitor mv, HashMap<String, HashMap<String, String>> typeContext, LinkedHashMap<String, String> localVars) throws Exception {
|
||||||
|
|
||||||
operand.codeGen(mv);
|
operand.codeGen(mv);
|
||||||
|
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
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");
|
|
||||||
}
|
|
||||||
}
|
|
@ -4,6 +4,7 @@ import TypeCheck.TypeCheckResult;
|
|||||||
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.Parameter.Parameter;
|
||||||
import abstractSyntaxTree.Parameter.ParameterList;
|
import abstractSyntaxTree.Parameter.ParameterList;
|
||||||
import org.objectweb.asm.ClassWriter;
|
import org.objectweb.asm.ClassWriter;
|
||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
@ -19,7 +20,7 @@ import java.util.jar.JarOutputStream;
|
|||||||
public class Program implements Node {
|
public class Program implements Node {
|
||||||
public List<RefType> classes;
|
public List<RefType> classes;
|
||||||
public HashMap<String, HashMap<String, String>> typeContext; // (class, (type, identifier))
|
public HashMap<String, HashMap<String, String>> typeContext; // (class, (type, identifier))
|
||||||
public HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext; // (class, (returntype, (identifier, parameterList)))
|
public HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext; // (class, (returntype, (identifier, parameter)))
|
||||||
|
|
||||||
public Program(List<RefType> classes){
|
public Program(List<RefType> classes){
|
||||||
this.classes = classes;
|
this.classes = classes;
|
||||||
@ -40,11 +41,11 @@ public class Program implements Node {
|
|||||||
typeContext.put(oneClass.name, classVars);
|
typeContext.put(oneClass.name, classVars);
|
||||||
|
|
||||||
// build method context
|
// build method context
|
||||||
HashMap<String, List<String>> methodIdentifierAndParameter = new HashMap<>();
|
HashMap<String, ParameterList> methodIdentifierAndParameter = new HashMap<>();
|
||||||
HashMap<String, HashMap<String, List<String >>> returnTypeAndMethod = new HashMap<>();
|
HashMap<String, HashMap<String, ParameterList>> returnTypeAndMethod = new HashMap<>();
|
||||||
for (MethodDecl methodDecl : oneClass.methodDecls){
|
for (MethodDecl methodDecl : oneClass.methodDecls){
|
||||||
|
|
||||||
methodIdentifierAndParameter.put(methodDecl.name, (List<String>) methodDecl.parameters);
|
methodIdentifierAndParameter.put(methodDecl.name, methodDecl.parameters);
|
||||||
returnTypeAndMethod.put(methodDecl.returnType, methodIdentifierAndParameter);
|
returnTypeAndMethod.put(methodDecl.returnType, methodIdentifierAndParameter);
|
||||||
}
|
}
|
||||||
methodContext.put(oneClass.name, returnTypeAndMethod);
|
methodContext.put(oneClass.name, returnTypeAndMethod);
|
||||||
@ -65,7 +66,7 @@ public class Program implements Node {
|
|||||||
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
|
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
|
||||||
cw.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, oneClass.name, null, "java/lang/Object", null);
|
cw.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, oneClass.name, null, "java/lang/Object", null);
|
||||||
|
|
||||||
oneClass.codeGen(cw, methodContext);
|
// oneClass.codeGen(cw);
|
||||||
|
|
||||||
cw.visitEnd();
|
cw.visitEnd();
|
||||||
byte[] bytecode = cw.toByteArray();
|
byte[] bytecode = cw.toByteArray();
|
||||||
@ -101,4 +102,14 @@ public class Program implements Node {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
Program program = (Program) o;
|
||||||
|
System.out.println(classes);
|
||||||
|
System.out.println(program.classes);
|
||||||
|
return (Objects.equals(classes, program.classes));
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,8 @@ package abstractSyntaxTree.Statement;
|
|||||||
|
|
||||||
import TypeCheck.TypeCheckResult;
|
import TypeCheck.TypeCheckResult;
|
||||||
import TypeCheck.AbstractType;
|
import TypeCheck.AbstractType;
|
||||||
|
import abstractSyntaxTree.Class.FieldDecl;
|
||||||
|
import abstractSyntaxTree.Parameter.ParameterList;
|
||||||
import org.objectweb.asm.*;
|
import org.objectweb.asm.*;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -11,8 +13,8 @@ public class BlockStatement extends AbstractType implements IStatement{
|
|||||||
|
|
||||||
//We will need a parameter which holds the symbol table
|
//We will need a parameter which holds the symbol table
|
||||||
HashMap<String, String > localVars;
|
HashMap<String, String > localVars;
|
||||||
String returnType;
|
public String returnType;
|
||||||
List<IStatement> statements;
|
public List<IStatement> statements;
|
||||||
// do we need expression, statementexpression
|
// do we need expression, statementexpression
|
||||||
|
|
||||||
public BlockStatement(List<IStatement> statements, String returnType){
|
public BlockStatement(List<IStatement> statements, String returnType){
|
||||||
@ -21,31 +23,24 @@ public class BlockStatement extends AbstractType implements IStatement{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypeCheckResult typeCheck() throws Exception {
|
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext,
|
||||||
return null;
|
HashMap<String, HashMap<String, String>> typeContext,
|
||||||
}
|
HashMap<String, String> localVars) throws Exception {
|
||||||
|
|
||||||
@Override
|
|
||||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, List<String>>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, List<String>>>> methodContext, HashMap<String, HashMap<String, String>> typeContext) throws Exception {
|
|
||||||
TypeCheckResult result = new TypeCheckResult();
|
TypeCheckResult result = new TypeCheckResult();
|
||||||
|
|
||||||
if(statements.size() == 0){
|
if(statements.size() == 0){
|
||||||
result.type = "void";
|
result.type = "void";
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeCheckResult blockType = new TypeCheckResult();
|
|
||||||
for (IStatement statement : statements) {
|
for (IStatement statement : statements) {
|
||||||
TypeCheckResult typeOfCurrentStatement = statement.typeCheck(methodContext, typeContext, localVars);
|
TypeCheckResult typeOfCurrentStatement = statement.typeCheck(methodContext, typeContext, localVars);
|
||||||
|
|
||||||
if (!typeOfCurrentStatement.equals(this.returnType) && !blockType.equals("void")) {
|
if (!typeOfCurrentStatement.type.equals(this.returnType)) {
|
||||||
throw new IllegalArgumentException("Block returns type that it should not return");
|
if(!typeOfCurrentStatement.type.equals("void"))
|
||||||
|
throw new Exception("TypeCheck Exception: Block returns the wrong type.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
result.type = this.returnType;
|
||||||
// todo check if the block returns the needed return type in every case
|
// todo check if the block returns the needed return type in every case
|
||||||
// todo ignore unreadchable statements?
|
// todo ignore unreadchable statements?
|
||||||
return result;
|
return result;
|
||||||
|
@ -2,26 +2,16 @@ package abstractSyntaxTree.Statement;
|
|||||||
|
|
||||||
import TypeCheck.TypeCheckResult;
|
import TypeCheck.TypeCheckResult;
|
||||||
import TypeCheck.AbstractType;
|
import TypeCheck.AbstractType;
|
||||||
|
import abstractSyntaxTree.Parameter.ParameterList;
|
||||||
import org.objectweb.asm.MethodVisitor;
|
import org.objectweb.asm.MethodVisitor;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class EmptyStatement extends AbstractType implements IStatement{
|
public class EmptyStatement extends AbstractType implements IStatement{
|
||||||
@Override
|
|
||||||
public TypeCheckResult typeCheck() throws Exception {
|
|
||||||
TypeCheckResult result = new TypeCheckResult();
|
|
||||||
result.type = "void";
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, List<String>>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception {
|
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception {
|
||||||
return typeCheck(methodContext, typeContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, List<String>>>> methodContext, HashMap<String, HashMap<String, String>> typeContext) throws Exception {
|
|
||||||
TypeCheckResult result = new TypeCheckResult();
|
TypeCheckResult result = new TypeCheckResult();
|
||||||
result.type = "void";
|
result.type = "void";
|
||||||
return result;
|
return result;
|
||||||
|
@ -2,22 +2,18 @@ package abstractSyntaxTree.Statement;
|
|||||||
|
|
||||||
import TypeCheck.TypeCheckResult;
|
import TypeCheck.TypeCheckResult;
|
||||||
import abstractSyntaxTree.Node;
|
import abstractSyntaxTree.Node;
|
||||||
|
import abstractSyntaxTree.Parameter.ParameterList;
|
||||||
import org.objectweb.asm.MethodVisitor;
|
import org.objectweb.asm.MethodVisitor;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public interface IStatement extends Node {
|
public interface IStatement extends Node {
|
||||||
|
|
||||||
|
TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception;
|
||||||
|
|
||||||
|
void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars) throws Exception;
|
||||||
|
|
||||||
TypeCheckResult typeCheck() throws Exception;
|
void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) throws Exception;
|
||||||
|
|
||||||
TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, List<String>>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception;
|
|
||||||
|
|
||||||
|
|
||||||
TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, List<String>>>> methodContext, HashMap<String, HashMap<String, String>> typeContext) throws Exception;
|
|
||||||
|
|
||||||
|
|
||||||
void codeGen(MethodVisitor mv, HashMap<String, String> localVars) throws Exception;
|
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package abstractSyntaxTree.Statement;
|
|||||||
import TypeCheck.TypeCheckResult;
|
import TypeCheck.TypeCheckResult;
|
||||||
import TypeCheck.AbstractType;
|
import TypeCheck.AbstractType;
|
||||||
import abstractSyntaxTree.Expression.IExpression;
|
import abstractSyntaxTree.Expression.IExpression;
|
||||||
|
import abstractSyntaxTree.Parameter.ParameterList;
|
||||||
import org.objectweb.asm.*;
|
import org.objectweb.asm.*;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -19,18 +20,19 @@ public class IfElseStatement extends AbstractType implements IStatement{
|
|||||||
this.elseStatement = elseStatement;
|
this.elseStatement = elseStatement;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypeCheckResult typeCheck() throws Exception {
|
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception {
|
||||||
TypeCheckResult result = new TypeCheckResult();
|
TypeCheckResult result = new TypeCheckResult();
|
||||||
|
|
||||||
TypeCheckResult conditionType = condition.typeCheck();
|
//TypeCheckResult conditionType = condition.typeCheck();
|
||||||
|
|
||||||
if (!conditionType.equals("bool")) {
|
// if (!conditionType.equals("bool")) {
|
||||||
throw new IllegalArgumentException("should be boolean");
|
// throw new IllegalArgumentException("should be boolean");
|
||||||
}
|
// }
|
||||||
|
|
||||||
TypeCheckResult ifStatementType = ifStatement.typeCheck();
|
TypeCheckResult ifStatementType = ifStatement.typeCheck(methodContext, typeContext, localVars);
|
||||||
TypeCheckResult elseStatementType = elseStatement.typeCheck();
|
TypeCheckResult elseStatementType = elseStatement.typeCheck(methodContext, typeContext, localVars);
|
||||||
|
|
||||||
if (!ifStatementType.equals(elseStatementType)) {
|
if (!ifStatementType.equals(elseStatementType)) {
|
||||||
throw new IllegalArgumentException("if and else have different types");
|
throw new IllegalArgumentException("if and else have different types");
|
||||||
@ -40,30 +42,22 @@ public class IfElseStatement extends AbstractType implements IStatement{
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, List<String>>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, List<String>>>> methodContext, HashMap<String, HashMap<String, String>> typeContext) throws Exception {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodVisitor mv, HashMap<String, String> localVars) throws Exception {
|
public void codeGen(MethodVisitor mv, HashMap<String, String> localVars) throws Exception {
|
||||||
|
|
||||||
|
HashMap<String, String> blockLocalVars = new HashMap<>(localVars);
|
||||||
|
|
||||||
Label conditionFalse = new Label();
|
Label conditionFalse = new Label();
|
||||||
Label statementEnd = new Label();
|
Label statementEnd = new Label();
|
||||||
|
|
||||||
condition.codeGen(mv);
|
condition.codeGen(mv);
|
||||||
|
|
||||||
mv.visitJumpInsn(Opcodes.IFEQ, conditionFalse); //Checks if the condition is false (0)
|
mv.visitJumpInsn(Opcodes.IFEQ, conditionFalse); //Checks if the condition is false (0)
|
||||||
ifStatement.codeGen(mv); //If the condition is true, execute the ifBlock
|
ifStatement.codeGen(mv, blockLocalVars); //If the condition is true, execute the ifBlock
|
||||||
mv.visitJumpInsn(Opcodes.GOTO, statementEnd); //Jump to the end of the if-else statement
|
mv.visitJumpInsn(Opcodes.GOTO, statementEnd); //Jump to the end of the if-else statement
|
||||||
|
|
||||||
mv.visitLabel(conditionFalse);
|
mv.visitLabel(conditionFalse);
|
||||||
elseStatement.codeGen(mv); //If the condition is false, execute the elseBlock
|
elseStatement.codeGen(mv, blockLocalVars); //If the condition is false, execute the elseBlock
|
||||||
|
|
||||||
mv.visitLabel(statementEnd); //End of the if-else statement
|
mv.visitLabel(statementEnd); //End of the if-else statement
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ package abstractSyntaxTree.Statement;
|
|||||||
import TypeCheck.TypeCheckResult;
|
import TypeCheck.TypeCheckResult;
|
||||||
import TypeCheck.AbstractType;
|
import TypeCheck.AbstractType;
|
||||||
import abstractSyntaxTree.Expression.IExpression;
|
import abstractSyntaxTree.Expression.IExpression;
|
||||||
|
import abstractSyntaxTree.Parameter.ParameterList;
|
||||||
import org.objectweb.asm.*;
|
import org.objectweb.asm.*;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -18,40 +19,33 @@ public class IfStatement extends AbstractType implements IStatement{
|
|||||||
this.condition = condition;
|
this.condition = condition;
|
||||||
this.ifStatement = ifStatement;
|
this.ifStatement = ifStatement;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypeCheckResult typeCheck() throws Exception {
|
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception {
|
||||||
TypeCheckResult result = new TypeCheckResult();
|
TypeCheckResult result = new TypeCheckResult();
|
||||||
|
|
||||||
TypeCheckResult conditionType = condition.typeCheck();
|
//TypeCheckResult conditionType = condition.typeCheck();
|
||||||
|
|
||||||
if (!conditionType.equals("bool")) {
|
// if (!conditionType.equals("bool")) {
|
||||||
throw new Exception("TypeCheck Exception: Condition of If-Statement should be bool.");
|
// throw new Exception("TypeCheck Exception: Condition of If-Statement should be bool.");
|
||||||
}
|
// }
|
||||||
|
|
||||||
TypeCheckResult ifStatementType = ifStatement.typeCheck();
|
TypeCheckResult ifStatementType = ifStatement.typeCheck(methodContext, typeContext, localVars);
|
||||||
result.type = ifStatementType.type;
|
result.type = ifStatementType.type;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, List<String>>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, List<String>>>> methodContext, HashMap<String, HashMap<String, String>> typeContext) throws Exception {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodVisitor mv, HashMap<String, String> localVars) throws Exception {
|
public void codeGen(MethodVisitor mv, HashMap<String, String> localVars) throws Exception {
|
||||||
|
|
||||||
|
HashMap<String, String> blockLocalVars = new HashMap<>(localVars);
|
||||||
|
|
||||||
Label conditionFalse = new Label();
|
Label conditionFalse = new Label();
|
||||||
|
|
||||||
condition.codeGen(mv);
|
condition.codeGen(mv);
|
||||||
|
|
||||||
mv.visitJumpInsn(Opcodes.IFEQ, conditionFalse); //Checks if the condition is false (0)
|
mv.visitJumpInsn(Opcodes.IFEQ, conditionFalse); //Checks if the condition is false (0)
|
||||||
ifStatement.codeGen(mv);
|
ifStatement.codeGen(mv, blockLocalVars);
|
||||||
|
|
||||||
mv.visitLabel(conditionFalse); // If the condition is false, the Statements in the ifBlock will not be executed
|
mv.visitLabel(conditionFalse); // If the condition is false, the Statements in the ifBlock will not be executed
|
||||||
}
|
}
|
||||||
|
55
src/main/java/abstractSyntaxTree/Statement/LocalVarDecl.java
Normal file
55
src/main/java/abstractSyntaxTree/Statement/LocalVarDecl.java
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
package abstractSyntaxTree.Statement;
|
||||||
|
|
||||||
|
import TypeCheck.TypeCheckHelper;
|
||||||
|
import TypeCheck.TypeCheckResult;
|
||||||
|
import abstractSyntaxTree.Parameter.ParameterList;
|
||||||
|
import org.objectweb.asm.MethodVisitor;
|
||||||
|
import org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class LocalVarDecl implements IStatement{
|
||||||
|
String type;
|
||||||
|
String identifier;
|
||||||
|
public LocalVarDecl(String type, String identifier) {
|
||||||
|
this.type = type;
|
||||||
|
this.identifier = identifier;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception {
|
||||||
|
TypeCheckHelper.typeExists(this.type, new ArrayList<>(methodContext.keySet()));
|
||||||
|
|
||||||
|
localVars.put(this.identifier, this.type);
|
||||||
|
|
||||||
|
TypeCheckResult result = new TypeCheckResult();
|
||||||
|
result.type = "void";
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void codeGen(MethodVisitor mv, HashMap<String, String> localVars) throws Exception {
|
||||||
|
localVars.put(identifier, type);
|
||||||
|
|
||||||
|
// Set a default value for the variable --> less problems
|
||||||
|
int index = localVars.size()-1;
|
||||||
|
|
||||||
|
switch (type){
|
||||||
|
case "int":
|
||||||
|
mv.visitInsn(Opcodes.ICONST_0);
|
||||||
|
mv.visitVarInsn(Opcodes.ISTORE, index);
|
||||||
|
break;
|
||||||
|
case "bool":
|
||||||
|
mv.visitInsn(Opcodes.ICONST_0);
|
||||||
|
mv.visitVarInsn(Opcodes.ISTORE, index);
|
||||||
|
break;
|
||||||
|
case "void":
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
mv.visitInsn(Opcodes.ACONST_NULL);
|
||||||
|
mv.visitVarInsn(Opcodes.ASTORE, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3,10 +3,10 @@ package abstractSyntaxTree.Statement;
|
|||||||
import TypeCheck.TypeCheckResult;
|
import TypeCheck.TypeCheckResult;
|
||||||
import TypeCheck.AbstractType;
|
import TypeCheck.AbstractType;
|
||||||
import abstractSyntaxTree.Expression.IExpression;
|
import abstractSyntaxTree.Expression.IExpression;
|
||||||
|
import abstractSyntaxTree.Parameter.ParameterList;
|
||||||
import org.objectweb.asm.*;
|
import org.objectweb.asm.*;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class ReturnStatement extends AbstractType implements IStatement{
|
public class ReturnStatement extends AbstractType implements IStatement{
|
||||||
IExpression expression;
|
IExpression expression;
|
||||||
@ -16,7 +16,7 @@ public class ReturnStatement extends AbstractType implements IStatement{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypeCheckResult typeCheck() throws Exception {
|
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception {
|
||||||
TypeCheckResult result = new TypeCheckResult();
|
TypeCheckResult result = new TypeCheckResult();
|
||||||
|
|
||||||
if (expression == null) {
|
if (expression == null) {
|
||||||
@ -29,17 +29,6 @@ public class ReturnStatement extends AbstractType implements IStatement{
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, List<String>>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, List<String>>>> methodContext, HashMap<String, HashMap<String, String>> typeContext) throws Exception {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//TODO: We do not differentiate between primitive types and reference types
|
//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
|
// 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
|
// At this point in time we can either return reference types or have an error message
|
||||||
@ -49,7 +38,8 @@ public class ReturnStatement extends AbstractType implements IStatement{
|
|||||||
if (expression != null) {
|
if (expression != null) {
|
||||||
expression.codeGen(mv);
|
expression.codeGen(mv);
|
||||||
//Get the Type of the expression
|
//Get the Type of the expression
|
||||||
String type = expression.typeCheck().type;
|
//TODO: Resolve how do we get the type of the expression
|
||||||
|
String type = expression.typeCheck(??).type;
|
||||||
|
|
||||||
if (type.equals("int") || type.equals("bool") || type.equals("char")) {
|
if (type.equals("int") || type.equals("bool") || type.equals("char")) {
|
||||||
mv.visitInsn(Opcodes.IRETURN);
|
mv.visitInsn(Opcodes.IRETURN);
|
||||||
|
@ -3,6 +3,7 @@ package abstractSyntaxTree.Statement;
|
|||||||
import TypeCheck.TypeCheckResult;
|
import TypeCheck.TypeCheckResult;
|
||||||
import TypeCheck.AbstractType;
|
import TypeCheck.AbstractType;
|
||||||
import abstractSyntaxTree.Expression.IExpression;
|
import abstractSyntaxTree.Expression.IExpression;
|
||||||
|
import abstractSyntaxTree.Parameter.ParameterList;
|
||||||
import org.objectweb.asm.*;
|
import org.objectweb.asm.*;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -18,33 +19,26 @@ public class WhileStatement extends AbstractType implements IStatement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypeCheckResult typeCheck() throws Exception {
|
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception {
|
||||||
TypeCheckResult result = new TypeCheckResult();
|
TypeCheckResult result = new TypeCheckResult();
|
||||||
|
|
||||||
TypeCheckResult conditionType = condition.typeCheck();
|
// TypeCheckResult conditionType = condition.typeCheck();
|
||||||
|
//
|
||||||
|
// if (!conditionType.equals("bool")) {
|
||||||
|
// throw new IllegalArgumentException("Expected boolean");
|
||||||
|
// }
|
||||||
|
|
||||||
if (!conditionType.equals("bool")) {
|
TypeCheckResult statementType = statement.typeCheck(methodContext, typeContext, localVars);
|
||||||
throw new IllegalArgumentException("Expected boolean");
|
|
||||||
}
|
|
||||||
|
|
||||||
TypeCheckResult statementType = statement.typeCheck();
|
|
||||||
|
|
||||||
result.type = statementType.type;
|
result.type = statementType.type;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, List<String>>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, List<String>>>> methodContext, HashMap<String, HashMap<String, String>> typeContext) throws Exception {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodVisitor mv, HashMap<String, String> localVars) throws Exception {
|
public void codeGen(MethodVisitor mv, HashMap<String, String> localVars) throws Exception {
|
||||||
|
|
||||||
|
HashMap<String, String> blockLocalVars = new HashMap<>(localVars);
|
||||||
|
|
||||||
Label conditionFalse = new Label();
|
Label conditionFalse = new Label();
|
||||||
Label LoopStart = new Label();
|
Label LoopStart = new Label();
|
||||||
|
|
||||||
@ -53,7 +47,8 @@ public class WhileStatement extends AbstractType implements IStatement {
|
|||||||
condition.codeGen(mv);
|
condition.codeGen(mv);
|
||||||
mv.visitJumpInsn(Opcodes.IFEQ, conditionFalse); // Checks if the condition is false (0)
|
mv.visitJumpInsn(Opcodes.IFEQ, conditionFalse); // Checks if the condition is false (0)
|
||||||
|
|
||||||
statement.codeGen(mv);
|
statement.codeGen(mv, blockLocalVars);
|
||||||
|
//statement.codeGen(mv);
|
||||||
//TODO: If the block ends with a return statement, we might have to pop it from the stack
|
//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
|
// So the next iteration starts with a clean stack
|
||||||
mv.visitJumpInsn(Opcodes.GOTO, LoopStart); // Jump to the start of the while loop
|
mv.visitJumpInsn(Opcodes.GOTO, LoopStart); // Jump to the start of the while loop
|
||||||
|
@ -5,63 +5,115 @@ import TypeCheck.TypeCheckHelper;
|
|||||||
import TypeCheck.TypeCheckResult;
|
import TypeCheck.TypeCheckResult;
|
||||||
import abstractSyntaxTree.Expression.IExpression;
|
import abstractSyntaxTree.Expression.IExpression;
|
||||||
import abstractSyntaxTree.Expression.InstVarExpression;
|
import abstractSyntaxTree.Expression.InstVarExpression;
|
||||||
import abstractSyntaxTree.Expression.VarRefExpression;
|
import abstractSyntaxTree.Expression.LocalVarIdentifier;
|
||||||
|
import abstractSyntaxTree.Parameter.ParameterList;
|
||||||
import abstractSyntaxTree.Statement.IStatement;
|
import abstractSyntaxTree.Statement.IStatement;
|
||||||
import org.objectweb.asm.*;
|
import org.objectweb.asm.*;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
public class AssignStatementExpression extends AbstractType implements IExpression, IStatement {
|
public class AssignStatementExpression extends AbstractType implements IExpression, IStatement {
|
||||||
public String operator;
|
public String operator;
|
||||||
public IExpression left;
|
public IExpression left;
|
||||||
public IExpression right;
|
public IExpression right;
|
||||||
|
private InstVarExpression instVar;
|
||||||
|
|
||||||
|
public AssignStatementExpression(String operator, IExpression leftExpression, IExpression rightExpression){
|
||||||
|
this.operator = operator;
|
||||||
|
this.left = leftExpression;
|
||||||
|
this.right = rightExpression;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypeCheckResult typeCheck() throws Exception {
|
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception {
|
||||||
TypeCheckHelper helper = new TypeCheckHelper();
|
TypeCheckHelper helper = new TypeCheckHelper();
|
||||||
TypeCheckResult result = new TypeCheckResult();
|
TypeCheckResult result = new TypeCheckResult();
|
||||||
|
|
||||||
TypeCheckResult leftType = left.typeCheck();
|
TypeCheckResult leftType;
|
||||||
TypeCheckResult rightType = right.typeCheck();
|
|
||||||
|
|
||||||
String upperbound = helper.upperBound(leftType.type, rightType.type);
|
if (left instanceof LocalVarIdentifier) {
|
||||||
if (Objects.equals(upperbound, leftType.type)) {
|
leftType = new TypeCheckResult();
|
||||||
result.type = leftType.type;
|
LocalVarIdentifier localVarIdentifier = (LocalVarIdentifier) left;
|
||||||
|
String identifier = localVarIdentifier.getIdentifier();
|
||||||
|
leftType.type = localVars.get(identifier);
|
||||||
|
}else{
|
||||||
|
//leftType = left.typeCheck();
|
||||||
}
|
}
|
||||||
setTypeCheckResult(result);
|
// TypeCheckResult rightType = right.typeCheck();
|
||||||
|
//
|
||||||
|
// String upperbound = helper.upperBound(leftType.type, rightType.type);
|
||||||
|
// if (Objects.equals(upperbound, leftType.type)) {
|
||||||
|
// result.type = leftType.type;
|
||||||
|
// }
|
||||||
|
// setTypeCheckResult(result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public TypeCheckResult typeCheck() throws Exception {
|
||||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, List<String>>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, List<String>>>> methodContext, HashMap<String, HashMap<String, String>> typeContext) throws Exception {
|
public void codeGen(MethodVisitor mv, HashMap<String, HashMap<String, String>> typeContext, LinkedHashMap<String, String> localVars) throws Exception {
|
||||||
return null;
|
//TODO: Do we need the value on the stack after assigning it?
|
||||||
}
|
//TODO: WE do not differentiate between InstanceVar and FieldVar
|
||||||
|
|
||||||
@Override
|
// Call the codeGen on the right expression which will push the value of the right expression onto the stack
|
||||||
public void codeGen(MethodVisitor mv, HashMap<String, String> localVars) throws Exception {
|
right.codeGen(mv, typeContext, localVars);
|
||||||
|
|
||||||
}
|
if (left instanceof LocalVarIdentifier) {
|
||||||
|
LocalVarIdentifier localVar = (LocalVarIdentifier) left;
|
||||||
|
String varName = localVar.getIdentifier();
|
||||||
|
|
||||||
@Override
|
//Get the index of the local variable
|
||||||
public void codeGen(MethodVisitor mv) throws Exception {
|
int index = -1;
|
||||||
left.codeGen(mv);
|
int counter = 0;
|
||||||
right.codeGen(mv);
|
for (String key : localVars.keySet()){
|
||||||
|
if (key.equals(varName)){
|
||||||
|
index = counter;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index == -1){
|
||||||
|
throw new Exception("Variable " + varName + " not found");
|
||||||
|
}
|
||||||
|
|
||||||
if (left instanceof VarRefExpression varRef) {
|
String type = localVars.get(localVar.getIdentifier());
|
||||||
//TODO: Implement the handling of a variable reference --> I need a list of local variables
|
switch (type) {
|
||||||
// for that to determine if the variable is a local or field variable
|
case "int":
|
||||||
} else if (left instanceof InstVarExpression instVar) {
|
case "bool":
|
||||||
mv.visitInsn(Opcodes.DUP_X1);
|
mv.visitVarInsn(Opcodes.ISTORE, index);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
mv.visitVarInsn(Opcodes.ASTORE, index);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (left instanceof InstVarExpression){
|
||||||
|
instVar = (InstVarExpression) left;
|
||||||
|
|
||||||
// We now again need the owner (class reference), name (of the Field in the owner) and type of the field
|
// Load "this" onto the stack
|
||||||
//mv.visitFieldInsn(Opcodes.PUTFIELD, instVar.className, instVar.varName, instVar.type);
|
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
||||||
|
|
||||||
|
String fieldType = typeContext.get(instVar.classRef.name).get(instVar.fieldName);
|
||||||
|
|
||||||
|
String fieldDescriptor;
|
||||||
|
switch (fieldType) {
|
||||||
|
case "int":
|
||||||
|
fieldDescriptor = "I";
|
||||||
|
break;
|
||||||
|
case "boolean":
|
||||||
|
fieldDescriptor = "Z";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
//TODO: We need the fully qualified name of the class here in field type
|
||||||
|
fieldDescriptor = "L" + fieldType + ";";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
mv.visitFieldInsn(Opcodes.PUTFIELD, instVar.classRef.name, instVar.fieldName, fieldDescriptor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,12 +5,14 @@ import TypeCheck.TypeCheckResult;
|
|||||||
import abstractSyntaxTree.Class.MethodDecl;
|
import abstractSyntaxTree.Class.MethodDecl;
|
||||||
import abstractSyntaxTree.Class.RefType;
|
import abstractSyntaxTree.Class.RefType;
|
||||||
import abstractSyntaxTree.Expression.IExpression;
|
import abstractSyntaxTree.Expression.IExpression;
|
||||||
|
import abstractSyntaxTree.Parameter.ParameterList;
|
||||||
import abstractSyntaxTree.Statement.IStatement;
|
import abstractSyntaxTree.Statement.IStatement;
|
||||||
import org.objectweb.asm.ClassWriter;
|
import org.objectweb.asm.ClassWriter;
|
||||||
import org.objectweb.asm.MethodVisitor;
|
import org.objectweb.asm.MethodVisitor;
|
||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class MethodCallStatementExpression extends AbstractType implements IExpression, IStatement {
|
public class MethodCallStatementExpression extends AbstractType implements IExpression, IStatement {
|
||||||
@ -24,7 +26,6 @@ public class MethodCallStatementExpression extends AbstractType implements IExpr
|
|||||||
this.arguments = arguments;
|
this.arguments = arguments;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public TypeCheckResult typeCheck() throws Exception {
|
public TypeCheckResult typeCheck() throws Exception {
|
||||||
TypeCheckResult result = new TypeCheckResult();
|
TypeCheckResult result = new TypeCheckResult();
|
||||||
|
|
||||||
@ -44,37 +45,50 @@ public class MethodCallStatementExpression extends AbstractType implements IExpr
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, List<String>>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception {
|
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, List<String>>>> methodContext, HashMap<String, HashMap<String, String>> typeContext) throws Exception {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void codeGen(MethodVisitor mv, HashMap<String, String> localVars) throws Exception {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//Errors occur due to the change in parameter in the RefType class
|
//Errors occur due to the change in parameter in the RefType class
|
||||||
|
// I need the methodContext here to get the method descriptor
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodVisitor mv) throws Exception {
|
public void codeGen(MethodVisitor mv, HashMap<String, HashMap<String, String>> typeContext, LinkedHashMap<String, String> localVars) throws Exception {
|
||||||
//Generate Bytecode for the receiver
|
//Generate Bytecode for the receiver
|
||||||
if(classThatHasTheMethodIfNotThis != null){
|
if(classThatHasTheMethodIfNotThis != null){
|
||||||
classThatHasTheMethodIfNotThis.codeGen(new ClassWriter(ClassWriter.COMPUTE_FRAMES));
|
//TODO: classThatHasTheMethodIfNotThis must be an object --> instance of the class not the class itself
|
||||||
|
//classThatHasTheMethodIfNotThis.codeGen();
|
||||||
|
|
||||||
|
String descriptor;
|
||||||
|
List<MethodDecl> methodDecls = thisClass.methodDecls;
|
||||||
|
for (MethodDecl methodDecl : methodDecls) {
|
||||||
|
if (methodDecl.name.equals(methodName)) {
|
||||||
|
//Get the method descriptor
|
||||||
|
descriptor = methodDecl.getMethodDescriptor(methodContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, classThatHasTheMethodIfNotThis.name, methodName, descriptor, false);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
// Load this onto the stack
|
||||||
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (IExpression argument : arguments) {
|
for (IExpression argument : arguments) {
|
||||||
argument.codeGen(mv);
|
argument.codeGen(mv, typeContext, localVars);
|
||||||
}
|
}
|
||||||
|
|
||||||
//We need the class reference and the return type of the method
|
// Get the method descriptor
|
||||||
//mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, thisClass.name, methodName, return type);
|
String descriptor;
|
||||||
|
List<MethodDecl> methodDecls = thisClass.methodDecls;
|
||||||
|
for (MethodDecl methodDecl : methodDecls) {
|
||||||
|
if (methodDecl.name.equals(methodName)) {
|
||||||
|
//Get the method descriptor
|
||||||
|
descriptor = methodDecl.getMethodDescriptor(methodContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, thisClass.name, methodName, descriptor, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package abstractSyntaxTree.StatementExpression;
|
|||||||
import TypeCheck.AbstractType;
|
import TypeCheck.AbstractType;
|
||||||
import TypeCheck.TypeCheckResult;
|
import TypeCheck.TypeCheckResult;
|
||||||
import abstractSyntaxTree.Expression.IExpression;
|
import abstractSyntaxTree.Expression.IExpression;
|
||||||
|
import abstractSyntaxTree.Parameter.ParameterList;
|
||||||
import abstractSyntaxTree.Statement.IStatement;
|
import abstractSyntaxTree.Statement.IStatement;
|
||||||
import org.objectweb.asm.MethodVisitor;
|
import org.objectweb.asm.MethodVisitor;
|
||||||
|
|
||||||
@ -10,18 +11,10 @@ import java.util.HashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class NewStatementExpression extends AbstractType implements IExpression, IStatement {
|
public class NewStatementExpression extends AbstractType implements IExpression, IStatement {
|
||||||
@Override
|
|
||||||
public TypeCheckResult typeCheck() throws Exception {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, List<String>>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception {
|
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws Exception {
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, List<String>>>> methodContext, HashMap<String, HashMap<String, String>> typeContext) throws Exception {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,7 +174,7 @@ public class ASTGenerator extends DecafBaseVisitor<Node> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Node visitAssign(DecafParser.AssignContext ctx) {
|
public Node visitAssign(DecafParser.AssignContext ctx) {
|
||||||
return new AssignStatementExpression();
|
return new AssignStatementExpression("", null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
44
src/test/java/AST/AstComparer.java
Normal file
44
src/test/java/AST/AstComparer.java
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
package AST;
|
||||||
|
|
||||||
|
import ASTs.emptyClassAST;
|
||||||
|
import abstractSyntaxTree.Program;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
import abstractSyntaxTree.Statement.BlockStatement;
|
||||||
|
import gen.DecafLexer;
|
||||||
|
import gen.DecafParser;
|
||||||
|
import org.antlr.v4.runtime.tree.ParseTree;
|
||||||
|
import org.junit.Test;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import org.antlr.v4.runtime.*;
|
||||||
|
import abstractSyntaxTree.ASTGenerator;
|
||||||
|
|
||||||
|
public class AstComparer {
|
||||||
|
|
||||||
|
private static String BASE_DIR;
|
||||||
|
public AstComparer(String base_directory){
|
||||||
|
BASE_DIR = base_directory + "/";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void astComparison(String sourceFilePath, Program expectedAST) throws Exception {
|
||||||
|
// Read the source file
|
||||||
|
String content = new String(Files.readAllBytes(Paths.get(BASE_DIR + sourceFilePath)));
|
||||||
|
CharStream codeCharStream = CharStreams.fromString(content);
|
||||||
|
|
||||||
|
// Setup Lexer and Parser
|
||||||
|
DecafLexer lexer = new DecafLexer(codeCharStream);
|
||||||
|
CommonTokenStream tokens = new CommonTokenStream(lexer);
|
||||||
|
DecafParser parser = new DecafParser(tokens);
|
||||||
|
ParseTree tree = parser.program();
|
||||||
|
|
||||||
|
// Generate AST
|
||||||
|
ASTGenerator generator = new ASTGenerator();
|
||||||
|
Program generatedAST = (Program) generator.visit(tree);
|
||||||
|
|
||||||
|
// Assert that both ASTs are equal
|
||||||
|
assertEquals("The generated AST does not match the expected AST", expectedAST, generatedAST);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
28
src/test/java/AST/testAll.java
Normal file
28
src/test/java/AST/testAll.java
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package AST;
|
||||||
|
import ASTs.emptyClassAST;
|
||||||
|
import abstractSyntaxTree.Program;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
public class testAll {
|
||||||
|
|
||||||
|
AstComparer astComparer;
|
||||||
|
public testAll()
|
||||||
|
{
|
||||||
|
this.astComparer = new AstComparer("src/test/resources");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void TestAstGeneration()
|
||||||
|
{
|
||||||
|
System.out.println("Current working directory: " + new File(".").getAbsolutePath());
|
||||||
|
Program testEmptyClassAST = emptyClassAST.getEmptyProgramm();
|
||||||
|
|
||||||
|
try {
|
||||||
|
astComparer.astComparison("basicClasses/emptyClass.java", testEmptyClassAST);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
24
src/test/java/ASTs/emptyClassAST.java
Normal file
24
src/test/java/ASTs/emptyClassAST.java
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package ASTs;
|
||||||
|
|
||||||
|
import abstractSyntaxTree.*;
|
||||||
|
import abstractSyntaxTree.Class.FieldDecl;
|
||||||
|
import abstractSyntaxTree.Class.MethodDecl;
|
||||||
|
import abstractSyntaxTree.Class.RefType;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class emptyClassAST {
|
||||||
|
|
||||||
|
|
||||||
|
public static Program getEmptyProgramm() {
|
||||||
|
List<FieldDecl> emptyFieldDeclList = new ArrayList<>();
|
||||||
|
List<MethodDecl> emptyMethodDeclList = new ArrayList<>();
|
||||||
|
RefType emptyClass = new RefType("emptyClass", emptyFieldDeclList, emptyMethodDeclList, false);
|
||||||
|
List<RefType> classes = new ArrayList<>();
|
||||||
|
classes.add(emptyClass);
|
||||||
|
|
||||||
|
return (new Program(classes));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
34
src/test/java/ASTs/emptyClassWithConstructorAST.java
Normal file
34
src/test/java/ASTs/emptyClassWithConstructorAST.java
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
package ASTs;
|
||||||
|
|
||||||
|
import abstractSyntaxTree.Class.FieldDecl;
|
||||||
|
import abstractSyntaxTree.Class.MethodDecl;
|
||||||
|
import abstractSyntaxTree.Class.RefType;
|
||||||
|
import abstractSyntaxTree.Parameter.Parameter;
|
||||||
|
import abstractSyntaxTree.Parameter.ParameterList;
|
||||||
|
import abstractSyntaxTree.Program;
|
||||||
|
import abstractSyntaxTree.Statement.BlockStatement;
|
||||||
|
import abstractSyntaxTree.Statement.IStatement;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class emptyClassWithConstructorAST extends Program {
|
||||||
|
public emptyClassWithConstructorAST()
|
||||||
|
{
|
||||||
|
super(staticClasses());
|
||||||
|
}
|
||||||
|
private static List<RefType> staticClasses() {
|
||||||
|
List<FieldDecl> fieldDeclList = new ArrayList<>();
|
||||||
|
|
||||||
|
ParameterList emptyParameterList = new ParameterList(new ArrayList<>());
|
||||||
|
List<IStatement> emptyIStatementList = new ArrayList<>();
|
||||||
|
BlockStatement emptyBlockStatement = new BlockStatement(emptyIStatementList, "void");
|
||||||
|
MethodDecl constructor = new MethodDecl("emptyClassWithConstructor", "null", "emptyClassWithConstructor", emptyParameterList, emptyBlockStatement);
|
||||||
|
List<MethodDecl> methodDeclList = new ArrayList<>();
|
||||||
|
methodDeclList.add(constructor);
|
||||||
|
RefType emptyClass = new RefType("emptyClass", fieldDeclList, methodDeclList, false);
|
||||||
|
List<RefType> classes = new ArrayList<>();
|
||||||
|
classes.add(emptyClass);
|
||||||
|
return classes;
|
||||||
|
}
|
||||||
|
}
|
80
src/test/java/ASTs/fourClassesAST.java
Normal file
80
src/test/java/ASTs/fourClassesAST.java
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
package ASTs;
|
||||||
|
|
||||||
|
import abstractSyntaxTree.Class.FieldDecl;
|
||||||
|
import abstractSyntaxTree.Class.MethodDecl;
|
||||||
|
import abstractSyntaxTree.Class.RefType;
|
||||||
|
import abstractSyntaxTree.Expression.IExpression;
|
||||||
|
import abstractSyntaxTree.Expression.InstVarExpression;
|
||||||
|
import abstractSyntaxTree.Parameter.Parameter;
|
||||||
|
import abstractSyntaxTree.Parameter.ParameterList;
|
||||||
|
import abstractSyntaxTree.Program;
|
||||||
|
import abstractSyntaxTree.Statement.BlockStatement;
|
||||||
|
import abstractSyntaxTree.Statement.IStatement;
|
||||||
|
import abstractSyntaxTree.Statement.ReturnStatement;
|
||||||
|
import abstractSyntaxTree.StatementExpression.AssignStatementExpression;
|
||||||
|
import abstractSyntaxTree.StatementExpression.NewStatementExpression;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/*
|
||||||
|
public class fourClassesAST extends Program {
|
||||||
|
|
||||||
|
public fourClassesAST()
|
||||||
|
{
|
||||||
|
super(staticClasses());
|
||||||
|
}
|
||||||
|
private static List<RefType> staticClasses() {
|
||||||
|
|
||||||
|
/////////// Classes ///////////
|
||||||
|
|
||||||
|
///////// Class: FourClasses /////////
|
||||||
|
|
||||||
|
/////// Fields ///////
|
||||||
|
List<FieldDecl> fieldDeclList = new ArrayList<>();
|
||||||
|
|
||||||
|
ParameterList emptyParameterList = new ParameterList(new ArrayList<>());
|
||||||
|
|
||||||
|
/////// Methods ///////
|
||||||
|
|
||||||
|
// Main //
|
||||||
|
|
||||||
|
List<IStatement> emptyIStatementList = new ArrayList<>();
|
||||||
|
BlockStatement emptyBlockStatement = new BlockStatement(emptyIStatementList, "void");
|
||||||
|
MethodDecl constructor = new MethodDecl("emptyClassWithConstructor", "null", "emptyClassWithConstructor", emptyParameterList, emptyBlockStatement);
|
||||||
|
|
||||||
|
//IStatement
|
||||||
|
List<IStatement> fourClassesMainBlockIstatements = new ArrayList<>();
|
||||||
|
|
||||||
|
IExpression atntiLeft = new InstVarExpression("Test", "t");
|
||||||
|
IExpression atntiRight = new NewStatementExpression();
|
||||||
|
AssignStatementExpression atnti = new AssignStatementExpression(atntiLeft, "=", );
|
||||||
|
|
||||||
|
|
||||||
|
ReturnStatement fcmbiReturn = new ReturnStatement();
|
||||||
|
|
||||||
|
fourClassesMainBlockIstatements.add(atnti);
|
||||||
|
//BlockStatement
|
||||||
|
BlockStatement fourClassesMainBlock = new BlockStatement(fourClassesMainBlockIstatements, "int");
|
||||||
|
|
||||||
|
//Parameter
|
||||||
|
Parameter intI = new Parameter("int", "i");
|
||||||
|
List<Parameter> fourClassesMainParameterList = new ArrayList<>();
|
||||||
|
|
||||||
|
ParameterList fourClassesMainParameters = new ParameterList(fourClassesMainParameterList);
|
||||||
|
|
||||||
|
MethodDecl fourClassesMain = new MethodDecl("fourClasses", "int", "main", fourClassesMainParameters, fourClassesMainBlock);
|
||||||
|
List<MethodDecl> MethodDeclList = new ArrayList<>();
|
||||||
|
|
||||||
|
RefType emptyClass = new RefType("emptyClass", fieldDeclList, MethodDeclList, false);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
List<RefType> classes = new ArrayList<>();
|
||||||
|
classes.add(emptyClass);
|
||||||
|
return classes;
|
||||||
|
}
|
||||||
|
}*/
|
@ -5,7 +5,6 @@ import org.antlr.v4.runtime.CharStream;
|
|||||||
import org.antlr.v4.runtime.CharStreams;
|
import org.antlr.v4.runtime.CharStreams;
|
||||||
import org.antlr.v4.runtime.CommonTokenStream;
|
import org.antlr.v4.runtime.CommonTokenStream;
|
||||||
import org.antlr.v4.runtime.Token;
|
import org.antlr.v4.runtime.Token;
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
@ -40,8 +39,6 @@ public class JavaLexerTest {
|
|||||||
}*/
|
}*/
|
||||||
|
|
||||||
// Compare tokens
|
// Compare tokens
|
||||||
//assertEquals("Number of tokens does not match expected", expectedTokens.size(), tokenList.size());
|
|
||||||
|
|
||||||
for (int i = 0; i < tokenList.size(); i++) {
|
for (int i = 0; i < tokenList.size(); i++) {
|
||||||
Token token = tokenList.get(i);
|
Token token = tokenList.get(i);
|
||||||
String tokenData = String.format("%s: \"%s\"", lexer.getVocabulary().getSymbolicName(token.getType()), token.getText());
|
String tokenData = String.format("%s: \"%s\"", lexer.getVocabulary().getSymbolicName(token.getType()), token.getText());
|
||||||
|
34
src/test/java/Tokens/TestAll.java
Normal file
34
src/test/java/Tokens/TestAll.java
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
package Tokens;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class TestAll {
|
||||||
|
JavaLexerTest testLexer;
|
||||||
|
public TestAll(){
|
||||||
|
testLexer = new JavaLexerTest("src/test/resources");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void main(String[] args){
|
||||||
|
TestAll tester = new TestAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEmptyClass() throws Exception {
|
||||||
|
testLexer.testTokens("basicClasses/emptyClass.java", "basicClasses/emptyClass.tokens");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEmptyClassWithConstructor() throws Exception {
|
||||||
|
testLexer.testTokens("basicClasses/EmptyClassWithConstructor.java", "basicClasses/EmptyClassWithConstructor.tokens");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFourClasses() throws Exception {
|
||||||
|
testLexer.testTokens("basicClasses/FourClasses.java", "basicClasses/FourClasses.tokens");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPublicEmptyClass() throws Exception {
|
||||||
|
testLexer.testTokens("basicClasses/PublicEmptyClass.java", "basicClasses/PublicEmptyClass.tokens");
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user