More work on binder type registration, support in REPL to show registered types.
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
@@ -54,13 +54,23 @@ namespace MalachScript::Binder {
|
||||
case Parser::ParsedStatementKind::Class: {
|
||||
const auto* s = static_cast<const ParsedClassStatement*>(statement);
|
||||
auto identifier = s->GetIdentifier();
|
||||
if (activeType.has_value()) {
|
||||
auto type = ns->ResolveType(s->GetIdentifier());
|
||||
if (!type.has_value()) {
|
||||
if (activeType.has_value()) {
|
||||
type = activeType.value()->ResolveType(s->GetIdentifier());
|
||||
}
|
||||
}
|
||||
auto* type = new BoundType(s->GetClassAttr());
|
||||
if (type.has_value()) {
|
||||
log(DiagnosticLevel::Error, DiagnosticType::TypeAlreadyDefined, s->GetSpan(),
|
||||
{identifier.GetStdString()});
|
||||
break;
|
||||
}
|
||||
|
||||
type = new BoundType(identifier, s->GetClassAttr());
|
||||
if (activeType.has_value()) {
|
||||
activeType.value()->RegisterType(identifier, type);
|
||||
activeType.value()->RegisterType(identifier, type.value());
|
||||
} else {
|
||||
ns->RegisterType(identifier, type);
|
||||
ns->RegisterType(identifier, type.value());
|
||||
}
|
||||
for (const auto& child : s->GetBody()) {
|
||||
TypeRegistrationFirstPass(ns, child.get(), type, log);
|
||||
@@ -92,7 +102,12 @@ namespace MalachScript::Binder {
|
||||
const auto* s = static_cast<const ParsedClassStatement*>(statement);
|
||||
auto type = ns->ResolveType(s->GetIdentifier());
|
||||
if (!type.has_value()) {
|
||||
throw std::logic_error("Shouldn't be reached");
|
||||
if (activeType.has_value()) {
|
||||
type = activeType.value()->ResolveType(s->GetIdentifier());
|
||||
}
|
||||
if (!type.has_value()) {
|
||||
throw std::logic_error("Shouldn't be reached");
|
||||
}
|
||||
}
|
||||
for (const auto& inherits : s->GetInherits()) {
|
||||
auto inheritType = ResolveType(ns, inherits);
|
||||
@@ -152,7 +167,12 @@ namespace MalachScript::Binder {
|
||||
const auto* s = static_cast<const ParsedClassStatement*>(statement);
|
||||
auto type = ns->ResolveType(s->GetIdentifier());
|
||||
if (!type.has_value()) {
|
||||
throw std::logic_error("Shouldn't be reached");
|
||||
if (activeType.has_value()) {
|
||||
type = activeType.value()->ResolveType(s->GetIdentifier());
|
||||
}
|
||||
if (!type.has_value()) {
|
||||
throw std::logic_error("Shouldn't be reached");
|
||||
}
|
||||
}
|
||||
for (const auto& child : s->GetBody()) {
|
||||
TypeRegistrationThirdPass(ns, child.get(), type.value(), log);
|
||||
|
||||
64
src/Binder/BoundNamespaceStringifier.hpp
Normal file
64
src/Binder/BoundNamespaceStringifier.hpp
Normal file
@@ -0,0 +1,64 @@
|
||||
#ifndef MALACHSCRIPT_BOUNDNAMESPACESTRINGIFIER_HPP
|
||||
#define MALACHSCRIPT_BOUNDNAMESPACESTRINGIFIER_HPP
|
||||
|
||||
#include "BoundNamespace.hpp"
|
||||
|
||||
template <typename K, typename V> static std::vector<std::pair<K, V>> mapToVector(const std::unordered_map<K, V>& map) {
|
||||
auto vec = std::vector<std::pair<K, V>>(map.begin(), map.end());
|
||||
std::reverse(vec.begin(), vec.end());
|
||||
return vec;
|
||||
};
|
||||
|
||||
namespace MalachScript::Binder {
|
||||
class BoundNamespaceStringifier {
|
||||
static void StringifyField(const MalachScript::Identifier& identifier, const BoundVariable* field,
|
||||
std::stringstream& stream, const std::string& prefix, bool isLast) {
|
||||
stream << prefix;
|
||||
stream << (isLast ? "└──" : "├──");
|
||||
stream << identifier << ": " << field->GetType()->GetIdentifier();
|
||||
}
|
||||
static void StringifyType(const MalachScript::Identifier& identifier, const BoundType* type,
|
||||
std::stringstream& stream, const std::string& prefix, bool isLast) {
|
||||
stream << prefix;
|
||||
stream << (isLast ? "└──" : "├──");
|
||||
stream << "class " << identifier << " (size: " << type->GetSize() << ")";
|
||||
auto types = mapToVector(type->GetTypes());
|
||||
for (size_t i = 0; i < types.size(); i++) {
|
||||
stream << std::endl;
|
||||
StringifyType(types[i].first, types[i].second, stream, prefix + (isLast ? " " : "│ "),
|
||||
i == types.size() - 1);
|
||||
}
|
||||
auto fields = mapToVector(type->GetFieldsLookup());
|
||||
for (size_t i = 0; i < fields.size(); i++) {
|
||||
stream << std::endl;
|
||||
StringifyField(fields[i].first, fields[i].second, stream, prefix + (isLast ? " " : "│ "),
|
||||
i == fields.size() - 1);
|
||||
}
|
||||
}
|
||||
static void StringifyNamespace(const MalachScript::Identifier& identifier, const BoundNamespace* boundNamespace,
|
||||
std::stringstream& stream, const std::string& prefix, bool isLast) {
|
||||
stream << prefix;
|
||||
stream << (isLast ? "└──" : "├──");
|
||||
stream << "namespace " << identifier;
|
||||
auto types = mapToVector(boundNamespace->GetTypes());
|
||||
for (size_t i = 0; i < types.size(); i++) {
|
||||
stream << std::endl;
|
||||
StringifyType(types[i].first, types[i].second, stream, prefix + (isLast ? " " : "│ "),
|
||||
i == types.size() - 1);
|
||||
}
|
||||
auto namespaces = mapToVector(boundNamespace->GetNamespaces());
|
||||
for (size_t i = 0; i < namespaces.size(); i++) {
|
||||
stream << std::endl;
|
||||
StringifyNamespace(namespaces[i].first, namespaces[i].second, stream,
|
||||
prefix + (isLast ? " " : "│ "), i == namespaces.size() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
static void Stringify(const BoundNamespace* ns, std::stringstream& stream) {
|
||||
StringifyNamespace("global"_id, ns, stream, "", true);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif // MALACHSCRIPT_BOUNDNAMESPACESTRINGIFIER_HPP
|
||||
@@ -7,14 +7,31 @@
|
||||
namespace MalachScript::Binder {
|
||||
class BoundType {
|
||||
public:
|
||||
BoundType(ClassAttr classAttr) : _classAttr(classAttr) {}
|
||||
BoundType(ClassAttr classAttr, size_t size) : _classAttr(classAttr), _size(size), _inherits(0) {}
|
||||
BoundType(Identifier identifier, ClassAttr classAttr) : _identifier(identifier), _classAttr(classAttr) {}
|
||||
BoundType(Identifier identifier, ClassAttr classAttr, size_t size)
|
||||
: _identifier(identifier), _classAttr(classAttr), _size(size), _inherits(0) {}
|
||||
|
||||
inline void Finalise() noexcept {
|
||||
if (_initialised) {
|
||||
return;
|
||||
}
|
||||
_initialised = true;
|
||||
// TODO: Calculate size
|
||||
for (auto& inherits : _inherits) {
|
||||
if (!inherits->IsInitialised()) {
|
||||
const_cast<BoundType*>(inherits)->Finalise();
|
||||
}
|
||||
_size += inherits->GetSize();
|
||||
}
|
||||
for (auto& field : _fields) {
|
||||
if (!field->GetType()->IsInitialised()) {
|
||||
const_cast<BoundType*>(field->GetType())->Finalise();
|
||||
}
|
||||
_size += field->GetType()->GetSize();
|
||||
}
|
||||
}
|
||||
[[nodiscard]] inline const Identifier& GetIdentifier() const noexcept { return _identifier; }
|
||||
[[nodiscard]] inline size_t GetSize() const noexcept { return _size; }
|
||||
[[nodiscard]] inline bool IsInitialised() const noexcept { return _initialised; }
|
||||
[[nodiscard]] inline ClassAttr GetAttributes() const noexcept { return _classAttr; }
|
||||
|
||||
inline void AddInheritType(const BoundType* type) { _inherits.push_back(type); }
|
||||
@@ -27,8 +44,24 @@ namespace MalachScript::Binder {
|
||||
_types[identifier] = const_cast<BoundType*>(type);
|
||||
}
|
||||
|
||||
[[nodiscard]] inline const std::unordered_map<Identifier, BoundType*>& GetTypes() const noexcept {
|
||||
return _types;
|
||||
}
|
||||
[[nodiscard]] inline const std::unordered_map<Identifier, BoundVariable*>& GetFieldsLookup() const noexcept {
|
||||
return _fieldsLookup;
|
||||
}
|
||||
|
||||
inline std::optional<BoundType*> ResolveType(const Identifier& identifier) const noexcept {
|
||||
auto find = _types.find(identifier);
|
||||
if (find == _types.end()) {
|
||||
return {};
|
||||
}
|
||||
return find->second;
|
||||
}
|
||||
|
||||
private:
|
||||
bool _initialised = false;
|
||||
Identifier _identifier;
|
||||
ClassAttr _classAttr;
|
||||
size_t _size = 0;
|
||||
std::vector<const BoundType*> _inherits;
|
||||
|
||||
@@ -48,7 +48,7 @@ namespace MalachScript {
|
||||
uint32_t _hash;
|
||||
|
||||
public:
|
||||
Identifier() : _str(nullptr), _length(0), _hash(0) {}
|
||||
Identifier() : _str(empty.c_str()), _length(0), _hash(0) {}
|
||||
constexpr Identifier(const char* c) : _str(c), _length(CalcLength(c)), _hash(Hash(c)) {}
|
||||
constexpr Identifier(const char* c, size_t length) : _str(c), _length(length), _hash(Hash(c)) {}
|
||||
constexpr Identifier(const char* c, size_t length, uint32_t hash) : _str(c), _length(length), _hash(hash) {}
|
||||
|
||||
@@ -27,17 +27,17 @@ namespace MalachScript {
|
||||
|
||||
static constinit Identifier _autoName = "auto";
|
||||
|
||||
static Binder::BoundType _int8Type = Binder::BoundType(ClassAttr::None, sizeof(int8_t));
|
||||
static Binder::BoundType _int16Type = Binder::BoundType(ClassAttr::None, sizeof(int16_t));
|
||||
static Binder::BoundType _int32Type = Binder::BoundType(ClassAttr::None, sizeof(int32_t));
|
||||
static Binder::BoundType _int64Type = Binder::BoundType(ClassAttr::None, sizeof(int64_t));
|
||||
static Binder::BoundType _uint8Type = Binder::BoundType(ClassAttr::None, sizeof(uint8_t));
|
||||
static Binder::BoundType _uint16Type = Binder::BoundType(ClassAttr::None, sizeof(uint16_t));
|
||||
static Binder::BoundType _uint32Type = Binder::BoundType(ClassAttr::None, sizeof(uint32_t));
|
||||
static Binder::BoundType _uint64Type = Binder::BoundType(ClassAttr::None, sizeof(uint64_t));
|
||||
static Binder::BoundType _floatType = Binder::BoundType(ClassAttr::None, sizeof(float));
|
||||
static Binder::BoundType _doubleType = Binder::BoundType(ClassAttr::None, sizeof(double));
|
||||
static Binder::BoundType _boolType = Binder::BoundType(ClassAttr::None, sizeof(uint8_t));
|
||||
static Binder::BoundType _int8Type = Binder::BoundType(_int8Name, ClassAttr::None, sizeof(int8_t));
|
||||
static Binder::BoundType _int16Type = Binder::BoundType(_int16Name, ClassAttr::None, sizeof(int16_t));
|
||||
static Binder::BoundType _int32Type = Binder::BoundType(_int32Name, ClassAttr::None, sizeof(int32_t));
|
||||
static Binder::BoundType _int64Type = Binder::BoundType(_int64Name, ClassAttr::None, sizeof(int64_t));
|
||||
static Binder::BoundType _uint8Type = Binder::BoundType(_uint8Name, ClassAttr::None, sizeof(uint8_t));
|
||||
static Binder::BoundType _uint16Type = Binder::BoundType(_uint16Name, ClassAttr::None, sizeof(uint16_t));
|
||||
static Binder::BoundType _uint32Type = Binder::BoundType(_uint32Name, ClassAttr::None, sizeof(uint32_t));
|
||||
static Binder::BoundType _uint64Type = Binder::BoundType(_uint64Name, ClassAttr::None, sizeof(uint64_t));
|
||||
static Binder::BoundType _floatType = Binder::BoundType(_floatName, ClassAttr::None, sizeof(float));
|
||||
static Binder::BoundType _doubleType = Binder::BoundType(_doubleName, ClassAttr::None, sizeof(double));
|
||||
static Binder::BoundType _boolType = Binder::BoundType(_boolName, ClassAttr::None, sizeof(uint8_t));
|
||||
|
||||
class PrimitiveTypes {
|
||||
public:
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace MalachScript::Diagnostics {
|
||||
DoubleProperty,
|
||||
|
||||
UnknownType,
|
||||
TypeAlreadyDefined,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,10 @@ namespace MalachScript::Diagnostics {
|
||||
}
|
||||
case DiagnosticType::DoubleProperty: return "Property block found twice.";
|
||||
|
||||
case DiagnosticType::UnknownType: util::Format("Unknown Type Encounted: '{0}'", diag->GetFormats());
|
||||
case DiagnosticType::UnknownType:
|
||||
return util::Format("Unknown Type Encounted: '{0}'", diag->GetFormats());
|
||||
case DiagnosticType::TypeAlreadyDefined:
|
||||
return util::Format("Type already defined: '{0}'", diag->GetFormats());
|
||||
}
|
||||
return std::to_string((uint8_t)diag->GetType());
|
||||
}
|
||||
|
||||
@@ -159,7 +159,8 @@ namespace MalachScript::Parser {
|
||||
ScopedPtr<const ParsedStatement> statement = nullptr;
|
||||
// TODO: Sort by complexity
|
||||
if (!ParseVirtProp(statement, current, log) && !ParseFunc(statement, current, log) &&
|
||||
!ParseVar(statement, current, log) && !ParseFuncDef(statement, current, log)) {
|
||||
!ParseVar(statement, current, log) && !ParseFuncDef(statement, current, log) &&
|
||||
!ParseClass(statement, current, log)) {
|
||||
logUnexpectedTokenWithoutExpected(current);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
#ifndef MALACHSCRIPT_TREEPRINTER_HPP
|
||||
#define MALACHSCRIPT_TREEPRINTER_HPP
|
||||
#include <sstream>
|
||||
|
||||
class MalachScript::Utils {
|
||||
class TreePrinter {
|
||||
public:
|
||||
private:
|
||||
std::stringstream _stream;
|
||||
};
|
||||
};
|
||||
|
||||
#endif // MALACHSCRIPT_TREEPRINTER_HPP
|
||||
Reference in New Issue
Block a user