Skip to content

Commit

Permalink
Add support for conditional statements
Browse files Browse the repository at this point in the history
  • Loading branch information
asynchroza committed Nov 15, 2023
1 parent 3e1c53f commit 4b905f4
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 6 deletions.
53 changes: 47 additions & 6 deletions nulascript/eval/eval.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,19 @@ NilStorage* nilStorage = new NilStorage();
Storage* evaluate(Node* node);
Storage* evaluateSequence(std::vector<Statement*> statements);

bool checkTruthiness(Storage* storage) {
if (storage == trueStorage) {
return true;
} else if (storage == falseStorage) {
return false;
} else if (storage == nilStorage) {
return false;
} else {
std::cout << "[DEBUG]: Got a non boolean or nil value";
return true;
}
}

Storage* evaluateMinusExpression(Storage* rightExpression) {
if (rightExpression->getType() == StorageType::INTEGER) {
auto integer = dynamic_cast<IntegerStorage*>(rightExpression);
Expand Down Expand Up @@ -86,22 +99,50 @@ Storage* evaluateInfix(std::string op, Storage* leftExpression,
return nilStorage;
}

Storage* evaluateIf(Conditional* expression) {
auto condition = evaluate(expression->condition);

if (checkTruthiness(condition)) {
return evaluate(expression->currentBlock);
} else if (expression->elseBlock) {
return evaluate(expression->elseBlock);
}

return nilStorage;
}

bool checkBase(Node* passed, const std::type_info& expected) {
return typeid(*passed) == expected;
}

Storage* evaluate(Node* node) {
if (auto program = dynamic_cast<Program*>(node)) {
if (checkBase(node, typeid(Program))) {
auto program = dynamic_cast<Program*>(node);
return evaluateSequence(program->statements);
} else if (auto statement = dynamic_cast<ExpressionStatement*>(node)) {
} else if (checkBase(node, typeid(ExpressionStatement))) {
auto statement = dynamic_cast<ExpressionStatement*>(node);
return evaluate(statement->expression);
} else if (auto integer = dynamic_cast<Integer*>(node)) {
} else if (checkBase(node, typeid(Integer))) {
auto integer = dynamic_cast<Integer*>(node);
return new IntegerStorage(integer->value);
} else if (auto boolean = dynamic_cast<Boolean*>(node)) {
} else if (checkBase(node, typeid(Boolean))) {
auto boolean = dynamic_cast<Boolean*>(node);
return boolean->value ? trueStorage : falseStorage;
} else if (auto prefix = dynamic_cast<Prefix*>(node)) {
} else if (checkBase(node, typeid(Prefix))) {
auto prefix = dynamic_cast<Prefix*>(node);
auto rightExpression = evaluate(prefix->right);
return evaluatePrefix(prefix->op, rightExpression);
} else if (auto infix = dynamic_cast<Infix*>(node)) {
} else if (checkBase(node, typeid(Infix))) {
auto infix = dynamic_cast<Infix*>(node);
auto leftExpression = evaluate(infix->left);
auto rightExpression = evaluate(infix->right);
return evaluateInfix(infix->op, leftExpression, rightExpression);
} else if (checkBase(node, typeid(BlockStatement))) {
auto block = dynamic_cast<BlockStatement*>(node);
return evaluateSequence(block->statements);
} else if (checkBase(node, typeid(Conditional))) {
auto conditional = dynamic_cast<Conditional*>(node);
return evaluateIf(conditional);
}

return nilStorage;
Expand Down
15 changes: 15 additions & 0 deletions nulascript/tests/eval_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,19 @@ TEST(EvalSuite, TestIntegerExpression) {
dynamic_cast<IntegerStorage*>(getEvaluatedStorage(test.input));
ASSERT_EQ(result->value, test.expected);
}
}

TEST(EvalSuite, TestIfStatement) {
struct Test {
std::string input;
std::string expected;
};

std::vector<Test> tests = {{"if (true) { 69 }", "69"},
{"if (false) { 69 }", "nil"}};

for (auto test : tests) {
auto result = getEvaluatedStorage(test.input);
ASSERT_EQ(result->evaluate(), test.expected);
}
}

0 comments on commit 4b905f4

Please sign in to comment.