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 boundLeftType = boundLeft->GetType();
|
||||||
auto boundRightType = boundRight->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()) {
|
switch (expression->GetOperatorKind()) {
|
||||||
case BinaryOperatorKind::Addition:
|
case BinaryOperatorKind::Addition:
|
||||||
if (boundLeftType->GetClass() == TypeClass::Number && boundRightType->GetClass() == TypeClass::Number) {
|
if (boundLeftType->GetClass() == TypeClass::Number && boundRightType->GetClass() == TypeClass::Number) {
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "../BoundOperators.hpp"
|
#include "../BoundOperators.hpp"
|
||||||
#include "../BoundVariables/BoundVariableKey.hpp"
|
#include "../BoundVariables/BoundVariableKey.hpp"
|
||||||
#include "../../Utilities/StringUtils.hpp"
|
#include "../../Utilities/StringUtils.hpp"
|
||||||
|
#include "../../UserData/UserDataOperation.hpp"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
@ -24,6 +25,7 @@ namespace Porygon::Binder {
|
||||||
|
|
||||||
Unary,
|
Unary,
|
||||||
Binary,
|
Binary,
|
||||||
|
UserdataBinary,
|
||||||
FunctionCall,
|
FunctionCall,
|
||||||
Index,
|
Index,
|
||||||
PeriodIndex,
|
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 {
|
class BoundUnaryExpression : public BoundExpression {
|
||||||
const BoundExpression *_operand;
|
const BoundExpression *_operand;
|
||||||
const BoundUnaryOperation _operation;
|
const BoundUnaryOperation _operation;
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include "../ScriptTypes/TableScriptType.hpp"
|
#include "../ScriptTypes/TableScriptType.hpp"
|
||||||
#include "../UserData/UserDataFunction.hpp"
|
#include "../UserData/UserDataFunction.hpp"
|
||||||
#include "EvalValues/NumericalTableEvalValue.hpp"
|
#include "EvalValues/NumericalTableEvalValue.hpp"
|
||||||
|
#include "../UserData/UserDataValue.hpp"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace Porygon::Binder;
|
using namespace Porygon::Binder;
|
||||||
|
@ -248,6 +249,8 @@ namespace Porygon::Evaluation {
|
||||||
return this->EvaluateUnary((BoundUnaryExpression *) expression);
|
return this->EvaluateUnary((BoundUnaryExpression *) expression);
|
||||||
case BoundExpressionKind::Binary:
|
case BoundExpressionKind::Binary:
|
||||||
return this->EvaluateBinary((BoundBinaryExpression *) expression);
|
return this->EvaluateBinary((BoundBinaryExpression *) expression);
|
||||||
|
case BoundExpressionKind ::UserdataBinary:
|
||||||
|
return this->EvaluateUserDataBinary(dynamic_cast<const BoundUserdataBinaryExpression*>(expression));
|
||||||
case BoundExpressionKind::FunctionCall:
|
case BoundExpressionKind::FunctionCall:
|
||||||
return this->EvaluateFunctionCallExpression(expression);
|
return this->EvaluateFunctionCallExpression(expression);
|
||||||
case BoundExpressionKind::Index:
|
case BoundExpressionKind::Index:
|
||||||
|
@ -282,6 +285,15 @@ namespace Porygon::Evaluation {
|
||||||
return leftValue->BinaryOperation(operation, rightValue.Get());
|
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) {
|
EvalValuePointer Evaluator::EvaluateUnary(const BoundUnaryExpression *expression) {
|
||||||
auto exp = expression->GetOperand();
|
auto exp = expression->GetOperand();
|
||||||
auto val = EvaluateExpression(exp);
|
auto val = EvaluateExpression(exp);
|
||||||
|
|
|
@ -39,6 +39,7 @@ namespace Porygon::Evaluation{
|
||||||
|
|
||||||
EvalValuePointer EvaluateExpression(const BoundExpression *expression);
|
EvalValuePointer EvaluateExpression(const BoundExpression *expression);
|
||||||
EvalValuePointer EvaluateBinary(const BoundBinaryExpression *expression);
|
EvalValuePointer EvaluateBinary(const BoundBinaryExpression *expression);
|
||||||
|
EvalValuePointer EvaluateUserDataBinary(const BoundUserdataBinaryExpression *expression);
|
||||||
EvalValuePointer EvaluateUnary(const BoundUnaryExpression *expression);
|
EvalValuePointer EvaluateUnary(const BoundUnaryExpression *expression);
|
||||||
|
|
||||||
EvalValuePointer EvaluateFunctionCallExpression(const BoundExpression *expression);
|
EvalValuePointer EvaluateFunctionCallExpression(const BoundExpression *expression);
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include "UserDataField.hpp"
|
#include "UserDataField.hpp"
|
||||||
#include "UserDataOperation.hpp"
|
#include "UserDataOperation.hpp"
|
||||||
|
#include "../Parser/BinaryOperatorKind.hpp"
|
||||||
|
|
||||||
namespace Porygon::UserData {
|
namespace Porygon::UserData {
|
||||||
class UserData {
|
class UserData {
|
||||||
|
@ -14,19 +15,16 @@ namespace Porygon::UserData {
|
||||||
std::mutex _mutex;
|
std::mutex _mutex;
|
||||||
|
|
||||||
// Binary operations
|
// Binary operations
|
||||||
UserDataBinaryOperation* _addition = nullptr;
|
std::vector<UserDataBinaryOperation*> _addition = {};
|
||||||
UserDataBinaryOperation* _subtraction = nullptr;
|
std::vector<UserDataBinaryOperation*> _subtraction = {};
|
||||||
UserDataBinaryOperation* _multiplication = nullptr;
|
std::vector<UserDataBinaryOperation*> _multiplication = {};
|
||||||
UserDataBinaryOperation* _division = nullptr;
|
std::vector<UserDataBinaryOperation*> _division = {};
|
||||||
UserDataBinaryOperation* _equality = nullptr;
|
std::vector<UserDataBinaryOperation*> _equality = {};
|
||||||
UserDataBinaryOperation* _inequality = nullptr;
|
std::vector<UserDataBinaryOperation*> _inequality = {};
|
||||||
UserDataBinaryOperation* _lessThen = nullptr;
|
std::vector<UserDataBinaryOperation*> _lessThan = {};
|
||||||
UserDataBinaryOperation* _lessThenEqual = nullptr;
|
std::vector<UserDataBinaryOperation*> _lessThanEquals = {};
|
||||||
UserDataBinaryOperation* _greaterThen = nullptr;
|
std::vector<UserDataBinaryOperation*> _greaterThan = {};
|
||||||
UserDataBinaryOperation* _greaterThenEqual = nullptr;
|
std::vector<UserDataBinaryOperation*> _greaterThanEquals = {};
|
||||||
UserDataBinaryOperation* _logicalAnd = nullptr;
|
|
||||||
UserDataBinaryOperation* _logicalOr = nullptr;
|
|
||||||
UserDataBinaryOperation* _concatenation = nullptr;
|
|
||||||
|
|
||||||
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);
|
||||||
|
@ -42,20 +40,16 @@ namespace Porygon::UserData {
|
||||||
|
|
||||||
~UserData(){
|
~UserData(){
|
||||||
_fields.clear();
|
_fields.clear();
|
||||||
|
for (auto o: _addition) delete o;
|
||||||
delete _addition;
|
for (auto o: _subtraction) delete o;
|
||||||
delete _subtraction;
|
for (auto o: _multiplication) delete o;
|
||||||
delete _multiplication;
|
for (auto o: _division) delete o;
|
||||||
delete _division;
|
for (auto o: _equality) delete o;
|
||||||
delete _equality;
|
for (auto o: _inequality) delete o;
|
||||||
delete _inequality;
|
for (auto o: _lessThan) delete o;
|
||||||
delete _lessThen;
|
for (auto o: _lessThanEquals) delete o;
|
||||||
delete _lessThenEqual;
|
for (auto o: _greaterThan) delete o;
|
||||||
delete _greaterThen;
|
for (auto o: _greaterThanEquals) delete o;
|
||||||
delete _greaterThenEqual;
|
|
||||||
delete _logicalAnd;
|
|
||||||
delete _logicalOr;
|
|
||||||
delete _concatenation;
|
|
||||||
|
|
||||||
delete _hashedString;
|
delete _hashedString;
|
||||||
}
|
}
|
||||||
|
@ -101,23 +95,49 @@ namespace Porygon::UserData {
|
||||||
return _cast(obj, castType);
|
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]]
|
[[nodiscard]]
|
||||||
UserDataBinaryOperation* GetBinaryOperation(Binder::BoundBinaryOperation op){
|
UserDataBinaryOperation* GetBinaryOperation(Parser::BinaryOperatorKind op, const shared_ptr<const ScriptType>& b){
|
||||||
switch (op){
|
switch (op){
|
||||||
|
|
||||||
case Binder::BoundBinaryOperation::Addition: return _addition;
|
case Parser::BinaryOperatorKind::Addition: return ResolveBinaryOperation(_addition, b);
|
||||||
case Binder::BoundBinaryOperation::Subtraction: return _subtraction;
|
case Parser::BinaryOperatorKind::Subtraction: return ResolveBinaryOperation(_subtraction, b);
|
||||||
case Binder::BoundBinaryOperation::Multiplication: return _multiplication;
|
case Parser::BinaryOperatorKind::Multiplication: return ResolveBinaryOperation(_multiplication, b);
|
||||||
case Binder::BoundBinaryOperation::Division: return _division;
|
case Parser::BinaryOperatorKind::Division: return ResolveBinaryOperation(_division, b);
|
||||||
case Binder::BoundBinaryOperation::Equality: return _equality;
|
case Parser::BinaryOperatorKind::Equality: return ResolveBinaryOperation(_equality, b);
|
||||||
case Binder::BoundBinaryOperation::Inequality: return _inequality;
|
case Parser::BinaryOperatorKind::Inequality: return ResolveBinaryOperation(_inequality, b);
|
||||||
case Binder::BoundBinaryOperation::LessThan: return _lessThen;
|
case Parser::BinaryOperatorKind::Less: return ResolveBinaryOperation(_lessThan, b);
|
||||||
case Binder::BoundBinaryOperation::LessThanEquals: return _lessThenEqual;
|
case Parser::BinaryOperatorKind::LessOrEquals: return ResolveBinaryOperation(_lessThanEquals, b);
|
||||||
case Binder::BoundBinaryOperation::GreaterThan: return _greaterThen;
|
case Parser::BinaryOperatorKind::Greater: return ResolveBinaryOperation(_greaterThan, b);
|
||||||
case Binder::BoundBinaryOperation::GreaterThanEquals: return _greaterThenEqual;
|
case Parser::BinaryOperatorKind::GreaterOrEquals: return ResolveBinaryOperation(_greaterThanEquals, b);
|
||||||
case Binder::BoundBinaryOperation::LogicalAnd: return _logicalAnd;
|
default: throw exception();
|
||||||
case Binder::BoundBinaryOperation::LogicalOr: return _logicalOr;
|
|
||||||
case Binder::BoundBinaryOperation::Concatenation: return _concatenation;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -7,20 +7,25 @@
|
||||||
|
|
||||||
namespace Porygon::UserData {
|
namespace Porygon::UserData {
|
||||||
class UserDataBinaryOperation {
|
class UserDataBinaryOperation {
|
||||||
void* _parent;
|
Evaluation::EvalValue *(*_func)(void *obj, const Evaluation::EvalValue *b);
|
||||||
Evaluation::EvalValue *(*_func)(void *obj, Evaluation::EvalValue *b);
|
|
||||||
const shared_ptr<const ScriptType> _secondParameter;
|
const shared_ptr<const ScriptType> _secondParameter;
|
||||||
const shared_ptr<const ScriptType> _returnType;
|
const shared_ptr<const ScriptType> _returnType;
|
||||||
public:
|
public:
|
||||||
UserDataBinaryOperation(void *parent,
|
UserDataBinaryOperation(Evaluation::EvalValue *(*func)(void *, const Evaluation::EvalValue *),
|
||||||
Evaluation::EvalValue *(*func)(void *, Evaluation::EvalValue *),
|
|
||||||
shared_ptr<ScriptType> secondParameter,
|
shared_ptr<ScriptType> secondParameter,
|
||||||
shared_ptr<ScriptType> returnType)
|
shared_ptr<ScriptType> returnType)
|
||||||
: _parent(parent), _func(func), _secondParameter(std::move(secondParameter)),
|
: _func(func), _secondParameter(std::move(secondParameter)),
|
||||||
_returnType(std::move(returnType)) {}
|
_returnType(std::move(returnType)) {}
|
||||||
|
|
||||||
Evaluation::EvalValue* Invoke(Evaluation::EvalValue * b) const{
|
Evaluation::EvalValue* Invoke(void* a, const Evaluation::EvalValue * b) const{
|
||||||
return _func(_parent, b);
|
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]]
|
[[nodiscard]]
|
||||||
|
|
|
@ -71,6 +71,7 @@ namespace Porygon::UserData {
|
||||||
s << ScriptType::ToString() << " (" << _userData->Get()->GetIdentifier()->GetDebugString() << ")";
|
s << ScriptType::ToString() << " (" << _userData->Get()->GetIdentifier()->GetDebugString() << ")";
|
||||||
return s.str();
|
return s.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -74,7 +74,7 @@ namespace Porygon::UserData {
|
||||||
delete value;
|
delete value;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void* GetObjectPointer(){
|
inline void* GetObjectPointer() const{
|
||||||
return _obj;
|
return _obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue