From 7e713430a8123288ec32674138874348c78c2b37 Mon Sep 17 00:00:00 2001 From: Maxwell Jeffress Date: Tue, 4 Aug 2026 08:14:07 +1000 Subject: [PATCH] Function call type checking and narrowing --- src/typechecker/typechecker.cpp | 35 ++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/src/typechecker/typechecker.cpp b/src/typechecker/typechecker.cpp index 2f9db90..b94db37 100644 --- a/src/typechecker/typechecker.cpp +++ b/src/typechecker/typechecker.cpp @@ -395,7 +395,7 @@ namespace Solstice { } - void TypeChecker::checkFunctionCallNodeType(Node& node) { + void TypeChecker::narrowFunctionCallNode(Node& node) { // get function auto name = node.children[0].getIdentifier(); if (!name.has_value()) { @@ -408,23 +408,34 @@ namespace Solstice { auto& function = functions[*name]; - // get types we are calling with - std::vector args; + std::vector args; + + // narrow types based on function for (auto& child : node.children[1].children) { checkNodeType(child); - auto childType = child.ptype.getOnlyType(); - if (!childType.has_value()) { - throw std::runtime_error("cannot call function with ambiguous type"); + args.push_back(child.ptype); + } + + // get all possible combinations + auto sets = doCartesianProductOnTypeSets(args); + + bool found = false; + for (const auto& set : sets) { + if (function.returnTypes.find(set) != function.returnTypes.end()) { + if (found) { + throw std::runtime_error("conflicting function definitions"); + } + found = true; + node.ptype = {{function.returnTypes[set]}}; } - args.push_back(*childType); } - - // find argument type - if (function.returnTypes.find(args) == function.returnTypes.end()) { - throw std::runtime_error("no matching function call to " + *name); + if (!found) { + throw std::runtime_error("no matching overload found for function " + *name); } + } - node.ptype = {{function.returnTypes[args]}}; + void TypeChecker::checkFunctionCallNodeType(Node& node) { + narrowFunctionCallNode(node); } void TypeChecker::checkSetNodeType(Node& node) {