Skip to content

Commit

Permalink
Prefix expressions with bang
Browse files Browse the repository at this point in the history
  • Loading branch information
madsravn committed Nov 1, 2023
1 parent 4cc2ff6 commit a24d86a
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 2 deletions.
47 changes: 45 additions & 2 deletions src/main/java/dk/madsravn/interpreter/evaluator/Evaluator.java
Original file line number Diff line number Diff line change
@@ -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());
}
Expand All @@ -27,6 +45,31 @@ private static IObject evaluateStatements(List<IStatement> 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;

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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";
}
Expand Down
9 changes: 9 additions & 0 deletions src/main/java/dk/madsravn/interpreter/repl/Repl.java
Original file line number Diff line number Diff line change
@@ -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;

Expand All @@ -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) {

Expand Down
39 changes: 39 additions & 0 deletions src/test/java/dk/madsravn/interpreter/evaluator/EvaluatorTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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() {
Expand All @@ -31,12 +33,49 @@ public void testEvalIntegerExpression() {
}
}

@Test
public void testBooleanExpression() {
List<EvalBooleanData> 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<EvalBooleanData> 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);
Expand Down

0 comments on commit a24d86a

Please sign in to comment.