Allows userdata binary operations to be set externally
continuous-integration/drone/push Build is passing Details

This commit is contained in:
Deukhoofd 2019-09-12 15:21:10 +02:00
parent b94c811e94
commit bd343c1b7e
Signed by: Deukhoofd
GPG Key ID: ADF2E9256009EDCE
8 changed files with 86 additions and 51 deletions

View File

@ -312,7 +312,7 @@ namespace Porygon::Binder {
const BoundExpression* _right; const BoundExpression* _right;
const UserData::UserDataBinaryOperation* _operation; const UserData::UserDataBinaryOperation* _operation;
public: public:
BoundUserdataBinaryExpression(BoundExpression *left, BoundExpression *right, UserData::UserDataBinaryOperation* op, BoundUserdataBinaryExpression(BoundExpression *left, BoundExpression *right, const UserData::UserDataBinaryOperation* op,
shared_ptr<const ScriptType> result, shared_ptr<const ScriptType> result,
unsigned int start, unsigned int length) unsigned int start, unsigned int length)
: BoundExpression(start, length, std::move(result)), : BoundExpression(start, length, std::move(result)),

View File

@ -3,21 +3,22 @@
#define PORYGONLANG_BOUNDOPERATORS_HPP #define PORYGONLANG_BOUNDOPERATORS_HPP
namespace Porygon::Binder { namespace Porygon::Binder {
enum class BoundBinaryOperation { enum class BoundBinaryOperation : char
Addition, {
Subtraction, Addition = 0,
Multiplication, Subtraction = 1,
Division, Multiplication = 2,
Equality, Division = 3,
Inequality, Equality = 4,
LessThan, Inequality = 5,
LessThanEquals, LessThan = 6,
GreaterThan, LessThanEquals = 7,
GreaterThanEquals, GreaterThan = 8,
GreaterThanEquals = 9,
LogicalAnd, LogicalAnd = 10,
LogicalOr, LogicalOr = 11,
Concatenation Concatenation = 12
}; };
enum class BoundUnaryOperation { enum class BoundUnaryOperation {

20
src/Exception.hpp Normal file
View File

@ -0,0 +1,20 @@
#ifndef PORYGONLANG_EXCEPTION_HPP
#define PORYGONLANG_EXCEPTION_HPP
#include <exception>
#include <utility>
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

View File

@ -5,13 +5,13 @@
namespace Porygon::Parser { namespace Porygon::Parser {
enum class BinaryOperatorKind { enum class BinaryOperatorKind {
// Math // Math
Addition, Addition,
Subtraction, Subtraction,
Multiplication, Multiplication,
Division, Division,
// Equality // Equality
Equality, Equality,
Inequality, Inequality,
Less, Less,
LessOrEquals, LessOrEquals,
@ -19,7 +19,7 @@ namespace Porygon::Parser {
GreaterOrEquals, GreaterOrEquals,
// Logical // Logical
LogicalAnd, LogicalAnd,
LogicalOr, LogicalOr,
}; };
} }

View File

@ -29,5 +29,10 @@ namespace Porygon::UserData {
auto ud = UserDataStorage::GetUserDataType(typeId); auto ud = UserDataStorage::GetUserDataType(typeId);
ud->Get()->SetCastFunc(cast); ud->Get()->SetCastFunc(cast);
} }
void AddUserdataBinaryOperation(uint32_t typeId, char kind, const UserDataBinaryOperation* operation){
auto ud = UserDataStorage::GetUserDataType(typeId);
ud->Get()->AddBinaryOperation(static_cast<Binder::BoundBinaryOperation >(kind), operation);
}
} }
} }

View File

@ -7,6 +7,7 @@
#include "UserDataField.hpp" #include "UserDataField.hpp"
#include "UserDataOperation.hpp" #include "UserDataOperation.hpp"
#include "../Parser/BinaryOperatorKind.hpp" #include "../Parser/BinaryOperatorKind.hpp"
#include "../Exception.hpp"
namespace Porygon::UserData { namespace Porygon::UserData {
class UserData { class UserData {
@ -15,16 +16,16 @@ namespace Porygon::UserData {
std::mutex _mutex; std::mutex _mutex;
// Binary operations // Binary operations
std::vector<UserDataBinaryOperation*> _addition = {}; std::vector<const UserDataBinaryOperation*> _addition = {};
std::vector<UserDataBinaryOperation*> _subtraction = {}; std::vector<const UserDataBinaryOperation*> _subtraction = {};
std::vector<UserDataBinaryOperation*> _multiplication = {}; std::vector<const UserDataBinaryOperation*> _multiplication = {};
std::vector<UserDataBinaryOperation*> _division = {}; std::vector<const UserDataBinaryOperation*> _division = {};
std::vector<UserDataBinaryOperation*> _equality = {}; std::vector<const UserDataBinaryOperation*> _equality = {};
std::vector<UserDataBinaryOperation*> _inequality = {}; std::vector<const UserDataBinaryOperation*> _inequality = {};
std::vector<UserDataBinaryOperation*> _lessThan = {}; std::vector<const UserDataBinaryOperation*> _lessThan = {};
std::vector<UserDataBinaryOperation*> _lessThanEquals = {}; std::vector<const UserDataBinaryOperation*> _lessThanEquals = {};
std::vector<UserDataBinaryOperation*> _greaterThan = {}; std::vector<const UserDataBinaryOperation*> _greaterThan = {};
std::vector<UserDataBinaryOperation*> _greaterThanEquals = {}; std::vector<const UserDataBinaryOperation*> _greaterThanEquals = {};
bool (*_isCastable)(const ScriptType* type, bool explicitCast); bool (*_isCastable)(const ScriptType* type, bool explicitCast);
Evaluation::EvalValue* (*_cast)(void* obj, const ScriptType* castType); Evaluation::EvalValue* (*_cast)(void* obj, const ScriptType* castType);
@ -95,25 +96,28 @@ namespace Porygon::UserData {
return _cast(obj, castType); return _cast(obj, castType);
} }
void AddBinaryOperation(Binder::BoundBinaryOperation kind, UserDataBinaryOperation* op){ void AddBinaryOperation(Binder::BoundBinaryOperation kind, const UserDataBinaryOperation* op){
switch (kind){ switch (kind){
case Binder::BoundBinaryOperation::Addition: return _addition.push_back(op);
case Binder::BoundBinaryOperation::Addition: _addition.push_back(op); case Binder::BoundBinaryOperation::Subtraction: return _subtraction.push_back(op);
case Binder::BoundBinaryOperation::Subtraction: _subtraction.push_back(op); case Binder::BoundBinaryOperation::Multiplication: return _multiplication.push_back(op);
case Binder::BoundBinaryOperation::Multiplication: _multiplication.push_back(op); case Binder::BoundBinaryOperation::Division: return _division.push_back(op);
case Binder::BoundBinaryOperation::Division: _division.push_back(op); case Binder::BoundBinaryOperation::Equality: return _equality.push_back(op);
case Binder::BoundBinaryOperation::Equality: _equality.push_back(op); case Binder::BoundBinaryOperation::Inequality: return _inequality.push_back(op);
case Binder::BoundBinaryOperation::Inequality: _inequality.push_back(op); case Binder::BoundBinaryOperation::LessThan: return _lessThan.push_back(op);
case Binder::BoundBinaryOperation::LessThan: _lessThan.push_back(op); case Binder::BoundBinaryOperation::LessThanEquals: return _lessThanEquals.push_back(op);
case Binder::BoundBinaryOperation::LessThanEquals: _lessThanEquals.push_back(op); case Binder::BoundBinaryOperation::GreaterThan: return _greaterThan.push_back(op);
case Binder::BoundBinaryOperation::GreaterThan: _greaterThan.push_back(op); case Binder::BoundBinaryOperation::GreaterThanEquals: return _greaterThanEquals.push_back(op);
case Binder::BoundBinaryOperation::GreaterThanEquals: _greaterThanEquals.push_back(op); default:
default: throw exception(); stringstream err;
err << "Unknown binary operation kind: " << static_cast<int>(kind);
throw Exception(err.str().c_str());
} }
} }
private: private:
static UserDataBinaryOperation* ResolveBinaryOperation(const vector<UserDataBinaryOperation*>& v, const shared_ptr<const ScriptType>& b){ static const UserDataBinaryOperation* ResolveBinaryOperation(const vector<const UserDataBinaryOperation*>& v,
const shared_ptr<const ScriptType>& b){
for (auto o: v){ for (auto o: v){
if (o->IsValid(b)){ if (o->IsValid(b)){
return o; return o;
@ -124,7 +128,7 @@ namespace Porygon::UserData {
public: public:
[[nodiscard]] [[nodiscard]]
UserDataBinaryOperation* GetBinaryOperation(Parser::BinaryOperatorKind op, const shared_ptr<const ScriptType>& b){ const UserDataBinaryOperation* GetBinaryOperation(Parser::BinaryOperatorKind op, const shared_ptr<const ScriptType>& b){
switch (op){ switch (op){
case Parser::BinaryOperatorKind::Addition: return ResolveBinaryOperation(_addition, b); case Parser::BinaryOperatorKind::Addition: return ResolveBinaryOperation(_addition, b);

View File

@ -1 +1,11 @@
#include "UserDataOperation.hpp" #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<const ScriptType>(secondParameter),
shared_ptr<const ScriptType>(returnType));
}
}
}

View File

@ -12,8 +12,8 @@ namespace Porygon::UserData {
const shared_ptr<const ScriptType> _returnType; const shared_ptr<const ScriptType> _returnType;
public: public:
UserDataBinaryOperation(Evaluation::EvalValue *(*func)(void *, const Evaluation::EvalValue *), UserDataBinaryOperation(Evaluation::EvalValue *(*func)(void *, const Evaluation::EvalValue *),
shared_ptr<ScriptType> secondParameter, shared_ptr<const ScriptType> secondParameter,
shared_ptr<ScriptType> returnType) shared_ptr<const ScriptType> returnType)
: _func(func), _secondParameter(std::move(secondParameter)), : _func(func), _secondParameter(std::move(secondParameter)),
_returnType(std::move(returnType)) {} _returnType(std::move(returnType)) {}
@ -21,18 +21,13 @@ namespace Porygon::UserData {
return _func(a, b); return _func(a, b);
} }
bool IsValid(const shared_ptr<const ScriptType>& v){ [[nodiscard]] bool IsValid(const shared_ptr<const ScriptType>& v) const{
if (v->operator==(_secondParameter)){ if (v->operator==(_secondParameter)){
return true; return true;
} }
return v->CastableTo(_secondParameter, true) != CastResult::InvalidCast; return v->CastableTo(_secondParameter, true) != CastResult::InvalidCast;
} }
[[nodiscard]]
inline shared_ptr<const ScriptType> GetSecondParameterType() const{
return _secondParameter;
}
[[nodiscard]] [[nodiscard]]
inline shared_ptr<const ScriptType> GetReturnType() const{ inline shared_ptr<const ScriptType> GetReturnType() const{
return _returnType; return _returnType;