diff --git a/CMakeLists.txt b/CMakeLists.txt index 5039626e2..5f23b7581 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -63,8 +63,8 @@ if (BOLT_ENABLE_TESTS) add_subdirectory(deps/googletest EXCLUDE_FROM_ALL) add_executable( alltests - src/TestText.cc - src/TestChecker.cc + test/TestText.cc + test/TestChecker.cc ) target_link_libraries( alltests diff --git a/include/bolt/DiagnosticEngine.hpp b/include/bolt/DiagnosticEngine.hpp index 7276f91a2..272a0b35e 100644 --- a/include/bolt/DiagnosticEngine.hpp +++ b/include/bolt/DiagnosticEngine.hpp @@ -54,6 +54,10 @@ namespace bolt { Diagnostics.clear(); } + std::size_t countDiagnostics() const noexcept { + return Diagnostics.size(); + } + ~DiagnosticStore(); }; diff --git a/include/bolt/Diagnostics.hpp b/include/bolt/Diagnostics.hpp index 888913636..e89b3b596 100644 --- a/include/bolt/Diagnostics.hpp +++ b/include/bolt/Diagnostics.hpp @@ -99,6 +99,14 @@ namespace bolt { inline UnificationErrorDiagnostic(Type* OrigLeft, Type* OrigRight, TypePath LeftPath, TypePath RightPath, Node* Source): Diagnostic(DiagnosticKind::UnificationError), OrigLeft(OrigLeft), OrigRight(OrigRight), LeftPath(LeftPath), RightPath(RightPath), Source(Source) {} + inline Type* getLeft() const { + return OrigLeft->resolve(LeftPath); + } + + inline Type* getRight() const { + return OrigRight->resolve(RightPath); + } + inline Node* getNode() const override { return Source; } diff --git a/src/Diagnostics.cc b/src/Diagnostics.cc index 6740f1f6e..5937e7a33 100644 --- a/src/Diagnostics.cc +++ b/src/Diagnostics.cc @@ -288,9 +288,9 @@ namespace bolt { } DiagnosticStore::~DiagnosticStore() { - for (auto D: Diagnostics) { - delete D; - } + // for (auto D: Diagnostics) { + // delete D; + // } } ConsoleDiagnostics::ConsoleDiagnostics(std::ostream& Out): diff --git a/src/TestChecker.cc b/src/TestChecker.cc deleted file mode 100644 index 663630477..000000000 --- a/src/TestChecker.cc +++ /dev/null @@ -1,33 +0,0 @@ - -#include "gtest/gtest.h" - -#include "bolt/CST.hpp" -#include "bolt/Diagnostics.hpp" -#include "bolt/Scanner.hpp" -#include "bolt/Parser.hpp" -#include "bolt/Checker.hpp" - -using namespace bolt; - -auto checkExpression(std::string Input) { - ConsoleDiagnostics DS; - TextFile T { "#", Input }; - VectorStream Chars { Input, EOF }; - Scanner S(T, Chars); - Punctuator PT(S); - Parser P(T, PT); - LanguageConfig Config; - auto SF = P.parseSourceFile(); - Checker C(Config, DS); - C.check(SF); - return std::make_tuple( - static_cast(SF->Elements[0])->Expression, - C - ); -} - -TEST(CheckerTest, InfersIntFromIntegerLiteral) { - auto [Expression, Checker] = checkExpression("1"); - ASSERT_EQ(Checker.getType(Expression), Checker.getIntType()); -} - diff --git a/src/main.cc b/src/main.cc index e1fdb7433..b63f2a5ed 100644 --- a/src/main.cc +++ b/src/main.cc @@ -103,7 +103,7 @@ int main(int Argc, const char* Argv[]) { std::sort(DS.Diagnostics.begin(), DS.Diagnostics.end(), lessThan); for (auto D: DS.Diagnostics) { - DE.printDiagnostic(*D); + DE.addDiagnostic(D); } if (DE.hasError()) { diff --git a/test/TestChecker.cc b/test/TestChecker.cc new file mode 100644 index 000000000..86393f11d --- /dev/null +++ b/test/TestChecker.cc @@ -0,0 +1,53 @@ + +#include "gtest/gtest.h" + +#include "bolt/CST.hpp" +#include "bolt/Diagnostics.hpp" +#include "bolt/DiagnosticEngine.hpp" +#include "bolt/Scanner.hpp" +#include "bolt/Parser.hpp" +#include "bolt/Checker.hpp" + +using namespace bolt; + +auto checkSourceFile(std::string Input) { + DiagnosticStore DS; + TextFile T { "#", Input }; + VectorStream Chars { Input, EOF }; + Scanner S(T, Chars); + Punctuator PT(S); + Parser P(T, PT, DS); + LanguageConfig Config; + auto SF = P.parseSourceFile(); + SF->setParents(); + Checker C(Config, DS); + C.check(SF); + return std::make_tuple(SF, C, DS); +} + +auto checkExpression(std::string Input) { + auto [SF, C, DS] = checkSourceFile(Input); + return std::make_tuple( + static_cast(SF->Elements[0])->Expression, + C, + DS + ); +} + +TEST(CheckerTest, InfersIntFromIntegerLiteral) { + auto [Expr, Checker, DS] = checkExpression("1"); + ASSERT_EQ(DS.countDiagnostics(), 0); + ASSERT_EQ(Checker.getType(Expr), Checker.getIntType()); +} + +TEST(CheckerTest, TestIllegalTypingVariable) { + auto [SF, C, DS] = checkSourceFile("let a: Int = \"foo\""); + ASSERT_EQ(DS.countDiagnostics(), 1); + auto D1 = DS.Diagnostics[0]; + ASSERT_EQ(D1->getKind(), DiagnosticKind::UnificationError); + auto Diag = static_cast(D1); + // TODO these types have to be sorted first + ASSERT_EQ(Diag->getLeft(), C.getIntType()); + ASSERT_EQ(Diag->getRight(), C.getStringType()); +} + diff --git a/src/TestText.cc b/test/TestText.cc similarity index 81% rename from src/TestText.cc rename to test/TestText.cc index 7cf5f2465..b7256a5c0 100644 --- a/src/TestText.cc +++ b/test/TestText.cc @@ -1,7 +1,7 @@ #include "gtest/gtest.h" -#include "bolt/Text.hpp" +#include "bolt/CST.hpp" using namespace bolt; @@ -23,11 +23,11 @@ TEST(TextFileTest, ReportsCorrectLine) { TEST(TextFileTest, ReportsCorrectStartOffset) { TextFile T1 { "foo.txt", "bar\nbaz\nbax\n" }; - ASSERT_EQ(T1.getStartOffset(1), 0); - ASSERT_EQ(T1.getStartOffset(2), 4); - ASSERT_EQ(T1.getStartOffset(3), 8); - ASSERT_EQ(T1.getStartOffset(4), 12); - ASSERT_EQ(T1.getStartOffset(5), 12); + ASSERT_EQ(T1.getStartOffsetOfLine(1), 0); + ASSERT_EQ(T1.getStartOffsetOfLine(2), 4); + ASSERT_EQ(T1.getStartOffsetOfLine(3), 8); + ASSERT_EQ(T1.getStartOffsetOfLine(4), 12); + ASSERT_EQ(T1.getStartOffsetOfLine(5), 12); } TEST(TextFileTest, ReportsCorrectColumn) {