From bd343c1b7eec68b9e76a86fb5bd6022cd4282a78 Mon Sep 17 00:00:00 2001 From: Deukhoofd Date: Thu, 12 Sep 2019 15:21:10 +0200 Subject: [PATCH] Allows userdata binary operations to be set externally --- .../BoundExpressions/BoundExpression.hpp | 2 +- src/Binder/BoundOperators.hpp | 29 +++++----- src/Exception.hpp | 20 +++++++ src/Parser/BinaryOperatorKind.hpp | 6 +-- src/UserData/UserData.cpp | 5 ++ src/UserData/UserData.hpp | 54 ++++++++++--------- src/UserData/UserDataOperation.cpp | 10 ++++ src/UserData/UserDataOperation.hpp | 11 ++-- 8 files changed, 86 insertions(+), 51 deletions(-) create mode 100644 src/Exception.hpp diff --git a/src/Binder/BoundExpressions/BoundExpression.hpp b/src/Binder/BoundExpressions/BoundExpression.hpp index de816a5..48c495e 100644 --- a/src/Binder/BoundExpressions/BoundExpression.hpp +++ b/src/Binder/BoundExpressions/BoundExpression.hpp @@ -312,7 +312,7 @@ namespace Porygon::Binder { const BoundExpression* _right; const UserData::UserDataBinaryOperation* _operation; public: - BoundUserdataBinaryExpression(BoundExpression *left, BoundExpression *right, UserData::UserDataBinaryOperation* op, + BoundUserdataBinaryExpression(BoundExpression *left, BoundExpression *right, const UserData::UserDataBinaryOperation* op, shared_ptr result, unsigned int start, unsigned int length) : BoundExpression(start, length, std::move(result)), diff --git a/src/Binder/BoundOperators.hpp b/src/Binder/BoundOperators.hpp index d8251c2..40389bb 100644 --- a/src/Binder/BoundOperators.hpp +++ b/src/Binder/BoundOperators.hpp @@ -3,21 +3,22 @@ #define PORYGONLANG_BOUNDOPERATORS_HPP namespace Porygon::Binder { - enum class BoundBinaryOperation { - Addition, - Subtraction, - Multiplication, - Division, - Equality, - Inequality, - LessThan, - LessThanEquals, - GreaterThan, - GreaterThanEquals, + enum class BoundBinaryOperation : char + { + Addition = 0, + Subtraction = 1, + Multiplication = 2, + Division = 3, + Equality = 4, + Inequality = 5, + LessThan = 6, + LessThanEquals = 7, + GreaterThan = 8, + GreaterThanEquals = 9, - LogicalAnd, - LogicalOr, - Concatenation + LogicalAnd = 10, + LogicalOr = 11, + Concatenation = 12 }; enum class BoundUnaryOperation { diff --git a/src/Exception.hpp b/src/Exception.hpp new file mode 100644 index 0000000..dd1665d --- /dev/null +++ b/src/Exception.hpp @@ -0,0 +1,20 @@ +#ifndef PORYGONLANG_EXCEPTION_HPP +#define PORYGONLANG_EXCEPTION_HPP + + +#include +#include + +class Exception : public std::exception{ + const std::string _err; +public: + explicit Exception(const char* err) :_err(std::string(err)){ } + + [[nodiscard]] const char *what() const noexcept final { + return _err.c_str(); + } + +}; + + +#endif //PORYGONLANG_EXCEPTION_HPP diff --git a/src/Parser/BinaryOperatorKind.hpp b/src/Parser/BinaryOperatorKind.hpp index 7a1ba5b..82469e6 100644 --- a/src/Parser/BinaryOperatorKind.hpp +++ b/src/Parser/BinaryOperatorKind.hpp @@ -5,13 +5,13 @@ namespace Porygon::Parser { enum class BinaryOperatorKind { // Math - Addition, + Addition, Subtraction, Multiplication, Division, // Equality - Equality, + Equality, Inequality, Less, LessOrEquals, @@ -19,7 +19,7 @@ namespace Porygon::Parser { GreaterOrEquals, // Logical - LogicalAnd, + LogicalAnd, LogicalOr, }; } diff --git a/src/UserData/UserData.cpp b/src/UserData/UserData.cpp index 11ee37d..ef18121 100644 --- a/src/UserData/UserData.cpp +++ b/src/UserData/UserData.cpp @@ -29,5 +29,10 @@ namespace Porygon::UserData { auto ud = UserDataStorage::GetUserDataType(typeId); ud->Get()->SetCastFunc(cast); } + + void AddUserdataBinaryOperation(uint32_t typeId, char kind, const UserDataBinaryOperation* operation){ + auto ud = UserDataStorage::GetUserDataType(typeId); + ud->Get()->AddBinaryOperation(static_cast(kind), operation); + } } } \ No newline at end of file diff --git a/src/UserData/UserData.hpp b/src/UserData/UserData.hpp index e566f86..d4872d5 100644 --- a/src/UserData/UserData.hpp +++ b/src/UserData/UserData.hpp @@ -7,6 +7,7 @@ #include "UserDataField.hpp" #include "UserDataOperation.hpp" #include "../Parser/BinaryOperatorKind.hpp" +#include "../Exception.hpp" namespace Porygon::UserData { class UserData { @@ -15,16 +16,16 @@ namespace Porygon::UserData { std::mutex _mutex; // Binary operations - std::vector _addition = {}; - std::vector _subtraction = {}; - std::vector _multiplication = {}; - std::vector _division = {}; - std::vector _equality = {}; - std::vector _inequality = {}; - std::vector _lessThan = {}; - std::vector _lessThanEquals = {}; - std::vector _greaterThan = {}; - std::vector _greaterThanEquals = {}; + std::vector _addition = {}; + std::vector _subtraction = {}; + std::vector _multiplication = {}; + std::vector _division = {}; + std::vector _equality = {}; + std::vector _inequality = {}; + std::vector _lessThan = {}; + std::vector _lessThanEquals = {}; + std::vector _greaterThan = {}; + std::vector _greaterThanEquals = {}; bool (*_isCastable)(const ScriptType* type, bool explicitCast); Evaluation::EvalValue* (*_cast)(void* obj, const ScriptType* castType); @@ -95,25 +96,28 @@ namespace Porygon::UserData { return _cast(obj, castType); } - void AddBinaryOperation(Binder::BoundBinaryOperation kind, UserDataBinaryOperation* op){ + void AddBinaryOperation(Binder::BoundBinaryOperation kind, const UserDataBinaryOperation* op){ switch (kind){ - - case Binder::BoundBinaryOperation::Addition: _addition.push_back(op); - case Binder::BoundBinaryOperation::Subtraction: _subtraction.push_back(op); - case Binder::BoundBinaryOperation::Multiplication: _multiplication.push_back(op); - case Binder::BoundBinaryOperation::Division: _division.push_back(op); - case Binder::BoundBinaryOperation::Equality: _equality.push_back(op); - case Binder::BoundBinaryOperation::Inequality: _inequality.push_back(op); - case Binder::BoundBinaryOperation::LessThan: _lessThan.push_back(op); - case Binder::BoundBinaryOperation::LessThanEquals: _lessThanEquals.push_back(op); - case Binder::BoundBinaryOperation::GreaterThan: _greaterThan.push_back(op); - case Binder::BoundBinaryOperation::GreaterThanEquals: _greaterThanEquals.push_back(op); - default: throw exception(); + case Binder::BoundBinaryOperation::Addition: return _addition.push_back(op); + case Binder::BoundBinaryOperation::Subtraction: return _subtraction.push_back(op); + case Binder::BoundBinaryOperation::Multiplication: return _multiplication.push_back(op); + case Binder::BoundBinaryOperation::Division: return _division.push_back(op); + case Binder::BoundBinaryOperation::Equality: return _equality.push_back(op); + case Binder::BoundBinaryOperation::Inequality: return _inequality.push_back(op); + case Binder::BoundBinaryOperation::LessThan: return _lessThan.push_back(op); + case Binder::BoundBinaryOperation::LessThanEquals: return _lessThanEquals.push_back(op); + case Binder::BoundBinaryOperation::GreaterThan: return _greaterThan.push_back(op); + case Binder::BoundBinaryOperation::GreaterThanEquals: return _greaterThanEquals.push_back(op); + default: + stringstream err; + err << "Unknown binary operation kind: " << static_cast(kind); + throw Exception(err.str().c_str()); } } private: - static UserDataBinaryOperation* ResolveBinaryOperation(const vector& v, const shared_ptr& b){ + static const UserDataBinaryOperation* ResolveBinaryOperation(const vector& v, + const shared_ptr& b){ for (auto o: v){ if (o->IsValid(b)){ return o; @@ -124,7 +128,7 @@ namespace Porygon::UserData { public: [[nodiscard]] - UserDataBinaryOperation* GetBinaryOperation(Parser::BinaryOperatorKind op, const shared_ptr& b){ + const UserDataBinaryOperation* GetBinaryOperation(Parser::BinaryOperatorKind op, const shared_ptr& b){ switch (op){ case Parser::BinaryOperatorKind::Addition: return ResolveBinaryOperation(_addition, b); diff --git a/src/UserData/UserDataOperation.cpp b/src/UserData/UserDataOperation.cpp index 7957446..ce79792 100644 --- a/src/UserData/UserDataOperation.cpp +++ b/src/UserData/UserDataOperation.cpp @@ -1 +1,11 @@ #include "UserDataOperation.hpp" + +namespace Porygon::UserData{ + extern "C" { + UserDataBinaryOperation* CreateUserdataBinaryOperation(Evaluation::EvalValue *(*func)(void *, const Evaluation::EvalValue *), + ScriptType* secondParameter, ScriptType* returnType){ + return new UserDataBinaryOperation(func, shared_ptr(secondParameter), + shared_ptr(returnType)); + } + } +} diff --git a/src/UserData/UserDataOperation.hpp b/src/UserData/UserDataOperation.hpp index 7f0c5c0..b59f4a3 100644 --- a/src/UserData/UserDataOperation.hpp +++ b/src/UserData/UserDataOperation.hpp @@ -12,8 +12,8 @@ namespace Porygon::UserData { const shared_ptr _returnType; public: UserDataBinaryOperation(Evaluation::EvalValue *(*func)(void *, const Evaluation::EvalValue *), - shared_ptr secondParameter, - shared_ptr returnType) + shared_ptr secondParameter, + shared_ptr returnType) : _func(func), _secondParameter(std::move(secondParameter)), _returnType(std::move(returnType)) {} @@ -21,18 +21,13 @@ namespace Porygon::UserData { return _func(a, b); } - bool IsValid(const shared_ptr& v){ + [[nodiscard]] bool IsValid(const shared_ptr& v) const{ if (v->operator==(_secondParameter)){ return true; } return v->CastableTo(_secondParameter, true) != CastResult::InvalidCast; } - [[nodiscard]] - inline shared_ptr GetSecondParameterType() const{ - return _secondParameter; - } - [[nodiscard]] inline shared_ptr GetReturnType() const{ return _returnType;