From 2f32211e9e413a4fe162bd6d5d359cc0e7ca5f49 Mon Sep 17 00:00:00 2001 From: sabotack Date: Wed, 17 May 2023 08:44:18 +0200 Subject: [PATCH] Removed usage of ExpressionParser and fixed negation-tests --- src/main/interpreter/ExpressionParser.java | 28 ---------- src/main/interpreter/Visitor.java | 61 ++++++++++++++++------ src/test/interpreter/VisitorUnitTest.java | 16 ++---- 3 files changed, 47 insertions(+), 58 deletions(-) delete mode 100644 src/main/interpreter/ExpressionParser.java diff --git a/src/main/interpreter/ExpressionParser.java b/src/main/interpreter/ExpressionParser.java deleted file mode 100644 index af987c5..0000000 --- a/src/main/interpreter/ExpressionParser.java +++ /dev/null @@ -1,28 +0,0 @@ -package interpreter; - -import interpreter.antlr.MineScriptBaseVisitor; -import interpreter.types.MSBool; -import interpreter.types.MSNumber; - -public class ExpressionParser extends MineScriptBaseVisitor { - - public MSBool getBoolean(T ctx) { - if (ctx instanceof MSBool b) { - return b; - } else if (ctx instanceof MSNumber i) { - return new MSBool(i.getValue() != 0); - } else { - throw new RuntimeException("Condition must be a bool"); - } - } - - public MSBool getNegatedBoolean(T ctx) { - if (ctx instanceof MSBool b) { - return new MSBool(!b.getValue()); - } else if (ctx instanceof MSNumber i) { - return new MSBool(i.getValue() == 0); - } else { - throw new RuntimeException("Condition must be a bool"); - } - } -} diff --git a/src/main/interpreter/Visitor.java b/src/main/interpreter/Visitor.java index 35325fc..082b626 100644 --- a/src/main/interpreter/Visitor.java +++ b/src/main/interpreter/Visitor.java @@ -22,7 +22,6 @@ import java.util.stream.Collectors; public class Visitor extends MineScriptBaseVisitor { - private final ExpressionParser parser = new ExpressionParser(); private final Random random = new Random(System.currentTimeMillis()); private final SymbolTable symbolTable; private boolean hasReturned = false; @@ -136,10 +135,13 @@ public MSType visitWhile(MineScriptParser.WhileContext ctx) { MSType value = null; /*Also checks for the returned state in case a return has been called inside the loop body*/ - while (parser.getBoolean(visit(ctx.expression())).getValue() && !hasReturned) { + while (visit(ctx.expression()) instanceof MSBool c && c.getValue() && !hasReturned) { value = visit(ctx.statements()); } + if (!(visit(ctx.expression()) instanceof MSBool)) + throw new RuntimeException("While condition must be a boolean"); + return value; } @@ -147,7 +149,12 @@ public MSType visitWhile(MineScriptParser.WhileContext ctx) { public MSType visitIf(MineScriptParser.IfContext ctx) { /*Handle if and else if*/ for (var expression : ctx.expression()) { - if (parser.getBoolean(visit(expression)).getValue()) { + MSType condition = visit(expression); + + if (!(condition instanceof MSBool)) + throw new RuntimeException("If condition must be a boolean"); + + if (((MSBool) condition).getValue()) { return visit(ctx.statements(ctx.expression().indexOf(expression))); } } @@ -186,7 +193,13 @@ public MSType visitBool(MineScriptParser.BoolContext ctx) { @Override public MSType visitNotExpr(MineScriptParser.NotExprContext ctx) { - return parser.getNegatedBoolean(visit(ctx.expression())); + MSType value = visit(ctx.expression()); + + if (!(value instanceof MSBool)) + throw new RuntimeException("Cannot negate non-boolean value"); + + boolean bool = ((MSBool) value).getValue(); + return new MSBool(!bool); } @Override @@ -257,6 +270,7 @@ public MSType visitAddSub(MineScriptParser.AddSubContext ctx) { MSType left = visit(ctx.expression(0)); MSType right = visit(ctx.expression(1)); + /*Check that both sides are numbers otherwise throw an error*/ if (!(left instanceof MSNumber l) || !(right instanceof MSNumber r)) { throw new RuntimeException("Cannot use '" + ctx.op.getText() + "' operator on " + left.getTypeName() + " and " + right.getTypeName()); } @@ -312,32 +326,46 @@ public MSType visitPow(MineScriptParser.PowContext ctx) { } return calculateArithmeticExpression(l, r, "^"); - } @Override public MSType visitAnd(MineScriptParser.AndContext ctx) { /*Handles and with short-circuit, that's why the left side is handled first*/ MSType left = visit(ctx.expression(0)); - /*If the left part is false, it returns without the need to evaluate the right side*/ - if (!parser.getBoolean(left).getValue()) { - return new MSBool(false); - } - MSType right = visit(ctx.expression(1)); - return new MSBool(parser.getBoolean(right).getValue()); + if (left instanceof MSBool l) {/*If the left part is false, it returns without the need to evaluate the right side*/ + if (!l.getValue()) { + return l; + } + + MSType right = visit(ctx.expression(1)); + if (!(right instanceof MSBool r)) { + throw new RuntimeException("Cannot use 'and' operator on " + left.getTypeName() + " and " + right.getTypeName()); + } + return r; + } else { + throw new RuntimeException("Cannot use 'and' operator on " + left.getTypeName() + " and " + visit(ctx.expression(1)).getTypeName()); + } } @Override public MSType visitOr(MineScriptParser.OrContext ctx) { /*Handles or with short-circuit, much like in the visitAnd method*/ MSType left = visit(ctx.expression(0)); - if (parser.getBoolean(left).getValue()) { - return new MSBool(true); - } - MSType right = visit(ctx.expression(1)); - return new MSBool(parser.getBoolean(right).getValue()); + if (left instanceof MSBool l) { + if (l.getValue()) { + return l; + } + + MSType right = visit(ctx.expression(1)); + if (!(right instanceof MSBool r)) { + throw new RuntimeException("Cannot use 'or' operator on " + left.getTypeName() + " and " + right.getTypeName()); + } + return r; + } else { + throw new RuntimeException("Cannot use 'or' operator on " + left.getTypeName() + " and " + visit(ctx.expression(1)).getTypeName()); + } } @Override @@ -702,7 +730,6 @@ private MSNumber calculateArithmeticExpression(MSNumber left, MSNumber right, St throw new RuntimeException("Result of '" + leftBig + " " + operator + " " + rightBig + "' is too small. Minimum number is " + Integer.MIN_VALUE); } return new MSNumber(result.intValue()); - } /** diff --git a/src/test/interpreter/VisitorUnitTest.java b/src/test/interpreter/VisitorUnitTest.java index d285165..d43967f 100644 --- a/src/test/interpreter/VisitorUnitTest.java +++ b/src/test/interpreter/VisitorUnitTest.java @@ -60,23 +60,13 @@ void visitNotExprValidBoolReturnsNegatedBool() { Assertions.assertTrue(((MSBool) result).getValue()); } - @Test - void visitNotExprPassZeroReturnsTrue() { - Mockito.when(mockNotExprContext.expression()).thenReturn(mockExpressionContext); - Mockito.when(spyVisitor.visit(mockExpressionContext)).thenReturn(new MSNumber(0)); - - MSType result = spyVisitor.visitNotExpr(mockNotExprContext); - Assertions.assertTrue(((MSBool) result).getValue()); - } - @ParameterizedTest - @ValueSource(ints = {-1000, -100, 100, 1000}) - void visitNotExprPassNonZeroNumberReturnsFalse(int value) { + @ValueSource(ints = {-1000, -100, 0, 100, 1000}) + void visitNotExprPassNumberThrowsRuntimeException(int value) { Mockito.when(mockNotExprContext.expression()).thenReturn(mockExpressionContext); Mockito.when(spyVisitor.visit(mockExpressionContext)).thenReturn(new MSNumber(value)); - MSType result = spyVisitor.visitNotExpr(mockNotExprContext); - Assertions.assertFalse(((MSBool) result).getValue()); + Assertions.assertThrows(RuntimeException.class, () -> spyVisitor.visitNotExpr(mockNotExprContext)); } @Test