2026-08-01 22:12:05 +10:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
#include "type.hpp"
|
|
|
|
|
#include "../parser/parser.hpp"
|
|
|
|
|
|
|
|
|
|
#include <string>
|
|
|
|
|
#include <unordered_map>
|
|
|
|
|
|
|
|
|
|
namespace Solstice {
|
|
|
|
|
|
2026-08-02 18:03:31 +10:00
|
|
|
enum class Narrowing {
|
|
|
|
|
None,
|
|
|
|
|
Left,
|
|
|
|
|
Right,
|
|
|
|
|
Both
|
|
|
|
|
};
|
|
|
|
|
|
2026-08-01 22:12:05 +10:00
|
|
|
class TypeChecker {
|
2026-08-02 15:14:43 +10:00
|
|
|
std::unordered_map<std::string, PossibleType> variables;
|
2026-08-01 22:12:05 +10:00
|
|
|
std::unordered_map<std::string, Type> types;
|
2026-08-03 08:15:48 +10:00
|
|
|
std::unordered_map<std::string, Function> functions;
|
2026-08-01 22:12:05 +10:00
|
|
|
|
|
|
|
|
std::unordered_map<TypePair, Type> addOverloads;
|
|
|
|
|
std::unordered_map<TypePair, Type> subtractOverloads;
|
|
|
|
|
std::unordered_map<TypePair, Type> multiplyOverloads;
|
|
|
|
|
std::unordered_map<TypePair, Type> divideOverloads;
|
|
|
|
|
std::unordered_map<TypePair, Type> equalOverloads;
|
|
|
|
|
std::unordered_map<TypePair, Type> notEqualOverloads;
|
|
|
|
|
std::unordered_map<TypePair, Type> greaterThanOverloads;
|
|
|
|
|
std::unordered_map<TypePair, Type> lesserThanOverloads;
|
|
|
|
|
|
2026-08-02 15:14:43 +10:00
|
|
|
Node* input;
|
2026-08-01 22:12:05 +10:00
|
|
|
|
2026-08-02 14:09:38 +10:00
|
|
|
bool inFunction = false;
|
|
|
|
|
|
2026-08-01 22:12:05 +10:00
|
|
|
void initOverloads();
|
|
|
|
|
|
2026-08-02 08:59:18 +10:00
|
|
|
void checkLiteralNodeType(Node& node);
|
|
|
|
|
void checkIdentifierNodeType(Node& node);
|
|
|
|
|
void checkTupleNodeType(Node& node);
|
|
|
|
|
|
2026-08-02 14:09:38 +10:00
|
|
|
void checkBindNodeType(Node& node);
|
|
|
|
|
void checkFunctionBindNodeType(Node& node);
|
|
|
|
|
void checkSetNodeType(Node& node);
|
|
|
|
|
|
|
|
|
|
void checkCodeBlockType(Node& node);
|
|
|
|
|
|
2026-08-02 18:03:31 +10:00
|
|
|
Narrowing doesNodeChildrenNeedNarrowing(Node& node);
|
|
|
|
|
void narrowBinaryNode(Node& node, std::unordered_map<TypePair, Type>& overloads);
|
2026-08-03 20:03:54 +10:00
|
|
|
void narrowFunctionCallNode(Node& node);
|
2026-08-02 18:03:31 +10:00
|
|
|
|
2026-08-02 15:14:43 +10:00
|
|
|
void checkAddType(Node& node);
|
|
|
|
|
void checkSubtractType(Node& node);
|
|
|
|
|
void checkMultiplyType(Node& node);
|
|
|
|
|
void checkDivideType(Node& node);
|
|
|
|
|
|
|
|
|
|
void checkEqualType(Node& node);
|
|
|
|
|
void checkNotEqualType(Node& node);
|
|
|
|
|
void checkGreaterThanType(Node& node);
|
|
|
|
|
void checkLesserThanType(Node& node);
|
|
|
|
|
|
2026-08-02 08:59:18 +10:00
|
|
|
void checkNodeType(Node& node);
|
|
|
|
|
|
2026-08-01 22:12:05 +10:00
|
|
|
public:
|
|
|
|
|
|
|
|
|
|
TypeChecker() = delete;
|
2026-08-02 15:14:43 +10:00
|
|
|
TypeChecker(Node& node) : input(&node) {
|
2026-08-01 22:12:05 +10:00
|
|
|
initOverloads();
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-02 15:14:43 +10:00
|
|
|
void setNode(Node& node) {
|
|
|
|
|
input = &node;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Only for use as a public function.
|
|
|
|
|
void setVariable(const std::string& name, const Type& type) {
|
|
|
|
|
variables[name] = {{type}};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void setVariableUnknown(const std::string& name) {
|
|
|
|
|
variables[name].unknownType = true;
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-01 22:12:05 +10:00
|
|
|
void checkTypes();
|
2026-08-03 08:15:48 +10:00
|
|
|
|
|
|
|
|
const Function* getFunction(const std::string& name) const {
|
|
|
|
|
auto it = functions.find(name);
|
|
|
|
|
if (it == functions.end()) {
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
return &it->second;
|
|
|
|
|
}
|
2026-08-01 22:12:05 +10:00
|
|
|
};
|
|
|
|
|
}
|