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 UserData::UserDataBinaryOperation* _operation;
public:
BoundUserdataBinaryExpression(BoundExpression *left, BoundExpression *right, UserData::UserDataBinaryOperation* op,
BoundUserdataBinaryExpression(BoundExpression *left, BoundExpression *right, const UserData::UserDataBinaryOperation* op,
shared_ptr<const ScriptType> result,
unsigned int start, unsigned int length)
: BoundExpression(start, length, std::move(result)),

View File

@ -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 {

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 {
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,
};
}

View File

@ -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<Binder::BoundBinaryOperation >(kind), operation);
}
}
}

View File

@ -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<UserDataBinaryOperation*> _addition = {};
std::vector<UserDataBinaryOperation*> _subtraction = {};
std::vector<UserDataBinaryOperation*> _multiplication = {};
std::vector<UserDataBinaryOperation*> _division = {};
std::vector<UserDataBinaryOperation*> _equality = {};
std::vector<UserDataBinaryOperation*> _inequality = {};
std::vector<UserDataBinaryOperation*> _lessThan = {};
std::vector<UserDataBinaryOperation*> _lessThanEquals = {};
std::vector<UserDataBinaryOperation*> _greaterThan = {};
std::vector<UserDataBinaryOperation*> _greaterThanEquals = {};
std::vector<const UserDataBinaryOperation*> _addition = {};
std::vector<const UserDataBinaryOperation*> _subtraction = {};
std::vector<const UserDataBinaryOperation*> _multiplication = {};
std::vector<const UserDataBinaryOperation*> _division = {};
std::vector<const UserDataBinaryOperation*> _equality = {};
std::vector<const UserDataBinaryOperation*> _inequality = {};
std::vector<const UserDataBinaryOperation*> _lessThan = {};
std::vector<const UserDataBinaryOperation*> _lessThanEquals = {};
std::vector<const UserDataBinaryOperation*> _greaterThan = {};
std::vector<const UserDataBinaryOperation*> _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<int>(kind);
throw Exception(err.str().c_str());
}
}
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){
if (o->IsValid(b)){
return o;
@ -124,7 +128,7 @@ namespace Porygon::UserData {
public:
[[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){
case Parser::BinaryOperatorKind::Addition: return ResolveBinaryOperation(_addition, b);

View File

@ -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<const ScriptType>(secondParameter),
shared_ptr<const ScriptType>(returnType));
}
}
}

View File

@ -12,8 +12,8 @@ namespace Porygon::UserData {
const shared_ptr<const ScriptType> _returnType;
public:
UserDataBinaryOperation(Evaluation::EvalValue *(*func)(void *, const Evaluation::EvalValue *),
shared_ptr<ScriptType> secondParameter,
shared_ptr<ScriptType> returnType)
shared_ptr<const ScriptType> secondParameter,
shared_ptr<const ScriptType> 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<const ScriptType>& v){
[[nodiscard]] bool IsValid(const shared_ptr<const ScriptType>& v) const{
if (v->operator==(_secondParameter)){
return true;
}
return v->CastableTo(_secondParameter, true) != CastResult::InvalidCast;
}
[[nodiscard]]
inline shared_ptr<const ScriptType> GetSecondParameterType() const{
return _secondParameter;
}
[[nodiscard]]
inline shared_ptr<const ScriptType> GetReturnType() const{
return _returnType;