diff --git a/makefile b/makefile index 7c3ab16..0411731 100644 --- a/makefile +++ b/makefile @@ -18,7 +18,7 @@ runTest: ./src/test/test ./src/test/test ./src/test/test: ./src/test/tests.s - gcc -o ./src/test/test ./src/test/tests.s ./src/test/functionCall/functionCall.c ./src/test/while/while.c ./src/test/recursive/recursive.c ./src/test/comparison/comparison.c ./src/test/testCode.c + gcc -o ./src/test/test ./src/test/tests.s ./src/test/functionCall/functionCall.c ./src/test/loop/loop.c ./src/test/recursive/recursive.c ./src/test/comparison/comparison.c ./src/test/testCode.c ./src/test/tests.s: target/klang-1.0-jar-with-dependencies.jar java -cp target/klang-1.0-jar-with-dependencies.jar de.hsrm.compiler.Klang.Klang < ./src/test/tests.k > ./src/test/tests.s diff --git a/src/main/antlr4/de/hsrm/compiler/Klang/Klang.g4 b/src/main/antlr4/de/hsrm/compiler/Klang/Klang.g4 index a670088..6e068b2 100644 --- a/src/main/antlr4/de/hsrm/compiler/Klang/Klang.g4 +++ b/src/main/antlr4/de/hsrm/compiler/Klang/Klang.g4 @@ -27,6 +27,7 @@ statement | variable_assignment | return_statement | whileLoop + | doWhileLoop ; print @@ -84,6 +85,10 @@ whileLoop : WHILE OPAR cond = expression CPAR braced_block ; +doWhileLoop + : DO braced_block WHILE OPAR cond = expression CPAR SCOL + ; + PRINT: 'print'; IF: 'if'; ELSE: 'else'; @@ -91,6 +96,7 @@ FUNC: 'function'; RETURN: 'return'; LET: 'let'; WHILE: 'while'; +DO: 'do'; SCOL: ';'; OBRK: '{'; diff --git a/src/main/java/de/hsrm/compiler/Klang/ContextAnalysis.java b/src/main/java/de/hsrm/compiler/Klang/ContextAnalysis.java index 11af808..1868667 100644 --- a/src/main/java/de/hsrm/compiler/Klang/ContextAnalysis.java +++ b/src/main/java/de/hsrm/compiler/Klang/ContextAnalysis.java @@ -5,6 +5,7 @@ import java.util.HashSet; import de.hsrm.compiler.Klang.nodes.*; import de.hsrm.compiler.Klang.nodes.expressions.*; +import de.hsrm.compiler.Klang.nodes.loops.doWhileLoop; import de.hsrm.compiler.Klang.nodes.loops.whileLoop; import de.hsrm.compiler.Klang.nodes.statements.*; import de.hsrm.compiler.Klang.types.Type; @@ -65,6 +66,13 @@ public class ContextAnalysis extends KlangBaseVisitor { return new whileLoop((Expression) condition, (Block) block); } + @Override + public Node visitDoWhileLoop(KlangParser.DoWhileLoopContext ctx) { + Node condition = this.visit(ctx.cond); + Node block = this.visit(ctx.braced_block()); + return new doWhileLoop((Expression) condition, (Block) block); + } + @Override public Node visitVariable_declaration(KlangParser.Variable_declarationContext ctx) { diff --git a/src/main/java/de/hsrm/compiler/Klang/nodes/loops/doWhileLoop.java b/src/main/java/de/hsrm/compiler/Klang/nodes/loops/doWhileLoop.java new file mode 100644 index 0000000..f5f8d1d --- /dev/null +++ b/src/main/java/de/hsrm/compiler/Klang/nodes/loops/doWhileLoop.java @@ -0,0 +1,24 @@ +package de.hsrm.compiler.Klang.nodes.loops; + +import de.hsrm.compiler.Klang.nodes.Block; +import de.hsrm.compiler.Klang.nodes.statements.Statement;; +import de.hsrm.compiler.Klang.nodes.expressions.Expression; +import de.hsrm.compiler.Klang.visitors.Visitor; + +public class doWhileLoop extends Statement { + + public Expression cond; + public Block block; + public Block alt; + + public doWhileLoop(Expression cond, Block block) { + this.cond = cond; + this.block = block; + } + + @Override + public R welcome(Visitor v) { + return v.visit(this); + } + +} \ No newline at end of file diff --git a/src/main/java/de/hsrm/compiler/Klang/visitors/EvalVisitor.java b/src/main/java/de/hsrm/compiler/Klang/visitors/EvalVisitor.java index eceb805..777b923 100644 --- a/src/main/java/de/hsrm/compiler/Klang/visitors/EvalVisitor.java +++ b/src/main/java/de/hsrm/compiler/Klang/visitors/EvalVisitor.java @@ -8,6 +8,7 @@ import de.hsrm.compiler.Klang.nodes.Block; import de.hsrm.compiler.Klang.nodes.FunctionDefinition; import de.hsrm.compiler.Klang.nodes.Program; import de.hsrm.compiler.Klang.nodes.expressions.*; +import de.hsrm.compiler.Klang.nodes.loops.doWhileLoop; import de.hsrm.compiler.Klang.nodes.loops.whileLoop; import de.hsrm.compiler.Klang.nodes.statements.*; @@ -156,14 +157,24 @@ public class EvalVisitor implements Visitor { public Value visit(whileLoop e) { Value condition = e.cond.welcome(this); Value result = null; - while(condition.asInteger() != 0) { - System.out.println(condition.asInteger()); + while (condition.asInteger() != 0) { result = e.block.welcome(this); } - + return result; } - + + @Override + public Value visit(doWhileLoop e) { + Value condition = e.cond.welcome(this); + Value result = null; + do { + result = e.block.welcome(this); + } while (condition.asInteger() != 0); + + return result; + } + @Override public Value visit(PrintStatement e) { Value value = e.expression.welcome(this); diff --git a/src/main/java/de/hsrm/compiler/Klang/visitors/GenASM.java b/src/main/java/de/hsrm/compiler/Klang/visitors/GenASM.java index e44ce3a..68cee1e 100644 --- a/src/main/java/de/hsrm/compiler/Klang/visitors/GenASM.java +++ b/src/main/java/de/hsrm/compiler/Klang/visitors/GenASM.java @@ -8,6 +8,7 @@ import java.util.TreeSet; import de.hsrm.compiler.Klang.nodes.*; import de.hsrm.compiler.Klang.nodes.expressions.*; +import de.hsrm.compiler.Klang.nodes.loops.doWhileLoop; import de.hsrm.compiler.Klang.nodes.loops.whileLoop; import de.hsrm.compiler.Klang.nodes.statements.*; @@ -305,6 +306,18 @@ public class GenASM implements Visitor { return null; } + + @Override + public Void visit(doWhileLoop e) { + int lblStart = ++lCount; + this.ex.write(".L" + lblStart + ":\n"); + e.block.welcome(this); + e.cond.welcome(this); + this.ex.write(" cmp $0, %rax\n"); + this.ex.write(" jnz .L" + lblStart + "\n"); + return null; + } + @Override public Void visit(PrintStatement e) { throw new RuntimeException("Das machen wir mal nicht, ne?!"); diff --git a/src/main/java/de/hsrm/compiler/Klang/visitors/GetVars.java b/src/main/java/de/hsrm/compiler/Klang/visitors/GetVars.java index 6f41e46..98f1503 100644 --- a/src/main/java/de/hsrm/compiler/Klang/visitors/GetVars.java +++ b/src/main/java/de/hsrm/compiler/Klang/visitors/GetVars.java @@ -4,6 +4,7 @@ import java.util.Set; import de.hsrm.compiler.Klang.nodes.*; import de.hsrm.compiler.Klang.nodes.expressions.*; +import de.hsrm.compiler.Klang.nodes.loops.doWhileLoop; import de.hsrm.compiler.Klang.nodes.loops.whileLoop; import de.hsrm.compiler.Klang.nodes.statements.*; @@ -127,6 +128,13 @@ class GetVars implements Visitor { return null; } + @Override + public Void visit(doWhileLoop e) { + e.cond.welcome(this); + e.block.welcome(this); + return null; + } + @Override public Void visit(PrintStatement e) { e.expression.welcome(this); diff --git a/src/main/java/de/hsrm/compiler/Klang/visitors/PrettyPrintVisitor.java b/src/main/java/de/hsrm/compiler/Klang/visitors/PrettyPrintVisitor.java index 9a7976e..bdc23ca 100644 --- a/src/main/java/de/hsrm/compiler/Klang/visitors/PrettyPrintVisitor.java +++ b/src/main/java/de/hsrm/compiler/Klang/visitors/PrettyPrintVisitor.java @@ -3,7 +3,7 @@ package de.hsrm.compiler.Klang.visitors; import java.io.*; import de.hsrm.compiler.Klang.nodes.*; import de.hsrm.compiler.Klang.nodes.expressions.*; -import de.hsrm.compiler.Klang.nodes.loops.whileLoop; +import de.hsrm.compiler.Klang.nodes.loops.*; import de.hsrm.compiler.Klang.nodes.statements.*; public class PrettyPrintVisitor implements Visitor { @@ -214,6 +214,16 @@ public class PrettyPrintVisitor implements Visitor { return null; } + @Override + public Void visit(doWhileLoop e) { + ex.write("do "); + e.block.welcome(this); + ex.write(" while ("); + e.cond.welcome(this); + ex.write(");"); + return null; + } + @Override public Void visit(PrintStatement e) { ex.write("print "); diff --git a/src/main/java/de/hsrm/compiler/Klang/visitors/Visitor.java b/src/main/java/de/hsrm/compiler/Klang/visitors/Visitor.java index c062d2a..a25a265 100644 --- a/src/main/java/de/hsrm/compiler/Klang/visitors/Visitor.java +++ b/src/main/java/de/hsrm/compiler/Klang/visitors/Visitor.java @@ -24,6 +24,7 @@ public interface Visitor { R visit(NegateExpression e); R visit(IfStatement e); R visit(whileLoop e); + R visit(doWhileLoop e); R visit(PrintStatement e); R visit(VariableDeclaration e); R visit(VariableAssignment e); diff --git a/src/test/loop/loop.c b/src/test/loop/loop.c new file mode 100644 index 0000000..b02eb38 --- /dev/null +++ b/src/test/loop/loop.c @@ -0,0 +1,30 @@ +#include +#include "loop.h" + +void printLoopSuccess(char* name, int x, int expected, int result) { + printf("SUCCESS:\t%s(%d)\tGOT: %d\tExpected: %d\n", name, x, result, expected); +} + +void printLoopError(char* name, int x, int expected, int result) { + printf("ERROR:\t\t%s(%d)\tGOT: %d\tExpected: %d\n", name, x, result, expected); +} + +int loopTest(char* name, int x, int expected, int result) { + if (expected == result) { + printLoopSuccess(name, x, expected, result); + return 0; + } else { + printLoopError(name, x, expected, result); + return 1; + } +} + +int runLoopTests() { + printf("\nLoop Tests \n"); + int failed = 0; + failed += loopTest("while", 5, 5, myWhile(5)); + failed += loopTest("doWhile", 0, 1, myDoWhile(0)); + failed += loopTest("doWhile", 1, 1, myDoWhile(1)); + + return failed; +} \ No newline at end of file diff --git a/src/test/loop/loop.h b/src/test/loop/loop.h new file mode 100644 index 0000000..bc6107c --- /dev/null +++ b/src/test/loop/loop.h @@ -0,0 +1,2 @@ +int myWhile(int x); +int myDoWhile(int x); \ No newline at end of file diff --git a/src/test/testCode.c b/src/test/testCode.c index 9a4f29d..ee19542 100644 --- a/src/test/testCode.c +++ b/src/test/testCode.c @@ -125,7 +125,7 @@ int main(){ failed += runComparisonTests(); // Tests for while loop - failed += runWhileTests(); + failed += runLoopTests(); printf("\n=== Failed Tests: %d\n", failed); diff --git a/src/test/tests.h b/src/test/tests.h index a8c9a1b..735466d 100644 --- a/src/test/tests.h +++ b/src/test/tests.h @@ -5,4 +5,4 @@ int runFunctionCallTests(); int runRecursiveTests(); int runComparisonTests(); -int runWhileTests(); \ No newline at end of file +int runLoopTests(); \ No newline at end of file diff --git a/src/test/tests.k b/src/test/tests.k index aaf7e91..9186df4 100644 --- a/src/test/tests.k +++ b/src/test/tests.k @@ -146,4 +146,12 @@ function myWhile(end) { return cond; } +function myDoWhile(end) { + let cond = 0; + do { + cond = (cond + 1); + } while((cond < end)); + return cond; +} + add(1, 1); diff --git a/src/test/while/while.c b/src/test/while/while.c deleted file mode 100644 index a44d065..0000000 --- a/src/test/while/while.c +++ /dev/null @@ -1,27 +0,0 @@ -#include -#include "while.h" - -void printWhileSuccess(char* name, int x, int expected, int result) { - printf("SUCCESS:\t%s(%d)\tGOT: %d\tExpected: %d\n", name, x, result, expected); -} - -void printWhileError(char* name, int x, int expected, int result) { - printf("ERROR:\t\t%s(%d)\tGOT: %d\tExpected: %d\n", name, x, result, expected); -} - -int whileTest(char* name, int x, int expected, int result) { - if (expected == result) { - printWhileSuccess(name, x, expected, result); - return 0; - } else { - printWhileError(name, x, expected, result); - return 1; - } -} - -int runWhileTests() { - printf("\nWhile Tests \n"); - int failed = 0; - failed += whileTest("while", 5, 5, myWhile(5)); - return failed; -} \ No newline at end of file diff --git a/src/test/while/while.h b/src/test/while/while.h deleted file mode 100644 index 940c076..0000000 --- a/src/test/while/while.h +++ /dev/null @@ -1 +0,0 @@ -int myWhile(int x); \ No newline at end of file