Rework of memory handling in Evaluation
continuous-integration/drone/push Build is failing Details

This commit is contained in:
Deukhoofd 2019-07-27 17:59:42 +02:00
parent 268f6b59fb
commit ccc6e297f2
Signed by: Deukhoofd
GPG Key ID: ADF2E9256009EDCE
32 changed files with 496 additions and 461 deletions

View File

@ -1,91 +0,0 @@
#include "../Script.hpp"
#include "EvaluationException.hpp"
#include "Evaluator.hpp"
#include "EvalValues/NumericEvalValue.hpp"
#include "EvalValues/StringEvalValue.hpp"
using namespace Porygon::Binder;
namespace Porygon::Evaluation {
shared_ptr<const NumericEvalValue> Evaluator::EvaluateIntegerBinary(const BoundBinaryExpression *expression) {
auto leftValue = this->EvaluateIntegerExpression(expression->GetLeft());
auto rightValue = this->EvaluateIntegerExpression(expression->GetRight());
switch (expression->GetOperation()) {
case BoundBinaryOperation::Addition:
return leftValue.get()->operator+(rightValue);
case BoundBinaryOperation::Subtraction:
return leftValue.get()->operator-(rightValue);
case BoundBinaryOperation::Multiplication:
return leftValue.get()->operator*(rightValue);
case BoundBinaryOperation::Division:
return leftValue.get()->operator/(rightValue);
default:
throw EvaluationException("Can't evaluate operation to numeric");
}
}
shared_ptr<const BooleanEvalValue> Evaluator::EvaluateBooleanBinary(const BoundBinaryExpression *expression) {
switch (expression->GetOperation()) {
case BoundBinaryOperation::Equality: {
auto leftValue = this->EvaluateExpression(expression->GetLeft());
auto rightValue = this->EvaluateExpression(expression->GetRight());
bool equals = leftValue.get()->operator==(rightValue.get());
return make_shared<BooleanEvalValue>(equals);
}
case BoundBinaryOperation::Inequality: {
auto leftValue = this->EvaluateExpression(expression->GetLeft());
auto rightValue = this->EvaluateExpression(expression->GetRight());
bool equals = leftValue.get()->operator!=(rightValue.get());
return make_shared<BooleanEvalValue>(equals);
}
case BoundBinaryOperation::LessThan: {
auto leftValue = this->EvaluateIntegerExpression(expression->GetLeft());
auto rightValue = this->EvaluateIntegerExpression(expression->GetRight());
return leftValue->operator<(rightValue);
}
case BoundBinaryOperation::LessThanEquals: {
auto leftValue = this->EvaluateIntegerExpression(expression->GetLeft());
auto rightValue = this->EvaluateIntegerExpression(expression->GetRight());
return leftValue->operator<=(rightValue);
}
case BoundBinaryOperation::GreaterThan: {
auto leftValue = this->EvaluateIntegerExpression(expression->GetLeft());
auto rightValue = this->EvaluateIntegerExpression(expression->GetRight());
return leftValue->operator>(rightValue);
}
case BoundBinaryOperation::GreaterThanEquals: {
auto leftValue = this->EvaluateIntegerExpression(expression->GetLeft());
auto rightValue = this->EvaluateIntegerExpression(expression->GetRight());
return leftValue->operator>=(rightValue);
}
case BoundBinaryOperation::LogicalAnd: {
auto leftValue = this->EvaluateBoolExpression(expression->GetLeft());
if (!leftValue->EvaluateBool()) return leftValue;
auto rightValue = this->EvaluateBoolExpression(expression->GetRight());
return rightValue;
}
case BoundBinaryOperation::LogicalOr: {
auto leftValue = this->EvaluateBoolExpression(expression->GetLeft());
if (leftValue->EvaluateBool()) return leftValue;
auto rightValue = this->EvaluateBoolExpression(expression->GetRight());
return rightValue;
}
default:
throw EvaluationException("Can't evaluate operation to boolean");
}
}
shared_ptr<const StringEvalValue> Evaluator::EvaluateStringBinary(const BoundBinaryExpression *expression) {
if (expression->GetOperation() != BoundBinaryOperation::Concatenation)
throw;
std::basic_ostringstream<char16_t> stringStream;
auto left = this->EvaluateStringExpression(expression->GetLeft());
stringStream << left->EvaluateString();
auto right = this->EvaluateExpression(expression->GetRight());
stringStream << right->EvaluateString();
return make_shared<StringEvalValue>(stringStream.str());
}
}

View File

@ -0,0 +1 @@
#include "EvalValuePointer.hpp"

View File

@ -0,0 +1,85 @@
#ifndef PORYGONLANG_EVALVALUEPOINTER_HPP
#define PORYGONLANG_EVALVALUEPOINTER_HPP
#include "EvalValues/EvalValue.hpp"
namespace Porygon::Evaluation {
class EvalValuePointer {
const EvalValue *_ptr;
public:
EvalValuePointer(const EvalValue* p) :_ptr(p){};
EvalValuePointer(const EvalValuePointer& b){
if (b._ptr == nullptr){
_ptr = nullptr;
} else{
_ptr = b._ptr->Clone();
}
};
EvalValuePointer(){
_ptr = nullptr;
};
~EvalValuePointer(){
delete _ptr;
}
[[nodiscard]]
inline const EvalValue* Get() const{
return _ptr;
}
[[nodiscard]]
inline const EvalValue* Clone() const{
if (_ptr == nullptr){
return nullptr;
}
return _ptr->Clone();
}
inline const EvalValue* Take(){
auto p = _ptr;
_ptr = nullptr;
return p;
}
inline void ClearAssign(const EvalValue* n){
delete _ptr;
_ptr = n;
}
inline const bool HasValue() const{
return _ptr == nullptr;
}
inline const EvalValue* operator ->() const{
return Get();
}
inline bool operator == (const EvalValuePointer& b) const{
if (!_ptr){
return !b._ptr;
}
if (!b._ptr) return false;
return _ptr->operator==(b._ptr);
}
inline bool operator != (const EvalValuePointer& b) const{
if (!_ptr){
return b._ptr;
}
if (!b._ptr) return false;
return _ptr->operator!=(b._ptr);
}
EvalValuePointer& operator =(const EvalValuePointer& a){
if (a._ptr == nullptr){
_ptr = nullptr;
} else{
_ptr = a._ptr->Clone();
}
return *this;
};
};
}
#endif //PORYGONLANG_EVALVALUEPOINTER_HPP

View File

