Initial work on iterators, rework of variable handling by including actual string
continuous-integration/drone/push Build is failing Details

This commit is contained in:
Deukhoofd 2019-06-23 15:58:14 +02:00
parent 1a84661c79
commit 76b8ba3ebc
No known key found for this signature in database
GPG Key ID: B4C087AC81641654
25 changed files with 185 additions and 78 deletions

View File

@ -72,8 +72,8 @@ namespace Porygon::Binder {
auto boundExpression = this->BindExpression(s->GetExpression()); auto boundExpression = this->BindExpression(s->GetExpression());
VariableAssignment assignment = VariableAssignment assignment =
s->IsLocal() ? s->IsLocal() ?
this->_scope->CreateExplicitLocal(s->GetIdentifier().GetHash(), boundExpression->GetType()) this->_scope->CreateExplicitLocal(s->GetIdentifier(), boundExpression->GetType())
: this->_scope->AssignVariable(s->GetIdentifier().GetHash(), boundExpression->GetType()); : this->_scope->AssignVariable(s->GetIdentifier(), boundExpression->GetType());
if (assignment.GetResult() == VariableAssignmentResult::Ok) { if (assignment.GetResult() == VariableAssignmentResult::Ok) {
auto key = assignment.GetKey(); auto key = assignment.GetKey();
return new BoundAssignmentStatement(key, boundExpression); return new BoundAssignmentStatement(key, boundExpression);
@ -139,7 +139,7 @@ namespace Porygon::Binder {
return new BoundBadStatement(); return new BoundBadStatement();
} }
parameterTypes.at(i) = parsedType; parameterTypes.at(i) = parsedType;
auto parameterAssignment = this->_scope->CreateExplicitLocal(var->GetIdentifier().GetHash(), parsedType); auto parameterAssignment = this->_scope->CreateExplicitLocal(var->GetIdentifier(), parsedType);
if (parameterAssignment.GetResult() == VariableAssignmentResult::Ok) { if (parameterAssignment.GetResult() == VariableAssignmentResult::Ok) {
parameterKeys.at(i) = std::shared_ptr<BoundVariableKey>(parameterAssignment.GetKey()); parameterKeys.at(i) = std::shared_ptr<BoundVariableKey>(parameterAssignment.GetKey());
} else { } else {
@ -153,7 +153,7 @@ namespace Porygon::Binder {
auto type = make_shared<FunctionScriptType>(returnType, parameterTypes, parameterKeys, scopeIndex); auto type = make_shared<FunctionScriptType>(returnType, parameterTypes, parameterKeys, scopeIndex);
this->_currentFunction = type; this->_currentFunction = type;
auto assignment = this->_scope->AssignVariable(identifier.GetHash(), type); auto assignment = this->_scope->AssignVariable(identifier, type);
if (assignment.GetResult() != VariableAssignmentResult::Ok) { if (assignment.GetResult() != VariableAssignmentResult::Ok) {
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::CantAssignVariable, statement->GetStartPosition(), this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::CantAssignVariable, statement->GetStartPosition(),
statement->GetLength()); statement->GetLength());
@ -242,7 +242,7 @@ namespace Porygon::Binder {
} }
this -> _scope ->GoInnerScope(); this -> _scope ->GoInnerScope();
auto variableKey = this -> _scope ->CreateExplicitLocal(identifier.GetHash(), make_shared<NumericScriptType>(true, false)); auto variableKey = this -> _scope ->CreateExplicitLocal(identifier, make_shared<NumericScriptType>(true, false));
if (variableKey.GetResult() != VariableAssignmentResult::Ok){ if (variableKey.GetResult() != VariableAssignmentResult::Ok){
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::CantAssignVariable, statement->GetStartPosition(), this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::CantAssignVariable, statement->GetStartPosition(),
statement->GetLength()); statement->GetLength());
@ -300,15 +300,15 @@ namespace Porygon::Binder {
BoundExpression *Binder::BindVariableExpression(const VariableExpression *expression) { BoundExpression *Binder::BindVariableExpression(const VariableExpression *expression) {
auto key = expression->GetValue(); auto key = expression->GetValue();
auto scope = this->_scope->Exists(key.GetHash()); auto scope = this->_scope->Exists(key);
if (scope == -1) { if (scope == -1) {
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::VariableNotFound, expression->GetStartPosition(), this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::VariableNotFound, expression->GetStartPosition(),
expression->GetLength()); expression->GetLength());
return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength()); return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength());
} }
auto var = this->_scope->GetVariable(scope, key.GetHash()); auto var = this->_scope->GetVariable(scope, key);
auto type = var->GetType(); auto type = var->GetType();
return new BoundVariableExpression(new BoundVariableKey(key.GetHash(), scope, false), type, return new BoundVariableExpression(new BoundVariableKey(key, scope, false), type,
expression->GetStartPosition(), expression->GetLength()); expression->GetStartPosition(), expression->GetLength());
} }
@ -616,7 +616,7 @@ namespace Porygon::Binder {
} }
BoundExpression *Binder::BindTableExpression(const ParsedTableExpression *expression) { BoundExpression *Binder::BindTableExpression(const ParsedTableExpression *expression) {
auto tableScope = new unordered_map<uint32_t, BoundVariable *>(); auto tableScope = new map<Utilities::HashedString, BoundVariable *>();
auto innerScope = new BoundScope(tableScope); auto innerScope = new BoundScope(tableScope);
auto currentScope = this->_scope; auto currentScope = this->_scope;
this->_scope = innerScope; this->_scope = innerScope;

View File

@ -4,11 +4,11 @@
#include "BoundScope.hpp" #include "BoundScope.hpp"
namespace Porygon::Binder { namespace Porygon::Binder {
BoundScope::BoundScope(unordered_map<uint32_t, BoundVariable *> *tableScope) { BoundScope::BoundScope(map<Utilities::HashedString, BoundVariable *> *tableScope) {
_tableScope = tableScope; _tableScope = tableScope;
_currentScope = 1; _currentScope = 1;
_lastCreatedScope = 1; _lastCreatedScope = 1;
auto localUpmostScope = new unordered_map<uint32_t, BoundVariable *>(); auto localUpmostScope = new map<Utilities::HashedString, BoundVariable *>();
_localScope.push_back(localUpmostScope); _localScope.push_back(localUpmostScope);
} }
@ -25,7 +25,7 @@ namespace Porygon::Binder {
_lastCreatedScope++; _lastCreatedScope++;
_currentScope = _lastCreatedScope; _currentScope = _lastCreatedScope;
if (_localScope.size() < _currentScope) { if (_localScope.size() < _currentScope) {
auto innerScope = new unordered_map<uint32_t, BoundVariable *>(); auto innerScope = new map<Utilities::HashedString, BoundVariable *>();
_localScope.push_back(innerScope); _localScope.push_back(innerScope);
} }
} }
@ -39,7 +39,7 @@ namespace Porygon::Binder {
_currentScope--; _currentScope--;
} }
int BoundScope::Exists(int key) { int BoundScope::Exists(Utilities::HashedString key) {
auto found = this->_tableScope->find(key); auto found = this->_tableScope->find(key);
if (found != _tableScope->end()) { if (found != _tableScope->end()) {
return 0; return 0;
@ -54,7 +54,7 @@ namespace Porygon::Binder {
return -1; return -1;
} }
BoundVariable *BoundScope::GetVariable(uint32_t scope, uint32_t identifier) { BoundVariable *BoundScope::GetVariable(uint32_t scope, Utilities::HashedString identifier) {
if (scope == 0) { if (scope == 0) {
auto find = this->_tableScope->find(identifier); auto find = this->_tableScope->find(identifier);
if (find != _tableScope->end()) { if (find != _tableScope->end()) {
@ -71,7 +71,7 @@ namespace Porygon::Binder {
} }
} }
VariableAssignment BoundScope::CreateExplicitLocal(uint32_t identifier, std::shared_ptr<ScriptType> type) { VariableAssignment BoundScope::CreateExplicitLocal(Utilities::HashedString identifier, std::shared_ptr<ScriptType> type) {
auto scope = this->_localScope.at(this->_currentScope - 1); auto scope = this->_localScope.at(this->_currentScope - 1);
if (scope->find(identifier) != scope->end()) { if (scope->find(identifier) != scope->end()) {
return VariableAssignment(VariableAssignmentResult::ExplicitLocalVariableExists, nullptr); return VariableAssignment(VariableAssignmentResult::ExplicitLocalVariableExists, nullptr);
@ -81,7 +81,7 @@ namespace Porygon::Binder {
new BoundVariableKey(identifier, this->_currentScope, true)); new BoundVariableKey(identifier, this->_currentScope, true));
} }
VariableAssignment BoundScope::AssignVariable(uint32_t identifier, const std::shared_ptr<ScriptType> &type) { VariableAssignment BoundScope::AssignVariable(Utilities::HashedString identifier, const std::shared_ptr<ScriptType> &type) {
int exists = this->Exists(identifier); int exists = this->Exists(identifier);
if (exists == -1) { if (exists == -1) {
// Creation // Creation

View File

@ -3,7 +3,7 @@
#define PORYGONLANG_BOUNDSCOPE_HPP #define PORYGONLANG_BOUNDSCOPE_HPP
#include <string> #include <string>
#include <unordered_map> #include <map>
#include <vector> #include <vector>
#include <memory> #include <memory>
#include "BoundVariable.hpp" #include "BoundVariable.hpp"
@ -15,12 +15,12 @@ using namespace std;
namespace Porygon::Binder { namespace Porygon::Binder {
class BoundScope { class BoundScope {
unordered_map<uint32_t, BoundVariable *> *_tableScope; map<Utilities::HashedString, BoundVariable *> *_tableScope;
vector<unordered_map<uint32_t, BoundVariable *> *> _localScope; vector<map<Utilities::HashedString, BoundVariable *> *> _localScope;
int _currentScope; int _currentScope;
int _lastCreatedScope; int _lastCreatedScope;
public: public:
explicit BoundScope(unordered_map<uint32_t, BoundVariable *> *tableScope); explicit BoundScope(map<Utilities::HashedString, BoundVariable *> *tableScope);
~BoundScope(); ~BoundScope();
@ -28,13 +28,13 @@ namespace Porygon::Binder {
void GoOuterScope(); void GoOuterScope();
int Exists(int key); int Exists(Utilities::HashedString key);
BoundVariable *GetVariable(uint32_t scope, uint32_t identifier); BoundVariable *GetVariable(uint32_t scope, Utilities::HashedString identifier);
VariableAssignment CreateExplicitLocal(uint32_t identifier, std::shared_ptr<ScriptType> type); VariableAssignment CreateExplicitLocal(Utilities::HashedString identifier, std::shared_ptr<ScriptType> type);
VariableAssignment AssignVariable(uint32_t identifier, const std::shared_ptr<ScriptType> &type); VariableAssignment AssignVariable(Utilities::HashedString identifier, const std::shared_ptr<ScriptType> &type);
size_t GetLocalVariableCount() { size_t GetLocalVariableCount() {
return _localScope.size(); return _localScope.size();

View File

@ -3,10 +3,11 @@
#define PORYGONLANG_BOUNDVARIABLEKEY_HPP #define PORYGONLANG_BOUNDVARIABLEKEY_HPP
#include <string> #include <string>
#include "../../Utilities/HashedString.hpp"
namespace Porygon::Binder { namespace Porygon::Binder {
class BoundVariableKey { class BoundVariableKey {
const int _identifier; const Utilities::HashedString _identifier;
const unsigned int _scopeId; const unsigned int _scopeId;
const bool _isCreation; const bool _isCreation;
const uint64_t _hash; const uint64_t _hash;
@ -18,14 +19,14 @@ namespace Porygon::Binder {
} }
public: public:
BoundVariableKey(int id, unsigned int scope, bool creation) BoundVariableKey(Utilities::HashedString id, unsigned int scope, bool creation)
: _identifier(id), : _identifier(id),
_scopeId(scope), _scopeId(scope),
_isCreation(creation), _isCreation(creation),
_hash(KnuthsHash(id, scope)) {} _hash(KnuthsHash(id.GetHash(), scope)) {}
const int GetIdentifier() const { const Utilities::HashedString GetIdentifier() const {
return _identifier; return _identifier;
} }

View File

@ -83,9 +83,9 @@ namespace Porygon::Evaluation {
throw; throw;
std::basic_ostringstream<char16_t> stringStream; std::basic_ostringstream<char16_t> stringStream;
auto left = this->EvaluateStringExpression(expression->GetLeft()); auto left = this->EvaluateStringExpression(expression->GetLeft());
stringStream << *left->EvaluateString(); stringStream << left->EvaluateString();
auto right = this->EvaluateExpression(expression->GetRight()); auto right = this->EvaluateExpression(expression->GetRight());
stringStream << *right->EvaluateString(); stringStream << right->EvaluateString();
return make_shared<StringEvalValue>(stringStream.str()); return make_shared<StringEvalValue>(stringStream.str());
} }
} }

View File

@ -24,7 +24,7 @@ namespace Porygon::Evaluation {
} }
const char16_t *EvaluateEvalValueString(EvalValue *v) { const char16_t *EvaluateEvalValueString(EvalValue *v) {
return v->EvaluateString()->c_str(); return (new u16string(v->EvaluateString()))->c_str();
} }

View File

@ -37,7 +37,7 @@ namespace Porygon::Evaluation {
throw EvaluationException("Can't evaluate this EvalValue as bool."); throw EvaluationException("Can't evaluate this EvalValue as bool.");
} }
virtual const std::u16string *EvaluateString() const { virtual const std::u16string EvaluateString() const {
throw EvaluationException("Can't evaluate this EvalValue as string."); throw EvaluationException("Can't evaluate this EvalValue as string.");
} }

View File

@ -4,6 +4,8 @@
#include <sstream> #include <sstream>
#include "EvalValue.hpp" #include "EvalValue.hpp"
#include "../../Utilities/StringUtils.hpp"
namespace Porygon::Evaluation { namespace Porygon::Evaluation {
class NumericEvalValue : public EvalValue { class NumericEvalValue : public EvalValue {
@ -58,6 +60,10 @@ namespace Porygon::Evaluation {
return _value; return _value;
} }
const std::u16string EvaluateString() const final{
return Utilities::StringUtils::IntToString(_value);
}
const shared_ptr<EvalValue> Clone() const final { const shared_ptr<EvalValue> Clone() const final {
return make_shared<IntegerEvalValue>(_value); return make_shared<IntegerEvalValue>(_value);
} }

View File

@ -28,8 +28,8 @@ namespace Porygon::Evaluation {
return this->_hash == b->GetHashCode(); return this->_hash == b->GetHashCode();
}; };
const u16string *EvaluateString() const final { const u16string EvaluateString() const final {
return &_value; return _value;
} }
const shared_ptr<EvalValue> Clone() const final { const shared_ptr<EvalValue> Clone() const final {

View File

@ -1,23 +1,23 @@
#ifndef PORYGONLANG_TABLEEVALVALUE_HPP #ifndef PORYGONLANG_TABLEEVALVALUE_HPP
#define PORYGONLANG_TABLEEVALVALUE_HPP #define PORYGONLANG_TABLEEVALVALUE_HPP
#include <utility> #include <utility>
#include <unordered_map> #include <map>
#include "EvalValue.hpp" #include "EvalValue.hpp"
using namespace std; using namespace std;
namespace Porygon::Evaluation { namespace Porygon::Evaluation {
class TableEvalValue : public EvalValue { class TableEvalValue : public EvalValue {
shared_ptr<unordered_map<uint32_t, shared_ptr<EvalValue>>> _table; shared_ptr<map<Utilities::HashedString, shared_ptr<EvalValue>>> _table;
size_t _hash; size_t _hash;
explicit TableEvalValue(shared_ptr<unordered_map<uint32_t, shared_ptr<EvalValue>>> table, size_t hash) { explicit TableEvalValue(shared_ptr<map<Utilities::HashedString, shared_ptr<EvalValue>>> table, size_t hash) {
_table = std::move(table); _table = std::move(table);
_hash = hash; _hash = hash;
} }
public: public:
explicit TableEvalValue(shared_ptr<unordered_map<uint32_t, shared_ptr<EvalValue>>> table) { explicit TableEvalValue(shared_ptr<map<Utilities::HashedString, shared_ptr<EvalValue>>> table) {
_table = std::move(table); _table = std::move(table);
_hash = rand(); _hash = rand();
} }
@ -39,23 +39,30 @@ namespace Porygon::Evaluation {
} }
const shared_ptr<EvalValue> IndexValue(EvalValue *val) const final { const shared_ptr<EvalValue> IndexValue(EvalValue *val) const final {
auto hash = val->GetHashCode(); const auto stringKey = val->EvaluateString();
return this->_table->at(hash); return this->_table->at(Utilities::HashedString(stringKey));
} }
const shared_ptr<EvalValue> IndexValue(uint32_t hash) const final { const shared_ptr<EvalValue> IndexValue(uint32_t hash) const final {
return this->_table->at(hash); return this->_table->at(Utilities::HashedString(hash));
} }
const shared_ptr<EvalValue> IndexValue(const char *val) const { const shared_ptr<EvalValue> IndexValue(const char *val) const {
auto hash = Utilities::HashedString::ConstHash(val); auto hash = Utilities::HashedString::ConstHash(val);
return this->_table->at(hash); return this->_table->at(Utilities::HashedString(hash));
} }
void SetIndexValue(EvalValue *key, const shared_ptr<EvalValue> &value) const final { void SetIndexValue(EvalValue *key, const shared_ptr<EvalValue> &value) const final {
auto hash = key->GetHashCode(); auto hash = key->GetHashCode();
this->_table->at(hash) = value; this->_table->at(Utilities::HashedString(hash)) = value;
} }
const _Rb_tree_const_iterator<pair<const Utilities::HashedString, shared_ptr<EvalValue>>> GetTableIterator() const{
return _table->cbegin();
};
const _Rb_tree_const_iterator<pair<const Utilities::HashedString, shared_ptr<EvalValue>>> GetTableIteratorEnd() const{
return _table->cend();
};
}; };
} }

View File

@ -3,10 +3,10 @@
#include <memory> #include <memory>
namespace Porygon::Evaluation { namespace Porygon::Evaluation {
EvaluationScope::EvaluationScope(unordered_map<uint32_t, shared_ptr<EvalValue>> *scriptVariables, EvaluationScope::EvaluationScope(map<Utilities::HashedString, shared_ptr<EvalValue>> *scriptVariables,
int localVariableCount) { int localVariableCount) {
_scriptScope = scriptVariables; _scriptScope = scriptVariables;
_localScope = unordered_map<uint64_t, shared_ptr<EvalValue>>(localVariableCount); _localScope = map<uint64_t, shared_ptr<EvalValue>>();
} }
void EvaluationScope::CreateVariable(const BoundVariableKey *key, const shared_ptr<EvalValue> &value) { void EvaluationScope::CreateVariable(const BoundVariableKey *key, const shared_ptr<EvalValue> &value) {

View File

@ -2,17 +2,17 @@
#ifndef PORYGONLANG_EVALUATIONSCOPE_HPP #ifndef PORYGONLANG_EVALUATIONSCOPE_HPP
#define PORYGONLANG_EVALUATIONSCOPE_HPP #define PORYGONLANG_EVALUATIONSCOPE_HPP
#include <unordered_map> #include <map>
#include <vector> #include <vector>
#include "../EvalValues/EvalValue.hpp" #include "../EvalValues/EvalValue.hpp"
using namespace Porygon::Binder; using namespace Porygon::Binder;
namespace Porygon::Evaluation { namespace Porygon::Evaluation {
class EvaluationScope { class EvaluationScope {
unordered_map<uint32_t, shared_ptr<EvalValue>> *_scriptScope; map<Utilities::HashedString, shared_ptr<EvalValue>> *_scriptScope;
unordered_map<uint64_t, shared_ptr<EvalValue>> _localScope; map<uint64_t, shared_ptr<EvalValue>> _localScope;
public: public:
explicit EvaluationScope(unordered_map<uint32_t, shared_ptr<EvalValue>> *scriptVariables, int deepestScope); explicit EvaluationScope(map<Utilities::HashedString, shared_ptr<EvalValue>> *scriptVariables, int deepestScope);
~EvaluationScope() = default; ~EvaluationScope() = default;

View File

@ -10,6 +10,7 @@
#include "../Binder/BoundExpressions/BoundTableExpression.hpp" #include "../Binder/BoundExpressions/BoundTableExpression.hpp"
#include "../TableScriptType.hpp" #include "../TableScriptType.hpp"
#include "../UserData/UserDataFunction.hpp" #include "../UserData/UserDataFunction.hpp"
#include "../Utilities/StringUtils.hpp"
using namespace std; using namespace std;
using namespace Porygon::Binder; using namespace Porygon::Binder;
@ -388,12 +389,13 @@ namespace Porygon::Evaluation {
const shared_ptr<EvalValue> Evaluator::EvaluateNumericTableExpression(const BoundExpression *expression) { const shared_ptr<EvalValue> Evaluator::EvaluateNumericTableExpression(const BoundExpression *expression) {
auto tableExpression = (BoundNumericalTableExpression *) expression; auto tableExpression = (BoundNumericalTableExpression *) expression;
auto valueExpressions = tableExpression->GetExpressions(); auto valueExpressions = tableExpression->GetExpressions();
auto values = new unordered_map<uint32_t, shared_ptr<EvalValue>>(valueExpressions->size()); auto values = new map<Utilities::HashedString, shared_ptr<EvalValue>>();
for (int i = 0; i < valueExpressions->size(); i++) { for (int i = 0; i < valueExpressions->size(); i++) {
auto val = this->EvaluateExpression(valueExpressions->at(i)); auto val = this->EvaluateExpression(valueExpressions->at(i));
values->insert({i + 1, val}); auto key = Utilities::StringUtils::IntToString(i + 1);
values->insert({Utilities::HashedString(key), val});
} }
auto valuesPointer = shared_ptr<unordered_map<uint32_t, shared_ptr<EvalValue>>>(values); auto valuesPointer = shared_ptr<map<Utilities::HashedString, shared_ptr<EvalValue>>>(values);
return make_shared<TableEvalValue>(valuesPointer); return make_shared<TableEvalValue>(valuesPointer);
} }
@ -401,7 +403,7 @@ namespace Porygon::Evaluation {
auto tableExpression = (BoundTableExpression *) expression; auto tableExpression = (BoundTableExpression *) expression;
auto type = dynamic_pointer_cast<TableScriptType>(tableExpression->GetType()); auto type = dynamic_pointer_cast<TableScriptType>(tableExpression->GetType());
auto declaredVars = type->GetValues(); auto declaredVars = type->GetValues();
auto variables = make_shared<unordered_map<uint32_t, shared_ptr<EvalValue>>>(declaredVars->size()); auto variables = make_shared<map<Utilities::HashedString, shared_ptr<EvalValue>>>();
for (auto i : *declaredVars) { for (auto i : *declaredVars) {
variables->insert({i.first, nullptr}); variables->insert({i.first, nullptr});
} }

View File

@ -16,7 +16,7 @@ using namespace std;
namespace Porygon::Evaluation{ namespace Porygon::Evaluation{
class Evaluator { class Evaluator {
shared_ptr<EvalValue> _returnValue; shared_ptr<EvalValue> _returnValue;
unordered_map<uint32_t, shared_ptr<EvalValue>>* _scriptVariables; map<Utilities::HashedString, shared_ptr<EvalValue>>* _scriptVariables;
bool _hasReturned; bool _hasReturned;
shared_ptr<EvalValue> _lastValue; shared_ptr<EvalValue> _lastValue;
@ -56,7 +56,7 @@ namespace Porygon::Evaluation{
const shared_ptr<EvalValue> GetVariable(const BoundVariableExpression *expression); const shared_ptr<EvalValue> GetVariable(const BoundVariableExpression *expression);
public: public:
explicit Evaluator(unordered_map<uint32_t, shared_ptr<EvalValue>>* scriptVariables){ explicit Evaluator(map<Utilities::HashedString, shared_ptr<EvalValue>>* scriptVariables){
_scriptVariables = scriptVariables; _scriptVariables = scriptVariables;
_hasReturned = false; _hasReturned = false;
_returnValue = nullptr; _returnValue = nullptr;

View File

@ -0,0 +1,2 @@
#include "Iterator.hpp"

View File

@ -0,0 +1,43 @@
#ifndef PORYGONLANG_ITERATOR_HPP
#define PORYGONLANG_ITERATOR_HPP
#include <memory>
#include "../EvalValues/EvalValue.hpp"
#include "../EvalValues/TableEvalValue.hpp"
#include "../EvalValues/StringEvalValue.hpp"
using namespace std;
namespace Porygon::Evaluation{
class Iterator {
public:
virtual shared_ptr<EvalValue> GetCurrent() = 0;
virtual bool MoveNext() = 0;
virtual void Reset() = 0;
};
class TableKeyIterator : Iterator{
_Rb_tree_const_iterator<pair<const Utilities::HashedString, shared_ptr<EvalValue>>> _iterator;
_Rb_tree_const_iterator<pair<const Utilities::HashedString, shared_ptr<EvalValue>>> _end;
public:
TableKeyIterator(shared_ptr<TableEvalValue> table)
: _iterator(table->GetTableIterator()), _end(table->GetTableIteratorEnd()){}
shared_ptr<EvalValue> GetCurrent() final{
return make_shared<StringEvalValue>(_iterator->first.GetString());
}
bool MoveNext() final{
std::advance(_iterator, 1);
return _iterator != _end;
}
void Reset(){
throw EvaluationException("Can't reset table key iterator");
}
};
}
#endif //PORYGONLANG_ITERATOR_HPP

View File

@ -25,7 +25,8 @@ Porygon::Script *Porygon::Script::Create(const string &script) {
Porygon::Script::Script(const u16string& s) { Porygon::Script::Script(const u16string& s) {
Diagnostics = new Diagnostics::DiagnosticsHolder(s); Diagnostics = new Diagnostics::DiagnosticsHolder(s);
_boundScript = nullptr; _boundScript = nullptr;
_scriptVariables = new unordered_map<uint32_t, shared_ptr<EvalValue>>(0);
_scriptVariables = new map<Utilities::HashedString, shared_ptr<EvalValue>>();
_evaluator = new Evaluator(this -> _scriptVariables); _evaluator = new Evaluator(this -> _scriptVariables);
this -> Parse(s); this -> Parse(s);
@ -53,7 +54,7 @@ void Porygon::Script::Parse(const u16string& script) {
} }
lexResult.clear(); lexResult.clear();
if (!Diagnostics->HasErrors()){ if (!Diagnostics->HasErrors()){
unordered_map<uint32_t, BoundVariable*> scriptScope; map<Utilities::HashedString, BoundVariable*> scriptScope;
auto bindScope = new BoundScope(&scriptScope); auto bindScope = new BoundScope(&scriptScope);
this->_boundScript = Binder::Binder::Bind(this, parseResult, bindScope); this->_boundScript = Binder::Binder::Bind(this, parseResult, bindScope);
for (const auto& v : scriptScope){ for (const auto& v : scriptScope){
@ -66,11 +67,11 @@ void Porygon::Script::Parse(const u16string& script) {
} }
EvalValue *Porygon::Script::GetVariable(const u16string &key) { EvalValue *Porygon::Script::GetVariable(const u16string &key) {
return _scriptVariables -> at(HashedString(key).GetHash()).get(); return _scriptVariables -> at(HashedString(key)).get();
} }
bool Porygon::Script::HasVariable(const u16string &key) { bool Porygon::Script::HasVariable(const u16string &key) {
auto f = _scriptVariables->find(HashedString(key).GetHash()); auto f = _scriptVariables->find(HashedString(key));
return f != _scriptVariables->end(); return f != _scriptVariables->end();
} }
@ -79,7 +80,7 @@ EvalValue *Porygon::Script::GetLastValue() {
} }
bool Porygon::Script::HasFunction(const u16string &key) { bool Porygon::Script::HasFunction(const u16string &key) {
auto f = _scriptVariables->find(HashedString(key).GetHash()); auto f = _scriptVariables->find(HashedString(key));
return f != _scriptVariables->end() && f.operator->()->second->GetTypeClass() == TypeClass ::Function; return f != _scriptVariables->end() && f.operator->()->second->GetTypeClass() == TypeClass ::Function;
} }

View File

@ -5,7 +5,7 @@
#include <utility> #include <utility>
#include <string> #include <string>
#include <unordered_map> #include <map>
#include "Diagnostics/DiagnosticsHolder.hpp" #include "Diagnostics/DiagnosticsHolder.hpp"
#include "Binder/BoundStatements/BoundStatement.hpp" #include "Binder/BoundStatements/BoundStatement.hpp"
#include "Evaluator/Evaluator.hpp" #include "Evaluator/Evaluator.hpp"
@ -18,7 +18,7 @@ using namespace Porygon::Evaluation;
namespace Porygon{ namespace Porygon{
class Script { class Script {
Evaluator* _evaluator; Evaluator* _evaluator;
unordered_map<uint32_t, shared_ptr<EvalValue>>* _scriptVariables; map<Utilities::HashedString, shared_ptr<EvalValue>>* _scriptVariables;
Binder::BoundScriptStatement* _boundScript; Binder::BoundScriptStatement* _boundScript;
shared_ptr<ScriptType> _returnType; shared_ptr<ScriptType> _returnType;

View File

@ -6,10 +6,10 @@
namespace Porygon{ namespace Porygon{
class TableScriptType : public ScriptType{ class TableScriptType : public ScriptType{
const unordered_map<uint32_t, BoundVariable*>* _values; const map<Utilities::HashedString, BoundVariable*>* _values;
const int _localVariableCount; const int _localVariableCount;
public: public:
explicit TableScriptType(unordered_map<uint32_t, BoundVariable*>* values, int localVariableCount) explicit TableScriptType(map<Utilities::HashedString, BoundVariable*>* values, int localVariableCount)
: ScriptType(TypeClass::Table), : ScriptType(TypeClass::Table),
_values(values), _values(values),
_localVariableCount(localVariableCount) _localVariableCount(localVariableCount)
@ -33,16 +33,16 @@ namespace Porygon{
const shared_ptr<ScriptType> GetIndexedType(ScriptType* indexer) const final{ const shared_ptr<ScriptType> GetIndexedType(ScriptType* indexer) const final{
auto stringKey = (StringScriptType*)indexer; auto stringKey = (StringScriptType*)indexer;
if (stringKey->IsKnownAtBind()){ if (stringKey->IsKnownAtBind()){
return _values-> at(stringKey->GetHashValue())->GetType(); return _values-> at(Utilities::HashedString(stringKey->GetHashValue()))->GetType();
} }
throw "TODO: indexing with dynamic keys"; throw "TODO: indexing with dynamic keys";
} }
const shared_ptr<ScriptType> GetIndexedType(uint32_t hash) const final{ const shared_ptr<ScriptType> GetIndexedType(uint32_t hash) const final{
return _values-> at(hash)->GetType(); return _values-> at(Utilities::HashedString(hash))->GetType();
} }
const unordered_map<uint32_t, BoundVariable*>* GetValues() const{ const map<Utilities::HashedString, BoundVariable*>* GetValues() const{
return _values; return _values;
} }

View File

@ -7,16 +7,28 @@
namespace Porygon::Utilities{ namespace Porygon::Utilities{
class HashedString{ class HashedString{
const uint32_t _hash; const uint32_t _hash;
const std::u16string _string;
public: public:
explicit HashedString(const std::u16string& s) : _hash(ConstHash(s.c_str())){ explicit HashedString(const std::u16string& s)
: _hash(ConstHash(s.c_str())),
_string(s)
{
} }
explicit HashedString(char16_t const *input) : _hash(ConstHash(input)){ explicit HashedString(char16_t const *input)
: _hash(ConstHash(input)),
_string(std::u16string(input))
{
} }
explicit HashedString(char const *input) : _hash(ConstHash(input)){ explicit HashedString(char const *input) : _hash(ConstHash(input)){
} }
HashedString(const HashedString& b) = default; explicit HashedString(uint32_t hash) : _hash(hash){
}
HashedString(const HashedString& b) :_hash(b._hash), _string(b._string){
};
static uint32_t constexpr ConstHash(char16_t const *input) { static uint32_t constexpr ConstHash(char16_t const *input) {
return *input ? return *input ?
@ -34,12 +46,24 @@ namespace Porygon::Utilities{
return _hash; return _hash;
} }
const std::u16string* GetString() const{
return &_string;
}
bool operator==(const HashedString& b) const{ bool operator==(const HashedString& b) const{
return _hash == b._hash; return _hash == b._hash;
} }
bool operator!=(const HashedString& b) const{ bool operator!=(const HashedString& b) const{
return _hash != b._hash; return _hash != b._hash;
} }
bool operator<(const HashedString& b) const{
return _hash < b._hash;
}
bool operator>(const HashedString& b) const{
return _hash > b._hash;
}
}; };
} }

View File

@ -0,0 +1,21 @@
#ifndef PORYGONLANG_STRINGUTILS_HPP
#define PORYGONLANG_STRINGUTILS_HPP
#include <iostream>
#include <string>
#include <locale>
#include <codecvt>
#include <sstream>
namespace Porygon::Utilities{
class StringUtils{
public:
static std::u16string IntToString(long const &i) {
std::wstring_convert<std::codecvt_utf8_utf16<char16_t, 0x10ffff, std::little_endian>, char16_t> conv;
return conv.from_bytes(std::to_string(i));
}
};
}
#endif //PORYGONLANG_STRINGUTILS_HPP

View File

@ -8,7 +8,7 @@ TEST_CASE( "String indexing", "[integration]" ) {
REQUIRE(!script->Diagnostics -> HasErrors()); REQUIRE(!script->Diagnostics -> HasErrors());
script->Evaluate(); script->Evaluate();
auto lastValue = script->GetLastValue(); auto lastValue = script->GetLastValue();
REQUIRE(*lastValue->EvaluateString() == u"b"); REQUIRE(lastValue->EvaluateString() == u"b");
delete script; delete script;
} }
@ -21,7 +21,7 @@ return foo.bar
)"); )");
REQUIRE(!script->Diagnostics -> HasErrors()); REQUIRE(!script->Diagnostics -> HasErrors());
auto result = script->Evaluate(); auto result = script->Evaluate();
REQUIRE(*result->EvaluateString() == u"test"); REQUIRE(result->EvaluateString() == u"test");
delete script; delete script;
} }

View File

@ -10,7 +10,7 @@ TEST_CASE( "Simple String", "[integration]" ) {
REQUIRE(!script->Diagnostics -> HasErrors()); REQUIRE(!script->Diagnostics -> HasErrors());
script->Evaluate(); script->Evaluate();
auto lastValue = script->GetLastValue(); auto lastValue = script->GetLastValue();
REQUIRE(*lastValue->EvaluateString() == u"foo bar"); REQUIRE(lastValue->EvaluateString() == u"foo bar");
delete script; delete script;
} }
@ -19,7 +19,7 @@ TEST_CASE( "String Concat", "[integration]" ) {
REQUIRE(!script->Diagnostics -> HasErrors()); REQUIRE(!script->Diagnostics -> HasErrors());
script->Evaluate(); script->Evaluate();
auto lastValue = script->GetLastValue(); auto lastValue = script->GetLastValue();
REQUIRE(*lastValue->EvaluateString() == u"foobar"); REQUIRE(lastValue->EvaluateString() == u"foobar");
delete script; delete script;
} }
@ -28,7 +28,7 @@ TEST_CASE( "String Concat 2", "[integration]" ) {
REQUIRE(!script->Diagnostics -> HasErrors()); REQUIRE(!script->Diagnostics -> HasErrors());
script->Evaluate(); script->Evaluate();
auto lastValue = script->GetLastValue(); auto lastValue = script->GetLastValue();
REQUIRE(*lastValue->EvaluateString() == u"foobar"); REQUIRE(lastValue->EvaluateString() == u"foobar");
delete script; delete script;
} }

View File

@ -40,7 +40,7 @@ return table[3]
REQUIRE(!script->Diagnostics -> HasErrors()); REQUIRE(!script->Diagnostics -> HasErrors());
auto variable = script->Evaluate(); auto variable = script->Evaluate();
REQUIRE(variable != nullptr); REQUIRE(variable != nullptr);
REQUIRE(*variable->EvaluateString() == u"foo"); REQUIRE(variable->EvaluateString() == u"foo");
delete script; delete script;
} }
@ -57,7 +57,7 @@ table = {
auto variable = script->GetVariable(u"table"); auto variable = script->GetVariable(u"table");
REQUIRE(variable != nullptr); REQUIRE(variable != nullptr);
auto table = (TableEvalValue*)variable; auto table = (TableEvalValue*)variable;
CHECK(*table->IndexValue("foo")->EvaluateString() == u"test"); CHECK(table->IndexValue("foo")->EvaluateString() == u"test");
CHECK(table->IndexValue("bar")->EvaluateInteger() == 100); CHECK(table->IndexValue("bar")->EvaluateInteger() == 100);
delete script; delete script;
} }

View File

@ -73,7 +73,7 @@ TEST_CASE( "Able to use emoji", "[integration]" ) {
REQUIRE(script -> HasVariable(uR"(💩)")); REQUIRE(script -> HasVariable(uR"(💩)"));
auto variable = script->GetVariable(uR"(💩)"); auto variable = script->GetVariable(uR"(💩)");
REQUIRE(variable != nullptr); REQUIRE(variable != nullptr);
CHECK(*variable->EvaluateString() == u"LJ"); CHECK(variable->EvaluateString() == u"LJ");
delete script; delete script;
} }