From be3aa416adcee87cb5f39798f91fddb119878921 Mon Sep 17 00:00:00 2001 From: Simon Hajek Date: Wed, 5 Jun 2024 11:58:43 +0200 Subject: [PATCH 1/9] First Part --- .../codegen/IRGenerator.java | 20 +++++++++-- .../codegen/instructions/CallInstruction.java | 35 +++++++++++++++++++ 2 files changed, 52 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/auberer/compilerdesignlectureproject/codegen/instructions/CallInstruction.java diff --git a/src/main/java/com/auberer/compilerdesignlectureproject/codegen/IRGenerator.java b/src/main/java/com/auberer/compilerdesignlectureproject/codegen/IRGenerator.java index 92aac9b..53ac832 100644 --- a/src/main/java/com/auberer/compilerdesignlectureproject/codegen/IRGenerator.java +++ b/src/main/java/com/auberer/compilerdesignlectureproject/codegen/IRGenerator.java @@ -1,8 +1,7 @@ package com.auberer.compilerdesignlectureproject.codegen; -import com.auberer.compilerdesignlectureproject.ast.ASTEntryNode; -import com.auberer.compilerdesignlectureproject.ast.ASTPrintBuiltinCallNode; -import com.auberer.compilerdesignlectureproject.ast.ASTVisitor; +import com.auberer.compilerdesignlectureproject.ast.*; +import com.auberer.compilerdesignlectureproject.codegen.instructions.CallInstruction; import com.auberer.compilerdesignlectureproject.codegen.instructions.Instruction; import com.auberer.compilerdesignlectureproject.codegen.instructions.PrintInstruction; import lombok.Getter; @@ -89,4 +88,19 @@ private boolean isBlockTerminated(BasicBlock block) { return !block.getInstructions().isEmpty() && block.getInstructions().getLast().isTerminator(); } + @Override + public IRExprResult visitFctCall(ASTFctCallNode node) { + CallInstruction callInstruction = new CallInstruction(node, module.getFunction(node.getName()), node.getCallParams()); + pushToCurrentBlock(callInstruction); + return new IRExprResult(node.getValue(), node, null); + } + + @Override + public IRExprResult visitFctDef(ASTFctDefNode node) { + Function function = new Function(node.getName()); + function.setEntryBlock(new BasicBlock("entry")); + module.addFunction(function); + switchToBlock(function.getEntryBlock()); + return new IRExprResult(node.getValue(), node, null); + } } diff --git a/src/main/java/com/auberer/compilerdesignlectureproject/codegen/instructions/CallInstruction.java b/src/main/java/com/auberer/compilerdesignlectureproject/codegen/instructions/CallInstruction.java new file mode 100644 index 0000000..d403748 --- /dev/null +++ b/src/main/java/com/auberer/compilerdesignlectureproject/codegen/instructions/CallInstruction.java @@ -0,0 +1,35 @@ +package com.auberer.compilerdesignlectureproject.codegen.instructions; + +import com.auberer.compilerdesignlectureproject.ast.ASTCallParamsNode; +import com.auberer.compilerdesignlectureproject.ast.ASTNode; +import com.auberer.compilerdesignlectureproject.codegen.Function; +import com.auberer.compilerdesignlectureproject.interpreter.InterpreterEnvironment; +import lombok.Getter; + +@Getter +public class CallInstruction extends Instruction { + private final Function function; + private final ASTCallParamsNode callParamsNode; + + public CallInstruction(ASTNode node, Function function, ASTCallParamsNode callParamsNode) { + super(node); + this.function = function; + this.callParamsNode = callParamsNode; + } + + @Override + public void run(InterpreterEnvironment env) { + env.setInstructionIterator(function.getEntryBlock().getInstructions().listIterator()); + } + + @Override + public void dumpIR(StringBuilder sb) { + sb.append("call ").append(function.getName()).append("(").append(callParamsNode.getParamsAsLogicNodes()).append(")"); + } + + @Override + public void trace(StringBuilder sb) { + sb.append(node.getCodeLoc().toString()).append(": call "); + } + +} From 6da77b8a35aed972061281aa730a3117aecd5b64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nick=20M=C3=B6hrmann?= <81536709+Shiny1708@users.noreply.github.com> Date: Sun, 9 Jun 2024 20:00:14 +0200 Subject: [PATCH 2/9] Call instruction, return logic and visit for def and call --- .../codegen/IRGenerator.java | 97 ++++--------------- .../codegen/instructions/CallInstruction.java | 45 +++++++++ .../instructions/ReturnInstruction.java | 5 +- .../interpreter/InterpreterEnvironment.java | 24 ++++- 4 files changed, 91 insertions(+), 80 deletions(-) create mode 100644 src/main/java/com/auberer/compilerdesignlectureproject/codegen/instructions/CallInstruction.java diff --git a/src/main/java/com/auberer/compilerdesignlectureproject/codegen/IRGenerator.java b/src/main/java/com/auberer/compilerdesignlectureproject/codegen/IRGenerator.java index 3cfedc1..e06fce1 100644 --- a/src/main/java/com/auberer/compilerdesignlectureproject/codegen/IRGenerator.java +++ b/src/main/java/com/auberer/compilerdesignlectureproject/codegen/IRGenerator.java @@ -1,56 +1,23 @@ package com.auberer.compilerdesignlectureproject.codegen; import com.auberer.compilerdesignlectureproject.ast.*; -import com.auberer.compilerdesignlectureproject.codegen.instructions.CondJumpInstruction; +import com.auberer.compilerdesignlectureproject.codegen.instructions.CallInstruction; import com.auberer.compilerdesignlectureproject.codegen.instructions.Instruction; -import com.auberer.compilerdesignlectureproject.codegen.instructions.JumpInstruction; import com.auberer.compilerdesignlectureproject.codegen.instructions.PrintInstruction; import lombok.Getter; -import lombok.Setter; -@Getter public class IRGenerator extends ASTVisitor { // IR module, which represents the whole program + @Getter private final Module module; // The basic block, which is currently the insert point for new instructions - @Setter private BasicBlock currentBlock = null; public IRGenerator(String moduleName) { module = new Module(moduleName); } - @Override - public IRExprResult visitForLoop(ASTForNode node) { - BasicBlock loopHeadBlock = new BasicBlock("loopHead"); - BasicBlock loopBodyBlock = new BasicBlock("loopBody"); - BasicBlock loopEndBlock = new BasicBlock("loopEnd"); - - visit(node.getInitialization()); - - JumpInstruction jumpToLoopHead = new JumpInstruction(node, loopHeadBlock); - pushToCurrentBlock(jumpToLoopHead); - - switchToBlock(loopHeadBlock); - IRExprResult conditionResult = visit(node.getCondition()); - - CondJumpInstruction condJumpInstruction = new CondJumpInstruction(node, conditionResult.getValue().getNode(), loopBodyBlock, loopEndBlock); - pushToCurrentBlock(condJumpInstruction); - - switchToBlock(loopBodyBlock); - visit(node.getBody()); - - visit(node.getIncrement()); - - JumpInstruction jumpInstruction = new JumpInstruction(node, loopHeadBlock); - pushToCurrentBlock(jumpInstruction); - - switchToBlock(loopEndBlock); - - return null; - } - @Override public IRExprResult visitEntry(ASTEntryNode node) { // We did not enter a function yet, so the current block has to be null @@ -72,46 +39,7 @@ public IRExprResult visitPrintBuiltin(ASTPrintBuiltinCallNode node) { return new IRExprResult(null, node, null); } - @Override - public IRExprResult visitWhileLoop(ASTWhileLoopNode node) { - BasicBlock conditionBlock = new BasicBlock("while.cond"); - BasicBlock bodyBlock = new BasicBlock("while.body"); - BasicBlock exitBlock = new BasicBlock("while.exit"); - - JumpInstruction jump = new JumpInstruction(node, conditionBlock); - pushToCurrentBlock(jump); - - switchToBlock(conditionBlock); - visitLogicalExpr(node.getCondition()); - CondJumpInstruction condJump = new CondJumpInstruction(node, node.getCondition(), bodyBlock, exitBlock); - pushToCurrentBlock(condJump); - switchToBlock(bodyBlock); - - visitStmtLst(node.getBody()); - jump = new JumpInstruction(node, conditionBlock); - pushToCurrentBlock(jump); - switchToBlock(conditionBlock); - - switchToBlock(exitBlock); - return new IRExprResult(null, node, null); - } - - @Override - public IRExprResult visitDoWhileLoop(ASTDoWhileLoopNode node) { - BasicBlock doWhileBlock = new BasicBlock("do_while.body"); - BasicBlock endDoWhileBlock = new BasicBlock("do_while.exit"); - CondJumpInstruction condJumpInstruction = new CondJumpInstruction(node, node.getCondition(), doWhileBlock, endDoWhileBlock); - - JumpInstruction jumpInstruction = new JumpInstruction(node, doWhileBlock); - currentBlock.pushInstruction(jumpInstruction); - - switchToBlock(doWhileBlock); - visitStmtLst(node.getBody()); - doWhileBlock.pushInstruction(condJumpInstruction); - switchToBlock(endDoWhileBlock); - - return new IRExprResult(null, node, null); - } + // ToDo: Insert other visit methods here /** * Can be used to set the instruction insert point to a specific block @@ -144,7 +72,7 @@ private void finalizeFunction() { private void pushToCurrentBlock(Instruction instruction) { assert instruction != null; assert currentBlock != null; - assert !isBlockTerminated(currentBlock); + assert isBlockTerminated(currentBlock); // Push to the back of the current block currentBlock.pushInstruction(instruction); @@ -160,4 +88,19 @@ private boolean isBlockTerminated(BasicBlock block) { return !block.getInstructions().isEmpty() && block.getInstructions().getLast().isTerminator(); } -} + @Override + public IRExprResult visitFctCall(ASTFctCallNode node) { + CallInstruction callInstruction = new CallInstruction(node, module.getFunction(node.getName()), node.getCallParams()); + pushToCurrentBlock(callInstruction); + return new IRExprResult(node.getValue(), node, null); + } + + @Override + public IRExprResult visitFctDef(ASTFctDefNode node) { + Function function = new Function(node.getName()); + function.setEntryBlock(new BasicBlock("entry")); + module.addFunction(function); + switchToBlock(function.getEntryBlock()); + return new IRExprResult(node.getValue(), node, null); + } +} \ No newline at end of file diff --git a/src/main/java/com/auberer/compilerdesignlectureproject/codegen/instructions/CallInstruction.java b/src/main/java/com/auberer/compilerdesignlectureproject/codegen/instructions/CallInstruction.java new file mode 100644 index 0000000..1973b5f --- /dev/null +++ b/src/main/java/com/auberer/compilerdesignlectureproject/codegen/instructions/CallInstruction.java @@ -0,0 +1,45 @@ +package com.auberer.compilerdesignlectureproject.codegen.instructions; + +import com.auberer.compilerdesignlectureproject.ast.ASTCallParamsNode; +import com.auberer.compilerdesignlectureproject.ast.ASTNode; +import com.auberer.compilerdesignlectureproject.codegen.Function; +import com.auberer.compilerdesignlectureproject.interpreter.InterpreterEnvironment; +import lombok.Getter; + +import java.util.ListIterator; + +@Getter +public class CallInstruction extends Instruction { + private final Function function; + private final ASTCallParamsNode callParamsNode; + + public CallInstruction(ASTNode node, Function function, ASTCallParamsNode callParamsNode) { + super(node); + this.function = function; + this.callParamsNode = callParamsNode; + } + + @Override + public void run(InterpreterEnvironment env) { + // Save the current instruction iterator + ListIterator returnIterator = env.getInstructionIterator(); + // Advance the iterator to the instruction after the call + if (returnIterator.hasNext()) { + returnIterator.next(); + } + // Handle the function call in the interpreter environment + env.callFunction(returnIterator, function); + } + + @Override + public void dumpIR(StringBuilder sb) { + // call () + sb.append("call ").append(function.getName()).append("(").append(callParamsNode.getParamsAsLogicNodes()).append(")"); + } + + @Override + public void trace(StringBuilder sb) { + sb.append(node.getCodeLoc().toString()).append(": call "); + } + +} \ No newline at end of file diff --git a/src/main/java/com/auberer/compilerdesignlectureproject/codegen/instructions/ReturnInstruction.java b/src/main/java/com/auberer/compilerdesignlectureproject/codegen/instructions/ReturnInstruction.java index 4392caa..fb1bf0c 100644 --- a/src/main/java/com/auberer/compilerdesignlectureproject/codegen/instructions/ReturnInstruction.java +++ b/src/main/java/com/auberer/compilerdesignlectureproject/codegen/instructions/ReturnInstruction.java @@ -15,7 +15,8 @@ public ReturnInstruction(ASTLogicNode logicNode) { @Override public void run(InterpreterEnvironment env) { - // ToDo(Team 6): Implement + // Return from the current function and set the instruction iterator to the instruction after the call + env.returnFromFunction(); } @Override @@ -34,4 +35,4 @@ public void trace(StringBuilder sb) { public boolean isTerminator() { return true; } -} +} \ No newline at end of file diff --git a/src/main/java/com/auberer/compilerdesignlectureproject/interpreter/InterpreterEnvironment.java b/src/main/java/com/auberer/compilerdesignlectureproject/interpreter/InterpreterEnvironment.java index c5a0701..8ca5582 100644 --- a/src/main/java/com/auberer/compilerdesignlectureproject/interpreter/InterpreterEnvironment.java +++ b/src/main/java/com/auberer/compilerdesignlectureproject/interpreter/InterpreterEnvironment.java @@ -3,15 +3,18 @@ import com.auberer.compilerdesignlectureproject.codegen.Function; import com.auberer.compilerdesignlectureproject.codegen.Module; import com.auberer.compilerdesignlectureproject.codegen.instructions.Instruction; +import lombok.Getter; import lombok.Setter; import java.util.ListIterator; +import java.util.Stack; public class InterpreterEnvironment { private final Module irModule; private final boolean doTracing; @Setter + @Getter private ListIterator instructionIterator; public InterpreterEnvironment(Module irModule, boolean doTracing) { @@ -36,4 +39,23 @@ public void interpret() { } } -} + private final Stack> callStack = new Stack<>(); + + public void callFunction(ListIterator returnIterator, Function function) { + // Push the current instruction iterator to the call stack + callStack.push(returnIterator); + // Set the instruction iterator to the first instruction of the called function + instructionIterator = function.getEntryBlock().getInstructions().listIterator(); + } + + public void returnFromFunction() { + // Check if there is a corresponding call for the return instruction + if (callStack.isEmpty()) { + throw new RuntimeException("Return instruction without corresponding call"); + } + // Pop the call stack and set the instruction iterator to the instruction after the call + // This logic allows for nested function calls + instructionIterator = callStack.pop(); + } + +} \ No newline at end of file From 5909c64b968a20927a8192a5e482b40c89827a55 Mon Sep 17 00:00:00 2001 From: nils bohland Date: Sun, 9 Jun 2024 21:12:13 +0200 Subject: [PATCH 3/9] changed visitFctDef function to reflect the block-structure Also fixed minor bugs from last week --- .../ast/FunctionDef.java | 2 +- .../codegen/IRGenerator.java | 33 +++++++++++++- .../sema/TypeChecker.java | 3 +- .../codegen/FctCallTest.java | 45 +++++++++++++++++++ 4 files changed, 79 insertions(+), 4 deletions(-) create mode 100644 src/test/java/com/auberer/compilerdesignlectureproject/codegen/FctCallTest.java diff --git a/src/main/java/com/auberer/compilerdesignlectureproject/ast/FunctionDef.java b/src/main/java/com/auberer/compilerdesignlectureproject/ast/FunctionDef.java index e000b49..b78c5be 100644 --- a/src/main/java/com/auberer/compilerdesignlectureproject/ast/FunctionDef.java +++ b/src/main/java/com/auberer/compilerdesignlectureproject/ast/FunctionDef.java @@ -59,7 +59,7 @@ public boolean equals(FunctionDef def) { return def.getName().equals(getName()) && isSameParams(def.getParams()); } - public boolean isSameParams(List otherParams) { + private boolean isSameParams(List otherParams) { if (params.size() != otherParams.size()) { return false; } diff --git a/src/main/java/com/auberer/compilerdesignlectureproject/codegen/IRGenerator.java b/src/main/java/com/auberer/compilerdesignlectureproject/codegen/IRGenerator.java index 53ac832..86e82ca 100644 --- a/src/main/java/com/auberer/compilerdesignlectureproject/codegen/IRGenerator.java +++ b/src/main/java/com/auberer/compilerdesignlectureproject/codegen/IRGenerator.java @@ -97,10 +97,39 @@ public IRExprResult visitFctCall(ASTFctCallNode node) { @Override public IRExprResult visitFctDef(ASTFctDefNode node) { + + BasicBlock body = new BasicBlock("body"); + BasicBlock params = new BasicBlock("params"); + + switchToBlock(params); + visitParamLst(node.getParams()); + Function function = new Function(node.getName()); - function.setEntryBlock(new BasicBlock("entry")); + function.setEntryBlock(body); module.addFunction(function); - switchToBlock(function.getEntryBlock()); + visitLogic(node.getBody()); + + switchToBlock(new BasicBlock("exit")); return new IRExprResult(node.getValue(), node, null); } + + @Override + public IRExprResult visitParamLst(ASTParamLstNode node){ + int i = 0; + for (ASTParamNode paramNode: node.getParamNodes()){ + BasicBlock block = new BasicBlock("param" + i); + switchToBlock(block); + i++; + visitParam(paramNode); + } + return new IRExprResult(null, node, null); + } + + @Override + public IRExprResult visitParam(ASTParamNode node){ + visitType(node.getDataType()); + return new IRExprResult(null, node, null); + } } + + diff --git a/src/main/java/com/auberer/compilerdesignlectureproject/sema/TypeChecker.java b/src/main/java/com/auberer/compilerdesignlectureproject/sema/TypeChecker.java index 3e73f15..0e63421 100644 --- a/src/main/java/com/auberer/compilerdesignlectureproject/sema/TypeChecker.java +++ b/src/main/java/com/auberer/compilerdesignlectureproject/sema/TypeChecker.java @@ -333,10 +333,11 @@ public ExprResult visitFctCall(ASTFctCallNode node) { } - Type resultType = new Type(SuperType.TY_FUNCTION); + Type resultType = new Type(def.getReturnType()); return new ExprResult(node.setEvaluatedSymbolType(resultType)); } +@Override public ExprResult visitParam(ASTParamNode node) { ASTTypeNode typeNode = node.getDataType(); ExprResult type = visitType(typeNode); diff --git a/src/test/java/com/auberer/compilerdesignlectureproject/codegen/FctCallTest.java b/src/test/java/com/auberer/compilerdesignlectureproject/codegen/FctCallTest.java new file mode 100644 index 0000000..523bf81 --- /dev/null +++ b/src/test/java/com/auberer/compilerdesignlectureproject/codegen/FctCallTest.java @@ -0,0 +1,45 @@ +package com.auberer.compilerdesignlectureproject.codegen; + +import com.auberer.compilerdesignlectureproject.ast.*; +import com.auberer.compilerdesignlectureproject.lexer.Lexer; +import com.auberer.compilerdesignlectureproject.parser.Parser; +import com.auberer.compilerdesignlectureproject.reader.Reader; +import com.auberer.compilerdesignlectureproject.sema.SymbolTableBuilder; +import com.auberer.compilerdesignlectureproject.sema.TypeChecker; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +public class FctCallTest { + + @Test + @DisplayName("Integration test for function call") + void testIntegrationTestForFunctionCall() { + String fctDef = """ + func int myFunc(int x) + int i = 17; + return x; + cnuf + + func int fn2() + call myFunc(7); + return 2; + cnuf + """; + + Reader reader = new Reader(fctDef); + Lexer lexer = new Lexer(reader, false); + Parser parser = new Parser(lexer); + + ASTEntryNode parseNode = parser.parse(); + + ASTFctDefNode defNode = parseNode.getChild(ASTFctDefNode.class, 0); + ASTFctDefNode defWithCallNode = parseNode.getChild(ASTFctDefNode.class, 1); + + ASTFctCallNode callNode = defWithCallNode.getChild(ASTLogicNode.class, 0).getChild(ASTStmtLstNode.class, 0).getChild(ASTStmtNode.class, 0).getChild(ASTAssignStmtNode.class, 0).getChild(ASTLogicalExprNode.class, 0).getChild(ASTCompareExprNode.class, 0).getChild(ASTAdditiveExprNode.class, 0).getChild(ASTMultiplicativeExprNode.class, 0).getChild(ASTPrefixExprNode.class, 0).getChild(ASTAtomicExprNode.class, 0).getFctCall(); + + /*IRGenerator generator = new IRGenerator(""); + generator.visitFctDef(defNode); + generator.visitFctCall(callNode); + */ + } +} From 0d3befdc935c3c96b11aac5a854a5cd4371b1017 Mon Sep 17 00:00:00 2001 From: nils bohland Date: Sun, 9 Jun 2024 21:18:07 +0200 Subject: [PATCH 4/9] changed visitFctDef function to reflect the block-structure Also fixed minor bugs from last week --- .../codegen/IRGenerator.java | 85 +++++++++++++++++-- 1 file changed, 78 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/auberer/compilerdesignlectureproject/codegen/IRGenerator.java b/src/main/java/com/auberer/compilerdesignlectureproject/codegen/IRGenerator.java index 86e82ca..be90ada 100644 --- a/src/main/java/com/auberer/compilerdesignlectureproject/codegen/IRGenerator.java +++ b/src/main/java/com/auberer/compilerdesignlectureproject/codegen/IRGenerator.java @@ -1,23 +1,54 @@ package com.auberer.compilerdesignlectureproject.codegen; import com.auberer.compilerdesignlectureproject.ast.*; -import com.auberer.compilerdesignlectureproject.codegen.instructions.CallInstruction; -import com.auberer.compilerdesignlectureproject.codegen.instructions.Instruction; -import com.auberer.compilerdesignlectureproject.codegen.instructions.PrintInstruction; +import com.auberer.compilerdesignlectureproject.codegen.instructions.*; import lombok.Getter; - +import lombok.Setter; +@Getter public class IRGenerator extends ASTVisitor { // IR module, which represents the whole program - @Getter + private final Module module; // The basic block, which is currently the insert point for new instructions + @Setter private BasicBlock currentBlock = null; public IRGenerator(String moduleName) { module = new Module(moduleName); } + + @Override + public IRExprResult visitForLoop(ASTForNode node) { + BasicBlock loopHeadBlock = new BasicBlock("loopHead"); + BasicBlock loopBodyBlock = new BasicBlock("loopBody"); + BasicBlock loopEndBlock = new BasicBlock("loopEnd"); + + visit(node.getInitialization()); + + JumpInstruction jumpToLoopHead = new JumpInstruction(node, loopHeadBlock); + pushToCurrentBlock(jumpToLoopHead); + + switchToBlock(loopHeadBlock); + IRExprResult conditionResult = visit(node.getCondition()); + + CondJumpInstruction condJumpInstruction = new CondJumpInstruction(node, conditionResult.getValue().getNode(), loopBodyBlock, loopEndBlock); + pushToCurrentBlock(condJumpInstruction); + + switchToBlock(loopBodyBlock); + visit(node.getBody()); + + visit(node.getIncrement()); + + JumpInstruction jumpInstruction = new JumpInstruction(node, loopHeadBlock); + pushToCurrentBlock(jumpInstruction); + + switchToBlock(loopEndBlock); + + return null; + } + @Override public IRExprResult visitEntry(ASTEntryNode node) { // We did not enter a function yet, so the current block has to be null @@ -39,8 +70,48 @@ public IRExprResult visitPrintBuiltin(ASTPrintBuiltinCallNode node) { return new IRExprResult(null, node, null); } - // ToDo: Insert other visit methods here + + @Override + public IRExprResult visitWhileLoop(ASTWhileLoopNode node) { + BasicBlock conditionBlock = new BasicBlock("while.cond"); + BasicBlock bodyBlock = new BasicBlock("while.body"); + BasicBlock exitBlock = new BasicBlock("while.exit"); + + JumpInstruction jump = new JumpInstruction(node, conditionBlock); + pushToCurrentBlock(jump); + + switchToBlock(conditionBlock); + visitLogicalExpr(node.getCondition()); + CondJumpInstruction condJump = new CondJumpInstruction(node, node.getCondition(), bodyBlock, exitBlock); + pushToCurrentBlock(condJump); + switchToBlock(bodyBlock); + + visitStmtLst(node.getBody()); + jump = new JumpInstruction(node, conditionBlock); + pushToCurrentBlock(jump); + switchToBlock(conditionBlock); + + switchToBlock(exitBlock); + return new IRExprResult(null, node, null); + } + + @Override + public IRExprResult visitDoWhileLoop(ASTDoWhileLoopNode node) { + BasicBlock doWhileBlock = new BasicBlock("do_while.body"); + BasicBlock endDoWhileBlock = new BasicBlock("do_while.exit"); + CondJumpInstruction condJumpInstruction = new CondJumpInstruction(node, node.getCondition(), doWhileBlock, endDoWhileBlock); + + JumpInstruction jumpInstruction = new JumpInstruction(node, doWhileBlock); + currentBlock.pushInstruction(jumpInstruction); + + switchToBlock(doWhileBlock); + visitStmtLst(node.getBody()); + doWhileBlock.pushInstruction(condJumpInstruction); + switchToBlock(endDoWhileBlock); + + return new IRExprResult(null, node, null); + } /** * Can be used to set the instruction insert point to a specific block * @@ -60,7 +131,7 @@ private void switchToBlock(BasicBlock targetBlock) { */ private void finalizeFunction() { assert currentBlock != null; - assert isBlockTerminated(currentBlock); + assert !isBlockTerminated(currentBlock); currentBlock = null; } From 04c57114ca52050e56be93764629bbaab36b9928 Mon Sep 17 00:00:00 2001 From: nils bohland Date: Mon, 10 Jun 2024 09:23:25 +0200 Subject: [PATCH 5/9] added return instruction to IRGenerator, also added a getReturn and a getBody node to logicNode --- .../ast/ASTLogicNode.java | 6 +++++- .../codegen/IRGenerator.java | 17 +++++++++++------ .../codegen/instructions/CallInstruction.java | 4 ---- .../codegen/instructions/ReturnInstruction.java | 2 +- 4 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/auberer/compilerdesignlectureproject/ast/ASTLogicNode.java b/src/main/java/com/auberer/compilerdesignlectureproject/ast/ASTLogicNode.java index e79afe8..9b4460b 100644 --- a/src/main/java/com/auberer/compilerdesignlectureproject/ast/ASTLogicNode.java +++ b/src/main/java/com/auberer/compilerdesignlectureproject/ast/ASTLogicNode.java @@ -14,7 +14,11 @@ public static Set getSelectionSet() { return ASTStmtLstNode.getSelectionSet(); } - public ASTLogicalExprNode logicalExpr() { + public ASTLogicalExprNode getReturnNode() { return getChild(ASTLogicalExprNode.class, 0); } + + public ASTStmtLstNode getBody() { + return getChild(ASTStmtLstNode.class, 0); + } } diff --git a/src/main/java/com/auberer/compilerdesignlectureproject/codegen/IRGenerator.java b/src/main/java/com/auberer/compilerdesignlectureproject/codegen/IRGenerator.java index be90ada..a1bb4b9 100644 --- a/src/main/java/com/auberer/compilerdesignlectureproject/codegen/IRGenerator.java +++ b/src/main/java/com/auberer/compilerdesignlectureproject/codegen/IRGenerator.java @@ -180,17 +180,12 @@ public IRExprResult visitFctDef(ASTFctDefNode node) { module.addFunction(function); visitLogic(node.getBody()); - switchToBlock(new BasicBlock("exit")); return new IRExprResult(node.getValue(), node, null); } @Override public IRExprResult visitParamLst(ASTParamLstNode node){ - int i = 0; for (ASTParamNode paramNode: node.getParamNodes()){ - BasicBlock block = new BasicBlock("param" + i); - switchToBlock(block); - i++; visitParam(paramNode); } return new IRExprResult(null, node, null); @@ -198,7 +193,17 @@ public IRExprResult visitParamLst(ASTParamLstNode node){ @Override public IRExprResult visitParam(ASTParamNode node){ - visitType(node.getDataType()); + IRExprResult datatype = visitType(node.getDataType()); + StoreInstruction storeParam = new StoreInstruction(node, datatype.getEntry()); + pushToCurrentBlock(storeParam); + return new IRExprResult(null, node, null); + } + + @Override + public IRExprResult visitLogic(ASTLogicNode node) { + visitStmtLst(node.getBody()); + ReturnInstruction returnInstruction = new ReturnInstruction(node); + pushToCurrentBlock(returnInstruction); return new IRExprResult(null, node, null); } } diff --git a/src/main/java/com/auberer/compilerdesignlectureproject/codegen/instructions/CallInstruction.java b/src/main/java/com/auberer/compilerdesignlectureproject/codegen/instructions/CallInstruction.java index 1973b5f..dc32bf6 100644 --- a/src/main/java/com/auberer/compilerdesignlectureproject/codegen/instructions/CallInstruction.java +++ b/src/main/java/com/auberer/compilerdesignlectureproject/codegen/instructions/CallInstruction.java @@ -23,10 +23,6 @@ public CallInstruction(ASTNode node, Function function, ASTCallParamsNode callPa public void run(InterpreterEnvironment env) { // Save the current instruction iterator ListIterator returnIterator = env.getInstructionIterator(); - // Advance the iterator to the instruction after the call - if (returnIterator.hasNext()) { - returnIterator.next(); - } // Handle the function call in the interpreter environment env.callFunction(returnIterator, function); } diff --git a/src/main/java/com/auberer/compilerdesignlectureproject/codegen/instructions/ReturnInstruction.java b/src/main/java/com/auberer/compilerdesignlectureproject/codegen/instructions/ReturnInstruction.java index fb1bf0c..aa3da17 100644 --- a/src/main/java/com/auberer/compilerdesignlectureproject/codegen/instructions/ReturnInstruction.java +++ b/src/main/java/com/auberer/compilerdesignlectureproject/codegen/instructions/ReturnInstruction.java @@ -10,7 +10,7 @@ public class ReturnInstruction extends Instruction { public ReturnInstruction(ASTLogicNode logicNode) { super(logicNode); - returnExpr = logicNode.logicalExpr(); + returnExpr = logicNode.getReturnNode(); } @Override From ff25fa813513e3ad807813e3fc617d83f0243567 Mon Sep 17 00:00:00 2001 From: nils bohland Date: Mon, 10 Jun 2024 11:53:10 +0200 Subject: [PATCH 6/9] added return instruction to IRGenerator, also added a getReturn and a getBody node to logicNode --- .../ast/ASTLogicNode.java | 3 ++ .../codegen/Function.java | 25 ++++++++++++++-- .../codegen/IRGenerator.java | 29 ++++++++++++++----- .../codegen/Module.java | 5 ++-- .../instructions/ReturnInstruction.java | 4 +-- .../interpreter/InterpreterEnvironment.java | 3 +- .../codegen/ModuleTest.java | 11 ++++++- .../codegen/WhileLoopTest.java | 4 ++- .../parser/DoWhileLoopNodeTest.java | 6 ++-- 9 files changed, 71 insertions(+), 19 deletions(-) diff --git a/src/main/java/com/auberer/compilerdesignlectureproject/ast/ASTLogicNode.java b/src/main/java/com/auberer/compilerdesignlectureproject/ast/ASTLogicNode.java index 9b4460b..6140bf8 100644 --- a/src/main/java/com/auberer/compilerdesignlectureproject/ast/ASTLogicNode.java +++ b/src/main/java/com/auberer/compilerdesignlectureproject/ast/ASTLogicNode.java @@ -15,6 +15,9 @@ public static Set getSelectionSet() { } public ASTLogicalExprNode getReturnNode() { + if(getChildren(ASTLogicalExprNode.class).isEmpty()){ + return null; + } return getChild(ASTLogicalExprNode.class, 0); } diff --git a/src/main/java/com/auberer/compilerdesignlectureproject/codegen/Function.java b/src/main/java/com/auberer/compilerdesignlectureproject/codegen/Function.java index 06e5193..411670b 100644 --- a/src/main/java/com/auberer/compilerdesignlectureproject/codegen/Function.java +++ b/src/main/java/com/auberer/compilerdesignlectureproject/codegen/Function.java @@ -1,8 +1,10 @@ package com.auberer.compilerdesignlectureproject.codegen; +import com.auberer.compilerdesignlectureproject.sema.Type; import lombok.Getter; import java.util.ArrayList; +import java.util.Collection; import java.util.List; @Getter @@ -10,9 +12,11 @@ public class Function implements IDumpable { private final String name; private BasicBlock entryBlock; + private final List parameters; - public Function(String name) { + public Function(String name, List parameters) { this.name = name; + this.parameters = parameters; } public void setEntryBlock(BasicBlock entryBlock) { @@ -22,9 +26,26 @@ public void setEntryBlock(BasicBlock entryBlock) { @Override public void dumpIR(StringBuilder sb) { - sb.append("function ").append(name).append(": {\n"); + sb.append("function ").append(name). + append("("); + for (Parameter parameter : parameters) { + sb.append(parameter.getType()).append(" ").append(parameter.getName()); + } + sb.append(")"); + sb.append(": {\n"); List dumpedBlocks = new ArrayList<>(); entryBlock.dumpIR(sb, dumpedBlocks); sb.append("}\n\n"); } + + @Getter + public static class Parameter{ + private final String name; + private final Type type; + + public Parameter(String name, Type type) { + this.name = name; + this.type = type; + } + } } diff --git a/src/main/java/com/auberer/compilerdesignlectureproject/codegen/IRGenerator.java b/src/main/java/com/auberer/compilerdesignlectureproject/codegen/IRGenerator.java index a1bb4b9..1d06732 100644 --- a/src/main/java/com/auberer/compilerdesignlectureproject/codegen/IRGenerator.java +++ b/src/main/java/com/auberer/compilerdesignlectureproject/codegen/IRGenerator.java @@ -4,6 +4,10 @@ import com.auberer.compilerdesignlectureproject.codegen.instructions.*; import lombok.Getter; import lombok.Setter; + +import java.util.ArrayList; +import java.util.List; + @Getter public class IRGenerator extends ASTVisitor { @@ -143,7 +147,7 @@ private void finalizeFunction() { private void pushToCurrentBlock(Instruction instruction) { assert instruction != null; assert currentBlock != null; - assert isBlockTerminated(currentBlock); + assert !isBlockTerminated(currentBlock); // Push to the back of the current block currentBlock.pushInstruction(instruction); @@ -161,25 +165,32 @@ private boolean isBlockTerminated(BasicBlock block) { @Override public IRExprResult visitFctCall(ASTFctCallNode node) { - CallInstruction callInstruction = new CallInstruction(node, module.getFunction(node.getName()), node.getCallParams()); + CallInstruction callInstruction = new CallInstruction(node, module.getFunction(node.getName(), node.getCallParams().getParamsAsLogicNodes().stream().map(ASTNode::getType).toList()), node.getCallParams()); pushToCurrentBlock(callInstruction); return new IRExprResult(node.getValue(), node, null); } @Override public IRExprResult visitFctDef(ASTFctDefNode node) { + BasicBlock fctDef = new BasicBlock("fctDef"); - BasicBlock body = new BasicBlock("body"); - BasicBlock params = new BasicBlock("params"); + switchToBlock(fctDef); + if(node.hasParams()){ + visitParamLst(node.getParams()); + } - switchToBlock(params); - visitParamLst(node.getParams()); - Function function = new Function(node.getName()); - function.setEntryBlock(body); + List params = node.hasParams()? + node.getParams().getParamNodes().stream().map((paramNode) -> new Function.Parameter(paramNode.getName(), paramNode.getType())).toList() + :new ArrayList<>(); + + Function function = new Function(node.getName(), params); + function.setEntryBlock(fctDef); module.addFunction(function); + visitLogic(node.getBody()); + currentBlock = null; return new IRExprResult(node.getValue(), node, null); } @@ -194,6 +205,8 @@ public IRExprResult visitParamLst(ASTParamLstNode node){ @Override public IRExprResult visitParam(ASTParamNode node){ IRExprResult datatype = visitType(node.getDataType()); + AllocaInstruction allocaInstruction = new AllocaInstruction(node, datatype.getEntry()); + pushToCurrentBlock(allocaInstruction); StoreInstruction storeParam = new StoreInstruction(node, datatype.getEntry()); pushToCurrentBlock(storeParam); return new IRExprResult(null, node, null); diff --git a/src/main/java/com/auberer/compilerdesignlectureproject/codegen/Module.java b/src/main/java/com/auberer/compilerdesignlectureproject/codegen/Module.java index f79fc54..d3c246d 100644 --- a/src/main/java/com/auberer/compilerdesignlectureproject/codegen/Module.java +++ b/src/main/java/com/auberer/compilerdesignlectureproject/codegen/Module.java @@ -1,5 +1,6 @@ package com.auberer.compilerdesignlectureproject.codegen; +import com.auberer.compilerdesignlectureproject.sema.Type; import lombok.Getter; import java.util.ArrayList; @@ -23,9 +24,9 @@ public void addFunction(Function function) { functions.add(function); } - public Function getFunction(String name) { + public Function getFunction(String name, List parameters) { for (Function function : functions) - if (function.getName().equals(name)) + if (function.getName().equals(name) && function.getParameters().stream().map(Function.Parameter::getType).toList().equals(parameters)) return function; return null; } diff --git a/src/main/java/com/auberer/compilerdesignlectureproject/codegen/instructions/ReturnInstruction.java b/src/main/java/com/auberer/compilerdesignlectureproject/codegen/instructions/ReturnInstruction.java index aa3da17..5f1f4a3 100644 --- a/src/main/java/com/auberer/compilerdesignlectureproject/codegen/instructions/ReturnInstruction.java +++ b/src/main/java/com/auberer/compilerdesignlectureproject/codegen/instructions/ReturnInstruction.java @@ -21,9 +21,9 @@ public void run(InterpreterEnvironment env) { @Override public void dumpIR(StringBuilder sb) { - sb.append("return "); + sb.append("return"); if (returnExpr != null) - sb.append(returnExpr.getValue().getName()); + sb.append(" ").append(returnExpr.getValue().getName()); } @Override diff --git a/src/main/java/com/auberer/compilerdesignlectureproject/interpreter/InterpreterEnvironment.java b/src/main/java/com/auberer/compilerdesignlectureproject/interpreter/InterpreterEnvironment.java index 8ca5582..1b6bf3f 100644 --- a/src/main/java/com/auberer/compilerdesignlectureproject/interpreter/InterpreterEnvironment.java +++ b/src/main/java/com/auberer/compilerdesignlectureproject/interpreter/InterpreterEnvironment.java @@ -6,6 +6,7 @@ import lombok.Getter; import lombok.Setter; +import java.util.ArrayList; import java.util.ListIterator; import java.util.Stack; @@ -24,7 +25,7 @@ public InterpreterEnvironment(Module irModule, boolean doTracing) { public void interpret() { // Search for main function - Function mainFunction = irModule.getFunction("main"); + Function mainFunction = irModule.getFunction("main", new ArrayList<>()); if (mainFunction == null) throw new RuntimeException("No main function found in module " + irModule.getName()); diff --git a/src/test/java/com/auberer/compilerdesignlectureproject/codegen/ModuleTest.java b/src/test/java/com/auberer/compilerdesignlectureproject/codegen/ModuleTest.java index c379d34..70e65d5 100644 --- a/src/test/java/com/auberer/compilerdesignlectureproject/codegen/ModuleTest.java +++ b/src/test/java/com/auberer/compilerdesignlectureproject/codegen/ModuleTest.java @@ -29,7 +29,16 @@ func empty main() StringBuilder sb = new StringBuilder(); module.dumpIR(sb); - assertEquals("module test.tinf:", sb.toString()); + String expectedOutput = """ +module test.tinf: + +function main(): { +fctDef: + return +} + +"""; + assertEquals(expectedOutput, sb.toString()); } static Module compileModule(String input) { diff --git a/src/test/java/com/auberer/compilerdesignlectureproject/codegen/WhileLoopTest.java b/src/test/java/com/auberer/compilerdesignlectureproject/codegen/WhileLoopTest.java index 38c8b62..505250d 100644 --- a/src/test/java/com/auberer/compilerdesignlectureproject/codegen/WhileLoopTest.java +++ b/src/test/java/com/auberer/compilerdesignlectureproject/codegen/WhileLoopTest.java @@ -7,6 +7,8 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import java.util.ArrayList; + import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -34,7 +36,7 @@ void testWhileLoopIntegratedTypeCheckerCorrectInput() { assertTrue(irGenerator.getCurrentBlock().getLabel().equals("while.exit")); StringBuilder sb = new StringBuilder(); - Function function = new Function("whileLoop"); + Function function = new Function("whileLoop", new ArrayList<>()); function.setEntryBlock(basicBlock); function.dumpIR(sb); String irCode = sb.toString(); diff --git a/src/test/java/com/auberer/compilerdesignlectureproject/parser/DoWhileLoopNodeTest.java b/src/test/java/com/auberer/compilerdesignlectureproject/parser/DoWhileLoopNodeTest.java index 0c84223..f19885d 100644 --- a/src/test/java/com/auberer/compilerdesignlectureproject/parser/DoWhileLoopNodeTest.java +++ b/src/test/java/com/auberer/compilerdesignlectureproject/parser/DoWhileLoopNodeTest.java @@ -16,6 +16,8 @@ import org.mockito.MockitoAnnotations; import org.mockito.Spy; +import java.util.ArrayList; + import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.mockito.Mockito.*; @@ -142,12 +144,12 @@ void testIRGeneration() { assert endBlock.getLabel().equals("do_while.exit"); StringBuilder stringBuilder = new StringBuilder(); - Function function = new Function("test"); + Function function = new Function("test", new ArrayList<>()); function.setEntryBlock(entryBlock); function.dumpIR(stringBuilder); String irCode = stringBuilder.toString(); assert irCode.startsWith(""" - function test: { + function test(): { entry: jump do_while.body do_while.body: From e6722d97a776ee7f52e0b7dcb97efd0b0cca51c3 Mon Sep 17 00:00:00 2001 From: nils bohland Date: Mon, 10 Jun 2024 16:04:20 +0200 Subject: [PATCH 7/9] added return instruction to IRGenerator, also added a getReturn and a getBody node to logicNode --- .../ast/ASTLogicNode.java | 4 + .../ast/ASTParamNode.java | 7 +- .../codegen/IRGenerator.java | 8 +- .../sema/SymbolTableBuilder.java | 1 + .../sema/TypeChecker.java | 12 +++ .../codegen/FctCallTest.java | 45 --------- .../codegen/FctDefAndCallTest.java | 95 +++++++++++++++++++ 7 files changed, 122 insertions(+), 50 deletions(-) delete mode 100644 src/test/java/com/auberer/compilerdesignlectureproject/codegen/FctCallTest.java create mode 100644 src/test/java/com/auberer/compilerdesignlectureproject/codegen/FctDefAndCallTest.java diff --git a/src/main/java/com/auberer/compilerdesignlectureproject/ast/ASTLogicNode.java b/src/main/java/com/auberer/compilerdesignlectureproject/ast/ASTLogicNode.java index 6140bf8..317616a 100644 --- a/src/main/java/com/auberer/compilerdesignlectureproject/ast/ASTLogicNode.java +++ b/src/main/java/com/auberer/compilerdesignlectureproject/ast/ASTLogicNode.java @@ -5,6 +5,7 @@ import java.util.Set; public class ASTLogicNode extends ASTNode { + @Override public T accept(ASTVisitor visitor) { return visitor.visitLogic(this); @@ -21,6 +22,9 @@ public ASTLogicalExprNode getReturnNode() { return getChild(ASTLogicalExprNode.class, 0); } + public boolean hasReturn(){ + return getReturnNode() != null; + } public ASTStmtLstNode getBody() { return getChild(ASTStmtLstNode.class, 0); } diff --git a/src/main/java/com/auberer/compilerdesignlectureproject/ast/ASTParamNode.java b/src/main/java/com/auberer/compilerdesignlectureproject/ast/ASTParamNode.java index def2f53..461d20d 100644 --- a/src/main/java/com/auberer/compilerdesignlectureproject/ast/ASTParamNode.java +++ b/src/main/java/com/auberer/compilerdesignlectureproject/ast/ASTParamNode.java @@ -1,16 +1,19 @@ package com.auberer.compilerdesignlectureproject.ast; import com.auberer.compilerdesignlectureproject.lexer.TokenType; +import com.auberer.compilerdesignlectureproject.sema.SymbolTableEntry; import lombok.Getter; import lombok.Setter; import java.util.Set; +@Getter +@Setter public class ASTParamNode extends ASTNode{ - @Getter - @Setter + private String name; + private SymbolTableEntry symbol; public static Set getSelectionSet() { return ASTTypeNode.getSelectionSet(); diff --git a/src/main/java/com/auberer/compilerdesignlectureproject/codegen/IRGenerator.java b/src/main/java/com/auberer/compilerdesignlectureproject/codegen/IRGenerator.java index 1d06732..d7da9b7 100644 --- a/src/main/java/com/auberer/compilerdesignlectureproject/codegen/IRGenerator.java +++ b/src/main/java/com/auberer/compilerdesignlectureproject/codegen/IRGenerator.java @@ -165,8 +165,11 @@ private boolean isBlockTerminated(BasicBlock block) { @Override public IRExprResult visitFctCall(ASTFctCallNode node) { + //BasicBlock basicBlock = new BasicBlock("fctCall"); + //switchToBlock(basicBlock); CallInstruction callInstruction = new CallInstruction(node, module.getFunction(node.getName(), node.getCallParams().getParamsAsLogicNodes().stream().map(ASTNode::getType).toList()), node.getCallParams()); pushToCurrentBlock(callInstruction); + //currentBlock = null; return new IRExprResult(node.getValue(), node, null); } @@ -204,10 +207,9 @@ public IRExprResult visitParamLst(ASTParamLstNode node){ @Override public IRExprResult visitParam(ASTParamNode node){ - IRExprResult datatype = visitType(node.getDataType()); - AllocaInstruction allocaInstruction = new AllocaInstruction(node, datatype.getEntry()); + AllocaInstruction allocaInstruction = new AllocaInstruction(node, node.getSymbol()); pushToCurrentBlock(allocaInstruction); - StoreInstruction storeParam = new StoreInstruction(node, datatype.getEntry()); + StoreInstruction storeParam = new StoreInstruction(node, node.getSymbol()); pushToCurrentBlock(storeParam); return new IRExprResult(null, node, null); } diff --git a/src/main/java/com/auberer/compilerdesignlectureproject/sema/SymbolTableBuilder.java b/src/main/java/com/auberer/compilerdesignlectureproject/sema/SymbolTableBuilder.java index d03d7de..dfda896 100644 --- a/src/main/java/com/auberer/compilerdesignlectureproject/sema/SymbolTableBuilder.java +++ b/src/main/java/com/auberer/compilerdesignlectureproject/sema/SymbolTableBuilder.java @@ -194,6 +194,7 @@ public Void visitParam(ASTParamNode node) { throw new SemaError(node, "Parameter name already in use"); } else { currentScopes.peek().insertSymbol(node.getName(), node); + node.setSymbol(new SymbolTableEntry(currentScopes.peek(), node.getName(), node)); } return null; } diff --git a/src/main/java/com/auberer/compilerdesignlectureproject/sema/TypeChecker.java b/src/main/java/com/auberer/compilerdesignlectureproject/sema/TypeChecker.java index 0e63421..02e9706 100644 --- a/src/main/java/com/auberer/compilerdesignlectureproject/sema/TypeChecker.java +++ b/src/main/java/com/auberer/compilerdesignlectureproject/sema/TypeChecker.java @@ -309,9 +309,21 @@ public ExprResult visitFctDef(ASTFctDefNode node) { node.setEvaluatedSymbolType(type.getType()); entryNode.defineFunction(new FunctionDef(node)); Type resultType = new Type(SuperType.TY_FUNCTION); + visitLogic(node.getBody()); + return new ExprResult(node.setEvaluatedSymbolType(resultType)); } + @Override + public ExprResult visitLogic(ASTLogicNode node) { + visitStmtLst(node.getBody()); + if (node.hasReturn()) + visitLogicalExpr(node.getReturnNode()); + + + return new ExprResult(new Type(SuperType.TY_INVALID)); + } + @Override public ExprResult visitFctCall(ASTFctCallNode node) { diff --git a/src/test/java/com/auberer/compilerdesignlectureproject/codegen/FctCallTest.java b/src/test/java/com/auberer/compilerdesignlectureproject/codegen/FctCallTest.java deleted file mode 100644 index 523bf81..0000000 --- a/src/test/java/com/auberer/compilerdesignlectureproject/codegen/FctCallTest.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.auberer.compilerdesignlectureproject.codegen; - -import com.auberer.compilerdesignlectureproject.ast.*; -import com.auberer.compilerdesignlectureproject.lexer.Lexer; -import com.auberer.compilerdesignlectureproject.parser.Parser; -import com.auberer.compilerdesignlectureproject.reader.Reader; -import com.auberer.compilerdesignlectureproject.sema.SymbolTableBuilder; -import com.auberer.compilerdesignlectureproject.sema.TypeChecker; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - -public class FctCallTest { - - @Test - @DisplayName("Integration test for function call") - void testIntegrationTestForFunctionCall() { - String fctDef = """ - func int myFunc(int x) - int i = 17; - return x; - cnuf - - func int fn2() - call myFunc(7); - return 2; - cnuf - """; - - Reader reader = new Reader(fctDef); - Lexer lexer = new Lexer(reader, false); - Parser parser = new Parser(lexer); - - ASTEntryNode parseNode = parser.parse(); - - ASTFctDefNode defNode = parseNode.getChild(ASTFctDefNode.class, 0); - ASTFctDefNode defWithCallNode = parseNode.getChild(ASTFctDefNode.class, 1); - - ASTFctCallNode callNode = defWithCallNode.getChild(ASTLogicNode.class, 0).getChild(ASTStmtLstNode.class, 0).getChild(ASTStmtNode.class, 0).getChild(ASTAssignStmtNode.class, 0).getChild(ASTLogicalExprNode.class, 0).getChild(ASTCompareExprNode.class, 0).getChild(ASTAdditiveExprNode.class, 0).getChild(ASTMultiplicativeExprNode.class, 0).getChild(ASTPrefixExprNode.class, 0).getChild(ASTAtomicExprNode.class, 0).getFctCall(); - - /*IRGenerator generator = new IRGenerator(""); - generator.visitFctDef(defNode); - generator.visitFctCall(callNode); - */ - } -} diff --git a/src/test/java/com/auberer/compilerdesignlectureproject/codegen/FctDefAndCallTest.java b/src/test/java/com/auberer/compilerdesignlectureproject/codegen/FctDefAndCallTest.java new file mode 100644 index 0000000..463a8e9 --- /dev/null +++ b/src/test/java/com/auberer/compilerdesignlectureproject/codegen/FctDefAndCallTest.java @@ -0,0 +1,95 @@ +package com.auberer.compilerdesignlectureproject.codegen; + +import com.auberer.compilerdesignlectureproject.ast.*; +import com.auberer.compilerdesignlectureproject.lexer.Lexer; +import com.auberer.compilerdesignlectureproject.parser.Parser; +import com.auberer.compilerdesignlectureproject.reader.Reader; +import com.auberer.compilerdesignlectureproject.sema.SymbolTableBuilder; +import com.auberer.compilerdesignlectureproject.sema.TypeChecker; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import javax.swing.*; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class FctDefAndCallTest { + + @Test + @DisplayName("Integration test for function call") + void testIntegrationTestForFunctionCall() { + String fctDef = """ + + func int myFunc(int x) + int i = 17; + return x; + cnuf + + func int fn2() + call myFunc(7); + return 2; + cnuf + + """; + + Reader reader = new Reader(fctDef); + Lexer lexer = new Lexer(reader, false); + Parser parser = new Parser(lexer); + + ASTEntryNode parseNode = parser.parse(); + + + ASTFctDefNode defNode = parseNode.getChild(ASTFctDefNode.class, 0); + ASTFctDefNode defWithCallNode = parseNode.getChild(ASTFctDefNode.class, 1); + + ASTFctCallNode callNode = defWithCallNode.getChild(ASTLogicNode.class, 0).getChild(ASTStmtLstNode.class, 0).getChild(ASTStmtNode.class, 0).getChild(ASTAssignStmtNode.class, 0).getChild(ASTLogicalExprNode.class, 0).getChild(ASTCompareExprNode.class, 0).getChild(ASTAdditiveExprNode.class, 0).getChild(ASTMultiplicativeExprNode.class, 0).getChild(ASTPrefixExprNode.class, 0).getChild(ASTAtomicExprNode.class, 0).getFctCall(); + + // Build symbol table + + SymbolTableBuilder symbolTableBuilder = new SymbolTableBuilder(); + symbolTableBuilder.visitFctDef(defNode); + symbolTableBuilder.visitFctDef(defWithCallNode); + + // Perform type checking + TypeChecker typeChecker = new TypeChecker(parseNode); + typeChecker.visitFctDef(defNode); + typeChecker.visitFctDef(defWithCallNode); + + + //definition of IRGenerator + String moduleName = "test.tinf"; + IRGenerator defGenerator = new IRGenerator(moduleName); + + + + + //fct def visit + defGenerator.visitFctDef(defNode); + defGenerator.visitFctDef(defWithCallNode); + + //fct Def codegen + StringBuilder defBuilder = new StringBuilder(); + defGenerator.getModule().dumpIR(defBuilder); + String irCode = defBuilder.toString(); + + + //fctDef Check + assertTrue(irCode.contains("function myFunc(TY_INT x)")); + assertTrue(irCode.contains("alloca x")); + assertTrue(irCode.contains("store x")); + assertTrue(irCode.contains("return")); + + // + + + IRGenerator callGenerator = new IRGenerator(moduleName); + callGenerator.visitFctCall(callNode); + StringBuilder callBuilder = new StringBuilder(); + defGenerator.getModule().dumpIR(callBuilder); + irCode = defBuilder.toString(); + System.out.println(irCode); + + + + } +} From cd7b59985572763929cf6be6f77ffc304116d635 Mon Sep 17 00:00:00 2001 From: nils bohland Date: Mon, 10 Jun 2024 16:11:29 +0200 Subject: [PATCH 8/9] added return instruction to IRGenerator, also added a getReturn and a getBody node to logicNode --- .../codegen/FctDefAndCallTest.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/test/java/com/auberer/compilerdesignlectureproject/codegen/FctDefAndCallTest.java b/src/test/java/com/auberer/compilerdesignlectureproject/codegen/FctDefAndCallTest.java index 463a8e9..a83a147 100644 --- a/src/test/java/com/auberer/compilerdesignlectureproject/codegen/FctDefAndCallTest.java +++ b/src/test/java/com/auberer/compilerdesignlectureproject/codegen/FctDefAndCallTest.java @@ -25,9 +25,9 @@ func int myFunc(int x) return x; cnuf - func int fn2() + func empty main() call myFunc(7); - return 2; + return; cnuf """; @@ -47,13 +47,11 @@ func int fn2() // Build symbol table SymbolTableBuilder symbolTableBuilder = new SymbolTableBuilder(); - symbolTableBuilder.visitFctDef(defNode); - symbolTableBuilder.visitFctDef(defWithCallNode); + symbolTableBuilder.visit(parseNode); // Perform type checking TypeChecker typeChecker = new TypeChecker(parseNode); - typeChecker.visitFctDef(defNode); - typeChecker.visitFctDef(defWithCallNode); + typeChecker.visit(parseNode); //definition of IRGenerator From a09f2d44d670cb7206eb37ee3de28a25f82b8b18 Mon Sep 17 00:00:00 2001 From: nils bohland Date: Wed, 12 Jun 2024 12:54:07 +0200 Subject: [PATCH 9/9] added return instruction to IRGenerator, also added a getReturn and a getBody node to logicNode --- .../compilerdesignlectureproject/ast/ASTNode.java | 9 ++++++++- .../codegen/Function.java | 7 ++++--- .../codegen/IRGenerator.java | 3 --- .../codegen/instructions/CallInstruction.java | 5 ++++- .../codegen/FctDefAndCallTest.java | 15 +++++++++------ 5 files changed, 25 insertions(+), 14 deletions(-) diff --git a/src/main/java/com/auberer/compilerdesignlectureproject/ast/ASTNode.java b/src/main/java/com/auberer/compilerdesignlectureproject/ast/ASTNode.java index 232e8fb..c4a393a 100644 --- a/src/main/java/com/auberer/compilerdesignlectureproject/ast/ASTNode.java +++ b/src/main/java/com/auberer/compilerdesignlectureproject/ast/ASTNode.java @@ -5,12 +5,15 @@ import com.auberer.compilerdesignlectureproject.sema.SuperType; import com.auberer.compilerdesignlectureproject.sema.Type; import lombok.Data; +import lombok.Getter; +import lombok.Setter; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; -@Data +@Getter +@Setter public abstract class ASTNode implements IVisitable { public void addChild(ASTNode child) { @@ -34,6 +37,10 @@ public Type setEvaluatedSymbolType(Type type) { return type; } + public String toString(){ + return ""; + } + ASTNode parent; List children = new ArrayList<>(); CodeLoc codeLoc; diff --git a/src/main/java/com/auberer/compilerdesignlectureproject/codegen/Function.java b/src/main/java/com/auberer/compilerdesignlectureproject/codegen/Function.java index 411670b..22e6292 100644 --- a/src/main/java/com/auberer/compilerdesignlectureproject/codegen/Function.java +++ b/src/main/java/com/auberer/compilerdesignlectureproject/codegen/Function.java @@ -6,6 +6,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.stream.Collectors; @Getter public class Function implements IDumpable { @@ -28,9 +29,9 @@ public void setEntryBlock(BasicBlock entryBlock) { public void dumpIR(StringBuilder sb) { sb.append("function ").append(name). append("("); - for (Parameter parameter : parameters) { - sb.append(parameter.getType()).append(" ").append(parameter.getName()); - } + String params = parameters.stream().map(parameter -> parameter.getType() + " " + parameter.getName()).collect(Collectors.joining(",")); + + sb.append(params); sb.append(")"); sb.append(": {\n"); List dumpedBlocks = new ArrayList<>(); diff --git a/src/main/java/com/auberer/compilerdesignlectureproject/codegen/IRGenerator.java b/src/main/java/com/auberer/compilerdesignlectureproject/codegen/IRGenerator.java index d7da9b7..52479c8 100644 --- a/src/main/java/com/auberer/compilerdesignlectureproject/codegen/IRGenerator.java +++ b/src/main/java/com/auberer/compilerdesignlectureproject/codegen/IRGenerator.java @@ -165,11 +165,8 @@ private boolean isBlockTerminated(BasicBlock block) { @Override public IRExprResult visitFctCall(ASTFctCallNode node) { - //BasicBlock basicBlock = new BasicBlock("fctCall"); - //switchToBlock(basicBlock); CallInstruction callInstruction = new CallInstruction(node, module.getFunction(node.getName(), node.getCallParams().getParamsAsLogicNodes().stream().map(ASTNode::getType).toList()), node.getCallParams()); pushToCurrentBlock(callInstruction); - //currentBlock = null; return new IRExprResult(node.getValue(), node, null); } diff --git a/src/main/java/com/auberer/compilerdesignlectureproject/codegen/instructions/CallInstruction.java b/src/main/java/com/auberer/compilerdesignlectureproject/codegen/instructions/CallInstruction.java index dc32bf6..4a453a8 100644 --- a/src/main/java/com/auberer/compilerdesignlectureproject/codegen/instructions/CallInstruction.java +++ b/src/main/java/com/auberer/compilerdesignlectureproject/codegen/instructions/CallInstruction.java @@ -7,6 +7,7 @@ import lombok.Getter; import java.util.ListIterator; +import java.util.stream.Collectors; @Getter public class CallInstruction extends Instruction { @@ -30,7 +31,9 @@ public void run(InterpreterEnvironment env) { @Override public void dumpIR(StringBuilder sb) { // call () - sb.append("call ").append(function.getName()).append("(").append(callParamsNode.getParamsAsLogicNodes()).append(")"); + sb.append("call ").append(function.getName()).append("("); + String params = callParamsNode.getParamsAsLogicNodes().stream().map(astLogicalExprNode -> astLogicalExprNode.getValue().getName()).collect(Collectors.joining(",")); + sb.append(params).append(")"); } @Override diff --git a/src/test/java/com/auberer/compilerdesignlectureproject/codegen/FctDefAndCallTest.java b/src/test/java/com/auberer/compilerdesignlectureproject/codegen/FctDefAndCallTest.java index a83a147..fff2337 100644 --- a/src/test/java/com/auberer/compilerdesignlectureproject/codegen/FctDefAndCallTest.java +++ b/src/test/java/com/auberer/compilerdesignlectureproject/codegen/FctDefAndCallTest.java @@ -20,13 +20,13 @@ public class FctDefAndCallTest { void testIntegrationTestForFunctionCall() { String fctDef = """ - func int myFunc(int x) + func int myFunc(int x, int y) int i = 17; return x; cnuf func empty main() - call myFunc(7); + call myFunc(7, 8); return; cnuf @@ -47,11 +47,13 @@ func empty main() // Build symbol table SymbolTableBuilder symbolTableBuilder = new SymbolTableBuilder(); - symbolTableBuilder.visit(parseNode); + symbolTableBuilder.visitFctDef(defNode); + symbolTableBuilder.visitFctDef(defWithCallNode); // Perform type checking TypeChecker typeChecker = new TypeChecker(parseNode); - typeChecker.visit(parseNode); + typeChecker.visitFctDef(defNode); + typeChecker.visitFctCall(callNode); //definition of IRGenerator @@ -72,7 +74,7 @@ func empty main() //fctDef Check - assertTrue(irCode.contains("function myFunc(TY_INT x)")); + assertTrue(irCode.contains("function myFunc(TY_INT x,TY_INT y)")); assertTrue(irCode.contains("alloca x")); assertTrue(irCode.contains("store x")); assertTrue(irCode.contains("return")); @@ -81,7 +83,8 @@ func empty main() IRGenerator callGenerator = new IRGenerator(moduleName); - callGenerator.visitFctCall(callNode); + callGenerator.visit(parseNode); + //callGenerator.visitFctCall(callNode); StringBuilder callBuilder = new StringBuilder(); defGenerator.getModule().dumpIR(callBuilder); irCode = defBuilder.toString();