@ -64,9 +64,9 @@ TEST_CASE( "Evaluate String", "[integration]" ) {
auto script = Porygon::Script::Create(*sc);
REQUIRE(!script->Diagnostics -> HasErrors());
auto result = script->Evaluate();
size_t size = GetEvalValueStringLength(result.get());
size_t size = GetEvalValueStringLength(result.Get());
auto dst = new char16_t[size + 1]{'\0'};
EvaluateEvalValueString(result.get(), dst, size);
EvaluateEvalValueString(result.Get(), dst, size);
auto s = u16string(dst);
REQUIRE(s == u"foo bar");
delete[] dst;

View File

@ -12,6 +12,7 @@ namespace Porygon::Evaluation{
class Iterator;
}
#include "../Iterator/Iterator.hpp"
#include "../../Binder/BoundOperators.hpp"
namespace Porygon::Evaluation {
@ -33,7 +34,7 @@ namespace Porygon::Evaluation {
}
[[nodiscard]]
virtual shared_ptr<const EvalValue> Clone() const = 0;
virtual EvalValue* Clone() const = 0;
[[nodiscard]]
virtual long EvaluateInteger() const {
@ -59,16 +60,16 @@ namespace Porygon::Evaluation {
virtual std::size_t GetHashCode() const = 0;
[[nodiscard]]
virtual shared_ptr<const EvalValue> IndexValue(const EvalValue *val) const {
virtual const EvalValue* IndexValue(const EvalValue *val) const {
throw EvaluationException("Can't index this EvalValue");
}
[[nodiscard]]
virtual shared_ptr<const EvalValue> IndexValue(uint32_t hash) const {
virtual const EvalValue* IndexValue(uint32_t hash) const {
throw EvaluationException("Can't index this EvalValue");
}
virtual void SetIndexValue(const EvalValue *key, const shared_ptr<const EvalValue> &value) const {
virtual void SetIndexValue(const EvalValue *key, const EvalValue* value) const {
throw EvaluationException("Can't index this EvalValue");
}
@ -76,6 +77,16 @@ namespace Porygon::Evaluation {
virtual Iterator * GetKeyIterator() const{
throw EvaluationException("Can't iterate over this EvalValue");
}
[[nodiscard]]
virtual EvalValue* BinaryOperation(Binder::BoundBinaryOperation operation, const EvalValue* b) const{
throw EvaluationException("Binary operations are not implemented for this type.");
}
[[nodiscard]]
virtual EvalValue* UnaryOperation(Binder::BoundUnaryOperation operation) const{
throw EvaluationException("Unary operations are not implemented for this type.");
}
};
class BooleanEvalValue : public EvalValue {
@ -86,8 +97,8 @@ namespace Porygon::Evaluation {
}
[[nodiscard]]
inline shared_ptr<const EvalValue> Clone() const final {
return make_shared<BooleanEvalValue>(_value);
inline EvalValue* Clone() const final {
return new BooleanEvalValue(_value);
}
[[nodiscard]]
@ -111,6 +122,25 @@ namespace Porygon::Evaluation {
inline std::size_t GetHashCode() const final {
return _value;
}
[[nodiscard]]
inline EvalValue* BinaryOperation(Binder::BoundBinaryOperation operation, const EvalValue* b) const final{
auto bVal = b -> EvaluateBool();
switch (operation){
case Binder::BoundBinaryOperation::LogicalAnd: return new BooleanEvalValue(_value && bVal);
case Binder::BoundBinaryOperation::LogicalOr: return new BooleanEvalValue(_value || bVal);
default:
throw;
}
}
[[nodiscard]]
EvalValue* UnaryOperation(Binder::BoundUnaryOperation operation) const final{
switch (operation){
case Binder::BoundUnaryOperation::LogicalNegation: return new BooleanEvalValue(!_value);
default: throw;
}
}
};
}

View File

@ -15,8 +15,8 @@ namespace Porygon::Evaluation{
}
[[nodiscard]]
inline shared_ptr<const EvalValue> Clone() const final{
return make_shared<NilEvalValue>();
inline EvalValue* Clone() const final{
return new NilEvalValue();
}
[[nodiscard]]

View File

@ -143,4 +143,70 @@ namespace Porygon::Evaluation {
}
}
}
EvalValue *IntegerEvalValue::BinaryOperation(Binder::BoundBinaryOperation operation, const EvalValue *b) const {
auto right = dynamic_cast<const NumericEvalValue*>(b);
if (right->IsFloat()){
auto rightVal = right->EvaluateFloat();
switch (operation){
case Binder::BoundBinaryOperation::Addition: return new FloatEvalValue((double)_value + rightVal);
case Binder::BoundBinaryOperation::Subtraction: return new FloatEvalValue((double)_value - rightVal);
case Binder::BoundBinaryOperation::Multiplication: return new FloatEvalValue((double)_value * rightVal);
case Binder::BoundBinaryOperation::Division: return new FloatEvalValue((double)_value / rightVal);
case Binder::BoundBinaryOperation::LessThan: return new BooleanEvalValue((double)_value < rightVal);
case Binder::BoundBinaryOperation::LessThanEquals: return new BooleanEvalValue((double)_value <= rightVal);
case Binder::BoundBinaryOperation::GreaterThan: return new BooleanEvalValue((double)_value > rightVal);
case Binder::BoundBinaryOperation::GreaterThanEquals: return new BooleanEvalValue((double)_value >= rightVal);
default:
throw;
}
} else{
auto rightVal = right->EvaluateInteger();
switch (operation){
case Binder::BoundBinaryOperation::Addition: return new IntegerEvalValue(_value + rightVal);
case Binder::BoundBinaryOperation::Subtraction: return new IntegerEvalValue(_value - rightVal);
case Binder::BoundBinaryOperation::Multiplication: return new IntegerEvalValue(_value * rightVal);
case Binder::BoundBinaryOperation::Division: return new IntegerEvalValue(_value / rightVal);
case Binder::BoundBinaryOperation::LessThan: return new BooleanEvalValue(_value < rightVal);
case Binder::BoundBinaryOperation::LessThanEquals: return new BooleanEvalValue(_value <= rightVal);
case Binder::BoundBinaryOperation::GreaterThan: return new BooleanEvalValue(_value > rightVal);
case Binder::BoundBinaryOperation::GreaterThanEquals: return new BooleanEvalValue(_value >= rightVal);
default:
throw;
}
}
}
EvalValue *FloatEvalValue::BinaryOperation(Binder::BoundBinaryOperation operation, const EvalValue *b) const {
auto right = dynamic_cast<const NumericEvalValue*>(b);
if (right->IsFloat()){
auto rightVal = right->EvaluateFloat();
switch (operation){
case Binder::BoundBinaryOperation::Addition: return new FloatEvalValue(_value + rightVal);
case Binder::BoundBinaryOperation::Subtraction: return new FloatEvalValue(_value - rightVal);
case Binder::BoundBinaryOperation::Multiplication: return new FloatEvalValue(_value * rightVal);
case Binder::BoundBinaryOperation::Division: return new FloatEvalValue(_value / rightVal);
case Binder::BoundBinaryOperation::LessThan: return new BooleanEvalValue(_value < rightVal);
case Binder::BoundBinaryOperation::LessThanEquals: return new BooleanEvalValue(_value <= rightVal);
case Binder::BoundBinaryOperation::GreaterThan: return new BooleanEvalValue(_value > rightVal);
case Binder::BoundBinaryOperation::GreaterThanEquals: return new BooleanEvalValue(_value >= rightVal);
default:
throw;
}
} else{
auto rightVal = right->EvaluateInteger();
switch (operation){
case Binder::BoundBinaryOperation::Addition: return new IntegerEvalValue((long)_value + rightVal);
case Binder::BoundBinaryOperation::Subtraction: return new IntegerEvalValue((long)_value - rightVal);
case Binder::BoundBinaryOperation::Multiplication: return new IntegerEvalValue((long)_value * rightVal);
case Binder::BoundBinaryOperation::Division: return new IntegerEvalValue((long)_value / rightVal);
case Binder::BoundBinaryOperation::LessThan: return new BooleanEvalValue(_value < rightVal);
case Binder::BoundBinaryOperation::LessThanEquals: return new BooleanEvalValue(_value <= rightVal);
case Binder::BoundBinaryOperation::GreaterThan: return new BooleanEvalValue(_value > rightVal);
case Binder::BoundBinaryOperation::GreaterThanEquals: return new BooleanEvalValue(_value >= rightVal);
default:
throw;
}
}
}
}

View File

@ -74,14 +74,25 @@ namespace Porygon::Evaluation {
}
[[nodiscard]]
inline shared_ptr<const EvalValue> Clone() const final {
return make_shared<IntegerEvalValue>(_value);
inline EvalValue* Clone() const final {
return new IntegerEvalValue(_value);
}
[[nodiscard]]
inline std::size_t GetHashCode() const final {
return std::hash<long>{}(_value);
}
[[nodiscard]]
EvalValue* BinaryOperation(Binder::BoundBinaryOperation operation, const EvalValue* b) const final;
[[nodiscard]]
EvalValue* UnaryOperation(Binder::BoundUnaryOperation operation) const final{
switch (operation){
case Binder::BoundUnaryOperation::Negation: return new IntegerEvalValue(-_value);
default: throw;
}
}
};
class FloatEvalValue : public NumericEvalValue {
@ -112,14 +123,25 @@ namespace Porygon::Evaluation {
}
[[nodiscard]]
inline shared_ptr<const EvalValue> Clone() const final {
return make_shared<FloatEvalValue>(_value);
inline EvalValue* Clone() const final {
return new FloatEvalValue(_value);
}
[[nodiscard]]
inline std::size_t GetHashCode() const final {
return std::hash<double>{}(_value);
}
[[nodiscard]]
inline EvalValue* BinaryOperation(Binder::BoundBinaryOperation operation, const EvalValue* b) const final;
[[nodiscard]]
EvalValue* UnaryOperation(Binder::BoundUnaryOperation operation) const final{
switch (operation){
case Binder::BoundUnaryOperation::Negation: return new FloatEvalValue(-_value);
default: throw;
}
}
};
}

View File

@ -4,3 +4,9 @@
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(rand())
{
}

View File

@ -5,26 +5,23 @@
#include <utility>
#include <map>
#include "EvalValue.hpp"
#include "../EvalValuePointer.hpp"
using namespace std;
namespace Porygon::Evaluation {
class NumericalTableEvalValue : public EvalValue {
const shared_ptr<vector<shared_ptr<const EvalValue>>> _table;
const shared_ptr<vector<EvalValuePointer>> _table;
const size_t _hash;
explicit NumericalTableEvalValue(shared_ptr<vector<shared_ptr<const EvalValue>>> table, 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<shared_ptr<const EvalValue>>> table) :
_table(std::move(table)),
_hash(rand())
{
}
explicit NumericalTableEvalValue(shared_ptr<vector<EvalValuePointer>> table);
[[nodiscard]]
inline TypeClass GetTypeClass() const final {
@ -42,22 +39,22 @@ namespace Porygon::Evaluation {
}
[[nodiscard]]
inline shared_ptr<const EvalValue> Clone() const final {
return shared_ptr<EvalValue>(new NumericalTableEvalValue(_table, _hash));
inline EvalValue* Clone() const final {
return new NumericalTableEvalValue(_table, _hash);
}
[[nodiscard]]
inline shared_ptr<const EvalValue> IndexValue(const EvalValue *val) const final {
inline const EvalValue* IndexValue(const EvalValue *val) const final {
const auto index = val->EvaluateInteger() - 1;
return this->_table->at(index);
return this->_table->at(index).Clone();
}
[[nodiscard]]
inline shared_ptr<const EvalValue> IndexValue(uint32_t hash) const final {
return this->_table->at(hash - 1);
inline EvalValue* IndexValue(uint32_t hash) const final {
return this->_table->at(hash - 1)-> Clone();
}
inline void SetIndexValue(const EvalValue *key, const shared_ptr<const EvalValue> &value) const final {
inline void SetIndexValue(const EvalValue *key, const EvalValue* value) const final {
auto index = key->EvaluateInteger();
this->_table->at(index - 1) = value;
}
@ -66,7 +63,7 @@ namespace Porygon::Evaluation {
Iterator * GetKeyIterator() const final;
[[nodiscard]]
inline shared_ptr<vector<shared_ptr<const EvalValue>>> GetTable() const{
inline shared_ptr<vector<EvalValuePointer>> GetTable() const{
return _table;
};
};

View File

@ -42,15 +42,15 @@ namespace Porygon::Evaluation {
protected:
const shared_ptr<const GenericFunctionScriptType> _type;
const size_t _hash;
vector<shared_ptr<GenericFunctionOption>>* _options;
shared_ptr<vector<shared_ptr<GenericFunctionOption>>> _options;
GenericFunctionEvalValue(shared_ptr<const GenericFunctionScriptType> type, size_t hash,
shared_ptr<vector<shared_ptr<GenericFunctionOption>>> options)
:_type(std::move(type)), _hash(hash), _options(std::move(options))
{}
public:
GenericFunctionEvalValue(shared_ptr<const GenericFunctionScriptType> type, size_t hash)
: _type(move(type)),
_hash(hash), _options(new vector<shared_ptr<GenericFunctionOption>>()){
}
~GenericFunctionEvalValue() final{
delete _options;
_hash(hash), _options(make_shared<vector<shared_ptr<GenericFunctionOption>>>()){
}
GenericFunctionEvalValue(const GenericFunctionEvalValue& _) = delete;
@ -58,19 +58,16 @@ namespace Porygon::Evaluation {
GenericFunctionEvalValue& operator =(GenericFunctionEvalValue v) = delete;
[[nodiscard]]
shared_ptr<const EvalValue> Clone() const final {
auto t = make_shared<GenericFunctionEvalValue>(_type, _hash);
for (const auto& o: *_options){
t->_options->push_back(o);
}
return t;
EvalValue* Clone() const final {
return new GenericFunctionEvalValue(_type, _hash, _options);
}
inline void RegisterOption(GenericFunctionOption* option) const{
_options->push_back(shared_ptr<GenericFunctionOption>(option));
}
inline std::shared_ptr<const ScriptType> GetType() const {
[[nodiscard]]
inline std::shared_ptr<const GenericFunctionScriptType> GetType() const {
return _type;
}

View File

@ -34,20 +34,31 @@ namespace Porygon::Evaluation {
}
[[nodiscard]]
inline shared_ptr<const EvalValue> Clone() const final {
return make_shared<StringEvalValue>(_value);
inline EvalValue* Clone() const final {
return new StringEvalValue(_value);
}
shared_ptr<const EvalValue> IndexValue(const EvalValue *val) const final {
EvalValue* IndexValue(const EvalValue *val) const final {
// Porygon is 1-indexed, so we convert to that.
auto l = val->EvaluateInteger() - 1;
return make_shared<const StringEvalValue>(u16string(1, _value[l]));
return new StringEvalValue(u16string(1, _value[l]));
}
[[nodiscard]]
inline std::size_t GetHashCode() const final {
return _hash;
}
[[nodiscard]]
inline EvalValue* BinaryOperation(Binder::BoundBinaryOperation operation, const EvalValue* b) const final{
if (operation != Binder::BoundBinaryOperation::Concatenation){
throw EvaluationException("Binary operation not supported for strings.");
}
std::basic_ostringstream<char16_t> stringStream;
stringStream << _value;
stringStream << b->EvaluateString();
return new StringEvalValue(stringStream.str());
}
};
}

View File

@ -5,22 +5,23 @@
#include <map>
#include "EvalValue.hpp"
#include "../../Utilities/Random.hpp"
#include "../EvalValuePointer.hpp"
using namespace std;
namespace Porygon::Evaluation {
class TableEvalValue : public EvalValue {
const shared_ptr<map<Utilities::HashedString, shared_ptr<const EvalValue>>> _table;
const shared_ptr<map<Utilities::HashedString, EvalValuePointer>> _table;
const size_t _hash;
explicit TableEvalValue(shared_ptr<map<Utilities::HashedString, shared_ptr<const EvalValue>>> table, size_t hash)
explicit TableEvalValue(shared_ptr<map<Utilities::HashedString, EvalValuePointer>> table, size_t hash)
: _table(std::move(table)),
_hash(hash)
{
}
public:
explicit TableEvalValue(shared_ptr<map<Utilities::HashedString, shared_ptr<const EvalValue>>> table) :
explicit TableEvalValue(shared_ptr<map<Utilities::HashedString, EvalValuePointer>> table) :
_table(std::move(table)),
_hash(Utilities::Random::Get())
{
@ -42,41 +43,41 @@ namespace Porygon::Evaluation {
}
[[nodiscard]]
inline shared_ptr<const EvalValue> Clone() const final {
return shared_ptr<EvalValue>(new TableEvalValue(_table, _hash));
inline EvalValue* Clone() const final {
return new TableEvalValue(_table, _hash);
}
[[nodiscard]]
inline shared_ptr<const EvalValue> IndexValue(const EvalValue *val) const final {
inline EvalValue* IndexValue(const EvalValue *val) const final {
const auto stringKey = val->EvaluateString();
return this->_table->at(Utilities::HashedString::CreateLookup(stringKey));
return this->_table->at(Utilities::HashedString::CreateLookup(stringKey))->Clone();
}
[[nodiscard]]
inline shared_ptr<const EvalValue> IndexValue(uint32_t hash) const final {
return this->_table->at(Utilities::HashedString::CreateLookup(hash));
inline EvalValue* IndexValue(uint32_t hash) const final {
return this->_table->at(Utilities::HashedString::CreateLookup(hash))->Clone();
}
[[nodiscard]]
inline shared_ptr<const EvalValue> IndexValue(const char *val) const {
inline const EvalValue* IndexValue(const char *val) const {
auto hash = Utilities::HashedString::ConstHash(val);
return this->_table->at(Utilities::HashedString::CreateLookup(hash));
return this->_table->at(Utilities::HashedString::CreateLookup(hash)).Clone();
}
inline void SetIndexValue(const EvalValue *key, const shared_ptr<const EvalValue> &value) const final {
inline void SetIndexValue(const EvalValue *key, const EvalValue* value) const final {
auto hash = key->GetHashCode();
this->_table->at(Utilities::HashedString::CreateLookup(hash)) = value;
this->_table->at(Utilities::HashedString::CreateLookup(hash)).ClearAssign(value);
}
[[nodiscard]]
Iterator * GetKeyIterator() const final;
[[nodiscard]]
inline _Rb_tree_const_iterator<pair<const Utilities::HashedString, shared_ptr<const EvalValue>>> GetTableIterator() const{
inline _Rb_tree_const_iterator<pair<const Utilities::HashedString, EvalValuePointer>> GetTableIterator() const{
return _table->cbegin();
};
[[nodiscard]]
inline _Rb_tree_const_iterator<pair<const Utilities::HashedString, shared_ptr<const EvalValue>>> GetTableIteratorEnd() const{
inline _Rb_tree_const_iterator<pair<const Utilities::HashedString, EvalValuePointer>> GetTableIteratorEnd() const{
return _table->cend();
};
};

View File

@ -4,38 +4,39 @@
#include <memory>
namespace Porygon::Evaluation {
EvaluationScope::EvaluationScope(map<Utilities::HashedString, shared_ptr<const EvalValue>> *scriptVariables)
EvaluationScope::EvaluationScope(map<Utilities::HashedString, EvalValuePointer> *scriptVariables)
: _scriptScope(scriptVariables),
_localScope(map<uint64_t, shared_ptr<const EvalValue>>()) {
_localScope(map<uint64_t, EvalValuePointer>()) {
}
void EvaluationScope::CreateVariable(const BoundVariableKey *key, const shared_ptr<const EvalValue>& value) {
void EvaluationScope::CreateVariable(const BoundVariableKey *key, EvalValuePointer value) {
if (key->GetScopeId() == 0) {
_scriptScope->at(*key->GetIdentifier()) = value;
_scriptScope->at(*key->GetIdentifier()).ClearAssign(value.Take());
} else {
auto insert = _localScope.insert({key->GetHash(), value});
auto val = value.Clone();
auto insert = _localScope.insert({key->GetHash(), val});
if (!insert.second) {
_localScope[key->GetHash()] = value;
_localScope[key->GetHash()].ClearAssign(value.Take());
}
}
}
void EvaluationScope::SetVariable(const BoundVariableKey *key, const shared_ptr<const EvalValue> &value) {
void EvaluationScope::SetVariable(const BoundVariableKey *key, EvalValuePointer value) {
if (key->GetScopeId() == 0) {
_scriptScope->at(*key->GetIdentifier()) = value;
_scriptScope->at(*key->GetIdentifier()).ClearAssign(value.Take());
} else {
_localScope[key->GetHash()] = value;
_localScope[key->GetHash()].ClearAssign(value.Take());
}
}
shared_ptr<const EvalValue> EvaluationScope::GetVariable(const BoundVariableKey *key) {
EvalValuePointer EvaluationScope::GetVariable(const BoundVariableKey *key) {
auto scopeId = key -> GetScopeId();
if (scopeId== 0) {
return _scriptScope->at(*key->GetIdentifier());
return _scriptScope->at(*key->GetIdentifier())->Clone();
} else if(scopeId == -2){
return StandardLibraries::StaticScope::GetVariable(*key->GetIdentifier());
return StandardLibraries::StaticScope::GetVariable(*key->GetIdentifier()).Clone();
} else {
return _localScope[key->GetHash()];
return _localScope[key->GetHash()]->Clone();
}
}
}

View File

@ -5,22 +5,26 @@
#include <map>
#include <vector>
#include "../EvalValues/EvalValue.hpp"
#include "../EvalValuePointer.hpp"
using namespace Porygon::Binder;
namespace Porygon::Evaluation {
class EvaluationScope {
map<Utilities::HashedString, shared_ptr<const EvalValue>> *_scriptScope;
map<uint64_t, shared_ptr<const EvalValue>> _localScope;
map<Utilities::HashedString, EvalValuePointer> *_scriptScope;
map<uint64_t, EvalValuePointer> _localScope;
public:
explicit EvaluationScope(map<Utilities::HashedString, shared_ptr<const EvalValue>> *scriptVariables);
explicit EvaluationScope(map<Utilities::HashedString, EvalValuePointer> *scriptVariables);
~EvaluationScope() = default;
~EvaluationScope(){
_localScope.clear();
};
void CreateVariable(const BoundVariableKey *key, const shared_ptr<const EvalValue>&value);
void CreateVariable(const BoundVariableKey *key, EvalValuePointer value);
void SetVariable(const BoundVariableKey *key, const shared_ptr<const EvalValue> &value);
void SetVariable(const BoundVariableKey *key, EvalValuePointer value);
shared_ptr<const EvalValue> GetVariable(const BoundVariableKey *key);
EvalValuePointer GetVariable(const BoundVariableKey *key);
};
}

View File

@ -15,15 +15,18 @@ using namespace std;
using namespace Porygon::Binder;
namespace Porygon::Evaluation {
shared_ptr<const EvalValue> Evaluator::Evaluate(const BoundScriptStatement *statement) {
const EvalValue* Evaluator::Evaluate(const BoundScriptStatement *statement) {
this->_evaluationScope = make_shared<EvaluationScope>(this->_scriptVariables);
auto statements = statement->GetStatements();
if (statements -> size() == 1 && statements->at(0)->GetKind() == BoundStatementKind::Expression){
auto expStatement = (BoundExpressionStatement*) statements -> at(0);
return this -> EvaluateExpression(expStatement -> GetExpression());
return this -> EvaluateExpression(expStatement -> GetExpression()).Clone();
}
EvaluateBlockStatement(statement);
return this->_returnValue;
if (this->_returnValue.Get() == nullptr){
return nullptr;
}
return this->_returnValue.Clone();
}
void Evaluator::EvaluateStatement(const BoundStatement *statement) {
@ -78,9 +81,9 @@ namespace Porygon::Evaluation {
auto value = this->EvaluateExpression(statement->GetExpression());
auto key = statement->GetKey();
if (key->IsCreation()) {
this->_evaluationScope->CreateVariable(key, value);
this->_evaluationScope->CreateVariable(key, value.Clone());
} else {
this->_evaluationScope->SetVariable(key, value);
this->_evaluationScope->SetVariable(key, value.Clone());
}
}
@ -90,7 +93,7 @@ namespace Porygon::Evaluation {
auto index = ((BoundIndexExpression *) indexExpression);
auto table = this->EvaluateExpression(index->GetIndexableExpression());
auto key = this->EvaluateExpression(index->GetIndexExpression());
table->SetIndexValue(key.get(), value);
table->SetIndexValue(key.Get(), value.Take());
}
void Evaluator::EvaluateFunctionDeclarationStatement(const BoundFunctionDeclarationStatement *statement) {
@ -100,13 +103,14 @@ namespace Porygon::Evaluation {
auto option = new Evaluation::EvaluationScriptFunctionOption(block, this->_evaluationScope);
if (key->IsCreation()) {
auto value = make_shared<GenericFunctionEvalValue>(type, Utilities::Random::Get());
value->RegisterOption(option);
auto p = new GenericFunctionEvalValue(type, Utilities::Random::Get());
p->RegisterOption(option);
auto value = EvalValuePointer(p);
this->_evaluationScope->CreateVariable(key, value);
} else {
auto var = dynamic_pointer_cast<const GenericFunctionEvalValue>(this -> _evaluationScope ->GetVariable(key));
auto var = (GenericFunctionEvalValue*)this -> _evaluationScope ->GetVariable(key).Get();
var->RegisterOption(option);
this->_evaluationScope->SetVariable(key, var);
//this->_evaluationScope->SetVariable(key, var);
}
}
@ -114,17 +118,17 @@ namespace Porygon::Evaluation {
auto expression = statement->GetExpression();
if (expression == nullptr) {
this->_hasReturned = true;
this -> _returnValue = nullptr;
this -> _returnValue.ClearAssign(nullptr);
return;
}
auto value = this->EvaluateExpression(expression);
auto value = this->EvaluateExpression(expression).Take();
this->_hasReturned = true;
this->_returnValue = value;
this->_returnValue.ClearAssign(value);
}
void Evaluator::EvaluateConditionalStatement(const BoundConditionalStatement *statement) {
auto condition = statement->GetCondition();
if (EvaluateBoolExpression(condition)->EvaluateBool()) {
if (EvaluateExpression(condition)->EvaluateBool()) {
this->EvaluateStatement(statement->GetBlock());
} else {
auto elseStatement = statement->GetElseStatement();
@ -135,12 +139,12 @@ namespace Porygon::Evaluation {
}
void Evaluator::EvaluateNumericalForStatement(const BoundNumericalForStatement *statement) {
long start = this->EvaluateIntegerExpression(statement -> GetStart()) -> EvaluateInteger();
long end = this->EvaluateIntegerExpression(statement -> GetEnd()) -> EvaluateInteger();
long start = this->EvaluateExpression(statement -> GetStart()) -> EvaluateInteger();
long end = this->EvaluateExpression(statement -> GetEnd()) -> EvaluateInteger();
long step = 1;
auto stepExp = statement -> GetStep();
if (stepExp != nullptr){
step = this -> EvaluateIntegerExpression(stepExp) -> EvaluateInteger();
step = this -> EvaluateExpression(stepExp) -> EvaluateInteger();
}
auto identifier = statement -> GetIdentifier();
this -> _evaluationScope -> CreateVariable(identifier, nullptr);
@ -148,7 +152,7 @@ namespace Porygon::Evaluation {
auto statements = *block -> GetStatements();
if (step >= 0){
for (long i = start; i <= end; i += step){
this -> _evaluationScope -> SetVariable(identifier, make_shared<IntegerEvalValue>(i));
this -> _evaluationScope -> SetVariable(identifier, new IntegerEvalValue(i));
for (auto s: statements) {
this->EvaluateStatement(s);
if (this->_hasReturned || this -> _hasBroken)
@ -159,7 +163,7 @@ namespace Porygon::Evaluation {
}
} else{
for (long i = start; i >= end; i += step){
this -> _evaluationScope -> SetVariable(identifier, make_shared<IntegerEvalValue>(i));
this -> _evaluationScope -> SetVariable(identifier, new IntegerEvalValue(i));
for (auto s: statements) {
this->EvaluateStatement(s);
if (this->_hasReturned || this -> _hasBroken)
@ -184,10 +188,10 @@ namespace Porygon::Evaluation {
auto block = (BoundBlockStatement*)statement -> GetBlock();
auto statements = *block -> GetStatements();
while (iterator->MoveNext()){
auto currentKey = iterator->GetCurrent();
auto currentKey = EvalValuePointer(iterator->GetCurrent());
this -> _evaluationScope -> SetVariable(keyVariable, currentKey);
if (valueVariable != nullptr){
auto currentValue = iteratorVal -> IndexValue(currentKey.get());
auto currentValue = EvalValuePointer(iteratorVal -> IndexValue(currentKey.Get()));
this -> _evaluationScope -> SetVariable(valueVariable, currentValue);
}
for (auto s: statements) {
@ -206,7 +210,7 @@ namespace Porygon::Evaluation {
auto condition = statement -> GetCondition();
auto block = (BoundBlockStatement*)statement -> GetBlock();
auto statements = *block -> GetStatements();
while (this->EvaluateBoolExpression(condition)->EvaluateBool()){
while (this->EvaluateExpression(condition)->EvaluateBool()){
for (auto s: statements) {
this->EvaluateStatement(s);
if (this->_hasReturned || this -> _hasBroken)
@ -222,161 +226,75 @@ namespace Porygon::Evaluation {
// Expressions //
/////////////////
shared_ptr<const EvalValue> Evaluator::EvaluateExpression(const BoundExpression *expression) {
auto type = expression->GetType();
switch (type->GetClass()) {
case TypeClass::Number:
return this->EvaluateIntegerExpression(expression);
case TypeClass::Bool:
return this->EvaluateBoolExpression(expression);
case TypeClass::String:
return this->EvaluateStringExpression(expression);
case TypeClass::Function:
return this->EvaluateFunctionExpression(expression);
case TypeClass::Nil:
return this->EvaluateNilExpression(expression);
case TypeClass::Table:
return this->EvaluateTableExpression(expression);
case TypeClass::UserData:
return this->EvaluateUserDataExpression(expression);
default:
throw;
}
}
EvalValuePointer Evaluator::EvaluateExpression(const BoundExpression *expression) {
switch (expression->GetKind()){
shared_ptr<const EvalValue> Evaluator::GetVariable(const BoundVariableExpression *expression) {
auto variable = this->_evaluationScope->GetVariable(expression->GetKey());
if (variable == nullptr) {
throw EvaluationException("Variable not found");
}
return variable->Clone();
}
shared_ptr<const NumericEvalValue> Evaluator::EvaluateIntegerExpression(const BoundExpression *expression) {
switch (expression->GetKind()) {
case BoundExpressionKind::Bad: throw;
case BoundExpressionKind::LiteralInteger:
return make_shared<IntegerEvalValue>(((BoundLiteralIntegerExpression *) expression)->GetValue());
return new IntegerEvalValue(((BoundLiteralIntegerExpression *) expression)->GetValue());
case BoundExpressionKind::LiteralFloat:
return make_shared<FloatEvalValue>(((BoundLiteralFloatExpression *) expression)->GetValue());
case BoundExpressionKind::Unary:
return this->EvaluateIntegerUnary((BoundUnaryExpression *) expression);
case BoundExpressionKind::Binary:
return this->EvaluateIntegerBinary((BoundBinaryExpression *) expression);
case BoundExpressionKind::Variable:
return dynamic_pointer_cast<const NumericEvalValue>(
this->GetVariable((BoundVariableExpression *) expression));
case BoundExpressionKind::FunctionCall:
return dynamic_pointer_cast<const NumericEvalValue>(this->EvaluateFunctionCallExpression(expression));
case BoundExpressionKind::Index:
return dynamic_pointer_cast<const NumericEvalValue>(this->EvaluateIndexExpression(expression));
case BoundExpressionKind::PeriodIndex:
return dynamic_pointer_cast<const NumericEvalValue>(this->EvaluatePeriodIndexExpression(expression));
default:
throw;
}
}
shared_ptr<const BooleanEvalValue> Evaluator::EvaluateBoolExpression(const BoundExpression *expression) {
switch (expression->GetKind()) {
case BoundExpressionKind::LiteralBool:
return make_shared<BooleanEvalValue>(((BoundLiteralBoolExpression *) expression)->GetValue());
case BoundExpressionKind::Unary:
return this->EvaluateBooleanUnary((BoundUnaryExpression *) expression);
case BoundExpressionKind::Binary:
return this->EvaluateBooleanBinary((BoundBinaryExpression *) expression);
case BoundExpressionKind::Variable:
return dynamic_pointer_cast<const BooleanEvalValue>(
this->GetVariable((BoundVariableExpression *) expression));
case BoundExpressionKind::FunctionCall:
return dynamic_pointer_cast<const BooleanEvalValue>(this->EvaluateFunctionCallExpression(expression));
case BoundExpressionKind::Index:
return dynamic_pointer_cast<const BooleanEvalValue>(this->EvaluateIndexExpression(expression));
case BoundExpressionKind::PeriodIndex:
return dynamic_pointer_cast<const BooleanEvalValue>(this->EvaluatePeriodIndexExpression(expression));
default:
throw;
}
}
shared_ptr<const StringEvalValue> Evaluator::EvaluateStringExpression(const BoundExpression *expression) {
switch (expression->GetKind()) {
return new FloatEvalValue(((BoundLiteralFloatExpression *) expression)->GetValue());
case BoundExpressionKind::LiteralString:
return make_shared<StringEvalValue>(*((BoundLiteralStringExpression *) expression)->GetValue());
return new StringEvalValue(*((BoundLiteralStringExpression *) expression)->GetValue());
case BoundExpressionKind::LiteralBool:
return new BooleanEvalValue(((BoundLiteralBoolExpression *) expression)->GetValue());
case BoundExpressionKind::Variable:
return this -> GetVariable((BoundVariableExpression*)expression);
case BoundExpressionKind::Unary:
return this->EvaluateUnary((BoundUnaryExpression *) expression);
case BoundExpressionKind::Binary:
return this->EvaluateStringBinary((BoundBinaryExpression *) expression);
case BoundExpressionKind::Variable:
return dynamic_pointer_cast<const StringEvalValue>(this->GetVariable((BoundVariableExpression *) expression));
return this->EvaluateBinary((BoundBinaryExpression *) expression);
case BoundExpressionKind::FunctionCall:
return dynamic_pointer_cast<const StringEvalValue>(this->EvaluateFunctionCallExpression(expression));
return this->EvaluateFunctionCallExpression(expression);
case BoundExpressionKind::Index:
return dynamic_pointer_cast<const StringEvalValue>(this->EvaluateIndexExpression(expression));
case BoundExpressionKind::PeriodIndex:
return dynamic_pointer_cast<const StringEvalValue>(this->EvaluatePeriodIndexExpression(expression));
default:
throw;
}
}
shared_ptr<const EvalValue> Evaluator::EvaluateFunctionExpression(const BoundExpression *expression) {
switch (expression->GetKind()) {
case BoundExpressionKind::Variable:
return this->GetVariable((BoundVariableExpression *) expression);
case BoundExpressionKind::Index:
return this->EvaluateIndexExpression(expression);
return this->EvaluateIndexExpression(expression).Take();
case BoundExpressionKind::PeriodIndex:
return this->EvaluatePeriodIndexExpression(expression);
default:
throw;
}
}
shared_ptr<const EvalValue> Evaluator::EvaluateNilExpression(const BoundExpression *expression) {
switch (expression->GetKind()) {
case BoundExpressionKind::FunctionCall:
return this->EvaluateFunctionCallExpression(expression);
default:
return nullptr;
}
}
shared_ptr<const EvalValue> Evaluator::EvaluateTableExpression(const BoundExpression *expression) {
switch (expression->GetKind()) {
case BoundExpressionKind::FunctionCall:
return this->EvaluateFunctionCallExpression(expression);
case BoundExpressionKind::Variable:
return this->GetVariable((BoundVariableExpression *) expression);
case BoundExpressionKind::Index:
return this->EvaluateIndexExpression(expression);
case BoundExpressionKind::NumericalTable:
return this->EvaluateNumericTableExpression(expression);
case BoundExpressionKind::Table:
return this->EvaluateComplexTableExpression(expression);
case BoundExpressionKind::PeriodIndex:
return this->EvaluatePeriodIndexExpression(expression);
default:
throw;
}
}
EvalValuePointer Evaluator::EvaluateBinary(const BoundBinaryExpression *expression){
auto leftValue = this -> EvaluateExpression(expression->GetLeft());
auto rightValue = this -> EvaluateExpression(expression->GetRight());
auto operation = expression->GetOperation();
if (operation == BoundBinaryOperation::Equality){
return new BooleanEvalValue(leftValue == rightValue);
} else if (operation == BoundBinaryOperation::Inequality){
return new BooleanEvalValue(leftValue != rightValue);
}
return leftValue->BinaryOperation(operation, rightValue.Get());
}
shared_ptr<const EvalValue> Evaluator::EvaluateFunctionCallExpression(const BoundExpression *expression) {
EvalValuePointer Evaluator::EvaluateUnary(const BoundUnaryExpression *expression) {
auto exp = expression->GetOperand();
auto val = EvaluateExpression(exp);
return val->UnaryOperation(expression->GetOperation());
}
EvalValuePointer Evaluator::GetVariable(const BoundVariableExpression *expression) {
auto variable = this->_evaluationScope->GetVariable(expression->GetKey());
if (variable.Get() == nullptr) {
throw EvaluationException("Variable not found");
}
return variable;
}
EvalValuePointer Evaluator::EvaluateFunctionCallExpression(const BoundExpression *expression) {
auto functionCall = (BoundFunctionCallExpression *) expression;
auto function = dynamic_pointer_cast<const GenericFunctionEvalValue>(
this->EvaluateExpression(functionCall->GetFunctionExpression()));
auto function = (GenericFunctionEvalValue*)this->EvaluateExpression(functionCall->GetFunctionExpression()).Clone();
auto boundParameters = functionCall->GetParameters();
auto parameters = vector<shared_ptr<const EvalValue>>(boundParameters->size());
auto parameters = vector<EvalValuePointer>(boundParameters->size());
for (size_t i = 0; i < boundParameters->size(); i++) {
parameters[i] = this->EvaluateExpression(boundParameters->at(i));
}
auto type = std::dynamic_pointer_cast<const GenericFunctionScriptType>(function->GetType());
auto func = dynamic_pointer_cast<const GenericFunctionEvalValue>(function);
auto func = function;
auto option = functionCall ->GetFunctionOption();
auto opt = func->GetOption(option->GetOptionId());
if (option -> IsScriptFunction()){
@ -390,28 +308,30 @@ namespace Porygon::Evaluation {
for (int i = 0; i < parameterTypes.size() && i < parameterKeys.size() && i < parameters.size(); i++) {
auto parameter = parameters[i];
auto key = parameterKeys.at(i);
this->_evaluationScope->CreateVariable(key.get(), parameter->Clone());
this->_evaluationScope->CreateVariable(key.get(), parameter.Clone());
}
this->EvaluateBlockStatement(scriptOption->GetInnerBlock().get());
this->_evaluationScope = originalScope;
this->_hasReturned = false;
auto r = this->_returnValue;
this->_returnValue = nullptr;
this->_returnValue.ClearAssign(nullptr);
delete function;
return r;
} else{
auto scriptOption = dynamic_pointer_cast<const UserData::UserDataFunction>(opt);
const EvalValue* arr[parameters.size()];
for (size_t i = 0; i < parameters.size(); i++){
arr[i] = parameters[i].get();
arr[i] = parameters[i].Get();
}
return shared_ptr<const EvalValue>(scriptOption -> Call(arr, parameters.size()));
delete function;
return scriptOption -> Call(arr, parameters.size());
}
}
shared_ptr<const EvalValue> Evaluator::EvaluateFunction(const GenericFunctionEvalValue *function,
const EvalValue* Evaluator::EvaluateFunction(const GenericFunctionEvalValue *function,
const vector<EvalValue *> &parameters) {
auto type = std::dynamic_pointer_cast<const GenericFunctionScriptType>(function->GetType());
auto type = function->GetType();
auto option = dynamic_cast<const ScriptFunctionOption*>(type->GetFirstOption());
auto parameterTypes = option->GetParameterTypes();
@ -429,42 +349,43 @@ namespace Porygon::Evaluation {
this->EvaluateBlockStatement(scriptOption->GetInnerBlock().get());
this->_evaluationScope = originalScope;
this->_hasReturned = false;
auto r = this->_returnValue;
this->_returnValue = nullptr;
auto r = this->_returnValue.Take();
delete function;
return r;
}
shared_ptr<const EvalValue> Evaluator::EvaluateIndexExpression(const BoundExpression *expression) {
EvalValuePointer Evaluator::EvaluateIndexExpression(const BoundExpression *expression) {
auto indexExpression = (BoundIndexExpression *) expression;
auto index = this->EvaluateExpression(indexExpression->GetIndexExpression());
auto indexable = this->EvaluateExpression(indexExpression->GetIndexableExpression());
return indexable->IndexValue(index.get());
return indexable->IndexValue(index.Get());
}
shared_ptr<const EvalValue> Evaluator::EvaluatePeriodIndexExpression(const BoundExpression *expression) {
EvalValuePointer Evaluator::EvaluatePeriodIndexExpression(const BoundExpression *expression) {
auto indexExpression = (BoundPeriodIndexExpression *) expression;
auto index = indexExpression->GetIndex()->GetHash();
auto indexable = this->EvaluateExpression(indexExpression->GetIndexableExpression());
return indexable->IndexValue(index)->Clone();
return indexable->IndexValue(index);
}
shared_ptr<const EvalValue> Evaluator::EvaluateNumericTableExpression(const BoundExpression *expression) {
EvalValuePointer Evaluator::EvaluateNumericTableExpression(const BoundExpression *expression) {
auto tableExpression = (BoundNumericalTableExpression *) expression;
auto valueExpressions = tableExpression->GetExpressions();
auto values = new vector<shared_ptr<const EvalValue>>(valueExpressions->size());
auto values = new vector<EvalValuePointer>(valueExpressions->size());
for (size_t i = 0; i < valueExpressions->size(); i++) {
auto val = this->EvaluateExpression(valueExpressions->at(i));
values->at(i) = val;
values->at(i) = val.Take();
}
auto valuesPointer = shared_ptr<vector<shared_ptr<const EvalValue>>>(values);
return make_shared<NumericalTableEvalValue>(valuesPointer);
auto valuesPointer = shared_ptr<vector<EvalValuePointer>>(values);
return new NumericalTableEvalValue(valuesPointer);
}
shared_ptr<const EvalValue> Evaluator::EvaluateComplexTableExpression(const BoundExpression *expression) {
EvalValuePointer Evaluator::EvaluateComplexTableExpression(const BoundExpression *expression) {
auto tableExpression = (BoundTableExpression *) expression;
auto type = dynamic_pointer_cast<const TableScriptType>(tableExpression->GetType());
const auto& baseType = tableExpression -> GetType();
auto type = dynamic_pointer_cast<const TableScriptType>(baseType);
auto declaredVars = type->GetValues();
auto variables = make_shared<map<Utilities::HashedString, shared_ptr<const EvalValue>>>();
auto variables = make_shared<map<Utilities::HashedString, EvalValuePointer>>();
for (const auto& i : *declaredVars) {
variables->insert({i.first, nullptr});
}
@ -473,17 +394,6 @@ namespace Porygon::Evaluation {
this->_evaluationScope = evaluator;
this->EvaluateBlockStatement(tableExpression->GetBlock());
this->_evaluationScope = currentEvaluator;
return make_shared<TableEvalValue>(variables);
}
shared_ptr<const EvalValue> Evaluator::EvaluateUserDataExpression(const BoundExpression *expression) {
switch (expression->GetKind()) {
case BoundExpressionKind::Variable:
return this->GetVariable((BoundVariableExpression *) expression);
case BoundExpressionKind::Index:
return this->EvaluateIndexExpression(expression);
default:
throw;
}
return new TableEvalValue(variables);
}
}

View File

@ -10,13 +10,14 @@
#include "EvalValues/StringEvalValue.hpp"
#include "EvalValues/ScriptFunctionEvalValue.hpp"
#include "EvaluationScope/EvaluationScope.hpp"
#include "EvalValuePointer.hpp"
using namespace std;
namespace Porygon::Evaluation{
class Evaluator {
shared_ptr<const EvalValue> _returnValue;
map<Utilities::HashedString, shared_ptr<const EvalValue>>* _scriptVariables;
EvalValuePointer _returnValue;
map<Utilities::HashedString, EvalValuePointer>* _scriptVariables;
bool _hasReturned;
bool _hasBroken;
@ -35,36 +36,25 @@ namespace Porygon::Evaluation{
void EvaluateGenericForStatement(const BoundGenericForStatement *statement);
void EvaluateWhileStatement(const BoundWhileStatement *statement);
shared_ptr<const EvalValue> EvaluateExpression(const BoundExpression *expression);
shared_ptr<const NumericEvalValue> EvaluateIntegerExpression(const BoundExpression *expression);
shared_ptr<const BooleanEvalValue> EvaluateBoolExpression(const BoundExpression *expression);
shared_ptr<const StringEvalValue> EvaluateStringExpression(const BoundExpression *expression);
shared_ptr<const EvalValue> EvaluateFunctionExpression(const BoundExpression *expression);
shared_ptr<const EvalValue> EvaluateNilExpression(const BoundExpression *expression);
shared_ptr<const EvalValue> EvaluateTableExpression(const BoundExpression *expression);
EvalValuePointer EvaluateExpression(const BoundExpression *expression);
EvalValuePointer EvaluateBinary(const BoundBinaryExpression *expression);
EvalValuePointer EvaluateUnary(const BoundUnaryExpression *expression);
shared_ptr<const NumericEvalValue> EvaluateIntegerBinary(const BoundBinaryExpression *expression);
shared_ptr<const BooleanEvalValue> EvaluateBooleanBinary(const BoundBinaryExpression *expression);
shared_ptr<const StringEvalValue> EvaluateStringBinary(const BoundBinaryExpression *expression);
EvalValuePointer EvaluateFunctionCallExpression(const BoundExpression *expression);
EvalValuePointer EvaluateIndexExpression(const BoundExpression *expression);
EvalValuePointer EvaluatePeriodIndexExpression(const BoundExpression *expression);
EvalValuePointer EvaluateNumericTableExpression(const BoundExpression *expression);
EvalValuePointer EvaluateComplexTableExpression(const BoundExpression *expression);
shared_ptr<const NumericEvalValue> EvaluateIntegerUnary(const BoundUnaryExpression *expression);
shared_ptr<const BooleanEvalValue> EvaluateBooleanUnary(const BoundUnaryExpression *expression);
shared_ptr<const EvalValue> EvaluateFunctionCallExpression(const BoundExpression *expression);
shared_ptr<const EvalValue> EvaluateIndexExpression(const BoundExpression *expression);
shared_ptr<const EvalValue> EvaluatePeriodIndexExpression(const BoundExpression *expression);
shared_ptr<const EvalValue> EvaluateNumericTableExpression(const BoundExpression *expression);
shared_ptr<const EvalValue> EvaluateUserDataExpression(const BoundExpression *expression);
shared_ptr<const EvalValue> EvaluateComplexTableExpression(const BoundExpression *expression);
shared_ptr<const EvalValue> GetVariable(const BoundVariableExpression *expression);
EvalValuePointer GetVariable(const BoundVariableExpression *expression);
public:
explicit Evaluator(map<Utilities::HashedString, shared_ptr<const EvalValue>>* scriptVariables)
explicit Evaluator(map<Utilities::HashedString, EvalValuePointer>* scriptVariables)
: _scriptVariables(scriptVariables), _hasReturned(false), _hasBroken(false), _returnValue(nullptr),
_evaluationScope(nullptr){
}
shared_ptr<const EvalValue> Evaluate(const BoundScriptStatement* statement);
shared_ptr<const EvalValue> EvaluateFunction(const GenericFunctionEvalValue *function,
const EvalValue* Evaluate(const BoundScriptStatement* statement);
const EvalValue* EvaluateFunction(const GenericFunctionEvalValue *function,
const vector<EvalValue *> &parameters);
};

View File

@ -10,7 +10,7 @@ using namespace std;
namespace Porygon::Evaluation{
class Iterator {
public:
virtual shared_ptr<EvalValue> GetCurrent() = 0;
virtual EvalValue* GetCurrent() = 0;
virtual bool MoveNext() = 0;
virtual void Reset() = 0;
virtual ~Iterator(){}

View File

@ -9,15 +9,15 @@
namespace Porygon::Evaluation{
class NumericalKeyIterator : public Iterator{
const shared_ptr<vector<shared_ptr<const EvalValue>>> _vec;
const shared_ptr<vector<EvalValuePointer>> _vec;
const size_t _size;
long _position = 0;
public:
explicit NumericalKeyIterator(const NumericalTableEvalValue* table)
: _vec(table->GetTable()), _size(_vec->size() + 1){}
inline shared_ptr<EvalValue> GetCurrent() final{
return make_shared<IntegerEvalValue>(_position);
inline EvalValue* GetCurrent() final{
return new IntegerEvalValue(_position);
}
inline bool MoveNext() final{

View File

@ -8,15 +8,15 @@
namespace Porygon::Evaluation{
class TableKeyIterator : public Iterator{
_Rb_tree_const_iterator<pair<const Utilities::HashedString, shared_ptr<const EvalValue>>> _iterator;
_Rb_tree_const_iterator<pair<const Utilities::HashedString, shared_ptr<const EvalValue>>> _end;
_Rb_tree_const_iterator<pair<const Utilities::HashedString, EvalValuePointer>> _iterator;
_Rb_tree_const_iterator<pair<const Utilities::HashedString, EvalValuePointer>> _end;
bool _hasStarted = false;
public:
explicit TableKeyIterator(const TableEvalValue* table)
: _iterator(table->GetTableIterator()), _end(table->GetTableIteratorEnd()){}
inline shared_ptr<EvalValue> GetCurrent() final{
return make_shared<StringEvalValue>(*_iterator->first.GetString());
inline EvalValue* GetCurrent() final{
return new StringEvalValue(*_iterator->first.GetString());
}
bool MoveNext() final{

View File

@ -1,36 +0,0 @@
#include "EvalValues/NumericEvalValue.hpp"
#include "Evaluator.hpp"
#include "EvaluationException.hpp"
#include "../Script.hpp"
namespace Porygon::Evaluation {
shared_ptr<const NumericEvalValue> Evaluator::EvaluateIntegerUnary(const BoundUnaryExpression *expression) {
switch (expression->GetOperation()) {
case BoundUnaryOperation::Negation: {
auto operandValue = EvaluateIntegerExpression(expression->GetOperand());
if (operandValue->IsFloat()) {
double f = operandValue->EvaluateFloat();
return make_shared<FloatEvalValue>(-f);
} else {
long l = operandValue->EvaluateInteger();
return make_shared<IntegerEvalValue>(-l);
}
}
default:
throw;
}
}
shared_ptr<const BooleanEvalValue> Evaluator::EvaluateBooleanUnary(const BoundUnaryExpression *expression) {
switch (expression->GetOperation()) {
case BoundUnaryOperation::LogicalNegation: {
auto val = EvaluateBoolExpression(expression->GetOperand());
bool b = val->EvaluateBool();
return make_shared<BooleanEvalValue>(!b);
}
default:
throw;
}
}
}

View File

@ -24,13 +24,13 @@ Porygon::Script *Porygon::Script::Create(const string &script) {
Porygon::Script::Script(const u16string& s)
: Diagnostics(make_shared<Diagnostics::DiagnosticsHolder>(s)),
_boundScript(nullptr),
_scriptVariables(new map<Utilities::HashedString, shared_ptr<const EvalValue>>())
_scriptVariables(new map<Utilities::HashedString, EvalValuePointer>())
{
_evaluator = new Evaluator(this -> _scriptVariables);
this -> Parse(s);
}
shared_ptr<const EvalValue> Porygon::Script::Evaluate() {
EvalValuePointer Porygon::Script::Evaluate() {
return _evaluator->Evaluate(_boundScript.get());
}
@ -62,8 +62,8 @@ void Porygon::Script::Parse(const u16string& script) {
delete parseResult;
}
const EvalValue *Porygon::Script::GetVariable(const u16string &key) {
return _scriptVariables -> at(HashedString::CreateLookup(key)).get();
const EvalValue* Porygon::Script::GetVariable(const u16string &key) {
return _scriptVariables -> at(HashedString::CreateLookup(key)).Clone();
}
bool Porygon::Script::HasVariable(const u16string &key) {
@ -80,7 +80,7 @@ bool Porygon::Script::HasFunction(const u16string &key) {
return f != _scriptVariables->end() && f.operator->()->second->GetTypeClass() == TypeClass ::Function;
}
shared_ptr<const EvalValue> Porygon::Script::CallFunction(const u16string &key, const vector<EvalValue *>& variables) {
const EvalValue* Porygon::Script::CallFunction(const u16string &key, const vector<EvalValue *>& variables) {
auto var = (GenericFunctionEvalValue*)GetVariable(key);
return this->_evaluator->EvaluateFunction(var, variables);
}
@ -98,7 +98,7 @@ Porygon::Script::Script(shared_ptr<BoundScriptStatement> boundScript,
shared_ptr<Porygon::Diagnostics::DiagnosticsHolder> diagnostics)
: _boundScript(std::move(boundScript)),
Diagnostics(std::move(diagnostics)),
_scriptVariables(new map<Utilities::HashedString, shared_ptr<const EvalValue>>())
_scriptVariables(new map<Utilities::HashedString, EvalValuePointer>())
{
_evaluator = new Evaluator(_scriptVariables);
}
@ -111,8 +111,7 @@ extern "C" {
const EvalValue* EvaluateScript(Porygon::Script* script){
auto result = script -> Evaluate();
auto resultPtr = result.get();
return resultPtr;
return result.Clone();
}
bool HasVariable(Porygon::Script* script, const char16_t* key){
@ -129,6 +128,6 @@ extern "C" {
const EvalValue* CallFunction(Porygon::Script* script, const char16_t* key, EvalValue* parameters[], int parameterCount){
std::vector<EvalValue*> v(parameters, parameters + parameterCount);
return script->CallFunction(key, v).get();
return script->CallFunction(key, v);
}
}

View File

@ -17,7 +17,7 @@ using namespace Porygon::Evaluation;
namespace Porygon{
class Script {
Evaluator* _evaluator;
map<Utilities::HashedString, shared_ptr<const EvalValue>>* _scriptVariables;
map<Utilities::HashedString, EvalValuePointer>* _scriptVariables;
shared_ptr<Binder::BoundScriptStatement> _boundScript;
shared_ptr<const ScriptType> _returnType;
@ -41,14 +41,12 @@ namespace Porygon{
_returnType = t;
}
shared_ptr<const EvalValue> Evaluate();
//const EvalValue* GetLastValue();
EvalValuePointer Evaluate();
const EvalValue* GetVariable(const u16string& key);
bool HasVariable(const u16string& key);
shared_ptr<const EvalValue> CallFunction(const u16string& key, const vector<EvalValue*>& variables);
const EvalValue* CallFunction(const u16string& key, const vector<EvalValue*>& variables);
bool HasFunction(const u16string& key);
};

View File

@ -74,10 +74,10 @@ namespace Porygon::StandardLibraries{
}
static shared_ptr<Evaluation::EvalValue> GetFuncEvalValue(
static Evaluation::EvalValue* GetFuncEvalValue(
const Evaluation::EvalValue* (*func)(void* obj, const Evaluation::EvalValue* parameters[], int parameterCount),
const shared_ptr<GenericFunctionScriptType>& type, size_t optionLength){
auto f = make_shared<Evaluation::GenericFunctionEvalValue>(type, rand());
auto f = new Evaluation::GenericFunctionEvalValue(type, rand());
for (size_t i = 0; i < optionLength; i++){
auto funcOption = new UserData::UserDataFunction(func, nullptr);
f->RegisterOption(funcOption);
@ -88,7 +88,7 @@ namespace Porygon::StandardLibraries{
public:
static void RegisterVariables(std::map<Utilities::HashedString, Binder::BoundVariable *>* bound,
std::map<Utilities::HashedString, shared_ptr<Evaluation::EvalValue>>* values){
std::map<Utilities::HashedString, Evaluation::EvalValue*>* values){
// Register error function
auto errorFuncType = BasicLibrary::GetErrorFuncType();
auto errorLookup = Utilities::HashedString::CreateLookup(u"error");

View File

@ -19,7 +19,7 @@ namespace Porygon::StandardLibraries{
class InternalScope{
public:
map<Utilities::HashedString, Binder::BoundVariable *> _boundVariables;
map<Utilities::HashedString, shared_ptr<Evaluation::EvalValue>> _variables;
map<Utilities::HashedString, Evaluation::EvalValue*> _variables;
InternalScope(){
BasicLibrary::RegisterVariables(&_boundVariables, &_variables);
@ -29,6 +29,9 @@ namespace Porygon::StandardLibraries{
for (const auto& b: _boundVariables){
delete b.second;
}
for (const auto& v: _variables){
delete v.second;
}
}
};
@ -36,7 +39,7 @@ namespace Porygon::StandardLibraries{
public:
static void RegisterVariable(const Utilities::HashedString& identifier, shared_ptr<ScriptType> type, Evaluation::EvalValue* value){
_internal._boundVariables.insert({identifier, new Binder::BoundVariable(std::move(type))});
_internal._variables.insert({identifier, shared_ptr<Evaluation::EvalValue>(value)});
_internal._variables.insert({identifier, value});
}
static Binder::BoundVariable* GetBoundVariable(const Utilities::HashedString &identifier){
@ -47,8 +50,8 @@ namespace Porygon::StandardLibraries{
return nullptr;
}
inline static shared_ptr<Evaluation::EvalValue> GetVariable(const Utilities::HashedString &identifier){
return _internal._variables[identifier];
inline static Evaluation::EvalValuePointer GetVariable(const Utilities::HashedString &identifier){
return _internal._variables[identifier]->Clone();
}
};
}

View File

@ -34,8 +34,8 @@ namespace Porygon::UserData {
}
[[nodiscard]]
inline shared_ptr<const EvalValue> Clone() const final {
return make_shared<UserDataValue>(_userData, _obj);
inline Evaluation::EvalValue* Clone() const final {
return new UserDataValue(_userData, _obj);
}
[[nodiscard]]
@ -43,22 +43,23 @@ namespace Porygon::UserData {
return reinterpret_cast<intptr_t>(_obj);
}
shared_ptr<const EvalValue> IndexValue(const EvalValue *val) const final {
const Evaluation::EvalValue* IndexValue(const EvalValue *val) const final {
auto fieldId = val->GetHashCode();
auto field = _userData->GetField(fieldId);
return shared_ptr<const EvalValue>(field->Get(_obj));
return field->Get(_obj);
}
[[nodiscard]]
inline shared_ptr<const EvalValue> IndexValue(uint32_t hash) const final {
inline const EvalValue* IndexValue(uint32_t hash) const final {
auto field = _userData->GetField(hash);
return shared_ptr<const EvalValue>(field->Get(_obj));
return field->Get(_obj);
}
void SetIndexValue(const EvalValue *key, const shared_ptr<const EvalValue> &value) const final {
void SetIndexValue(const EvalValue *key, const EvalValue* value) const final {
auto fieldId = key->GetHashCode();
auto field = _userData->GetField(fieldId);
field->Set(_obj, value.get());
field->Set(_obj, value);
delete value;
}
inline void* GetObjectPointer(){

View File

@ -14,6 +14,7 @@ TEST_CASE( "Basic conditional", "[integration]" ) {
REQUIRE(variable != nullptr);
REQUIRE(variable->EvaluateBool());
delete script;
delete variable;
}
TEST_CASE( "If then, else", "[integration]" ) {
@ -26,6 +27,7 @@ TEST_CASE( "If then, else", "[integration]" ) {
REQUIRE(variable != nullptr);
REQUIRE(variable->EvaluateBool());
delete script;
delete variable;
}
TEST_CASE( "If then, else if", "[integration]" ) {
@ -38,6 +40,7 @@ TEST_CASE( "If then, else if", "[integration]" ) {
REQUIRE(variable != nullptr);
REQUIRE(variable->EvaluateBool());
delete script;
delete variable;
}

View File

@ -12,6 +12,7 @@ TEST_CASE( "Define script function", "[integration]" ) {
REQUIRE(variable != nullptr);
REQUIRE(variable->GetTypeClass() == TypeClass::Function);
delete script;
delete variable;
}
TEST_CASE( "Define script function and call", "[integration]" ) {
@ -25,6 +26,8 @@ TEST_CASE( "Define script function and call", "[integration]" ) {
REQUIRE(result->GetTypeClass() == TypeClass::Number);
REQUIRE(result->EvaluateInteger() == 3);
delete script;
delete variable;
delete result;
}
TEST_CASE( "Define script function and call multiple times", "[integration]" ) {
@ -38,6 +41,8 @@ TEST_CASE( "Define script function and call multiple times", "[integration]" ) {
REQUIRE(result->GetTypeClass() == TypeClass::Number);
REQUIRE(result->EvaluateInteger() == 5);
delete script;
delete variable;
delete result;
}
TEST_CASE( "Define script function and call from extern", "[integration]" ) {
@ -57,6 +62,7 @@ TEST_CASE( "Define script function and call from extern", "[integration]" ) {
REQUIRE(result->GetTypeClass() == TypeClass::Number);
REQUIRE(result->EvaluateInteger() == 11);
delete script;
delete result;
}
TEST_CASE( "Define script function and return", "[integration]" ) {
@ -84,6 +90,8 @@ TEST_CASE( "Define script function and return", "[integration]" ) {
REQUIRE(variable->EvaluateInteger() == 0);
delete script;
delete variable;
delete result;
}
TEST_CASE( "Functions can call themselves", "[integration]" ) {
@ -106,6 +114,7 @@ end
REQUIRE(variable->EvaluateInteger() == 5);
delete script;
delete variable;
}
TEST_CASE( "Functions respect scope", "[integration]" ) {
@ -134,6 +143,7 @@ test()
REQUIRE(variable->EvaluateInteger() == 50);
delete script;
delete variable;
}
TEST_CASE( "Return doesn't parse next line expression", "[integration]" ) {
@ -174,8 +184,9 @@ stringResult = add('foo', 'bar')
REQUIRE(stringVar != nullptr);
CHECK(stringVar->EvaluateString() == u"foobar");
delete script;
delete intVar;
delete stringVar;
}

View File

@ -15,6 +15,7 @@ end
auto var = script->GetVariable(u"result");
REQUIRE(var->EvaluateInteger() == 33);
delete script;
delete var;
}
TEST_CASE( "Numerical for loop with step", "[integration]" ) {
@ -29,6 +30,7 @@ end
auto var = script->GetVariable(u"result");
REQUIRE(var->EvaluateInteger() == 12);
delete script;
delete var;
}
TEST_CASE( "Numerical for loop with negative step", "[integration]" ) {
@ -43,6 +45,7 @@ end
auto var = script->GetVariable(u"result");
REQUIRE(var->EvaluateInteger() == 33);
delete script;
delete var;
}
@ -58,6 +61,7 @@ end
auto var = script->GetVariable(u"result");
REQUIRE(var->EvaluateInteger() == 15);
delete script;
delete var;
}
TEST_CASE( "Numerical for loop, break", "[integration]" ) {
@ -73,6 +77,7 @@ end
auto var = script->GetVariable(u"result");
REQUIRE(var->EvaluateInteger() == 6);
delete script;
delete var;
}
@ -89,6 +94,7 @@ end
auto var = script->GetVariable(u"result");
REQUIRE(var->EvaluateInteger() == 15);
delete script;
delete var;
}
TEST_CASE( "Generic for loop over simple numerical table, get values", "[integration]" ) {
@ -104,6 +110,7 @@ end
auto var = script->GetVariable(u"result");
REQUIRE(var->EvaluateInteger() == 25);
delete script;
delete var;
}
TEST_CASE( "Generic for loop over simple numerical table, break", "[integration]" ) {
@ -120,6 +127,7 @@ end
auto var = script->GetVariable(u"result");
REQUIRE(var->EvaluateInteger() == 9);
delete script;
delete var;
}
TEST_CASE( "While loop", "[integration]" ) {
@ -134,6 +142,7 @@ end
auto var = script->GetVariable(u"result");
REQUIRE(var->EvaluateInteger() == 5);
delete script;
delete var;
}
TEST_CASE( "While loop break", "[integration]" ) {
@ -149,6 +158,7 @@ end
auto var = script->GetVariable(u"result");
REQUIRE(var->EvaluateInteger() == 5);
delete script;
delete var;
}
#endif

View File

@ -11,6 +11,7 @@ TEST_CASE( "Create empty table", "[integration]" ) {
auto variable = script->GetVariable(u"table");
REQUIRE(variable != nullptr);
delete script;
delete variable;
}
TEST_CASE( "Create simple integer table", "[integration]" ) {
@ -20,6 +21,7 @@ TEST_CASE( "Create simple integer table", "[integration]" ) {
auto variable = script->GetVariable(u"table");
REQUIRE(variable != nullptr);
delete script;
delete variable;
}
TEST_CASE( "Create simple string table", "[integration]" ) {
@ -29,6 +31,7 @@ TEST_CASE( "Create simple string table", "[integration]" ) {
auto variable = script->GetVariable(u"table");
REQUIRE(variable != nullptr);
delete script;
delete variable;
}
TEST_CASE( "Index string table", "[integration]" ) {
@ -39,7 +42,7 @@ return table[3]
)");
REQUIRE(!script->Diagnostics -> HasErrors());
auto variable = script->Evaluate();
REQUIRE(variable != nullptr);
REQUIRE(variable.Get() != nullptr);
REQUIRE(variable->EvaluateString() == u"foo");
delete script;
}
@ -57,9 +60,14 @@ table = {
auto variable = script->GetVariable(u"table");
REQUIRE(variable != nullptr);
auto table = (TableEvalValue*)variable;
CHECK(table->IndexValue("foo")->EvaluateString() == u"test");
CHECK(table->IndexValue("bar")->EvaluateInteger() == 100);
auto res = table->IndexValue("foo");
auto res2 = table->IndexValue("bar");
CHECK(res->EvaluateString() == u"test");
CHECK(res2->EvaluateInteger() == 100);
delete script;
delete table;
delete res;
delete res2;
}
TEST_CASE( "Complex table with function", "[integration]" ) {
@ -75,7 +83,7 @@ return table["getFoo"]()
)");
REQUIRE(!script->Diagnostics -> HasErrors());
auto variable = script->Evaluate();
REQUIRE(variable != nullptr);
REQUIRE(variable.Get() != nullptr);
delete script;
}

View File

@ -54,6 +54,7 @@ end
delete par;
delete parameter;
delete script;
delete variable;
UserDataStorage::ClearTypes();
}
@ -92,6 +93,7 @@ end
delete script;
delete obj;
delete parameter;
delete result;
UserDataStorage::ClearTypes();
}
@ -111,6 +113,7 @@ end
delete script;
delete obj;
delete parameter;
delete result;
UserDataStorage::ClearTypes();
}

View File

@ -13,6 +13,7 @@ TEST_CASE( "Create script variable", "[integration]" ) {
REQUIRE(variable != nullptr);
REQUIRE(variable->EvaluateBool());
delete script;
delete variable;
}
TEST_CASE( "Create local variable", "[integration]" ) {
@ -32,6 +33,7 @@ TEST_CASE( "Create script variable and use", "[integration]" ) {
REQUIRE(variable != nullptr);
CHECK(variable->EvaluateBool());
delete script;
delete variable;
}
TEST_CASE( "Create local variable and use", "[integration]" ) {
@ -43,6 +45,7 @@ TEST_CASE( "Create local variable and use", "[integration]" ) {
REQUIRE(variable != nullptr);
CHECK(variable->EvaluateBool());
delete script;
delete variable;
}
TEST_CASE( "Local variables in upmost scope persist", "[integration]" ) {
@ -62,6 +65,7 @@ end
REQUIRE(variable != nullptr);
CHECK(variable->EvaluateInteger() == 2);
delete script;
delete variable;
}
TEST_CASE( "Able to use emoji", "[integration]" ) {
@ -75,6 +79,7 @@ TEST_CASE( "Able to use emoji", "[integration]" ) {
REQUIRE(variable != nullptr);
CHECK(variable->EvaluateString() == u"LJ");
delete script;
delete variable;
}
#endif