#ifndef PORYGONLANG_BOUNDSTATEMENT_HPP #define PORYGONLANG_BOUNDSTATEMENT_HPP #include <utility> #include <vector> #include "../BoundExpressions/BoundExpression.hpp" #include "../BoundVariables/BoundVariableKey.hpp" using namespace std; namespace Porygon::Binder { enum class BoundStatementKind : uint8_t { Bad, Break, Script, Block, Expression, Assignment, IndexAssignment, FunctionDeclaration, Return, Conditional, NumericalFor, GenericFor, While, }; class BoundStatement { public: [[nodiscard]] virtual BoundStatementKind GetKind() const = 0; virtual ~BoundStatement() = default; virtual void GetTreeString(std::stringstream& stream, size_t indents) const = 0; }; class BoundBadStatement : public BoundStatement { public: [[nodiscard]] inline BoundStatementKind GetKind() const final { return BoundStatementKind::Bad; } void GetTreeString(std::stringstream& stream, size_t indents) const final{ for (size_t i = 0; i < indents; i++) stream << "\t"; stream << "BadStatement"; } }; class BoundBreakStatement : public BoundStatement { public: [[nodiscard]] inline BoundStatementKind GetKind() const final { return BoundStatementKind::Break; } void GetTreeString(std::stringstream& stream, size_t indents) const final{ for (size_t i = 0; i < indents; i++) stream << "\t"; stream << "BreakStatement"; } }; class BoundBlockStatement : public BoundStatement { const vector<const BoundStatement *> _statements; public: explicit BoundBlockStatement(vector<const BoundStatement *> statements) : _statements(std::move(statements)) { } ~BoundBlockStatement() override { for (auto s : _statements) { delete s; } } [[nodiscard]] inline BoundStatementKind GetKind() const override { return BoundStatementKind::Block; } [[nodiscard]] inline const vector<const BoundStatement *> *GetStatements() const { return &_statements; } void GetTreeString(std::stringstream& stream, size_t indents) const override{ for (size_t i = 0; i < indents; i++) stream << "\t"; stream << "BlockStatement"; for (auto s : _statements){ stream << endl; s->GetTreeString(stream, indents + 1); } } }; class BoundScriptStatement : public BoundBlockStatement { const int _localVariableCount; public: explicit BoundScriptStatement(vector<const BoundStatement *> statements, int localVariableCount) : BoundBlockStatement(std::move(statements)), _localVariableCount(localVariableCount) { } [[nodiscard]] inline BoundStatementKind GetKind() const final { return BoundStatementKind::Script; } [[nodiscard]] inline int GetLocalVariableCount() const { return _localVariableCount; } }; class BoundExpressionStatement : public BoundStatement { const BoundExpression *_expression; public: explicit BoundExpressionStatement(BoundExpression *expression) : _expression(expression) { _expression = expression; } ~BoundExpressionStatement() final { delete _expression; } [[nodiscard]] inline BoundStatementKind GetKind() const final { return BoundStatementKind::Expression; } [[nodiscard]] inline const BoundExpression *GetExpression() const { return _expression; } void GetTreeString(std::stringstream& stream, size_t indents) const override{ for (size_t i = 0; i < indents; i++) stream << "\t"; stream << "ExpressionStatement" << endl; _expression->GetTreeString(stream, indents + 1); } }; class BoundAssignmentStatement : public BoundStatement { const BoundVariableKey *_key; const BoundExpression *_expression; public: BoundAssignmentStatement(const BoundVariableKey *key, BoundExpression *expression) : _key(key), _expression(expression) { } ~BoundAssignmentStatement() final { delete _key; delete _expression; } [[nodiscard]] inline BoundStatementKind GetKind() const final { return BoundStatementKind::Assignment; } [[nodiscard]] inline const BoundVariableKey *GetKey() const { return _key; } [[nodiscard]] inline const BoundExpression *GetExpression() const { return _expression; } void GetTreeString(std::stringstream& stream, size_t indents) const override{ for (size_t i = 0; i < indents; i++) stream << "\t"; stream << "Assignment -> " << _key->GetIdentifier()->GetString() << endl; _expression->GetTreeString(stream, indents + 1); } }; class BoundIndexAssignmentStatement : public BoundStatement { const BoundExpression *_indexExpression; const BoundExpression *_valueExpression; public: BoundIndexAssignmentStatement(const BoundExpression *index, BoundExpression *value) : _indexExpression(index), _valueExpression(value) { } ~BoundIndexAssignmentStatement() final { delete _indexExpression; delete _valueExpression; } [[nodiscard]] inline BoundStatementKind GetKind() const final { return BoundStatementKind::IndexAssignment; } [[nodiscard]] inline const BoundExpression *GetIndexExpression() const { return _indexExpression; } [[nodiscard]] inline const BoundExpression *GetValueExpression() const { return _valueExpression; } void GetTreeString(std::stringstream& stream, size_t indents) const override{ for (size_t i = 0; i < indents; i++) stream << "\t"; stream << "IndexAssignment" << endl; _indexExpression->GetTreeString(stream, indents + 1); stream << endl; _valueExpression->GetTreeString(stream, indents + 1); } }; class BoundReturnStatement : public BoundStatement { const BoundExpression *_expression; public: explicit BoundReturnStatement(BoundExpression *expression) : _expression(expression) { } ~BoundReturnStatement() final { delete _expression; } [[nodiscard]] inline BoundStatementKind GetKind() const final { return BoundStatementKind::Return; } [[nodiscard]] inline const BoundExpression *GetExpression() const { return _expression; } void GetTreeString(std::stringstream& stream, size_t indents) const override{ for (size_t i = 0; i < indents; i++) stream << "\t"; stream << "ReturnStatement" << endl; if (_expression != nullptr){ _expression->GetTreeString(stream, indents + 1); } } }; class BoundConditionalStatement : public BoundStatement { const BoundExpression *_condition; const BoundStatement *_block; const BoundStatement *_elseStatement; public: explicit BoundConditionalStatement(BoundExpression *condition, BoundStatement *block, BoundStatement *next) : _condition(condition), _block(block), _elseStatement(next) { } ~BoundConditionalStatement() final { delete _condition; delete _block; delete _elseStatement; } [[nodiscard]] inline BoundStatementKind GetKind() const final { return BoundStatementKind::Conditional; } [[nodiscard]] inline const BoundExpression *GetCondition() const { return _condition; } [[nodiscard]] inline const BoundStatement *GetBlock() const { return _block; } [[nodiscard]] inline const BoundStatement *GetElseStatement() const { return _elseStatement; } void GetTreeString(std::stringstream& stream, size_t indents) const override{ for (size_t i = 0; i < indents; i++) stream << "\t"; stream << "ConditionalStatement" << endl; for (size_t i = 0; i < indents; i++) stream << "\t"; stream << "Condition:" << endl; _condition->GetTreeString(stream, indents + 1); for (size_t i = 0; i < indents; i++) stream << "\t"; stream << "If True:" << endl; _block->GetTreeString(stream, indents + 1); if (_elseStatement != nullptr){ for (size_t i = 0; i < indents; i++) stream << "\t"; stream << "Else:" << endl; _elseStatement->GetTreeString(stream, indents + 1); } } }; class BoundNumericalForStatement : public BoundStatement { const BoundVariableKey* _identifier; const BoundExpression *_start; const BoundExpression *_end; const BoundExpression *_step; const BoundStatement *_block; public: explicit BoundNumericalForStatement(const BoundVariableKey* identifier, const BoundExpression *start, const BoundExpression *end, const BoundExpression *step, const BoundStatement *block) : _identifier(identifier), _start(start), _end(end), _step(step), _block(block) { } ~BoundNumericalForStatement() final { delete _identifier; delete _start; delete _end; delete _step; delete _block; } [[nodiscard]] inline BoundStatementKind GetKind() const final { return BoundStatementKind::NumericalFor; } [[nodiscard]] inline const BoundVariableKey* GetIdentifier() const{ return _identifier; } [[nodiscard]] inline const BoundExpression* GetStart() const{ return _start; } [[nodiscard]] inline const BoundExpression* GetEnd() const{ return _end; } [[nodiscard]] inline const BoundExpression* GetStep() const{ return _step; } [[nodiscard]] inline const BoundStatement* GetBlock() const{ return _block; } void GetTreeString(std::stringstream& stream, size_t indents) const override{ for (size_t i = 0; i < indents; i++) stream << "\t"; stream << "NumericForLoopStatement" << endl; for (size_t i = 0; i < indents; i++) stream << "\t"; stream << "Start:" << endl; _start->GetTreeString(stream, indents + 1); for (size_t i = 0; i < indents; i++) stream << "\t"; stream << "End:" << endl; _end->GetTreeString(stream, indents + 1); if (_step != nullptr){ for (size_t i = 0; i < indents; i++) stream << "\t"; stream << "Step:" << endl; _step->GetTreeString(stream, indents + 1); } for (size_t i = 0; i < indents; i++) stream << "\t"; stream << "Do:" << endl; _block->GetTreeString(stream, indents + 1); } }; class BoundGenericForStatement : public BoundStatement { const BoundVariableKey* _keyIdentifier; const BoundVariableKey* _valueIdentifier; const BoundExpression* _iterator; const BoundStatement *_block; public: explicit BoundGenericForStatement(const BoundVariableKey *keyIdentifier, const BoundVariableKey *valueIdentifier, const BoundExpression *iterator, const BoundStatement *block) : _keyIdentifier(keyIdentifier), _valueIdentifier(valueIdentifier), _iterator(iterator), _block(block) { } ~BoundGenericForStatement() final { delete _keyIdentifier; delete _valueIdentifier; delete _iterator; delete _block; } [[nodiscard]] inline BoundStatementKind GetKind() const final { return BoundStatementKind::GenericFor; } [[nodiscard]] inline const BoundVariableKey* GetKeyIdentifier() const{ return _keyIdentifier; } [[nodiscard]] inline const BoundVariableKey* GetValueIdentifier() const{ return _valueIdentifier; } [[nodiscard]] inline const BoundExpression* GetIterator() const{ return _iterator; } [[nodiscard]] inline const BoundStatement* GetBlock() const{ return _block; } void GetTreeString(std::stringstream& stream, size_t indents) const override{ for (size_t i = 0; i < indents; i++) stream << "\t"; stream << "GenericForLoopStatement" << endl; for (size_t i = 0; i < indents; i++) stream << "\t"; stream << "Key: " << _keyIdentifier->GetIdentifier()->GetString().get() << endl; for (size_t i = 0; i < indents; i++) stream << "\t"; stream << "Value: " << _valueIdentifier->GetIdentifier()->GetString().get() << endl; stream << "Iterator: " << endl; _iterator->GetTreeString(stream, indents + 1); stream << endl; _block->GetTreeString(stream, indents + 1); } }; class BoundWhileStatement : public BoundStatement { const BoundExpression* _condition; const BoundStatement *_block; public: explicit BoundWhileStatement(const BoundExpression *condition, const BoundStatement *block) : _condition(condition), _block(block) { } ~BoundWhileStatement() final { delete _condition; delete _block; } [[nodiscard]] inline BoundStatementKind GetKind() const final { return BoundStatementKind::While; } [[nodiscard]] inline const BoundExpression* GetCondition() const{ return _condition; } [[nodiscard]] inline const BoundStatement* GetBlock() const{ return _block; } void GetTreeString(std::stringstream& stream, size_t indents) const override{ for (size_t i = 0; i < indents; i++) stream << "\t"; stream << "ConditionalStatement" << endl; for (size_t i = 0; i < indents; i++) stream << "\t"; stream << "Condition:" << endl; _condition->GetTreeString(stream, indents + 1); for (size_t i = 0; i < indents; i++) stream << "\t"; stream << "While True:" << endl; _block->GetTreeString(stream, indents + 1); } }; } #include "BoundFunctionDeclarationStatement.hpp" #endif //PORYGONLANG_BOUNDSTATEMENT_HPP