Function call type checking and narrowing

This commit is contained in:
2026-08-04 08:14:07 +10:00
parent fa0b3ce34d
commit 7e713430a8

View File

@@ -395,7 +395,7 @@ namespace Solstice {
} }
void TypeChecker::checkFunctionCallNodeType(Node& node) { void TypeChecker::narrowFunctionCallNode(Node& node) {
// get function // get function
auto name = node.children[0].getIdentifier(); auto name = node.children[0].getIdentifier();
if (!name.has_value()) { if (!name.has_value()) {
@@ -408,23 +408,34 @@ namespace Solstice {
auto& function = functions[*name]; auto& function = functions[*name];
// get types we are calling with std::vector<PossibleType> args;
std::vector<Type> args;
// narrow types based on function
for (auto& child : node.children[1].children) { for (auto& child : node.children[1].children) {
checkNodeType(child); checkNodeType(child);
auto childType = child.ptype.getOnlyType(); args.push_back(child.ptype);
if (!childType.has_value()) { }
throw std::runtime_error("cannot call function with ambiguous type");
// 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);
} }
if (!found) {
// find argument type throw std::runtime_error("no matching overload found for function " + *name);
if (function.returnTypes.find(args) == function.returnTypes.end()) {
throw std::runtime_error("no matching function call to " + *name);
} }
}
node.ptype = {{function.returnTypes[args]}}; void TypeChecker::checkFunctionCallNodeType(Node& node) {
narrowFunctionCallNode(node);
} }
void TypeChecker::checkSetNodeType(Node& node) { void TypeChecker::checkSetNodeType(Node& node) {