shushus

Спринт 16. Реализация интерпретатора.

Jun 22nd, 2023
633
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 130.13 KB | None | 0 0
  1. -----------------------------------------------------------------------
  2. lexer.h
  3. -----------------------------------------------------------------------
  4. #pragma once
  5.  
  6. #include <sstream>
  7. #include <stdexcept>
  8. #include <string>
  9. #include <variant>
  10. #include <vector>
  11. #include <map>
  12.  
  13. namespace parse {
  14. namespace token_type {
  15.    
  16. struct Number {int value;};
  17. struct Id {std::string value;};
  18. struct Char {char value;};
  19. struct String {std::string value;};
  20.  
  21. struct Class {};
  22. struct Return {};
  23. struct If {};
  24. struct Else {};
  25. struct Def {};
  26. struct Newline {};
  27. struct Print {};
  28. struct Indent {};
  29. struct Dedent {};
  30. struct Eof {};
  31. struct And {};
  32. struct Or {};
  33. struct Not {};
  34. struct Eq {};
  35. struct NotEq {};
  36. struct LessOrEq {};
  37. struct GreaterOrEq {};
  38. struct None {};
  39. struct True {};
  40. struct False {};
  41.  
  42. }//end namespace token_type
  43.  
  44. using TokenBase = std::variant<token_type::Number,
  45.                                token_type::Id,
  46.                                token_type::Char,
  47.                                token_type::String,
  48.                                token_type::Class,
  49.                                token_type::Return,     
  50.                                token_type::If,
  51.                                token_type::Else,
  52.                                token_type::Def,
  53.                                token_type::Newline,
  54.                                token_type::Print,
  55.                                token_type::Indent,
  56.                                token_type::Dedent,
  57.                                token_type::And,
  58.                                token_type::Or,
  59.                                token_type::Not,
  60.                                token_type::Eq,
  61.                                token_type::NotEq,      
  62.                                token_type::LessOrEq,
  63.                                token_type::GreaterOrEq,
  64.                                token_type::None,   
  65.                                token_type::True,
  66.                                token_type::False,
  67.                                token_type::Eof>;
  68.  
  69. struct Token : TokenBase {
  70.     using TokenBase::TokenBase;
  71.  
  72.     template <typename T>
  73.     [[nodiscard]] bool Is() const {return std::holds_alternative<T>(*this);}
  74.  
  75.     template <typename T>
  76.     [[nodiscard]] const T& As() const {return std::get<T>(*this);}
  77.  
  78.     template <typename T>
  79.     [[nodiscard]] const T* TryAs() const {return std::get_if<T>(this);}
  80. };
  81.  
  82. bool operator==(const Token& lhs, const Token& rhs);
  83. bool operator!=(const Token& lhs, const Token& rhs);
  84.  
  85. std::ostream& operator<<(std::ostream& os, const Token& rhs);
  86.  
  87. class LexerError : public std::runtime_error {
  88.     public:
  89.         using std::runtime_error::runtime_error;
  90. };
  91.  
  92. class Lexer {
  93.    
  94.     public:
  95.  
  96.         explicit Lexer(std::istream& input);
  97.  
  98.         [[nodiscard]] const Token& CurrentToken() const;
  99.         Token NextToken();
  100.  
  101.         template <typename T>
  102.         const T& Expect() const {
  103.        
  104.             using namespace std::literals;
  105.        
  106.             if (CurrentToken().Is<T>()) {
  107.                 return CurrentToken().As<T>();
  108.            
  109.             } else {
  110.                 throw LexerError("expectation error");
  111.             }        
  112.         }
  113.  
  114.         template <typename T, typename U>
  115.         void Expect(const U& value) const {
  116.        
  117.             using namespace std::literals;
  118.        
  119.             try {
  120.            
  121.                 if (CurrentToken().As<T>().value != value) {
  122.                     throw LexerError("expectation error");
  123.                 } else {
  124.                     return;
  125.                 }
  126.            
  127.             } catch (std::bad_variant_access&) {
  128.                 throw LexerError("expectation error");
  129.             }
  130.         }
  131.  
  132.         template <typename T>
  133.         const T& ExpectNext() {
  134.             NextToken();
  135.             return Expect<T>();
  136.         }
  137.  
  138.         template <typename T, typename U>
  139.         void ExpectNext(const U& value) {
  140.             NextToken();
  141.             Expect<T>(value);
  142.         }
  143.  
  144.     private:
  145.  
  146.         std::map<std::string, Token> keywords_ {
  147.             {"class", token_type::Class{}},
  148.             {"return", token_type::Return{}},
  149.             {"if", token_type::If{}},
  150.             {"else", token_type::Else{}},
  151.             {"def", token_type::Def{}},
  152.             {"print", token_type::Print{}},
  153.             {"or", token_type::Or{}},
  154.             {"None", token_type::None{}},
  155.             {"and", token_type::And{}},
  156.             {"not", token_type::Not{}},
  157.             {"True", token_type::True{}},
  158.             {"False", token_type::False{}}
  159.         };
  160.    
  161.         int spaces_ = 0;
  162.    
  163.         std::vector<Token> tokens_;
  164.         std::vector<Token>::const_iterator current_token_;
  165.    
  166.         void parse_number(std::istream& input);
  167.         void parse_char(std::istream& input);
  168.         void parse_string(std::istream& input);
  169.         void parse_operator(std::istream& input);
  170.         void parse_id(std::istream& input);
  171.         void parse_newline(std::istream& input);
  172.         void parse_indent(std::istream& input);
  173.  
  174.         void pass_spaces(std::istream& input);
  175.         void pass_comment(std::istream& input);
  176.    
  177.         std::vector<Token>::const_iterator parse_tokens(std::istream& input);
  178. };
  179.  
  180. }//end namespace parse
  181. -----------------------------------------------------------------------
  182. lexer.cpp
  183. -----------------------------------------------------------------------
  184. #include "lexer.h"
  185.  
  186. #include <algorithm>
  187. #include <charconv>
  188. #include <unordered_map>
  189.  
  190. using namespace std;
  191.  
  192. namespace parse {
  193.  
  194. bool operator==(const Token& lhs, const Token& rhs) {
  195.     using namespace token_type;
  196.  
  197.     if (lhs.index() != rhs.index()) {return false;}
  198.     if (lhs.Is<Char>()) {return lhs.As<Char>().value == rhs.As<Char>().value;}
  199.     if (lhs.Is<Number>()) {return lhs.As<Number>().value == rhs.As<Number>().value;}
  200.     if (lhs.Is<String>()) {return lhs.As<String>().value == rhs.As<String>().value;}
  201.     if (lhs.Is<Id>()) {return lhs.As<Id>().value == rhs.As<Id>().value;}
  202.     return true;
  203. }
  204.  
  205. bool operator!=(const Token& lhs, const Token& rhs) {return !(lhs == rhs);}
  206.  
  207. std::ostream& operator<<(std::ostream& os, const Token& rhs) {
  208.     using namespace token_type;
  209.  
  210. #define VALUED_OUTPUT(type) \
  211.     if (auto p = rhs.TryAs<type>()) return os << #type << '{' << p->value << '}';
  212.  
  213.     VALUED_OUTPUT(Number);
  214.     VALUED_OUTPUT(Id);
  215.     VALUED_OUTPUT(String);
  216.     VALUED_OUTPUT(Char);
  217.  
  218. #undef VALUED_OUTPUT
  219.  
  220. #define UNVALUED_OUTPUT(type) \
  221.     if (rhs.Is<type>()) return os << #type;
  222.  
  223.     UNVALUED_OUTPUT(Class);
  224.     UNVALUED_OUTPUT(Return);
  225.     UNVALUED_OUTPUT(If);
  226.     UNVALUED_OUTPUT(Else);
  227.     UNVALUED_OUTPUT(Def);
  228.     UNVALUED_OUTPUT(Newline);
  229.     UNVALUED_OUTPUT(Print);
  230.     UNVALUED_OUTPUT(Indent);
  231.     UNVALUED_OUTPUT(Dedent);
  232.     UNVALUED_OUTPUT(And);
  233.     UNVALUED_OUTPUT(Or);
  234.     UNVALUED_OUTPUT(Not);
  235.     UNVALUED_OUTPUT(Eq);
  236.     UNVALUED_OUTPUT(NotEq);
  237.     UNVALUED_OUTPUT(LessOrEq);
  238.     UNVALUED_OUTPUT(GreaterOrEq);
  239.     UNVALUED_OUTPUT(None);
  240.     UNVALUED_OUTPUT(True);
  241.     UNVALUED_OUTPUT(False);
  242.     UNVALUED_OUTPUT(Eof);
  243.  
  244. #undef UNVALUED_OUTPUT
  245.  
  246.     return os << "Unknown token :("sv;
  247. }
  248.  
  249. Lexer::Lexer(std::istream& input) : current_token_(parse_tokens(input)) {}
  250.  
  251. const Token& Lexer::CurrentToken() const {return *current_token_;}
  252.  
  253. Token Lexer::NextToken() {
  254.    
  255.     if ((current_token_ + 1) == tokens_.end()) {
  256.         return token_type::Eof{};
  257.        
  258.     } else {
  259.         return *++current_token_;
  260.     }  
  261. }
  262.  
  263. void Lexer::parse_number(std::istream& input) {
  264.  
  265.     char curr;
  266.     curr = input.peek();
  267.  
  268.     if (std::isdigit(curr)) {
  269.  
  270.         string parsed;
  271.  
  272.         while (input.get(curr)) {
  273.  
  274.             if (std::isdigit(curr)) {
  275.                 parsed.push_back(curr);
  276.  
  277.             } else {
  278.                 input.putback(curr);
  279.                 break;
  280.             }
  281.         }
  282.  
  283.         tokens_.emplace_back(token_type::Number{std::stoi(parsed)});
  284.     }
  285. }
  286.    
  287. void Lexer::parse_char(std::istream& input) {
  288.    
  289.     char curr;
  290.     curr = input.peek();
  291.    
  292.     if (std::ispunct(curr)) {
  293.        
  294.         if (curr == '#') {
  295.             pass_comment(input);
  296.             return;
  297.         }
  298.        
  299.         input.get(curr);        
  300.         tokens_.emplace_back(token_type::Char{curr});
  301.     }
  302. }
  303.    
  304. void Lexer::parse_string(std::istream& input) {
  305.      
  306.     char quote;
  307.     input.get(quote);
  308.      
  309.     if (quote == '\'' || quote == '\"') {
  310.        
  311.         auto it = std::istreambuf_iterator<char>(input);
  312.         auto end = std::istreambuf_iterator<char>();
  313.        
  314.         std::string str;
  315.        
  316.         while (it != end) {
  317.            
  318.             const char curr = *it;
  319.             if (curr == quote) {
  320.                 ++it;
  321.                 break;
  322.                
  323.             } else if (curr == '\\') {
  324.                 ++it;
  325.                
  326.                 if (it == end) {
  327.                     throw std::logic_error("unable to parse. string");
  328.                 }
  329.                
  330.                 const char escaped = *(it);            
  331.                 switch (escaped) {
  332.                        
  333.                     case 'n':
  334.                         str.push_back('\n');
  335.                         break;
  336.                        
  337.                     case 't':
  338.                         str.push_back('\t');
  339.                         break;
  340.                        
  341.                     case 'r':
  342.                         str.push_back('\r');
  343.                         break;
  344.                        
  345.                     case '"':
  346.                         str.push_back('"');
  347.                         break;
  348.                        
  349.                     case '\'':
  350.                         str.push_back('\'');
  351.                         break;
  352.                    
  353.                     case '\\':
  354.                         str.push_back('\\');
  355.                         break;
  356.                    
  357.                     default:
  358.                         throw std::invalid_argument("invalid escape char");
  359.                 }
  360.                
  361.             } else if (curr == '\n' || curr == '\r') {
  362.                 throw std::logic_error("invalid eof"s);
  363.                
  364.             } else {
  365.                 str.push_back(curr);
  366.             }
  367.            
  368.             ++it;
  369.         }
  370.        
  371.         tokens_.emplace_back(token_type::String{str});
  372.        
  373.     } else {
  374.         input.putback(quote);
  375.     }
  376. }
  377.    
  378. void Lexer::parse_operator(std::istream& input) {
  379.    
  380.     char curr;
  381.     input.get(curr);
  382.    
  383.     char next = input.peek();
  384.    
  385.     if (curr == '=' && next == '=') {
  386.         input.get();
  387.         tokens_.emplace_back(token_type::Eq{});
  388.        
  389.     } else if (curr == '!' && next == '=') {
  390.         input.get();
  391.         tokens_.emplace_back(token_type::NotEq{});
  392.        
  393.     } else if (curr == '<' && next == '=') {
  394.         input.get();
  395.         tokens_.emplace_back(token_type::LessOrEq{});  
  396.        
  397.     } else if (curr == '>' && next == '=') {
  398.         input.get();
  399.         tokens_.emplace_back(token_type::GreaterOrEq{});
  400.  
  401.     } else {
  402.         input.putback(curr);
  403.     }
  404. }
  405.    
  406. void Lexer::parse_id(std::istream& input) {
  407.    
  408.     char curr;
  409.     curr = input.peek();
  410.    
  411.     if (std::isalpha(curr) || curr == '_') {
  412.        
  413.         std::string parsed;
  414.        
  415.         while (input.get(curr)) {
  416.            
  417.             if (std::isalnum(curr) || curr == '_') {
  418.                 parsed.push_back(curr);
  419.                
  420.             } else {
  421.                 input.putback(curr);
  422.                 break;
  423.             }
  424.         }
  425.        
  426.         if (keywords_.find(parsed) != keywords_.end()) {
  427.             tokens_.push_back(keywords_.at(parsed));
  428.            
  429.         } else {
  430.             tokens_.emplace_back(token_type::Id{parsed});
  431.         }
  432.     }
  433. }
  434.    
  435. void Lexer::parse_newline(std::istream& input) {
  436.  
  437.     char curr;
  438.     input.get(curr);
  439.  
  440.     if (curr == '\n') {
  441.  
  442.         if (!tokens_.empty() && tokens_.back() != token_type::Newline{}) {
  443.             tokens_.emplace_back(token_type::Newline{});
  444.         }
  445.  
  446.         parse_indent(input);
  447.  
  448.     } else {
  449.         input.putback(curr);
  450.     }
  451. }
  452.    
  453. void Lexer::parse_indent(std::istream& input) {
  454.  
  455.     int spaces = 0;
  456.     char curr;
  457.    
  458.     while (input.get(curr) && curr == ' ') {
  459.         ++spaces;
  460.     }
  461.    
  462.     if (input.rdstate() != std::ios_base::eofbit) {
  463.         input.putback(curr);
  464.     }
  465.    
  466.     char next = input.peek();
  467.    
  468.     if (next == '\n' || next == '#') {
  469.         return;
  470.     }
  471.    
  472.     int indents = (spaces - spaces_) / 2;
  473.     spaces_ = spaces;
  474.    
  475.     Token indent;
  476.    
  477.     if (indents > 0) {
  478.         indent = token_type::Indent{};
  479.        
  480.     } else if (indents < 0) {
  481.         indent = token_type::Dedent{};
  482.     }
  483.    
  484.     for (int i = 0; i < std::abs(indents); ++i) {
  485.         tokens_.emplace_back(indent);
  486.     }
  487. }
  488.    
  489. void Lexer::pass_spaces(std::istream& input) {
  490.    
  491.     while (input.peek() == ' ') {
  492.         input.get();
  493.     }
  494. }
  495.  
  496. void Lexer::pass_comment(std::istream& input) {
  497.    
  498.     char curr;
  499.     input.get(curr);
  500.    
  501.     if (curr == '#') {
  502.        
  503.         string comment;
  504.         getline(input, comment, '\n');
  505.        
  506.         if (input.rdstate() != std::ios_base::eofbit) {
  507.             input.putback('\n');
  508.         }
  509.        
  510.     } else {
  511.         input.putback(curr);
  512.     }
  513. }
  514.    
  515. std::vector<Token>::const_iterator Lexer::parse_tokens(std::istream& input) {
  516.    
  517.     char curr;
  518.    
  519.     while (input.get(curr)) {
  520.        
  521.         input.putback(curr);
  522.  
  523.         parse_newline(input);
  524.         parse_string(input);
  525.         parse_id(input);
  526.         parse_operator(input);
  527.         parse_char(input);
  528.         parse_number(input);
  529.  
  530.         pass_spaces(input);
  531.     }
  532.    
  533.     if (!tokens_.empty() && tokens_.back() != token_type::Newline{} && tokens_.back() != token_type::Dedent{}) {
  534.         tokens_.emplace_back(token_type::Newline{});
  535.     }
  536.    
  537.     tokens_.emplace_back(token_type::Eof{});
  538.     return tokens_.begin();
  539. }
  540.    
  541. }//end namespace parse
  542. -----------------------------------------------------------------------
  543. lexer_test_open.cpp
  544. -----------------------------------------------------------------------
  545. #include "lexer.h"
  546. #include "test_runner_p.h"
  547.  
  548. #include <sstream>
  549. #include <string>
  550.  
  551. using namespace std;
  552.  
  553. namespace parse {
  554. namespace {
  555.    
  556. void TestSimpleAssignment() {
  557.     istringstream input("x = 42\n"s);
  558.     Lexer lexer(input);
  559.  
  560.     ASSERT_EQUAL(lexer.CurrentToken(), Token(token_type::Id{"x"s}));
  561.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Char{'='}));
  562.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Number{42}));
  563.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Newline{}));
  564.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Eof{}));
  565.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Eof{}));
  566.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Eof{}));
  567. }
  568.  
  569. void TestKeywords() {
  570.     istringstream input("class return if else def print or None and not True False"s);
  571.     Lexer lexer(input);
  572.  
  573.     ASSERT_EQUAL(lexer.CurrentToken(), Token(token_type::Class{}));
  574.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Return{}));
  575.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::If{}));
  576.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Else{}));
  577.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Def{}));
  578.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Print{}));
  579.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Or{}));
  580.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::None{}));
  581.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::And{}));
  582.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Not{}));
  583.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::True{}));
  584.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::False{}));
  585. }
  586.  
  587. void TestNumbers() {
  588.     istringstream input("42 15 -53"s);
  589.     Lexer lexer(input);
  590.  
  591.     ASSERT_EQUAL(lexer.CurrentToken(), Token(token_type::Number{42}));
  592.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Number{15}));
  593.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Char{'-'}));
  594.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Number{53}));
  595. }
  596.  
  597. void TestIds() {
  598.     istringstream input("x    _42 big_number   Return Class  dEf"s);
  599.     Lexer lexer(input);
  600.  
  601.     ASSERT_EQUAL(lexer.CurrentToken(), Token(token_type::Id{"x"s}));
  602.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Id{"_42"s}));
  603.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Id{"big_number"s}));
  604.     ASSERT_EQUAL(lexer.NextToken(),
  605.                  Token(token_type::Id{"Return"s}));  // keywords are case-sensitive
  606.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Id{"Class"s}));
  607.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Id{"dEf"s}));
  608. }
  609.  
  610. void TestStrings() {
  611.     istringstream input(
  612.         R"('word' "two words" 'long string with a double quote " inside' "another long string with single quote ' inside")"s);
  613.     Lexer lexer(input);
  614.  
  615.     ASSERT_EQUAL(lexer.CurrentToken(), Token(token_type::String{"word"s}));
  616.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::String{"two words"s}));
  617.     ASSERT_EQUAL(lexer.NextToken(),
  618.                  Token(token_type::String{"long string with a double quote \" inside"s}));
  619.     ASSERT_EQUAL(lexer.NextToken(),
  620.                  Token(token_type::String{"another long string with single quote ' inside"s}));
  621. }
  622.  
  623. void TestOperations() {
  624.     istringstream input("+-*/= > < != == <> <= >="s);
  625.     Lexer lexer(input);
  626.  
  627.     ASSERT_EQUAL(lexer.CurrentToken(), Token(token_type::Char{'+'}));
  628.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Char{'-'}));
  629.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Char{'*'}));
  630.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Char{'/'}));
  631.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Char{'='}));
  632.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Char{'>'}));
  633.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Char{'<'}));
  634.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::NotEq{}));
  635.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Eq{}));
  636.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Char{'<'}));
  637.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Char{'>'}));
  638.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::LessOrEq{}));
  639.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::GreaterOrEq{}));
  640. }
  641.  
  642. void TestIndentsAndNewlines() {
  643.     istringstream input(R"(
  644. no_indent
  645.  indent_one
  646.    indent_two
  647.      indent_three
  648.      indent_three
  649.      indent_three
  650.    indent_two
  651.  indent_one
  652.    indent_two
  653. no_indent
  654. )"s);
  655.  
  656.     Lexer lexer(input);
  657.  
  658.     ASSERT_EQUAL(lexer.CurrentToken(), Token(token_type::Id{"no_indent"s}));
  659.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Newline{}));
  660.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Indent{}));
  661.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Id{"indent_one"s}));
  662.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Newline{}));
  663.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Indent{}));
  664.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Id{"indent_two"s}));
  665.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Newline{}));
  666.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Indent{}));
  667.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Id{"indent_three"s}));
  668.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Newline{}));
  669.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Id{"indent_three"s}));
  670.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Newline{}));
  671.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Id{"indent_three"s}));
  672.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Newline{}));
  673.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Dedent{}));
  674.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Id{"indent_two"s}));
  675.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Newline{}));
  676.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Dedent{}));
  677.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Id{"indent_one"s}));
  678.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Newline{}));
  679.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Indent{}));
  680.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Id{"indent_two"s}));
  681.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Newline{}));
  682.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Dedent{}));
  683.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Dedent{}));
  684.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Id{"no_indent"s}));
  685.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Newline{}));
  686.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Eof{}));
  687. }
  688.  
  689. void TestEmptyLinesAreIgnored() {
  690.     istringstream input(R"(
  691. x = 1
  692.  y = 2
  693.  
  694.  z = 3
  695.  
  696.  
  697. )"s);
  698.     Lexer lexer(input);
  699.  
  700.     ASSERT_EQUAL(lexer.CurrentToken(), Token(token_type::Id{"x"s}));
  701.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Char{'='}));
  702.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Number{1}));
  703.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Newline{}));
  704.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Indent{}));
  705.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Id{"y"s}));
  706.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Char{'='}));
  707.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Number{2}));
  708.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Newline{}));
  709.     // Пустая строка, состоящая только из пробельных символов не меняет текущий отступ,
  710.     // поэтому следующая лексема — это Id, а не Dedent
  711.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Id{"z"s}));
  712.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Char{'='}));
  713.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Number{3}));
  714.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Newline{}));
  715.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Dedent{}));
  716.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Eof{}));
  717. }
  718.  
  719. void TestMythonProgram() {
  720.     istringstream input(R"(
  721. x = 4
  722. y = "hello"
  723.  
  724. class Point:
  725.  def __init__(self, x, y):
  726.    self.x = x
  727.    self.y = y
  728.  
  729.  def __str__(self):
  730.    return str(x) + ' ' + str(y)
  731.  
  732. p = Point(1, 2)
  733. print str(p)
  734. )"s);
  735.     Lexer lexer(input);
  736.  
  737.     ASSERT_EQUAL(lexer.CurrentToken(), Token(token_type::Id{"x"s}));
  738.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Char{'='}));
  739.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Number{4}));
  740.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Newline{}));
  741.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Id{"y"s}));
  742.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Char{'='}));
  743.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::String{"hello"s}));
  744.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Newline{}));
  745.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Class{}));
  746.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Id{"Point"s}));
  747.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Char{':'}));
  748.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Newline{}));
  749.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Indent{}));
  750.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Def{}));
  751.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Id{"__init__"s}));
  752.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Char{'('}));
  753.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Id{"self"s}));
  754.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Char{','}));
  755.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Id{"x"s}));
  756.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Char{','}));
  757.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Id{"y"s}));
  758.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Char{')'}));
  759.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Char{':'}));
  760.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Newline{}));
  761.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Indent{}));
  762.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Id{"self"s}));
  763.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Char{'.'}));
  764.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Id{"x"s}));
  765.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Char{'='}));
  766.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Id{"x"s}));
  767.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Newline{}));
  768.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Id{"self"s}));
  769.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Char{'.'}));
  770.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Id{"y"s}));
  771.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Char{'='}));
  772.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Id{"y"s}));
  773.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Newline{}));
  774.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Dedent{}));
  775.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Def{}));
  776.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Id{"__str__"s}));
  777.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Char{'('}));
  778.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Id{"self"s}));
  779.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Char{')'}));
  780.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Char{':'}));
  781.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Newline{}));
  782.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Indent{}));
  783.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Return{}));
  784.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Id{"str"s}));
  785.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Char{'('}));
  786.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Id{"x"s}));
  787.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Char{')'}));
  788.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Char{'+'}));
  789.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::String{" "s}));
  790.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Char{'+'}));
  791.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Id{"str"s}));
  792.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Char{'('}));
  793.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Id{"y"s}));
  794.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Char{')'}));
  795.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Newline{}));
  796.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Dedent{}));
  797.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Dedent{}));
  798.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Id{"p"s}));
  799.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Char{'='}));
  800.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Id{"Point"s}));
  801.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Char{'('}));
  802.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Number{1}));
  803.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Char{','}));
  804.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Number{2}));
  805.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Char{')'}));
  806.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Newline{}));
  807.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Print{}));
  808.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Id{"str"s}));
  809.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Char{'('}));
  810.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Id{"p"s}));
  811.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Char{')'}));
  812.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Newline{}));
  813.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Eof{}));
  814.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Eof{}));
  815.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Eof{}));
  816.     ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Eof{}));
  817. }
  818.  
  819. void TestExpect() {
  820.     istringstream is("bugaga"s);
  821.     Lexer lex(is);
  822.  
  823.     ASSERT_DOESNT_THROW(lex.Expect<token_type::Id>());
  824.     ASSERT_EQUAL(lex.Expect<token_type::Id>().value, "bugaga"s);
  825.     ASSERT_DOESNT_THROW(lex.Expect<token_type::Id>("bugaga"s));
  826.     ASSERT_THROWS(lex.Expect<token_type::Id>("widget"s), LexerError);
  827.     ASSERT_THROWS(lex.Expect<token_type::Return>(), LexerError);
  828. }
  829.  
  830. void TestExpectNext() {
  831.     istringstream is("+ bugaga + def 52"s);
  832.     Lexer lex(is);
  833.  
  834.     ASSERT_EQUAL(lex.CurrentToken(), Token(token_type::Char{'+'}));
  835.     ASSERT_DOESNT_THROW(lex.ExpectNext<token_type::Id>());
  836.     ASSERT_DOESNT_THROW(lex.ExpectNext<token_type::Char>('+'));
  837.     ASSERT_THROWS(lex.ExpectNext<token_type::Newline>(), LexerError);
  838.     ASSERT_THROWS(lex.ExpectNext<token_type::Number>(57), LexerError);
  839. }
  840.  
  841. void TestAlwaysEmitsNewlineAtTheEndOfNonemptyLine() {
  842.     {
  843.         istringstream is("a b"s);
  844.         Lexer lexer(is);
  845.  
  846.         ASSERT_EQUAL(lexer.CurrentToken(), Token(token_type::Id{"a"s}));
  847.         ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Id{"b"s}));
  848.         ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Newline{}));
  849.         ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Eof{}));
  850.         ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Eof{}));
  851.         ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Eof{}));
  852.     }
  853.     {
  854.         istringstream is("+"s);
  855.         Lexer lexer(is);
  856.  
  857.         ASSERT_EQUAL(lexer.CurrentToken(), Token(token_type::Char{'+'}));
  858.         ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Newline{}));
  859.         ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Eof{}));
  860.     }
  861. }
  862. void TestCommentsAreIgnored() {
  863.     {
  864.         istringstream is(R"(# comment
  865. )"s);
  866.         Lexer lexer(is);
  867.  
  868.         ASSERT_EQUAL(lexer.CurrentToken(), Token(token_type::Eof{}));
  869.     }
  870.     {
  871.         istringstream is(R"(# comment
  872.  
  873. )"s);
  874.         Lexer lexer(is);
  875.         ASSERT_EQUAL(lexer.CurrentToken(), Token(token_type::Eof{}));
  876.     }
  877.     {
  878.         istringstream is(R"(# comment
  879. x #another comment
  880. abc#
  881. '#'
  882. "#123"
  883. #)"s);
  884.  
  885.         Lexer lexer(is);
  886.         ASSERT_EQUAL(lexer.CurrentToken(), Token(token_type::Id{"x"s}));
  887.         ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Newline{}));
  888.         ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Id{"abc"s}));
  889.         ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Newline{}));
  890.         ASSERT_EQUAL(lexer.NextToken(), Token(token_type::String{"#"s}));
  891.         ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Newline{}));
  892.         ASSERT_EQUAL(lexer.NextToken(), Token(token_type::String{"#123"s}));
  893.         ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Newline{}));
  894.         ASSERT_EQUAL(lexer.NextToken(), Token(token_type::Eof{}));
  895.     }
  896. }
  897.    
  898. }//end namespace
  899.  
  900. void RunOpenLexerTests(TestRunner& tr) {
  901.     RUN_TEST(tr, parse::TestSimpleAssignment);
  902.     RUN_TEST(tr, parse::TestKeywords);
  903.     RUN_TEST(tr, parse::TestNumbers);
  904.     RUN_TEST(tr, parse::TestIds);
  905.     RUN_TEST(tr, parse::TestStrings);
  906.     RUN_TEST(tr, parse::TestOperations);
  907.     RUN_TEST(tr, parse::TestIndentsAndNewlines);
  908.     RUN_TEST(tr, parse::TestEmptyLinesAreIgnored);
  909.     RUN_TEST(tr, parse::TestExpect);
  910.     RUN_TEST(tr, parse::TestExpectNext);
  911.     RUN_TEST(tr, parse::TestMythonProgram);
  912.     RUN_TEST(tr, parse::TestAlwaysEmitsNewlineAtTheEndOfNonemptyLine);
  913.     RUN_TEST(tr, parse::TestCommentsAreIgnored);
  914. }
  915.  
  916. }//end namespace parse
  917. -----------------------------------------------------------------------
  918. main.cpp
  919. -----------------------------------------------------------------------
  920. #include "lexer.h"
  921. #include "parse.h"
  922. #include "runtime.h"
  923. #include "statement.h"
  924. #include "test_runner_p.h"
  925.  
  926. #include <iostream>
  927.  
  928. using namespace std;
  929.  
  930. namespace parse {
  931.    
  932. void RunOpenLexerTests(TestRunner& tr);
  933.    
  934. }//end namespace parse
  935.  
  936. namespace ast {
  937.    
  938. void RunUnitTests(TestRunner& tr);
  939.    
  940. }
  941.  
  942. namespace runtime {
  943.    
  944. void RunObjectHolderTests(TestRunner& tr);
  945. void RunObjectsTests(TestRunner& tr);
  946.    
  947. }//end namespace runtime
  948.  
  949. void TestParseProgram(TestRunner& tr);
  950.  
  951. namespace {
  952.  
  953. void RunMythonProgram(istream& input, ostream& output) {
  954.     parse::Lexer lexer(input);
  955.     auto program = ParseProgram(lexer);
  956.  
  957.     runtime::SimpleContext context{output};
  958.     runtime::Closure closure;
  959.     program->Execute(closure, context);
  960. }
  961.  
  962. void TestSimplePrints() {
  963.     istringstream input(R"(
  964. print 57
  965. print 10, 24, -8
  966. print 'hello'
  967. print "world"
  968. print True, False
  969. print
  970. print None
  971. )");
  972.  
  973.     ostringstream output;
  974.     RunMythonProgram(input, output);
  975.  
  976.     ASSERT_EQUAL(output.str(), "57\n10 24 -8\nhello\nworld\nTrue False\n\nNone\n");
  977. }
  978.  
  979. void TestAssignments() {
  980.     istringstream input(R"(
  981. x = 57
  982. print x
  983. x = 'C++ black belt'
  984. print x
  985. y = False
  986. x = y
  987. print x
  988. x = None
  989. print x, y
  990. )");
  991.  
  992.     ostringstream output;
  993.     RunMythonProgram(input, output);
  994.  
  995.     ASSERT_EQUAL(output.str(), "57\nC++ black belt\nFalse\nNone False\n");
  996. }
  997.  
  998. void TestArithmetics() {
  999.     istringstream input("print 1+2+3+4+5, 1*2*3*4*5, 1-2-3-4-5, 36/4/3, 2*5+10/2");
  1000.  
  1001.     ostringstream output;
  1002.     RunMythonProgram(input, output);
  1003.  
  1004.     ASSERT_EQUAL(output.str(), "15 120 -13 3 15\n");
  1005. }
  1006.  
  1007. void TestVariablesArePointers() {
  1008.     istringstream input(R"(
  1009. class Counter:
  1010.  def __init__():
  1011.    self.value = 0
  1012.  
  1013.  def add():
  1014.    self.value = self.value + 1
  1015.  
  1016. class Dummy:
  1017.  def do_add(counter):
  1018.    counter.add()
  1019.  
  1020. x = Counter()
  1021. y = x
  1022.  
  1023. x.add()
  1024. y.add()
  1025.  
  1026. print x.value
  1027.  
  1028. d = Dummy()
  1029. d.do_add(x)
  1030.  
  1031. print y.value
  1032. )");
  1033.  
  1034.     ostringstream output;
  1035.     RunMythonProgram(input, output);
  1036.  
  1037.     ASSERT_EQUAL(output.str(), "2\n3\n");
  1038. }
  1039.  
  1040. void TestAll() {
  1041.     TestRunner tr;
  1042.     parse::RunOpenLexerTests(tr);
  1043.     runtime::RunObjectHolderTests(tr);
  1044.     runtime::RunObjectsTests(tr);
  1045.     ast::RunUnitTests(tr);
  1046.     TestParseProgram(tr);
  1047.  
  1048.     RUN_TEST(tr, TestSimplePrints);
  1049.     RUN_TEST(tr, TestAssignments);
  1050.     RUN_TEST(tr, TestArithmetics);
  1051.     RUN_TEST(tr, TestVariablesArePointers);
  1052. }
  1053.  
  1054. }//end namespace
  1055.  
  1056. int main() {
  1057.    
  1058.     try {
  1059.         TestAll();
  1060.  
  1061.         RunMythonProgram(cin, cout);
  1062.     } catch (const std::exception& e) {
  1063.         std::cerr << e.what() << std::endl;
  1064.         return 1;
  1065.     }
  1066.     return 0;
  1067. }
  1068. -----------------------------------------------------------------------
  1069. parse.cpp
  1070. -----------------------------------------------------------------------
  1071. #include "parse.h"
  1072.  
  1073. #include "lexer.h"
  1074. #include "statement.h"
  1075.  
  1076. using namespace std;
  1077.  
  1078. namespace TokenType = parse::token_type;
  1079.  
  1080. namespace {
  1081.    
  1082. bool operator==(const parse::Token& token, char c) {
  1083.     const auto* p = token.TryAs<TokenType::Char>();
  1084.     return p != nullptr && p->value == c;
  1085. }
  1086.  
  1087. bool operator!=(const parse::Token& token, char c) {return !(token == c);}
  1088.  
  1089. class Parser {
  1090. public:
  1091.    
  1092.     explicit Parser(parse::Lexer& lexer) : lexer_(lexer) {}
  1093.  
  1094.     unique_ptr<ast::Statement> ParseProgram() {
  1095.         auto result = make_unique<ast::Compound>();
  1096.        
  1097.         while (!lexer_.CurrentToken().Is<TokenType::Eof>()) {result->AddStatement(ParseStatement());}
  1098.         return result;
  1099.     }
  1100.  
  1101. private:
  1102.  
  1103.     unique_ptr<ast::Statement> ParseSuite() {
  1104.        
  1105.         lexer_.Expect<TokenType::Newline>();
  1106.         lexer_.ExpectNext<TokenType::Indent>();
  1107.  
  1108.         lexer_.NextToken();
  1109.  
  1110.         auto result = make_unique<ast::Compound>();
  1111.         while (!lexer_.CurrentToken().Is<TokenType::Dedent>()) {result->AddStatement(ParseStatement());}
  1112.  
  1113.         lexer_.Expect<TokenType::Dedent>();
  1114.         lexer_.NextToken();
  1115.  
  1116.         return result;
  1117.     }
  1118.  
  1119.     vector<runtime::Method> ParseMethods() {
  1120.        
  1121.         vector<runtime::Method> result;
  1122.  
  1123.         while (lexer_.CurrentToken().Is<TokenType::Def>()) {
  1124.             runtime::Method m;
  1125.  
  1126.             m.name = lexer_.ExpectNext<TokenType::Id>().value;
  1127.             lexer_.ExpectNext<TokenType::Char>('(');
  1128.  
  1129.             if (lexer_.NextToken().Is<TokenType::Id>()) {
  1130.                 m.formal_params.push_back(lexer_.Expect<TokenType::Id>().value);
  1131.                
  1132.                 while (lexer_.NextToken() == ',') {
  1133.                     m.formal_params.push_back(lexer_.ExpectNext<TokenType::Id>().value);
  1134.                 }
  1135.             }
  1136.  
  1137.             lexer_.Expect<TokenType::Char>(')');
  1138.             lexer_.ExpectNext<TokenType::Char>(':');
  1139.             lexer_.NextToken();
  1140.  
  1141.             m.body = std::make_unique<ast::MethodBody>(ParseSuite());
  1142.  
  1143.             result.push_back(std::move(m));
  1144.         }
  1145.         return result;
  1146.     }
  1147.  
  1148.     unique_ptr<ast::Statement> ParseClassDefinition() {
  1149.        
  1150.         string class_name = lexer_.Expect<TokenType::Id>().value;
  1151.         lexer_.NextToken();
  1152.  
  1153.         const runtime::Class* base_class = nullptr;
  1154.         if (lexer_.CurrentToken() == '(') {
  1155.            
  1156.             auto name = lexer_.ExpectNext<TokenType::Id>().value;
  1157.            
  1158.             lexer_.ExpectNext<TokenType::Char>(')');
  1159.             lexer_.NextToken();
  1160.  
  1161.             auto it = declared_classes_.find(name);
  1162.             if (it == declared_classes_.end()) {throw ParseError("Base class "s + name + " not found for class "s + class_name);}
  1163.            
  1164.             base_class = static_cast<const runtime::Class*>(it->second.Get());
  1165.         }
  1166.  
  1167.         lexer_.Expect<TokenType::Char>(':');
  1168.         lexer_.ExpectNext<TokenType::Newline>();
  1169.         lexer_.ExpectNext<TokenType::Indent>();
  1170.         lexer_.ExpectNext<TokenType::Def>();
  1171.         vector<runtime::Method> methods = ParseMethods();
  1172.  
  1173.         lexer_.Expect<TokenType::Dedent>();
  1174.         lexer_.NextToken();
  1175.  
  1176.         auto [it, inserted] = declared_classes_.insert({
  1177.             class_name,
  1178.             runtime::ObjectHolder::Own(runtime::Class(class_name, std::move(methods), base_class)),
  1179.         });
  1180.  
  1181.         if (!inserted) {throw ParseError("Class "s + class_name + " already exists"s);}
  1182.         return make_unique<ast::ClassDefinition>(it->second);
  1183.     }
  1184.  
  1185.     vector<string> ParseDottedIds() {
  1186.        
  1187.         vector<string> result(1, lexer_.Expect<TokenType::Id>().value);
  1188.  
  1189.         while (lexer_.NextToken() == '.') {result.push_back(lexer_.ExpectNext<TokenType::Id>().value);}
  1190.        
  1191.         return result;
  1192.     }
  1193.  
  1194.     unique_ptr<ast::Statement> ParseAssignmentOrCall() {
  1195.        
  1196.         lexer_.Expect<TokenType::Id>();
  1197.  
  1198.         vector<string> id_list = ParseDottedIds();
  1199.         string last_name = id_list.back();
  1200.         id_list.pop_back();
  1201.  
  1202.         if (lexer_.CurrentToken() == '=') {
  1203.             lexer_.NextToken();
  1204.  
  1205.             if (id_list.empty()) {
  1206.                 return make_unique<ast::Assignment>(std::move(last_name), ParseTest());
  1207.             }
  1208.            
  1209.             return make_unique<ast::FieldAssignment>(ast::VariableValue{std::move(id_list)}, std::move(last_name), ParseTest());
  1210.         }
  1211.        
  1212.         lexer_.Expect<TokenType::Char>('(');
  1213.         lexer_.NextToken();
  1214.  
  1215.         if (id_list.empty()) {throw ParseError("Mython doesn't support functions, only methods: "s + last_name);}
  1216.  
  1217.         vector<unique_ptr<ast::Statement>> args;
  1218.         if (lexer_.CurrentToken() != ')') {
  1219.             args = ParseTestList();
  1220.         }
  1221.        
  1222.         lexer_.Expect<TokenType::Char>(')');
  1223.         lexer_.NextToken();
  1224.  
  1225.         return make_unique<ast::MethodCall>(make_unique<ast::VariableValue>(std::move(id_list)), std::move(last_name), std::move(args));
  1226.     }
  1227.  
  1228.     unique_ptr<ast::Statement> ParseExpression() {
  1229.        
  1230.         unique_ptr<ast::Statement> result = ParseAdder();
  1231.        
  1232.         while (lexer_.CurrentToken() == '+' || lexer_.CurrentToken() == '-') {
  1233.            
  1234.             char op = lexer_.CurrentToken().As<TokenType::Char>().value;
  1235.             lexer_.NextToken();
  1236.  
  1237.             if (op == '+') {
  1238.                 result = make_unique<ast::Add>(std::move(result), ParseAdder());
  1239.             } else {
  1240.                 result = make_unique<ast::Sub>(std::move(result), ParseAdder());
  1241.             }
  1242.         }
  1243.         return result;
  1244.     }
  1245.  
  1246.     unique_ptr<ast::Statement> ParseAdder() {
  1247.        
  1248.         unique_ptr<ast::Statement> result = ParseMult();
  1249.        
  1250.         while (lexer_.CurrentToken() == '*' || lexer_.CurrentToken() == '/') {
  1251.            
  1252.             char op = lexer_.CurrentToken().As<TokenType::Char>().value;
  1253.             lexer_.NextToken();
  1254.  
  1255.             if (op == '*') {
  1256.                 result = make_unique<ast::Mult>(std::move(result), ParseMult());
  1257.             } else {
  1258.                 result = make_unique<ast::Div>(std::move(result), ParseMult());
  1259.             }
  1260.         }
  1261.        
  1262.         return result;
  1263.     }
  1264.  
  1265.     unique_ptr<ast::Statement> ParseMult() {
  1266.        
  1267.         if (lexer_.CurrentToken() == '(') {
  1268.            
  1269.             lexer_.NextToken();
  1270.             auto result = ParseTest();
  1271.            
  1272.             lexer_.Expect<TokenType::Char>(')');
  1273.             lexer_.NextToken();
  1274.            
  1275.             return result;
  1276.         }
  1277.        
  1278.         if (lexer_.CurrentToken() == '-') {
  1279.             lexer_.NextToken();
  1280.            
  1281.             return make_unique<ast::Mult>(ParseMult(), make_unique<ast::NumericConst>(-1));
  1282.         }
  1283.        
  1284.         if (const auto* num = lexer_.CurrentToken().TryAs<TokenType::Number>()) {
  1285.             int result = num->value;
  1286.             lexer_.NextToken();
  1287.            
  1288.             return make_unique<ast::NumericConst>(result);
  1289.         }
  1290.        
  1291.         if (const auto* str = lexer_.CurrentToken().TryAs<TokenType::String>()) {
  1292.             string result = str->value;
  1293.             lexer_.NextToken();
  1294.            
  1295.             return make_unique<ast::StringConst>(std::move(result));
  1296.         }
  1297.        
  1298.         if (lexer_.CurrentToken().Is<TokenType::True>()) {
  1299.             lexer_.NextToken();
  1300.            
  1301.             return make_unique<ast::BoolConst>(runtime::Bool(true));
  1302.         }
  1303.        
  1304.         if (lexer_.CurrentToken().Is<TokenType::False>()) {
  1305.             lexer_.NextToken();
  1306.            
  1307.             return make_unique<ast::BoolConst>(runtime::Bool(false));
  1308.         }
  1309.        
  1310.         if (lexer_.CurrentToken().Is<TokenType::None>()) {
  1311.             lexer_.NextToken();
  1312.            
  1313.             return make_unique<ast::None>();
  1314.         }
  1315.  
  1316.         return ParseDottedIdsInMultExpr();
  1317.     }
  1318.  
  1319.     std::unique_ptr<ast::Statement> ParseDottedIdsInMultExpr() {
  1320.        
  1321.         vector<string> names = ParseDottedIds();
  1322.  
  1323.         if (lexer_.CurrentToken() == '(') {
  1324.  
  1325.             vector<unique_ptr<ast::Statement>> args;
  1326.             if (lexer_.NextToken() != ')') {
  1327.                 args = ParseTestList();
  1328.             }
  1329.            
  1330.             lexer_.Expect<TokenType::Char>(')');
  1331.             lexer_.NextToken();
  1332.  
  1333.             auto method_name = names.back();
  1334.             names.pop_back();
  1335.  
  1336.             if (!names.empty()) {return make_unique<ast::MethodCall>(make_unique<ast::VariableValue>(std::move(names)), std::move(method_name), std::move(args));}
  1337.            
  1338.             if (auto it = declared_classes_.find(method_name); it != declared_classes_.end()) {
  1339.                 return make_unique<ast::NewInstance>(static_cast<const runtime::Class&>(*it->second), std::move(args));
  1340.             }
  1341.            
  1342.             if (method_name == "str"sv) {
  1343.                
  1344.                 if (args.size() != 1) {
  1345.                     throw ParseError("Function str takes exactly one argument"s);
  1346.                 }
  1347.                
  1348.                 return make_unique<ast::Stringify>(std::move(args.front()));
  1349.             }
  1350.            
  1351.             throw ParseError("Unknown call to "s + method_name + "()"s);
  1352.         }
  1353.        
  1354.         return make_unique<ast::VariableValue>(std::move(names));
  1355.     }
  1356.  
  1357.     vector<unique_ptr<ast::Statement>> ParseTestList() {
  1358.        
  1359.         vector<unique_ptr<ast::Statement>> result;
  1360.         result.push_back(ParseTest());
  1361.  
  1362.         while (lexer_.CurrentToken() == ',') {
  1363.             lexer_.NextToken();
  1364.             result.push_back(ParseTest());
  1365.         }
  1366.        
  1367.         return result;
  1368.     }
  1369.  
  1370.     unique_ptr<ast::Statement> ParseCondition() {
  1371.        
  1372.         lexer_.Expect<TokenType::If>();
  1373.         lexer_.NextToken();
  1374.  
  1375.         auto condition = ParseTest();
  1376.  
  1377.         lexer_.Expect<TokenType::Char>(':');
  1378.         lexer_.NextToken();
  1379.  
  1380.         auto if_body = ParseSuite();
  1381.  
  1382.         unique_ptr<ast::Statement> else_body;
  1383.         if (lexer_.CurrentToken().Is<TokenType::Else>()) {
  1384.             lexer_.ExpectNext<TokenType::Char>(':');
  1385.             lexer_.NextToken();
  1386.             else_body = ParseSuite();
  1387.         }
  1388.  
  1389.         return make_unique<ast::IfElse>(std::move(condition), std::move(if_body), std::move(else_body));
  1390.     }
  1391.  
  1392.     unique_ptr<ast::Statement> ParseTest() {
  1393.        
  1394.         auto result = ParseAndTest();
  1395.         while (lexer_.CurrentToken().Is<TokenType::Or>()) {
  1396.             lexer_.NextToken();
  1397.             result = make_unique<ast::Or>(std::move(result), ParseAndTest());
  1398.         }
  1399.        
  1400.         return result;
  1401.     }
  1402.  
  1403.     unique_ptr<ast::Statement> ParseAndTest() {
  1404.        
  1405.         auto result = ParseNotTest();
  1406.         while (lexer_.CurrentToken().Is<TokenType::And>()) {
  1407.             lexer_.NextToken();
  1408.             result = make_unique<ast::And>(std::move(result), ParseNotTest());
  1409.         }
  1410.        
  1411.         return result;
  1412.     }
  1413.  
  1414.     unique_ptr<ast::Statement> ParseNotTest() {
  1415.        
  1416.         if (lexer_.CurrentToken().Is<TokenType::Not>()) {
  1417.             lexer_.NextToken();
  1418.             return make_unique<ast::Not>(ParseNotTest());
  1419.         }
  1420.        
  1421.         return ParseComparison();
  1422.     }
  1423.  
  1424.     unique_ptr<ast::Statement> ParseComparison() {
  1425.        
  1426.         auto result = ParseExpression();
  1427.         const auto tok = lexer_.CurrentToken();
  1428.  
  1429.         if (tok == '<') {
  1430.             lexer_.NextToken();
  1431.            
  1432.             return make_unique<ast::Comparison>(runtime::Less, std::move(result), ParseExpression());
  1433.         }
  1434.        
  1435.         if (tok == '>') {
  1436.             lexer_.NextToken();
  1437.            
  1438.             return make_unique<ast::Comparison>(runtime::Greater, std::move(result), ParseExpression());
  1439.         }
  1440.        
  1441.         if (tok.Is<TokenType::Eq>()) {
  1442.             lexer_.NextToken();
  1443.            
  1444.             return make_unique<ast::Comparison>(runtime::Equal, std::move(result), ParseExpression());
  1445.         }
  1446.        
  1447.         if (tok.Is<TokenType::NotEq>()) {
  1448.             lexer_.NextToken();
  1449.            
  1450.             return make_unique<ast::Comparison>(runtime::NotEqual, std::move(result), ParseExpression());
  1451.         }
  1452.        
  1453.         if (tok.Is<TokenType::LessOrEq>()) {
  1454.             lexer_.NextToken();
  1455.            
  1456.             return make_unique<ast::Comparison>(runtime::LessOrEqual, std::move(result), ParseExpression());
  1457.         }
  1458.        
  1459.         if (tok.Is<TokenType::GreaterOrEq>()) {
  1460.             lexer_.NextToken();
  1461.            
  1462.             return make_unique<ast::Comparison>(runtime::GreaterOrEqual, std::move(result), ParseExpression());
  1463.         }
  1464.        
  1465.         return result;
  1466.     }
  1467.  
  1468.     unique_ptr<ast::Statement> ParseStatement() {
  1469.        
  1470.         const auto& tok = lexer_.CurrentToken();
  1471.  
  1472.         if (tok.Is<TokenType::Class>()) {
  1473.             lexer_.NextToken();
  1474.            
  1475.             return ParseClassDefinition();
  1476.         }
  1477.        
  1478.         if (tok.Is<TokenType::If>()) {
  1479.             return ParseCondition();
  1480.         }
  1481.        
  1482.         auto result = ParseSimpleStatement();
  1483.        
  1484.         lexer_.Expect<TokenType::Newline>();
  1485.         lexer_.NextToken();
  1486.        
  1487.         return result;
  1488.     }
  1489.  
  1490.     unique_ptr<ast::Statement> ParseSimpleStatement() {
  1491.        
  1492.         const auto& tok = lexer_.CurrentToken();
  1493.  
  1494.         if (tok.Is<TokenType::Return>()) {
  1495.             lexer_.NextToken();
  1496.            
  1497.             return make_unique<ast::Return>(ParseTest());
  1498.         }
  1499.        
  1500.         if (tok.Is<TokenType::Print>()) {
  1501.             lexer_.NextToken();
  1502.             vector<unique_ptr<ast::Statement>> args;
  1503.            
  1504.             if (!lexer_.CurrentToken().Is<TokenType::Newline>()) {
  1505.                 args = ParseTestList();
  1506.             }
  1507.            
  1508.             return make_unique<ast::Print>(std::move(args));
  1509.         }
  1510.        
  1511.         return ParseAssignmentOrCall();
  1512.     }
  1513.  
  1514.     parse::Lexer& lexer_;
  1515.     runtime::Closure declared_classes_;
  1516. };
  1517.  
  1518. }//end namespace
  1519.  
  1520. unique_ptr<runtime::Executable> ParseProgram(parse::Lexer& lexer) {return Parser{lexer}.ParseProgram();}
  1521. -----------------------------------------------------------------------
  1522. parse.h
  1523. -----------------------------------------------------------------------
  1524. #pragma once
  1525.  
  1526. #include <memory>
  1527. #include <stdexcept>
  1528.  
  1529. namespace parse {
  1530.    
  1531. class Lexer;
  1532.    
  1533. }//end namespace parse
  1534.  
  1535. namespace runtime {
  1536.    
  1537. class Executable;
  1538.    
  1539. }//end namespace runtime
  1540.  
  1541. struct ParseError : std::runtime_error {
  1542.     using std::runtime_error::runtime_error;
  1543. };
  1544.  
  1545. std::unique_ptr<runtime::Executable> ParseProgram(parse::Lexer& lexer);
  1546. -----------------------------------------------------------------------
  1547. parse_test.cpp
  1548. -----------------------------------------------------------------------
  1549. #include "lexer.h"
  1550. #include "parse.h"
  1551. #include "statement.h"
  1552. #include "test_runner_p.h"
  1553.  
  1554. using namespace std;
  1555.  
  1556. namespace parse {
  1557.  
  1558. unique_ptr<ast::Statement> ParseProgramFromString(const string& program) {
  1559.     istringstream is(program);
  1560.     parse::Lexer lexer(is);
  1561.     return ParseProgram(lexer);
  1562. }
  1563.  
  1564. void TestSimpleProgram() {
  1565.     const string program = R"(
  1566. x = 4
  1567. y = 5
  1568. z = "hello, "
  1569. n = "world"
  1570. print x + y, z + n
  1571. )"s;
  1572.  
  1573.     runtime::DummyContext context;
  1574.  
  1575.     runtime::Closure closure;
  1576.     auto tree = ParseProgramFromString(program);
  1577.     tree->Execute(closure, context);
  1578.  
  1579.     ASSERT_EQUAL(context.output.str(), "9 hello, world\n"s);
  1580. }
  1581.  
  1582. void TestProgramWithClasses() {
  1583.     const string program = R"(
  1584. program_name = "Classes test"
  1585.  
  1586. class Empty:
  1587.  def __init__():
  1588.    x = 0
  1589.  
  1590. class Point:
  1591.  def __init__(x, y):
  1592.    self.x = x
  1593.    self.y = y
  1594.  
  1595.  def SetX(value):
  1596.    self.x = value
  1597.  def SetY(value):
  1598.    self.y = value
  1599.  
  1600.  def __str__():
  1601.    return '(' + str(self.x) + '; ' + str(self.y) + ')'
  1602.  
  1603. origin = Empty()
  1604. origin = Point(0, 0)
  1605.  
  1606. far_far_away = Point(10000, 50000)
  1607.  
  1608. print program_name, origin, far_far_away, origin.SetX(1)
  1609. )"s;
  1610.  
  1611.     runtime::DummyContext context;
  1612.  
  1613.     runtime::Closure closure;
  1614.     auto tree = ParseProgramFromString(program);
  1615.     tree->Execute(closure, context);
  1616.  
  1617.     ASSERT_EQUAL(context.output.str(), "Classes test (0; 0) (10000; 50000) None\n"s);
  1618. }
  1619.  
  1620. void TestProgramWithIf() {
  1621.     const string program = R"(
  1622. x = 4
  1623. y = 5
  1624. if x > y:
  1625.  print "x > y"
  1626. else:
  1627.  print "x <= y"
  1628. if x > 0:
  1629.  if y < 0:
  1630.    print "y < 0"
  1631.  else:
  1632.    print "y >= 0"
  1633. else:
  1634.  print 'x <= 0'
  1635. )"s;
  1636.  
  1637.     runtime::DummyContext context;
  1638.  
  1639.     runtime::Closure closure;
  1640.     auto tree = ParseProgramFromString(program);
  1641.     tree->Execute(closure, context);
  1642.  
  1643.     ASSERT_EQUAL(context.output.str(), "x <= y\ny >= 0\n"s);
  1644. }
  1645.  
  1646. void TestReturnFromIf() {
  1647.     const string program = R"(
  1648. class Abs:
  1649.  def calc(n):
  1650.    if n > 0:
  1651.      return n
  1652.    else:
  1653.      return -n
  1654.  
  1655. x = Abs()
  1656. print x.calc(2)
  1657. )"s;
  1658.  
  1659.     runtime::DummyContext context;
  1660.  
  1661.     runtime::Closure closure;
  1662.     auto tree = ParseProgramFromString(program);
  1663.     tree->Execute(closure, context);
  1664.  
  1665.     ASSERT_EQUAL(context.output.str(), "2\n"s);
  1666. }
  1667.  
  1668. void TestRecursion() {
  1669.     const string program = R"(
  1670. class ArithmeticProgression:
  1671.  def calc(n):
  1672.    self.result = 0
  1673.    self.calc_impl(n)
  1674.  
  1675.  def calc_impl(n):
  1676.    value = n
  1677.    if value > 0:
  1678.      self.result = self.result + value
  1679.      self.calc_impl(value - 1)
  1680.  
  1681. x = ArithmeticProgression()
  1682. x.calc(10)
  1683. print x.result
  1684. )"s;
  1685.  
  1686.     runtime::DummyContext context;
  1687.  
  1688.     runtime::Closure closure;
  1689.     auto tree = ParseProgramFromString(program);
  1690.     tree->Execute(closure, context);
  1691.  
  1692.     ASSERT_EQUAL(context.output.str(), "55\n"s);
  1693. }
  1694.  
  1695. void TestRecursion2() {
  1696.     const string program = R"(
  1697. class GCD:
  1698.  def __init__():
  1699.    self.call_count = 0
  1700.  
  1701.  def calc(a, b):
  1702.    self.call_count = self.call_count + 1
  1703.    if a < b:
  1704.      return self.calc(b, a)
  1705.    if b == 0:
  1706.      return a
  1707.    return self.calc(a - b, b)
  1708.  
  1709. x = GCD()
  1710. print x.calc(510510, 18629977)
  1711. print x.calc(22, 17)
  1712. print x.call_count
  1713. )"s;
  1714.  
  1715.     runtime::DummyContext context;
  1716.  
  1717.     runtime::Closure closure;
  1718.     auto tree = ParseProgramFromString(program);
  1719.     tree->Execute(closure, context);
  1720.  
  1721.     ASSERT_EQUAL(context.output.str(), "17\n1\n115\n"s);
  1722. }
  1723.  
  1724. void TestComplexLogicalExpression() {
  1725.     const string program = R"(
  1726. a = 1
  1727. b = 2
  1728. c = 3
  1729. ok = a + b > c and a + c > b and b + c > a
  1730. print ok
  1731. )"s;
  1732.  
  1733.     runtime::DummyContext context;
  1734.  
  1735.     runtime::Closure closure;
  1736.     auto tree = ParseProgramFromString(program);
  1737.     tree->Execute(closure, context);
  1738.  
  1739.     ASSERT_EQUAL(context.output.str(), "False\n"s);
  1740. }
  1741.  
  1742. void TestClassicalPolymorphism() {
  1743.     const string program = R"(
  1744. class Shape:
  1745.  def __str__():
  1746.    return "Shape"
  1747.  
  1748. class Rect(Shape):
  1749.  def __init__(w, h):
  1750.    self.w = w
  1751.    self.h = h
  1752.  
  1753.  def __str__():
  1754.    return "Rect(" + str(self.w) + 'x' + str(self.h) + ')'
  1755.  
  1756. class Circle(Shape):
  1757.  def __init__(r):
  1758.    self.r = r
  1759.  
  1760.  def __str__():
  1761.    return 'Circle(' + str(self.r) + ')'
  1762.  
  1763. class Triangle(Shape):
  1764.  def __init__(a, b, c):
  1765.    self.ok = a + b > c and a + c > b and b + c > a
  1766.    if (self.ok):
  1767.      self.a = a
  1768.      self.b = b
  1769.      self.c = c
  1770.  
  1771.  def __str__():
  1772.    if self.ok:
  1773.      return 'Triangle(' + str(self.a) + ', ' + str(self.b) + ', ' + str(self.c) + ')'
  1774.    else:
  1775.      return 'Wrong triangle'
  1776.  
  1777. r = Rect(10, 20)
  1778. c = Circle(52)
  1779. t1 = Triangle(3, 4, 5)
  1780. t2 = Triangle(125, 1, 2)
  1781.  
  1782. print r, c, t1, t2
  1783. )"s;
  1784.  
  1785.     runtime::DummyContext context;
  1786.  
  1787.     runtime::Closure closure;
  1788.     auto tree = ParseProgramFromString(program);
  1789.     tree->Execute(closure, context);
  1790.  
  1791.     ASSERT_EQUAL(context.output.str(),
  1792.                  "Rect(10x20) Circle(52) Triangle(3, 4, 5) Wrong triangle\n"s);
  1793. }
  1794.  
  1795. void TestSelfInConstructor() {
  1796.     const string program = (R"--(
  1797. class X:
  1798.  def __init__(p):
  1799.    p.x = self
  1800. class XHolder:
  1801.  def __init__():
  1802.    dummy = 0
  1803. xh = XHolder()
  1804. x = X(xh)
  1805. )--");
  1806.  
  1807.     runtime::DummyContext context;
  1808.     runtime::Closure closure;
  1809.     auto tree = ParseProgramFromString(program);
  1810.     tree->Execute(closure, context);
  1811.  
  1812.     const auto* xh = closure.at("xh"s).TryAs<runtime::ClassInstance>();
  1813.     ASSERT(xh != nullptr);
  1814.     ASSERT_EQUAL(xh->Fields().at("x"s).Get(), closure.at("x"s).Get());
  1815. }
  1816.  
  1817. }//end namespace parse
  1818.  
  1819. void TestParseProgram(TestRunner& tr) {
  1820.     RUN_TEST(tr, parse::TestSimpleProgram);
  1821.     RUN_TEST(tr, parse::TestProgramWithClasses);
  1822.     RUN_TEST(tr, parse::TestProgramWithIf);
  1823.     RUN_TEST(tr, parse::TestReturnFromIf);
  1824.     RUN_TEST(tr, parse::TestRecursion);
  1825.     RUN_TEST(tr, parse::TestRecursion2);
  1826.     RUN_TEST(tr, parse::TestComplexLogicalExpression);
  1827.     RUN_TEST(tr, parse::TestClassicalPolymorphism);
  1828.     RUN_TEST(tr, parse::TestSelfInConstructor);
  1829. }
  1830. -----------------------------------------------------------------------
  1831. runtime.h
  1832. -----------------------------------------------------------------------
  1833. #pragma once
  1834.  
  1835. #include <memory>
  1836. #include <sstream>
  1837. #include <string>
  1838. #include <unordered_map>
  1839. #include <vector>
  1840. #include <cassert>
  1841.  
  1842. namespace runtime {
  1843.  
  1844. class Context {
  1845. public:
  1846.     virtual std::ostream& GetOutputStream() = 0;
  1847.  
  1848. protected:
  1849.     ~Context() = default;
  1850. };
  1851.  
  1852. class Object {
  1853. public:
  1854.     virtual ~Object() = default;
  1855.     virtual void Print(std::ostream& os, Context& context) = 0;
  1856. };
  1857.  
  1858. class ObjectHolder {
  1859. public:
  1860.     ObjectHolder() = default;
  1861.  
  1862.     template <typename T>
  1863.     [[nodiscard]] static ObjectHolder Own(T&& object) {
  1864.         return ObjectHolder(std::make_shared<T>(std::forward<T>(object)));
  1865.     }
  1866.  
  1867.     [[nodiscard]] static ObjectHolder Share(Object& object);
  1868.     [[nodiscard]] static ObjectHolder None();
  1869.  
  1870.     Object& operator*() const;
  1871.     Object* operator->() const;
  1872.     [[nodiscard]] Object* Get() const;
  1873.  
  1874.     template <typename T>
  1875.     [[nodiscard]] T* TryAs() const {return dynamic_cast<T*>(this->Get());}
  1876.  
  1877.     explicit operator bool() const;
  1878.  
  1879. private:
  1880.    
  1881.     explicit ObjectHolder(std::shared_ptr<Object> data);  
  1882.     void AssertIsValid() const;
  1883.     std::shared_ptr<Object> data_;
  1884. };
  1885.  
  1886. template <typename T>
  1887. class ValueObject : public Object {
  1888. public:
  1889.    
  1890.     ValueObject(T v) : value_(v) {}
  1891.     void Print(std::ostream& os, [[maybe_unused]] Context& context) override {os << value_;}
  1892.     [[nodiscard]] const T& GetValue() const {return value_;}
  1893.  
  1894. private:
  1895.     T value_;
  1896. };
  1897.  
  1898. using Closure = std::unordered_map<std::string, ObjectHolder>;
  1899. bool IsTrue(const ObjectHolder& object);
  1900.    
  1901. class Executable {
  1902. public:
  1903.     virtual ~Executable() = default;
  1904.     virtual ObjectHolder Execute(Closure& closure, Context& context) = 0;
  1905. };
  1906.  
  1907. using String = ValueObject<std::string>;
  1908. using Number = ValueObject<int>;
  1909.  
  1910. class Bool : public ValueObject<bool> {
  1911. public:
  1912.    
  1913.     using ValueObject<bool>::ValueObject;
  1914.     void Print(std::ostream& os, Context& context) override;
  1915. };
  1916.  
  1917. struct Method {
  1918.     std::string name;
  1919.     std::vector<std::string> formal_params;
  1920.     std::unique_ptr<Executable> body;
  1921. };
  1922.  
  1923. class Class : public Object {
  1924. public:
  1925.  
  1926.     explicit Class(std::string name, std::vector<Method> methods, const Class* parent);
  1927.     [[nodiscard]] const Method* GetMethod(const std::string& name) const;
  1928.     [[nodiscard]] const std::string& GetName() const;
  1929.     void Print(std::ostream& os, Context& context) override;
  1930.    
  1931. private:
  1932.  
  1933.     std::unordered_map<std::string_view, const Method*> methods_with_name_;
  1934.     std::string name_;
  1935.     std::vector<Method> methods_;
  1936.    
  1937.     const Class* parent_ = nullptr;
  1938. };
  1939.  
  1940. class ClassInstance : public Object {
  1941. public:
  1942.     explicit ClassInstance(const Class& cls);
  1943.  
  1944.     void Print(std::ostream& os, Context& context) override;
  1945.  
  1946.     ObjectHolder Call(const std::string& method, const std::vector<ObjectHolder>& actual_args, Context& context);
  1947.     [[nodiscard]] bool HasMethod(const std::string& method, size_t argument_count) const;
  1948.     [[nodiscard]] Closure& Fields();
  1949.     [[nodiscard]] const Closure& Fields() const;
  1950.    
  1951. private:
  1952.     const Class& class_;
  1953.     Closure fields_;
  1954. };
  1955.  
  1956. bool Equal(const ObjectHolder& lhs, const ObjectHolder& rhs, Context& context);
  1957. bool Less(const ObjectHolder& lhs, const ObjectHolder& rhs, Context& context);
  1958. bool NotEqual(const ObjectHolder& lhs, const ObjectHolder& rhs, Context& context);
  1959. bool Greater(const ObjectHolder& lhs, const ObjectHolder& rhs, Context& context);
  1960. bool LessOrEqual(const ObjectHolder& lhs, const ObjectHolder& rhs, Context& context);
  1961. bool GreaterOrEqual(const ObjectHolder& lhs, const ObjectHolder& rhs, Context& context);
  1962.  
  1963. struct DummyContext : Context {
  1964.    
  1965.     std::ostream& GetOutputStream() override {return output;}
  1966.     std::ostringstream output;
  1967. };
  1968.  
  1969. class SimpleContext : public runtime::Context {
  1970. public:
  1971.    
  1972.     explicit SimpleContext(std::ostream& output) : output_(output) {}
  1973.     std::ostream& GetOutputStream() override {return output_;}
  1974.  
  1975. private:
  1976.     std::ostream& output_;
  1977. };
  1978.  
  1979. }//end namespace runtime
  1980. -----------------------------------------------------------------------
  1981. runtime.cpp
  1982. -----------------------------------------------------------------------
  1983. #include "runtime.h"
  1984.  
  1985. #include <cassert>
  1986. #include <optional>
  1987. #include <sstream>
  1988.  
  1989. using namespace std;
  1990.  
  1991. namespace runtime {
  1992.  
  1993. ObjectHolder::ObjectHolder(std::shared_ptr<Object> data) : data_(std::move(data)) {}
  1994. void ObjectHolder::AssertIsValid() const {assert(data_ != nullptr);}
  1995.  
  1996. ObjectHolder ObjectHolder::Share(Object& object) {return ObjectHolder(std::shared_ptr<Object>(&object, [](auto*) {}));}
  1997. ObjectHolder ObjectHolder::None() {return ObjectHolder();}
  1998.  
  1999. Object& ObjectHolder::operator*() const {
  2000.     AssertIsValid();
  2001.     return *Get();
  2002. }
  2003.  
  2004. Object* ObjectHolder::operator->() const {
  2005.     AssertIsValid();
  2006.     return Get();
  2007. }
  2008.  
  2009. Object* ObjectHolder::Get() const {return data_.get();}
  2010. ObjectHolder::operator bool() const {return Get() != nullptr;}
  2011.  
  2012. bool IsTrue(const ObjectHolder& object) {
  2013.    
  2014.     if (!object) {return false;}
  2015.    
  2016.     auto object_boolean = object.TryAs<Bool>();
  2017.     if (object_boolean) {return object_boolean->GetValue();}
  2018.    
  2019.     auto object_string = object.TryAs<String>();
  2020.     if (object_string && !object_string->GetValue().empty()) {return true;}
  2021.    
  2022.     auto object_number = object.TryAs<Number>();
  2023.     if (object_number && object_number->GetValue() != 0) {return true;}
  2024.    
  2025.     auto object_val_boolean = object.TryAs<ValueObject<bool>>();
  2026.     if (object_val_boolean) {return object_val_boolean->GetValue();}
  2027.    
  2028.     return false;
  2029. }
  2030.  
  2031. void ClassInstance::Print(std::ostream& os, Context& context) {
  2032.    
  2033.     if (this->HasMethod("__str__", 0)) {
  2034.         this->Call("__str__", {}, context)->Print(os, context);
  2035.        
  2036.     } else {
  2037.         os << this;
  2038.     }
  2039. }
  2040.  
  2041. bool ClassInstance::HasMethod(const std::string& method, size_t argument_count) const {
  2042.     return (class_.GetMethod(method) && class_.GetMethod(method)->formal_params.size() == argument_count);
  2043. }
  2044.  
  2045. Closure& ClassInstance::Fields() {return fields_;}
  2046. const Closure& ClassInstance::Fields() const {return fields_;}
  2047. ClassInstance::ClassInstance(const Class& cls) : class_(cls) {}
  2048.  
  2049. ObjectHolder ClassInstance::Call(const std::string& method, const std::vector<ObjectHolder>& actual_args, Context& context) {
  2050.    
  2051.     if (!this->HasMethod(method, actual_args.size())) {
  2052.         throw std::runtime_error("not implemented"s);
  2053.     }
  2054.    
  2055.     Closure closure = {{"self", ObjectHolder::Share(*this)}};
  2056.     auto method_ptr = class_.GetMethod(method);
  2057.    
  2058.     for (size_t i = 0; i < method_ptr->formal_params.size(); ++i) {
  2059.         auto arg = method_ptr->formal_params[i];
  2060.         closure[arg] = actual_args[i];
  2061.     }
  2062.    
  2063.     return method_ptr->body->Execute(closure, context);
  2064. }
  2065.  
  2066. Class::Class(std::string name, std::vector<Method> methods, const Class* parent) : name_(std::move(name))
  2067.                                                                                  , methods_(std::move(methods))
  2068.                                                                                  , parent_(std::move(parent)) {
  2069.     if (parent_) {
  2070.        
  2071.         for (const auto& method : parent_->methods_) {
  2072.             methods_with_name_[method.name] = &method;
  2073.         }
  2074.     }
  2075.    
  2076.     for (const auto& method : methods_) {
  2077.         methods_with_name_[method.name] = &method;
  2078.     }
  2079. }
  2080.  
  2081. const Method* Class::GetMethod(const std::string& name) const {
  2082.    
  2083.     if (methods_with_name_.find(name) != methods_with_name_.end()) {
  2084.         return methods_with_name_.at(name);
  2085.        
  2086.     } else {
  2087.         return nullptr;
  2088.     }
  2089. }
  2090.  
  2091. const std::string& Class::GetName() const {return name_;}
  2092. void Class::Print(ostream& os, [[maybe_unused]] Context& context) {os <<"Class "sv << GetName();}
  2093. void Bool::Print(std::ostream& os, [[maybe_unused]] Context& context) {os << (GetValue() ? "True"sv : "False"sv);}
  2094.  
  2095. bool Equal(const ObjectHolder& lhs, const ObjectHolder& rhs, Context& context) {
  2096.    
  2097.     if (!lhs && !rhs) {
  2098.         return true;
  2099.        
  2100.     } else {
  2101.        
  2102.         if (!lhs) {
  2103.             throw std::runtime_error("invalid args. cannot compare. == or !="s);
  2104.            
  2105.         } else {
  2106.            
  2107.             auto lhs_string = lhs.TryAs<String>();
  2108.             auto rhs_string = rhs.TryAs<String>();        
  2109.             if (lhs_string && rhs_string) {return lhs_string->GetValue() == rhs_string->GetValue();}
  2110.  
  2111.             auto lhs_number = lhs.TryAs<Number>();
  2112.             auto rhs_number = rhs.TryAs<Number>();
  2113.             if (lhs_number && rhs_number) {return lhs_number->GetValue() == rhs_number->GetValue();}
  2114.  
  2115.             auto lhs_boolean = lhs.TryAs<Bool>();
  2116.             auto rhs_boolean = rhs.TryAs<Bool>();
  2117.             if (lhs_boolean && rhs_boolean) {return lhs_boolean->GetValue() == rhs_boolean->GetValue();}
  2118.  
  2119.             auto lhs_class = lhs.TryAs<ClassInstance>();
  2120.             if (lhs_class && lhs_class->HasMethod("__eq__", 1)) {
  2121.  
  2122.                 auto result = lhs_class->Call("__eq__", {rhs}, context);
  2123.                 return result.TryAs<Bool>()->GetValue();
  2124.             }
  2125.  
  2126.             throw std::runtime_error("invalid args. cannot compare. == or !="s);
  2127.         }
  2128.     }
  2129. }
  2130.  
  2131. bool Less(const ObjectHolder& lhs, const ObjectHolder& rhs, Context& context) {
  2132.    
  2133.     if (!lhs) {
  2134.         throw std::runtime_error("invalid args. cannot compare. < or >"s);
  2135.        
  2136.     } else {
  2137.        
  2138.         auto lhs_string = lhs.TryAs<String>();
  2139.         auto rhs_string = rhs.TryAs<String>();
  2140.         if (lhs_string && rhs_string) {return lhs_string->GetValue() < rhs_string->GetValue();}
  2141.        
  2142.         auto lhs_number = lhs.TryAs<Number>();
  2143.         auto rhs_number = rhs.TryAs<Number>();
  2144.         if (lhs_number && rhs_number) {return lhs_number->GetValue() < rhs_number->GetValue();}
  2145.        
  2146.         auto lhs_boolean = lhs.TryAs<Bool>();
  2147.         auto rhs_boolean = rhs.TryAs<Bool>();
  2148.         if (lhs_boolean && rhs_boolean) {return lhs_boolean->GetValue() < rhs_boolean->GetValue();}
  2149.        
  2150.         auto lhs_class = lhs.TryAs<ClassInstance>();
  2151.         if (lhs_class && lhs_class->HasMethod("__lt__", 1)) {
  2152.            
  2153.             auto result = lhs_class->Call("__lt__", { rhs }, context);
  2154.             return result.TryAs<Bool>()->GetValue();
  2155.         }
  2156.        
  2157.         throw std::runtime_error("invalid args. cannot compare. < or >"s);
  2158.     }
  2159. }
  2160.  
  2161. bool NotEqual(const ObjectHolder& lhs, const ObjectHolder& rhs, Context& context) {return !Equal(lhs, rhs, context);}
  2162. bool Greater(const ObjectHolder& lhs, const ObjectHolder& rhs, Context& context) {return !Less(lhs, rhs, context) && !Equal(lhs, rhs, context);}
  2163. bool LessOrEqual(const ObjectHolder& lhs, const ObjectHolder& rhs, Context& context) {return Less(lhs, rhs, context) || Equal(lhs, rhs, context);}
  2164. bool GreaterOrEqual(const ObjectHolder& lhs, const ObjectHolder& rhs, Context& context) {return !Less(lhs, rhs, context);}
  2165.  
  2166. }//end namespace runtime
  2167. -----------------------------------------------------------------------
  2168. runtime_test.cpp
  2169. -----------------------------------------------------------------------
  2170. #include "runtime.h"
  2171. #include "test_runner_p.h"
  2172.  
  2173. #include <functional>
  2174.  
  2175. using namespace std;
  2176.  
  2177. namespace runtime {
  2178.  
  2179. namespace {
  2180. class Logger : public Object {
  2181. public:
  2182.     static int instance_count;
  2183.  
  2184.     explicit Logger(int value_ = 0) : id_(value_) {++instance_count;}
  2185.  
  2186.     Logger(const Logger& rhs) : id_(rhs.id_) {++instance_count;}
  2187.     Logger(Logger&& rhs) noexcept : id_(rhs.id_) {++instance_count;}
  2188.     Logger& operator=(const Logger&) = default;
  2189.     Logger& operator=(Logger&&) = default;
  2190.  
  2191.     [[nodiscard]] int GetId() const {return id_;}
  2192.    
  2193.     ~Logger() {--instance_count;}
  2194.     void Print(ostream& os, [[maybe_unused]] Context& context) override {os << id_;}
  2195.  
  2196. private:
  2197.     int id_;
  2198. };
  2199.  
  2200. int Logger::instance_count = 0;
  2201.  
  2202. void TestNumber() {
  2203.     Number num(127);
  2204.  
  2205.     DummyContext context;
  2206.  
  2207.     num.Print(context.output, context);
  2208.     ASSERT_EQUAL(context.output.str(), "127"s);
  2209.     ASSERT_EQUAL(num.GetValue(), 127);
  2210. }
  2211.  
  2212. void TestString() {
  2213.     String word("hello!"s);
  2214.  
  2215.     DummyContext context;
  2216.     word.Print(context.output, context);
  2217.     ASSERT_EQUAL(context.output.str(), "hello!"s);
  2218.     ASSERT_EQUAL(word.GetValue(), "hello!"s);
  2219. }
  2220.  
  2221. void TestBool() {
  2222.     Bool t(true);
  2223.     ASSERT_EQUAL(t.GetValue(), true);
  2224.  
  2225.     DummyContext context;
  2226.     ostringstream out;
  2227.     t.Print(out, context);
  2228.     ASSERT_EQUAL(out.str(), "True"s);
  2229.     out.str({});
  2230.  
  2231.     Bool f(false);
  2232.     ASSERT_EQUAL(f.GetValue(), false);
  2233.  
  2234.     f.Print(out, context);
  2235.     ASSERT_EQUAL(out.str(), "False"s);
  2236.  
  2237.     ASSERT(context.output.str().empty());
  2238. }
  2239.  
  2240. struct TestMethodBody : Executable {
  2241.     using Fn = std::function<ObjectHolder(Closure& closure, Context& context)>;
  2242.     Fn body;
  2243.  
  2244.     explicit TestMethodBody(Fn body) : body(std::move(body)) {}
  2245.  
  2246.     ObjectHolder Execute(Closure& closure, Context& context) override {
  2247.        
  2248.         if (body) {
  2249.             return body(closure, context);
  2250.         } else {
  2251.             return {};
  2252.         }    
  2253.     }
  2254. };
  2255.  
  2256. void TestMethodInvocation() {
  2257.     DummyContext context;
  2258.     Closure base_closure;
  2259.     auto base_method_1 = [&base_closure, &context](Closure& closure, Context& ctx) {
  2260.         ASSERT_EQUAL(&context, &ctx);
  2261.         base_closure = closure;
  2262.         return ObjectHolder::Own(Number{123});
  2263.     };
  2264.     auto base_method_2 = [&base_closure, &context](Closure& closure, Context& ctx) {
  2265.         ASSERT_EQUAL(&context, &ctx);
  2266.         base_closure = closure;
  2267.         return ObjectHolder::Own(Number{456});
  2268.     };
  2269.     vector<Method> base_methods;
  2270.     base_methods.push_back(
  2271.         {"test"s, {"arg1"s, "arg2"s}, make_unique<TestMethodBody>(base_method_1)});
  2272.     base_methods.push_back({"test_2"s, {"arg1"s}, make_unique<TestMethodBody>(base_method_2)});
  2273.     Class base_class{"Base"s, std::move(base_methods), nullptr};
  2274.     ClassInstance base_inst{base_class};
  2275.     base_inst.Fields()["base_field"s] = ObjectHolder::Own(String{"hello"s});
  2276.     ASSERT(base_inst.HasMethod("test"s, 2U));
  2277.     auto res = base_inst.Call(
  2278.         "test"s, {ObjectHolder::Own(Number{1}), ObjectHolder::Own(String{"abc"s})}, context);
  2279.     ASSERT(Equal(res, ObjectHolder::Own(Number{123}), context));
  2280.     ASSERT_EQUAL(base_closure.size(), 3U);
  2281.     ASSERT_EQUAL(base_closure.count("self"s), 1U);
  2282.     ASSERT_EQUAL(base_closure.at("self"s).Get(), &base_inst);
  2283.     ASSERT_EQUAL(base_closure.count("self"s), 1U);
  2284.     ASSERT_EQUAL(base_closure.count("arg1"s), 1U);
  2285.     ASSERT(Equal(base_closure.at("arg1"s), ObjectHolder::Own(Number{1}), context));
  2286.     ASSERT_EQUAL(base_closure.count("arg2"s), 1U);
  2287.     ASSERT(Equal(base_closure.at("arg2"s), ObjectHolder::Own(String{"abc"s}), context));
  2288.     ASSERT_EQUAL(base_closure.count("base_field"s), 0U);
  2289.  
  2290.     Closure child_closure;
  2291.     auto child_method_1 = [&child_closure, &context](Closure& closure, Context& ctx) {
  2292.         ASSERT_EQUAL(&context, &ctx);
  2293.         child_closure = closure;
  2294.         return ObjectHolder::Own(String("child"s));
  2295.     };
  2296.     vector<Method> child_methods;
  2297.     child_methods.push_back(
  2298.         {"test"s, {"arg1_child"s, "arg2_child"s}, make_unique<TestMethodBody>(child_method_1)});
  2299.     Class child_class{"Child"s, std::move(child_methods), &base_class};
  2300.     ClassInstance child_inst{child_class};
  2301.     ASSERT(child_inst.HasMethod("test"s, 2U));
  2302.     base_closure.clear();
  2303.     res = child_inst.Call(
  2304.         "test"s, {ObjectHolder::Own(String{"value1"s}), ObjectHolder::Own(String{"value2"s})},
  2305.         context);
  2306.     ASSERT(Equal(res, ObjectHolder::Own(String{"child"s}), context));
  2307.     ASSERT(base_closure.empty());
  2308.     ASSERT_EQUAL(child_closure.size(), 3U);
  2309.     ASSERT_EQUAL(child_closure.count("self"s), 1U);
  2310.     ASSERT_EQUAL(child_closure.at("self"s).Get(), &child_inst);
  2311.     ASSERT_EQUAL(child_closure.count("arg1_child"s), 1U);
  2312.     ASSERT(Equal(child_closure.at("arg1_child"s), (ObjectHolder::Own(String{"value1"s})), context));
  2313.     ASSERT_EQUAL(child_closure.count("arg2_child"s), 1U);
  2314.     ASSERT(Equal(child_closure.at("arg2_child"s), (ObjectHolder::Own(String{"value2"s})), context));
  2315.  
  2316.     ASSERT(child_inst.HasMethod("test_2"s, 1U));
  2317.     child_closure.clear();
  2318.     res = child_inst.Call("test_2"s, {ObjectHolder::Own(String{":)"s})}, context);
  2319.     ASSERT(Equal(res, ObjectHolder::Own(Number{456}), context));
  2320.     ASSERT_EQUAL(base_closure.size(), 2U);
  2321.     ASSERT_EQUAL(base_closure.count("self"s), 1U);
  2322.     ASSERT_EQUAL(base_closure.at("self"s).Get(), &child_inst);
  2323.     ASSERT_EQUAL(base_closure.count("arg1"s), 1U);
  2324.     ASSERT(Equal(base_closure.at("arg1"s), (ObjectHolder::Own(String{":)"s})), context));
  2325.  
  2326.     ASSERT(!child_inst.HasMethod("test"s, 1U));
  2327.     ASSERT_THROWS(child_inst.Call("test"s, {ObjectHolder::None()}, context), runtime_error);
  2328. }
  2329.  
  2330. void TestNonowning() {
  2331.     ASSERT_EQUAL(Logger::instance_count, 0);
  2332.     Logger logger(784);
  2333.     {
  2334.         auto oh = ObjectHolder::Share(logger);
  2335.         ASSERT(oh);
  2336.     }
  2337.     ASSERT_EQUAL(Logger::instance_count, 1);
  2338.  
  2339.     auto oh = ObjectHolder::Share(logger);
  2340.     ASSERT(oh);
  2341.     ASSERT(oh.Get() == &logger);
  2342.  
  2343.     DummyContext context;
  2344.     oh->Print(context.output, context);
  2345.  
  2346.     ASSERT_EQUAL(context.output.str(), "784"sv);
  2347. }
  2348.  
  2349. void TestOwning() {
  2350.     ASSERT_EQUAL(Logger::instance_count, 0);
  2351.     {
  2352.         auto oh = ObjectHolder::Own(Logger());
  2353.         ASSERT(oh);
  2354.         ASSERT_EQUAL(Logger::instance_count, 1);
  2355.     }
  2356.     ASSERT_EQUAL(Logger::instance_count, 0);
  2357.  
  2358.     auto oh = ObjectHolder::Own(Logger(312));
  2359.     ASSERT(oh);
  2360.     ASSERT_EQUAL(Logger::instance_count, 1);
  2361.  
  2362.     DummyContext context;
  2363.     oh->Print(context.output, context);
  2364.  
  2365.     ASSERT_EQUAL(context.output.str(), "312"sv);
  2366. }
  2367.  
  2368. void TestMove() {
  2369.     {
  2370.         ASSERT_EQUAL(Logger::instance_count, 0);
  2371.         Logger logger;
  2372.  
  2373.         auto one = ObjectHolder::Share(logger);
  2374.         ObjectHolder two = std::move(one);
  2375.  
  2376.         ASSERT_EQUAL(Logger::instance_count, 1);
  2377.         ASSERT(two.Get() == &logger);
  2378.     }
  2379.     {
  2380.         ASSERT_EQUAL(Logger::instance_count, 0);
  2381.         auto one = ObjectHolder::Own(Logger());
  2382.         ASSERT_EQUAL(Logger::instance_count, 1);
  2383.         Object* stored = one.Get();
  2384.         ObjectHolder two = std::move(one);
  2385.         ASSERT_EQUAL(Logger::instance_count, 1);
  2386.  
  2387.         ASSERT(two.Get() == stored);
  2388.         ASSERT(!one);
  2389.     }
  2390. }
  2391.  
  2392. void TestNullptr() {
  2393.     ObjectHolder oh;
  2394.     ASSERT(!oh);
  2395.     ASSERT(!oh.Get());
  2396. }
  2397.  
  2398. void TestIsTrue() {
  2399.     {
  2400.         ASSERT(!IsTrue(ObjectHolder::Own(Bool{false})));
  2401.         ASSERT(IsTrue(ObjectHolder::Own(Bool{true})));
  2402.     }
  2403.  
  2404.     ASSERT(!IsTrue(ObjectHolder::None()));
  2405.  
  2406.     {
  2407.         ASSERT(!IsTrue(ObjectHolder::Own(Number{0})));
  2408.         ASSERT(IsTrue(ObjectHolder::Own(Number{1})));
  2409.         ASSERT(IsTrue(ObjectHolder::Own(Number{-1})));
  2410.         ASSERT(IsTrue(ObjectHolder::Own(Number{42})));
  2411.     }
  2412.  
  2413.     {
  2414.         ASSERT(!IsTrue(ObjectHolder::Own(String{""s})));
  2415.         ASSERT(IsTrue(ObjectHolder::Own(String{"0"s})));
  2416.         ASSERT(IsTrue(ObjectHolder::Own(String{"1"s})));
  2417.         ASSERT(IsTrue(ObjectHolder::Own(String{"abc"s})));
  2418.         ASSERT(IsTrue(ObjectHolder::Own(String{"True"s})));
  2419.         ASSERT(IsTrue(ObjectHolder::Own(String{"False"s})));
  2420.     }
  2421.  
  2422.     {
  2423.         Class cls{"Test"s, {}, nullptr};
  2424.         ASSERT(!IsTrue(ObjectHolder::Share(cls)));
  2425.         ASSERT(!IsTrue(ObjectHolder::Own(ClassInstance{cls})));
  2426.     }
  2427. }
  2428.  
  2429. void TestComparison() {
  2430.     auto test_equal = [](const ObjectHolder& lhs, const ObjectHolder& rhs, bool equality_result) {
  2431.         DummyContext ctx;
  2432.         ASSERT(Equal(lhs, rhs, ctx) == equality_result);
  2433.         ASSERT(NotEqual(lhs, rhs, ctx) == !equality_result);
  2434.     };
  2435.  
  2436.     auto test_less = [](const ObjectHolder& lhs, const ObjectHolder& rhs, bool less_result) {
  2437.         DummyContext ctx;
  2438.         ASSERT(Less(lhs, rhs, ctx) == less_result);
  2439.         ASSERT(GreaterOrEqual(lhs, rhs, ctx) == !less_result);
  2440.     };
  2441.  
  2442.     auto test_greater = [](const ObjectHolder& lhs, const ObjectHolder& rhs, bool greater_result) {
  2443.         DummyContext ctx;
  2444.         ASSERT(Greater(lhs, rhs, ctx) == greater_result);
  2445.         ASSERT(LessOrEqual(lhs, rhs, ctx) == !greater_result);
  2446.     };
  2447.  
  2448.     auto test_eq_uncomparable = [](const ObjectHolder& lhs, const ObjectHolder& rhs) {
  2449.         DummyContext ctx;
  2450.         ASSERT_THROWS(Equal(lhs, rhs, ctx), runtime_error);
  2451.         ASSERT_THROWS(NotEqual(lhs, rhs, ctx), runtime_error);
  2452.     };
  2453.  
  2454.     auto test_lt_uncomparable = [](const ObjectHolder& lhs, const ObjectHolder& rhs) {
  2455.         DummyContext ctx;
  2456.         ASSERT_THROWS(Less(lhs, rhs, ctx), runtime_error);
  2457.         ASSERT_THROWS(GreaterOrEqual(lhs, rhs, ctx), runtime_error);
  2458.     };
  2459.  
  2460.     auto test_gt_uncomparable = [](const ObjectHolder& lhs, const ObjectHolder& rhs) {
  2461.         DummyContext ctx;
  2462.         ASSERT_THROWS(Greater(lhs, rhs, ctx), runtime_error);
  2463.         ASSERT_THROWS(LessOrEqual(lhs, rhs, ctx), runtime_error);
  2464.     };
  2465.  
  2466.     {
  2467.         test_equal(ObjectHolder::Own(Number{3}), ObjectHolder::Own(Number{3}), true);
  2468.         test_equal(ObjectHolder::Own(Number{3}), ObjectHolder::Own(Number{4}), false);
  2469.         test_equal(ObjectHolder::Own(Number{4}), ObjectHolder::Own(Number{3}), false);
  2470.  
  2471.         test_less(ObjectHolder::Own(Number{3}), ObjectHolder::Own(Number{4}), true);
  2472.         test_less(ObjectHolder::Own(Number{3}), ObjectHolder::Own(Number{3}), false);
  2473.         test_less(ObjectHolder::Own(Number{3}), ObjectHolder::Own(Number{2}), false);
  2474.  
  2475.         test_greater(ObjectHolder::Own(Number{4}), ObjectHolder::Own(Number{2}), true);
  2476.         test_greater(ObjectHolder::Own(Number{3}), ObjectHolder::Own(Number{3}), false);
  2477.         test_greater(ObjectHolder::Own(Number{2}), ObjectHolder::Own(Number{3}), false);
  2478.  
  2479.         test_eq_uncomparable(ObjectHolder::Own(Number{4}), ObjectHolder::Own(String{"4"s}));
  2480.         test_eq_uncomparable(ObjectHolder::Own(Number{0}), ObjectHolder::Own(Bool{false}));
  2481.  
  2482.         test_lt_uncomparable(ObjectHolder::Own(Number{0}), ObjectHolder::Own(Bool{false}));
  2483.         test_gt_uncomparable(ObjectHolder::Own(Number{0}), ObjectHolder::Own(String{"test"s}));
  2484.     }
  2485.  
  2486.     {
  2487.         test_equal(ObjectHolder::Own(String{""s}), ObjectHolder::Own(String{""s}), true);
  2488.         test_equal(ObjectHolder::Own(String{"1"s}), ObjectHolder::Own(String{""s}), false);
  2489.         test_equal(ObjectHolder::Own(String{""s}), ObjectHolder::Own(String{"1"s}), false);
  2490.         test_equal(ObjectHolder::Own(String{"Hello"s}), ObjectHolder::Own(String{"Hello"s}), true);
  2491.         test_equal(ObjectHolder::Own(String{"Hello"s}), ObjectHolder::Own(String{"hello"s}), false);
  2492.  
  2493.         test_less(ObjectHolder::Own(String{""s}), ObjectHolder::Own(String{"1"s}), true);
  2494.         test_less(ObjectHolder::Own(String{"abb"s}), ObjectHolder::Own(String{"abc"s}), true);
  2495.         test_less(ObjectHolder::Own(String{""s}), ObjectHolder::Own(String{""s}), false);
  2496.         test_less(ObjectHolder::Own(String{"abc"s}), ObjectHolder::Own(String{"abc"s}), false);
  2497.         test_less(ObjectHolder::Own(String{"abc"s}), ObjectHolder::Own(String{"abb"s}), false);
  2498.  
  2499.         test_greater(ObjectHolder::Own(String{"1"s}), ObjectHolder::Own(String{""s}), true);
  2500.         test_greater(ObjectHolder::Own(String{"abc"s}), ObjectHolder::Own(String{"abb"s}), true);
  2501.         test_greater(ObjectHolder::Own(String{""s}), ObjectHolder::Own(String{""s}), false);
  2502.         test_greater(ObjectHolder::Own(String{"abc"s}), ObjectHolder::Own(String{"abc"s}), false);
  2503.         test_greater(ObjectHolder::Own(String{"abb"s}), ObjectHolder::Own(String{"abc"s}), false);
  2504.  
  2505.         test_eq_uncomparable(ObjectHolder::Own(String{"123"s}), ObjectHolder::Own(Number{123}));
  2506.         test_eq_uncomparable(ObjectHolder::Own(String{"True"s}), ObjectHolder::Own(Bool{true}));
  2507.  
  2508.         test_lt_uncomparable(ObjectHolder::Own(String{"123"s}), ObjectHolder::Own(Number{123}));
  2509.         test_lt_uncomparable(ObjectHolder::Own(String{"True"s}), ObjectHolder::Own(Bool{true}));
  2510.  
  2511.         test_gt_uncomparable(ObjectHolder::Own(String{"123"s}), ObjectHolder::Own(Number{123}));
  2512.         test_gt_uncomparable(ObjectHolder::Own(String{"True"s}), ObjectHolder::Own(Bool{true}));
  2513.     }
  2514.  
  2515.     {
  2516.         test_equal(ObjectHolder::Own(Bool{true}), ObjectHolder::Own(Bool{true}), true);
  2517.         test_equal(ObjectHolder::Own(Bool{false}), ObjectHolder::Own(Bool{false}), true);
  2518.         test_equal(ObjectHolder::Own(Bool{false}), ObjectHolder::Own(Bool{true}), false);
  2519.         test_equal(ObjectHolder::Own(Bool{true}), ObjectHolder::Own(Bool{false}), false);
  2520.  
  2521.         test_less(ObjectHolder::Own(Bool{false}), ObjectHolder::Own(Bool{true}), true);
  2522.         test_less(ObjectHolder::Own(Bool{true}), ObjectHolder::Own(Bool{true}), false);
  2523.         test_less(ObjectHolder::Own(Bool{false}), ObjectHolder::Own(Bool{false}), false);
  2524.         test_less(ObjectHolder::Own(Bool{true}), ObjectHolder::Own(Bool{false}), false);
  2525.  
  2526.         test_greater(ObjectHolder::Own(Bool{false}), ObjectHolder::Own(Bool{true}), false);
  2527.         test_greater(ObjectHolder::Own(Bool{true}), ObjectHolder::Own(Bool{true}), false);
  2528.         test_greater(ObjectHolder::Own(Bool{false}), ObjectHolder::Own(Bool{false}), false);
  2529.         test_greater(ObjectHolder::Own(Bool{true}), ObjectHolder::Own(Bool{false}), true);
  2530.  
  2531.         test_eq_uncomparable(ObjectHolder::Own(Bool{true}), ObjectHolder::Own(String{"true"s}));
  2532.         test_eq_uncomparable(ObjectHolder::Own(Bool{false}), ObjectHolder::Own(Number{0}));
  2533.  
  2534.         test_lt_uncomparable(ObjectHolder::Own(Bool{true}), ObjectHolder::Own(String{"true"s}));
  2535.         test_lt_uncomparable(ObjectHolder::Own(Bool{false}), ObjectHolder::Own(Number{0}));
  2536.  
  2537.         test_gt_uncomparable(ObjectHolder::Own(Bool{true}), ObjectHolder::Own(String{"true"s}));
  2538.         test_gt_uncomparable(ObjectHolder::Own(Bool{false}), ObjectHolder::Own(Number{0}));
  2539.     }
  2540.  
  2541.     {
  2542.         test_equal(ObjectHolder::None(), ObjectHolder::None(), true);
  2543.  
  2544.         test_eq_uncomparable(ObjectHolder::None(), ObjectHolder::Own(Bool{false}));
  2545.         test_eq_uncomparable(ObjectHolder::None(), ObjectHolder::Own(String{"None"s}));
  2546.  
  2547.         test_lt_uncomparable(ObjectHolder::None(), ObjectHolder::None());
  2548.         test_gt_uncomparable(ObjectHolder::None(), ObjectHolder::None());
  2549.     }
  2550.  
  2551.     {
  2552.         Closure eq_closure;
  2553.         auto eq_result = ObjectHolder::Own(Bool{true});
  2554.         auto eq_body = [&eq_closure, &eq_result](Closure& closure, [[maybe_unused]] Context& ctx) {
  2555.             eq_closure = closure;
  2556.             return eq_result;
  2557.         };
  2558.  
  2559.         Closure lt_closure;
  2560.         auto lt_result = ObjectHolder::Own(Bool{true});
  2561.         auto lt_body = [&lt_closure, &lt_result](Closure& closure, [[maybe_unused]] Context& ctx) {
  2562.             lt_closure = closure;
  2563.             return lt_result;
  2564.         };
  2565.  
  2566.         std::vector<Method> cls1_methods;
  2567.         cls1_methods.push_back({"__eq__"s, {"rhs"s}, std::make_unique<TestMethodBody>(eq_body)});
  2568.         cls1_methods.push_back({"__lt__"s, {"rhs"s}, std::make_unique<TestMethodBody>(lt_body)});
  2569.         Class cls1{"Class1"s, std::move(cls1_methods), nullptr};
  2570.         ClassInstance lhs{cls1};
  2571.  
  2572.         Class cls2{"Class2"s, {}, nullptr};
  2573.         ClassInstance rhs{cls2};
  2574.  
  2575.         eq_result = ObjectHolder::Own(Bool{true});
  2576.         test_equal(ObjectHolder::Share(lhs), ObjectHolder::Share(rhs), true);
  2577.         ASSERT(eq_closure.at("self"s).TryAs<ClassInstance>() == &lhs);
  2578.         ASSERT(eq_closure.at("rhs"s).TryAs<ClassInstance>() == &rhs);
  2579.         ASSERT(lt_closure.empty());
  2580.         eq_result = ObjectHolder::Own(Bool{false});
  2581.         test_equal(ObjectHolder::Share(lhs), ObjectHolder::Share(rhs), false);
  2582.         eq_closure.clear();
  2583.         lt_closure.clear();
  2584.  
  2585.         eq_result = ObjectHolder::Own(Bool{false});
  2586.         lt_result = ObjectHolder::Own(Bool{true});
  2587.         test_less(ObjectHolder::Share(lhs), ObjectHolder::Share(rhs), true);
  2588.         ASSERT(lt_closure.at("self"s).TryAs<ClassInstance>() == &lhs);
  2589.         ASSERT(lt_closure.at("rhs"s).TryAs<ClassInstance>() == &rhs);
  2590.         ASSERT(eq_closure.empty());
  2591.         eq_result = ObjectHolder::Own(Bool{true});
  2592.         lt_result = ObjectHolder::Own(Bool{false});
  2593.         test_less(ObjectHolder::Share(lhs), ObjectHolder::Share(rhs), false);
  2594.         eq_closure.clear();
  2595.         lt_closure.clear();
  2596.  
  2597.         eq_result = ObjectHolder::Own(Bool{false});
  2598.         lt_result = ObjectHolder::Own(Bool{false});
  2599.         test_greater(ObjectHolder::Share(lhs), ObjectHolder::Share(rhs), true);
  2600.         ASSERT(eq_closure.at("self"s).TryAs<ClassInstance>() == &lhs);
  2601.         ASSERT(eq_closure.at("rhs"s).TryAs<ClassInstance>() == &rhs);
  2602.         ASSERT(lt_closure.at("self"s).TryAs<ClassInstance>() == &lhs);
  2603.         ASSERT(lt_closure.at("rhs"s).TryAs<ClassInstance>() == &rhs);
  2604.         eq_result = ObjectHolder::Own(Bool{true});
  2605.         lt_result = ObjectHolder::Own(Bool{true});
  2606.         test_greater(ObjectHolder::Share(lhs), ObjectHolder::Share(rhs), false);
  2607.     }
  2608. }
  2609.  
  2610. void TestClass() {
  2611.     vector<Method> methods;
  2612.     Closure* passed_closure = nullptr;
  2613.     Context* passed_context = nullptr;
  2614.     auto body = [&passed_closure, &passed_context](Closure& closure, Context& ctx) {
  2615.         passed_closure = &closure;
  2616.         passed_context = &ctx;
  2617.         return ObjectHolder::Own(Number{42});
  2618.     };
  2619.     methods.push_back({"method"s, {"arg1"s, "arg2"s}, make_unique<TestMethodBody>(body)});
  2620.     Class cls{"Test"s, move(methods), nullptr};
  2621.     ASSERT_EQUAL(cls.GetName(), "Test"s);
  2622.     ASSERT_EQUAL(cls.GetMethod("missing_method"s), nullptr);
  2623.  
  2624.     const Method* method = cls.GetMethod("method"s);
  2625.     ASSERT(method != nullptr);
  2626.     DummyContext ctx;
  2627.     Closure closure;
  2628.     auto result = method->body->Execute(closure, ctx);
  2629.     ASSERT_EQUAL(passed_context, &ctx);
  2630.     ASSERT_EQUAL(passed_closure, &closure);
  2631.     const Number* returned_number = result.TryAs<Number>();
  2632.     ASSERT(returned_number != nullptr && returned_number->GetValue() == 42);
  2633.  
  2634.     ostringstream out;
  2635.     cls.Print(out, ctx);
  2636.     ASSERT(ctx.output.str().empty());
  2637.     ASSERT_EQUAL(out.str(), "Class Test"s);
  2638. }
  2639.  
  2640. void TestClassInstance() {
  2641.     vector<Method> methods;
  2642.  
  2643.     Closure passed_closure;
  2644.     auto str_body = [&passed_closure](Closure& closure, [[maybe_unused]] Context& ctx) {
  2645.         passed_closure = closure;
  2646.         return ObjectHolder::Own(String{"result"s});
  2647.     };
  2648.  
  2649.     methods.push_back({"__str__", {}, make_unique<TestMethodBody>(str_body)});
  2650.  
  2651.     Class cls{"Test"s, move(methods), nullptr};
  2652.     ClassInstance instance{cls};
  2653.  
  2654.     ASSERT_EQUAL(&instance.Fields(), &const_cast<const ClassInstance&>(instance).Fields());
  2655.     ASSERT(instance.HasMethod("__str__"s, 0));
  2656.  
  2657.     ostringstream out;
  2658.     DummyContext ctx;
  2659.     instance.Print(out, ctx);
  2660.     ASSERT_EQUAL(out.str(), "result"s);
  2661.  
  2662.     ASSERT_THROWS(instance.Call("missing_method"s, {}, ctx), runtime_error);
  2663. }
  2664.  
  2665. }//end namespace
  2666.  
  2667. void RunObjectsTests(TestRunner& tr) {
  2668.     RUN_TEST(tr, runtime::TestNumber);
  2669.     RUN_TEST(tr, runtime::TestString);
  2670.     RUN_TEST(tr, runtime::TestBool);
  2671.     RUN_TEST(tr, runtime::TestMethodInvocation);
  2672.     RUN_TEST(tr, runtime::TestIsTrue);
  2673.     RUN_TEST(tr, runtime::TestComparison);
  2674.     RUN_TEST(tr, runtime::TestClass);
  2675.     RUN_TEST(tr, runtime::TestClassInstance);
  2676. }
  2677.  
  2678. void RunObjectHolderTests(TestRunner& tr) {
  2679.     RUN_TEST(tr, runtime::TestNonowning);
  2680.     RUN_TEST(tr, runtime::TestOwning);
  2681.     RUN_TEST(tr, runtime::TestMove);
  2682.     RUN_TEST(tr, runtime::TestNullptr);
  2683. }
  2684.  
  2685. }//end namespace runtime
  2686. -----------------------------------------------------------------------
  2687. statement.cpp
  2688. -----------------------------------------------------------------------
  2689. #include "statement.h"
  2690.  
  2691. #include <iostream>
  2692. #include <sstream>
  2693.  
  2694. using namespace std;
  2695.  
  2696. namespace ast {
  2697.  
  2698. using runtime::Closure;
  2699. using runtime::Context;
  2700. using runtime::ObjectHolder;
  2701.  
  2702. namespace {
  2703.    
  2704. const string ADD_METHOD = "__add__"s;
  2705. const string INIT_METHOD = "__init__"s;
  2706.    
  2707. }//end namespace
  2708.    
  2709. class ReturnExcept : public std::exception {
  2710. public:
  2711.  
  2712.     explicit ReturnExcept(const runtime::ObjectHolder& object) : object_(object) {}
  2713.     runtime::ObjectHolder GetValue() {return object_;}
  2714.  
  2715. private:
  2716.     runtime::ObjectHolder object_;
  2717. };
  2718.  
  2719. ObjectHolder Assignment::Execute(Closure& closure, Context& context) {
  2720.     closure[var_] = std::move(rv_->Execute(closure, context));
  2721.     return closure.at(var_);
  2722. }
  2723.  
  2724. Assignment::Assignment(std::string var, std::unique_ptr<Statement> rv) : var_(std::move(var))
  2725.                                                                        , rv_(std::move(rv)) {}
  2726.  
  2727. VariableValue::VariableValue(const std::string& var_name) {dotted_ids_.push_back(var_name);}
  2728. VariableValue::VariableValue(std::vector<std::string> dotted_ids) : dotted_ids_(std::move(dotted_ids)) {}
  2729.  
  2730. ObjectHolder VariableValue::Execute(Closure& closure, [[maybe_unused]] Context& context) {
  2731.    
  2732.     Closure* closure_ptr = &closure;
  2733.     ObjectHolder object;
  2734.    
  2735.     for (const auto& id : dotted_ids_) {
  2736.        
  2737.         if (closure_ptr->count(id)) {
  2738.            
  2739.             object = closure_ptr->at(id);
  2740.            
  2741.             if (object.TryAs<runtime::ClassInstance>()) {
  2742.                 closure_ptr = &object.TryAs<runtime::ClassInstance>()->Fields();
  2743.             }
  2744.  
  2745.         } else {
  2746.             throw runtime_error("invalid argument. variable value execute");
  2747.         }  
  2748.     }
  2749.    
  2750.     return object;
  2751. }
  2752.  
  2753. unique_ptr<Print> Print::Variable(const std::string& name) {return std::make_unique<Print>(std::make_unique<VariableValue>(name));}
  2754.  
  2755. Print::Print(unique_ptr<Statement> argument) {args_.push_back(std::move(argument));}
  2756. Print::Print(vector<unique_ptr<Statement>> args) : args_(std::move(args)) {}
  2757.  
  2758. ObjectHolder Print::Execute(Closure& closure, Context& context) {
  2759.    
  2760.     ObjectHolder object;
  2761.    
  2762.     for (const auto& arg : args_) {
  2763.        
  2764.         if (arg != args_.front()) {
  2765.             context.GetOutputStream() << " "s;
  2766.         }
  2767.        
  2768.         object = arg->Execute(closure, context);
  2769.         if (object) {
  2770.             object->Print(context.GetOutputStream(), context);
  2771.            
  2772.         } else {
  2773.             context.GetOutputStream() << "None"s;
  2774.         }
  2775.     }
  2776.    
  2777.     context.GetOutputStream() << "\n"s;
  2778.     return object;
  2779. }
  2780.  
  2781. MethodCall::MethodCall(std::unique_ptr<Statement> object, std::string method, std::vector<std::unique_ptr<Statement>> args) : object_(std::move(object))
  2782.                                                                                                                             , method_(std::move(method))
  2783.                                                                                                                             , args_(std::move(args)) {}
  2784.  
  2785. ObjectHolder MethodCall::Execute(Closure& closure, Context& context) {
  2786.    
  2787.     auto object = object_->Execute(closure, context);
  2788.     auto class_ptr = object.TryAs<runtime::ClassInstance>();
  2789.     std::vector<runtime::ObjectHolder> args_now;
  2790.  
  2791.     for (const auto& arg : args_) {
  2792.         args_now.push_back(std::move(arg->Execute(closure, context)));
  2793.     }
  2794.  
  2795.     return class_ptr->Call(method_, args_now, context);
  2796. }
  2797.  
  2798. ObjectHolder Stringify::Execute(Closure& closure, Context& context) {
  2799.    
  2800.     auto object = argument_->Execute(closure, context);
  2801.    
  2802.     if (!object) {
  2803.         return ObjectHolder::Own(runtime::String{ "None"s });
  2804.        
  2805.     } else {
  2806.         runtime::DummyContext dummy_context;
  2807.         object->Print(dummy_context.GetOutputStream(), dummy_context);
  2808.  
  2809.         return ObjectHolder::Own(runtime::String{dummy_context.output.str()});
  2810.     }
  2811. }
  2812.  
  2813. ObjectHolder Add::Execute(Closure& closure, Context& context) {
  2814.    
  2815.     if (!lhs_ || !rhs_) {
  2816.         throw std::runtime_error("invalid argument. add execute"s);
  2817.        
  2818.     } else {
  2819.        
  2820.         auto lhs_object = lhs_->Execute(closure, context);
  2821.         auto rhs_object = rhs_->Execute(closure, context);
  2822.  
  2823.         auto lhs_number_ptr = lhs_object.TryAs<runtime::Number>();
  2824.         auto rhs_number_ptr = rhs_object.TryAs<runtime::Number>();
  2825.  
  2826.         if (lhs_number_ptr && rhs_number_ptr) {
  2827.            
  2828.             auto lhs_numuber = lhs_number_ptr->GetValue();
  2829.             auto rhs_numuber = rhs_number_ptr->GetValue();
  2830.  
  2831.             return ObjectHolder::Own(runtime::Number{lhs_numuber + rhs_numuber});
  2832.         }
  2833.        
  2834.         auto lhs_string_ptr = lhs_object.TryAs<runtime::String>();
  2835.         auto rhs_string_ptr = rhs_object.TryAs<runtime::String>();
  2836.  
  2837.         if (lhs_string_ptr && rhs_string_ptr) {
  2838.            
  2839.             auto lhs_string = lhs_string_ptr->GetValue();
  2840.             auto rhs_string = rhs_string_ptr->GetValue();
  2841.  
  2842.             return ObjectHolder::Own(runtime::String{lhs_string + rhs_string});
  2843.         }
  2844.        
  2845.         auto lhs_class_ptr = lhs_object.TryAs<runtime::ClassInstance>();
  2846.  
  2847.         if (lhs_class_ptr != nullptr) {
  2848.  
  2849.             if (lhs_class_ptr->HasMethod(ADD_METHOD, 1)) {
  2850.                 return lhs_class_ptr->Call(ADD_METHOD, {rhs_object}, context);
  2851.             }
  2852.         }
  2853.        
  2854.         throw std::runtime_error("invalid arument. add execute"s);
  2855.     }
  2856. }
  2857.  
  2858. ObjectHolder Sub::Execute(Closure& closure, Context& context) {
  2859.    
  2860.     if (!lhs_ || !rhs_) {
  2861.         throw std::runtime_error("invalid argument. sub execute"s);
  2862.        
  2863.     } else {
  2864.        
  2865.         auto lhs_object = lhs_->Execute(closure, context);
  2866.         auto rhs_object = rhs_->Execute(closure, context);
  2867.  
  2868.         auto lhs_number_ptr = lhs_object.TryAs<runtime::Number>();
  2869.         auto rhs_number_ptr = rhs_object.TryAs<runtime::Number>();
  2870.  
  2871.         if (lhs_number_ptr && rhs_number_ptr) {
  2872.            
  2873.             auto lhs_numuber = lhs_number_ptr->GetValue();
  2874.             auto rhs_numuber = rhs_number_ptr->GetValue();
  2875.  
  2876.             return ObjectHolder::Own(runtime::Number{lhs_numuber - rhs_numuber});
  2877.            
  2878.         } else {
  2879.             throw std::runtime_error("invalid argument. sub execute"s);
  2880.         }        
  2881.     }
  2882. }
  2883.  
  2884. ObjectHolder Mult::Execute(Closure& closure, Context& context) {
  2885.    
  2886.     if (!lhs_ || !rhs_) {
  2887.         throw std::runtime_error("invalid argument. mult execute"s);
  2888.        
  2889.     } else {
  2890.        
  2891.         auto lhs_object = lhs_->Execute(closure, context);
  2892.         auto rhs_object = rhs_->Execute(closure, context);
  2893.  
  2894.         auto lhs_number_ptr = lhs_object.TryAs<runtime::Number>();
  2895.         auto rhs_number_ptr = rhs_object.TryAs<runtime::Number>();
  2896.  
  2897.         if (lhs_number_ptr && rhs_number_ptr) {
  2898.            
  2899.             auto lhs_numuber = lhs_number_ptr->GetValue();
  2900.             auto rhs_numuber = rhs_number_ptr->GetValue();
  2901.  
  2902.             return ObjectHolder::Own(runtime::Number{lhs_numuber * rhs_numuber});
  2903.            
  2904.         } else {
  2905.             throw std::runtime_error("invalid argument. mult execute"s);  
  2906.         }
  2907.     }
  2908. }
  2909.  
  2910. ObjectHolder Div::Execute(Closure& closure, Context& context) {
  2911.    
  2912.     if (!lhs_ || !rhs_) {
  2913.         throw std::runtime_error("invalid argument. div execute"s);
  2914.        
  2915.     } else {
  2916.         auto lhs_object = lhs_->Execute(closure, context);
  2917.         auto rhs_object = rhs_->Execute(closure, context);
  2918.  
  2919.         auto lhs_number_ptr = lhs_object.TryAs<runtime::Number>();
  2920.         auto rhs_number_ptr = rhs_object.TryAs<runtime::Number>();
  2921.  
  2922.         if (lhs_number_ptr && rhs_number_ptr) {
  2923.            
  2924.             auto lhs_numuber = lhs_number_ptr->GetValue();
  2925.             auto rhs_numuber = rhs_number_ptr->GetValue();
  2926.  
  2927.             if (rhs_numuber == 0) {
  2928.                 throw std::runtime_error("div0"s);
  2929.                
  2930.             } else {
  2931.                 return ObjectHolder::Own(runtime::Number{lhs_numuber / rhs_numuber});
  2932.             }  
  2933.            
  2934.         } else {
  2935.             throw std::runtime_error("invalid argument. div execute"s);
  2936.         }
  2937.     }
  2938. }
  2939.  
  2940. ObjectHolder Compound::Execute(Closure& closure, Context& context) {
  2941.    
  2942.     for (const auto& statement : statements_) {
  2943.         statement->Execute(closure, context);      
  2944.     }
  2945.    
  2946.     return {};
  2947. }
  2948.  
  2949. ObjectHolder Return::Execute(Closure& closure, Context& context) {
  2950.    
  2951.     auto object = statement_->Execute(closure, context);
  2952.     throw ReturnExcept(object);
  2953. }
  2954.  
  2955. ClassDefinition::ClassDefinition(ObjectHolder cls) : class_(cls) {}
  2956.  
  2957. ObjectHolder ClassDefinition::Execute(Closure& closure, [[maybe_unused]] Context& context) {
  2958.    
  2959.     auto object = class_.TryAs<runtime::Class>();
  2960.     closure[object->GetName()] = std::move(class_);
  2961.  
  2962.     return {};
  2963. }
  2964.  
  2965. FieldAssignment::FieldAssignment(VariableValue object, std::string field_name, std::unique_ptr<Statement> rv)  : object_(std::move(object))
  2966.                                                                                                                , field_name_(std::move(field_name))
  2967.                                                                                                                , rv_(std::move(rv)) {}
  2968.  
  2969. ObjectHolder FieldAssignment::Execute(Closure& closure, Context& context) {
  2970.  
  2971.     Closure *closure_ptr = &closure;
  2972.    
  2973.     for (const auto& id: object_.GetDottedIds()) {
  2974.        
  2975.         auto& object = closure_ptr->at(id);
  2976.         closure_ptr = &object.TryAs<runtime::ClassInstance>()->Fields();
  2977.     }
  2978.    
  2979.     (*closure_ptr)[field_name_] = std::move(rv_->Execute(closure, context));
  2980.    
  2981.     return closure_ptr->at(field_name_);
  2982. }
  2983.  
  2984. IfElse::IfElse(std::unique_ptr<Statement> condition, std::unique_ptr<Statement> if_body, std::unique_ptr<Statement> else_body) : condition_(std::move(condition))
  2985.                                                                                                                                , if_body_(std::move(if_body))
  2986.                                                                                                                                , else_body_(std::move(else_body)) {}
  2987.  
  2988. ObjectHolder IfElse::Execute(Closure& closure, Context& context) {
  2989.    
  2990.     auto condition = condition_->Execute(closure, context);
  2991.     if (runtime::IsTrue(condition)) {
  2992.         return if_body_->Execute(closure, context);
  2993.        
  2994.     } else if (else_body_) {
  2995.         return else_body_->Execute(closure, context);
  2996.        
  2997.     } else {
  2998.         return {};
  2999.     }
  3000. }
  3001.  
  3002. ObjectHolder Or::Execute(Closure& closure, Context& context) {
  3003.    
  3004.     if (!lhs_ || !rhs_) {
  3005.         throw std::runtime_error("invalid argument. or execute"s);
  3006.        
  3007.     } else {
  3008.        
  3009.         auto lhs_object = lhs_->Execute(closure, context);
  3010.         auto rhs_object = rhs_->Execute(closure, context);
  3011.  
  3012.         if (runtime::IsTrue(lhs_object)) {
  3013.             return ObjectHolder::Own(runtime::Bool{true});
  3014.            
  3015.         } else if (runtime::IsTrue(rhs_object)) {
  3016.             return ObjectHolder::Own(runtime::Bool{true});
  3017.            
  3018.         } else {
  3019.             return ObjectHolder::Own(runtime::Bool{false});
  3020.         }
  3021.     }
  3022. }
  3023.  
  3024. ObjectHolder And::Execute(Closure& closure, Context& context) {
  3025.    
  3026.     if (!lhs_ || !rhs_) {
  3027.         throw std::runtime_error("invalid argument. and execute"s);
  3028.        
  3029.     } else {
  3030.        
  3031.         auto lhs_object = lhs_->Execute(closure, context);
  3032.         auto rhs_object = rhs_->Execute(closure, context);
  3033.  
  3034.         if (runtime::IsTrue(lhs_object) && runtime::IsTrue(rhs_object)) {
  3035.             return ObjectHolder::Own(runtime::Bool{true});
  3036.            
  3037.         } else {
  3038.             return ObjectHolder::Own(runtime::Bool{false});
  3039.         }
  3040.     }
  3041. }
  3042.  
  3043. ObjectHolder Not::Execute(Closure& closure, Context& context) {
  3044.    
  3045.     if (!argument_) {
  3046.         throw std::runtime_error("invalid argument. not execute"s);
  3047.        
  3048.     } else {
  3049.        
  3050.         auto object = argument_->Execute(closure, context);
  3051.         auto result = runtime::IsTrue(object);
  3052.        
  3053.         return ObjectHolder::Own(runtime::Bool{!result});
  3054.     }
  3055. }
  3056.  
  3057. Comparison::Comparison(Comparator cmp, unique_ptr<Statement> lhs, unique_ptr<Statement> rhs) : BinaryOperation(std::move(lhs), std::move(rhs))
  3058.                                                                                              , comparator_(std::move(cmp)) {}
  3059.  
  3060. ObjectHolder Comparison::Execute(Closure& closure, Context& context) {
  3061.    
  3062.     if (!lhs_ || !rhs_) {
  3063.         throw std::runtime_error("invalid argument. comparison execute"s);
  3064.        
  3065.     } else {
  3066.        
  3067.         auto lhs_object = lhs_->Execute(closure, context);
  3068.         auto rhs_object = rhs_->Execute(closure, context);
  3069.         bool result = comparator_(lhs_object, rhs_object, context);
  3070.  
  3071.         return ObjectHolder::Own(runtime::Bool{result});
  3072.     }
  3073. }
  3074.  
  3075. NewInstance::NewInstance(const runtime::Class& class_, std::vector<std::unique_ptr<Statement>> args) : class_(class_)
  3076.                                                                                                      , args_(std::move(args)) {}
  3077. NewInstance::NewInstance(const runtime::Class& class_) : class_(class_) {}
  3078.  
  3079. ObjectHolder NewInstance::Execute(Closure& closure, Context& context) {
  3080.    
  3081.     std::vector<runtime::ObjectHolder> args_now;
  3082.     for (const auto& arg : args_) {
  3083.         args_now.push_back(std::move(arg->Execute(closure, context)));
  3084.     }
  3085.    
  3086.     if (class_.HasMethod(INIT_METHOD, args_.size())) {
  3087.         class_.Call(INIT_METHOD, std::move(args_now), context);
  3088.     }
  3089.    
  3090.     return runtime::ObjectHolder::Share(class_);
  3091. }
  3092.  
  3093. MethodBody::MethodBody(std::unique_ptr<Statement>&& body) : body_(std::move(body)) {}
  3094.  
  3095. ObjectHolder MethodBody::Execute(Closure& closure, Context& context) {
  3096.    
  3097.     try {
  3098.         body_->Execute(closure, context);
  3099.        
  3100.     } catch (ReturnExcept& object) {
  3101.         return object.GetValue();
  3102.     }
  3103.    
  3104.     return {};
  3105. }
  3106.  
  3107. }//end namespace ast
  3108. -----------------------------------------------------------------------
  3109. statement.h
  3110. -----------------------------------------------------------------------
  3111. #pragma once
  3112.  
  3113. #include "runtime.h"
  3114.  
  3115. #include <functional>
  3116.  
  3117. namespace ast {
  3118.  
  3119. using Statement = runtime::Executable;
  3120.  
  3121. template <typename T>
  3122. class ValueStatement : public Statement {
  3123. public:
  3124.    
  3125.     explicit ValueStatement(T v) : value_(std::move(v)) {}
  3126.  
  3127.     runtime::ObjectHolder Execute(runtime::Closure&, runtime::Context&) override {
  3128.         return runtime::ObjectHolder::Share(value_);
  3129.     }
  3130.  
  3131. private:
  3132.     T value_;
  3133. };
  3134.  
  3135. using NumericConst = ValueStatement<runtime::Number>;
  3136. using StringConst = ValueStatement<runtime::String>;
  3137. using BoolConst = ValueStatement<runtime::Bool>;
  3138.  
  3139. class VariableValue : public Statement {
  3140. public:
  3141.    
  3142.     explicit VariableValue(const std::string& var_name);
  3143.     explicit VariableValue(std::vector<std::string> dotted_ids);
  3144.  
  3145.     runtime::ObjectHolder Execute(runtime::Closure& closure, [[maybe_unused]] runtime::Context& context) override;
  3146.    
  3147.     const std::vector<std::string>& GetDottedIds() const {return dotted_ids_;}
  3148.    
  3149. private:
  3150.     std::vector<std::string> dotted_ids_;
  3151. };
  3152.  
  3153. class Assignment : public Statement {
  3154. public:
  3155.    
  3156.     Assignment(std::string var, std::unique_ptr<Statement> rv);
  3157.     runtime::ObjectHolder Execute(runtime::Closure& closure, runtime::Context& context) override;
  3158.    
  3159. private:
  3160.     std::string var_;
  3161.     std::unique_ptr<Statement> rv_;
  3162. };
  3163.  
  3164. class FieldAssignment : public Statement {
  3165. public:
  3166.    
  3167.     FieldAssignment(VariableValue object, std::string field_name, std::unique_ptr<Statement> rv);
  3168.     runtime::ObjectHolder Execute(runtime::Closure& closure, runtime::Context& context) override;
  3169.    
  3170. private:
  3171.     VariableValue object_;
  3172.     std::string field_name_;
  3173.     std::unique_ptr<Statement> rv_;
  3174. };
  3175.  
  3176. class None : public Statement {
  3177. public:
  3178.     runtime::ObjectHolder Execute([[maybe_unused]] runtime::Closure& closure, [[maybe_unused]] runtime::Context& context) override {return {};}
  3179. };
  3180.  
  3181. class Print : public Statement {
  3182. public:
  3183.  
  3184.     explicit Print(std::unique_ptr<Statement> argument);
  3185.     explicit Print(std::vector<std::unique_ptr<Statement>> args);
  3186.     static std::unique_ptr<Print> Variable(const std::string& name);
  3187.     runtime::ObjectHolder Execute(runtime::Closure& closure, runtime::Context& context) override;
  3188.    
  3189. private:
  3190.     std::vector<std::unique_ptr<Statement>> args_;
  3191. };
  3192.  
  3193. class MethodCall : public Statement {
  3194. public:
  3195.    
  3196.     MethodCall(std::unique_ptr<Statement> object, std::string method, std::vector<std::unique_ptr<Statement>> args);
  3197.     runtime::ObjectHolder Execute(runtime::Closure& closure, runtime::Context& context) override;
  3198.    
  3199. private:
  3200.     std::unique_ptr<Statement> object_;
  3201.     std::string method_;
  3202.     std::vector<std::unique_ptr<Statement>> args_;
  3203. };
  3204.  
  3205. class NewInstance : public Statement {
  3206. public:
  3207.    
  3208.     explicit NewInstance(const runtime::Class& class_);
  3209.    
  3210.     NewInstance(const runtime::Class& class_, std::vector<std::unique_ptr<Statement>> args);
  3211.     runtime::ObjectHolder Execute(runtime::Closure& closure, runtime::Context& context) override;
  3212.    
  3213. private:
  3214.     runtime::ClassInstance class_;
  3215.     std::vector<std::unique_ptr<Statement>> args_;
  3216. };
  3217.  
  3218. class UnaryOperation : public Statement {
  3219. public:
  3220.    
  3221.     explicit UnaryOperation(std::unique_ptr<Statement> argument) : argument_(std::move(argument)) {}
  3222.    
  3223. protected:
  3224.     std::unique_ptr<Statement> argument_;
  3225. };
  3226.  
  3227. class Stringify : public UnaryOperation {
  3228. public:
  3229.    
  3230.     using UnaryOperation::UnaryOperation;
  3231.     runtime::ObjectHolder Execute(runtime::Closure& closure, runtime::Context& context) override;
  3232. };
  3233.  
  3234. class BinaryOperation : public Statement {
  3235. public:
  3236.    
  3237.     BinaryOperation(std::unique_ptr<Statement> lhs, std::unique_ptr<Statement> rhs) : lhs_(std::move(lhs))
  3238.                                                                                     , rhs_(std::move(rhs)) {}
  3239.    
  3240. protected:
  3241.     std::unique_ptr<Statement> lhs_;
  3242.     std::unique_ptr<Statement> rhs_;
  3243. };
  3244.  
  3245. class Add : public BinaryOperation {
  3246. public:
  3247.    
  3248.     using BinaryOperation::BinaryOperation;
  3249.     runtime::ObjectHolder Execute(runtime::Closure& closure, runtime::Context& context) override;
  3250. };
  3251.  
  3252. class Sub : public BinaryOperation {
  3253. public:
  3254.    
  3255.     using BinaryOperation::BinaryOperation;
  3256.     runtime::ObjectHolder Execute(runtime::Closure& closure, runtime::Context& context) override;
  3257. };
  3258.  
  3259. class Mult : public BinaryOperation {
  3260. public:
  3261.    
  3262.     using BinaryOperation::BinaryOperation;
  3263.     runtime::ObjectHolder Execute(runtime::Closure& closure, runtime::Context& context) override;
  3264. };
  3265.  
  3266. class Div : public BinaryOperation {
  3267. public:
  3268.    
  3269.     using BinaryOperation::BinaryOperation;
  3270.     runtime::ObjectHolder Execute(runtime::Closure& closure, runtime::Context& context) override;
  3271. };
  3272.  
  3273. class Or : public BinaryOperation {
  3274. public:
  3275.    
  3276.     using BinaryOperation::BinaryOperation;
  3277.     runtime::ObjectHolder Execute(runtime::Closure& closure, runtime::Context& context) override;
  3278. };
  3279.  
  3280. class And : public BinaryOperation {
  3281. public:
  3282.    
  3283.     using BinaryOperation::BinaryOperation;
  3284.     runtime::ObjectHolder Execute(runtime::Closure& closure, runtime::Context& context) override;
  3285. };
  3286.  
  3287. class Not : public UnaryOperation {
  3288. public:
  3289.    
  3290.     using UnaryOperation::UnaryOperation;
  3291.     runtime::ObjectHolder Execute(runtime::Closure& closure, runtime::Context& context) override;
  3292. };
  3293.  
  3294. class Compound : public Statement {
  3295. public:
  3296.  
  3297.     template <typename... Args>
  3298.     explicit Compound(Args&&... args) {ReqursiveCompound(args...);}
  3299.  
  3300.     void AddStatement(std::unique_ptr<Statement> stmt) {statements_.push_back(std::move(stmt));}
  3301.     runtime::ObjectHolder Execute(runtime::Closure& closure, runtime::Context& context) override;
  3302.    
  3303. private:
  3304.  
  3305.     std::vector<std::unique_ptr<Statement>> statements_;
  3306.    
  3307.     void ReqursiveCompound() {}
  3308.    
  3309.     template <typename T, typename... Ts>
  3310.     void ReqursiveCompound(T& arg, Ts&&... other) {
  3311.         AddStatement(std::forward<T>(arg));
  3312.         ReqursiveCompound(other...);
  3313.     }
  3314. };
  3315.  
  3316. class MethodBody : public Statement {
  3317. public:
  3318.    
  3319.     explicit MethodBody(std::unique_ptr<Statement>&& body);
  3320.     runtime::ObjectHolder Execute(runtime::Closure& closure, runtime::Context& context) override;
  3321.    
  3322. private:
  3323.     std::unique_ptr<Statement> body_;
  3324. };
  3325.  
  3326. class Return : public Statement {
  3327. public:
  3328.    
  3329.     explicit Return(std::unique_ptr<Statement> statement) : statement_(std::move(statement)) {}
  3330.  
  3331.     runtime::ObjectHolder Execute(runtime::Closure& closure, runtime::Context& context) override;
  3332.    
  3333. private:
  3334.     std::unique_ptr<Statement> statement_;
  3335. };
  3336.  
  3337. class ClassDefinition : public Statement {
  3338. public:
  3339.  
  3340.     explicit ClassDefinition(runtime::ObjectHolder cls);
  3341.     runtime::ObjectHolder Execute(runtime::Closure& closure, [[maybe_unused]] runtime::Context& context) override;
  3342.    
  3343. private:
  3344.     runtime::ObjectHolder class_;
  3345. };
  3346.  
  3347. class IfElse : public Statement {
  3348. public:
  3349.  
  3350.     IfElse(std::unique_ptr<Statement> condition, std::unique_ptr<Statement> if_body, std::unique_ptr<Statement> else_body);
  3351.     runtime::ObjectHolder Execute(runtime::Closure& closure, runtime::Context& context) override;
  3352.    
  3353. private:
  3354.     std::unique_ptr<Statement> condition_;
  3355.     std::unique_ptr<Statement> if_body_;
  3356.     std::unique_ptr<Statement> else_body_;
  3357. };
  3358.  
  3359. class Comparison : public BinaryOperation {
  3360. public:
  3361.  
  3362.     using Comparator = std::function<bool(const runtime::ObjectHolder&, const runtime::ObjectHolder&, runtime::Context&)>;
  3363.     Comparison(Comparator cmp, std::unique_ptr<Statement> lhs, std::unique_ptr<Statement> rhs);
  3364.     runtime::ObjectHolder Execute(runtime::Closure& closure, runtime::Context& context) override;
  3365.    
  3366. private:
  3367.     Comparator comparator_;
  3368. };
  3369.  
  3370. }//end namespace ast
  3371. -----------------------------------------------------------------------
  3372. statement_test.cpp
  3373. -----------------------------------------------------------------------
  3374. #include "statement.h"
  3375. #include "test_runner_p.h"
  3376.  
  3377. using namespace std;
  3378.  
  3379. namespace ast {
  3380.  
  3381. using runtime::Closure;
  3382. using runtime::ObjectHolder;
  3383.  
  3384. namespace {
  3385.  
  3386. template <typename T>
  3387. void AssertObjectValueEqual(const ObjectHolder& obj, const T& expected, const string& msg) {
  3388.     ostringstream one;
  3389.     runtime::DummyContext context;
  3390.     obj->Print(one, context);
  3391.  
  3392.     ostringstream two;
  3393.     two << expected;
  3394.  
  3395.     AssertEqual(one.str(), two.str(), msg);
  3396. }
  3397.  
  3398. #define ASSERT_OBJECT_VALUE_EQUAL(obj, expected)                                          \
  3399.     {                                                                                     \
  3400.         std::ostringstream __assert_equal_private_os;                                     \
  3401.         __assert_equal_private_os << #obj << "'s value_ "sv                               \
  3402.                                   << " != "sv << #expected << "s, "sv << FILE_NAME << ':' \
  3403.                                   << __LINE__;                                            \
  3404.         AssertObjectValueEqual(obj, expected, __assert_equal_private_os.str());           \
  3405.     }
  3406.  
  3407. void TestNumericConst() {
  3408.     runtime::DummyContext context;
  3409.  
  3410.     NumericConst num(runtime::Number(57));
  3411.     Closure empty;
  3412.  
  3413.     ObjectHolder o = num.Execute(empty, context);
  3414.     ASSERT(o);
  3415.     ASSERT(empty.empty());
  3416.  
  3417.     ostringstream os;
  3418.     o->Print(os, context);
  3419.     ASSERT_EQUAL(os.str(), "57"s);
  3420.  
  3421.     ASSERT(context.output.str().empty());
  3422. }
  3423.  
  3424. void TestStringConst() {
  3425.     runtime::DummyContext context;
  3426.  
  3427.     StringConst value_(runtime::String("Hello!"s));
  3428.     Closure empty;
  3429.  
  3430.     ObjectHolder o = value_.Execute(empty, context);
  3431.     ASSERT(o);
  3432.     ASSERT(empty.empty());
  3433.  
  3434.     ostringstream os;
  3435.     o->Print(os, context);
  3436.     ASSERT_EQUAL(os.str(), "Hello!"s);
  3437.  
  3438.     ASSERT(context.output.str().empty());
  3439. }
  3440.  
  3441. void TestVariable() {
  3442.     runtime::DummyContext context;
  3443.  
  3444.     runtime::Number num(42);
  3445.     runtime::String word("Hello"s);
  3446.  
  3447.     Closure closure = {{"x"s, ObjectHolder::Share(num)}, {"w"s, ObjectHolder::Share(word)}};
  3448.     ASSERT(VariableValue("x"s).Execute(closure, context).Get() == &num);
  3449.     ASSERT(VariableValue("w"s).Execute(closure, context).Get() == &word);
  3450.     ASSERT_THROWS(VariableValue("unknown"s).Execute(closure, context), std::runtime_error);
  3451.  
  3452.     ASSERT(context.output.str().empty());
  3453. }
  3454.  
  3455. void TestAssignment() {
  3456.     runtime::DummyContext context;
  3457.  
  3458.     Assignment assign_x("x"s, make_unique<NumericConst>(runtime::Number(57)));
  3459.     Assignment assign_y("y"s, make_unique<StringConst>(runtime::String("Hello"s)));
  3460.  
  3461.     Closure closure = {{"y"s, ObjectHolder::Own(runtime::Number(42))}};
  3462.  
  3463.     {
  3464.         ObjectHolder o = assign_x.Execute(closure, context);
  3465.         ASSERT(o);
  3466.         ASSERT_OBJECT_VALUE_EQUAL(o, 57);
  3467.     }
  3468.     ASSERT(closure.find("x"s) != closure.end());
  3469.     ASSERT_OBJECT_VALUE_EQUAL(closure.at("x"s), 57);
  3470.  
  3471.     {
  3472.         ObjectHolder o = assign_y.Execute(closure, context);
  3473.         ASSERT(o);
  3474.         ASSERT_OBJECT_VALUE_EQUAL(o, "Hello"s);
  3475.     }
  3476.     ASSERT(closure.find("y"s) != closure.end());
  3477.     ASSERT_OBJECT_VALUE_EQUAL(closure.at("y"s), "Hello"s);
  3478.  
  3479.     ASSERT(context.output.str().empty());
  3480. }
  3481.  
  3482. void TestFieldAssignment() {
  3483.     runtime::DummyContext context;
  3484.  
  3485.     runtime::Class empty("Empty"s, {}, nullptr);
  3486.     runtime::ClassInstance object{empty};
  3487.  
  3488.     FieldAssignment assign_x(VariableValue{"self"s}, "x"s,
  3489.                              make_unique<NumericConst>(runtime::Number(57)));
  3490.     FieldAssignment assign_y(VariableValue{"self"s}, "y"s, make_unique<NewInstance>(empty));
  3491.  
  3492.     Closure closure = {{"self"s, ObjectHolder::Share(object)}};
  3493.  
  3494.     {
  3495.         ObjectHolder o = assign_x.Execute(closure, context);
  3496.         ASSERT(o);
  3497.         ASSERT_OBJECT_VALUE_EQUAL(o, 57);
  3498.     }
  3499.     ASSERT(object.Fields().find("x"s) != object.Fields().end());
  3500.     ASSERT_OBJECT_VALUE_EQUAL(object.Fields().at("x"s), 57);
  3501.  
  3502.     assign_y.Execute(closure, context);
  3503.     FieldAssignment assign_yz(
  3504.         VariableValue{vector<string>{"self"s, "y"s}}, "z"s,
  3505.         make_unique<StringConst>(runtime::String("Hello, world! Hooray! Yes-yes!!!"s)));
  3506.     {
  3507.         ObjectHolder o = assign_yz.Execute(closure, context);
  3508.         ASSERT(o);
  3509.         ASSERT_OBJECT_VALUE_EQUAL(o, "Hello, world! Hooray! Yes-yes!!!"s);
  3510.     }
  3511.  
  3512.     ASSERT(object.Fields().find("y"s) != object.Fields().end());
  3513.     const auto* subobject = object.Fields().at("y"s).TryAs<runtime::ClassInstance>();
  3514.     ASSERT(subobject != nullptr && subobject->Fields().find("z"s) != subobject->Fields().end());
  3515.     ASSERT_OBJECT_VALUE_EQUAL(subobject->Fields().at("z"s), "Hello, world! Hooray! Yes-yes!!!"s);
  3516.  
  3517.     ASSERT(context.output.str().empty());
  3518. }
  3519.  
  3520. void TestPrintVariable() {
  3521.     runtime::DummyContext context;
  3522.  
  3523.     Closure closure = {{"y"s, ObjectHolder::Own(runtime::Number(42))}};
  3524.  
  3525.     auto print_statement = Print::Variable("y"s);
  3526.     print_statement->Execute(closure, context);
  3527.  
  3528.     ASSERT_EQUAL(context.output.str(), "42\n"s);
  3529. }
  3530.  
  3531. void TestPrintMultipleStatements() {
  3532.     runtime::DummyContext context;
  3533.  
  3534.     runtime::String hello("hello"s);
  3535.     Closure closure = {{"word"s, ObjectHolder::Share(hello)}, {"empty"s, ObjectHolder::None()}};
  3536.  
  3537.     vector<unique_ptr<Statement>> args;
  3538.     args.push_back(make_unique<VariableValue>("word"s));
  3539.     args.push_back(make_unique<NumericConst>(57));
  3540.     args.push_back(make_unique<StringConst>("Python"s));
  3541.     args.push_back(make_unique<VariableValue>("empty"s));
  3542.  
  3543.     Print(std::move(args)).Execute(closure, context);
  3544.  
  3545.     ASSERT_EQUAL(context.output.str(), "hello 57 Python None\n"s);
  3546. }
  3547.  
  3548. void TestStringify() {
  3549.     runtime::DummyContext context;
  3550.  
  3551.     Closure empty;
  3552.  
  3553.     {
  3554.         auto result = Stringify(make_unique<NumericConst>(57)).Execute(empty, context);
  3555.         ASSERT_OBJECT_VALUE_EQUAL(result, "57"s);
  3556.         ASSERT(result.TryAs<runtime::String>());
  3557.     }
  3558.     {
  3559.         auto result = Stringify(make_unique<StringConst>("Wazzup!"s)).Execute(empty, context);
  3560.         ASSERT_OBJECT_VALUE_EQUAL(result, "Wazzup!"s);
  3561.         ASSERT(result.TryAs<runtime::String>());
  3562.     }
  3563.     {
  3564.         vector<runtime::Method> methods;
  3565.         methods.push_back({"__str__"s, {}, make_unique<NumericConst>(842)});
  3566.  
  3567.         runtime::Class cls("BoxedValue"s, std::move(methods), nullptr);
  3568.  
  3569.         auto result = Stringify(make_unique<NewInstance>(cls)).Execute(empty, context);
  3570.         ASSERT_OBJECT_VALUE_EQUAL(result, "842"s);
  3571.         ASSERT(result.TryAs<runtime::String>());
  3572.     }
  3573.     {
  3574.         runtime::Class cls("BoxedValue"s, {}, nullptr);
  3575.         runtime::Closure closure{{"x"s, ObjectHolder::Own(runtime::ClassInstance{cls})}};
  3576.  
  3577.         std::ostringstream expected_output;
  3578.         expected_output << closure.at("x"s).Get();
  3579.  
  3580.         Stringify str(make_unique<VariableValue>("x"s));
  3581.         ASSERT_OBJECT_VALUE_EQUAL(str.Execute(closure, context), expected_output.str());
  3582.     }
  3583.     {
  3584.         Stringify str(make_unique<None>());
  3585.         ASSERT_OBJECT_VALUE_EQUAL(str.Execute(empty, context), "None"s);
  3586.     }
  3587.  
  3588.     ASSERT(context.output.str().empty());
  3589. }
  3590.  
  3591. void TestNumbersAddition() {
  3592.     runtime::DummyContext context;
  3593.  
  3594.     Add sum(make_unique<NumericConst>(23), make_unique<NumericConst>(34));
  3595.  
  3596.     Closure empty;
  3597.     ASSERT_OBJECT_VALUE_EQUAL(sum.Execute(empty, context), 57);
  3598.  
  3599.     ASSERT(context.output.str().empty());
  3600. }
  3601.  
  3602. void TestStringsAddition() {
  3603.     runtime::DummyContext context;
  3604.  
  3605.     Add sum(make_unique<StringConst>("23"s), make_unique<StringConst>("34"s));
  3606.  
  3607.     Closure empty;
  3608.     ASSERT_OBJECT_VALUE_EQUAL(sum.Execute(empty, context), "2334"s);
  3609.  
  3610.     ASSERT(context.output.str().empty());
  3611. }
  3612.  
  3613. void TestBadAddition() {
  3614.     runtime::DummyContext context;
  3615.  
  3616.     Closure empty;
  3617.  
  3618.     ASSERT_THROWS(
  3619.         Add(make_unique<NumericConst>(42), make_unique<StringConst>("4"s)).Execute(empty, context),
  3620.         std::runtime_error);
  3621.     ASSERT_THROWS(
  3622.         Add(make_unique<StringConst>("4"s), make_unique<NumericConst>(42)).Execute(empty, context),
  3623.         std::runtime_error);
  3624.     ASSERT_THROWS(Add(make_unique<None>(), make_unique<StringConst>("4"s)).Execute(empty, context),
  3625.                   std::runtime_error);
  3626.     ASSERT_THROWS(Add(make_unique<None>(), make_unique<None>()).Execute(empty, context),
  3627.                   std::runtime_error);
  3628.  
  3629.     ASSERT(context.output.str().empty());
  3630. }
  3631.  
  3632. void TestSuccessfulClassInstanceAdd() {
  3633.     runtime::DummyContext context;
  3634.  
  3635.     vector<runtime::Method> methods;
  3636.     methods.push_back({"__add__"s,
  3637.                        {"value_"s},
  3638.                        make_unique<Add>(make_unique<StringConst>("hello, "s),
  3639.                                         make_unique<VariableValue>("value_"s))});
  3640.  
  3641.     runtime::Class cls("BoxedValue"s, std::move(methods), nullptr);
  3642.  
  3643.     Closure empty;
  3644.     auto result = Add(make_unique<NewInstance>(cls), make_unique<StringConst>("world"s))
  3645.                       .Execute(empty, context);
  3646.     ASSERT_OBJECT_VALUE_EQUAL(result, "hello, world"s);
  3647.  
  3648.     ASSERT(context.output.str().empty());
  3649. }
  3650.  
  3651. void TestClassInstanceAddWithoutMethod() {
  3652.     runtime::DummyContext context;
  3653.  
  3654.     runtime::Class cls("BoxedValue"s, {}, nullptr);
  3655.  
  3656.     Closure empty;
  3657.     Add addition(make_unique<NewInstance>(cls), make_unique<StringConst>("world"s));
  3658.     ASSERT_THROWS(addition.Execute(empty, context), std::runtime_error);
  3659.  
  3660.     ASSERT(context.output.str().empty());
  3661. }
  3662.  
  3663. void TestCompound() {
  3664.     runtime::DummyContext context;
  3665.  
  3666.     Compound cpd{
  3667.         make_unique<Assignment>("x"s, make_unique<StringConst>("one"s)),
  3668.         make_unique<Assignment>("y"s, make_unique<NumericConst>(2)),
  3669.         make_unique<Assignment>("z"s, make_unique<VariableValue>("x"s)),
  3670.     };
  3671.  
  3672.     Closure closure;
  3673.     auto result = cpd.Execute(closure, context);
  3674.  
  3675.     ASSERT_OBJECT_VALUE_EQUAL(closure.at("x"s), "one"s);
  3676.     ASSERT_OBJECT_VALUE_EQUAL(closure.at("y"s), 2);
  3677.     ASSERT_OBJECT_VALUE_EQUAL(closure.at("z"s), "one"s);
  3678.  
  3679.     ASSERT(!result);
  3680.  
  3681.     ASSERT(context.output.str().empty());
  3682. }
  3683.  
  3684. void TestFields() {
  3685.     runtime::DummyContext context;
  3686.  
  3687.     vector<runtime::Method> methods;
  3688.  
  3689.     methods.push_back({"__init__"s,
  3690.                        {},
  3691.                        {make_unique<FieldAssignment>(VariableValue{"self"s}, "value"s,
  3692.                                                      make_unique<NumericConst>(0))}});
  3693.     methods.push_back(
  3694.         {"value"s, {}, {make_unique<VariableValue>(vector<string>{"self"s, "value"s})}});
  3695.     methods.push_back(
  3696.         {"add"s,
  3697.          {"x"s},
  3698.          {make_unique<FieldAssignment>(
  3699.              VariableValue{"self"s}, "value"s,
  3700.              make_unique<Add>(make_unique<VariableValue>(vector<string>{"self"s, "value"s}),
  3701.                               make_unique<VariableValue>("x"s)))}});
  3702.  
  3703.     runtime::Class cls("BoxedValue"s, std::move(methods), nullptr);
  3704.     runtime::ClassInstance inst(cls);
  3705.  
  3706.     inst.Call("__init__"s, {}, context);
  3707.  
  3708.     for (int i = 1, expected = 0; i < 10; expected += i, ++i) {
  3709.         auto fv = inst.Call("value"s, {}, context);
  3710.         auto* obj = fv.TryAs<runtime::Number>();
  3711.         ASSERT(obj);
  3712.         ASSERT_EQUAL(obj->GetValue(), expected);
  3713.  
  3714.         inst.Call("add"s, {ObjectHolder::Own(runtime::Number(i))}, context);
  3715.     }
  3716.  
  3717.     ASSERT(context.output.str().empty());
  3718. }
  3719.  
  3720. void TestBaseClass() {
  3721.     vector<runtime::Method> methods;
  3722.     methods.push_back({"GetValue"s, {}, make_unique<VariableValue>(vector{"self"s, "value"s})});
  3723.     methods.push_back({"SetValue"s,
  3724.                        {"x"s},
  3725.                        make_unique<FieldAssignment>(VariableValue{"self"s}, "value"s,
  3726.                                                     make_unique<ast::VariableValue>("x"s))});
  3727.  
  3728.     runtime::Class cls("BoxedValue"s, move(methods), nullptr);
  3729.  
  3730.     ASSERT_EQUAL(cls.GetName(), "BoxedValue"s);
  3731.     {
  3732.         const auto* m = cls.GetMethod("GetValue"s);
  3733.         ASSERT(m != nullptr);
  3734.         ASSERT_EQUAL(m->name, "GetValue"s);
  3735.         ASSERT(m->formal_params.empty());
  3736.     }
  3737.     {
  3738.         const auto* m = cls.GetMethod("SetValue"s);
  3739.         ASSERT(m != nullptr);
  3740.         ASSERT_EQUAL(m->name, "SetValue"s);
  3741.         ASSERT_EQUAL(m->formal_params.size(), 1U);
  3742.     }
  3743.     ASSERT(!cls.GetMethod("AsString"s));
  3744. }
  3745.  
  3746. void TestInheritance() {
  3747.     vector<runtime::Method> methods;
  3748.     methods.push_back({"GetValue"s, {}, make_unique<VariableValue>(vector{"self"s, "value"s})});
  3749.     methods.push_back({"SetValue"s,
  3750.                        {"x"s},
  3751.                        make_unique<FieldAssignment>(VariableValue{"self"s}, "value"s,
  3752.                                                     make_unique<VariableValue>("x"s))});
  3753.  
  3754.     runtime::Class base("BoxedValue"s, std::move(methods), nullptr);
  3755.  
  3756.     methods.clear();
  3757.     methods.push_back({"GetValue"s, {"z"s}, make_unique<VariableValue>("z"s)});
  3758.     methods.push_back({"AsString"s, {}, make_unique<StringConst>("value"s)});
  3759.     runtime::Class cls("StringableValue"s, std::move(methods), &base);
  3760.  
  3761.     ASSERT_EQUAL(cls.GetName(), "StringableValue"s);
  3762.     {
  3763.         const auto* m = cls.GetMethod("GetValue"s);
  3764.         ASSERT(m != nullptr);
  3765.         ASSERT_EQUAL(m->name, "GetValue"s);
  3766.         ASSERT_EQUAL(m->formal_params.size(), 1U);
  3767.     }
  3768.     {
  3769.         const auto* m = cls.GetMethod("SetValue"s);
  3770.         ASSERT(m != nullptr);
  3771.         ASSERT_EQUAL(m->name, "SetValue"s);
  3772.         ASSERT_EQUAL(m->formal_params.size(), 1U);
  3773.     }
  3774.     {
  3775.         const auto* m = cls.GetMethod("AsString"s);
  3776.         ASSERT(m != nullptr);
  3777.         ASSERT_EQUAL(m->name, "AsString"s);
  3778.         ASSERT(m->formal_params.empty());
  3779.     }
  3780.     ASSERT(!cls.GetMethod("AsStringValue"s));
  3781. }
  3782.  
  3783. void TestOr() {
  3784.     auto test_or = [](bool lhs, bool rhs) {
  3785.         Or or_statement{make_unique<BoolConst>(lhs), make_unique<BoolConst>(rhs)};
  3786.         Closure closure;
  3787.         runtime::DummyContext context;
  3788.         ASSERT_EQUAL(runtime::Equal(or_statement.Execute(closure, context),
  3789.                                     ObjectHolder::Own(runtime::Bool(true)), context),
  3790.                      lhs || rhs);
  3791.     };
  3792.  
  3793.     test_or(true, true);
  3794.     test_or(true, false);
  3795.     test_or(false, true);
  3796.     test_or(false, false);
  3797. }
  3798.  
  3799. void TestAnd() {
  3800.     auto test_and = [](bool lhs, bool rhs) {
  3801.         And and_statement{make_unique<BoolConst>(lhs), make_unique<BoolConst>(rhs)};
  3802.         Closure closure;
  3803.         runtime::DummyContext context;
  3804.         ASSERT_EQUAL(runtime::Equal(and_statement.Execute(closure, context),
  3805.                                     ObjectHolder::Own(runtime::Bool(true)), context),
  3806.                      lhs && rhs);
  3807.     };
  3808.  
  3809.     test_and(true, true);
  3810.     test_and(true, false);
  3811.     test_and(false, true);
  3812.     test_and(false, false);
  3813. }
  3814.  
  3815. void TestNot() {
  3816.     auto test_not = [](bool arg) {
  3817.         Not not_statement{make_unique<BoolConst>(arg)};
  3818.         Closure closure;
  3819.         runtime::DummyContext context;
  3820.         ASSERT_EQUAL(runtime::Equal(not_statement.Execute(closure, context),
  3821.                                     ObjectHolder::Own(runtime::Bool(true)), context),
  3822.                      !arg);
  3823.     };
  3824.  
  3825.     test_not(true);
  3826.     test_not(false);
  3827. }
  3828.  
  3829. }//end namespace
  3830.  
  3831. void RunUnitTests(TestRunner& tr) {
  3832.     RUN_TEST(tr, ast::TestNumericConst);
  3833.     RUN_TEST(tr, ast::TestStringConst);
  3834.     RUN_TEST(tr, ast::TestVariable);
  3835.     RUN_TEST(tr, ast::TestAssignment);
  3836.     RUN_TEST(tr, ast::TestFieldAssignment);
  3837.     RUN_TEST(tr, ast::TestPrintVariable);
  3838.     RUN_TEST(tr, ast::TestPrintMultipleStatements);
  3839.     RUN_TEST(tr, ast::TestStringify);
  3840.     RUN_TEST(tr, ast::TestNumbersAddition);
  3841.     RUN_TEST(tr, ast::TestStringsAddition);
  3842.     RUN_TEST(tr, ast::TestBadAddition);
  3843.     RUN_TEST(tr, ast::TestSuccessfulClassInstanceAdd);
  3844.     RUN_TEST(tr, ast::TestClassInstanceAddWithoutMethod);
  3845.     RUN_TEST(tr, ast::TestCompound);
  3846.     RUN_TEST(tr, ast::TestFields);
  3847.     RUN_TEST(tr, ast::TestBaseClass);
  3848.     RUN_TEST(tr, ast::TestInheritance);
  3849.     RUN_TEST(tr, ast::TestOr);
  3850.     RUN_TEST(tr, ast::TestAnd);
  3851.     RUN_TEST(tr, ast::TestNot);
  3852. }
  3853.  
  3854. }//end namespace ast
  3855. -----------------------------------------------------------------------
  3856. test_runner_p.h
  3857. -----------------------------------------------------------------------
  3858. #pragma once
  3859.  
  3860. #include <iostream>
  3861. #include <map>
  3862. #include <set>
  3863. #include <sstream>
  3864. #include <stdexcept>
  3865. #include <string>
  3866. #include <unordered_map>
  3867. #include <vector>
  3868.  
  3869. namespace TestRunnerPrivate {
  3870.    
  3871. template <class Map>
  3872. std::ostream& PrintMap(std::ostream& os, const Map& m) {
  3873.     os << "{";
  3874.     bool first = true;
  3875.     for (const auto& kv : m) {
  3876.         if (!first) {
  3877.             os << ", ";
  3878.         }
  3879.         first = false;
  3880.         os << kv.first << ": " << kv.second;
  3881.     }
  3882.     return os << "}";
  3883. }
  3884.  
  3885. }//end namespace TestRunnerPrivate
  3886.  
  3887. template <class T>
  3888. std::ostream& operator<<(std::ostream& os, const std::vector<T>& s) {
  3889.     os << "{";
  3890.     bool first = true;
  3891.     for (const auto& x : s) {
  3892.         if (!first) {
  3893.             os << ", ";
  3894.         }
  3895.         first = false;
  3896.         os << x;
  3897.     }
  3898.     return os << "}";
  3899. }
  3900.  
  3901. template <class T>
  3902. std::ostream& operator<<(std::ostream& os, const std::set<T>& s) {
  3903.     os << "{";
  3904.     bool first = true;
  3905.     for (const auto& x : s) {
  3906.         if (!first) {
  3907.             os << ", ";
  3908.         }
  3909.         first = false;
  3910.         os << x;
  3911.     }
  3912.     return os << "}";
  3913. }
  3914.  
  3915. template <class K, class V>
  3916. std::ostream& operator<<(std::ostream& os, const std::map<K, V>& m) {return TestRunnerPrivate::PrintMap(os, m);}
  3917.  
  3918. template <class K, class V>
  3919. std::ostream& operator<<(std::ostream& os, const std::unordered_map<K, V>& m) {return TestRunnerPrivate::PrintMap(os, m);}
  3920.  
  3921. template <class T, class U>
  3922. void AssertEqual(const T& t, const U& u, const std::string& hint = {}) {
  3923.    
  3924.     if (!(t == u)) {
  3925.         std::ostringstream os;
  3926.         os << "Assertion failed: " << t << " != " << u;
  3927.         if (!hint.empty()) {
  3928.             os << " hint: " << hint;
  3929.         }
  3930.         throw std::runtime_error(os.str());
  3931.     }
  3932. }
  3933.  
  3934. inline void Assert(bool b, const std::string& hint) {AssertEqual(b, true, hint);}
  3935.  
  3936. class TestRunner {
  3937. public:
  3938.    
  3939.     template <class TestFunc>
  3940.     void RunTest(TestFunc func, const std::string& test_name) {
  3941.         try {
  3942.             func();
  3943.             std::cerr << test_name << " OK" << std::endl;
  3944.         } catch (std::exception& e) {
  3945.             ++fail_count;
  3946.             std::cerr << test_name << " fail: " << e.what() << std::endl;
  3947.         } catch (...) {
  3948.             ++fail_count;
  3949.             std::cerr << "Unknown exception caught" << std::endl;
  3950.         }
  3951.     }
  3952.  
  3953.     ~TestRunner() {
  3954.         std::cerr.flush();
  3955.         if (fail_count > 0) {
  3956.             std::cerr << fail_count << " unit tests failed. Terminate" << std::endl;
  3957.             exit(1);
  3958.         }
  3959.     }
  3960.  
  3961. private:
  3962.     int fail_count = 0;
  3963. };
  3964.  
  3965. #ifndef FILE_NAME
  3966. #define FILE_NAME __FILE__
  3967. #endif
  3968.  
  3969. #define ASSERT_EQUAL(x, y)                                                                       \
  3970.     {                                                                                            \
  3971.         std::ostringstream __assert_equal_private_os;                                            \
  3972.         __assert_equal_private_os << #x << " != " << #y << ", " << FILE_NAME << ":" << __LINE__; \
  3973.         AssertEqual(x, y, __assert_equal_private_os.str());                                      \
  3974.     }
  3975.  
  3976. #define ASSERT(x)                                                                   \
  3977.     {                                                                               \
  3978.         std::ostringstream __assert_private_os;                                     \
  3979.         __assert_private_os << #x << " is false, " << FILE_NAME << ":" << __LINE__; \
  3980.         Assert(static_cast<bool>(x), __assert_private_os.str());                    \
  3981.     }
  3982.  
  3983. #define RUN_TEST(tr, func) tr.RunTest(func, #func)
  3984.  
  3985. #define ASSERT_THROWS(expr, expected_exception)                                                   \
  3986.     {                                                                                             \
  3987.         bool __assert_private_flag = true;                                                        \
  3988.         try {                                                                                     \
  3989.             expr;                                                                                 \
  3990.             __assert_private_flag = false;                                                        \
  3991.         } catch (expected_exception&) {                                                           \
  3992.         } catch (...) {                                                                           \
  3993.             std::ostringstream __assert_private_os;                                               \
  3994.             __assert_private_os << "Expression " #expr                                            \
  3995.                                    " threw an unexpected exception"                               \
  3996.                                    " " FILE_NAME ":"                                              \
  3997.                                 << __LINE__;                                                      \
  3998.             Assert(false, __assert_private_os.str());                                             \
  3999.         }                                                                                         \
  4000.         if (!__assert_private_flag) {                                                             \
  4001.             std::ostringstream __assert_private_os;                                               \
  4002.             __assert_private_os << "Expression " #expr                                            \
  4003.                                    " is expected to throw " #expected_exception " " FILE_NAME ":" \
  4004.                                 << __LINE__;                                                      \
  4005.             Assert(false, __assert_private_os.str());                                             \
  4006.         }                                                                                         \
  4007.     }
  4008.  
  4009. #define ASSERT_DOESNT_THROW(expr)                               \
  4010.     try {                                                       \
  4011.         expr;                                                   \
  4012.     } catch (...) {                                             \
  4013.         std::ostringstream __assert_private_os;                 \
  4014.         __assert_private_os << "Expression " #expr              \
  4015.                                " threw an unexpected exception" \
  4016.                                " " FILE_NAME ":"                \
  4017.                             << __LINE__;                        \
  4018.         Assert(false, __assert_private_os.str());               \
  4019.     }
  4020.  
  4021. #define EOF_GUARD
Advertisement
Add Comment
Please, Sign In to add comment