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,18 +102,35 @@ namespace Porygon::Binder {
|
|||
auto s = (ParsedIndexAssignmentStatement *) statement;
|
||||
auto indexExp = s->GetIndexExpression();
|
||||
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 boundIndexType = indexable->GetType();
|
||||
if (boundIndexType->GetClass() != TypeClass::Error &&
|
||||
boundIndexType->operator!=(valueExpression->GetType())) {
|
||||
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::InvalidTableValueType,
|
||||
statement->GetStartPosition(), statement->GetLength());
|
||||
return new BoundBadStatement();
|
||||
auto valueType = valueExpression->GetType();
|
||||
|
||||
if (indexExp->GetKind() == ParsedExpressionKind::Indexer) {
|
||||
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());
|
||||
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);
|
||||
|
@ -326,7 +343,7 @@ namespace Porygon::Binder {
|
|||
auto isValueVariableDefined = valueIdentifier.GetHash() != 0;
|
||||
const BoundVariableKey *valueVariable = nullptr;
|
||||
if (isValueVariableDefined) {
|
||||
auto valueType = itType->GetIndexedType(keyType.get());
|
||||
auto valueType = itType->GetIndexedType(keyType);
|
||||
auto valueVariableAssignment = this->_scope->CreateExplicitLocal(valueIdentifier, valueType);
|
||||
if (valueVariableAssignment.GetResult() != VariableAssignmentResult::Ok) {
|
||||
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::CantAssignVariable,
|
||||
|
@ -746,7 +763,8 @@ namespace Porygon::Binder {
|
|||
}
|
||||
if (indexerType->GetClass() == TypeClass::UserData) {
|
||||
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 (!field->HasGetter()) {
|
||||
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(),
|
||||
expression->GetLength());
|
||||
}
|
||||
|
@ -816,13 +834,19 @@ namespace Porygon::Binder {
|
|||
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::InvalidTableValueType,
|
||||
boundExpressions[i]->GetStartPosition(),
|
||||
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) {
|
||||
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(),
|
||||
expression->GetLength());
|
||||
}
|
||||
|
@ -835,7 +859,14 @@ namespace Porygon::Binder {
|
|||
auto block = dynamic_cast<BoundBlockStatement*>(this->BindBlockStatement(expression->GetBlock()));
|
||||
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;
|
||||
|
||||
return new BoundTableExpression(block, tableType, expression->GetStartPosition(), expression->GetLength());
|
||||
|
|
|
@ -145,7 +145,8 @@ namespace Porygon::Binder {
|
|||
public:
|
||||
BoundLiteralStringExpression(const u16string &value, unsigned int start, unsigned int 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) {
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ namespace Porygon::Diagnostics {
|
|||
VariableNotFound,
|
||||
ExpressionIsNotAFunction,
|
||||
CantIndex,
|
||||
CantIndexAssign,
|
||||
InvalidReturnType,
|
||||
ConditionNotABool,
|
||||
InvalidTableValueType,
|
||||
|
|
|
@ -77,6 +77,12 @@ namespace Porygon::Evaluation {
|
|||
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]]
|
||||
virtual Iterator * GetKeyIterator() const{
|
||||
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 "../Iterator/SimpleKeyIterator.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);
|
||||
}
|
||||
|
||||
|
@ -13,3 +14,20 @@ Porygon::Evaluation::TableEvalValue::UnaryOperation(Porygon::Binder::BoundUnaryO
|
|||
}
|
||||
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 {
|
||||
class TableEvalValue : public EvalValue {
|
||||
const shared_ptr<map<Utilities::HashedString, EvalValuePointer>> _table;
|
||||
const size_t _hash;
|
||||
|
||||
protected:
|
||||
explicit TableEvalValue(shared_ptr<map<Utilities::HashedString, EvalValuePointer>> table, size_t hash)
|
||||
: _table(std::move(table)),
|
||||
_hash(hash)
|
||||
{
|
||||
}
|
||||
|
||||
const shared_ptr<map<Utilities::HashedString, EvalValuePointer>> _table;
|
||||
const size_t _hash;
|
||||
public:
|
||||
explicit TableEvalValue(shared_ptr<map<Utilities::HashedString, EvalValuePointer>> table) :
|
||||
_table(std::move(table)),
|
||||
|
@ -47,7 +47,7 @@ namespace Porygon::Evaluation {
|
|||
}
|
||||
|
||||
[[nodiscard]]
|
||||
inline EvalValue* Clone() const final {
|
||||
inline EvalValue* Clone() const override {
|
||||
return new TableEvalValue(_table, _hash);
|
||||
}
|
||||
|
||||
|
@ -70,11 +70,15 @@ namespace Porygon::Evaluation {
|
|||
|
||||
inline void SetIndexValue(const EvalValue *key, const EvalValue* value) const final {
|
||||
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]]
|
||||
Iterator * GetKeyIterator() const final;
|
||||
Iterator * GetKeyIterator() const override;
|
||||
|
||||
[[nodiscard]]
|
||||
inline _Rb_tree_const_iterator<pair<const Utilities::HashedString, EvalValuePointer>> GetTableIterator() const{
|
||||
|
@ -85,7 +89,26 @@ namespace Porygon::Evaluation {
|
|||
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 "../ScriptTypes/TableScriptType.hpp"
|
||||
#include "../UserData/UserDataFunction.hpp"
|
||||
#include "EvalValues/NumericalTableEvalValue.hpp"
|
||||
#include "../UserData/UserDataValue.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
@ -93,12 +92,21 @@ namespace Porygon::Evaluation {
|
|||
void Evaluator::EvaluateIndexAssignmentStatement(const BoundIndexAssignmentStatement *statement) {
|
||||
auto indexExpression = statement->GetIndexExpression();
|
||||
auto value = this->EvaluateExpression(statement->GetValueExpression());
|
||||
auto index = ((BoundIndexExpression *) indexExpression);
|
||||
auto table = this->EvaluateExpression(index->GetIndexableExpression());
|
||||
auto key = this->EvaluateExpression(index->GetIndexExpression());
|
||||
table->SetIndexValue(key.Get(), value.Take());
|
||||
if (indexExpression->GetKind() == BoundExpressionKind::Index){
|
||||
auto index = dynamic_cast<const BoundIndexExpression*>(indexExpression);
|
||||
auto table = this->EvaluateExpression(index->GetIndexableExpression());
|
||||
auto key = this->EvaluateExpression(index->GetIndexExpression());
|
||||
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) {
|
||||
auto type = statement->GetType();
|
||||
auto key = statement->GetKey();
|
||||
|
@ -396,20 +404,22 @@ namespace Porygon::Evaluation {
|
|||
EvalValuePointer Evaluator::EvaluateNumericTableExpression(const BoundExpression *expression) {
|
||||
auto tableExpression = (BoundNumericalTableExpression *) expression;
|
||||
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++) {
|
||||
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);
|
||||
return new NumericalTableEvalValue(valuesPointer);
|
||||
auto valuesPointer = shared_ptr<map<Utilities::HashedString, EvalValuePointer>>(values);
|
||||
return new NumericTableEvalValue(valuesPointer);
|
||||
}
|
||||
|
||||
EvalValuePointer Evaluator::EvaluateComplexTableExpression(const BoundExpression *expression) {
|
||||
auto tableExpression = (BoundTableExpression *) expression;
|
||||
const auto& baseType = tableExpression -> GetType();
|
||||
auto type = dynamic_pointer_cast<const TableScriptType>(baseType);
|
||||
auto declaredVars = type->GetValues();
|
||||
auto declaredVars = type->GetContentTypes();
|
||||
auto variables = make_shared<map<Utilities::HashedString, EvalValuePointer>>();
|
||||
for (const auto& i : *declaredVars) {
|
||||
variables->insert({i.first, nullptr});
|
||||
|
|
|
@ -1 +1,6 @@
|
|||
#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
|
||||
#define PORYGONLANG_NUMERICALKEYITERATOR_HPP
|
||||
|
||||
|
||||
#include "Iterator.hpp"
|
||||
#include "../EvalValues/NumericalTableEvalValue.hpp"
|
||||
#include "../EvalValues/NumericEvalValue.hpp"
|
||||
|
||||
#include "SimpleKeyIterator.hpp"
|
||||
|
||||
namespace Porygon::Evaluation{
|
||||
class NumericalKeyIterator : public Iterator{
|
||||
const shared_ptr<vector<EvalValuePointer>> _vec;
|
||||
const size_t _size;
|
||||
size_t _position = 0;
|
||||
class NumericalKeyIterator : public TableKeyIterator{
|
||||
public:
|
||||
explicit NumericalKeyIterator(const NumericalTableEvalValue* table)
|
||||
: _vec(table->GetTable()), _size(_vec->size() + 1){}
|
||||
const EvalValue *GetCurrent() override;
|
||||
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
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
namespace Porygon::Evaluation{
|
||||
class TableKeyIterator : public Iterator{
|
||||
protected:
|
||||
_Rb_tree_const_iterator<pair<const Utilities::HashedString, EvalValuePointer>> _iterator;
|
||||
_Rb_tree_const_iterator<pair<const Utilities::HashedString, EvalValuePointer>> _end;
|
||||
bool _hasStarted = false;
|
||||
|
@ -15,7 +16,7 @@ namespace Porygon::Evaluation{
|
|||
explicit TableKeyIterator(const TableEvalValue* table)
|
||||
: _iterator(table->GetTableIterator()), _end(table->GetTableIteratorEnd()){}
|
||||
|
||||
inline const EvalValue* GetCurrent() final{
|
||||
inline const EvalValue* GetCurrent() override {
|
||||
return new StringEvalValue(*_iterator->first.GetString());
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#include "../Script.hpp"
|
||||
#include "../UserData/UserDataFunctionType.hpp"
|
||||
#include "ScriptType.hpp"
|
||||
|
||||
|
||||
namespace Porygon{
|
||||
|
@ -11,12 +10,13 @@ namespace Porygon{
|
|||
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::AnyType = make_shared<ScriptType>(TypeClass::Any);
|
||||
shared_ptr<const NumericScriptType> NumericScriptType::AwareInt = make_shared<NumericScriptType>(true, false);
|
||||
shared_ptr<const NumericScriptType> NumericScriptType::AwareFloat = make_shared<NumericScriptType>(true, true);
|
||||
shared_ptr<const NumericScriptType> NumericScriptType::Unaware = make_shared<NumericScriptType>(false, false);
|
||||
shared_ptr<const StringScriptType> StringScriptType::Dynamic = make_shared<StringScriptType>(false, 0);
|
||||
shared_ptr<const NumericScriptType> NumericScriptType::AwareInt = make_shared<const NumericScriptType>(true, false);
|
||||
shared_ptr<const NumericScriptType> NumericScriptType::AwareFloat = make_shared<const NumericScriptType>(true, true);
|
||||
shared_ptr<const NumericScriptType> NumericScriptType::Unaware = make_shared<const NumericScriptType>(false, false);
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -96,7 +96,7 @@ namespace Porygon{
|
|||
}
|
||||
|
||||
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){
|
||||
|
|
|
@ -43,9 +43,19 @@ namespace Porygon{
|
|||
|
||||
virtual bool CanBeIndexedWith(const ScriptType* indexer) 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 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 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{
|
||||
if (this->operator==(castType))
|
||||
return CastResult ::ValidCast;
|
||||
if (!explicitCast){
|
||||
if (castType->GetClass() != TypeClass::Number )
|
||||
return CastResult::InvalidCast;
|
||||
|
@ -117,11 +129,11 @@ namespace Porygon{
|
|||
|
||||
class StringScriptType : public ScriptType{
|
||||
bool _isKnownAtBind;
|
||||
uint32_t _hashValue;
|
||||
Utilities::HashedString _hashValue;
|
||||
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;
|
||||
_hashValue = hashValue;
|
||||
}
|
||||
|
||||
static shared_ptr<const StringScriptType> Dynamic;
|
||||
|
@ -134,7 +146,7 @@ namespace Porygon{
|
|||
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;
|
||||
}
|
||||
|
||||
|
@ -144,45 +156,12 @@ namespace Porygon{
|
|||
}
|
||||
|
||||
[[nodiscard]]
|
||||
inline uint32_t GetHashValue() const{
|
||||
inline Utilities::HashedString GetHashValue() const{
|
||||
return _hashValue;
|
||||
}
|
||||
|
||||
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
|
||||
#define PORYGONLANG_TABLESCRIPTTYPE_HPP
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include "../Binder/BoundVariables/BoundVariable.hpp"
|
||||
#include "../Exception.hpp"
|
||||
|
||||
namespace Porygon{
|
||||
|
||||
class TableScriptType : public ScriptType{
|
||||
const map<Utilities::HashedString, BoundVariable*>* _values;
|
||||
const int _localVariableCount;
|
||||
enum TableType{
|
||||
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:
|
||||
explicit TableScriptType(map<Utilities::HashedString, BoundVariable*>* values, int localVariableCount)
|
||||
: ScriptType(TypeClass::Table),
|
||||
_values(values),
|
||||
_localVariableCount(localVariableCount)
|
||||
{}
|
||||
|
||||
explicit TableScriptType()
|
||||
: ScriptType(TypeClass::Table),
|
||||
_values(nullptr),
|
||||
_localVariableCount(0)
|
||||
{}
|
||||
: ScriptType(TypeClass::Table), _tableType(TableType::Unknown) {}
|
||||
|
||||
explicit TableScriptType(shared_ptr<const ScriptType> valueType)
|
||||
: ScriptType(TypeClass::Table), _tableType(TableType::Numerical), _valueType(std::move(valueType)) {}
|
||||
|
||||
~TableScriptType() final{
|
||||
if (_values != nullptr){
|
||||
for (const auto& i : *_values){
|
||||
delete i.second;
|
||||
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;
|
||||
}
|
||||
|
||||
[[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.");
|
||||
}
|
||||
}
|
||||
|
||||
[[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;
|
||||
}
|
||||
else if (_tableType == TableType::Numerical){
|
||||
return indexer->GetClass() == TypeClass::Number;
|
||||
}
|
||||
else{
|
||||
auto keyType = _keyValueType.first;
|
||||
return indexer->CastableTo(keyType, false) != CastResult ::InvalidCast;
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] bool CanBeIndexedWithIdentifier(uint32_t hash) const override {
|
||||
if (_tableType != TableType::StringKeyed)
|
||||
return false;
|
||||
return _isContentAware;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
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;
|
||||
}
|
||||
|
||||
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});
|
||||
}
|
||||
}
|
||||
delete _values;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
inline bool CanBeIndexedWith(const ScriptType* indexer) const final{
|
||||
return indexer->GetClass() == TypeClass ::String;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool CanBeIndexedWithIdentifier(uint32_t hash) const final{
|
||||
return true;
|
||||
}
|
||||
|
||||
shared_ptr<const ScriptType> GetIndexedType(const ScriptType* indexer) const final{
|
||||
auto stringKey = dynamic_cast<const StringScriptType*>(indexer);
|
||||
if (stringKey != nullptr && stringKey->IsKnownAtBind() && _values != nullptr){
|
||||
return _values-> at(Utilities::HashedString::CreateLookup(stringKey->GetHashValue()))->GetType();
|
||||
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}
|
||||
};
|
||||
}
|
||||
return make_shared<ScriptType>(TypeClass::Any);
|
||||
}
|
||||
|
||||
[[nodiscard]] inline shared_ptr<const ScriptType> GetIndexedType(uint32_t hash) const final{
|
||||
return _values-> at(Utilities::HashedString::CreateLookup(hash))->GetType();
|
||||
}
|
||||
|
||||
[[nodiscard]] inline const map<Utilities::HashedString, BoundVariable*>* GetValues() const{
|
||||
return _values;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
bool CanBeIterated() const final {
|
||||
return true;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
shared_ptr<const ScriptType> GetIteratorKeyType() const final {
|
||||
return make_shared<ScriptType>(TypeClass::Any);
|
||||
}
|
||||
|
||||
bool IsCountable() const override {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ namespace Porygon::UserData {
|
|||
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;
|
||||
}
|
||||
|
||||
|
@ -70,6 +70,15 @@ namespace Porygon::UserData {
|
|||
[[nodiscard]] bool IsCountable() const override {
|
||||
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)) {
|
||||
|
||||
}
|
||||
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 p = vector<shared_ptr<const ScriptType>>(parameterTypes.size());
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ namespace Porygon::UserData {
|
|||
auto str = dynamic_cast<const StringScriptType*>(indexer);
|
||||
if (!str->IsKnownAtBind())
|
||||
return false;
|
||||
return _userData->Get()->ContainsField(str->GetHashValue());
|
||||
return _userData->Get()->ContainsField(str->GetHashValue().GetHash());
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool CanBeIndexedWithIdentifier(uint32_t hash) const final {
|
||||
|
@ -47,10 +47,10 @@ namespace Porygon::UserData {
|
|||
return _userData->Get()->GetField(id);
|
||||
}
|
||||
|
||||
shared_ptr<const ScriptType> GetIndexedType(const ScriptType *indexer) const final {
|
||||
auto stringKey = dynamic_cast<const StringScriptType*>(indexer);
|
||||
shared_ptr<const ScriptType> GetIndexedType(shared_ptr<const ScriptType> indexer) const final {
|
||||
auto stringKey = dynamic_pointer_cast<const StringScriptType>(indexer);
|
||||
if (stringKey->IsKnownAtBind()) {
|
||||
return _userData->Get()->GetField(stringKey->GetHashValue())->GetType();
|
||||
return _userData->Get()->GetField(stringKey->GetHashValue().GetHash())->GetType();
|
||||
}
|
||||
throw "TODO: indexing with dynamic keys";
|
||||
}
|
||||
|
@ -72,6 +72,30 @@ namespace Porygon::UserData {
|
|||
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;
|
||||
}
|
||||
|
||||
TEST_CASE( "Dynamic table size", "[integration]" ) {
|
||||
Script* script = Script::Create(
|
||||
R"(
|
||||
table = {}
|
||||
table.foo = 500
|
||||
)");
|
||||
REQUIRE(!script->Diagnostics -> HasErrors());
|
||||
script->Evaluate();
|
||||
delete script;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Reference in New Issue