From a24d86a738005afdbd0f8632809ec96013a36393 Mon Sep 17 00:00:00 2001 From: Mads Ravn Date: Wed, 1 Nov 2023 21:46:44 +0100 Subject: [PATCH] Prefix expressions with bang --- .../interpreter/evaluator/Evaluator.java | 47 ++++++++++++++++++- .../interpreter/object/BooleanObject.java | 8 ++++ .../dk/madsravn/interpreter/repl/Repl.java | 9 ++++ .../interpreter/evaluator/EvaluatorTest.java | 39 +++++++++++++++ 4 files changed, 101 insertions(+), 2 deletions(-) diff --git a/src/main/java/dk/madsravn/interpreter/evaluator/Evaluator.java b/src/main/java/dk/madsravn/interpreter/evaluator/Evaluator.java index 07ff952..ec83cc6 100644 --- a/src/main/java/dk/madsravn/interpreter/evaluator/Evaluator.java +++ b/src/main/java/dk/madsravn/interpreter/evaluator/Evaluator.java @@ -1,19 +1,37 @@ package dk.madsravn.interpreter.evaluator; import dk.madsravn.interpreter.ast.*; +import dk.madsravn.interpreter.object.BooleanObject; import dk.madsravn.interpreter.object.IObject; import dk.madsravn.interpreter.object.IntegerObject; +import dk.madsravn.interpreter.object.NullObject; import java.util.List; public class Evaluator { + private static BooleanObject TRUE = new BooleanObject(true); + private static BooleanObject FALSE = new BooleanObject(false); + private static NullObject NULL = new NullObject(); + public static IObject evaluate(INode node) { // TODO: Ugly? + if(node instanceof PrefixExpression) { + PrefixExpression prefixExpression = (PrefixExpression) node; + IObject right = evaluate(prefixExpression.getRight()); + return evaluatePrefixExpression(prefixExpression.getOperator(), right); + } if(node instanceof IntegerLiteral) { - // TODO: Ugly? return new IntegerObject(((IntegerLiteral) node).getValue()); } + if(node instanceof BooleanType) { + boolean value = ((BooleanType)node).getValue(); + if (value == true) { + return TRUE; + } else { + return FALSE; + } + } if(node instanceof ExpressionStatement) { return evaluate(((ExpressionStatement)node).getExpression()); } @@ -27,6 +45,31 @@ private static IObject evaluateStatements(List statements) { for(IStatement statement : statements) { return evaluate(statement); } - return null; + return NULL; + } + + private static IObject evaluatePrefixExpression(String operator, IObject right) { + if(operator.equals("!")) { + return evalulateBangOperatorExpression(right); + } + return new NullObject(); + } + + private static IObject evalulateBangOperatorExpression(IObject right) { + if (right.equals(TRUE)) { + return FALSE; + } else if (right.equals(FALSE) || right.equals(NULL)) { + return TRUE; + } + if(right instanceof IntegerObject) { + IntegerObject integerObject = (IntegerObject) right; + if (integerObject.getValue() == 0) { + return TRUE; + } else { + return FALSE; + } + } + return FALSE; + } } diff --git a/src/main/java/dk/madsravn/interpreter/object/BooleanObject.java b/src/main/java/dk/madsravn/interpreter/object/BooleanObject.java index 0515831..2deada8 100644 --- a/src/main/java/dk/madsravn/interpreter/object/BooleanObject.java +++ b/src/main/java/dk/madsravn/interpreter/object/BooleanObject.java @@ -3,6 +3,14 @@ public class BooleanObject implements IObject { private boolean value; + public BooleanObject(boolean value) { + this.value = value; + } + + public boolean getValue() { + return value; + } + public String type() { return "BOOLEAN"; } diff --git a/src/main/java/dk/madsravn/interpreter/repl/Repl.java b/src/main/java/dk/madsravn/interpreter/repl/Repl.java index be13b73..d2ba994 100644 --- a/src/main/java/dk/madsravn/interpreter/repl/Repl.java +++ b/src/main/java/dk/madsravn/interpreter/repl/Repl.java @@ -1,7 +1,9 @@ package dk.madsravn.interpreter.repl; import dk.madsravn.interpreter.ast.Program; +import dk.madsravn.interpreter.evaluator.Evaluator; import dk.madsravn.interpreter.lexer.Lexer; +import dk.madsravn.interpreter.object.IObject; import dk.madsravn.interpreter.parser.Parser; import dk.madsravn.interpreter.tokens.Token; @@ -26,6 +28,13 @@ public void start() { continue; } System.out.println(program.string()); + System.out.println("YIELDS:"); + IObject evaluated = Evaluator.evaluate(program); + if (evaluated != null) { + System.out.println(evaluated.inspect()); + } else { + System.out.println("NOTHING"); + } System.out.println(""); } catch (Exception e) { diff --git a/src/test/java/dk/madsravn/interpreter/evaluator/EvaluatorTest.java b/src/test/java/dk/madsravn/interpreter/evaluator/EvaluatorTest.java index 8f90960..23d43a5 100644 --- a/src/test/java/dk/madsravn/interpreter/evaluator/EvaluatorTest.java +++ b/src/test/java/dk/madsravn/interpreter/evaluator/EvaluatorTest.java @@ -2,6 +2,7 @@ import dk.madsravn.interpreter.ast.Program; import dk.madsravn.interpreter.lexer.Lexer; +import dk.madsravn.interpreter.object.BooleanObject; import dk.madsravn.interpreter.object.IObject; import dk.madsravn.interpreter.object.IntegerObject; import dk.madsravn.interpreter.parser.Parser; @@ -17,6 +18,7 @@ public class EvaluatorTest { private record EvalIntegerData(String input, int value) { } + private record EvalBooleanData(String input, boolean value) { } @Test public void testEvalIntegerExpression() { @@ -31,12 +33,49 @@ public void testEvalIntegerExpression() { } } + @Test + public void testBooleanExpression() { + List inputs = Arrays.asList( + new EvalBooleanData("true", true), + new EvalBooleanData("false", false) + ); + + for(EvalBooleanData input : inputs) { + IObject object = testEval(input.input); + testBooleanObject(object, input.value, input.input); + } + } + + @Test + public void testBangOperator() { + List inputs = Arrays.asList( + new EvalBooleanData("!true", false), + new EvalBooleanData("!false", true), + new EvalBooleanData("!5", false), + new EvalBooleanData("!!true", true), + new EvalBooleanData("!!false", false), + new EvalBooleanData("!!5", true), + new EvalBooleanData("!!0", false), + new EvalBooleanData("!0", true) + ); + for(EvalBooleanData input : inputs) { + IObject object = testEval(input.input); + testBooleanObject(object, input.value, input.input); + } + } + private void testIntegerObject(IObject object, int expected) { assertTrue(object instanceof IntegerObject); IntegerObject integerObject = (IntegerObject) object; assertEquals(integerObject.getValue(), expected); } + private void testBooleanObject(IObject object, boolean expected, String input) { + assertTrue(object instanceof BooleanObject); + BooleanObject booleanObject = (BooleanObject) object; + assertEquals(booleanObject.getValue(), expected, input); + } + private IObject testEval(String input) { Lexer lexer = new Lexer(input); Parser parser = new Parser(lexer);