Skip to content

Commit

Permalink
fix else continue bug and add print() test
Browse files Browse the repository at this point in the history
  • Loading branch information
MadsVind committed May 14, 2024
1 parent 448bbcc commit b178310
Show file tree
Hide file tree
Showing 15 changed files with 155 additions and 63 deletions.
3 changes: 3 additions & 0 deletions docs/examples/table_operation.dpl
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,8 @@ t2 = { "width": [3, 4, 3], "height": [7, 8, 6], "area": [None, None, None]}

t3 = t1 union t2

print(t3)

t4 = t1 intersection t2

print(t4)
7 changes: 6 additions & 1 deletion include/tests/TestingUtil.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
#include <DplParserBaseVisitor.h>
#include <AstTestVisitor.hpp>
#include <Evaluator.hpp>
#include <fstream>
#include <cstdio>


#define LEXER_TEST(name) TEST_CASE("Lexer -- " #name, "[lexer]")
#define PARSER_TEST(name) TEST_CASE("Parser -- " #name, "[parser]")
Expand Down Expand Up @@ -39,7 +42,9 @@ namespace dplutil {
static void testTokens(std::string testFileName, std::vector<size_t> expectedTokenTypes);
static void testParser(std::string testFileName, std::vector<size_t> expectedTreeNodes);
static void testAst(std::string testFileName, std::vector<size_t> expectedTreeNodes);
static void testEval(std::string testFileName, std::vector<std::pair<std::string, dplsrc::Value>> expectedVarVec);
static void testEval(std::string testFileName,
std::vector<std::pair<std::string, dplsrc::Value>> expectedVarVec,
std::vector<std::string> expectedOutputLines);

private:
static constexpr std::string_view exampleLocation = "../../docs/examples/";
Expand Down
77 changes: 37 additions & 40 deletions src/Evaluator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -203,52 +203,49 @@ void Evaluator::visit(const std::shared_ptr<FilterNode> &node) {
Value identifierVal = identifierNode->getVal();
Value filterVal = filterNode->getVal();

if (identifierVal.is<Value::LIST>()) {
//? is it possible to use on list?
} else if (identifierVal.is<Value::COLUMN>()) {
const Value::COLUMN &col = identifierVal.get<Value::COLUMN>();

// Map string to operator function
std::map<std::string, std::function<bool(const Value &, const Value &)>> ops = {
{"<", [](const Value &a, const Value &b) { return a < b; }},
{">", [](const Value &a, const Value &b) { return a > b; }},
{"==", [](const Value &a, const Value &b) { return a == b; }},
{"!=", [](const Value &a, const Value &b) { return a != b; }},
{">=", [](const Value &a, const Value &b) { return a >= b; }},
{"<=", [](const Value &a, const Value &b) { return a <= b; }},
};
if (!identifierVal.is<Value::COLUMN>()) {
throw RuntimeException("Filter operation not allowed for this type");
}
const Value::COLUMN &col = identifierVal.get<Value::COLUMN>();

// Map string to operator function
std::map<std::string, std::function<bool(const Value &, const Value &)>> ops = {
{"<", [](const Value &a, const Value &b) { return a < b; }},
{">", [](const Value &a, const Value &b) { return a > b; }},
{"==", [](const Value &a, const Value &b) { return a == b; }},
{"!=", [](const Value &a, const Value &b) { return a != b; }},
{">=", [](const Value &a, const Value &b) { return a >= b; }},
{"<=", [](const Value &a, const Value &b) { return a <= b; }},
};

std::string op = node->getText();
std::string op = node->getText();

// Compute indices to keep
std::vector<Value::INT> indicesToKeep;
for (size_t i = 0; i < col->data->size(); ++i) {
Value val = *(*col->data)[i];
if (ops[op](val, filterVal)) {
indicesToKeep.push_back(i);
}
// Compute indices to keep
std::vector<Value::INT> indicesToKeep;
for (size_t i = 0; i < col->data->size(); ++i) {
Value val = *(*col->data)[i];
if (ops[op](val, filterVal)) {
indicesToKeep.push_back(i);
}
}

// Create new columns with filtered data and insert into new table
Value::TABLE table = col->parent;
Value::TABLE newTable = std::make_shared<std::map<Value::STR, Value::COLUMN>>();
for (const std::pair<const Value::STR, Value::COLUMN> &entry : *table) {
Value::LIST newData = std::make_shared<std::vector<std::shared_ptr<Value>>>();
for (Value::INT index : indicesToKeep) {
newData->emplace_back((*entry.second->data)[index]);
}

Value::COLUMN newCol = std::make_shared<Value::COL_STRUCT>();
newCol->parent = newTable;
newCol->header = entry.first;
newCol->data = newData;
newTable->insert({entry.first, newCol});
// Create new columns with filtered data and insert into new table
Value::TABLE table = col->parent;
Value::TABLE newTable = std::make_shared<std::map<Value::STR, Value::COLUMN>>();
for (const std::pair<const Value::STR, Value::COLUMN> &entry : *table) {
Value::LIST newData = std::make_shared<std::vector<std::shared_ptr<Value>>>();
for (Value::INT index : indicesToKeep) {
newData->emplace_back((*entry.second->data)[index]);
}

node->setVal(newTable);
} else {
throw RuntimeException("Filter operation not allowed for this type");
Value::COLUMN newCol = std::make_shared<Value::COL_STRUCT>();
newCol->parent = newTable;
newCol->header = entry.first;
newCol->data = newData;
newTable->insert({entry.first, newCol});
}

node->setVal(newTable);
}

void Evaluator::visit(const std::shared_ptr<GreaterEqualExprNode> &node) {
Expand Down Expand Up @@ -784,7 +781,7 @@ void Evaluator::visit(const std::shared_ptr<WhileNode> &node) {

condNode->accept(shared_from_this());

if (!(condNode->getVal().isNumeric())) {
if (!(condNode->getVal().isNumeric())) { // should probably be changed to bool cuz string and list shouldalso work
throw RuntimeException("Invalid type");
}
while (condNode->getVal().getNumericValue() != 0.0) {
Expand Down
33 changes: 25 additions & 8 deletions src/Value.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -492,8 +492,19 @@ Value Value::operator%(const Value& other) const {
(val2.is<BOOL>() && val2.get<BOOL>() == false)) {
throw InternalException("Cannot take remainder of values with divisor 0");
}
return Value(std::fmod(((val1.is<INT>()) ? val1.get<INT>() : val1.get<FLOAT>()),
((val2.is<INT>()) ? val2.get<INT>() : val2.get<FLOAT>())));
if (!val1.is<FLOAT>() && !val2.is<FLOAT>()) {
Value::INT int1 = (val1.is<INT>()) ? val1.get<INT>() : val1.get<BOOL>();
Value::INT int2 = (val2.is<INT>()) ? val2.get<INT>() : val2.get<BOOL>();

return Value::INT(std::fmod(int1, int2));
}
auto float1 = (val1.is<INT>()) ? val1.get<INT>() :
(val1.is<FLOAT>()) ? val1.get<FLOAT>() : val1.get<BOOL>();

auto float2 = (val2.is<INT>()) ? val2.get<INT>() :
(val2.is<FLOAT>()) ? val2.get<FLOAT>() : val2.get<BOOL>();

return Value(std::fmod(float1, float2));

};
return Value::binaryOperator(other, errOpWord, op);
Expand All @@ -503,17 +514,23 @@ Value Value::pow(const Value& other) const {
std::string errOpWord = "get exponent between";
const std::function<Value(Value, Value)> op = [](const Value& val1,
const Value& val2) -> Value {
if (!val1.isNumeric() && val2.isNumeric()) {
if (!val1.isNumeric() && !val2.isNumeric()) {
throw InternalException("Cannot get exponent between values of type " +
val1.toTypeString() + " and " + val2.toTypeString());
}
auto num1 = (val1.is<INT>()) ? val1.get<INT>() :
(val1.is<FLOAT>()) ? val1.get<FLOAT>() : val1.get<BOOL>();
if (!val1.is<FLOAT>() && !val2.is<FLOAT>()) {
Value::INT int1 = (val1.is<INT>()) ? val1.get<INT>() : val1.get<BOOL>();
Value::INT int2 = (val2.is<INT>()) ? val2.get<INT>() : val2.get<BOOL>();

return Value::INT(std::pow(int1, int2));
}
auto float1 = (val1.is<INT>()) ? val1.get<INT>() :
(val1.is<FLOAT>()) ? val1.get<FLOAT>() : val1.get<BOOL>();

auto num2 = (val2.is<INT>()) ? val2.get<INT>() :
(val2.is<FLOAT>()) ? val2.get<FLOAT>() : val2.get<BOOL>();
auto float2 = (val2.is<INT>()) ? val2.get<INT>() :
(val2.is<FLOAT>()) ? val2.get<FLOAT>() : val2.get<BOOL>();

return Value(std::pow(num1, num2));
return Value(std::pow(float1, float2));
};
return Value::binaryOperator(other, errOpWord, op);
}
Expand Down
2 changes: 1 addition & 1 deletion src/ast/AstBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -541,7 +541,7 @@ antlrcpp::Any AstBuilder::flowStm(tree::TerminalNode* node) {
newNode->setRule(lexerRule);
newNode->setText(node->getText());

currentNode->addChild(newNode); // Error here
currentNode->addChild(newNode); // error here

return nullptr;
}
Expand Down
5 changes: 2 additions & 3 deletions src/ast/nodes/IfNode.cpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
#include <DplParserBaseVisitor.h>

#include <IfNode.hpp>

Check notice on line 1 in src/ast/nodes/IfNode.cpp

View workflow job for this annotation

GitHub Actions / lint

Run clang-format on src/ast/nodes/IfNode.cpp

File src/ast/nodes/IfNode.cpp does not conform to Custom style guidelines. (lines 7)
#include <ElseNode.hpp>

void IfNode::addChild(std::shared_ptr<AstNode> node) {
if (condNode->getChildNode() == nullptr) {
condNode->addChild(node);
} else if (node->getRule() == dplgrammar::DplParser::RuleElsestm) {
} else if (dynamic_cast<ElseNode*>(node.get())) { // continue and else same rule index
elseNode->addChild(node);
} else {
bodyNodeList->addChild(node);
Expand Down
35 changes: 34 additions & 1 deletion tests/TestingUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,10 @@ void TestingUtil::testAst(std::string testFileName, std::vector<size_t> expected
root->accept(visitor);
}

void TestingUtil::testEval(std::string testFileName, std::vector<std::pair<std::string, dplsrc::Value>> expectedVarVec) {
void TestingUtil::testEval(std::string testFileName,
std::vector<std::pair<std::string, dplsrc::Value>> expectedVarVec,
std::vector<std::string> expectedOutputLines) {

std::string filePath = std::filesystem::path(std::string{exampleLocation} + testFileName).string();

if (!std::filesystem::exists(filePath)) {
Expand Down Expand Up @@ -149,11 +152,16 @@ void TestingUtil::testEval(std::string testFileName, std::vector<std::pair<std::
}

std::shared_ptr<dplsrc::Evaluator> evaluator;

try {
std::freopen("../../testOutput.txt", "w", stdout);
evaluator = std::make_shared<dplsrc::Evaluator>();
root->accept(evaluator);
std::fclose(stdout);
} catch (const dplsrc::DplException &e) {
std::fclose(stdout);
std::cerr << e.what() << '\n';
FAIL("Evaluator failed to evaluate");
}

dplsrc::VariableTable varTable = evaluator->getVtable();
Expand All @@ -178,4 +186,29 @@ void TestingUtil::testEval(std::string testFileName, std::vector<std::pair<std::
" and expected value: " + expectedVal.toString());
}
}

std::ifstream printFile("../../testOutput.txt");
std::string line;
std::vector<std::string> lines;

while (std::getline(printFile, line)) {
lines.push_back(line);
}

printFile.close();
std::remove("../../testOutput.txt");

if (lines.size() != expectedOutputLines.size()) {
FAIL("Printed output doesn't have the correct amount of lines");
for (std::string l : lines) {
std::cout << l << '\n';
}
}

for (size_t i = 0; i < lines.size(); ++i) {
if (lines[i] != expectedOutputLines[i]) {
FAIL("Printed output " + lines[i] + "doesn't match expected output" + expectedOutputLines[i]);
}
}

}
10 changes: 9 additions & 1 deletion tests/eval/BreakEvalTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,16 @@ using namespace dplgrammar;

EVAL_TEST("break.dpl") {
std::vector<std::pair<std::string, dplsrc::Value>> expectedVarVec;
std::vector<std::string> expectedOutputLines;
int i = 0;
while (true) {
i++;
if (i == 10) break;
expectedOutputLines.push_back("Loop until break!");
}


expectedVarVec.push_back(std::make_pair("i", dplsrc::Value(10)));

dplutil::TestingUtil::testEval("break.dpl", expectedVarVec);
dplutil::TestingUtil::testEval("break.dpl", expectedVarVec, expectedOutputLines);
}
9 changes: 8 additions & 1 deletion tests/eval/ContinueEvalTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,15 @@ using namespace dplgrammar;

EVAL_TEST("continue.dpl") {
std::vector<std::pair<std::string, dplsrc::Value>> expectedVarVec;
std::vector<std::string> expectedOutputLines;

expectedOutputLines.push_back("1");
expectedOutputLines.push_back("3");
expectedOutputLines.push_back("5");
expectedOutputLines.push_back("7");
expectedOutputLines.push_back("9");

expectedVarVec.push_back(std::make_pair("i", dplsrc::Value(10)));

dplutil::TestingUtil::testEval("continue.dpl", expectedVarVec);
dplutil::TestingUtil::testEval("continue.dpl", expectedVarVec, expectedOutputLines);
}
4 changes: 3 additions & 1 deletion tests/eval/GcdEvalTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ using namespace dplgrammar;

EVAL_TEST("gcd.dpl") {
std::vector<std::pair<std::string, dplsrc::Value>> expectedVarVec;
std::vector<std::string> expectedOutputLines;

expectedOutputLines.push_back("5");

dplutil::TestingUtil::testEval("gcd.dpl", expectedVarVec);
dplutil::TestingUtil::testEval("gcd.dpl", expectedVarVec, expectedOutputLines);
}
8 changes: 7 additions & 1 deletion tests/eval/MathEvalTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,17 @@ using namespace dplgrammar;

EVAL_TEST("math.dpl") {
std::vector<std::pair<std::string, dplsrc::Value>> expectedVarVec;
std::vector<std::string> expectedOutputLines;

expectedOutputLines.push_back("8");
expectedOutputLines.push_back("6");
expectedOutputLines.push_back("5.0");
expectedOutputLines.push_back("0");

expectedVarVec.push_back(std::make_pair("i", dplsrc::Value(0)));
expectedVarVec.push_back(std::make_pair("z", dplsrc::Value(5.0)));
expectedVarVec.push_back(std::make_pair("y", dplsrc::Value(6)));
expectedVarVec.push_back(std::make_pair("x", dplsrc::Value(8)));

dplutil::TestingUtil::testEval("math.dpl", expectedVarVec);
dplutil::TestingUtil::testEval("math.dpl", expectedVarVec, expectedOutputLines);
}
5 changes: 4 additions & 1 deletion tests/eval/NotAndOrEvalTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ using namespace dplgrammar;

EVAL_TEST("not_and_or.dpl") {
std::vector<std::pair<std::string, dplsrc::Value>> expectedVarVec;
std::vector<std::string> expectedOutputLines;

expectedOutputLines.push_back("test");

expectedVarVec.push_back(std::make_pair("x", dplsrc::Value(false)));

dplutil::TestingUtil::testEval("not_and_or.dpl", expectedVarVec);
dplutil::TestingUtil::testEval("not_and_or.dpl", expectedVarVec, expectedOutputLines);
}
5 changes: 4 additions & 1 deletion tests/eval/QuicksortEvalTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ using namespace dplgrammar;

EVAL_TEST("quicksort.dpl") {
std::vector<std::pair<std::string, dplsrc::Value>> expectedVarVec;
std::vector<std::string> expectedOutputLines;

expectedOutputLines.push_back("Sorted list: [1, 1, 2, 3, 3, 4, 5, 5, 5, 6, 9]");

dplsrc::Value::LIST list = std::make_shared<std::vector<std::shared_ptr<dplsrc::Value>>>();

Expand All @@ -22,5 +25,5 @@ EVAL_TEST("quicksort.dpl") {

expectedVarVec.push_back(std::make_pair("A", list));

dplutil::TestingUtil::testEval("quicksort.dpl", expectedVarVec);
dplutil::TestingUtil::testEval("quicksort.dpl", expectedVarVec, expectedOutputLines);
}
6 changes: 4 additions & 2 deletions tests/eval/ReplaceWithEvalTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ using namespace dplgrammar;

EVAL_TEST("replace_with.dpl") {
std::vector<std::pair<std::string, dplsrc::Value>> expectedVarVec;

std::vector<std::string> expectedOutputLines;

expectedOutputLines.push_back("{ \'area\': [4, 18], \'height\': [4, 6], \'width\': [1, 3] }");

//
// TABLE 1
Expand Down Expand Up @@ -106,5 +108,5 @@ EVAL_TEST("replace_with.dpl") {
expectedVarVec.push_back({"t2", dplsrc::Value(table2)});
expectedVarVec.push_back({"t3", dplsrc::Value(columnT3Area)});

dplutil::TestingUtil::testEval("replace_with.dpl", expectedVarVec);
dplutil::TestingUtil::testEval("replace_with.dpl", expectedVarVec, expectedOutputLines);
}
Loading

0 comments on commit b178310

Please sign in to comment.