Start working on type checker
This commit is contained in:
@@ -4,6 +4,8 @@ sources = files(
|
||||
'src/main.cpp',
|
||||
'src/lexer/lexer.cpp',
|
||||
'src/parser/parser.cpp',
|
||||
'src/typechecker/typechecker.cpp',
|
||||
'src/typechecker/type.cpp',
|
||||
'src/ir/ir.cpp',
|
||||
'src/compiler/compiler.cpp'
|
||||
)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "lexer/lexer.hpp"
|
||||
#include "parser/parser.hpp"
|
||||
#include "typechecker/typechecker.hpp"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <ostream>
|
||||
@@ -23,5 +24,8 @@ int main(int argc, char** argv) {
|
||||
auto parsed = parser.parse();
|
||||
std::cout << parsed << std::endl;
|
||||
|
||||
Solstice::TypeChecker typeChecker(parsed);
|
||||
typeChecker.checkTypes();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
19
src/typechecker/type.cpp
Normal file
19
src/typechecker/type.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#include "type.hpp"
|
||||
|
||||
namespace Solstice {
|
||||
|
||||
bool operator==(const Type& left, const Type& right) {
|
||||
if (left.type != right.type) {
|
||||
return false;
|
||||
}
|
||||
if (left.type == BaseType::Object && left.fields != right.fields) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool operator==(const TypePair& left, const TypePair& right) {
|
||||
return left.left == right.left && left.right == right.right;
|
||||
}
|
||||
|
||||
}
|
||||
71
src/typechecker/type.hpp
Normal file
71
src/typechecker/type.hpp
Normal file
@@ -0,0 +1,71 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <unordered_set>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
namespace Solstice {
|
||||
enum class BaseType {
|
||||
None, Int, Double, String, Char, Bool, Array, Pointer, Object
|
||||
};
|
||||
|
||||
enum class Operator {
|
||||
Add, Subtract, Multiply, Divide, Equal, NotEqual, GreaterThan, LesserThan
|
||||
};
|
||||
|
||||
struct Type {
|
||||
BaseType type = BaseType::None;
|
||||
std::map<std::string, Type> fields; // use map for ordering
|
||||
|
||||
Type() = delete;
|
||||
Type(BaseType type) : type(type) {}
|
||||
};
|
||||
|
||||
bool operator==(const Type& left, const Type& right);
|
||||
|
||||
struct TypePair {
|
||||
Type left;
|
||||
Type right;
|
||||
TypePair() = delete;
|
||||
TypePair(const Type& left, const Type& right) : left(left), right(right) {}
|
||||
};
|
||||
|
||||
bool operator==(const TypePair& left, const TypePair& right);
|
||||
}
|
||||
|
||||
namespace std {
|
||||
template<>
|
||||
struct hash<Solstice::Type> {
|
||||
size_t operator()(const Solstice::Type& t) const {
|
||||
size_t output = std::hash<int>{}((int)t.type);
|
||||
for (const auto& [key, value] : t.fields) {
|
||||
size_t keyHash = std::hash<std::string>{}(key);
|
||||
size_t valHash = std::hash<Solstice::Type>{}(value);
|
||||
|
||||
output ^= keyHash + 0x9e3779b97f4a7c15ULL + (output << 6) + (output >> 2);
|
||||
output ^= valHash + 0x9e3779b97f4a7c15ULL + (output << 6) + (output >> 2);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct hash<Solstice::TypePair> {
|
||||
size_t operator()(const Solstice::TypePair& t) const {
|
||||
size_t leftHash = std::hash<Solstice::Type>{}(t.left);
|
||||
size_t rightHash = std::hash<Solstice::Type>{}(t.right);
|
||||
|
||||
leftHash ^= rightHash + 0x9e3779b97f4a7c15ULL + (leftHash << 6) + (leftHash >> 2);
|
||||
return leftHash;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
namespace Solstice {
|
||||
|
||||
struct PossibleType {
|
||||
std::unordered_set<Type> possiblities;
|
||||
};
|
||||
|
||||
}
|
||||
72
src/typechecker/typechecker.cpp
Normal file
72
src/typechecker/typechecker.cpp
Normal file
@@ -0,0 +1,72 @@
|
||||
#include "typechecker.hpp"
|
||||
|
||||
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},
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
37
src/typechecker/typechecker.hpp
Normal file
37
src/typechecker/typechecker.hpp
Normal file
@@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#include "type.hpp"
|
||||
#include "../parser/parser.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace Solstice {
|
||||
|
||||
class TypeChecker {
|
||||
std::unordered_map<std::string, Type> variables;
|
||||
std::unordered_map<std::string, Type> types;
|
||||
|
||||
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;
|
||||
|
||||
Node& input;
|
||||
|
||||
void initOverloads();
|
||||
|
||||
public:
|
||||
|
||||
TypeChecker() = delete;
|
||||
TypeChecker(Node& node) : input(node) {
|
||||
initOverloads();
|
||||
}
|
||||
|
||||
void checkTypes();
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user