Work on userdata binary operations
continuous-integration/drone/push Build encountered an error
Details
continuous-integration/drone/push Build encountered an error
Details
This commit is contained in:
parent
85936f3d68
commit
eca0c6b075
|
@ -420,6 +420,19 @@ namespace Porygon::Binder {
|
|||
auto boundLeftType = boundLeft->GetType();
|
||||
auto boundRightType = boundRight->GetType();
|
||||
|
||||
if (boundLeftType->GetClass() == TypeClass::UserData){
|
||||
auto ud = dynamic_pointer_cast<const UserData::UserDataScriptType>(boundLeftType);
|
||||
auto op = ud->GetUserData()->Get()->GetBinaryOperation(expression->GetOperatorKind(), boundRightType);
|
||||
if (op == nullptr){
|
||||
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::NoBinaryOperationFound,
|
||||
expression->GetStartPosition(),
|
||||
expression->GetLength());
|
||||
return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength());
|
||||
}
|
||||
return new BoundUserdataBinaryExpression(boundLeft, boundRight, op, op->GetReturnType(),
|
||||
expression->GetStartPosition(), expression->GetLength());
|
||||
}
|
||||
|
||||
switch (expression->GetOperatorKind()) {
|
||||
case BinaryOperatorKind::Addition:
|
||||
if (boundLeftType->GetClass() == TypeClass::Number && boundRightType->GetClass() == TypeClass::Number) {
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "../BoundOperators.hpp"
|
||||
#include "../BoundVariables/BoundVariableKey.hpp"
|
||||
#include "../../Utilities/StringUtils.hpp"
|
||||
#include "../../UserData/UserDataOperation.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
@ -24,6 +25,7 @@ namespace Porygon::Binder {
|
|||
|
||||
Unary,
|
||||
Binary,
|
||||
UserdataBinary,
|
||||
FunctionCall,
|
||||
Index,
|
||||
PeriodIndex,
|
||||
|
@ -304,6 +306,39 @@ namespace Porygon::Binder {
|
|||
}
|
||||
};
|
||||
|
||||
class BoundUserdataBinaryExpression : public BoundExpression{
|
||||
private:
|
||||
const BoundExpression* _left;
|
||||
const BoundExpression* _right;
|
||||
const UserData::UserDataBinaryOperation* _operation;
|
||||
public:
|
||||
BoundUserdataBinaryExpression(BoundExpression *left, BoundExpression *right, UserData::UserDataBinaryOperation* op,
|
||||
shared_ptr<const ScriptType> result,
|
||||
unsigned int start, unsigned int length)
|
||||
: BoundExpression(start, length, std::move(result)),
|
||||
_left(left),
|
||||
_right(right),
|
||||
_operation(op) {}
|
||||
|
||||
[[nodiscard]] inline const BoundExpression* GetLeft() const { return _left; }
|
||||
[[nodiscard]] inline const BoundExpression* GetRight() const { return _right; }
|
||||
[[nodiscard]] inline const UserData::UserDataBinaryOperation* GetOperation() const { return _operation; }
|
||||
|
||||
[[nodiscard]]
|
||||
inline BoundExpressionKind GetKind() const final {
|
||||
return BoundExpressionKind::UserdataBinary;
|
||||
}
|
||||
|
||||
void GetTreeString(std::stringstream& stream, size_t indents) const final {
|
||||
DrawIndents(stream, indents);
|
||||
stream << "BinaryExpression: " << "Userdata operand "
|
||||
<< " (" << GetType()->ToString() << ")" << endl;
|
||||
_left->GetTreeString(stream, indents + 1);
|
||||
stream << endl;
|
||||
_right->GetTreeString(stream, indents + 1);
|
||||
}
|
||||
};
|
||||
|
||||
class BoundUnaryExpression : public BoundExpression {
|
||||
const BoundExpression *_operand;
|
||||
const BoundUnaryOperation _operation;
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "../ScriptTypes/TableScriptType.hpp"
|
||||
#include "../UserData/UserDataFunction.hpp"
|
||||
#include "EvalValues/NumericalTableEvalValue.hpp"
|
||||
#include "../UserData/UserDataValue.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace Porygon::Binder;
|
||||
|
@ -248,6 +249,8 @@ namespace Porygon::Evaluation {
|
|||
return this->EvaluateUnary((BoundUnaryExpression *) expression);
|
||||
case BoundExpressionKind::Binary:
|
||||
return this->EvaluateBinary((BoundBinaryExpression *) expression);
|
||||
case BoundExpressionKind ::UserdataBinary:
|
||||
return this->EvaluateUserDataBinary(dynamic_cast<const BoundUserdataBinaryExpression*>(expression));
|
||||
case BoundExpressionKind::FunctionCall:
|
||||
return this->EvaluateFunctionCallExpression(expression);
|
||||
case BoundExpressionKind::Index:
|
||||
|
@ -282,6 +285,15 @@ namespace Porygon::Evaluation {
|
|||
return leftValue->BinaryOperation(operation, rightValue.Get());
|
||||
}
|
||||
|
||||
EvalValuePointer Evaluator::EvaluateUserDataBinary(const BoundUserdataBinaryExpression *expression) {
|
||||
auto leftValue = this->EvaluateExpression(expression->GetLeft());
|
||||
auto rightValue = this->EvaluateExpression(expression->GetRight());
|
||||
auto op = expression->GetOperation();
|
||||
auto o = dynamic_cast<const UserData::UserDataValue*>(leftValue.Get());
|
||||
auto val = op->Invoke(o->GetObjectPointer(), rightValue.Get());
|
||||
return val;
|
||||
}
|
||||
|
||||
EvalValuePointer Evaluator::EvaluateUnary(const BoundUnaryExpression *expression) {
|
||||
auto exp = expression->GetOperand();
|
||||
auto val = EvaluateExpression(exp);
|
||||
|
|
|
@ -39,6 +39,7 @@ namespace Porygon::Evaluation{
|
|||
|
||||
EvalValuePointer EvaluateExpression(const BoundExpression *expression);
|
||||
EvalValuePointer EvaluateBinary(const BoundBinaryExpression *expression);
|
||||
EvalValuePointer EvaluateUserDataBinary(const BoundUserdataBinaryExpression *expression);
|
||||
EvalValuePointer EvaluateUnary(const BoundUnaryExpression *expression);
|
||||
|
||||
EvalValuePointer EvaluateFunctionCallExpression(const BoundExpression *expression);
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <mutex>
|
||||
#include "UserDataField.hpp"
|
||||
#include "UserDataOperation.hpp"
|
||||
#include "../Parser/BinaryOperatorKind.hpp"
|
||||
|
||||
namespace Porygon::UserData {
|
||||
class UserData {
|
||||
|
@ -14,19 +15,16 @@ namespace Porygon::UserData {
|
|||
std::mutex _mutex;
|
||||
|
||||
// Binary operations
|
||||
UserDataBinaryOperation* _addition = nullptr;
|
||||
UserDataBinaryOperation* _subtraction = nullptr;
|
||||
UserDataBinaryOperation* _multiplication = nullptr;
|
||||
UserDataBinaryOperation* _division = nullptr;
|
||||
UserDataBinaryOperation* _equality = nullptr;
|
||||
UserDataBinaryOperation* _inequality = nullptr;
|
||||
UserDataBinaryOperation* _lessThen = nullptr;
|
||||
UserDataBinaryOperation* _lessThenEqual = nullptr;
|
||||
UserDataBinaryOperation* _greaterThen = nullptr;
|
||||
UserDataBinaryOperation* _greaterThenEqual = nullptr;
|
||||
UserDataBinaryOperation* _logicalAnd = nullptr;
|
||||
UserDataBinaryOperation* _logicalOr = nullptr;
|
||||
UserDataBinaryOperation* _concatenation = nullptr;
|
||||
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 = {};
|
||||
|
||||
bool (*_isCastable)(const ScriptType* type, bool explicitCast);
|
||||
Evaluation::EvalValue* (*_cast)(void* obj, const ScriptType* castType);
|
||||
|
@ -42,20 +40,16 @@ namespace Porygon::UserData {
|
|||
|
||||
~UserData(){
|
||||
_fields.clear();
|
||||
|
||||
delete _addition;
|
||||
delete _subtraction;
|
||||
delete _multiplication;
|
||||
delete _division;
|
||||
delete _equality;
|
||||
delete _inequality;
|
||||
delete _lessThen;
|
||||
delete _lessThenEqual;
|
||||
delete _greaterThen;
|
||||
delete _greaterThenEqual;
|
||||
delete _logicalAnd;
|
||||
delete _logicalOr;
|
||||
delete _concatenation;
|
||||
for (auto o: _addition) delete o;
|
||||
for (auto o: _subtraction) delete o;
|
||||
for (auto o: _multiplication) delete o;
|
||||
for (auto o: _division) delete o;
|
||||
for (auto o: _equality) delete o;
|
||||
for (auto o: _inequality) delete o;
|
||||
for (auto o: _lessThan) delete o;
|
||||
for (auto o: _lessThanEquals) delete o;
|
||||
for (auto o: _greaterThan) delete o;
|
||||
for (auto o: _greaterThanEquals) delete o;
|
||||
|
||||
delete _hashedString;
|
||||
}
|
||||
|
@ -101,23 +95,49 @@ namespace Porygon::UserData {
|
|||
return _cast(obj, castType);
|
||||
}
|
||||
|
||||
void AddBinaryOperation(Binder::BoundBinaryOperation kind, 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();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static UserDataBinaryOperation* ResolveBinaryOperation(const vector<UserDataBinaryOperation*>& v, const shared_ptr<const ScriptType>& b){
|
||||
for (auto o: v){
|
||||
if (o->IsValid(b)){
|
||||
return o;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
public:
|
||||
[[nodiscard]]
|
||||
UserDataBinaryOperation* GetBinaryOperation(Binder::BoundBinaryOperation op){
|
||||
UserDataBinaryOperation* GetBinaryOperation(Parser::BinaryOperatorKind op, const shared_ptr<const ScriptType>& b){
|
||||
switch (op){
|
||||
|
||||
case Binder::BoundBinaryOperation::Addition: return _addition;
|
||||
case Binder::BoundBinaryOperation::Subtraction: return _subtraction;
|
||||
case Binder::BoundBinaryOperation::Multiplication: return _multiplication;
|
||||
case Binder::BoundBinaryOperation::Division: return _division;
|
||||
case Binder::BoundBinaryOperation::Equality: return _equality;
|
||||
case Binder::BoundBinaryOperation::Inequality: return _inequality;
|
||||
case Binder::BoundBinaryOperation::LessThan: return _lessThen;
|
||||
case Binder::BoundBinaryOperation::LessThanEquals: return _lessThenEqual;
|
||||
case Binder::BoundBinaryOperation::GreaterThan: return _greaterThen;
|
||||
case Binder::BoundBinaryOperation::GreaterThanEquals: return _greaterThenEqual;
|
||||
case Binder::BoundBinaryOperation::LogicalAnd: return _logicalAnd;
|
||||
case Binder::BoundBinaryOperation::LogicalOr: return _logicalOr;
|
||||
case Binder::BoundBinaryOperation::Concatenation: return _concatenation;
|
||||
case Parser::BinaryOperatorKind::Addition: return ResolveBinaryOperation(_addition, b);
|
||||
case Parser::BinaryOperatorKind::Subtraction: return ResolveBinaryOperation(_subtraction, b);
|
||||
case Parser::BinaryOperatorKind::Multiplication: return ResolveBinaryOperation(_multiplication, b);
|
||||
case Parser::BinaryOperatorKind::Division: return ResolveBinaryOperation(_division, b);
|
||||
case Parser::BinaryOperatorKind::Equality: return ResolveBinaryOperation(_equality, b);
|
||||
case Parser::BinaryOperatorKind::Inequality: return ResolveBinaryOperation(_inequality, b);
|
||||
case Parser::BinaryOperatorKind::Less: return ResolveBinaryOperation(_lessThan, b);
|
||||
case Parser::BinaryOperatorKind::LessOrEquals: return ResolveBinaryOperation(_lessThanEquals, b);
|
||||
case Parser::BinaryOperatorKind::Greater: return ResolveBinaryOperation(_greaterThan, b);
|
||||
case Parser::BinaryOperatorKind::GreaterOrEquals: return ResolveBinaryOperation(_greaterThanEquals, b);
|
||||
default: throw exception();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -7,20 +7,25 @@
|
|||
|
||||
namespace Porygon::UserData {
|
||||
class UserDataBinaryOperation {
|
||||
void* _parent;
|
||||
Evaluation::EvalValue *(*_func)(void *obj, Evaluation::EvalValue *b);
|
||||
Evaluation::EvalValue *(*_func)(void *obj, const Evaluation::EvalValue *b);
|
||||
const shared_ptr<const ScriptType> _secondParameter;
|
||||
const shared_ptr<const ScriptType> _returnType;
|
||||
public:
|
||||
UserDataBinaryOperation(void *parent,
|
||||
Evaluation::EvalValue *(*func)(void *, Evaluation::EvalValue *),
|
||||
UserDataBinaryOperation(Evaluation::EvalValue *(*func)(void *, const Evaluation::EvalValue *),
|
||||
shared_ptr<ScriptType> secondParameter,
|
||||
shared_ptr<ScriptType> returnType)
|
||||
: _parent(parent), _func(func), _secondParameter(std::move(secondParameter)),
|
||||
: _func(func), _secondParameter(std::move(secondParameter)),
|
||||
_returnType(std::move(returnType)) {}
|
||||
|
||||
Evaluation::EvalValue* Invoke(Evaluation::EvalValue * b) const{
|
||||
return _func(_parent, b);
|
||||
Evaluation::EvalValue* Invoke(void* a, const Evaluation::EvalValue * b) const{
|
||||
return _func(a, b);
|
||||
}
|
||||
|
||||
bool IsValid(const shared_ptr<const ScriptType>& v){
|
||||
if (v->operator==(_secondParameter)){
|
||||
return true;
|
||||
}
|
||||
return v->CastableTo(_secondParameter, true) != CastResult::InvalidCast;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
|
|
|
@ -71,6 +71,7 @@ namespace Porygon::UserData {
|
|||
s << ScriptType::ToString() << " (" << _userData->Get()->GetIdentifier()->GetDebugString() << ")";
|
||||
return s.str();
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -74,7 +74,7 @@ namespace Porygon::UserData {
|
|||
delete value;
|
||||
}
|
||||
|
||||
inline void* GetObjectPointer(){
|
||||
inline void* GetObjectPointer() const{
|
||||
return _obj;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue