Large rework of tables
continuous-integration/drone/push Build is failing
Details
continuous-integration/drone/push Build is failing
Details
This commit is contained in:
parent
e89782f921
commit
458274f370
|
@ -102,19 +102,36 @@ namespace Porygon::Binder {
|
||||||
auto s = (ParsedIndexAssignmentStatement *) statement;
|
auto s = (ParsedIndexAssignmentStatement *) statement;
|
||||||
auto indexExp = s->GetIndexExpression();
|
auto indexExp = s->GetIndexExpression();
|
||||||
const BoundExpression *indexable;
|
const BoundExpression *indexable;
|
||||||
if (indexExp->GetKind() == ParsedExpressionKind::Indexer) {
|
|
||||||
indexable = this->BindIndexExpression((IndexExpression *) indexExp, true);
|
|
||||||
} else {
|
|
||||||
indexable = this->BindPeriodIndexExpression((PeriodIndexExpression *) indexExp, true);
|
|
||||||
}
|
|
||||||
auto valueExpression = this->BindExpression(s->GetValueExpression());
|
auto valueExpression = this->BindExpression(s->GetValueExpression());
|
||||||
auto boundIndexType = indexable->GetType();
|
auto valueType = valueExpression->GetType();
|
||||||
if (boundIndexType->GetClass() != TypeClass::Error &&
|
|
||||||
boundIndexType->operator!=(valueExpression->GetType())) {
|
if (indexExp->GetKind() == ParsedExpressionKind::Indexer) {
|
||||||
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::InvalidTableValueType,
|
auto exp = dynamic_cast<const IndexExpression*>(indexExp);
|
||||||
|
auto indexParent = this->BindExpression(exp->GetIndexer());
|
||||||
|
auto indexChild = this->BindExpression(exp->GetIndex());
|
||||||
|
auto t = indexParent->GetType();
|
||||||
|
if (!t->CanSetIndexValue(indexChild->GetType(), valueType)){
|
||||||
|
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::CantIndexAssign,
|
||||||
statement->GetStartPosition(), statement->GetLength());
|
statement->GetStartPosition(), statement->GetLength());
|
||||||
return new BoundBadStatement();
|
return new BoundBadStatement();
|
||||||
}
|
}
|
||||||
|
t->SetIndexValue(indexChild->GetType(), valueType);
|
||||||
|
indexable = new BoundIndexExpression(indexParent, indexChild, indexChild->GetType(), indexParent->GetStartPosition(),
|
||||||
|
exp->GetStartPosition() - exp->GetEndPosition());
|
||||||
|
} else {
|
||||||
|
auto exp = dynamic_cast<const PeriodIndexExpression*>(indexExp);
|
||||||
|
auto indexParent = this->BindExpression(exp->GetIndexer());
|
||||||
|
const auto& key = exp->GetIndex();
|
||||||
|
auto t = indexParent->GetType();
|
||||||
|
if (!t->CanSetIndexValue(key, valueType)){
|
||||||
|
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::CantIndexAssign,
|
||||||
|
statement->GetStartPosition(), statement->GetLength());
|
||||||
|
return new BoundBadStatement();
|
||||||
|
}
|
||||||
|
t->SetIndexValue(key, valueType);
|
||||||
|
indexable = new BoundPeriodIndexExpression(indexParent, key, valueType, indexParent->GetStartPosition(),
|
||||||
|
exp->GetStartPosition() - exp->GetEndPosition());
|
||||||
|
}
|
||||||
|
|
||||||
return new BoundIndexAssignmentStatement(indexable, valueExpression);
|
return new BoundIndexAssignmentStatement(indexable, valueExpression);
|
||||||
}
|
}
|
||||||
|
@ -326,7 +343,7 @@ namespace Porygon::Binder {
|
||||||
auto isValueVariableDefined = valueIdentifier.GetHash() != 0;
|
auto isValueVariableDefined = valueIdentifier.GetHash() != 0;
|
||||||
const BoundVariableKey *valueVariable = nullptr;
|
const BoundVariableKey *valueVariable = nullptr;
|
||||||
if (isValueVariableDefined) {
|
if (isValueVariableDefined) {
|
||||||
auto valueType = itType->GetIndexedType(keyType.get());
|
auto valueType = itType->GetIndexedType(keyType);
|
||||||
auto valueVariableAssignment = this->_scope->CreateExplicitLocal(valueIdentifier, valueType);
|
auto valueVariableAssignment = this->_scope->CreateExplicitLocal(valueIdentifier, valueType);
|
||||||
if (valueVariableAssignment.GetResult() != VariableAssignmentResult::Ok) {
|
if (valueVariableAssignment.GetResult() != VariableAssignmentResult::Ok) {
|
||||||
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::CantAssignVariable,
|
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::CantAssignVariable,
|
||||||
|
@ -746,7 +763,8 @@ namespace Porygon::Binder {
|
||||||
}
|
}
|
||||||
if (indexerType->GetClass() == TypeClass::UserData) {
|
if (indexerType->GetClass() == TypeClass::UserData) {
|
||||||
auto stringKey = dynamic_pointer_cast<const StringScriptType>(index->GetType());
|
auto stringKey = dynamic_pointer_cast<const StringScriptType>(index->GetType());
|
||||||
auto field = dynamic_pointer_cast<const UserData::UserDataScriptType>(indexerType)->GetField(stringKey->GetHashValue());
|
auto field = dynamic_pointer_cast<const UserData::UserDataScriptType>(indexerType)
|
||||||
|
->GetField(stringKey->GetHashValue().GetHash());
|
||||||
if (!setter) {
|
if (!setter) {
|
||||||
if (!field->HasGetter()) {
|
if (!field->HasGetter()) {
|
||||||
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::UserDataFieldNoGetter,
|
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::UserDataFieldNoGetter,
|
||||||
|
@ -764,7 +782,7 @@ namespace Porygon::Binder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto resultType = indexer->GetType()->GetIndexedType(index->GetType().get());
|
auto resultType = indexer->GetType()->GetIndexedType(index->GetType());
|
||||||
return new BoundIndexExpression(indexer, index, resultType, expression->GetStartPosition(),
|
return new BoundIndexExpression(indexer, index, resultType, expression->GetStartPosition(),
|
||||||
expression->GetLength());
|
expression->GetLength());
|
||||||
}
|
}
|
||||||
|
@ -816,13 +834,19 @@ namespace Porygon::Binder {
|
||||||
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::InvalidTableValueType,
|
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::InvalidTableValueType,
|
||||||
boundExpressions[i]->GetStartPosition(),
|
boundExpressions[i]->GetStartPosition(),
|
||||||
boundExpressions[i]->GetLength());
|
boundExpressions[i]->GetLength());
|
||||||
|
return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else{
|
||||||
|
auto tableType = std::make_shared<const TableScriptType>();
|
||||||
|
return new BoundNumericalTableExpression(boundExpressions, tableType, expression->GetStartPosition(),
|
||||||
|
expression->GetLength());
|
||||||
|
}
|
||||||
if (valueType == nullptr) {
|
if (valueType == nullptr) {
|
||||||
valueType = ScriptType::NilType;
|
valueType = ScriptType::NilType;
|
||||||
}
|
}
|
||||||
auto tableType = std::make_shared<const NumericalTableScriptType>(valueType);
|
auto tableType = std::make_shared<const TableScriptType>(valueType);
|
||||||
return new BoundNumericalTableExpression(boundExpressions, tableType, expression->GetStartPosition(),
|
return new BoundNumericalTableExpression(boundExpressions, tableType, expression->GetStartPosition(),
|
||||||
expression->GetLength());
|
expression->GetLength());
|
||||||
}
|
}
|
||||||
|
@ -835,7 +859,14 @@ namespace Porygon::Binder {
|
||||||
auto block = dynamic_cast<BoundBlockStatement*>(this->BindBlockStatement(expression->GetBlock()));
|
auto block = dynamic_cast<BoundBlockStatement*>(this->BindBlockStatement(expression->GetBlock()));
|
||||||
this->_scope = currentScope;
|
this->_scope = currentScope;
|
||||||
|
|
||||||
auto tableType = std::make_shared<TableScriptType>(tableScope, innerScope->GetLocalVariableCount());
|
auto dictionary = new unordered_map<HashedString, shared_ptr<const ScriptType>>();
|
||||||
|
for (auto i : *tableScope){
|
||||||
|
dictionary->insert({i.first, i.second->GetType()});
|
||||||
|
delete i.second;
|
||||||
|
}
|
||||||
|
delete tableScope;
|
||||||
|
|
||||||
|
auto tableType = std::make_shared<TableScriptType>(dictionary);
|
||||||
delete innerScope;
|
delete innerScope;
|
||||||
|
|
||||||
return new BoundTableExpression(block, tableType, expression->GetStartPosition(), expression->GetLength());
|
return new BoundTableExpression(block, tableType, expression->GetStartPosition(), expression->GetLength());
|
||||||
|
|
|
@ -145,7 +145,8 @@ namespace Porygon::Binder {
|
||||||
public:
|
public:
|
||||||
BoundLiteralStringExpression(const u16string &value, unsigned int start, unsigned int length)
|
BoundLiteralStringExpression(const u16string &value, unsigned int start, unsigned int length)
|
||||||
: BoundExpression(start, length,
|
: BoundExpression(start, length,
|
||||||
make_shared<StringScriptType>(true, Utilities::HashedString::ConstHash(value.c_str()))),
|
make_shared<StringScriptType>(true,
|
||||||
|
Utilities::HashedString(new u16string(value)))),
|
||||||
_value(value) {
|
_value(value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ namespace Porygon::Diagnostics {
|
||||||
VariableNotFound,
|
VariableNotFound,
|
||||||
ExpressionIsNotAFunction,
|
ExpressionIsNotAFunction,
|
||||||
CantIndex,
|
CantIndex,
|
||||||
|
CantIndexAssign,
|
||||||
InvalidReturnType,
|
InvalidReturnType,
|
||||||
ConditionNotABool,
|
ConditionNotABool,
|
||||||
InvalidTableValueType,
|
InvalidTableValueType,
|
||||||
|
|
|
@ -77,6 +77,12 @@ namespace Porygon::Evaluation {
|
||||||
throw EvaluationException(err.str());
|
throw EvaluationException(err.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void SetIndexValue(const Utilities::HashedString *key, const EvalValue* value) const {
|
||||||
|
std::stringstream err;
|
||||||
|
err << "Can't index this EvalValue: " << ToString() << " with key: " << value->ToString();
|
||||||
|
throw EvaluationException(err.str());
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
virtual Iterator * GetKeyIterator() const{
|
virtual Iterator * GetKeyIterator() const{
|
||||||
throw EvaluationException("Can't iterate over this EvalValue");
|
throw EvaluationException("Can't iterate over this EvalValue");
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
#include "NumericalTableEvalValue.hpp"
|
|
||||||
#include "../Iterator/NumericalKeyIterator.hpp"
|
|
||||||
#include "../../Utilities/Random.hpp"
|
|
||||||
|
|
||||||
inline Porygon::Evaluation::Iterator *Porygon::Evaluation::NumericalTableEvalValue::GetKeyIterator() const {
|
|
||||||
return new NumericalKeyIterator(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
Porygon::Evaluation::NumericalTableEvalValue::NumericalTableEvalValue(shared_ptr<vector<EvalValuePointer>> table) :
|
|
||||||
_table(std::move(table)),
|
|
||||||
_hash(Utilities::Random::Get())
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Porygon::Evaluation::EvalValue *
|
|
||||||
Porygon::Evaluation::NumericalTableEvalValue::UnaryOperation(Porygon::Binder::BoundUnaryOperation operation) const {
|
|
||||||
if (operation == Porygon::Binder::BoundUnaryOperation::Count){
|
|
||||||
return new NumericEvalValue(static_cast<int64_t>(this->_table->size()));
|
|
||||||
}
|
|
||||||
return EvalValue::UnaryOperation(operation);
|
|
||||||
}
|
|
|
@ -1,84 +0,0 @@
|
||||||
#ifndef PORYGONLANG_NUMERICALTABLEEVALVALUE_HPP
|
|
||||||
#define PORYGONLANG_NUMERICALTABLEEVALVALUE_HPP
|
|
||||||
|
|
||||||
|
|
||||||
#include <utility>
|
|
||||||
#include <map>
|
|
||||||
#include "EvalValue.hpp"
|
|
||||||
#include "../EvalValuePointer.hpp"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace Porygon::Evaluation {
|
|
||||||
class NumericalTableEvalValue : public EvalValue {
|
|
||||||
const shared_ptr<vector<EvalValuePointer>> _table;
|
|
||||||
const size_t _hash;
|
|
||||||
|
|
||||||
explicit NumericalTableEvalValue(shared_ptr<vector<EvalValuePointer>> table, size_t hash)
|
|
||||||
: _table(std::move(table)),
|
|
||||||
_hash(hash)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit NumericalTableEvalValue(shared_ptr<vector<EvalValuePointer>> table);
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
inline TypeClass GetTypeClass() const final {
|
|
||||||
return TypeClass::Table;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
inline size_t GetHashCode() const final {
|
|
||||||
return _hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
inline bool operator==(const EvalValue *b) const final {
|
|
||||||
return this->_hash == b->GetHashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator!=(const EvalValue *b) const override {
|
|
||||||
return !operator==(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
inline EvalValue* Clone() const final {
|
|
||||||
return new NumericalTableEvalValue(_table, _hash);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
inline const EvalValue* IndexValue(const EvalValue *val) const final {
|
|
||||||
const auto index = val->EvaluateInteger() - 1;
|
|
||||||
return this->_table->at(index).Clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
inline EvalValue* IndexValue(const Utilities::HashedString* hash) const final {
|
|
||||||
return this->_table->at(hash->GetHash() - 1)-> Clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void SetIndexValue(const EvalValue *key, const EvalValue* value) const final {
|
|
||||||
auto index = key->EvaluateInteger();
|
|
||||||
index--;
|
|
||||||
if (this->_table->size() <= index){
|
|
||||||
this->_table->resize(index);
|
|
||||||
}
|
|
||||||
this->_table->at(index) = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
Iterator * GetKeyIterator() const final;
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
inline shared_ptr<vector<EvalValuePointer>> GetTable() const{
|
|
||||||
return _table;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] EvalValue *UnaryOperation(Binder::BoundUnaryOperation operation) const override;;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef iteratorKind
|
|
||||||
|
|
||||||
#endif //PORYGONLANG_NUMERICALTABLEEVALVALUE_HPP
|
|
|
@ -1,8 +1,9 @@
|
||||||
#include "TableEvalValue.hpp"
|
#include "TableEvalValue.hpp"
|
||||||
#include "../Iterator/SimpleKeyIterator.hpp"
|
#include "../Iterator/SimpleKeyIterator.hpp"
|
||||||
#include "NumericEvalValue.hpp"
|
#include "NumericEvalValue.hpp"
|
||||||
|
#include "../Iterator/NumericalKeyIterator.hpp"
|
||||||
|
|
||||||
inline Porygon::Evaluation::Iterator * Porygon::Evaluation::TableEvalValue::GetKeyIterator() const {
|
Porygon::Evaluation::Iterator * Porygon::Evaluation::TableEvalValue::GetKeyIterator() const {
|
||||||
return new TableKeyIterator(this);
|
return new TableKeyIterator(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,3 +14,20 @@ Porygon::Evaluation::TableEvalValue::UnaryOperation(Porygon::Binder::BoundUnaryO
|
||||||
}
|
}
|
||||||
return EvalValue::UnaryOperation(operation);
|
return EvalValue::UnaryOperation(operation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Porygon::Evaluation::TableEvalValue::SetIndexValue(const Porygon::Utilities::HashedString *key,
|
||||||
|
const Porygon::Evaluation::EvalValue *value) const {
|
||||||
|
auto insert = _table->insert({*key, value});
|
||||||
|
if (!insert.second) {
|
||||||
|
_table->at(*key).ClearAssign(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Porygon::Evaluation::Iterator *Porygon::Evaluation::NumericTableEvalValue::GetKeyIterator() const {
|
||||||
|
return new NumericalKeyIterator(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
Porygon::Evaluation::EvalValue *Porygon::Evaluation::NumericTableEvalValue::Clone() const {
|
||||||
|
return new NumericTableEvalValue(_table, _hash);
|
||||||
|
}
|
||||||
|
|
|
@ -11,15 +11,15 @@ using namespace std;
|
||||||
|
|
||||||
namespace Porygon::Evaluation {
|
namespace Porygon::Evaluation {
|
||||||
class TableEvalValue : public EvalValue {
|
class TableEvalValue : public EvalValue {
|
||||||
const shared_ptr<map<Utilities::HashedString, EvalValuePointer>> _table;
|
protected:
|
||||||
const size_t _hash;
|
|
||||||
|
|
||||||
explicit TableEvalValue(shared_ptr<map<Utilities::HashedString, EvalValuePointer>> table, size_t hash)
|
explicit TableEvalValue(shared_ptr<map<Utilities::HashedString, EvalValuePointer>> table, size_t hash)
|
||||||
: _table(std::move(table)),
|
: _table(std::move(table)),
|
||||||
_hash(hash)
|
_hash(hash)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const shared_ptr<map<Utilities::HashedString, EvalValuePointer>> _table;
|
||||||
|
const size_t _hash;
|
||||||
public:
|
public:
|
||||||
explicit TableEvalValue(shared_ptr<map<Utilities::HashedString, EvalValuePointer>> table) :
|
explicit TableEvalValue(shared_ptr<map<Utilities::HashedString, EvalValuePointer>> table) :
|
||||||
_table(std::move(table)),
|
_table(std::move(table)),
|
||||||
|
@ -47,7 +47,7 @@ namespace Porygon::Evaluation {
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
inline EvalValue* Clone() const final {
|
inline EvalValue* Clone() const override {
|
||||||
return new TableEvalValue(_table, _hash);
|
return new TableEvalValue(_table, _hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,11 +70,15 @@ namespace Porygon::Evaluation {
|
||||||
|
|
||||||
inline void SetIndexValue(const EvalValue *key, const EvalValue* value) const final {
|
inline void SetIndexValue(const EvalValue *key, const EvalValue* value) const final {
|
||||||
auto hash = key->GetHashCode();
|
auto hash = key->GetHashCode();
|
||||||
this->_table->at(Utilities::HashedString::CreateLookup(hash)).ClearAssign(value);
|
auto lookup = Utilities::HashedString::CreateLookup(hash);
|
||||||
|
auto insert = _table->insert({lookup, value});
|
||||||
|
if (!insert.second) {
|
||||||
|
_table->at(lookup).ClearAssign(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
Iterator * GetKeyIterator() const final;
|
Iterator * GetKeyIterator() const override;
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
inline _Rb_tree_const_iterator<pair<const Utilities::HashedString, EvalValuePointer>> GetTableIterator() const{
|
inline _Rb_tree_const_iterator<pair<const Utilities::HashedString, EvalValuePointer>> GetTableIterator() const{
|
||||||
|
@ -85,7 +89,26 @@ namespace Porygon::Evaluation {
|
||||||
return _table->cend();
|
return _table->cend();
|
||||||
}
|
}
|
||||||
|
|
||||||
EvalValue *UnaryOperation(Binder::BoundUnaryOperation operation) const override;;
|
[[nodiscard]] EvalValue *UnaryOperation(Binder::BoundUnaryOperation operation) const override;
|
||||||
|
|
||||||
|
void SetIndexValue(const Utilities::HashedString *key, const EvalValue *value) const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class NumericTableEvalValue : public TableEvalValue{
|
||||||
|
|
||||||
|
explicit NumericTableEvalValue(shared_ptr<map<Utilities::HashedString, EvalValuePointer>> table, size_t hash)
|
||||||
|
: TableEvalValue(std::move(table), hash)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
explicit NumericTableEvalValue(shared_ptr<map<Utilities::HashedString, EvalValuePointer>> table)
|
||||||
|
:TableEvalValue(std::move(table))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] Iterator *GetKeyIterator() const final;
|
||||||
|
|
||||||
|
[[nodiscard]] EvalValue *Clone() const override;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,6 @@
|
||||||
#include "../Binder/BoundExpressions/BoundRequireExpression.hpp"
|
#include "../Binder/BoundExpressions/BoundRequireExpression.hpp"
|
||||||
#include "../ScriptTypes/TableScriptType.hpp"
|
#include "../ScriptTypes/TableScriptType.hpp"
|
||||||
#include "../UserData/UserDataFunction.hpp"
|
#include "../UserData/UserDataFunction.hpp"
|
||||||
#include "EvalValues/NumericalTableEvalValue.hpp"
|
|
||||||
#include "../UserData/UserDataValue.hpp"
|
#include "../UserData/UserDataValue.hpp"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
@ -93,11 +92,20 @@ namespace Porygon::Evaluation {
|
||||||
void Evaluator::EvaluateIndexAssignmentStatement(const BoundIndexAssignmentStatement *statement) {
|
void Evaluator::EvaluateIndexAssignmentStatement(const BoundIndexAssignmentStatement *statement) {
|
||||||
auto indexExpression = statement->GetIndexExpression();
|
auto indexExpression = statement->GetIndexExpression();
|
||||||
auto value = this->EvaluateExpression(statement->GetValueExpression());
|
auto value = this->EvaluateExpression(statement->GetValueExpression());
|
||||||
auto index = ((BoundIndexExpression *) indexExpression);
|
if (indexExpression->GetKind() == BoundExpressionKind::Index){
|
||||||
|
auto index = dynamic_cast<const BoundIndexExpression*>(indexExpression);
|
||||||
auto table = this->EvaluateExpression(index->GetIndexableExpression());
|
auto table = this->EvaluateExpression(index->GetIndexableExpression());
|
||||||
auto key = this->EvaluateExpression(index->GetIndexExpression());
|
auto key = this->EvaluateExpression(index->GetIndexExpression());
|
||||||
table->SetIndexValue(key.Get(), value.Take());
|
table->SetIndexValue(key.Get(), value.Take());
|
||||||
}
|
}
|
||||||
|
else{
|
||||||
|
auto index = dynamic_cast<const BoundPeriodIndexExpression*>(indexExpression);
|
||||||
|
auto table = this->EvaluateExpression(index->GetIndexableExpression());
|
||||||
|
auto key = index->GetIndex();
|
||||||
|
table->SetIndexValue(key, value.Take());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Evaluator::EvaluateFunctionDeclarationStatement(const BoundFunctionDeclarationStatement *statement) {
|
void Evaluator::EvaluateFunctionDeclarationStatement(const BoundFunctionDeclarationStatement *statement) {
|
||||||
auto type = statement->GetType();
|
auto type = statement->GetType();
|
||||||
|
@ -396,20 +404,22 @@ namespace Porygon::Evaluation {
|
||||||
EvalValuePointer Evaluator::EvaluateNumericTableExpression(const BoundExpression *expression) {
|
EvalValuePointer Evaluator::EvaluateNumericTableExpression(const BoundExpression *expression) {
|
||||||
auto tableExpression = (BoundNumericalTableExpression *) expression;
|
auto tableExpression = (BoundNumericalTableExpression *) expression;
|
||||||
auto valueExpressions = tableExpression->GetExpressions();
|
auto valueExpressions = tableExpression->GetExpressions();
|
||||||
auto values = new vector<EvalValuePointer>(valueExpressions->size());
|
auto values = new map<Utilities::HashedString, EvalValuePointer>();
|
||||||
for (size_t i = 0; i < valueExpressions->size(); i++) {
|
for (size_t i = 0; i < valueExpressions->size(); i++) {
|
||||||
auto val = this->EvaluateExpression(valueExpressions->at(i));
|
auto val = this->EvaluateExpression(valueExpressions->at(i));
|
||||||
values->at(i) = val.Take();
|
auto k = Utilities::StringUtils::IntToString(i + 1);
|
||||||
|
auto s = Utilities::HashedString(new u16string(k));
|
||||||
|
values->insert({s, val});
|
||||||
}
|
}
|
||||||
auto valuesPointer = shared_ptr<vector<EvalValuePointer>>(values);
|
auto valuesPointer = shared_ptr<map<Utilities::HashedString, EvalValuePointer>>(values);
|
||||||
return new NumericalTableEvalValue(valuesPointer);
|
return new NumericTableEvalValue(valuesPointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
EvalValuePointer Evaluator::EvaluateComplexTableExpression(const BoundExpression *expression) {
|
EvalValuePointer Evaluator::EvaluateComplexTableExpression(const BoundExpression *expression) {
|
||||||
auto tableExpression = (BoundTableExpression *) expression;
|
auto tableExpression = (BoundTableExpression *) expression;
|
||||||
const auto& baseType = tableExpression -> GetType();
|
const auto& baseType = tableExpression -> GetType();
|
||||||
auto type = dynamic_pointer_cast<const TableScriptType>(baseType);
|
auto type = dynamic_pointer_cast<const TableScriptType>(baseType);
|
||||||
auto declaredVars = type->GetValues();
|
auto declaredVars = type->GetContentTypes();
|
||||||
auto variables = make_shared<map<Utilities::HashedString, EvalValuePointer>>();
|
auto variables = make_shared<map<Utilities::HashedString, EvalValuePointer>>();
|
||||||
for (const auto& i : *declaredVars) {
|
for (const auto& i : *declaredVars) {
|
||||||
variables->insert({i.first, nullptr});
|
variables->insert({i.first, nullptr});
|
||||||
|
|
|
@ -1 +1,6 @@
|
||||||
#include "NumericalKeyIterator.hpp"
|
#include "NumericalKeyIterator.hpp"
|
||||||
|
|
||||||
|
const Porygon::Evaluation::EvalValue *Porygon::Evaluation::NumericalKeyIterator::GetCurrent() {
|
||||||
|
auto s = *_iterator->first.GetString();
|
||||||
|
return new NumericEvalValue(Utilities::StringUtils::ParseInteger(s));
|
||||||
|
}
|
||||||
|
|
|
@ -1,34 +1,15 @@
|
||||||
#ifndef PORYGONLANG_NUMERICALKEYITERATOR_HPP
|
#ifndef PORYGONLANG_NUMERICALKEYITERATOR_HPP
|
||||||
#define PORYGONLANG_NUMERICALKEYITERATOR_HPP
|
#define PORYGONLANG_NUMERICALKEYITERATOR_HPP
|
||||||
|
|
||||||
|
#include "SimpleKeyIterator.hpp"
|
||||||
#include "Iterator.hpp"
|
|
||||||
#include "../EvalValues/NumericalTableEvalValue.hpp"
|
|
||||||
#include "../EvalValues/NumericEvalValue.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
namespace Porygon::Evaluation{
|
namespace Porygon::Evaluation{
|
||||||
class NumericalKeyIterator : public Iterator{
|
class NumericalKeyIterator : public TableKeyIterator{
|
||||||
const shared_ptr<vector<EvalValuePointer>> _vec;
|
|
||||||
const size_t _size;
|
|
||||||
size_t _position = 0;
|
|
||||||
public:
|
public:
|
||||||
explicit NumericalKeyIterator(const NumericalTableEvalValue* table)
|
const EvalValue *GetCurrent() override;
|
||||||
: _vec(table->GetTable()), _size(_vec->size() + 1){}
|
explicit NumericalKeyIterator(const TableEvalValue* table)
|
||||||
|
: TableKeyIterator(table){}
|
||||||
|
|
||||||
inline const EvalValue* GetCurrent() final{
|
|
||||||
return new NumericEvalValue(static_cast<int64_t >(_position));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool MoveNext() final{
|
|
||||||
_position++;
|
|
||||||
return _position != _size;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void Reset() final{
|
|
||||||
_position = 0;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //PORYGONLANG_NUMERICALKEYITERATOR_HPP
|
#endif //PORYGONLANG_NUMERICALKEYITERATOR_HPP
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
namespace Porygon::Evaluation{
|
namespace Porygon::Evaluation{
|
||||||
class TableKeyIterator : public Iterator{
|
class TableKeyIterator : public Iterator{
|
||||||
|
protected:
|
||||||
_Rb_tree_const_iterator<pair<const Utilities::HashedString, EvalValuePointer>> _iterator;
|
_Rb_tree_const_iterator<pair<const Utilities::HashedString, EvalValuePointer>> _iterator;
|
||||||
_Rb_tree_const_iterator<pair<const Utilities::HashedString, EvalValuePointer>> _end;
|
_Rb_tree_const_iterator<pair<const Utilities::HashedString, EvalValuePointer>> _end;
|
||||||
bool _hasStarted = false;
|
bool _hasStarted = false;
|
||||||
|
@ -15,7 +16,7 @@ namespace Porygon::Evaluation{
|
||||||
explicit TableKeyIterator(const TableEvalValue* table)
|
explicit TableKeyIterator(const TableEvalValue* table)
|
||||||
: _iterator(table->GetTableIterator()), _end(table->GetTableIteratorEnd()){}
|
: _iterator(table->GetTableIterator()), _end(table->GetTableIteratorEnd()){}
|
||||||
|
|
||||||
inline const EvalValue* GetCurrent() final{
|
inline const EvalValue* GetCurrent() override {
|
||||||
return new StringEvalValue(*_iterator->first.GetString());
|
return new StringEvalValue(*_iterator->first.GetString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
#include "../Script.hpp"
|
#include "../Script.hpp"
|
||||||
#include "../UserData/UserDataFunctionType.hpp"
|
#include "../UserData/UserDataFunctionType.hpp"
|
||||||
#include "ScriptType.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
namespace Porygon{
|
namespace Porygon{
|
||||||
|
@ -11,12 +10,13 @@ namespace Porygon{
|
||||||
shared_ptr<const ScriptType> ScriptType::BoolType = make_shared<ScriptType>(TypeClass::Bool);
|
shared_ptr<const ScriptType> ScriptType::BoolType = make_shared<ScriptType>(TypeClass::Bool);
|
||||||
shared_ptr<const ScriptType> ScriptType::NilType = make_shared<ScriptType>(TypeClass::Nil);
|
shared_ptr<const ScriptType> ScriptType::NilType = make_shared<ScriptType>(TypeClass::Nil);
|
||||||
shared_ptr<const ScriptType> ScriptType::AnyType = make_shared<ScriptType>(TypeClass::Any);
|
shared_ptr<const ScriptType> ScriptType::AnyType = make_shared<ScriptType>(TypeClass::Any);
|
||||||
shared_ptr<const NumericScriptType> NumericScriptType::AwareInt = make_shared<NumericScriptType>(true, false);
|
shared_ptr<const NumericScriptType> NumericScriptType::AwareInt = make_shared<const NumericScriptType>(true, false);
|
||||||
shared_ptr<const NumericScriptType> NumericScriptType::AwareFloat = make_shared<NumericScriptType>(true, true);
|
shared_ptr<const NumericScriptType> NumericScriptType::AwareFloat = make_shared<const NumericScriptType>(true, true);
|
||||||
shared_ptr<const NumericScriptType> NumericScriptType::Unaware = make_shared<NumericScriptType>(false, false);
|
shared_ptr<const NumericScriptType> NumericScriptType::Unaware = make_shared<const NumericScriptType>(false, false);
|
||||||
shared_ptr<const StringScriptType> StringScriptType::Dynamic = make_shared<StringScriptType>(false, 0);
|
shared_ptr<const StringScriptType> StringScriptType::Dynamic = make_shared<const StringScriptType>(false,
|
||||||
|
Utilities::HashedString::CreateLookup(0));
|
||||||
|
|
||||||
shared_ptr<const ScriptType> ScriptType::GetIndexedType(const ScriptType*) const{
|
shared_ptr<const ScriptType> ScriptType::GetIndexedType(shared_ptr<const ScriptType>) const{
|
||||||
return make_shared<ScriptType>(TypeClass::Error);
|
return make_shared<ScriptType>(TypeClass::Error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,7 +96,7 @@ namespace Porygon{
|
||||||
}
|
}
|
||||||
|
|
||||||
ScriptType* CreateStringScriptType(bool knownAtBind, uint32_t hash){
|
ScriptType* CreateStringScriptType(bool knownAtBind, uint32_t hash){
|
||||||
return new StringScriptType(knownAtBind, hash);
|
return new StringScriptType(knownAtBind, Utilities::HashedString::CreateLookup(hash));
|
||||||
}
|
}
|
||||||
|
|
||||||
ScriptType* CreateUserDataFunctionScriptType(ScriptType* returnType, ScriptType* parameters[], size_t parameterCount){
|
ScriptType* CreateUserDataFunctionScriptType(ScriptType* returnType, ScriptType* parameters[], size_t parameterCount){
|
||||||
|
|
|
@ -43,9 +43,19 @@ namespace Porygon{
|
||||||
|
|
||||||
virtual bool CanBeIndexedWith(const ScriptType* indexer) const;
|
virtual bool CanBeIndexedWith(const ScriptType* indexer) const;
|
||||||
[[nodiscard]] virtual bool CanBeIndexedWithIdentifier(uint32_t hash) const;
|
[[nodiscard]] virtual bool CanBeIndexedWithIdentifier(uint32_t hash) const;
|
||||||
[[nodiscard]] virtual shared_ptr<const ScriptType> GetIndexedType(const ScriptType* indexer) const;
|
[[nodiscard]] virtual shared_ptr<const ScriptType> GetIndexedType(shared_ptr<const ScriptType> indexer) const;
|
||||||
[[nodiscard]] virtual shared_ptr<const ScriptType> GetIndexedType(uint32_t hash) const;
|
[[nodiscard]] virtual shared_ptr<const ScriptType> GetIndexedType(uint32_t hash) const;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual bool CanSetIndexValue(shared_ptr<const ScriptType> indexer, shared_ptr<const ScriptType> val) const{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
[[nodiscard]] virtual bool CanSetIndexValue(Utilities::HashedString indexer, shared_ptr<const ScriptType> val) const{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void SetIndexValue(shared_ptr<const ScriptType> indexer, shared_ptr<const ScriptType> val) const { }
|
||||||
|
virtual void SetIndexValue(Utilities::HashedString indexer, shared_ptr<const ScriptType> val) const { }
|
||||||
|
|
||||||
[[nodiscard]] virtual bool CanBeIterated() const;
|
[[nodiscard]] virtual bool CanBeIterated() const;
|
||||||
[[nodiscard]] virtual shared_ptr<const ScriptType> GetIteratorKeyType() const;
|
[[nodiscard]] virtual shared_ptr<const ScriptType> GetIteratorKeyType() const;
|
||||||
|
|
||||||
|
@ -104,6 +114,8 @@ namespace Porygon{
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] CastResult CastableTo(const shared_ptr<const ScriptType>& castType, bool explicitCast) const final{
|
[[nodiscard]] CastResult CastableTo(const shared_ptr<const ScriptType>& castType, bool explicitCast) const final{
|
||||||
|
if (this->operator==(castType))
|
||||||
|
return CastResult ::ValidCast;
|
||||||
if (!explicitCast){
|
if (!explicitCast){
|
||||||
if (castType->GetClass() != TypeClass::Number )
|
if (castType->GetClass() != TypeClass::Number )
|
||||||
return CastResult::InvalidCast;
|
return CastResult::InvalidCast;
|
||||||
|
@ -117,11 +129,11 @@ namespace Porygon{
|
||||||
|
|
||||||
class StringScriptType : public ScriptType{
|
class StringScriptType : public ScriptType{
|
||||||
bool _isKnownAtBind;
|
bool _isKnownAtBind;
|
||||||
uint32_t _hashValue;
|
Utilities::HashedString _hashValue;
|
||||||
public:
|
public:
|
||||||
explicit StringScriptType(bool knownAtBind, uint32_t hashValue): ScriptType(TypeClass::String){
|
explicit StringScriptType(bool knownAtBind, const Utilities::HashedString& hashValue)
|
||||||
|
: ScriptType(TypeClass::String), _hashValue(hashValue){
|
||||||
_isKnownAtBind = knownAtBind;
|
_isKnownAtBind = knownAtBind;
|
||||||
_hashValue = hashValue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static shared_ptr<const StringScriptType> Dynamic;
|
static shared_ptr<const StringScriptType> Dynamic;
|
||||||
|
@ -134,7 +146,7 @@ namespace Porygon{
|
||||||
return !(num->IsAwareOfFloat() && num->IsFloat());
|
return !(num->IsAwareOfFloat() && num->IsFloat());
|
||||||
}
|
}
|
||||||
|
|
||||||
inline shared_ptr<const ScriptType> GetIndexedType(const ScriptType* indexer) const final{
|
inline shared_ptr<const ScriptType> GetIndexedType(shared_ptr<const ScriptType> indexer) const final{
|
||||||
return StringScriptType::Dynamic;
|
return StringScriptType::Dynamic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,45 +156,12 @@ namespace Porygon{
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
inline uint32_t GetHashValue() const{
|
inline Utilities::HashedString GetHashValue() const{
|
||||||
return _hashValue;
|
return _hashValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsCountable() const override;
|
bool IsCountable() const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class NumericalTableScriptType : public ScriptType{
|
|
||||||
shared_ptr<const ScriptType> _valueType;
|
|
||||||
// Consider adding a check whether the table actually contains a type if every key is static.
|
|
||||||
public:
|
|
||||||
explicit NumericalTableScriptType(shared_ptr<const ScriptType> valueType)
|
|
||||||
: ScriptType(TypeClass::Table), _valueType(std::move(valueType)){
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CanBeIndexedWith(const ScriptType* indexer) const final{
|
|
||||||
if (indexer -> GetClass() != TypeClass::Number)
|
|
||||||
return false;
|
|
||||||
auto num = dynamic_cast<const NumericScriptType*>(indexer);
|
|
||||||
return !(num->IsAwareOfFloat() && num->IsFloat());
|
|
||||||
}
|
|
||||||
|
|
||||||
inline shared_ptr<const ScriptType> GetIndexedType(const ScriptType* indexer) const final{
|
|
||||||
return _valueType;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
inline bool CanBeIterated() const final{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
[[nodiscard]]
|
|
||||||
inline shared_ptr<const ScriptType> GetIteratorKeyType() const final{
|
|
||||||
return NumericScriptType::AwareInt;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] bool IsCountable() const override {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,72 +2,165 @@
|
||||||
#ifndef PORYGONLANG_TABLESCRIPTTYPE_HPP
|
#ifndef PORYGONLANG_TABLESCRIPTTYPE_HPP
|
||||||
#define PORYGONLANG_TABLESCRIPTTYPE_HPP
|
#define PORYGONLANG_TABLESCRIPTTYPE_HPP
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <utility>
|
||||||
#include "../Binder/BoundVariables/BoundVariable.hpp"
|
#include "../Binder/BoundVariables/BoundVariable.hpp"
|
||||||
|
#include "../Exception.hpp"
|
||||||
|
|
||||||
namespace Porygon{
|
namespace Porygon{
|
||||||
|
|
||||||
class TableScriptType : public ScriptType{
|
class TableScriptType : public ScriptType{
|
||||||
const map<Utilities::HashedString, BoundVariable*>* _values;
|
enum TableType{
|
||||||
const int _localVariableCount;
|
Unknown,
|
||||||
|
Numerical,
|
||||||
|
StringKeyed,
|
||||||
|
Dictionary
|
||||||
|
};
|
||||||
|
|
||||||
|
bool _isContentAware;
|
||||||
|
TableType _tableType;
|
||||||
|
|
||||||
|
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:
|
public:
|
||||||
explicit TableScriptType(map<Utilities::HashedString, BoundVariable*>* values, int localVariableCount)
|
|
||||||
: ScriptType(TypeClass::Table),
|
|
||||||
_values(values),
|
|
||||||
_localVariableCount(localVariableCount)
|
|
||||||
{}
|
|
||||||
|
|
||||||
explicit TableScriptType()
|
explicit TableScriptType()
|
||||||
: ScriptType(TypeClass::Table),
|
: ScriptType(TypeClass::Table), _tableType(TableType::Unknown) {}
|
||||||
_values(nullptr),
|
|
||||||
_localVariableCount(0)
|
|
||||||
{}
|
|
||||||
|
|
||||||
|
explicit TableScriptType(shared_ptr<const ScriptType> valueType)
|
||||||
|
: ScriptType(TypeClass::Table), _tableType(TableType::Numerical), _valueType(std::move(valueType)) {}
|
||||||
|
|
||||||
~TableScriptType() final{
|
explicit TableScriptType(unordered_map<Utilities::HashedString, shared_ptr<const ScriptType>>* contentTypes)
|
||||||
if (_values != nullptr){
|
: ScriptType(TypeClass::Table), _tableType(TableType::StringKeyed), _contentTypes(contentTypes),
|
||||||
for (const auto& i : *_values){
|
_isContentAware(true) {}
|
||||||
delete i.second;
|
|
||||||
}
|
explicit TableScriptType(std::pair<shared_ptr<ScriptType>, shared_ptr<ScriptType>> kvType)
|
||||||
}
|
: ScriptType(TypeClass::Table), _tableType(TableType::Dictionary), _keyValueType(std::move(kvType)) {}
|
||||||
delete _values;
|
|
||||||
|
~TableScriptType() override {
|
||||||
|
if (_tableType == TableType::StringKeyed)
|
||||||
|
delete _contentTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]] bool CanBeIterated() const final {
|
||||||
inline bool CanBeIndexedWith(const ScriptType* indexer) 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.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool IsCountable() const override {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CanBeIndexedWith(const ScriptType *indexer) const override {
|
||||||
|
if (_tableType == TableType::Unknown)
|
||||||
|
return true;
|
||||||
|
else if (_tableType == TableType::StringKeyed){
|
||||||
return indexer->GetClass() == TypeClass::String;
|
return indexer->GetClass() == TypeClass::String;
|
||||||
}
|
}
|
||||||
|
else if (_tableType == TableType::Numerical){
|
||||||
[[nodiscard]] bool CanBeIndexedWithIdentifier(uint32_t hash) const final{
|
return indexer->GetClass() == TypeClass::Number;
|
||||||
return true;
|
}
|
||||||
|
else{
|
||||||
|
auto keyType = _keyValueType.first;
|
||||||
|
return indexer->CastableTo(keyType, false) != CastResult ::InvalidCast;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
shared_ptr<const ScriptType> GetIndexedType(const ScriptType* indexer) const final{
|
[[nodiscard]] bool CanBeIndexedWithIdentifier(uint32_t hash) const override {
|
||||||
auto stringKey = dynamic_cast<const StringScriptType*>(indexer);
|
if (_tableType != TableType::StringKeyed)
|
||||||
if (stringKey != nullptr && stringKey->IsKnownAtBind() && _values != nullptr){
|
return false;
|
||||||
return _values-> at(Utilities::HashedString::CreateLookup(stringKey->GetHashValue()))->GetType();
|
return _isContentAware;
|
||||||
}
|
|
||||||
return make_shared<ScriptType>(TypeClass::Any);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] inline shared_ptr<const ScriptType> GetIndexedType(uint32_t hash) const final{
|
shared_ptr<const ScriptType> GetIndexedType(shared_ptr<const ScriptType> indexer) const override {
|
||||||
return _values-> at(Utilities::HashedString::CreateLookup(hash))->GetType();
|
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]] inline const map<Utilities::HashedString, BoundVariable*>* GetValues() const{
|
[[nodiscard]] shared_ptr<const ScriptType> GetIndexedType(uint32_t hash) const override {
|
||||||
return _values;
|
auto lookup = Utilities::HashedString::CreateLookup(hash);
|
||||||
|
return _contentTypes->at(lookup);
|
||||||
|
}
|
||||||
|
|
||||||
|
unordered_map<Utilities::HashedString, shared_ptr<const ScriptType>>* GetContentTypes() const{
|
||||||
|
return _contentTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
bool CanBeIterated() const final {
|
bool CanSetIndexValue(shared_ptr<const ScriptType> indexer, shared_ptr<const ScriptType> val) const override {
|
||||||
return true;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
shared_ptr<const ScriptType> GetIteratorKeyType() const final {
|
bool CanSetIndexValue(Utilities::HashedString indexer, shared_ptr<const ScriptType> val) const override {
|
||||||
return make_shared<ScriptType>(TypeClass::Any);
|
switch (_tableType){
|
||||||
|
case StringKeyed:
|
||||||
|
return true;
|
||||||
|
case Unknown:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsCountable() const override {
|
void SetIndexValue(shared_ptr<const ScriptType> indexer, shared_ptr<const ScriptType> val) const override {
|
||||||
return true;
|
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}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,7 +51,7 @@ namespace Porygon::UserData {
|
||||||
return indexer->operator==(_keyType);
|
return indexer->operator==(_keyType);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] shared_ptr<const ScriptType> GetIndexedType(const ScriptType* indexer) const final{
|
[[nodiscard]] shared_ptr<const ScriptType> GetIndexedType(shared_ptr<const ScriptType> indexer) const final{
|
||||||
return _valueType;
|
return _valueType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,6 +70,15 @@ namespace Porygon::UserData {
|
||||||
[[nodiscard]] bool IsCountable() const override {
|
[[nodiscard]] bool IsCountable() const override {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
bool CanSetIndexValue(shared_ptr<const ScriptType> indexer, shared_ptr<const ScriptType> val) const override {
|
||||||
|
if (indexer->CastableTo(_keyType, false) == CastResult::InvalidCast)
|
||||||
|
return false;
|
||||||
|
if (val->CastableTo(_valueType, false) == CastResult::InvalidCast)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,11 +12,11 @@ namespace Porygon::UserData{
|
||||||
: GenericFunctionOption(std::move(returnType), std::move(parameterTypes)) {
|
: GenericFunctionOption(std::move(returnType), std::move(parameterTypes)) {
|
||||||
|
|
||||||
}
|
}
|
||||||
static UserDataFunctionOption* FromRawPointers(const ScriptType* returnType, vector<const ScriptType*> parameterTypes){
|
static UserDataFunctionOption* FromRawPointers(ScriptType* returnType, vector<ScriptType*> parameterTypes){
|
||||||
auto rt = shared_ptr<const ScriptType>(returnType);
|
auto rt = shared_ptr<const ScriptType>(returnType);
|
||||||
auto p = vector<shared_ptr<const ScriptType>>(parameterTypes.size());
|
auto p = vector<shared_ptr<const ScriptType>>(parameterTypes.size());
|
||||||
for (size_t i = 0; i < parameterTypes.size(); i++){
|
for (size_t i = 0; i < parameterTypes.size(); i++){
|
||||||
p[i] = shared_ptr<const ScriptType>(parameterTypes[i]);
|
p[i] = shared_ptr<ScriptType>(parameterTypes[i]);
|
||||||
}
|
}
|
||||||
return new UserDataFunctionOption(rt, p);
|
return new UserDataFunctionOption(rt, p);
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ namespace Porygon::UserData {
|
||||||
auto str = dynamic_cast<const StringScriptType*>(indexer);
|
auto str = dynamic_cast<const StringScriptType*>(indexer);
|
||||||
if (!str->IsKnownAtBind())
|
if (!str->IsKnownAtBind())
|
||||||
return false;
|
return false;
|
||||||
return _userData->Get()->ContainsField(str->GetHashValue());
|
return _userData->Get()->ContainsField(str->GetHashValue().GetHash());
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] inline bool CanBeIndexedWithIdentifier(uint32_t hash) const final {
|
[[nodiscard]] inline bool CanBeIndexedWithIdentifier(uint32_t hash) const final {
|
||||||
|
@ -47,10 +47,10 @@ namespace Porygon::UserData {
|
||||||
return _userData->Get()->GetField(id);
|
return _userData->Get()->GetField(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
shared_ptr<const ScriptType> GetIndexedType(const ScriptType *indexer) const final {
|
shared_ptr<const ScriptType> GetIndexedType(shared_ptr<const ScriptType> indexer) const final {
|
||||||
auto stringKey = dynamic_cast<const StringScriptType*>(indexer);
|
auto stringKey = dynamic_pointer_cast<const StringScriptType>(indexer);
|
||||||
if (stringKey->IsKnownAtBind()) {
|
if (stringKey->IsKnownAtBind()) {
|
||||||
return _userData->Get()->GetField(stringKey->GetHashValue())->GetType();
|
return _userData->Get()->GetField(stringKey->GetHashValue().GetHash())->GetType();
|
||||||
}
|
}
|
||||||
throw "TODO: indexing with dynamic keys";
|
throw "TODO: indexing with dynamic keys";
|
||||||
}
|
}
|
||||||
|
@ -72,6 +72,30 @@ namespace Porygon::UserData {
|
||||||
return s.str();
|
return s.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
bool CanSetIndexValue(shared_ptr<const ScriptType> indexer, shared_ptr<const ScriptType> val) const override {
|
||||||
|
if (indexer->GetClass() != TypeClass::String)
|
||||||
|
return false;
|
||||||
|
auto s = dynamic_pointer_cast<const StringScriptType>(indexer);
|
||||||
|
if (!s->IsKnownAtBind())
|
||||||
|
return false;
|
||||||
|
auto hash = s->GetHashValue();
|
||||||
|
auto ud = _userData->Get();
|
||||||
|
if (!ud->ContainsField(hash.GetHash()))
|
||||||
|
return false;
|
||||||
|
auto field = _userData->Get()->GetField(hash.GetHash());
|
||||||
|
return (val->CastableTo(field->GetType(), false) != CastResult::InvalidCast);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool CanSetIndexValue(Utilities::HashedString indexer, shared_ptr<const ScriptType> val) const override {
|
||||||
|
auto ud = _userData->Get();
|
||||||
|
if (ud->ContainsField(indexer.GetHash()))
|
||||||
|
return false;
|
||||||
|
auto field = _userData->Get()->GetField(indexer.GetHash());
|
||||||
|
return (val->CastableTo(field->GetType(), false) != CastResult::InvalidCast);
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -87,6 +87,18 @@ return table["getFoo"]()
|
||||||
delete script;
|
delete script;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE( "Dynamic table size", "[integration]" ) {
|
||||||
|
Script* script = Script::Create(
|
||||||
|
R"(
|
||||||
|
table = {}
|
||||||
|
table.foo = 500
|
||||||
|
)");
|
||||||
|
REQUIRE(!script->Diagnostics -> HasErrors());
|
||||||
|
script->Evaluate();
|
||||||
|
delete script;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue