Merge remote-tracking branch 'origin/master'

# Conflicts:
#	src/main/java/abstractSyntaxTree/StatementExpression/NewStatementExpression.java
This commit is contained in:
Jochen Seyfried 2024-05-31 12:09:47 +02:00
commit 5592a6cfe1
10 changed files with 161 additions and 43 deletions

View File

@ -27,9 +27,21 @@ public class Compiler {
public static void main(String[] args) throws Exception{ public static void main(String[] args) throws Exception{
Path filePath = Paths.get("NichtHaskell/src/main/java/Input.java"); Path filePath = Paths.get("src/main/java/Input.java");
// todo remove this debug info
Path absolutePath = filePath.toAbsolutePath();
System.out.println("Full path: " + absolutePath);
String content;
try {
content = Files.readString(filePath);
}catch (java.nio.file.NoSuchFileException e){
System.out.println("File not found");
return;
}
String content = Files.readString(filePath);
System.out.println("--- print content ---"); System.out.println("--- print content ---");
System.out.println(content); System.out.println(content);
@ -91,16 +103,7 @@ 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();

View File

@ -6,6 +6,12 @@ class Example {
} }
class Example2 { class Example2 {
boolean instVarBool; boolean instVarBool;
int m(int n){return 1;} int m(int n){
boolean localBool;
localBool = true;
if(localBool){
return n;
}
return -1;
}
} }

View File

@ -0,0 +1,27 @@
package abstractSyntaxTree.Expression;
import TypeCheck.AbstractType;
import TypeCheck.TypeCheckResult;
import abstractSyntaxTree.Parameter.ParameterList;
import org.objectweb.asm.MethodVisitor;
import java.util.HashMap;
import java.util.LinkedHashMap;
public class IntConstantExpression extends AbstractType implements IExpression{
public int value;
public IntConstantExpression(int value) {
this.value = value;
}
@Override
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, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) throws Exception {
}
}

View File

@ -24,7 +24,13 @@ public class LocalVarIdentifier 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 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; TypeCheckResult result = new TypeCheckResult();
if (localVars.containsKey(identifier)) {
result.type = localVars.get(identifier);
} else {
throw new Exception("TypeCheck Exception: local var does not exist");
}
return result;
} }
@Override @Override

View File

@ -34,13 +34,40 @@ public class BlockStatement extends AbstractType implements IStatement {
} }
for (IStatement statement : statements) { for (IStatement statement : statements) {
// todo remove later if there are no null statement any more
if (statement != null) {
TypeCheckResult typeOfCurrentStatement = statement.typeCheck(methodContext, typeContext, localVars); TypeCheckResult typeOfCurrentStatement = statement.typeCheck(methodContext, typeContext, localVars);
if (typeOfCurrentStatement.type.contains(",")) {
// else if has 2 returns, all code paths must retrun a value.
String[] substrings = typeOfCurrentStatement.type.split(",");
String firstType = substrings[0];
String secondType = substrings[1];
if (!firstType.equals(this.returnType) || !firstType.equals(this.returnType)) {
if (!firstType.equals("void")) {
throw new Exception("TypeCeck Exception: if paths return wrong type");
}
if (!secondType.equals("void")) {
throw new Exception("TypeCeck Exception: else paths return wrong type");
}
boolean firstIsVoid = firstType.equals("void");
if (!firstIsVoid) {
typeOfCurrentStatement.type = firstType;
} else {
typeOfCurrentStatement.type = secondType;
}
}
}
if (!typeOfCurrentStatement.type.equals(this.returnType)) { if (!typeOfCurrentStatement.type.equals(this.returnType)) {
if (!typeOfCurrentStatement.type.equals("void")) if (!typeOfCurrentStatement.type.equals("void"))
throw new Exception("TypeCheck Exception: Block returns the wrong type."); throw new Exception("TypeCheck Exception: Block returns the wrong type.");
} }
} }
}
result.type = this.returnType; 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 unreachable statements? // todo ignore unreachable statements?

View File

