diff --git a/include/syntax_tree.hpp b/include/syntax_tree.hpp index 784ddc4..106354b 100644 --- a/include/syntax_tree.hpp +++ b/include/syntax_tree.hpp @@ -18,6 +18,7 @@ struct Node { void Insert(Node*); void InsertBefore(Node*); virtual void Run(std::vector>& stack) = 0; + virtual ~Node() {} }; @@ -54,241 +55,62 @@ struct TypeVariable { }; TypeVariable() {} + TypeVariable(ID id) : id(id) {} + ID id = ID::none; size_t size; }; struct DeallocateStack : public Node { DeallocateStack(size_t count) : count(count) {} - void Run(std::vector>& stack) override { - for (size_t i = 0; i < count; ++i) { - stack.pop_back(); - } - } + + void Run(std::vector>& stack) override; + size_t count; }; struct HiddenDeallocateStack : public Node { HiddenDeallocateStack(size_t count) : count(count) {} - void Run(std::vector>& stack) override { - for (size_t i = 0; i < count; ++i) { - stack.pop_back(); - } - } + + void Run(std::vector>& stack) override; + size_t count; }; struct VariableInStack { VariableInStack(TypeVariable type_variable) : type_variable(type_variable) {} - void CallOperator(std::shared_ptr& another, std::shared_ptr& result, Operation op) { - if (op == Operation::Equal || op == Operation::PlusEqual || op == Operation::MinusEqual || op == Operation::StarEqual || op == Operation::SlashEqual) { - if (type_variable.id != TypeVariable::ID::none && type_variable.id != another->type_variable.id) { - throw std::logic_error("error variable convert"); - } - if (result->type_variable.id != TypeVariable::ID::none && result->type_variable.id != another->type_variable.id) { - throw std::logic_error("error variable convert"); - } - result->Clear(); - result->type_variable.id = another->type_variable.id; - result->Allocate(); - if (op == Operation::Equal) { - Clear(); - type_variable.id = another->type_variable.id; - Allocate(); - } - if (another->type_variable.id == TypeVariable::ID::type_int) { - int& x = *static_cast(memory); - int& y = *static_cast(another->memory); - int& res = *static_cast(result->memory); - if (op == Operation::Equal) { - if (this == another.get()) { - res = x; - } else { - res = x = y; - } - } else if (op == Operation::PlusEqual) { - if (this == another.get()) { - res += x; - } else { - res = x += y; - } - } else if (op == Operation::MinusEqual) { - if (this == another.get()) { - res -= x; - } else { - res = x -= y; - } - } else if (op == Operation::StarEqual) { - if (this == another.get()) { - res *= x; - } else { - res = x *= y; - } - } else { - if (this == another.get()) { - res /= x; - } else { - res = x /= y; - } - } - } else if (another->type_variable.id == TypeVariable::ID::type_string) { - std::string& x = *static_cast(memory); - std::string& y = *static_cast(another->memory); - std::string& res = *static_cast(result->memory); - if (op == Operation::Equal) { - if (this == another.get()) { - res = x; - } else { - res = x = y; - } - } else if (op == Operation::PlusEqual) { - if (this == another.get()) { - res += x; - } else { - res = x += y; - } - } else { - throw std::logic_error("invalid operation string"); - } - } - return; - } else if (op == Operation::EqualEqual || op == Operation::ExclamationMarkEqual || op == Operation::LAngle || op == Operation::RAngle || op == Operation::LAngleEqual || op == Operation::RAngleEqual) { - result->Clear(); - result->type_variable.id = TypeVariable::ID::type_int; - result->Allocate(); - int& res = *static_cast(result->memory); - if (another->type_variable.id == TypeVariable::ID::type_int && type_variable.id == TypeVariable::ID::type_int) { - auto& x = *static_cast(memory); - auto& y = *static_cast(another->memory); - if (op == Operation::EqualEqual) { - res = (x == y); - } else if (op == Operation::ExclamationMarkEqual) { - res = (x != y); - } else if (op == Operation::LAngle) { - res = (x < y); - } else if (op == Operation::RAngle) { - res = (x > y); - } else if (op == Operation::LAngleEqual) { - res = (x <= y); - } else if (op == Operation::RAngleEqual) { - res = (x >= y); - } - } else if (another->type_variable.id == TypeVariable::ID::type_string && type_variable.id == TypeVariable::ID::type_string) { - auto& x = *static_cast(memory); - auto& y = *static_cast(another->memory); - if (op == Operation::EqualEqual) { - res = (x == y); - } else if (op == Operation::ExclamationMarkEqual) { - res = (x != y); - } else if (op == Operation::LAngle) { - res = (x < y); - } else if (op == Operation::RAngle) { - res = (x > y); - } else if (op == Operation::LAngleEqual) { - res = (x <= y); - } else if (op == Operation::RAngleEqual) { - res = (x >= y); - } - } - } else if (op == Operation::Plus || op == Operation::Minus || op == Operation::Star || op == Operation::Slash) { - result->Clear(); - result->type_variable.id = another->type_variable.id; - result->Allocate(); - if (another->type_variable.id == TypeVariable::ID::type_int && type_variable.id == TypeVariable::ID::type_int) { - int& x = *static_cast(memory); - int& y = *static_cast(another->memory); - int& res = *static_cast(result->memory); - if (op == Operation::Plus) { - res = (x + y); - } else if (op == Operation::Minus) { - res = (x - y); - } else if (op == Operation::Star) { - res = (x * y); - } else if (op == Operation::Slash) { - res = (x / y); - } - } else if (another->type_variable.id == TypeVariable::ID::type_string && type_variable.id == TypeVariable::ID::type_string) { - std::string& x = *static_cast(memory); - std::string& y = *static_cast(another->memory); - std::string& res = *static_cast(result->memory); - if (op == Operation::Plus) { - res = (x + y); - } - } - } - return; + void CallOperator(std::shared_ptr& another, std::shared_ptr& result, Operation op); + void Clear(); + void Allocate(); - - - - if (type_variable.id == TypeVariable::ID::type_int) { - int& x = *static_cast(memory); - if (another->type_variable.id == TypeVariable::ID::type_int) { - int& y = *static_cast(another->memory); - result->type_variable.id = TypeVariable::ID::type_int; - result->Clear(); - result->Allocate(); - int& res = *static_cast(result->memory); - if (op == Operation::Equal) { - /* - if (this == &another) - res = y; - else - x = res = y; - */ - } else if (op == Operation::Plus) { - res = x + y; - } else if (op == Operation::Star) { - res = x * y; - } else if (op == Operation::LAngle) { - res = x < y; - } - } - } else if (type_variable.id == TypeVariable::ID::type_string) { - using std::string; - string& x = *static_cast(memory); - if (another->type_variable.id == TypeVariable::ID::type_string) { - string& y = *static_cast(another->memory); - result->type_variable.id = TypeVariable::ID::type_string; - result->Clear(); - result->Allocate(); - string& res = *static_cast(result->memory); - if (op == Operation::Equal) { - if (this == another.get()) - res = y; - else - x = res = y; - } - } - } - } - void Clear() { - if (memory) { - if (type_variable.id == TypeVariable::ID::type_int) { - delete static_cast(memory); - } else if (type_variable.id == TypeVariable::ID::type_string) { - delete static_cast(memory); - } - } - memory = nullptr; - } - void Allocate() { - if (type_variable.id == TypeVariable::ID::type_int) { - memory = new int(15); - } else if (type_variable.id == TypeVariable::ID::type_string) { - memory = new std::string("lkajsdf"); - } - } TypeVariable type_variable; void* memory = nullptr; + private: + + void CallEqualOperator(const std::shared_ptr& another, + std::shared_ptr& result, + const Operation& op); + void CallComparisonOperator(const std::shared_ptr& another, + std::shared_ptr& result, + const Operation& op) const; + void CallArithmeticOperator(const std::shared_ptr& another, + std::shared_ptr& result, + const Operation& op) const; + void CallEqualOperatorInt(const std::shared_ptr& another, + const std::shared_ptr& result, + const Operation& op) const; + void CallEqualOperatorString(const std::shared_ptr& another, + const std::shared_ptr& result, + const Operation& op) const; }; struct Variable : public Node { Variable(std::string type, std::string name) : type(std::move(type)), name(std::move(name)) {} + void Run(std::vector>& stack) override; std::string type; std::string name; @@ -299,13 +121,8 @@ struct Variable : public Node { struct Container : public Node { void AddChildren(Node*); - void Run(std::vector>& stack) override { - Node* cur = children_begin; - while (cur) { - cur->Run(stack); - cur = cur->next; - } - } + + void Run(std::vector>& stack) override; Node* children_begin = nullptr; Node* children_end = nullptr; @@ -313,26 +130,17 @@ struct Container : public Node { struct CodeBlock : public Container {}; -struct Function : public Node { - Function(const std::string& name) : name(name), code(new CodeBlock()) {} - Function(std::string&& name) : name(name) {} - void Run(std::vector>& stack) override { - code->Run(stack); - // TODO - } - std::string name; - CodeBlock* code; - // RETURN VALUE -}; - struct CreateVariables : Node { CreateVariables(size_t count) : count(count) {} + void Run(std::vector>& stack) override {} + size_t count; }; struct CallFunction : public Node { CallFunction(std::string name_function) : name_function(std::move(name_function)) {} + void Run(std::vector>& stack) override; std::string name_function; std::vector parameters; @@ -342,52 +150,15 @@ using stack_pointer = size_t; struct Expression : public Node { using Types = std::variant; - Expression() {} - Expression(Types type1, Types type2, Operation op) : type1(std::move(type1)), type2(std::move(type2)), op(op) { - if (op == Operation::Value) { - count = 1; - } else { - count = 1; - auto e_type1 = std::get(type1); - auto e_type2 = std::get(type2); - count += e_type1->count; - count += e_type2->count; - position_result = count; - e_type2->AddStackPointer(e_type1->count); - } - } - void AddStackPointer(stack_pointer d) { - position_result += d; - } - void Run(std::vector>& stack) override { - if (op == Operation::Value) { - if (std::holds_alternative(type1)) { - stack.push_back(*(stack.end() - std::get(type1))); - } else { - stack.push_back(std::make_shared(TypeVariable())); - if (std::get(type1)[0] == '\"') { - stack.back()->type_variable = TypeVariable(TypeVariable::ID::type_string); - stack.back()->Allocate(); - (*(std::string*) stack.back()->memory) = - std::get(type1).substr(1, std::get(type1).size() - 2); - } else { - stack.back()->type_variable = TypeVariable(TypeVariable::ID::type_int); - stack.back()->Allocate(); - (*(int*) stack.back()->memory) = std::atoi(std::get(type1).c_str()); - } - } - } else { - std::get(type1)->Run(stack); - std::shared_ptr x = std::move(stack.back()); - stack.pop_back(); - std::get(type2)->Run(stack); - std::shared_ptr y = std::move(stack.back()); - stack.pop_back(); - stack.push_back(std::make_shared(TypeVariable())); - x->CallOperator(y, stack.back(), op); - } - } + Expression() {} + + Expression(Types type1, Types type2, Operation op); + + void AddStackPointer(stack_pointer d); + + void Run(std::vector>& stack) override; + static size_t GetPriority(Operation); static PriorityType GetPriorityType(Operation); static Operation Convert(Lexer::LexerToken::Type); @@ -397,59 +168,25 @@ struct Expression : public Node { size_t count; }; -struct FOR : public Node { - void Run(std::vector>& stack) override { - while (true) { - check->Run(stack); - auto res = *((int*) stack.back()->memory); - stack.pop_back(); - if (!res) { - break; - } - code->Run(stack); - size_t sz = stack.size(); - tick->Run(stack); - while (stack.size() != sz) { - stack.pop_back(); - } - } - } +struct BlockFor : public Node { + void Run(std::vector>& stack) override; + Variable* var = nullptr; Expression* check = nullptr; Expression* tick = nullptr; CodeBlock* code = nullptr; }; -struct IF : public Node { - void Run(std::vector>& stack) override { - if (check) { - check->Run(stack); - auto res = *((int*) stack.back()->memory); - stack.pop_back(); - if (res) { - code->Run(stack); - } - } - } +struct BlockIf : public Node { + void Run(std::vector>& stack) override; + Expression* check = nullptr; CodeBlock* code = nullptr; }; -struct WHILE : public Node { - void Run(std::vector>& stack) override { - if (check) { - while (true) { - check->Run(stack); - auto res = *((int*) stack.back()->memory); - stack.pop_back(); - if (res) { - code->Run(stack); - } else { - break; - } - } - } - } +struct BlockWhile : public Node { + void Run(std::vector>& stack) override; + Expression* check = nullptr; CodeBlock* code = nullptr; }; @@ -457,6 +194,7 @@ struct WHILE : public Node { class SyntaxTree { public: SyntaxTree() {} + void PushLexerTokenList(const LexerTokenList&); void Compile(); void Run(); @@ -474,12 +212,12 @@ class SyntaxTree { void PushExpression(Container*, const LexerTokenList&, LexerTokenList::const_iterator&); void PushParametersFunction(CallFunction*, const LexerTokenList&, LexerTokenList::const_iterator&); void PushCallFunction(Container*, const LexerTokenList&, LexerTokenList::const_iterator&); - void PushFOR(Container*, const LexerTokenList&, LexerTokenList::const_iterator&); - void PushSignatureFOR(FOR*, const LexerTokenList&, LexerTokenList::const_iterator&); - void PushIF(Container*, const LexerTokenList&, LexerTokenList::const_iterator&); - void PushSignatureIF(IF*, const LexerTokenList&, LexerTokenList::const_iterator&); - void PushWHILE(Container*, const LexerTokenList&, LexerTokenList::const_iterator&); - void PushSignatureWHILE(WHILE*, const LexerTokenList&, LexerTokenList::const_iterator&); + void PushBlockFor(Container* container, const LexerTokenList& list, LexerTokenList::const_iterator& it); + void PushSignatureBlockFor(BlockFor* node_for, const LexerTokenList& list, LexerTokenList::const_iterator& it); + void PushBlockIf(Container* container, const LexerTokenList& list, LexerTokenList::const_iterator& it); + void PushSignatureBlockIf(BlockIf* node_if, const LexerTokenList& list, LexerTokenList::const_iterator& it); + void PushBlockWhile(Container* container, const LexerTokenList& list, LexerTokenList::const_iterator& it); + void PushSignatureBlockWhile(BlockWhile* node_if, const LexerTokenList& list, LexerTokenList::const_iterator& it); Expression* ParseExpression(LexerTokenList::const_iterator, LexerTokenList::const_iterator); Expression* ParseExpression(const LexerTokenList&, LexerTokenList::const_iterator&); void PushDeallocateStack(Node*, size_t); diff --git a/src/preprocessor.cpp b/src/preprocessor.cpp index 536c96b..9c1b389 100644 --- a/src/preprocessor.cpp +++ b/src/preprocessor.cpp @@ -1,8 +1,6 @@ #include "preprocessor.hpp" #include -#include // TODO - std::string DeleteComments(std::string&& text) { std::vector> text_without_comments; size_t n = text.size(); diff --git a/src/syntax_tree.cpp b/src/syntax_tree.cpp index f622338..185b372 100644 --- a/src/syntax_tree.cpp +++ b/src/syntax_tree.cpp @@ -6,8 +6,6 @@ using Type = Lexer::LexerToken::Type; -std::unordered_set special_words = {"def"}; - bool IsOperation(Type type) { switch (type) { case Type::Equal: @@ -72,6 +70,14 @@ void Container::AddChildren(Node* node) { } } +void Container::Run(std::vector>& stack) { + Node* current = children_begin; + while (current) { + current->Run(stack); + current = current->next; + } +} + size_t Expression::GetPriority(Operation op) { switch (op) { case Operation::Equal: @@ -147,6 +153,54 @@ PriorityType Expression::GetPriorityType(Operation op) { throw std::logic_error("unsupported operator"); } +void Expression::Run(std::vector>& stack) { + if (op == Operation::Value) { + if (std::holds_alternative(type1)) { + stack.push_back(*(stack.end() - std::get(type1))); + } else { + stack.push_back(std::make_shared(TypeVariable())); + if (std::get(type1)[0] == '\"') { + stack.back()->type_variable = TypeVariable(TypeVariable::ID::type_string); + stack.back()->Allocate(); + (*(std::string*) stack.back()->memory) = + std::get(type1).substr(1, std::get(type1).size() - 2); + } else { + stack.back()->type_variable = TypeVariable(TypeVariable::ID::type_int); + stack.back()->Allocate(); + (*(int*) stack.back()->memory) = std::atoi(std::get(type1).c_str()); + } + } + } else { + std::get(type1)->Run(stack); + std::shared_ptr x = std::move(stack.back()); + stack.pop_back(); + std::get(type2)->Run(stack); + std::shared_ptr y = std::move(stack.back()); + stack.pop_back(); + stack.push_back(std::make_shared(TypeVariable())); + x->CallOperator(y, stack.back(), op); + } +} + +void Expression::AddStackPointer(stack_pointer d) { + position_result += d; +} + +Expression::Expression(Expression::Types type1, Expression::Types type2, Operation op) : type1(std::move(type1)), type2(std::move(type2)), op(op) { + if (op == Operation::Value) { + count = 1; + } else { + count = 1; + auto e_type1 = std::get(type1); + auto e_type2 = std::get(type2); + count += e_type1->count; + count += e_type2->count; + + position_result = count; + e_type2->AddStackPointer(e_type1->count); + } +} + bool SyntaxTree::IsTypeName(Node* node, const std::string& str) { return str == "int" || str == "string"; } @@ -198,78 +252,18 @@ void SyntaxTree::PushCurlyBrackets(Container* container, const LexerTokenList& l container->AddChildren(ParseCurlyBrackets(container, list, it)); } -/* -void SyntaxTree::PushRoundBrackets(Container* container, const LexerTokenList& list, - LexerTokenList::const_iterator& it) { - RoundBrackets* current = new RoundBrackets(); - container->AddChildren(current); - - for (; it->type != Type::RoundCloseBracket; ++it) { - if (it->type == Type::Word) { - if (IsTypeName(container->children_end, it->info)) { - std::string type = it->info; - ++it; - if (it->type == Type::Word) { - container->AddChildren(new Variable(std::move(type), it->info)); - } - } else if (IsVariableName(container->children_end, it->info)) { - ++it; - // TODO - } - } else { - throw std::logic_error("I expected type or name"); - } - } -} - */ - -/* -void SyntaxTree::PushFunction(Container* container, const LexerTokenList& list, - LexerTokenList::const_iterator& it) { - if (it->type == Type::Word && !IsSpecialWord(it->info)) { - auto func = new Function(it->info); - ++it; - if (it->type == Type::RoundOpenBracket) { - PushRoundBrackets(func->parameters, list, ++it); - ++it; - if (it->type == Type::RArrow) { - ++it; - if (it->type == Type::Word && IsTypeName(container->children_end, it->info)) { - ++it; - if (it->type == Type::CurlyOpenBracket) { - PushCurlyBrackets(func->code, list, ++it); - container->AddChildren(func); - } else { - throw std::logic_error("Invalid function body"); - } - } else { - throw std::logic_error("Invalit return type"); - } - } else { - throw std::logic_error("Missing -> in function"); - } - } else { - throw std::logic_error("Invalid function parameters"); - } - } else { - throw std::logic_error("Invalid function name"); - } -} - */ - void SyntaxTree::PushLine(Container* container, const LexerTokenList& list, LexerTokenList::const_iterator& it) { if (it->type == Type::CurlyOpenBracket) { PushCurlyBrackets(container, list, ++it); } else if (it->type == Type::RoundOpenBracket) { PushExpression(container, list, it); - // PushRoundBrackets(container, list, ++it); } else if (it->type == Type::IF) { - PushIF(container, list, it); + PushBlockIf(container, list, it); } else if (it->type == Type::FOR) { - PushFOR(container, list, it); + PushBlockFor(container, list, it); } else if (it->type == Type::WHILE) { - PushWHILE(container, list, it); + PushBlockWhile(container, list, it); } else if (it->type == Type::Word) { auto place = container->children_end; if (!place) @@ -350,13 +344,13 @@ void SyntaxTree::PushCallFunction(Container* container, container->AddChildren(new HiddenDeallocateStack(function->parameters.size())); } -void SyntaxTree::PushFOR(Container* container, - const LexerTokenList& list, - std::list::const_iterator& it) { +void SyntaxTree::PushBlockFor(Container* container, + const LexerTokenList& list, + std::list::const_iterator& it) { auto c = new Container; - auto f = new FOR(); + auto f = new BlockFor(); container->AddChildren(c); - PushSignatureFOR(f, list, ++it); + PushSignatureBlockFor(f, list, ++it); c->AddChildren(f->var); c->AddChildren(f); if (it->type != Type::CurlyOpenBracket) { @@ -367,9 +361,9 @@ void SyntaxTree::PushFOR(Container* container, f->code->previous = nullptr; } -void SyntaxTree::PushSignatureFOR(FOR* node_for, - const LexerTokenList& list, - std::list::const_iterator& it) { +void SyntaxTree::PushSignatureBlockFor(BlockFor* node_for, + const LexerTokenList& list, + std::list::const_iterator& it) { if (it->type != Type::RoundOpenBracket) throw std::logic_error("expected ( after for"); ++it; @@ -408,12 +402,12 @@ void SyntaxTree::PushSignatureFOR(FOR* node_for, } } -void SyntaxTree::PushIF(Container* container, - const LexerTokenList& list, - std::list::const_iterator& it) { - auto f = new IF(); +void SyntaxTree::PushBlockIf(Container* container, + const LexerTokenList& list, + std::list::const_iterator& it) { + auto f = new BlockIf(); container->AddChildren(f); - PushSignatureIF(f, list, ++it); + PushSignatureBlockIf(f, list, ++it); f->check->parent = f; if (it->type != Type::CurlyOpenBracket) { throw std::logic_error("expected { after if (...)"); @@ -422,9 +416,9 @@ void SyntaxTree::PushIF(Container* container, f->code->parent = f; } -void SyntaxTree::PushSignatureIF(IF* node_if, - const LexerTokenList& list, - std::list::const_iterator& it) { +void SyntaxTree::PushSignatureBlockIf(BlockIf* node_if, + const LexerTokenList& list, + std::list::const_iterator& it) { if (it->type != Type::RoundOpenBracket) throw std::logic_error("expected ( after if"); ++it; @@ -436,21 +430,21 @@ void SyntaxTree::PushSignatureIF(IF* node_if, ++it; } -void SyntaxTree::PushWHILE(Container* container, - const LexerTokenList& list, - std::list::const_iterator& it) { - auto f = new WHILE(); +void SyntaxTree::PushBlockWhile(Container* container, + const LexerTokenList& list, + std::list::const_iterator& it) { + auto f = new BlockWhile(); container->AddChildren(f); - PushSignatureWHILE(f, list, ++it); + PushSignatureBlockWhile(f, list, ++it); if (it->type != Type::CurlyOpenBracket) { throw std::logic_error("expected { after while (...)"); } f->code = ParseCurlyBrackets(container, list, ++it); } -void SyntaxTree::PushSignatureWHILE(WHILE* node_if, - const LexerTokenList& list, - std::list::const_iterator& it) { +void SyntaxTree::PushSignatureBlockWhile(BlockWhile* node_if, + const LexerTokenList& list, + std::list::const_iterator& it) { if (it->type != Type::RoundOpenBracket) throw std::logic_error("expected ( after while"); ++it; @@ -539,10 +533,10 @@ void SyntaxTree::PushDeallocateStack(Node* node, size_t count_variables = 0) { PushDeallocateStack(code_block->children_begin); } } - if (auto if_ = dynamic_cast(node)) { + if (auto if_ = dynamic_cast(node)) { PushDeallocateStack(if_->code); } - if (auto for_ = dynamic_cast(node)) { + if (auto for_ = dynamic_cast(node)) { PushDeallocateStack(for_->code); } if (dynamic_cast(node)) { @@ -580,15 +574,15 @@ void SyntaxTree::LinkVariables(Node* node) { LinkVariablesInExpression(var->default_value, node); } } - if (auto if_ = dynamic_cast(node)) { + if (auto if_ = dynamic_cast(node)) { LinkVariablesInExpression(if_->check, node); LinkVariables(if_->code->children_begin); } - if (auto while_ = dynamic_cast(node)) { + if (auto while_ = dynamic_cast(node)) { LinkVariablesInExpression(while_->check, node); LinkVariables(while_->code->children_begin); } - if (auto for_ = dynamic_cast(node)) { + if (auto for_ = dynamic_cast(node)) { LinkVariablesInExpression(for_->check, node); LinkVariablesInExpression(for_->tick, node); LinkVariables(for_->code->children_begin); @@ -678,3 +672,256 @@ void Variable::Run(std::vector>& stack) { stack.pop_back(); } } + +void VariableInStack::CallOperator(std::shared_ptr& another, + std::shared_ptr& result, + Operation op) { + if (op == Operation::Equal || op == Operation::PlusEqual || op == Operation::MinusEqual + || op == Operation::StarEqual || op == Operation::SlashEqual) { + CallEqualOperator(another, result, op); + return; + } + if (op == Operation::EqualEqual || op == Operation::ExclamationMarkEqual || op == Operation::LAngle + || op == Operation::RAngle || op == Operation::LAngleEqual || op == Operation::RAngleEqual) { + CallComparisonOperator(another, result, op); + return; + } + if (op == Operation::Plus || op == Operation::Minus || op == Operation::Star || op == Operation::Slash) { + CallArithmeticOperator(another, result, op); + return; + } +} + +void VariableInStack::CallArithmeticOperator(const std::shared_ptr& another, + std::shared_ptr& result, + const Operation& op) const { + result->Clear(); + result->type_variable.id = another->type_variable.id; + result->Allocate(); + if (another->type_variable.id == TypeVariable::type_int && type_variable.id == TypeVariable::type_int) { + int& x = *static_cast(memory); + int& y = *static_cast(another->memory); + int& res = *static_cast(result->memory); + if (op == Operation::Plus) { + res = (x + y); + } else if (op == Operation::Minus) { + res = (x - y); + } else if (op == Operation::Star) { + res = (x * y); + } else if (op == Operation::Slash) { + res = (x / y); + } + } else if (another->type_variable.id == TypeVariable::type_string + && type_variable.id == TypeVariable::type_string) { + std::string& x = *static_cast(memory); + std::string& y = *static_cast(another->memory); + std::string& res = *static_cast(result->memory); + if (op == Operation::Plus) { + res = (x + y); + } + } +} + +void VariableInStack::CallComparisonOperator(const std::shared_ptr& another, + std::shared_ptr& result, + const Operation& op) const { + result->Clear(); + result->type_variable.id = TypeVariable::type_int; + result->Allocate(); + int& res = *static_cast(result->memory); + + if (another->type_variable.id == TypeVariable::type_int && type_variable.id == TypeVariable::type_int) { + auto& x = *static_cast(memory); + auto& y = *static_cast(another->memory); + if (op == Operation::EqualEqual) { + res = (x == y); + } else if (op == Operation::ExclamationMarkEqual) { + res = (x != y); + } else if (op == Operation::LAngle) { + res = (x < y); + } else if (op == Operation::RAngle) { + res = (x > y); + } else if (op == Operation::LAngleEqual) { + res = (x <= y); + } else if (op == Operation::RAngleEqual) { + res = (x >= y); + } + } else if (another->type_variable.id == TypeVariable::type_string + && type_variable.id == TypeVariable::type_string) { + auto& x = *static_cast(memory); + auto& y = *static_cast(another->memory); + if (op == Operation::EqualEqual) { + res = (x == y); + } else if (op == Operation::ExclamationMarkEqual) { + res = (x != y); + } else if (op == Operation::LAngle) { + res = (x < y); + } else if (op == Operation::RAngle) { + res = (x > y); + } else if (op == Operation::LAngleEqual) { + res = (x <= y); + } else if (op == Operation::RAngleEqual) { + res = (x >= y); + } + } +} + +void VariableInStack::CallEqualOperator(const std::shared_ptr& another, + std::shared_ptr& result, + const Operation& op) { + if (type_variable.id != TypeVariable::none && type_variable.id != another->type_variable.id) { + throw std::logic_error("error variable convert"); + } + if (result->type_variable.id != TypeVariable::none && result->type_variable.id != another->type_variable.id) { + throw std::logic_error("error variable convert"); + } + result->Clear(); + result->type_variable.id = another->type_variable.id; + result->Allocate(); + if (op == Operation::Equal) { + Clear(); + type_variable.id = another->type_variable.id; + Allocate(); + } + if (another->type_variable.id == TypeVariable::type_int) { + CallEqualOperatorInt(another, result, op); + } else if (another->type_variable.id == TypeVariable::type_string) { + CallEqualOperatorString(another, result, op); + } +} + +void VariableInStack::CallEqualOperatorString(const std::shared_ptr& another, + const std::shared_ptr& result, + const Operation& op) const { + std::string& x = *static_cast(memory); + std::string& y = *static_cast(another->memory); + std::string& res = *static_cast(result->memory); + if (op == Operation::Equal) { + if (this == another.get()) { + res = x; + } else { + res = x = y; + } + } else if (op == Operation::PlusEqual) { + if (this == another.get()) { + res += x; + } else { + res = x += y; + } + } else { + throw std::logic_error("invalid operation string"); + } +} + +void VariableInStack::CallEqualOperatorInt(const std::shared_ptr& another, + const std::shared_ptr& result, + const Operation& op) const { + int& x = *static_cast(memory); + int& y = *static_cast(another->memory); + int& res = *static_cast(result->memory); + if (op == Operation::Equal) { + if (this == another.get()) { + res = x; + } else { + res = x = y; + } + } else if (op == Operation::PlusEqual) { + if (this == another.get()) { + res += x; + } else { + res = x += y; + } + } else if (op == Operation::MinusEqual) { + if (this == another.get()) { + res -= x; + } else { + res = x -= y; + } + } else if (op == Operation::StarEqual) { + if (this == another.get()) { + res *= x; + } else { + res = x *= y; + } + } else { + if (this == another.get()) { + res /= x; + } else { + res = x /= y; + } + } +} + +void VariableInStack::Clear() { + if (memory) { + if (type_variable.id == TypeVariable::ID::type_int) { + delete static_cast(memory); + } else if (type_variable.id == TypeVariable::ID::type_string) { + delete static_cast(memory); + } + } + memory = nullptr; +} + +void VariableInStack::Allocate() { + if (type_variable.id == TypeVariable::ID::type_int) { + memory = new int(); + } else if (type_variable.id == TypeVariable::ID::type_string) { + memory = new std::string(); + } +} + +void BlockWhile::Run(std::vector>& stack) { + if (check) { + while (true) { + check->Run(stack); + auto res = *((int*) stack.back()->memory); + stack.pop_back(); + if (res) { + code->Run(stack); + } else { + break; + } + } + } +} + +void BlockIf::Run(std::vector>& stack) { + if (check) { + check->Run(stack); + auto res = *((int*) stack.back()->memory); + stack.pop_back(); + if (res) { + code->Run(stack); + } + } +} + +void BlockFor::Run(std::vector>& stack) { + while (true) { + check->Run(stack); + auto res = *((int*) stack.back()->memory); + stack.pop_back(); + if (!res) { + break; + } + code->Run(stack); + size_t sz = stack.size(); + tick->Run(stack); + while (stack.size() != sz) { + stack.pop_back(); + } + } +} + +void HiddenDeallocateStack::Run(std::vector>& stack) { + for (size_t i = 0; i < count; ++i) { + stack.pop_back(); + } +} + +void DeallocateStack::Run(std::vector>& stack) { + for (size_t i = 0; i < count; ++i) { + stack.pop_back(); + } +}