Skip to content

Commit

Permalink
fix: fix typechecking for variadics vs function defs. also fixes all …
Browse files Browse the repository at this point in the history
…tests
  • Loading branch information
alexdovzhanyn committed Sep 3, 2024
1 parent 718fb3c commit 4306171
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 20 deletions.
30 changes: 22 additions & 8 deletions src/compiler/TypeChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ namespace Theta {

bool TypeChecker::checkAssignmentNode(shared_ptr<AssignmentNode> node) {
bool typesMatch = isSameType(node->getLeft()->getValue(), node->getRight()->getResolvedType());

shared_ptr<IdentifierNode> ident = dynamic_pointer_cast<IdentifierNode>(node->getLeft());

if (!typesMatch) {
Expand Down Expand Up @@ -485,8 +485,10 @@ namespace Theta {

shared_ptr<TypeDeclarationNode> type = make_shared<TypeDeclarationNode>(DataTypes::TUPLE, node);

type->setLeft(node->getLeft()->getResolvedType());
type->setRight(node->getRight()->getResolvedType());
type->setElements({
node->getLeft()->getResolvedType(),
node->getRight()->getResolvedType()
});

node->setResolvedType(type);

Expand Down Expand Up @@ -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();
Expand Down
28 changes: 16 additions & 12 deletions test/TypeCheckerTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ TEST_CASE_METHOD(TypeCheckerTest, "TypeChecker") {
SECTION("Can typecheck function assignents with parameters correctly") {
shared_ptr<ASTNode> ast = setup(R"(
capsule Test {
x<Function<String>> = (a<String>) -> a
x<Function<String, String>> = (a<String>) -> a
}
)");

Expand All @@ -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);
}
Expand All @@ -270,7 +274,7 @@ TEST_CASE_METHOD(TypeCheckerTest, "TypeChecker") {
SECTION("Can typecheck curried functions correctly") {
shared_ptr<ASTNode> ast = setup(R"(
capsule Test {
x<Function<Function<Number>>> = (a<Number>) -> (b<Number>) -> a + b
x<Function<Number, Function<Number, Number>>> = (a<Number>) -> (b<Number>) -> a + b
}
)");

Expand All @@ -289,7 +293,7 @@ TEST_CASE_METHOD(TypeCheckerTest, "TypeChecker") {
:HIGH
}
severityIdent<Function<Severity>> = (sev<Severity>) -> {
severityIdent<Function<Severity, Severity>> = (sev<Severity>) -> {
sev
}
}
Expand All @@ -304,7 +308,7 @@ TEST_CASE_METHOD(TypeCheckerTest, "TypeChecker") {
SECTION("Can typecheck control flow correctly") {
shared_ptr<ASTNode> ast = setup(R"(
capsule Test {
isEven<Function<Boolean>> = (num<Number>) -> {
isEven<Function<Number, Boolean>> = (num<Number>) -> {
if (num % 2 == 0) {
return true
} else if (num % 3 == 0) {
Expand All @@ -325,7 +329,7 @@ TEST_CASE_METHOD(TypeCheckerTest, "TypeChecker") {
SECTION("Throws if control flow condition is not a boolean") {
shared_ptr<ASTNode> ast = setup(R"(
capsule Test {
isLongString<Function<Boolean>> = (str<String>) -> {
isLongString<Function<String, Boolean>> = (str<String>) -> {
if (str) {
return true
}
Expand All @@ -342,7 +346,7 @@ TEST_CASE_METHOD(TypeCheckerTest, "TypeChecker") {
SECTION("Can typecheck recursive functions correctly") {
shared_ptr<ASTNode> ast = setup(R"(
capsule Test {
addUntilTen<Function<Number>> = (sum<Number>) -> {
addUntilTen<Function<Number, Number>> = (sum<Number>) -> {
if (sum == 10) {
return sum
}
Expand Down Expand Up @@ -406,9 +410,9 @@ TEST_CASE_METHOD(TypeCheckerTest, "TypeChecker") {
SECTION("Can typecheck function overloads correctly") {
shared_ptr<ASTNode> ast = setup(R"(
capsule Test {
add<Function<Number>> = (x<Number>) -> x
add<Function<Number>> = (x<Number>, y<Number>) -> x + y
add<Function<Number>> = (x<Number>, y<String>) -> x
add<Function<Number, Number>> = (x<Number>) -> x
add<Function<Number, Number, Number>> = (x<Number>, y<Number>) -> x + y
add<Function<Number, String, Number>> = (x<Number>, y<String>) -> x
doTheThing<Function<Number>> = () -> {
add(1)
Expand Down Expand Up @@ -501,7 +505,7 @@ TEST_CASE_METHOD(TypeCheckerTest, "TypeChecker") {
y<Number>
}
addPoints<Function<Point>> = (p1<Point>, p2<Point>) -> {
addPoints<Function<Point, Point, Point>> = (p1<Point>, p2<Point>) -> {
@Point {
x: 4,
y: 2
Expand All @@ -524,7 +528,7 @@ TEST_CASE_METHOD(TypeCheckerTest, "TypeChecker") {
y<Number>
}
addPoints<Function<Point>> = (p1<Point>, p2<Point>) -> {
addPoints<Function<Point, Point, Point>> = (p1<Point>, p2<Point>) -> {
@Point {
x: 4
}
Expand Down Expand Up @@ -608,7 +612,7 @@ TEST_CASE_METHOD(TypeCheckerTest, "TypeChecker") {
capsule Test {
z<Number> = 5
add<Function<Function<Number>>> = (x<Number>) -> (y<Number>) -> x + y + z
add<Function<Number, Function<Number, Number>>> = (x<Number>) -> (y<Number>) -> x + y + z
}
)");

Expand Down

0 comments on commit 4306171

Please sign in to comment.