From 1186bb455074f272951ae0e9ed880b831d25b8e5 Mon Sep 17 00:00:00 2001 From: nitrix Date: Mon, 20 Jan 2020 15:26:55 +0100 Subject: [PATCH 1/5] add bool literal --- .../antlr4/de/hsrm/compiler/Klang/Klang.g4 | 8 +++++++- .../hsrm/compiler/Klang/ContextAnalysis.java | 7 +++++++ .../java/de/hsrm/compiler/Klang/Value.java | 4 ++++ .../nodes/expressions/BooleanExpression.java | 16 +++++++++++++++ .../compiler/Klang/types/BooleanType.java | 20 +++++++++++++++++++ .../compiler/Klang/types/PrimitiveType.java | 4 ++++ .../de/hsrm/compiler/Klang/types/Type.java | 4 ++++ .../compiler/Klang/visitors/EvalVisitor.java | 5 +++++ .../hsrm/compiler/Klang/visitors/GenASM.java | 12 ++++++++--- .../hsrm/compiler/Klang/visitors/GetVars.java | 5 +++++ .../Klang/visitors/PrettyPrintVisitor.java | 6 ++++++ .../hsrm/compiler/Klang/visitors/Visitor.java | 1 + 12 files changed, 88 insertions(+), 4 deletions(-) create mode 100644 src/main/java/de/hsrm/compiler/Klang/nodes/expressions/BooleanExpression.java create mode 100644 src/main/java/de/hsrm/compiler/Klang/types/BooleanType.java diff --git a/src/main/antlr4/de/hsrm/compiler/Klang/Klang.g4 b/src/main/antlr4/de/hsrm/compiler/Klang/Klang.g4 index 4d8b903..c88746e 100644 --- a/src/main/antlr4/de/hsrm/compiler/Klang/Klang.g4 +++ b/src/main/antlr4/de/hsrm/compiler/Klang/Klang.g4 @@ -78,7 +78,8 @@ expression atom : INTEGER_LITERAL #intAtom - | IDENT # variable + | BOOLEAN_LITERAL #boolAtom + | IDENT #variable ; functionCall @@ -137,6 +138,11 @@ INTEGER_LITERAL : [0-9]+ ; +BOOLEAN_LITERAL + : 'true' + | 'false' + ; + IDENT : [a-zA-Z][a-zA-Z0-9]* ; diff --git a/src/main/java/de/hsrm/compiler/Klang/ContextAnalysis.java b/src/main/java/de/hsrm/compiler/Klang/ContextAnalysis.java index 87cc448..bfb3905 100644 --- a/src/main/java/de/hsrm/compiler/Klang/ContextAnalysis.java +++ b/src/main/java/de/hsrm/compiler/Klang/ContextAnalysis.java @@ -209,6 +209,13 @@ public class ContextAnalysis extends KlangBaseVisitor { return n; } + @Override + public Node visitBoolAtom(KlangParser.BoolAtomContext ctx) { + Node n = new BooleanExpression(ctx.getText().equals("true") ? true : false); + n.type = Type.getBooleanType(); + return n; + } + @Override public Node visitFunctionDef(KlangParser.FunctionDefContext ctx) { String name = ctx.funcName.getText(); diff --git a/src/main/java/de/hsrm/compiler/Klang/Value.java b/src/main/java/de/hsrm/compiler/Klang/Value.java index ebaec1e..81c05ea 100644 --- a/src/main/java/de/hsrm/compiler/Klang/Value.java +++ b/src/main/java/de/hsrm/compiler/Klang/Value.java @@ -10,4 +10,8 @@ public class Value { public int asInteger() { return (int) this.value; } + + public boolean asBoolean() { + return (boolean) this.value; + } } diff --git a/src/main/java/de/hsrm/compiler/Klang/nodes/expressions/BooleanExpression.java b/src/main/java/de/hsrm/compiler/Klang/nodes/expressions/BooleanExpression.java new file mode 100644 index 0000000..fadb6f5 --- /dev/null +++ b/src/main/java/de/hsrm/compiler/Klang/nodes/expressions/BooleanExpression.java @@ -0,0 +1,16 @@ +package de.hsrm.compiler.Klang.nodes.expressions; + +import de.hsrm.compiler.Klang.visitors.Visitor; + +public class BooleanExpression extends Expression { + public boolean value; + + public BooleanExpression(boolean value) { + this.value = value; + } + + @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/types/BooleanType.java b/src/main/java/de/hsrm/compiler/Klang/types/BooleanType.java new file mode 100644 index 0000000..d5d1517 --- /dev/null +++ b/src/main/java/de/hsrm/compiler/Klang/types/BooleanType.java @@ -0,0 +1,20 @@ +package de.hsrm.compiler.Klang.types; + +public class BooleanType extends PrimitiveType { + + private static BooleanType instance = null; + + public static BooleanType getType() { + if (instance != null) { + return instance; + } + instance = new BooleanType(); + return instance; + } + + @Override + public boolean isBooleanType() { + return true; + } + +} \ No newline at end of file diff --git a/src/main/java/de/hsrm/compiler/Klang/types/PrimitiveType.java b/src/main/java/de/hsrm/compiler/Klang/types/PrimitiveType.java index b45c08f..3a87c7a 100644 --- a/src/main/java/de/hsrm/compiler/Klang/types/PrimitiveType.java +++ b/src/main/java/de/hsrm/compiler/Klang/types/PrimitiveType.java @@ -10,4 +10,8 @@ public abstract class PrimitiveType extends Type { public boolean isIntegerType() { return false; }; + + public boolean isBooleanType() { + return false; + }; } \ No newline at end of file diff --git a/src/main/java/de/hsrm/compiler/Klang/types/Type.java b/src/main/java/de/hsrm/compiler/Klang/types/Type.java index db90f30..bc429d7 100644 --- a/src/main/java/de/hsrm/compiler/Klang/types/Type.java +++ b/src/main/java/de/hsrm/compiler/Klang/types/Type.java @@ -8,5 +8,9 @@ public abstract class Type { return IntegerType.getType(); } + public static BooleanType getBooleanType() { + return BooleanType.getType(); + } + public abstract boolean isPrimitiveType(); } \ 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 aae571b..c34fea5 100644 --- a/src/main/java/de/hsrm/compiler/Klang/visitors/EvalVisitor.java +++ b/src/main/java/de/hsrm/compiler/Klang/visitors/EvalVisitor.java @@ -23,6 +23,11 @@ public class EvalVisitor implements Visitor { return new Value(e.value); } + @Override + public Value visit(BooleanExpression e) { + return new Value(e.value); + } + @Override public Value visit(EqualityExpression e) { Value lhs = e.lhs.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 d021f1d..6a69845 100644 --- a/src/main/java/de/hsrm/compiler/Klang/visitors/GenASM.java +++ b/src/main/java/de/hsrm/compiler/Klang/visitors/GenASM.java @@ -78,6 +78,12 @@ public class GenASM implements Visitor { return null; } + @Override + public Void visit(BooleanExpression e) { + this.ex.write(" movq $" + (e.value ? 1 : 0) + ", %rax\n"); + return null; + } + @Override public Void visit(Variable e) { this.ex.write(" movq " + this.env.get(e.name) + "(%rbp), %rax\n"); @@ -324,7 +330,7 @@ public class GenASM implements Visitor { this.ex.write(" jnz .L" + lblStart + "\n"); return null; } - + @Override public Void visit(ForLoop e) { int lblStart = ++lCount; @@ -338,7 +344,7 @@ public class GenASM implements Visitor { e.step.welcome(this); this.ex.write(" jmp .L" + lblStart + "\n"); this.ex.write(".L" + lblEnd + ":\n"); - + return null; } @@ -453,7 +459,7 @@ public class GenASM implements Visitor { this.ex.write("\n"); } this.ex.write(".globl " + mainName + "\n"); - this.ex.write(".type " +mainName + ", @function\n"); + this.ex.write(".type " + mainName + ", @function\n"); this.ex.write(mainName + ":\n"); this.ex.write(" pushq %rbp\n"); this.ex.write(" movq %rsp, %rbp\n"); 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 319b18f..8a6fa14 100644 --- a/src/main/java/de/hsrm/compiler/Klang/visitors/GetVars.java +++ b/src/main/java/de/hsrm/compiler/Klang/visitors/GetVars.java @@ -22,6 +22,11 @@ class GetVars implements Visitor { return null; } + @Override + public Void visit(BooleanExpression e) { + return null; + } + @Override public Void visit(Variable e) { return null; 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 14b9e97..ae1f364 100644 --- a/src/main/java/de/hsrm/compiler/Klang/visitors/PrettyPrintVisitor.java +++ b/src/main/java/de/hsrm/compiler/Klang/visitors/PrettyPrintVisitor.java @@ -72,6 +72,12 @@ public class PrettyPrintVisitor implements Visitor { return null; } + @Override + public Void visit(BooleanExpression e) { + ex.write(e.value); + return null; + } + @Override public Void visit(EqualityExpression e) { ex.write("("); 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 02784b5..eb7121e 100644 --- a/src/main/java/de/hsrm/compiler/Klang/visitors/Visitor.java +++ b/src/main/java/de/hsrm/compiler/Klang/visitors/Visitor.java @@ -9,6 +9,7 @@ import de.hsrm.compiler.Klang.nodes.statements.*; public interface Visitor { R visit(IntegerExpression e); + R visit(BooleanExpression e); R visit(Variable e); R visit(AdditionExpression e); R visit(EqualityExpression e); From d27df13ec10e1328a668a24b65e82b2476751469 Mon Sep 17 00:00:00 2001 From: Marvin Kaiser Date: Mon, 20 Jan 2020 16:01:25 +0100 Subject: [PATCH 2/5] added boolean operators --- .../antlr4/de/hsrm/compiler/Klang/Klang.g4 | 6 ++++++ .../hsrm/compiler/Klang/ContextAnalysis.java | 16 ++++++++++++++++ .../nodes/expressions/AndExpression.java | 14 ++++++++++++++ .../nodes/expressions/NotExpression.java | 16 ++++++++++++++++ .../Klang/nodes/expressions/OrExpression.java | 14 ++++++++++++++ .../hsrm/compiler/Klang/visitors/Visitor.java | 3 +++ src/test/comparison/comparison.c | 16 ++++++++++++++++ src/test/comparison/comparison.h | 6 ++++++ src/test/print/print.c | 19 +++++++++++++++++++ src/test/print/print.h | 5 ++++- src/test/test.k | 12 ++++++++++++ 11 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 src/main/java/de/hsrm/compiler/Klang/nodes/expressions/AndExpression.java create mode 100644 src/main/java/de/hsrm/compiler/Klang/nodes/expressions/NotExpression.java create mode 100644 src/main/java/de/hsrm/compiler/Klang/nodes/expressions/OrExpression.java diff --git a/src/main/antlr4/de/hsrm/compiler/Klang/Klang.g4 b/src/main/antlr4/de/hsrm/compiler/Klang/Klang.g4 index c88746e..136d971 100644 --- a/src/main/antlr4/de/hsrm/compiler/Klang/Klang.g4 +++ b/src/main/antlr4/de/hsrm/compiler/Klang/Klang.g4 @@ -72,7 +72,10 @@ expression | OPAR lhs=expression GT rhs=expression CPAR #greaterThanExpression | OPAR lhs=expression LTE rhs=expression CPAR #lessThanOrEqualToExpression | OPAR lhs=expression GTE rhs=expression CPAR #GreaterThanOrEqualToExpression + | OPAR lhs=expression OR rhs=expression CPAR #OrExpression + | OPAR lhs=expression AND rhs=expression CPAR #AndExpression | SUB expression #negateExpression + | NOT expression #NotExpression | functionCall #functionCallExpression ; @@ -127,6 +130,9 @@ LT: '<'; GT: '>'; LTE: '<='; GTE: '>='; +OR: '||'; +AND: '&&'; +NOT: '!'; MUL: '*'; ADD: '+'; diff --git a/src/main/java/de/hsrm/compiler/Klang/ContextAnalysis.java b/src/main/java/de/hsrm/compiler/Klang/ContextAnalysis.java index bfb3905..da7cfa0 100644 --- a/src/main/java/de/hsrm/compiler/Klang/ContextAnalysis.java +++ b/src/main/java/de/hsrm/compiler/Klang/ContextAnalysis.java @@ -10,6 +10,7 @@ import de.hsrm.compiler.Klang.nodes.loops.ForLoop; import de.hsrm.compiler.Klang.nodes.loops.WhileLoop; import de.hsrm.compiler.Klang.nodes.statements.*; import de.hsrm.compiler.Klang.types.Type; +import sun.tools.tree.OrExpression; public class ContextAnalysis extends KlangBaseVisitor { Set vars = new HashSet<>(); @@ -126,6 +127,16 @@ public class ContextAnalysis extends KlangBaseVisitor { return new ReturnStatement(expression); } + @Override + public Node visitOrExpression(KlangParser.OrExpressionContext ctx) { + return new OrExpression((Expression) this.visit(ctx.lhs), (Expression) this.visit(ctx.rhs)); + } + + @Override + public Node visitAndExpression(KlangParser.AndExpressionContext ctx) { + return new AndExpression((Expression) this.visit(ctx.lhs), (Expression) this.visit(ctx.rhs)); + } + @Override public Node visitAdditionExpression(KlangParser.AdditionExpressionContext ctx) { return new AdditionExpression((Expression) this.visit(ctx.lhs), (Expression) this.visit(ctx.rhs)); @@ -186,6 +197,11 @@ public class ContextAnalysis extends KlangBaseVisitor { return new NegateExpression((Expression) this.visit(ctx.expression())); } + @Override + public Node visitNotExpression(KlangParser.NotExpressionContext ctx) { + return new NotExpression((Expression) this.visit(ctx.expression())); + } + @Override public Node visitVariable(KlangParser.VariableContext ctx) { String name = ctx.IDENT().getText(); diff --git a/src/main/java/de/hsrm/compiler/Klang/nodes/expressions/AndExpression.java b/src/main/java/de/hsrm/compiler/Klang/nodes/expressions/AndExpression.java new file mode 100644 index 0000000..523a8fe --- /dev/null +++ b/src/main/java/de/hsrm/compiler/Klang/nodes/expressions/AndExpression.java @@ -0,0 +1,14 @@ +package de.hsrm.compiler.Klang.nodes.expressions; + +import de.hsrm.compiler.Klang.visitors.Visitor; + +public class AndExpression extends BinaryExpression { + public AndExpression(Expression lhs, Expression rhs) { + super(lhs, rhs); + } + + @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/nodes/expressions/NotExpression.java b/src/main/java/de/hsrm/compiler/Klang/nodes/expressions/NotExpression.java new file mode 100644 index 0000000..f35dd29 --- /dev/null +++ b/src/main/java/de/hsrm/compiler/Klang/nodes/expressions/NotExpression.java @@ -0,0 +1,16 @@ +package de.hsrm.compiler.Klang.nodes.expressions; + +import de.hsrm.compiler.Klang.visitors.Visitor; + +public class NotExpression extends UnaryExpression { + + public NotExpression(Expression lhs) { + super(lhs); + } + + @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/nodes/expressions/OrExpression.java b/src/main/java/de/hsrm/compiler/Klang/nodes/expressions/OrExpression.java new file mode 100644 index 0000000..6514275 --- /dev/null +++ b/src/main/java/de/hsrm/compiler/Klang/nodes/expressions/OrExpression.java @@ -0,0 +1,14 @@ +package de.hsrm.compiler.Klang.nodes.expressions; + +import de.hsrm.compiler.Klang.visitors.Visitor; + +public class OrExpression extends BinaryExpression { + public OrExpression(Expression lhs, Expression rhs) { + super(lhs, rhs); + } + + @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/Visitor.java b/src/main/java/de/hsrm/compiler/Klang/visitors/Visitor.java index eb7121e..b0abb24 100644 --- a/src/main/java/de/hsrm/compiler/Klang/visitors/Visitor.java +++ b/src/main/java/de/hsrm/compiler/Klang/visitors/Visitor.java @@ -8,6 +8,9 @@ import de.hsrm.compiler.Klang.nodes.loops.*; import de.hsrm.compiler.Klang.nodes.statements.*; public interface Visitor { + R visit(OrExpression e); + R visit(AndExpression e); + R visit (NotExpression e); R visit(IntegerExpression e); R visit(BooleanExpression e); R visit(Variable e); diff --git a/src/test/comparison/comparison.c b/src/test/comparison/comparison.c index c6d12d4..e8f876f 100644 --- a/src/test/comparison/comparison.c +++ b/src/test/comparison/comparison.c @@ -1,4 +1,5 @@ #include +#include #include "comparison.h" #include "../print/print.h" @@ -12,6 +13,16 @@ int comparisonTest(char* name, int x, int y, int expected, int result) { } } +int boolTest(char* name, bool a, bool b, bool expected, bool result) { + if (expected == result) { + bool_succInfixTwo(name, a, b, expected, result); + return 0; + } else { + bool_errInfixTwo(name, a, b, expected, result); + return 1; + } +} + void runComparisonTests() { printf("\nComparison Tests \n"); comparisonTest("==", 1, 1, 1, eq(1, 1)); @@ -43,4 +54,9 @@ void runComparisonTests() { comparisonTest(">=", 1, 0, 1, gte(1, 0)); comparisonTest(">=", 0, 1, 0, gte(0, 1)); comparisonTest(">=", 0, 0, 1, gte(0, 0)); + + boolTest("&&", true, true, true, and(true, true)); + boolTest("&&", true, false, false, and(true, false)); + boolTest("&&", false, true, false, and(false, true)); + boolTest("&&", false, false, false, and(false, false)); } \ No newline at end of file diff --git a/src/test/comparison/comparison.h b/src/test/comparison/comparison.h index 9d4b35a..f5a9566 100644 --- a/src/test/comparison/comparison.h +++ b/src/test/comparison/comparison.h @@ -1,6 +1,12 @@ +#include + int eq(int x, int y); int neq(int x, int y); int lt(int x, int y); int lte(int x, int y); int gt(int x, int y); int gte(int x, int y); + +bool and(bool a, bool b); +bool or(bool a, bool b); +bool not(bool a); \ No newline at end of file diff --git a/src/test/print/print.c b/src/test/print/print.c index 511a67e..ae46b7f 100644 --- a/src/test/print/print.c +++ b/src/test/print/print.c @@ -1,3 +1,4 @@ +#include #include #include "print.h" @@ -39,4 +40,22 @@ void succPrefixTwo(char* name, int x, int y, int expected, int result) { void errPrefixTwo(char* name, int x, int y, int expected, int result) { incFailure(); printf("\033[0;31mERROR:\t\t%s(%d, %d)\tGOT: %d\tExpected: %d\033[0;0m\n", name, x, y, result, expected); +} + +void bool_succPrefixTwo(char* name, bool a, bool b, bool expected, bool result) { + incSuccess(); + printf("\033[0;32mSUCCESS:\t%s(%s, %s)\tGOT: %s\tExpected: %s\033[0;0m\n", name, printBool(a), printBool(b), printBool(result), printBool(expected)); +} + +void bool_errPrefixTwo(char* name, bool a, bool b, bool expected, bool result) { + incFailure(); + printf("\033[0;32mSUCCESS:\t%s(%s, %s)\tGOT: %s\tExpected: %s\033[0;0m\n", name, printBool(a), printBool(b), printBool(result), printBool(expected)); + +} + +char* printBool(bool a) { + if (a == true) { + return "true"; + } + return "false"; } \ No newline at end of file diff --git a/src/test/print/print.h b/src/test/print/print.h index d274b51..5673d5c 100644 --- a/src/test/print/print.h +++ b/src/test/print/print.h @@ -10,4 +10,7 @@ void succPrefixTwo(char* name, int x, int y, int expected, int result); void errPrefixTwo(char* name, int x, int y, int expected, int result); void succInfixTwo(char* name, int x, int y, int expected, int result); -void errInfixTwo(char* name, int x, int y, int expected, int result); \ No newline at end of file +void errInfixTwo(char* name, int x, int y, int expected, int result); + +void bool_succInfixTwo(char* name, bool x, bool y, bool expected, bool result); +void bool_errInfixTwo(char* name, bool x, bool y, bool expected, bool result); diff --git a/src/test/test.k b/src/test/test.k index 6a6abbf..b6066a8 100644 --- a/src/test/test.k +++ b/src/test/test.k @@ -162,4 +162,16 @@ function myFor(end) { return x; } +function and(a, b) { + return (a && b); +} + +function or(a, b) { + return (a || b); +} + +function not(a) { + return (!a); +} + add(1, 1); From 722a9babcb56d862581e4ccd6c2184d02c91db17 Mon Sep 17 00:00:00 2001 From: nitrix Date: Mon, 20 Jan 2020 19:32:16 +0100 Subject: [PATCH 3/5] remove unused import --- src/main/java/de/hsrm/compiler/Klang/ContextAnalysis.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/de/hsrm/compiler/Klang/ContextAnalysis.java b/src/main/java/de/hsrm/compiler/Klang/ContextAnalysis.java index da7cfa0..80facdb 100644 --- a/src/main/java/de/hsrm/compiler/Klang/ContextAnalysis.java +++ b/src/main/java/de/hsrm/compiler/Klang/ContextAnalysis.java @@ -10,7 +10,6 @@ import de.hsrm.compiler.Klang.nodes.loops.ForLoop; import de.hsrm.compiler.Klang.nodes.loops.WhileLoop; import de.hsrm.compiler.Klang.nodes.statements.*; import de.hsrm.compiler.Klang.types.Type; -import sun.tools.tree.OrExpression; public class ContextAnalysis extends KlangBaseVisitor { Set vars = new HashSet<>(); From 295bcaec8a64ac9f533b96397e29803debe96fd8 Mon Sep 17 00:00:00 2001 From: nitrix Date: Mon, 20 Jan 2020 19:32:50 +0100 Subject: [PATCH 4/5] implement visitors for boolean expressions --- .../compiler/Klang/visitors/EvalVisitor.java | 20 ++++ .../hsrm/compiler/Klang/visitors/GenASM.java | 97 +++++++++++++++++++ .../hsrm/compiler/Klang/visitors/GetVars.java | 20 ++++ .../Klang/visitors/PrettyPrintVisitor.java | 27 ++++++ 4 files changed, 164 insertions(+) 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 c34fea5..7151a76 100644 --- a/src/main/java/de/hsrm/compiler/Klang/visitors/EvalVisitor.java +++ b/src/main/java/de/hsrm/compiler/Klang/visitors/EvalVisitor.java @@ -129,6 +129,26 @@ public class EvalVisitor implements Visitor { return new Value(-a.asInteger()); } + @Override + public Value visit(OrExpression e) { + Value lhs = e.lhs.welcome(this); + Value rhs = e.rhs.welcome(this); + return new Value(lhs.asBoolean() || rhs.asBoolean()); + } + + @Override + public Value visit(AndExpression e) { + Value lhs = e.lhs.welcome(this); + Value rhs = e.rhs.welcome(this); + return new Value(lhs.asBoolean() && rhs.asBoolean()); + } + + @Override + public Value visit(NotExpression e) { + Value lhs = e.lhs.welcome(this); + return new Value(!lhs.asBoolean()); + } + @Override public Value visit(Variable e) { Value result = this.env.get(e.name); 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 6a69845..8dcc6e0 100644 --- a/src/main/java/de/hsrm/compiler/Klang/visitors/GenASM.java +++ b/src/main/java/de/hsrm/compiler/Klang/visitors/GenASM.java @@ -278,6 +278,103 @@ public class GenASM implements Visitor { return null; } + @Override + public Void visit(OrExpression e) { + int lblTrue = ++lCount; + int lblFalse = ++lCount; + int lblEnd = ++lCount; + + // Werte LHS aus + // Wenn LHS != 0 bedeutet das true + // also können wir direkt sagen dass das Ergebnis true ist + e.lhs.welcome(this); + this.ex.write(" cmpq $0, %rax\n"); + this.ex.write(" jne .L" + lblTrue + "\n"); + + // LHS war false, also werte RHS aus + // Wenn RHS == 0 bedeutet das false, + // also ist das Gesamtergebnis false + e.rhs.welcome(this); + this.ex.write(" cmpq $0, %rax\n"); + this.ex.write(" je .L" + lblFalse + "\n"); + + // Die Expression wertet zu true aus + // Springe am false Teil vorbei + this.ex.write(".L" + lblTrue + ":\n"); + this.ex.write(" movq $1, %rax\n"); + this.ex.write(" jmp .L" + lblEnd + "\n"); + + // Die Expressoin wertet zu false aus + this.ex.write(".L" + lblFalse + ":\n"); + this.ex.write(" movq $0, %rax\n"); + + // Das hier ist das ende + this.ex.write(".L" + lblEnd + ":\n"); + return null; + } + + @Override + public Void visit(AndExpression e) { + int lblTrue = ++lCount; + int lblFalse = ++lCount; + int lblEnd = ++lCount; + + // Werte LHS aus + // Wenn LHS == 0, bedeutet das false + // also können wir direkt sagen dass das Ergebnis false ist + e.lhs.welcome(this); + this.ex.write(" cmpq $0, %rax\n"); + this.ex.write(" je .L" + lblFalse + "\n"); + + // LHS war true, also werte RHS aus. + // Wenn RHS == 0, bedeutet das false + // also ist das Gesamtergebnis false + e.rhs.welcome(this); + this.ex.write(" cmpq $0, %rax\n"); + this.ex.write(" je .L" + lblFalse +"\n"); + + // Die Expression wertet zu true aus + // Springe am false Teil vorbei + this.ex.write(".L" + lblTrue +":\n"); + this.ex.write(" movq $1, %rax\n"); + this.ex.write(" jmp .L" + lblEnd + "\n"); + + // Die Expressoin wertet zu false aus + this.ex.write(".L" + lblFalse +":\n"); + this.ex.write(" movq $0, %rax\n"); + + // Das hier ist das ende + this.ex.write(".L" + lblEnd +":\n"); + return null; + } + + @Override + public Void visit(NotExpression e) { + int lblFalse = ++lCount; + int lblEnd = ++lCount; + + // Werte LHS aus + // Wenn LHS != 0 bedeutet das true, also jumpe zum false Teil + // Wenn nicht, falle durch zum true Teil + e.lhs.welcome(this); + this.ex.write(" cmpq $0, %rax\n"); + this.ex.write(" jne .L" +lblFalse +"\n"); + + // Hier ist das Ergebnis true + // Springe am false Teil vorbei + this.ex.write(" movq $1, %rax\n"); + this.ex.write(" jmp .L" +lblEnd +"\n"); + + // Hier ist das Ergebnis false + // Falle zum Ende durch + this.ex.write(".L" +lblFalse + ":\n"); + this.ex.write("movq $0, %rax\n"); + + // Hier ist das Ende + this.ex.write(".L" +lblEnd + ":\n"); + return null; + } + @Override public Void visit(IfStatement e) { int lblElse = ++lCount; 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 8a6fa14..0d55d41 100644 --- a/src/main/java/de/hsrm/compiler/Klang/visitors/GetVars.java +++ b/src/main/java/de/hsrm/compiler/Klang/visitors/GetVars.java @@ -115,6 +115,26 @@ class GetVars implements Visitor { return null; } + @Override + public Void visit(OrExpression e) { + e.lhs.welcome(this); + e.rhs.welcome(this); + return null; + } + + @Override + public Void visit(AndExpression e) { + e.lhs.welcome(this); + e.rhs.welcome(this); + return null; + } + + @Override + public Void visit(NotExpression e) { + e.lhs.welcome(this); + return null; + } + @Override public Void visit(IfStatement e) { e.cond.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 ae1f364..0b35907 100644 --- a/src/main/java/de/hsrm/compiler/Klang/visitors/PrettyPrintVisitor.java +++ b/src/main/java/de/hsrm/compiler/Klang/visitors/PrettyPrintVisitor.java @@ -195,6 +195,33 @@ public class PrettyPrintVisitor implements Visitor { return null; } + @Override + public Void visit(OrExpression e) { + ex.write("("); + e.lhs.welcome(this); + ex.write(" || "); + e.rhs.welcome(this); + ex.write(")"); + return null; + } + + @Override + public Void visit(AndExpression e) { + ex.write("("); + e.lhs.welcome(this); + ex.write(" && "); + e.rhs.welcome(this); + ex.write(")"); + return null; + } + + @Override + public Void visit(NotExpression e) { + ex.write("!"); + e.lhs.welcome(this); + return null; + } + @Override public Void visit(IfStatement e) { ex.write("if ("); From e5baad62e6d8c0d79311cb30ff2d37161cd9872c Mon Sep 17 00:00:00 2001 From: nitrix Date: Mon, 20 Jan 2020 19:33:07 +0100 Subject: [PATCH 5/5] implement tests --- src/test/comparison/comparison.c | 29 +++++++++++++++++++++++------ src/test/print/print.c | 30 +++++++++++++++++++----------- src/test/print/print.h | 6 ++++++ src/test/test.k | 2 +- 4 files changed, 49 insertions(+), 18 deletions(-) diff --git a/src/test/comparison/comparison.c b/src/test/comparison/comparison.c index e8f876f..46bc381 100644 --- a/src/test/comparison/comparison.c +++ b/src/test/comparison/comparison.c @@ -1,5 +1,4 @@ #include -#include #include "comparison.h" #include "../print/print.h" @@ -13,7 +12,17 @@ int comparisonTest(char* name, int x, int y, int expected, int result) { } } -int boolTest(char* name, bool a, bool b, bool expected, bool result) { +int boolTestOne(char* name, bool x, bool expected, bool result) { + if (expected == result) { + bool_succPrefixOne(name, x, expected, result); + return 0; + } else { + bool_errPrefixOne(name, x, expected, result); + return 1; + } +} + +int boolTestTwo(char* name, bool a, bool b, bool expected, bool result) { if (expected == result) { bool_succInfixTwo(name, a, b, expected, result); return 0; @@ -55,8 +64,16 @@ void runComparisonTests() { comparisonTest(">=", 0, 1, 0, gte(0, 1)); comparisonTest(">=", 0, 0, 1, gte(0, 0)); - boolTest("&&", true, true, true, and(true, true)); - boolTest("&&", true, false, false, and(true, false)); - boolTest("&&", false, true, false, and(false, true)); - boolTest("&&", false, false, false, and(false, false)); + boolTestTwo("&&", true, true, true, and(true, true)); + boolTestTwo("&&", true, false, false, and(true, false)); + boolTestTwo("&&", false, true, false, and(false, true)); + boolTestTwo("&&", false, false, false, and(false, false)); + + boolTestTwo("||", true, true, true, or(true, true)); + boolTestTwo("||", true, false, true, or(true, false)); + boolTestTwo("||", false, true, true, or(false, true)); + boolTestTwo("||", false, false, false, or(false, false)); + + boolTestOne("!", true, false, not(true)); + boolTestOne("!", false, true, not(false)); } \ No newline at end of file diff --git a/src/test/print/print.c b/src/test/print/print.c index ae46b7f..21109f9 100644 --- a/src/test/print/print.c +++ b/src/test/print/print.c @@ -1,7 +1,13 @@ -#include #include #include "print.h" +char* printBool(bool a) { + if (a == true) { + return "true"; + } + return "false"; +} + void succInfixTwo(char* name, int x, int y, int expected, int result) { incSuccess(); printf("\033[0;32mSUCCESS:\t%d %s %d\tGOT: %d\tExpected: %d\033[0;0m\n", x, name, y, result, expected); @@ -42,20 +48,22 @@ void errPrefixTwo(char* name, int x, int y, int expected, int result) { printf("\033[0;31mERROR:\t\t%s(%d, %d)\tGOT: %d\tExpected: %d\033[0;0m\n", name, x, y, result, expected); } -void bool_succPrefixTwo(char* name, bool a, bool b, bool expected, bool result) { +void bool_succPrefixOne(char* name, bool x, bool expected, bool result) { incSuccess(); - printf("\033[0;32mSUCCESS:\t%s(%s, %s)\tGOT: %s\tExpected: %s\033[0;0m\n", name, printBool(a), printBool(b), printBool(result), printBool(expected)); + printf("\033[0;32mSUCCESS:\t%s%s\tGOT: %s\tExpected: %s\033[0;0m\n", name, printBool(x), printBool(result), printBool(expected)); } -void bool_errPrefixTwo(char* name, bool a, bool b, bool expected, bool result) { +void bool_errPrefixOne(char* name, bool x, bool expected, bool result) { incFailure(); - printf("\033[0;32mSUCCESS:\t%s(%s, %s)\tGOT: %s\tExpected: %s\033[0;0m\n", name, printBool(a), printBool(b), printBool(result), printBool(expected)); - + printf("\033[0;31mERROR:\t\t%s%s\tGOT: %s\tExpected: %s\033[0;0m\n", name, printBool(x), printBool(result), printBool(expected)); } -char* printBool(bool a) { - if (a == true) { - return "true"; - } - return "false"; +void bool_succInfixTwo(char* name, bool a, bool b, bool expected, bool result) { + incSuccess(); + printf("\033[0;32mSUCCESS:\t%s %s %s\tGOT: %s\tExpected: %s\033[0;0m\n", printBool(a), name, printBool(b), printBool(result), printBool(expected)); +} + +void bool_errInfixTwo(char* name, bool a, bool b, bool expected, bool result) { + incFailure(); + printf("\033[0;31mERROR:\t\t%s %s %s\tGOT: %s\tExpected: %s\033[0;0m\n", printBool(a), name, printBool(b), printBool(result), printBool(expected)); } \ No newline at end of file diff --git a/src/test/print/print.h b/src/test/print/print.h index 5673d5c..637cc5c 100644 --- a/src/test/print/print.h +++ b/src/test/print/print.h @@ -1,3 +1,5 @@ +#include + void incSuccess(); void incFailure(); @@ -6,11 +8,15 @@ void err(char* name, int expected, int result); void succPrefixOne(char* name, int x, int expected, int result); void errPrefixOne(char* name, int x, int expected, int result); + void succPrefixTwo(char* name, int x, int y, int expected, int result); void errPrefixTwo(char* name, int x, int y, int expected, int result); void succInfixTwo(char* name, int x, int y, int expected, int result); void errInfixTwo(char* name, int x, int y, int expected, int result); +void bool_succPrefixOne(char* name, bool x, bool expected, bool result); +void bool_errPrefixOne(char* name, bool x, bool expected, bool result); + void bool_succInfixTwo(char* name, bool x, bool y, bool expected, bool result); void bool_errInfixTwo(char* name, bool x, bool y, bool expected, bool result); diff --git a/src/test/test.k b/src/test/test.k index b6066a8..5478bca 100644 --- a/src/test/test.k +++ b/src/test/test.k @@ -171,7 +171,7 @@ function or(a, b) { } function not(a) { - return (!a); + return !a; } add(1, 1);