Files
newsolstice/src/typechecker/typechecker.cpp

141 lines
5.6 KiB
C++
Raw Normal View History

2026-08-01 22:12:05 +10:00
#include "typechecker.hpp"
2026-08-02 08:59:18 +10:00
#include "type.hpp"
#include <stdexcept>
2026-08-01 22:12:05 +10:00
namespace Solstice {
void TypeChecker::initOverloads() {
addOverloads = {
{{BaseType::Int, BaseType::Int}, BaseType::Int},
{{BaseType::Double, BaseType::Double}, BaseType::Double},
{{BaseType::Int, BaseType::Double}, BaseType::Double},
{{BaseType::Double, BaseType::Int}, BaseType::Double},
{{BaseType::String, BaseType::String}, BaseType::String},
{{BaseType::String, BaseType::Char}, BaseType::String},
{{BaseType::Char, BaseType::String}, BaseType::String},
{{BaseType::Char, BaseType::Char}, BaseType::Char}
};
subtractOverloads = {
{{BaseType::Int, BaseType::Int}, BaseType::Int},
{{BaseType::Double, BaseType::Double}, BaseType::Double},
{{BaseType::Int, BaseType::Double}, BaseType::Double},
{{BaseType::Double, BaseType::Int}, BaseType::Double},
{{BaseType::Char, BaseType::Char}, BaseType::Char}
};
multiplyOverloads = {
{{BaseType::Int, BaseType::Int}, BaseType::Int},
{{BaseType::Double, BaseType::Double}, BaseType::Double},
{{BaseType::Int, BaseType::Double}, BaseType::Double},
{{BaseType::Double, BaseType::Int}, BaseType::Double},
{{BaseType::Char, BaseType::Char}, BaseType::Char}
};
divideOverloads = {
{{BaseType::Int, BaseType::Int}, BaseType::Double},
{{BaseType::Double, BaseType::Double}, BaseType::Double},
{{BaseType::Int, BaseType::Double}, BaseType::Double},
{{BaseType::Double, BaseType::Int}, BaseType::Double},
{{BaseType::Char, BaseType::Char}, BaseType::Char}
};
equalOverloads = {
{{BaseType::Int, BaseType::Int}, BaseType::Bool},
{{BaseType::Double, BaseType::Double}, BaseType::Bool},
{{BaseType::Int, BaseType::Double}, BaseType::Bool},
{{BaseType::Double, BaseType::Int}, BaseType::Bool},
{{BaseType::String, BaseType::String}, BaseType::Bool},
{{BaseType::Char, BaseType::Char}, BaseType::Bool},
{{BaseType::Bool, BaseType::Bool}, BaseType::Bool},
};
notEqualOverloads = {
{{BaseType::Int, BaseType::Int}, BaseType::Bool},
{{BaseType::Double, BaseType::Double}, BaseType::Bool},
{{BaseType::Int, BaseType::Double}, BaseType::Bool},
{{BaseType::Double, BaseType::Int}, BaseType::Bool},
{{BaseType::String, BaseType::String}, BaseType::Bool},
{{BaseType::Char, BaseType::Char}, BaseType::Bool},
{{BaseType::Bool, BaseType::Bool}, BaseType::Bool},
};
greaterThanOverloads = {
{{BaseType::Int, BaseType::Int}, BaseType::Bool},
{{BaseType::Double, BaseType::Double}, BaseType::Bool},
{{BaseType::Int, BaseType::Double}, BaseType::Bool},
{{BaseType::Double, BaseType::Int}, BaseType::Bool},
{{BaseType::Char, BaseType::Char}, BaseType::Bool},
};
lesserThanOverloads = {
{{BaseType::Int, BaseType::Int}, BaseType::Bool},
{{BaseType::Double, BaseType::Double}, BaseType::Bool},
{{BaseType::Int, BaseType::Double}, BaseType::Bool},
{{BaseType::Double, BaseType::Int}, BaseType::Bool},
{{BaseType::Char, BaseType::Char}, BaseType::Bool},
};
}
2026-08-02 08:59:18 +10:00
void TypeChecker::checkLiteralNodeType(Node& node) {
auto literal = node.getLiteral();
if (!literal.has_value()) {
throw std::runtime_error("FIXME literal node does not contain literal");
}
switch (literal->type) {
case LiteralType::None:
node.ptype = {{BaseType::None}};
break;
case LiteralType::String:
node.ptype = {{BaseType::String}};
break;
case LiteralType::Int:
node.ptype = {{BaseType::Int}};
break;
case LiteralType::Double:
node.ptype = {{BaseType::Double}};
break;
case LiteralType::Bool:
node.ptype = {{BaseType::Bool}};
break;
case LiteralType::Char:
node.ptype = {{BaseType::Char}};
break;
}
}
void TypeChecker::checkIdentifierNodeType(Node& node) {
auto identifier = node.getIdentifier();
if (!identifier.has_value()) {
throw std::runtime_error("FIXME identifier node does not contain identifier");
}
if (variables.find(*identifier) == variables.end()) {
throw std::runtime_error("unknown variable " + *identifier);
}
node.ptype = variables[*identifier];
}
void TypeChecker::checkTupleNodeType(Node& node) {}
void TypeChecker::checkNodeType(Node& node) {
switch (node.type) {
case NodeType::Root:
node.ptype = {{}}; // no possible types for root node
break;
case NodeType::Literal:
checkLiteralNodeType(node);
break;
case NodeType::Expression:
checkNodeType(node.children[0]);
break;
case NodeType::Identifier:
checkIdentifierNodeType(node);
break;
case NodeType::Tuple:
checkTupleNodeType(node);
break;
}
}
void TypeChecker::checkTypes() {
checkNodeType(input);
}
2026-08-01 22:12:05 +10:00
}