From 43061717157f80b733d1c6cebe36953385f41dbe Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 2 Sep 2024 22:52:18 -0400 Subject: [PATCH] fix: fix typechecking for variadics vs function defs. also fixes all tests --- src/compiler/TypeChecker.cpp | 30 ++++++++++++++++++++++-------- test/TypeCheckerTest.cpp | 28 ++++++++++++++++------------ 2 files changed, 38 insertions(+), 20 deletions(-) diff --git a/src/compiler/TypeChecker.cpp b/src/compiler/TypeChecker.cpp index d0e86da..9961162 100644 --- a/src/compiler/TypeChecker.cpp +++ b/src/compiler/TypeChecker.cpp @@ -137,7 +137,7 @@ namespace Theta { bool TypeChecker::checkAssignmentNode(shared_ptr node) { bool typesMatch = isSameType(node->getLeft()->getValue(), node->getRight()->getResolvedType()); - + shared_ptr ident = dynamic_pointer_cast(node->getLeft()); if (!typesMatch) { @@ -485,8 +485,10 @@ namespace Theta { shared_ptr type = make_shared(DataTypes::TUPLE, node); - type->setLeft(node->getLeft()->getResolvedType()); - type->setRight(node->getRight()->getResolvedType()); + type->setElements({ + node->getLeft()->getResolvedType(), + node->getRight()->getResolvedType() + }); node->setResolvedType(type); @@ -769,15 +771,27 @@ namespace Theta { if (!containsType) return false; } } else if (t1->hasMany() && t2->hasMany()) { - for (int i = 0; i < t2->getElements().size(); i++) { - bool containsType = false; + if (t1->getType() == DataTypes::VARIADIC) { + // In Variadic types, it makes sense that the types on the right can be any of the values defined + // on the left, in any order + for (int i = 0; i < t2->getElements().size(); i++) { + bool containsType = false; + + for (int j = 0; j < t1->getElements().size(); j++) { + if (isSameType(t2->getElements().at(i), t1->getElements().at(j))) containsType = true; + } - for (int j = 0; j < t1->getElements().size(); j++) { - if (isSameType(t2->getElements().at(i), t1->getElements().at(j))) containsType = true; + if (!containsType) return false; } + } else { + // In every other case, though, order matters. The left and right types must be exactly the same + if (t1->getElements().size() != t2->getElements().size()) return false; - if (!containsType) return false; + for (int i = 0; i < t1->getElements().size(); i++) { + if (!isSameType(t1->getElements().at(i), t2->getElements().at(i))) return false; + } } + } return t1->getType() == t2->getType(); diff --git a/test/TypeCheckerTest.cpp b/test/TypeCheckerTest.cpp index 571c0b3..7d289cb 100644 --- a/test/TypeCheckerTest.cpp +++ b/test/TypeCheckerTest.cpp @@ -223,7 +223,7 @@ TEST_CASE_METHOD(TypeCheckerTest, "TypeChecker") { SECTION("Can typecheck function assignents with parameters correctly") { shared_ptr ast = setup(R"( capsule Test { - x> = (a) -> a + x> = (a) -> a } )"); @@ -246,6 +246,10 @@ TEST_CASE_METHOD(TypeCheckerTest, "TypeChecker") { bool isValid = typeChecker.checkAST(ast); + for (auto ex : Compiler::getInstance().getEncounteredExceptions()) { + ex->display(); + } + REQUIRE(isValid); REQUIRE(Compiler::getInstance().getEncounteredExceptions().size() == 0); } @@ -270,7 +274,7 @@ TEST_CASE_METHOD(TypeCheckerTest, "TypeChecker") { SECTION("Can typecheck curried functions correctly") { shared_ptr ast = setup(R"( capsule Test { - x>> = (a) -> (b) -> a + b + x>> = (a) -> (b) -> a + b } )"); @@ -289,7 +293,7 @@ TEST_CASE_METHOD(TypeCheckerTest, "TypeChecker") { :HIGH } - severityIdent> = (sev) -> { + severityIdent> = (sev) -> { sev } } @@ -304,7 +308,7 @@ TEST_CASE_METHOD(TypeCheckerTest, "TypeChecker") { SECTION("Can typecheck control flow correctly") { shared_ptr ast = setup(R"( capsule Test { - isEven> = (num) -> { + isEven> = (num) -> { if (num % 2 == 0) { return true } else if (num % 3 == 0) { @@ -325,7 +329,7 @@ TEST_CASE_METHOD(TypeCheckerTest, "TypeChecker") { SECTION("Throws if control flow condition is not a boolean") { shared_ptr ast = setup(R"( capsule Test { - isLongString> = (str) -> { + isLongString> = (str) -> { if (str) { return true } @@ -342,7 +346,7 @@ TEST_CASE_METHOD(TypeCheckerTest, "TypeChecker") { SECTION("Can typecheck recursive functions correctly") { shared_ptr ast = setup(R"( capsule Test { - addUntilTen> = (sum) -> { + addUntilTen> = (sum) -> { if (sum == 10) { return sum } @@ -406,9 +410,9 @@ TEST_CASE_METHOD(TypeCheckerTest, "TypeChecker") { SECTION("Can typecheck function overloads correctly") { shared_ptr ast = setup(R"( capsule Test { - add> = (x) -> x - add> = (x, y) -> x + y - add> = (x, y) -> x + add> = (x) -> x + add> = (x, y) -> x + y + add> = (x, y) -> x doTheThing> = () -> { add(1) @@ -501,7 +505,7 @@ TEST_CASE_METHOD(TypeCheckerTest, "TypeChecker") { y } - addPoints> = (p1, p2) -> { + addPoints> = (p1, p2) -> { @Point { x: 4, y: 2 @@ -524,7 +528,7 @@ TEST_CASE_METHOD(TypeCheckerTest, "TypeChecker") { y } - addPoints> = (p1, p2) -> { + addPoints> = (p1, p2) -> { @Point { x: 4 } @@ -608,7 +612,7 @@ TEST_CASE_METHOD(TypeCheckerTest, "TypeChecker") { capsule Test { z = 5 - add>> = (x) -> (y) -> x + y + z + add>> = (x) -> (y) -> x + y + z } )");