A bunch more stuffs
This commit is contained in:
@@ -56,4 +56,15 @@ namespace Solstice {
|
||||
return left.left == right.left && left.right == right.right;
|
||||
}
|
||||
|
||||
std::optional<Type> PossibleType::getOnlyType() {
|
||||
if (possiblities.size() != 1) {
|
||||
return {};
|
||||
}
|
||||
for (const auto& type : possiblities) {
|
||||
// just return one
|
||||
return type;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -30,11 +30,13 @@ namespace Solstice {
|
||||
std::nullopt_t
|
||||
> fields = std::nullopt;
|
||||
|
||||
bool isConstant = false;
|
||||
|
||||
std::optional<std::map<std::string, Type>> getObject() const;
|
||||
std::optional<std::vector<Type>> getTuple() const;
|
||||
std::optional<Type> getArrayOrPointer() const;
|
||||
|
||||
Type() = delete;
|
||||
Type() = default;
|
||||
Type(BaseType type) : type(type) {}
|
||||
};
|
||||
|
||||
@@ -106,6 +108,18 @@ namespace Solstice {
|
||||
|
||||
PossibleType() = default;
|
||||
PossibleType(const std::unordered_set<Type>& possiblities) : possiblities(possiblities) {}
|
||||
|
||||
std::optional<Type> getOnlyType();
|
||||
};
|
||||
|
||||
struct Function {
|
||||
PossibleType returnType = {{BaseType::None}};
|
||||
std::vector<PossibleType> argumentTypes = {};
|
||||
|
||||
Function() = default;
|
||||
Function(PossibleType returnType) : returnType(returnType) {}
|
||||
Function(PossibleType returnType, std::vector<PossibleType> argumentTypes)
|
||||
: returnType(returnType), argumentTypes(argumentTypes) {}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "typechecker.hpp"
|
||||
#include "type.hpp"
|
||||
#include <stdexcept>
|
||||
#include <iostream>
|
||||
|
||||
namespace Solstice {
|
||||
|
||||
@@ -107,21 +108,84 @@ namespace Solstice {
|
||||
throw std::runtime_error("unknown variable " + *identifier);
|
||||
}
|
||||
|
||||
node.ptype = variables[*identifier];
|
||||
node.ptype = {{variables[*identifier]}};
|
||||
}
|
||||
|
||||
void TypeChecker::checkTupleNodeType(Node& node) {
|
||||
for (auto& child : node.children) {
|
||||
checkNodeType(child);
|
||||
}
|
||||
|
||||
|
||||
// TODO implemnt tuple type checking
|
||||
}
|
||||
|
||||
void TypeChecker::checkBindNodeType(Node& node) {
|
||||
auto id = node.children[0].getIdentifier();
|
||||
if (!id.has_value()) {
|
||||
throw std::runtime_error("FIXME identifier node does not contain identifier");
|
||||
}
|
||||
if (variables.find(*id) != variables.end()) {
|
||||
throw std::runtime_error("Cannot overwrite existing bind/variable/function with new bind");
|
||||
}
|
||||
|
||||
checkNodeType(node.children[1]);
|
||||
auto nodeType = node.children[1].ptype.getOnlyType();
|
||||
if (!nodeType.has_value()) {
|
||||
throw std::runtime_error("cannot assign ambiguous type to name");
|
||||
}
|
||||
variables[*id] = *nodeType;
|
||||
variables[*id].isConstant = true;
|
||||
}
|
||||
|
||||
void TypeChecker::checkFunctionBindNodeType(Node& node) {
|
||||
auto id = node.children[0].getIdentifier();
|
||||
if (!id.has_value()) {
|
||||
throw std::runtime_error("FIXME identifier node does not contain identifier");
|
||||
}
|
||||
if (variables.find(*id) != variables.end()) {
|
||||
throw std::runtime_error("Cannot overwrite existing bind/variable/function with new function");
|
||||
}
|
||||
|
||||
checkNodeType(node.children[1]);
|
||||
auto nodeType = node.children[1].ptype.getOnlyType();
|
||||
if (!nodeType.has_value()) {
|
||||
throw std::runtime_error("cannot assign ambiguous type to name");
|
||||
}
|
||||
variables[*id] = *nodeType;
|
||||
variables[*id].isConstant = true;
|
||||
}
|
||||
|
||||
void TypeChecker::checkSetNodeType(Node& node) {
|
||||
auto id = node.children[0].getIdentifier();
|
||||
if (!id.has_value()) {
|
||||
throw std::runtime_error("FIXME identifier node does not contain identifier");
|
||||
}
|
||||
if (variables.find(*id) != variables.end()) {
|
||||
if (variables[*id].isConstant) {
|
||||
throw std::runtime_error("cannot reassign existing bind");
|
||||
}
|
||||
}
|
||||
if (!inFunction) {
|
||||
throw std::runtime_error("mutable variables may only be used in functions");
|
||||
}
|
||||
|
||||
checkNodeType(node.children[1]);
|
||||
auto nodeType = node.children[1].ptype.getOnlyType();
|
||||
if (!nodeType.has_value()) {
|
||||
throw std::runtime_error("cannot assign ambiguous type to name");
|
||||
}
|
||||
variables[*id] = *nodeType;
|
||||
}
|
||||
|
||||
void TypeChecker::checkCodeBlockType(Node& node) {}
|
||||
|
||||
|
||||
void TypeChecker::checkNodeType(Node& node) {
|
||||
switch (node.type) {
|
||||
case NodeType::Root:
|
||||
node.ptype = {{}}; // no possible types for root node
|
||||
for (auto& child : node.children) {
|
||||
checkNodeType(child);
|
||||
}
|
||||
break;
|
||||
case NodeType::Literal:
|
||||
checkLiteralNodeType(node);
|
||||
@@ -135,6 +199,19 @@ namespace Solstice {
|
||||
case NodeType::Tuple:
|
||||
checkTupleNodeType(node);
|
||||
break;
|
||||
case NodeType::Bind:
|
||||
checkBindNodeType(node);
|
||||
break;
|
||||
case NodeType::FunctionBind:
|
||||
checkFunctionBindNodeType(node);
|
||||
break;
|
||||
case NodeType::Set:
|
||||
checkSetNodeType(node);
|
||||
break;
|
||||
case NodeType::CodeBlock:
|
||||
checkCodeBlockType(node);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
namespace Solstice {
|
||||
|
||||
class TypeChecker {
|
||||
std::unordered_map<std::string, PossibleType> variables;
|
||||
std::unordered_map<std::string, Type> variables;
|
||||
std::unordered_map<std::string, Type> types;
|
||||
|
||||
std::unordered_map<TypePair, Type> addOverloads;
|
||||
@@ -23,12 +23,20 @@ namespace Solstice {
|
||||
|
||||
Node& input;
|
||||
|
||||
bool inFunction = false;
|
||||
|
||||
void initOverloads();
|
||||
|
||||
void checkLiteralNodeType(Node& node);
|
||||
void checkIdentifierNodeType(Node& node);
|
||||
void checkTupleNodeType(Node& node);
|
||||
|
||||
void checkBindNodeType(Node& node);
|
||||
void checkFunctionBindNodeType(Node& node);
|
||||
void checkSetNodeType(Node& node);
|
||||
|
||||
void checkCodeBlockType(Node& node);
|
||||
|
||||
void checkNodeType(Node& node);
|
||||
|
||||
public:
|
||||
|
||||
Reference in New Issue
Block a user