@ -9,6 +9,7 @@ import org.objectweb.asm.*;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Objects;
public class IfElseStatement extends AbstractType implements IStatement{ public class IfElseStatement extends AbstractType implements IStatement{
IExpression condition; IExpression condition;
@ -26,11 +27,11 @@ public class IfElseStatement extends AbstractType implements IStatement{
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> 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 {
TypeCheckResult result = new TypeCheckResult(); TypeCheckResult result = new TypeCheckResult();
//TypeCheckResult conditionType = condition.typeCheck(); TypeCheckResult conditionType = condition.typeCheck(methodContext, typeContext, localVars);
// if (!conditionType.equals("bool")) { if (!conditionType.equals("bool")) {
// throw new IllegalArgumentException("should be boolean"); throw new IllegalArgumentException("should be boolean");
// } }
TypeCheckResult ifStatementType = ifStatement.typeCheck(methodContext, typeContext, localVars); TypeCheckResult ifStatementType = ifStatement.typeCheck(methodContext, typeContext, localVars);
TypeCheckResult elseStatementType = elseStatement.typeCheck(methodContext, typeContext, localVars); TypeCheckResult elseStatementType = elseStatement.typeCheck(methodContext, typeContext, localVars);
@ -38,11 +39,17 @@ public class IfElseStatement extends AbstractType implements IStatement{
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");
} }
if(ifStatementType.type != "void" && elseStatementType.type != "void"){
result.type = elseStatementType.type; if(Objects.equals(ifStatementType.type, elseStatementType.type)){
throw new Exception("TypeCeck Exception: If and else return different not-void types");
}
}
result.type = ifStatementType.type + "," + elseStatementType.type;
return result; return result;
} }
@Override @Override
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) throws Exception { public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext) throws Exception {

View File

@ -25,11 +25,11 @@ public class IfStatement extends AbstractType implements IStatement{
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> 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 {
TypeCheckResult result = new TypeCheckResult(); TypeCheckResult result = new TypeCheckResult();
//TypeCheckResult conditionType = condition.typeCheck(); TypeCheckResult conditionType = condition.typeCheck(methodContext, typeContext, localVars);
// 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(methodContext, typeContext, localVars); TypeCheckResult ifStatementType = ifStatement.typeCheck(methodContext, typeContext, localVars);
result.type = ifStatementType.type; result.type = ifStatementType.type;

View File

@ -23,15 +23,18 @@ public class WhileStatement extends AbstractType implements IStatement {
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> 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 {
TypeCheckResult result = new TypeCheckResult(); TypeCheckResult result = new TypeCheckResult();
// TypeCheckResult conditionType = condition.typeCheck(); // check condition
// TypeCheckResult conditionType = condition.typeCheck(methodContext, typeContext, localVars);
// if (!conditionType.equals("bool")) { if (!conditionType.equals("bool")) {
// throw new IllegalArgumentException("Expected boolean"); throw new IllegalArgumentException("Expected boolean");
// } }
// check code block
TypeCheckResult statementType = statement.typeCheck(methodContext, typeContext, localVars); TypeCheckResult statementType = statement.typeCheck(methodContext, typeContext, localVars);
// set result
result.type = statementType.type; result.type = statementType.type;
setTypeCheckResult(result);
return result; return result;
} }

View File

@ -3,8 +3,7 @@ package astGenerator;
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.*;
import abstractSyntaxTree.Expression.IExpression;
import abstractSyntaxTree.Node; import abstractSyntaxTree.Node;
import abstractSyntaxTree.Parameter.Parameter; import abstractSyntaxTree.Parameter.Parameter;
import abstractSyntaxTree.Parameter.ParameterList; import abstractSyntaxTree.Parameter.ParameterList;
@ -132,12 +131,12 @@ public class ASTGenerator extends DecafBaseVisitor<Node> {
@Override @Override
public Node visitIfElseStmt(DecafParser.IfElseStmtContext ctx) { public Node visitIfElseStmt(DecafParser.IfElseStmtContext ctx) {
if (ctx.elseStmt() != null) { if (ctx.elseStmt() != null) {
return visitIfStmt(ctx.ifStmt());
} else {
Node expression = visitExpression(ctx.ifStmt().expression()); Node expression = visitExpression(ctx.ifStmt().expression());
Node ifStatement = visitStatement(ctx.ifStmt().statement()); Node ifStatement = visitStatement(ctx.ifStmt().statement());
Node elseStatement = visitStatement(ctx.elseStmt().statement()); Node elseStatement = visitStatement(ctx.elseStmt().statement());
return new IfElseStatement((IExpression) expression, (IStatement) ifStatement, (IStatement) elseStatement); return new IfElseStatement((IExpression) expression, (IStatement) ifStatement, (IStatement) elseStatement);
} else {
return visitIfStmt(ctx.ifStmt());
} }
} }
@ -174,9 +173,12 @@ public class ASTGenerator extends DecafBaseVisitor<Node> {
@Override @Override
public Node visitAssign(DecafParser.AssignContext ctx) { public Node visitAssign(DecafParser.AssignContext ctx) {
return new AssignStatementExpression("", null, null); Node right = visitExpression(ctx.expression());
Node left = visitAssignableExpr(ctx.assignableExpr());
return new AssignStatementExpression(ctx.Assign().getText(),(IExpression) left, (IExpression) right);
} }
@Override @Override
public Node visitMethodCall(DecafParser.MethodCallContext ctx) { public Node visitMethodCall(DecafParser.MethodCallContext ctx) {
return super.visitMethodCall(ctx); return super.visitMethodCall(ctx);
@ -190,7 +192,7 @@ public class ASTGenerator extends DecafBaseVisitor<Node> {
@Override @Override
public Node visitExpression(DecafParser.ExpressionContext ctx) { public Node visitExpression(DecafParser.ExpressionContext ctx) {
if (ctx.subExpression() != null) { if (ctx.subExpression() != null) {
return visitSubExpression(ctx.subExpression());
} else if (ctx.binaryExpr() != null) { } else if (ctx.binaryExpr() != null) {
return visitBinaryExpr(ctx.binaryExpr()); return visitBinaryExpr(ctx.binaryExpr());
} }
@ -238,7 +240,16 @@ public class ASTGenerator extends DecafBaseVisitor<Node> {
//todo //todo
@Override @Override
public Node visitDotSubExpr(DecafParser.DotSubExprContext ctx) { public Node visitDotSubExpr(DecafParser.DotSubExprContext ctx) {
return super.visitDotSubExpr(ctx); if (ctx.IntValue() != null) {
int value = Integer.parseInt(ctx.IntValue().getText());
return new IntConstantExpression(value);
} else if(ctx.Identifier() != null) {
String identifier = ctx.Identifier().getText();
return new LocalVarIdentifier(identifier);
} else if(ctx.instVar() != null) {
return visitInstVar(ctx.instVar());
}
return null;
} }
@Override @Override
@ -256,9 +267,37 @@ public class ASTGenerator extends DecafBaseVisitor<Node> {
@Override @Override
public Node visitSubExpression(DecafParser.SubExpressionContext ctx) { public Node visitSubExpression(DecafParser.SubExpressionContext ctx) {
if (ctx.subExpression() != null) { if (ctx.assignableExpr() != null) {
visitSubExpression(ctx.subExpression()); return visitAssignableExpr(ctx.assignableExpr());
} else if (ctx.stmtExpr() != null) {
return visitStmtExpr(ctx.stmtExpr());
} else if (ctx.subExpression() != null) {
return visitSubExpression(ctx.subExpression());
} }
return null; return null;
} }
@Override
public Node visitAssignableExpr(DecafParser.AssignableExprContext ctx) {
if (ctx.Identifier() != null) {
return new LocalVarIdentifier(ctx.Identifier().getText());
}
return null;
}
@Override
public Node visitInstVar(DecafParser.InstVarContext ctx) {
return super.visitInstVar(ctx);
}
// @Override
// public Node visitArgumentList(DecafParser.ArgumentListContext ctx) {
// if (ctx.expression().size() == 1) {
// return visitExpression(ctx.expression(0));
// } else if (ctx.expression().size() >= 2) {
// for(DecafParser.ExpressionContext expressionContext: ctx.expression()) {
//
// }
// }
// }
} }