PorygonLang/src/Binder/BoundExpressions/BoundExpression.hpp

534 lines
18 KiB
C++

#ifndef PORYGONLANG_BOUNDEXPRESSION_HPP
#define PORYGONLANG_BOUNDEXPRESSION_HPP
#include <string>
#include <memory>
#include <utility>
#include "../../ScriptTypes/ScriptType.hpp"
#include "../BoundOperators.hpp"
#include "../BoundVariables/BoundVariableKey.hpp"
#include "../../Utilities/StringUtils.hpp"
#include "../../UserData/UserDataOperation.hpp"
using namespace std;
namespace Porygon::Binder {
enum class BoundExpressionKind : uint8_t {
Bad,
LiteralInteger,
LiteralFloat,
LiteralString,
LiteralBool,
Nil,
Variable,
Unary,
Binary,
UserdataBinary,
FunctionCall,
Index,
PeriodIndex,
NumericalTable,
Table,
Require,
Cast,
};
class BoundExpression {
private:
const unsigned int _start;
const unsigned int _length;
const shared_ptr<const ScriptType> _type;
protected:
inline void DrawIndents(std::stringstream& stream, size_t indents) const{
for (size_t i = 0; i < indents; i++)
stream << "\t";
}
public:
BoundExpression(unsigned int start, unsigned int length, shared_ptr<const ScriptType> type)
: _start(start),
_length(length),
_type(std::move(type)) {
}
virtual ~BoundExpression() = default;
[[nodiscard]]
virtual BoundExpressionKind GetKind() const = 0;
[[nodiscard]]
virtual const std::shared_ptr<const ScriptType> &GetType() const {
return _type;
};
[[nodiscard]]
inline unsigned int GetStartPosition() const {
return _start;
}
[[nodiscard]]
inline unsigned int GetLength() const {
return _length;
}
virtual void GetTreeString(std::stringstream& stream, size_t indents) const = 0;
};
class BoundBadExpression : public BoundExpression {
public:
BoundBadExpression(unsigned int start, unsigned int length) : BoundExpression(start, length,
make_shared<ScriptType>(
TypeClass::Error)) {}
[[nodiscard]]
inline BoundExpressionKind GetKind() const final {
return BoundExpressionKind::Bad;
}
void GetTreeString(std::stringstream& stream, size_t indents) const final{
DrawIndents(stream, indents);
stream << "BadExpression";
}
};
class BoundLiteralIntegerExpression : public BoundExpression {
const int64_t _value;
public:
BoundLiteralIntegerExpression(int64_t value, unsigned int start, unsigned int length)
: BoundExpression(start, length, NumericScriptType::AwareInt),
_value(value) {
}
[[nodiscard]]
inline BoundExpressionKind GetKind() const final {
return BoundExpressionKind::LiteralInteger;
}
[[nodiscard]]
inline int64_t GetValue() const {
return _value;
}
void GetTreeString(std::stringstream& stream, size_t indents) const final{
DrawIndents(stream, indents);
stream << "LiteralInteger: " << _value << " (" << GetType()->ToString() << ")";
}
};
class BoundLiteralFloatExpression : public BoundExpression {
const double _value;
public:
BoundLiteralFloatExpression(double value, unsigned int start, unsigned int length)
: BoundExpression(start, length, NumericScriptType::AwareFloat),
_value(value) {
}
[[nodiscard]]
inline BoundExpressionKind GetKind() const final {
return BoundExpressionKind::LiteralFloat;
}
[[nodiscard]]
inline double GetValue() const {
return _value;
}
void GetTreeString(std::stringstream& stream, size_t indents) const final{
DrawIndents(stream, indents);
stream << "LiteralFloat: " << _value << " (" << GetType()->ToString() << ")";
}
};
class BoundLiteralStringExpression : public BoundExpression {
const u16string _value;
public:
BoundLiteralStringExpression(const u16string &value, unsigned int start, unsigned int length)
: BoundExpression(start, length,
make_shared<StringScriptType>(true, Utilities::HashedString::ConstHash(value.c_str()))),
_value(value) {
}
[[nodiscard]]
inline BoundExpressionKind GetKind() const final {
return BoundExpressionKind::LiteralString;
}
[[nodiscard]]
inline const u16string* GetValue() const {
return &_value;
}
void GetTreeString(std::stringstream& stream, size_t indents) const final{
DrawIndents(stream, indents);
stream << "LiteralString: \"" << Utilities::StringUtils::FromUTF8(_value)
<< "\" (" << GetType()->ToString() << ")";
}
};
class BoundLiteralBoolExpression : public BoundExpression {
const bool _value;
public:
BoundLiteralBoolExpression(bool value, unsigned int start, unsigned int length)
: BoundExpression(start, length, ScriptType::BoolType),
_value(value) {
}
[[nodiscard]]
inline BoundExpressionKind GetKind() const final {
return BoundExpressionKind::LiteralBool;
}
[[nodiscard]]
inline bool GetValue() const {
return _value;
}
void GetTreeString(std::stringstream& stream, size_t indents) const final{
DrawIndents(stream, indents);
stream << "LiteralBool: " << _value << " (" << GetType()->ToString() << ")";
}
};
class BoundNilExpression : public BoundExpression {
public:
BoundNilExpression(unsigned int start, unsigned int length)
: BoundExpression(start, length, ScriptType::NilType)
{ }
[[nodiscard]]
inline BoundExpressionKind GetKind() const final {
return BoundExpressionKind::Nil;
}
void GetTreeString(std::stringstream& stream, size_t indents) const final{
DrawIndents(stream, indents);
stream << "NilExpression" << " (" << GetType()->ToString() << ")";
}
};
class BoundVariableExpression : public BoundExpression {
const BoundVariableKey *_key;
public:
BoundVariableExpression(BoundVariableKey *key, const shared_ptr<const ScriptType>& type, unsigned int start,
unsigned int length)
: BoundExpression(start, length, type),
_key(key) {
}
~BoundVariableExpression() override {
delete _key;
}
[[nodiscard]]
inline BoundExpressionKind GetKind() const final {
return BoundExpressionKind::Variable;
}
[[nodiscard]]
inline const BoundVariableKey *GetKey() const {
return _key;
}
void GetTreeString(std::stringstream& stream, size_t indents) const final{
DrawIndents(stream, indents);
stream << "VariableExpression: " << _key->GetIdentifier()->GetDebugString()
<< " (" << GetType()->ToString() << ")";
}
};
class BoundBinaryExpression : public BoundExpression {
const BoundExpression *_left;
const BoundExpression *_right;
const BoundBinaryOperation _operation;
public:
BoundBinaryExpression(BoundExpression *left, BoundExpression *right, BoundBinaryOperation op,
shared_ptr<const ScriptType> result,
unsigned int start, unsigned int length)
: BoundExpression(start, length, std::move(result)),
_left(left),
_right(right),
_operation(op) {
}
~BoundBinaryExpression() final {
delete _left;
delete _right;
}
[[nodiscard]]
inline BoundExpressionKind GetKind() const final {
return BoundExpressionKind::Binary;
}
[[nodiscard]]
inline const BoundExpression *GetLeft() const {
return _left;
}
[[nodiscard]]
inline const BoundExpression *GetRight() const {
return _right;
}
[[nodiscard]]
inline BoundBinaryOperation GetOperation() const {
return _operation;
}
static std::string GetOperationString(BoundBinaryOperation op){
switch (op){
case BoundBinaryOperation::Addition: return "addition";
case BoundBinaryOperation::Subtraction: return "subtraction";
case BoundBinaryOperation::Multiplication: return "multiplication";
case BoundBinaryOperation::Division: return "division";
case BoundBinaryOperation::Equality: return "equality";
case BoundBinaryOperation::Inequality: return "inequality";
case BoundBinaryOperation::LessThan: return "lessThan";
case BoundBinaryOperation::LessThanEquals: return "lessThanEquals";
case BoundBinaryOperation::GreaterThan: return "greaterThan";
case BoundBinaryOperation::GreaterThanEquals: return "greaterThanEquals";
case BoundBinaryOperation::LogicalAnd: return "logicalAnd";
case BoundBinaryOperation::LogicalOr: return "logicalOr";
case BoundBinaryOperation::Concatenation: return "concatenation";
}
throw exception();
}
void GetTreeString(std::stringstream& stream, size_t indents) const final{
DrawIndents(stream, indents);
stream << "BinaryExpression: " << GetOperationString(_operation)
<< " (" << GetType()->ToString() << ")" << endl;
_left->GetTreeString(stream, indents + 1);
stream << endl;
_right->GetTreeString(stream, indents + 1);
}
};
class BoundUserdataBinaryExpression : public BoundExpression{
private:
const BoundExpression* _left;
const BoundExpression* _right;
const UserData::UserDataBinaryOperation* _operation;
public:
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)),
_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;
public:
BoundUnaryExpression(BoundExpression *operand, BoundUnaryOperation op, shared_ptr<const ScriptType> result,
unsigned int start, unsigned int length)
: BoundExpression(start, length, std::move(result)),
_operand(operand),
_operation(op) {
}
~BoundUnaryExpression() final {
delete _operand;
}
[[nodiscard]]
inline BoundExpressionKind GetKind() const final {
return BoundExpressionKind::Unary;
}
[[nodiscard]]
inline const BoundExpression *GetOperand() const {
return _operand;
}
[[nodiscard]]
inline BoundUnaryOperation GetOperation() const {
return _operation;
}
static std::string GetOperationString(BoundUnaryOperation op){
switch (op){
case BoundUnaryOperation::Negation: return "negation";
case BoundUnaryOperation::LogicalNegation: return "logicalNegation";
}
throw exception();
}
void GetTreeString(std::stringstream& stream, size_t indents) const final{
DrawIndents(stream, indents);
stream << "UnaryExpression: " << GetOperationString(_operation)
<< " (" << GetType()->ToString() << ")" << endl;
_operand->GetTreeString(stream, indents + 1);
}
};
class BoundIndexExpression : public BoundExpression {
const BoundExpression *_indexableExpression;
const BoundExpression *_indexExpression;
public:
BoundIndexExpression(BoundExpression *indexableExpression, BoundExpression *indexExpression,
shared_ptr<const ScriptType> result,
unsigned int start, unsigned int length)
: BoundExpression(start, length, std::move(result)), _indexableExpression(indexableExpression),
_indexExpression(indexExpression) {}
~BoundIndexExpression() final {
delete _indexableExpression;
delete _indexExpression;
}
[[nodiscard]]
inline BoundExpressionKind GetKind() const final {
return BoundExpressionKind::Index;
}
[[nodiscard]]
inline const BoundExpression *GetIndexableExpression() const {
return _indexableExpression;
}
[[nodiscard]]
inline const BoundExpression *GetIndexExpression() const {
return _indexExpression;
}
void GetTreeString(std::stringstream& stream, size_t indents) const final{
DrawIndents(stream, indents);
stream << "IndexExpression" << " (" << GetType()->ToString() << ")" << endl;
_indexableExpression->GetTreeString(stream, indents + 1);
stream << endl;
_indexExpression->GetTreeString(stream, indents + 1);
}
};
class BoundPeriodIndexExpression : public BoundExpression {
const BoundExpression *_indexableExpression;
const Utilities::HashedString _index;
public:
BoundPeriodIndexExpression(BoundExpression *indexableExpression, const Utilities::HashedString& index,
shared_ptr<const ScriptType> result,
unsigned int start, unsigned int length)
: BoundExpression(start, length, std::move(result)), _indexableExpression(indexableExpression),
_index(index) {}
~BoundPeriodIndexExpression() final {
delete _indexableExpression;
}
[[nodiscard]]
inline BoundExpressionKind GetKind() const final {
return BoundExpressionKind::PeriodIndex;
}
[[nodiscard]]
inline const BoundExpression *GetIndexableExpression() const {
return _indexableExpression;
}
[[nodiscard]]
inline const Utilities::HashedString* GetIndex() const {
return &_index;
}
void GetTreeString(std::stringstream& stream, size_t indents) const final{
DrawIndents(stream, indents);
stream << "PeriodIndex: " << _index.GetDebugString() << " (" << GetType()->ToString() << ")" << endl;
_indexableExpression->GetTreeString(stream, indents + 1);
}
};
class BoundNumericalTableExpression : public BoundExpression {
const vector<const BoundExpression *> _expressions;
public:
BoundNumericalTableExpression(vector<const BoundExpression *> expressions, shared_ptr<const ScriptType> type,
unsigned int start, unsigned int length)
: BoundExpression(start, length, std::move(type)),
_expressions(std::move(expressions)) {}
~BoundNumericalTableExpression() final {
for (auto e: _expressions) {
delete e;
}
}
[[nodiscard]]
inline BoundExpressionKind GetKind() const final {
return BoundExpressionKind::NumericalTable;
}
[[nodiscard]]
inline const vector<const BoundExpression *> *GetExpressions() const {
return &_expressions;
}
void GetTreeString(std::stringstream& stream, size_t indents) const final{
for (size_t i = 0; i < indents; i++)
stream << "\t";
stream << "NumericalTable" << " (" << GetType()->ToString() << ")";
for (auto _expression : _expressions){
stream << endl;
_expression->GetTreeString(stream, indents + 1);
}
}
};
class BoundCastExpression : public BoundExpression {
const BoundExpression* _expression;
public:
BoundCastExpression(BoundExpression* expression, shared_ptr<const ScriptType> castType)
: BoundExpression(expression->GetStartPosition(), expression->GetLength(), castType),
_expression(expression)
{}
[[nodiscard]] const BoundExpression* GetExpression() const{
return _expression;
}
~BoundCastExpression() final {
delete _expression;
}
[[nodiscard]]
inline BoundExpressionKind GetKind() const final {
return BoundExpressionKind::Cast;
}
void GetTreeString(std::stringstream& stream, size_t indents) const final{
for (size_t i = 0; i < indents; i++)
stream << "\t";
stream << "CastExpression" << " (" << GetType()->ToString() << ")" << endl;
_expression->GetTreeString(stream, indents + 1);
}
};
}
#endif //PORYGONLANG_BOUNDEXPRESSION_HPP