Rework of memory handling in Evaluation
continuous-integration/drone/push Build is failing
Details
continuous-integration/drone/push Build is failing
Details
This commit is contained in:
parent
268f6b59fb
commit
ccc6e297f2
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
#include "EvalValuePointer.hpp"
|
|
@ -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
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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]]
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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())
|
||||
{
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
};
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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 *> ¶meters) {
|
||||
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);
|
||||
}
|
||||
}
|
|
@ -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 *> ¶meters);
|
||||
|
||||
};
|
||||
|
|
|
@ -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(){}
|
||||
|
|
|
@ -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{
|
||||
|
|
|
@ -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{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
};
|
||||
|
||||
|
|
|
@ -74,10 +74,10 @@ namespace Porygon::StandardLibraries{
|
|||
}
|
||||
|
||||
|
||||
static shared_ptr<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());
|
||||
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 = 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");
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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(){
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue