diff --git a/src/main/java/dk/madsravn/interpreter/evaluator/Evaluator.java b/src/main/java/dk/madsravn/interpreter/evaluator/Evaluator.java new file mode 100644 index 0000000..07ff952 --- /dev/null +++ b/src/main/java/dk/madsravn/interpreter/evaluator/Evaluator.java @@ -0,0 +1,32 @@ +package dk.madsravn.interpreter.evaluator; + +import dk.madsravn.interpreter.ast.*; +import dk.madsravn.interpreter.object.IObject; +import dk.madsravn.interpreter.object.IntegerObject; + +import java.util.List; + +public class Evaluator { + + public static IObject evaluate(INode node) { + // TODO: Ugly? + if(node instanceof IntegerLiteral) { + // TODO: Ugly? + return new IntegerObject(((IntegerLiteral) node).getValue()); + } + if(node instanceof ExpressionStatement) { + return evaluate(((ExpressionStatement)node).getExpression()); + } + if(node instanceof Program) { + return evaluateStatements(((Program)node).getStatements()); + } + return null; + } + + private static IObject evaluateStatements(List statements) { + for(IStatement statement : statements) { + return evaluate(statement); + } + return null; + } +} diff --git a/src/main/java/dk/madsravn/interpreter/object/BooleanObject.java b/src/main/java/dk/madsravn/interpreter/object/BooleanObject.java new file mode 100644 index 0000000..0515831 --- /dev/null +++ b/src/main/java/dk/madsravn/interpreter/object/BooleanObject.java @@ -0,0 +1,14 @@ +package dk.madsravn.interpreter.object; + +public class BooleanObject implements IObject { + private boolean value; + + public String type() { + return "BOOLEAN"; + } + + public String inspect() { + return "" + value; + } +} + diff --git a/src/main/java/dk/madsravn/interpreter/object/IObject.java b/src/main/java/dk/madsravn/interpreter/object/IObject.java new file mode 100644 index 0000000..1236c23 --- /dev/null +++ b/src/main/java/dk/madsravn/interpreter/object/IObject.java @@ -0,0 +1,7 @@ +package dk.madsravn.interpreter.object; + +public interface IObject { + String type(); + String inspect(); + +} diff --git a/src/main/java/dk/madsravn/interpreter/object/IntegerObject.java b/src/main/java/dk/madsravn/interpreter/object/IntegerObject.java new file mode 100644 index 0000000..be7604d --- /dev/null +++ b/src/main/java/dk/madsravn/interpreter/object/IntegerObject.java @@ -0,0 +1,25 @@ +package dk.madsravn.interpreter.object; + +public class IntegerObject implements IObject { + private int value; + + public IntegerObject(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + + @Override + public String inspect() { + return "" + value; + } + + // TODO: Create enum for this. + @Override + public String type() { + return "INTEGER"; + } + +} diff --git a/src/main/java/dk/madsravn/interpreter/object/NullObject.java b/src/main/java/dk/madsravn/interpreter/object/NullObject.java new file mode 100644 index 0000000..6c7842a --- /dev/null +++ b/src/main/java/dk/madsravn/interpreter/object/NullObject.java @@ -0,0 +1,14 @@ +package dk.madsravn.interpreter.object; + +public class NullObject implements IObject { + @Override + public String type() { + return "NULL"; + } + + @Override + public String inspect() { + return "null"; + } + +} diff --git a/src/test/java/dk/madsravn/interpreter/evaluator/EvaluatorTest.java b/src/test/java/dk/madsravn/interpreter/evaluator/EvaluatorTest.java new file mode 100644 index 0000000..73917ce --- /dev/null +++ b/src/test/java/dk/madsravn/interpreter/evaluator/EvaluatorTest.java @@ -0,0 +1,55 @@ +package dk.madsravn.interpreter.evaluator; + +import dk.madsravn.interpreter.ast.Program; +import dk.madsravn.interpreter.lexer.Lexer; +import dk.madsravn.interpreter.object.IObject; +import dk.madsravn.interpreter.object.IntegerObject; +import dk.madsravn.interpreter.parser.Parser; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.List; + +import static dk.madsravn.interpreter.evaluator.Evaluator.evaluate; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class EvaluatorTest { + + //TODO: Use record instead. Then we get all of this + private class EvalIntegerData { + public String input; + public int value; + public EvalIntegerData(String input, int value) { + this.input = input; + this.value = value; + } + } + + @Test + public void testEvalIntegerExpression() { + List inputs = Arrays.asList( + new EvalIntegerData("5", 5), + new EvalIntegerData("10", 10) + ); + + for(EvalIntegerData input : inputs) { + IObject object = testEval(input.input); + testIntegerObject(object, input.value); + } + } + + private void testIntegerObject(IObject object, int expected) { + assertTrue(object instanceof IntegerObject); + IntegerObject integerObject = (IntegerObject) object; + assertEquals(integerObject.getValue(), expected); + } + + private IObject testEval(String input) { + Lexer lexer = new Lexer(input); + Parser parser = new Parser(lexer); + Program program = parser.parseProgram(); + + return evaluate(program); + } +}