Start working on type checker
This commit is contained in:
@@ -4,6 +4,8 @@ sources = files(
|
|||||||
'src/main.cpp',
|
'src/main.cpp',
|
||||||
'src/lexer/lexer.cpp',
|
'src/lexer/lexer.cpp',
|
||||||
'src/parser/parser.cpp',
|
'src/parser/parser.cpp',
|
||||||
|
'src/typechecker/typechecker.cpp',
|
||||||
|
'src/typechecker/type.cpp',
|
||||||
'src/ir/ir.cpp',
|
'src/ir/ir.cpp',
|
||||||
'src/compiler/compiler.cpp'
|
'src/compiler/compiler.cpp'
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include "lexer/lexer.hpp"
|
#include "lexer/lexer.hpp"
|
||||||
#include "parser/parser.hpp"
|
#include "parser/parser.hpp"
|
||||||
|
#include "typechecker/typechecker.hpp"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
@@ -23,5 +24,8 @@ int main(int argc, char** argv) {
|
|||||||
auto parsed = parser.parse();
|
auto parsed = parser.parse();
|
||||||
std::cout << parsed << std::endl;
|
std::cout << parsed << std::endl;
|
||||||
|
|
||||||
|
Solstice::TypeChecker typeChecker(parsed);
|
||||||
|
typeChecker.checkTypes();
|
||||||
|
|
||||||
return 0;
|
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