PorygonLang/src/ScriptTypes/TableScriptType.hpp

171 lines
6.5 KiB
C++
Raw Normal View History

2019-06-12 13:19:28 +00:00
#ifndef PORYGONLANG_TABLESCRIPTTYPE_HPP
#define PORYGONLANG_TABLESCRIPTTYPE_HPP
#include <unordered_map>
2019-09-15 11:08:11 +00:00
#include <utility>
#include "../Binder/BoundVariables/BoundVariable.hpp"
2019-09-15 11:08:11 +00:00
#include "../Exception.hpp"
2019-06-12 13:19:28 +00:00
namespace Porygon{
2019-09-15 11:08:11 +00:00
class TableScriptType : public ScriptType{
2019-09-15 11:08:11 +00:00
enum TableType{
Unknown,
Numerical,
StringKeyed,
Dictionary
};
bool _isContentAware;
TableType _tableType;
2019-06-12 13:19:28 +00:00
2019-09-15 11:08:11 +00:00
union{
shared_ptr<const ScriptType> _valueType; // numerical
unordered_map<Utilities::HashedString, shared_ptr<const ScriptType>>* _contentTypes = nullptr; // string keyed
std::pair<shared_ptr<const ScriptType>, shared_ptr<const ScriptType>> _keyValueType; // dictionary
};
public:
2019-09-01 18:07:09 +00:00
explicit TableScriptType()
2019-09-15 11:08:11 +00:00
: ScriptType(TypeClass::Table), _tableType(TableType::Unknown) {}
2019-09-01 18:07:09 +00:00
2019-09-15 11:08:11 +00:00
explicit TableScriptType(shared_ptr<const ScriptType> valueType)
: ScriptType(TypeClass::Table), _tableType(TableType::Numerical), _valueType(std::move(valueType)) {}
2019-09-01 18:07:09 +00:00
2019-09-15 11:08:11 +00:00
explicit TableScriptType(unordered_map<Utilities::HashedString, shared_ptr<const ScriptType>>* contentTypes)
: ScriptType(TypeClass::Table), _tableType(TableType::StringKeyed), _contentTypes(contentTypes),
_isContentAware(true) {}
explicit TableScriptType(std::pair<shared_ptr<ScriptType>, shared_ptr<ScriptType>> kvType)
: ScriptType(TypeClass::Table), _tableType(TableType::Dictionary), _keyValueType(std::move(kvType)) {}
~TableScriptType() override {
if (_tableType == TableType::StringKeyed)
delete _contentTypes;
2019-06-12 13:19:28 +00:00
}
2019-09-15 11:08:11 +00:00
[[nodiscard]] bool CanBeIterated() const final {
return true;
}
[[nodiscard]] shared_ptr<const ScriptType> GetIteratorKeyType() const override {
switch (_tableType){
case Unknown: return ScriptType::AnyType;
case Numerical: return NumericScriptType::AwareInt;
case StringKeyed: return StringScriptType::Dynamic;
case Dictionary: throw Exception("Not implemented.");
}
}
2019-06-12 13:19:28 +00:00
2019-09-15 11:08:11 +00:00
[[nodiscard]] bool IsCountable() const override {
return true;
}
2019-09-15 11:08:11 +00:00
bool CanBeIndexedWith(const ScriptType *indexer) const override {
if (_tableType == TableType::Unknown)
return true;
else if (_tableType == TableType::StringKeyed){
return indexer->GetClass() == TypeClass::String;
}
else if (_tableType == TableType::Numerical){
return indexer->GetClass() == TypeClass::Number;
}
else{
auto keyType = _keyValueType.first;
return indexer->CastableTo(keyType, false) != CastResult ::InvalidCast;
}
2019-06-12 13:19:28 +00:00
}
2019-09-15 11:08:11 +00:00
[[nodiscard]] bool CanBeIndexedWithIdentifier(uint32_t hash) const override {
if (_tableType != TableType::StringKeyed)
return false;
return _isContentAware;
}
2019-09-15 11:08:11 +00:00
shared_ptr<const ScriptType> GetIndexedType(shared_ptr<const ScriptType> indexer) const override {
if (_tableType == TableType::Unknown)
return ScriptType::AnyType;
else if (_tableType == TableType::StringKeyed){
auto stringType = dynamic_pointer_cast<const StringScriptType>(indexer);
if (stringType->IsKnownAtBind() && _isContentAware){
auto h = stringType->GetHashValue();
return _contentTypes->at(h);
}
return ScriptType::AnyType;
}
else if (_tableType == TableType::Numerical){
return _valueType;
}
else{
return _keyValueType.second;
}
}
[[nodiscard]] shared_ptr<const ScriptType> GetIndexedType(uint32_t hash) const override {
auto lookup = Utilities::HashedString::CreateLookup(hash);
return _contentTypes->at(lookup);
}
unordered_map<Utilities::HashedString, shared_ptr<const ScriptType>>* GetContentTypes() const{
return _contentTypes;
}
2019-09-01 18:07:09 +00:00
[[nodiscard]]
2019-09-15 11:08:11 +00:00
bool CanSetIndexValue(shared_ptr<const ScriptType> indexer, shared_ptr<const ScriptType> val) const override {
switch (_tableType){
case Unknown: return true;
case Numerical:
return indexer->GetClass() == TypeClass ::Number &&
val->CastableTo(_valueType, false) != CastResult ::InvalidCast;
case StringKeyed:
return indexer->GetClass() == TypeClass ::String;
case Dictionary:
return indexer->CastableTo(_keyValueType.first, false) != CastResult ::InvalidCast &&
val->CastableTo(_keyValueType.second, false) != CastResult ::InvalidCast;
}
2019-09-01 18:07:09 +00:00
}
[[nodiscard]]
2019-09-15 11:08:11 +00:00
bool CanSetIndexValue(Utilities::HashedString indexer, shared_ptr<const ScriptType> val) const override {
switch (_tableType){
case StringKeyed:
return true;
case Unknown:
return true;
default:
break;
}
return false;
2019-09-01 18:07:09 +00:00
}
2019-09-12 16:19:06 +00:00
2019-09-15 11:08:11 +00:00
void SetIndexValue(shared_ptr<const ScriptType> indexer, shared_ptr<const ScriptType> val) const override {
if (_tableType == TableType::StringKeyed){
auto s = dynamic_pointer_cast<const StringScriptType>(indexer);
if (s->IsKnownAtBind()){
auto key = s->GetHashValue();
_contentTypes->insert({key, val});
}
}
}
void SetIndexValue(Utilities::HashedString indexer, shared_ptr<const ScriptType> val) const override {
if (_tableType == TableType::StringKeyed){
_contentTypes->insert({indexer, val});
}
else if (_tableType == TableType::Unknown){
auto t = const_cast<TableScriptType*>(this);
t->_tableType = TableType ::StringKeyed;
t->_isContentAware = true;
t->_contentTypes = new unordered_map<Utilities::HashedString, shared_ptr<const ScriptType>>{
{indexer, val}
};
}
2019-09-12 16:19:06 +00:00
}
};
}
2019-06-12 13:19:28 +00:00
#include "ScriptType.hpp"
#endif //PORYGONLANG_TABLESCRIPTTYPE_HPP