LCOV - code coverage report
Current view: top level - tests - catch_node.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1720 1748 98.4 %
Date: 2023-12-10 17:25:12 Functions: 15 16 93.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2011-2023  Made to Order Software Corp.  All Rights Reserved
       2             : //
       3             : // https://snapwebsites.org/project/as2js
       4             : // contact@m2osw.com
       5             : //
       6             : // This program is free software: you can redistribute it and/or modify
       7             : // it under the terms of the GNU General Public License as published by
       8             : // the Free Software Foundation, either version 3 of the License, or
       9             : // (at your option) any later version.
      10             : //
      11             : // This program is distributed in the hope that it will be useful,
      12             : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             : // GNU General Public License for more details.
      15             : //
      16             : // You should have received a copy of the GNU General Public License
      17             : // along with this program.  If not, see <https://www.gnu.org/licenses/>.
      18             : 
      19             : // as2js
      20             : //
      21             : #include    <as2js/node.h>
      22             : 
      23             : #include    <as2js/exception.h>
      24             : #include    <as2js/message.h>
      25             : 
      26             : 
      27             : // self
      28             : //
      29             : #include    "catch_main.h"
      30             : 
      31             : 
      32             : // snapdev
      33             : //
      34             : #include    <snapdev/not_reached.h>
      35             : #include    <snapdev/ostream_to_buf.h>
      36             : #include    <snapdev/safe_stream.h>
      37             : #include    <snapdev/tokenize_string.h>
      38             : 
      39             : 
      40             : // libutf8
      41             : //
      42             : #include    <libutf8/iterator.h>
      43             : 
      44             : 
      45             : // C++
      46             : //
      47             : #include    <cstring>
      48             : #include    <algorithm>
      49             : #include    <iomanip>
      50             : 
      51             : 
      52             : // C
      53             : //
      54             : #include    <signal.h>
      55             : #include    <sys/wait.h>
      56             : 
      57             : 
      58             : // last include
      59             : //
      60             : #include    <snapdev/poison.h>
      61             : 
      62             : 
      63             : 
      64             : 
      65             : #include    "catch_node_data.ci"
      66             : 
      67             : 
      68             : 
      69             : namespace
      70             : {
      71             : 
      72             : 
      73           2 : int quick_exec(std::string const & cmd)
      74             : {
      75           2 :     int const child_pid(fork());
      76           4 :     if(child_pid < 0)
      77             :     {
      78           0 :         int const e(errno);
      79           0 :         std::cerr << "error: fork() failed: "
      80             :             << e
      81             :             << ", "
      82           0 :             << strerror(e)
      83           0 :             << "\n";
      84           0 :         return -1;
      85             :     }
      86             : 
      87           4 :     if(child_pid != 0)
      88             :     {
      89             :         // parent just waits on the child
      90             :         //
      91           2 :         int status(0);
      92           2 :         pid_t const pid(waitpid(child_pid, &status, 0));
      93           2 :         if(pid != child_pid)
      94             :         {
      95           0 :             std::cerr << "error: waitpid() returned "
      96             :                 << pid
      97           0 :                 << ", expected: "
      98             :                 << child_pid
      99           0 :                 << " instead.\n";
     100           0 :             return 128;
     101             :         }
     102             : 
     103           2 :         if(!WIFEXITED(status))
     104             :         {
     105           0 :             std::cerr << "error: waitpid() returned with a status other than \"exited\".\n";
     106           0 :             return 128;
     107             :         }
     108           2 :         else if(WIFSIGNALED(status))
     109             :         {
     110           0 :             std::cerr << "error: child was signaled.\n";
     111           0 :             return 128;
     112             :         }
     113             :         else
     114             :         {
     115           2 :             return WEXITSTATUS(status);
     116             :         }
     117             :     }
     118             : 
     119           2 :     std::vector<std::string> arg_strings;
     120           2 :     snapdev::tokenize_string(arg_strings, cmd, {" "}, true);
     121             : 
     122           4 :     std::vector<char *> args(arg_strings.size() + 1);
     123           5 :     for(std::size_t idx(0); idx < arg_strings.size(); ++idx)
     124             :     {
     125           3 :         args[idx] = const_cast<char *>(arg_strings[idx].c_str());
     126             :     }
     127             : 
     128           2 :     execvp(args[0], args.data());
     129             : 
     130             :     // it should never return
     131             :     //
     132           2 :     snapdev::NOT_REACHED();
     133           0 : }
     134             : 
     135             : 
     136             : 
     137             : }
     138             : 
     139             : 
     140             : 
     141             : 
     142             : 
     143             : 
     144             : 
     145           2 : CATCH_TEST_CASE("node_types", "[node][type]")
     146             : {
     147           2 :     CATCH_START_SECTION("node_types: all types (defined in catch_node.ci)")
     148             :     {
     149           2 :         std::vector<bool> valid_types(static_cast<std::size_t>(as2js::node_t::NODE_max) + 1);
     150         219 :         for(std::size_t i(0); i < g_node_types_size; ++i)
     151             :         {
     152             : //std::cout << "--- working on node type: [" << g_node_types[i].f_name << "] (" << static_cast<std::size_t>(g_node_types[i].f_type) << ")\n";
     153         218 :             if(static_cast<std::size_t>(g_node_types[i].f_type) < static_cast<std::size_t>(as2js::node_t::NODE_max))
     154             :             {
     155         217 :                 valid_types[static_cast<std::size_t>(g_node_types[i].f_type)] = true;
     156             :             }
     157             : 
     158             :             // define the type
     159             :             //
     160         218 :             as2js::node_t const node_type(g_node_types[i].f_type);
     161             : 
     162         218 :             CATCH_REQUIRE(strcmp(as2js::node::type_to_string(node_type), g_node_types[i].f_name) == 0);
     163             : 
     164         218 :             if(static_cast<std::size_t>(node_type) > static_cast<std::size_t>(as2js::node_t::NODE_max)
     165           1 :             && node_type != as2js::node_t::NODE_EOF)
     166             :             {
     167           0 :                 std::cerr << "Somehow a node type (" << static_cast<int>(node_type)
     168           0 :                           << ") is larger than the maximum allowed ("
     169           0 :                           << (static_cast<int>(as2js::node_t::NODE_max) - 1) << ")" << std::endl;
     170           0 :                 CATCH_REQUIRE(node_type == as2js::node_t::NODE_EOF);
     171             :             }
     172             : 
     173             :             // get the next type of node
     174             :             //
     175         218 :             as2js::node::pointer_t node(std::make_shared<as2js::node>(node_type));
     176             : 
     177             :             // check the type
     178             :             //
     179         218 :             CATCH_REQUIRE(node->get_type() == node_type);
     180             : 
     181             :             // get the name
     182             :             //
     183         218 :             char const * name(node->get_type_name());
     184             : //std::cout << "type = " << static_cast<int>(node_type) << " / " << name << "\n";
     185         218 :             CATCH_REQUIRE(strcmp(name, g_node_types[i].f_name) == 0);
     186             : 
     187             :             // test functions determining general types
     188             :             //
     189         218 :             CATCH_REQUIRE((node->is_number() == false || node->is_number() == true));
     190         218 :             CATCH_REQUIRE(static_cast<as2js::node const *>(node.get())->is_number() ^ ((g_node_types[i].f_flags & TEST_NODE_IS_NUMBER) == 0));
     191             : 
     192             :             // This NaN test is not sufficient for strings
     193             :             //
     194         218 :             CATCH_REQUIRE((node->is_nan() == false || node->is_nan() == true));
     195         218 :             CATCH_REQUIRE(static_cast<as2js::node const *>(node.get())->is_nan() ^ ((g_node_types[i].f_flags & TEST_NODE_IS_NAN) == 0));
     196             : 
     197         218 :             CATCH_REQUIRE((node->is_integer() == false || node->is_integer() == true));
     198         218 :             CATCH_REQUIRE(static_cast<as2js::node const *>(node.get())->is_integer() ^ ((g_node_types[i].f_flags & TEST_NODE_IS_INTEGER) == 0));
     199             : 
     200         218 :             CATCH_REQUIRE((node->is_floating_point() == false || node->is_floating_point() == true));
     201         218 :             CATCH_REQUIRE(static_cast<as2js::node const *>(node.get())->is_floating_point() ^ ((g_node_types[i].f_flags & TEST_NODE_IS_FLOATING_POINT) == 0));
     202             : 
     203         218 :             CATCH_REQUIRE((node->is_boolean() == false || node->is_boolean() == true));
     204         218 :             CATCH_REQUIRE(static_cast<as2js::node const *>(node.get())->is_boolean() ^ ((g_node_types[i].f_flags & TEST_NODE_IS_BOOLEAN) == 0));
     205             : 
     206         218 :             CATCH_REQUIRE((node->is_true() == false || node->is_true() == true));
     207         218 :             CATCH_REQUIRE(static_cast<as2js::node const *>(node.get())->is_true() ^ ((g_node_types[i].f_flags & TEST_NODE_IS_TRUE) == 0));
     208             : 
     209         218 :             CATCH_REQUIRE((node->is_false() == false || node->is_false() == true));
     210         218 :             CATCH_REQUIRE(static_cast<as2js::node const *>(node.get())->is_false() ^ ((g_node_types[i].f_flags & TEST_NODE_IS_FALSE) == 0));
     211             : 
     212         218 :             CATCH_REQUIRE((node->is_string() == false || node->is_string() == true));
     213         218 :             CATCH_REQUIRE(static_cast<as2js::node const *>(node.get())->is_string() ^ ((g_node_types[i].f_flags & TEST_NODE_IS_STRING) == 0));
     214             : 
     215         218 :             CATCH_REQUIRE((node->is_undefined() == false || node->is_undefined() == true));
     216         218 :             CATCH_REQUIRE(static_cast<as2js::node const *>(node.get())->is_undefined() ^ ((g_node_types[i].f_flags & TEST_NODE_IS_UNDEFINED) == 0));
     217             : 
     218         218 :             CATCH_REQUIRE((node->is_null() == false || node->is_null() == true));
     219         218 :             CATCH_REQUIRE(static_cast<as2js::node const *>(node.get())->is_null() ^ ((g_node_types[i].f_flags & TEST_NODE_IS_NULL) == 0));
     220             : 
     221         218 :             CATCH_REQUIRE((node->is_identifier() == false || node->is_identifier() == true));
     222         218 :             CATCH_REQUIRE(static_cast<as2js::node const *>(node.get())->is_identifier() ^ ((g_node_types[i].f_flags & TEST_NODE_IS_IDENTIFIER) == 0));
     223             : 
     224         218 :             CATCH_REQUIRE((node->is_literal() == false || node->is_literal() == true));
     225         218 :             CATCH_REQUIRE(static_cast<as2js::node const *>(node.get())->is_literal() ^ ((g_node_types[i].f_flags & (
     226             :                                                                                               TEST_NODE_IS_INTEGER
     227             :                                                                                             | TEST_NODE_IS_FLOATING_POINT
     228             :                                                                                             | TEST_NODE_IS_TRUE
     229             :                                                                                             | TEST_NODE_IS_FALSE
     230             :                                                                                             | TEST_NODE_IS_STRING
     231             :                                                                                             | TEST_NODE_IS_UNDEFINED
     232             :                                                                                             | TEST_NODE_IS_NULL)) == 0));
     233             : 
     234         218 :             if(!node->is_literal())
     235             :             {
     236         211 :                 as2js::node::pointer_t literal(std::make_shared<as2js::node>(as2js::node_t::NODE_STRING));
     237         211 :                 CATCH_REQUIRE(as2js::node::compare(node, literal, as2js::compare_mode_t::COMPARE_STRICT)  == as2js::compare_t::COMPARE_ERROR);
     238         211 :                 CATCH_REQUIRE(as2js::node::compare(node, literal, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_ERROR);
     239         211 :                 CATCH_REQUIRE(as2js::node::compare(node, literal, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_ERROR);
     240         211 :                 CATCH_REQUIRE(as2js::node::compare(literal, node, as2js::compare_mode_t::COMPARE_STRICT)  == as2js::compare_t::COMPARE_ERROR);
     241         211 :                 CATCH_REQUIRE(as2js::node::compare(literal, node, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_ERROR);
     242         211 :                 CATCH_REQUIRE(as2js::node::compare(literal, node, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_ERROR);
     243         211 :                 CATCH_REQUIRE(as2js::node::compare(literal, node, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_ERROR);
     244         211 :             }
     245             : 
     246         218 :             CATCH_REQUIRE((node->has_side_effects() == false || node->has_side_effects() == true));
     247         218 :             CATCH_REQUIRE(static_cast<as2js::node const *>(node.get())->has_side_effects() ^ ((g_node_types[i].f_flags & TEST_NODE_HAS_SIDE_EFFECTS) == 0));
     248             : 
     249         218 :             if(g_node_types[i].f_operator != nullptr)
     250             :             {
     251          65 :                 char const *op(as2js::node::operator_to_string(g_node_types[i].f_type));
     252          65 :                 CATCH_REQUIRE(op != nullptr);
     253          65 :                 CATCH_REQUIRE(strcmp(g_node_types[i].f_operator, op) == 0);
     254             :                 //std::cerr << " testing " << node->get_type_name() << " from " << op << std::endl;
     255          65 :                 CATCH_REQUIRE(as2js::node::string_to_operator(op) == g_node_types[i].f_type);
     256             : 
     257             :                 // check the special cases
     258             :                 //
     259          65 :                 switch(g_node_types[i].f_type)
     260             :                 {
     261           1 :                 case as2js::node_t::NODE_NOT_EQUAL:
     262           1 :                     CATCH_REQUIRE(as2js::node::string_to_operator("<>") == g_node_types[i].f_type);
     263           1 :                     break;
     264             : 
     265           1 :                 case as2js::node_t::NODE_ASSIGNMENT:
     266           1 :                     CATCH_REQUIRE(as2js::node::string_to_operator(":=") == g_node_types[i].f_type);
     267           1 :                     CATCH_REQUIRE(as2js::node::string_to_operator("\xE2\x89\x94") == g_node_types[i].f_type);
     268           1 :                     break;
     269             : 
     270           1 :                 case as2js::node_t::NODE_MULTIPLY:
     271           1 :                     CATCH_REQUIRE(as2js::node::string_to_operator("\xC3\x97") == g_node_types[i].f_type);
     272           1 :                     break;
     273             : 
     274           1 :                 case as2js::node_t::NODE_DIVIDE:
     275           1 :                     CATCH_REQUIRE(as2js::node::string_to_operator("\xC3\xB7") == g_node_types[i].f_type);
     276           1 :                     break;
     277             : 
     278           1 :                 case as2js::node_t::NODE_ARROW:
     279           1 :                     CATCH_REQUIRE(as2js::node::string_to_operator("\xE2\x87\x92") == g_node_types[i].f_type);
     280           1 :                     break;
     281             : 
     282           1 :                 case as2js::node_t::NODE_IN:
     283           1 :                     CATCH_REQUIRE(as2js::node::string_to_operator("\xE2\x88\x88") == g_node_types[i].f_type);
     284           1 :                     CATCH_REQUIRE(as2js::node::string_to_operator("\xE2\x88\x8A") == g_node_types[i].f_type);
     285           1 :                     break;
     286             : 
     287           1 :                 case as2js::node_t::NODE_LOGICAL_AND:
     288           1 :                     CATCH_REQUIRE(as2js::node::string_to_operator("\xE2\x88\xA7") == g_node_types[i].f_type);
     289           1 :                     break;
     290             : 
     291           1 :                 case as2js::node_t::NODE_LOGICAL_OR:
     292           1 :                     CATCH_REQUIRE(as2js::node::string_to_operator("\xE2\x88\xA8") == g_node_types[i].f_type);
     293           1 :                     break;
     294             : 
     295           1 :                 case as2js::node_t::NODE_ALMOST_EQUAL:
     296           1 :                     CATCH_REQUIRE(as2js::node::string_to_operator("\xE2\x89\x88") == g_node_types[i].f_type);
     297           1 :                     break;
     298             : 
     299           1 :                 case as2js::node_t::NODE_LESS_EQUAL:
     300           1 :                     CATCH_REQUIRE(as2js::node::string_to_operator("\xE2\x89\xA4") == g_node_types[i].f_type);
     301           1 :                     break;
     302             : 
     303           1 :                 case as2js::node_t::NODE_GREATER_EQUAL:
     304           1 :                     CATCH_REQUIRE(as2js::node::string_to_operator("\xE2\x89\xA5") == g_node_types[i].f_type);
     305           1 :                     break;
     306             : 
     307          54 :                 default:
     308             :                     // no special case
     309          54 :                     break;
     310             : 
     311             :                 }
     312             :             }
     313             :             else
     314             :             {
     315             :                 // static function can also be called from the node pointer
     316             :                 //std::cerr << " testing " << node->get_type_name() << std::endl;
     317         153 :                 CATCH_REQUIRE(node->operator_to_string(g_node_types[i].f_type) == nullptr);
     318         153 :                 CATCH_REQUIRE(as2js::node::string_to_operator(node->get_type_name()) == as2js::node_t::NODE_UNKNOWN);
     319             :             }
     320             : 
     321         218 :             if((g_node_types[i].f_flags & TEST_NODE_IS_SWITCH_OPERATOR) == 0)
     322             :             {
     323             :                 // only NODE_PARAM_MATCH accepts this call
     324         202 :                 as2js::node::pointer_t node_switch(std::make_shared<as2js::node>(as2js::node_t::NODE_SWITCH));
     325         202 :                 CATCH_REQUIRE_THROWS_MATCHES(
     326             :                       node_switch->set_switch_operator(node_type)
     327             :                     , as2js::internal_error
     328             :                     , Catch::Matchers::ExceptionMessage(
     329             :                               "internal_error: set_switch_operator() called with an operator which is not valid for switch."));
     330         202 :             }
     331             :             else
     332             :             {
     333          16 :                 as2js::node::pointer_t node_switch(std::make_shared<as2js::node>(as2js::node_t::NODE_SWITCH));
     334          16 :                 node_switch->set_switch_operator(node_type);
     335          16 :                 CATCH_REQUIRE(node_switch->get_switch_operator() == node_type);
     336          16 :             }
     337         218 :             if(node_type != as2js::node_t::NODE_SWITCH)
     338             :             {
     339             :                 // a valid operator, but not a valid node to set
     340         217 :                 CATCH_REQUIRE_THROWS_MATCHES(
     341             :                       node->set_switch_operator(as2js::node_t::NODE_STRICTLY_EQUAL)
     342             :                     , as2js::internal_error
     343             :                     , Catch::Matchers::ExceptionMessage(
     344             :                               "internal_error: set_switch_operator() called on a node which is not a switch node."));
     345             :                 // not a valid node to get
     346         217 :                 CATCH_REQUIRE_THROWS_MATCHES(
     347             :                       node->get_switch_operator()
     348             :                     , as2js::internal_error
     349             :                     , Catch::Matchers::ExceptionMessage(
     350             :                               "internal_error: get_switch_operator() called on a node which is not a switch node."));
     351             :             }
     352             : 
     353         218 :             if((g_node_types[i].f_flags & TEST_NODE_IS_PARAM_MATCH) == 0)
     354             :             {
     355             :                 // only NODE_PARAM_MATCH accepts this call
     356         217 :                 CATCH_REQUIRE_THROWS_MATCHES(
     357             :                       node->set_param_size(10)
     358             :                     , as2js::internal_error
     359             :                     , Catch::Matchers::ExceptionMessage(
     360             :                               "internal_error: set_param_size() called with a node other than a \"NODE_PARAM_MATCH\"."));
     361             :             }
     362             :             else
     363             :             {
     364             :                 // zero is not acceptable
     365           1 :                 CATCH_REQUIRE_THROWS_MATCHES(
     366             :                       node->set_param_size(0)
     367             :                     , as2js::internal_error
     368             :                     , Catch::Matchers::ExceptionMessage(
     369             :                               "internal_error: set_param_size() was called with a size of zero."));
     370             :                 // this one is accepted
     371           1 :                 node->set_param_size(10);
     372             :                 // cannot change the size once set
     373           1 :                 CATCH_REQUIRE_THROWS_MATCHES(
     374             :                       node->set_param_size(10)
     375             :                     , as2js::internal_error
     376             :                     , Catch::Matchers::ExceptionMessage(
     377             :                               "internal_error: set_param_size() called twice."));
     378             :             }
     379             : 
     380         218 :             if((g_node_types[i].f_flags & TEST_NODE_IS_BOOLEAN) == 0)
     381             :             {
     382         216 :                 CATCH_REQUIRE_THROWS_MATCHES(
     383             :                       node->get_boolean()
     384             :                     , as2js::internal_error
     385             :                     , Catch::Matchers::ExceptionMessage(
     386             :                               "internal_error: get_boolean() called with a non-Boolean node type."));
     387         216 :                 CATCH_REQUIRE_THROWS_MATCHES(
     388             :                       node->set_boolean(rand() & 1)
     389             :                     , as2js::internal_error
     390             :                     , Catch::Matchers::ExceptionMessage(
     391             :                               "internal_error: set_boolean() called with a non-Boolean node type."));
     392             :             }
     393           2 :             else if((g_node_types[i].f_flags & TEST_NODE_IS_TRUE) != 0)
     394             :             {
     395           1 :                 CATCH_REQUIRE(node->get_boolean());
     396             :             }
     397             :             else
     398             :             {
     399           1 :                 CATCH_REQUIRE(!node->get_boolean());
     400             :             }
     401             : 
     402         218 :             if((g_node_types[i].f_flags & TEST_NODE_IS_INTEGER) == 0)
     403             :             {
     404         217 :                 CATCH_REQUIRE_THROWS_MATCHES(
     405             :                       node->get_integer()
     406             :                     , as2js::internal_error
     407             :                     , Catch::Matchers::ExceptionMessage(
     408             :                               "internal_error: get_integer() called with a non-integer node type."));
     409         217 :                 as2js::integer random(rand());
     410         217 :                 CATCH_REQUIRE_THROWS_MATCHES(
     411             :                       node->set_integer(random)
     412             :                     , as2js::internal_error
     413             :                     , Catch::Matchers::ExceptionMessage(
     414             :                               "internal_error: set_integer() called with a non-integer node type."));
     415             :             }
     416             : 
     417         218 :             if((g_node_types[i].f_flags & TEST_NODE_IS_FLOATING_POINT) == 0)
     418             :             {
     419         217 :                 CATCH_REQUIRE_THROWS_MATCHES(
     420             :                       node->get_floating_point()
     421             :                     , as2js::internal_error
     422             :                     , Catch::Matchers::ExceptionMessage(
     423             :                               "internal_error: get_floating_point() called with a non-floating point node type."));
     424             : 
     425         217 :                 as2js::floating_point random(rand());
     426         217 :                 CATCH_REQUIRE_THROWS_MATCHES(
     427             :                       node->set_floating_point(random)
     428             :                     , as2js::internal_error
     429             :                     , Catch::Matchers::ExceptionMessage(
     430             :                               "internal_error: set_floating_point() called with a non-floating point node type."));
     431             :             }
     432             : 
     433             :             // here we have a special case as "many" different nodes accept
     434             :             // a string to represent one thing or another
     435             :             //
     436         218 :             if((g_node_types[i].f_flags & TEST_NODE_ACCEPT_STRING) == 0)
     437             :             {
     438         195 :                 CATCH_REQUIRE_THROWS_MATCHES(
     439             :                       node->get_string()
     440             :                     , as2js::internal_error
     441             :                     , Catch::Matchers::ExceptionMessage(
     442             :                               "internal_error: get_string() called with non-string node type: \""
     443             :                             + std::string(as2js::node::type_to_string(node_type))
     444             :                             + "\"."));
     445         975 :                 CATCH_REQUIRE_THROWS_MATCHES(
     446             :                       node->set_string("test")
     447             :                     , as2js::internal_error
     448             :                     , Catch::Matchers::ExceptionMessage(
     449             :                               "internal_error: set_string() called with a non-string node type."));
     450             :             }
     451             :             else
     452             :             {
     453          23 :                 node->set_string("random test");
     454          23 :                 CATCH_REQUIRE(node->get_string() == "random test");
     455             :             }
     456             : 
     457             :             // first test the flags that this type of node accepts
     458         218 :             std::bitset<static_cast<int>(as2js::flag_t::NODE_FLAG_max)> valid_flags;
     459         305 :             for(flags_per_node_t const *node_flags(g_node_types[i].f_node_flags);
     460         305 :                                         node_flags->f_flag != as2js::flag_t::NODE_FLAG_max;
     461             :                                         ++node_flags)
     462             :             {
     463             :                 // mark this specific flag as valid
     464          87 :                 valid_flags[static_cast<int>(node_flags->f_flag)] = true;
     465             : 
     466          87 :                 as2js::flag_set_t set;
     467          87 :                 CATCH_REQUIRE(node->compare_all_flags(set));
     468             : 
     469             : 
     470             :                 // before we set it, always false
     471          87 :                 CATCH_REQUIRE_FALSE(node->get_flag(node_flags->f_flag));
     472          87 :                 node->set_flag(node_flags->f_flag, true);
     473          87 :                 CATCH_REQUIRE(node->get_flag(node_flags->f_flag));
     474             : 
     475          87 :                 CATCH_REQUIRE_FALSE(node->compare_all_flags(set));
     476          87 :                 set[static_cast<int>(node_flags->f_flag)] = true;
     477          87 :                 CATCH_REQUIRE(node->compare_all_flags(set));
     478             : 
     479          87 :                 node->set_flag(node_flags->f_flag, false);
     480          87 :                 CATCH_REQUIRE_FALSE(node->get_flag(node_flags->f_flag));
     481             :             }
     482             : 
     483             :             // now test all the other flags
     484       13298 :             for(int j(-5); j <= static_cast<int>(as2js::flag_t::NODE_FLAG_max) + 5; ++j)
     485             :             {
     486       23762 :                 if(j < 0
     487       11990 :                 || j >= static_cast<int>(as2js::flag_t::NODE_FLAG_max)
     488       35752 :                 || !valid_flags[j])
     489             :                 {
     490       12993 :                     std::stringstream ss;
     491       12993 :                     ss << *node;
     492       25986 :                     std::string flag_name("<out of range>");
     493       12993 :                     if(j >= 0
     494       11903 :                     && j < static_cast<int>(as2js::flag_t::NODE_FLAG_max))
     495             :                     {
     496       10595 :                         flag_name = as2js::node::flag_to_string(static_cast<as2js::flag_t>(j));
     497             :                     }
     498             : #if 0
     499             : std::cerr << "--- [ERROR NOT HAPPENING?] internal_error: node_flag.cpp: node::verify_flag(): node type: "
     500             :                                 + std::string(g_node_types[i].f_name)
     501             :                                 + " flag ("
     502             :                                 + flag_name
     503             :                                 + "/"
     504             :                                 + std::to_string(j)
     505             :                                 + ") / type mismatch ("
     506             :                                 + node->get_type_name()
     507             :                                 + '/'
     508             :                                 + std::to_string(static_cast<int>(node->get_type()))
     509             :                                 + ") for node:\n"
     510             :                                 + ss.str()
     511             :                                 + '\n';
     512             : #endif
     513       12993 :                     CATCH_REQUIRE_THROWS_MATCHES(
     514             :                           node->get_flag(static_cast<as2js::flag_t>(j))
     515             :                         , as2js::internal_error
     516             :                         , Catch::Matchers::ExceptionMessage(
     517             :                                   "internal_error: node_flag.cpp: node::verify_flag(): flag ("
     518             :                                 + flag_name
     519             :                                 + "/"
     520             :                                 + std::to_string(j)
     521             :                                 + ") / type mismatch ("
     522             :                                 + as2js::node::type_to_string(node->get_type())
     523             :                                 + ':'
     524             :                                 + std::to_string(static_cast<int>(node->get_type()))
     525             :                                 + ") for node:\n"
     526             :                                 + ss.str()
     527             :                                 + '\n'));
     528       12993 :                     CATCH_REQUIRE_THROWS_MATCHES(
     529             :                           node->set_flag(static_cast<as2js::flag_t>(j), true)
     530             :                         , as2js::internal_error
     531             :                         , Catch::Matchers::ExceptionMessage(
     532             :                                   "internal_error: node_flag.cpp: node::verify_flag(): flag ("
     533             :                                 + flag_name
     534             :                                 + "/"
     535             :                                 + std::to_string(j)
     536             :                                 + ") / type mismatch ("
     537             :                                 + as2js::node::type_to_string(node->get_type())
     538             :                                 + ':'
     539             :                                 + std::to_string(static_cast<int>(node->get_type()))
     540             :                                 + ") for node:\n"
     541             :                                 + ss.str()
     542             :                                 + '\n'));
     543       12993 :                     CATCH_REQUIRE_THROWS_MATCHES(
     544             :                           node->set_flag(static_cast<as2js::flag_t>(j), false)
     545             :                         , as2js::internal_error
     546             :                         , Catch::Matchers::ExceptionMessage(
     547             :                                   "internal_error: node_flag.cpp: node::verify_flag(): flag ("
     548             :                                 + flag_name
     549             :                                 + "/"
     550             :                                 + std::to_string(j)
     551             :                                 + ") / type mismatch ("
     552             :                                 + as2js::node::type_to_string(node->get_type())
     553             :                                 + ':'
     554             :                                 + std::to_string(static_cast<int>(node->get_type()))
     555             :                                 + ") for node:\n"
     556             :                                 + ss.str()
     557             :                                 + '\n'));
     558       12993 :                 }
     559             :             }
     560             : 
     561             :             // test completely invalid attribute indices
     562        1308 :             for(int j(-5); j < 0; ++j)
     563             :             {
     564        1090 :                 CATCH_REQUIRE_THROWS_MATCHES(
     565             :                       node->get_attribute(static_cast<as2js::attribute_t>(j))
     566             :                     , as2js::internal_error
     567             :                     , Catch::Matchers::ExceptionMessage(
     568             :                               "internal_error: unknown attribute number (out of range) in node::attribute_to_string()."));
     569        1090 :                 CATCH_REQUIRE_THROWS_MATCHES(
     570             :                       node->set_attribute(static_cast<as2js::attribute_t>(j), true)
     571             :                     , as2js::internal_error
     572             :                     , Catch::Matchers::ExceptionMessage(
     573             :                               "internal_error: unknown attribute number (out of range) in node::attribute_to_string()."));
     574        1090 :                 CATCH_REQUIRE_THROWS_MATCHES(
     575             :                       node->set_attribute(static_cast<as2js::attribute_t>(j), false)
     576             :                     , as2js::internal_error
     577             :                     , Catch::Matchers::ExceptionMessage(
     578             :                               "internal_error: unknown attribute number (out of range) in node::attribute_to_string()."));
     579        1090 :                 CATCH_REQUIRE_THROWS_MATCHES(
     580             :                       node->attribute_to_string(static_cast<as2js::attribute_t>(j))
     581             :                     , as2js::internal_error
     582             :                     , Catch::Matchers::ExceptionMessage(
     583             :                               "internal_error: unknown attribute number (out of range) in node::attribute_to_string()."));
     584        1090 :                 CATCH_REQUIRE_THROWS_MATCHES(
     585             :                       as2js::node::attribute_to_string(static_cast<as2js::attribute_t>(j))
     586             :                     , as2js::internal_error
     587             :                     , Catch::Matchers::ExceptionMessage(
     588             :                               "internal_error: unknown attribute number (out of range) in node::attribute_to_string()."));
     589             :             }
     590        1526 :             for(int j(static_cast<int>(as2js::attribute_t::NODE_ATTR_max));
     591        1526 :                     j <= static_cast<int>(as2js::attribute_t::NODE_ATTR_max) + 5;
     592             :                     ++j)
     593             :             {
     594        1308 :                 CATCH_REQUIRE_THROWS_MATCHES(
     595             :                       node->get_attribute(static_cast<as2js::attribute_t>(j))
     596             :                     , as2js::internal_error
     597             :                     , Catch::Matchers::ExceptionMessage(
     598             :                               "internal_error: unknown attribute number (out of range) in node::attribute_to_string()."));
     599        1308 :                 CATCH_REQUIRE_THROWS_MATCHES(
     600             :                       node->set_attribute(static_cast<as2js::attribute_t>(j), true)
     601             :                     , as2js::internal_error
     602             :                     , Catch::Matchers::ExceptionMessage(
     603             :                               "internal_error: unknown attribute number (out of range) in node::attribute_to_string()."));
     604        1308 :                 CATCH_REQUIRE_THROWS_MATCHES(
     605             :                       node->set_attribute(static_cast<as2js::attribute_t>(j), false)
     606             :                     , as2js::internal_error
     607             :                     , Catch::Matchers::ExceptionMessage(
     608             :                               "internal_error: unknown attribute number (out of range) in node::attribute_to_string()."));
     609        1308 :                 CATCH_REQUIRE_THROWS_MATCHES(
     610             :                       node->attribute_to_string(static_cast<as2js::attribute_t>(j))
     611             :                     , as2js::internal_error
     612             :                     , Catch::Matchers::ExceptionMessage(
     613             :                               "internal_error: unknown attribute number (out of range) in node::attribute_to_string()."));
     614        1308 :                 CATCH_REQUIRE_THROWS_MATCHES(
     615             :                       as2js::node::attribute_to_string(static_cast<as2js::attribute_t>(j))
     616             :                     , as2js::internal_error
     617             :                     , Catch::Matchers::ExceptionMessage(
     618             :                               "internal_error: unknown attribute number (out of range) in node::attribute_to_string()."));
     619             :             }
     620             : 
     621             :             // attributes can be assigned to all types except NODE_PROGRAM
     622             :             // which only accepts NODE_DEFINED
     623        6758 :             for(int j(0); j < static_cast<int>(as2js::attribute_t::NODE_ATTR_max); ++j)
     624             :             {
     625        6540 :                 bool valid(true);
     626        6540 :                 switch(node_type)
     627             :                 {
     628          30 :                 case as2js::node_t::NODE_PROGRAM:
     629          30 :                     valid = j == static_cast<int>(as2js::attribute_t::NODE_ATTR_DEFINED);
     630          30 :                     break;
     631             : 
     632        2580 :                 case as2js::node_t::NODE_ADD:
     633             :                 case as2js::node_t::NODE_ARRAY:
     634             :                 case as2js::node_t::NODE_ARRAY_LITERAL:
     635             :                 case as2js::node_t::NODE_AS:
     636             :                 case as2js::node_t::NODE_ASSIGNMENT:
     637             :                 case as2js::node_t::NODE_ASSIGNMENT_ADD:
     638             :                 case as2js::node_t::NODE_ASSIGNMENT_BITWISE_AND:
     639             :                 case as2js::node_t::NODE_ASSIGNMENT_BITWISE_OR:
     640             :                 case as2js::node_t::NODE_ASSIGNMENT_BITWISE_XOR:
     641             :                 case as2js::node_t::NODE_ASSIGNMENT_DIVIDE:
     642             :                 case as2js::node_t::NODE_ASSIGNMENT_LOGICAL_AND:
     643             :                 case as2js::node_t::NODE_ASSIGNMENT_LOGICAL_OR:
     644             :                 case as2js::node_t::NODE_ASSIGNMENT_LOGICAL_XOR:
     645             :                 case as2js::node_t::NODE_ASSIGNMENT_MAXIMUM:
     646             :                 case as2js::node_t::NODE_ASSIGNMENT_MINIMUM:
     647             :                 case as2js::node_t::NODE_ASSIGNMENT_MODULO:
     648             :                 case as2js::node_t::NODE_ASSIGNMENT_MULTIPLY:
     649             :                 case as2js::node_t::NODE_ASSIGNMENT_POWER:
     650             :                 case as2js::node_t::NODE_ASSIGNMENT_ROTATE_LEFT:
     651             :                 case as2js::node_t::NODE_ASSIGNMENT_ROTATE_RIGHT:
     652             :                 case as2js::node_t::NODE_ASSIGNMENT_SHIFT_LEFT:
     653             :                 case as2js::node_t::NODE_ASSIGNMENT_SHIFT_RIGHT:
     654             :                 case as2js::node_t::NODE_ASSIGNMENT_SHIFT_RIGHT_UNSIGNED:
     655             :                 case as2js::node_t::NODE_ASSIGNMENT_SUBTRACT:
     656             :                 case as2js::node_t::NODE_BITWISE_AND:
     657             :                 case as2js::node_t::NODE_BITWISE_NOT:
     658             :                 case as2js::node_t::NODE_BITWISE_OR:
     659             :                 case as2js::node_t::NODE_BITWISE_XOR:
     660             :                 case as2js::node_t::NODE_CALL:
     661             :                 case as2js::node_t::NODE_CONDITIONAL:
     662             :                 case as2js::node_t::NODE_DECREMENT:
     663             :                 case as2js::node_t::NODE_DELETE:
     664             :                 case as2js::node_t::NODE_DIVIDE:
     665             :                 case as2js::node_t::NODE_EQUAL:
     666             :                 case as2js::node_t::NODE_FALSE:
     667             :                 case as2js::node_t::NODE_FLOATING_POINT:
     668             :                 case as2js::node_t::NODE_FUNCTION:
     669             :                 case as2js::node_t::NODE_GREATER:
     670             :                 case as2js::node_t::NODE_GREATER_EQUAL:
     671             :                 case as2js::node_t::NODE_IDENTIFIER:
     672             :                 case as2js::node_t::NODE_IN:
     673             :                 case as2js::node_t::NODE_INCREMENT:
     674             :                 case as2js::node_t::NODE_INSTANCEOF:
     675             :                 case as2js::node_t::NODE_INTEGER:
     676             :                 case as2js::node_t::NODE_IS:
     677             :                 case as2js::node_t::NODE_LESS:
     678             :                 case as2js::node_t::NODE_LESS_EQUAL:
     679             :                 case as2js::node_t::NODE_LIST:
     680             :                 case as2js::node_t::NODE_LOGICAL_AND:
     681             :                 case as2js::node_t::NODE_LOGICAL_NOT:
     682             :                 case as2js::node_t::NODE_LOGICAL_OR:
     683             :                 case as2js::node_t::NODE_LOGICAL_XOR:
     684             :                 case as2js::node_t::NODE_MATCH:
     685             :                 case as2js::node_t::NODE_MAXIMUM:
     686             :                 case as2js::node_t::NODE_MEMBER:
     687             :                 case as2js::node_t::NODE_MINIMUM:
     688             :                 case as2js::node_t::NODE_MODULO:
     689             :                 case as2js::node_t::NODE_MULTIPLY:
     690             :                 case as2js::node_t::NODE_NAME:
     691             :                 case as2js::node_t::NODE_NEW:
     692             :                 case as2js::node_t::NODE_NOT_EQUAL:
     693             :                 case as2js::node_t::NODE_NULL:
     694             :                 case as2js::node_t::NODE_OBJECT_LITERAL:
     695             :                 case as2js::node_t::NODE_POST_DECREMENT:
     696             :                 case as2js::node_t::NODE_POST_INCREMENT:
     697             :                 case as2js::node_t::NODE_POWER:
     698             :                 case as2js::node_t::NODE_PRIVATE:
     699             :                 case as2js::node_t::NODE_PUBLIC:
     700             :                 case as2js::node_t::NODE_RANGE:
     701             :                 case as2js::node_t::NODE_ROTATE_LEFT:
     702             :                 case as2js::node_t::NODE_ROTATE_RIGHT:
     703             :                 case as2js::node_t::NODE_SCOPE:
     704             :                 case as2js::node_t::NODE_SHIFT_LEFT:
     705             :                 case as2js::node_t::NODE_SHIFT_RIGHT:
     706             :                 case as2js::node_t::NODE_SHIFT_RIGHT_UNSIGNED:
     707             :                 case as2js::node_t::NODE_STRICTLY_EQUAL:
     708             :                 case as2js::node_t::NODE_STRICTLY_NOT_EQUAL:
     709             :                 case as2js::node_t::NODE_STRING:
     710             :                 case as2js::node_t::NODE_SUBTRACT:
     711             :                 case as2js::node_t::NODE_SUPER:
     712             :                 case as2js::node_t::NODE_THIS:
     713             :                 case as2js::node_t::NODE_TRUE:
     714             :                 case as2js::node_t::NODE_TYPEOF:
     715             :                 case as2js::node_t::NODE_UNDEFINED:
     716             :                 case as2js::node_t::NODE_VIDENTIFIER:
     717             :                 case as2js::node_t::NODE_VOID:
     718        2580 :                     break;
     719             : 
     720        3930 :                 default:
     721             :                     // any other type and you get an exception
     722        3930 :                     valid = j != static_cast<int>(as2js::attribute_t::NODE_ATTR_TYPE);
     723        3930 :                     break;
     724             : 
     725             :                 }
     726             : 
     727             :                 //if(node_type == as2js::node_t::NODE_PROGRAM
     728             :                 //&& j != static_cast<int>(as2js::attribute_t::NODE_ATTR_DEFINED))
     729        6540 :                 if(!valid)
     730             :                 {
     731         160 :                     CATCH_REQUIRE_THROWS_MATCHES(
     732             :                           node->get_attribute(static_cast<as2js::attribute_t>(j))
     733             :                         , as2js::internal_error
     734             :                         , Catch::Matchers::ExceptionMessage(
     735             :                                   "internal_error: node \""
     736             :                                 + std::string(as2js::node::type_to_string(node->get_type()))
     737             :                                 + "\" does not like attribute \""
     738             :                                 + as2js::node::attribute_to_string(static_cast<as2js::attribute_t>(j))
     739             :                                 + "\" in node::verify_attribute()."));
     740         160 :                     CATCH_REQUIRE_THROWS_MATCHES(
     741             :                           node->set_attribute(static_cast<as2js::attribute_t>(j), true)
     742             :                         , as2js::internal_error
     743             :                         , Catch::Matchers::ExceptionMessage(
     744             :                                   "internal_error: node \""
     745             :                                 + std::string(as2js::node::type_to_string(node->get_type()))
     746             :                                 + "\" does not like attribute \""
     747             :                                 + as2js::node::attribute_to_string(static_cast<as2js::attribute_t>(j))
     748             :                                 + "\" in node::verify_attribute()."));
     749         160 :                     CATCH_REQUIRE_THROWS_MATCHES(
     750             :                           node->set_attribute(static_cast<as2js::attribute_t>(j), false)
     751             :                         , as2js::internal_error
     752             :                         , Catch::Matchers::ExceptionMessage(
     753             :                                   "internal_error: node \""
     754             :                                 + std::string(as2js::node::type_to_string(node->get_type()))
     755             :                                 + "\" does not like attribute \""
     756             :                                 + as2js::node::attribute_to_string(static_cast<as2js::attribute_t>(j))
     757             :                                 + "\" in node::verify_attribute()."));
     758             :                 }
     759             :                 else
     760             :                 {
     761             :                     // before we set it, always false
     762        6380 :                     CATCH_REQUIRE(!node->get_attribute(static_cast<as2js::attribute_t>(j)));
     763        6380 :                     node->set_attribute(static_cast<as2js::attribute_t>(j), true);
     764        6380 :                     CATCH_REQUIRE(node->get_attribute(static_cast<as2js::attribute_t>(j)));
     765             :                     // since we reset them all we won't have a problem with conflicts in this loop
     766        6380 :                     node->set_attribute(static_cast<as2js::attribute_t>(j), false);
     767        6380 :                     CATCH_REQUIRE(!node->get_attribute(static_cast<as2js::attribute_t>(j)));
     768             :                 }
     769        6540 :                 char const *attr_name1(node->attribute_to_string(static_cast<as2js::attribute_t>(j)));
     770        6540 :                 CATCH_REQUIRE(attr_name1 != nullptr);
     771        6540 :                 char const *attr_name2(as2js::node::attribute_to_string(static_cast<as2js::attribute_t>(j)));
     772        6540 :                 CATCH_REQUIRE(attr_name2 != nullptr);
     773        6540 :                 CATCH_REQUIRE(strcmp(attr_name1, attr_name2) == 0);
     774             : 
     775        6540 :                 switch(static_cast<as2js::attribute_t>(j))
     776             :                 {
     777         436 :                 case as2js::attribute_t::NODE_ATTR_PUBLIC:        CATCH_REQUIRE(strcmp(attr_name1, "PUBLIC")         == 0); break;
     778         436 :                 case as2js::attribute_t::NODE_ATTR_PRIVATE:       CATCH_REQUIRE(strcmp(attr_name1, "PRIVATE")        == 0); break;
     779         436 :                 case as2js::attribute_t::NODE_ATTR_PROTECTED:     CATCH_REQUIRE(strcmp(attr_name1, "PROTECTED")      == 0); break;
     780         436 :                 case as2js::attribute_t::NODE_ATTR_INTERNAL:      CATCH_REQUIRE(strcmp(attr_name1, "INTERNAL")       == 0); break;
     781         436 :                 case as2js::attribute_t::NODE_ATTR_TRANSIENT:     CATCH_REQUIRE(strcmp(attr_name1, "TRANSIENT")      == 0); break;
     782         436 :                 case as2js::attribute_t::NODE_ATTR_VOLATILE:      CATCH_REQUIRE(strcmp(attr_name1, "VOLATILE")       == 0); break;
     783         436 :                 case as2js::attribute_t::NODE_ATTR_STATIC:        CATCH_REQUIRE(strcmp(attr_name1, "STATIC")         == 0); break;
     784         436 :                 case as2js::attribute_t::NODE_ATTR_ABSTRACT:      CATCH_REQUIRE(strcmp(attr_name1, "ABSTRACT")       == 0); break;
     785         436 :                 case as2js::attribute_t::NODE_ATTR_VIRTUAL:       CATCH_REQUIRE(strcmp(attr_name1, "VIRTUAL")        == 0); break;
     786         436 :                 case as2js::attribute_t::NODE_ATTR_ARRAY:         CATCH_REQUIRE(strcmp(attr_name1, "ARRAY")          == 0); break;
     787         436 :                 case as2js::attribute_t::NODE_ATTR_INLINE:        CATCH_REQUIRE(strcmp(attr_name1, "INLINE")         == 0); break;
     788         436 :                 case as2js::attribute_t::NODE_ATTR_REQUIRE_ELSE:  CATCH_REQUIRE(strcmp(attr_name1, "REQUIRE_ELSE")   == 0); break;
     789         436 :                 case as2js::attribute_t::NODE_ATTR_ENSURE_THEN:   CATCH_REQUIRE(strcmp(attr_name1, "ENSURE_THEN")    == 0); break;
     790         436 :                 case as2js::attribute_t::NODE_ATTR_NATIVE:        CATCH_REQUIRE(strcmp(attr_name1, "NATIVE")         == 0); break;
     791         436 :                 case as2js::attribute_t::NODE_ATTR_UNIMPLEMENTED: CATCH_REQUIRE(strcmp(attr_name1, "UNIMPLEMENTED")  == 0); break;
     792         436 :                 case as2js::attribute_t::NODE_ATTR_DEPRECATED:    CATCH_REQUIRE(strcmp(attr_name1, "DEPRECATED")     == 0); break;
     793         436 :                 case as2js::attribute_t::NODE_ATTR_UNSAFE:        CATCH_REQUIRE(strcmp(attr_name1, "UNSAFE")         == 0); break;
     794         436 :                 case as2js::attribute_t::NODE_ATTR_EXTERN:        CATCH_REQUIRE(strcmp(attr_name1, "EXTERN")         == 0); break;
     795         436 :                 case as2js::attribute_t::NODE_ATTR_CONSTRUCTOR:   CATCH_REQUIRE(strcmp(attr_name1, "CONSTRUCTOR")    == 0); break;
     796         436 :                 case as2js::attribute_t::NODE_ATTR_FINAL:         CATCH_REQUIRE(strcmp(attr_name1, "FINAL")          == 0); break;
     797         436 :                 case as2js::attribute_t::NODE_ATTR_ENUMERABLE:    CATCH_REQUIRE(strcmp(attr_name1, "ENUMERABLE")     == 0); break;
     798         436 :                 case as2js::attribute_t::NODE_ATTR_TRUE:          CATCH_REQUIRE(strcmp(attr_name1, "TRUE")           == 0); break;
     799         436 :                 case as2js::attribute_t::NODE_ATTR_FALSE:         CATCH_REQUIRE(strcmp(attr_name1, "FALSE")          == 0); break;
     800         436 :                 case as2js::attribute_t::NODE_ATTR_UNUSED:        CATCH_REQUIRE(strcmp(attr_name1, "UNUSED")         == 0); break;
     801         436 :                 case as2js::attribute_t::NODE_ATTR_DYNAMIC:       CATCH_REQUIRE(strcmp(attr_name1, "DYNAMIC")        == 0); break;
     802         436 :                 case as2js::attribute_t::NODE_ATTR_FOREACH:       CATCH_REQUIRE(strcmp(attr_name1, "FOREACH")        == 0); break;
     803         436 :                 case as2js::attribute_t::NODE_ATTR_NOBREAK:       CATCH_REQUIRE(strcmp(attr_name1, "NOBREAK")        == 0); break;
     804         436 :                 case as2js::attribute_t::NODE_ATTR_AUTOBREAK:     CATCH_REQUIRE(strcmp(attr_name1, "AUTOBREAK")      == 0); break;
     805         436 :                 case as2js::attribute_t::NODE_ATTR_TYPE:          CATCH_REQUIRE(strcmp(attr_name1, "TYPE")           == 0); break;
     806         436 :                 case as2js::attribute_t::NODE_ATTR_DEFINED:       CATCH_REQUIRE(strcmp(attr_name1, "DEFINED")        == 0); break;
     807           0 :                 case as2js::attribute_t::NODE_ATTR_max:           CATCH_REQUIRE(!"attribute max should not be checked in this test"); break;
     808             :                 }
     809             :             }
     810             : 
     811             :             // cloning is available for basic nodes
     812             :             //
     813         218 :             if((g_node_types[i].f_flags & TEST_NODE_IS_BASIC) == 0)
     814             :             {
     815         210 :                 CATCH_REQUIRE_THROWS_MATCHES(
     816             :                       node->clone_basic_node()
     817             :                     , as2js::internal_error
     818             :                     , Catch::Matchers::ExceptionMessage(
     819             :                               "internal_error: node.cpp: clone_basic_node(): called with a node which is not considered to be a basic node."));
     820             :             }
     821             :             else
     822             :             {
     823             :                 // TODO: better test what is copied and what is not copied
     824             :                 //
     825           8 :                 as2js::node::pointer_t clone(node->clone_basic_node());
     826           8 :                 CATCH_REQUIRE(node->get_type() == clone->get_type());
     827             :                 //CATCH_REQUIRE(node->get_flag(...) == clone->get_flag(...));
     828           8 :                 CATCH_REQUIRE(node->get_attribute_node() == clone->get_attribute_node());
     829             :                 //CATCH_REQUIRE(node->get_attribute(...) == clone->get_attribute(...));
     830             :                 //CATCH_REQUIRE(node->get_switch_operator() == clone->get_switch_operator()); -- none of these nodes are NODE_SWITCH
     831           8 :                 CATCH_REQUIRE(node->is_locked() == clone->is_locked());
     832           8 :                 CATCH_REQUIRE(node->get_position() == clone->get_position());
     833           8 :                 CATCH_REQUIRE(node->get_instance() == clone->get_instance());
     834           8 :                 CATCH_REQUIRE(node->get_goto_enter() == clone->get_goto_enter());
     835           8 :                 CATCH_REQUIRE(node->get_goto_exit() == clone->get_goto_exit());
     836             :                 //CATCH_REQUIRE(node->get_variable(...) == clone->get_variable(...));
     837             :                 //CATCH_REQUIRE(node->find_label(...) == clone->find_label(...));
     838           8 :             }
     839         218 :         }
     840             : 
     841             :         // as we may be adding new node types without updating the tests,
     842             :         // here we verify that all node types that were not checked are
     843             :         // indeed invalid
     844             :         //
     845             :         // the vector is important because the node type numbers are not
     846             :         // incremental; some make use of the input character (i.e. '=' and
     847             :         // '!' are node types for the assignment and logical not) then we
     848             :         // jump to number 1001
     849             :         //
     850        1195 :         for(std::size_t i(0); i <= static_cast<std::size_t>(as2js::node_t::NODE_max); ++i)
     851             :         {
     852        1194 :             if(!valid_types[i])
     853             :             {
     854             :                 // WARNING: if an errror occurs here it is likely because
     855             :                 //          the corresponding node type is new and the test
     856             :                 //          was not yet updated; i.e. if the node is now
     857             :                 //          considered valid, then we are expected to
     858             :                 //          return from the make_shared<>() instead of
     859             :                 //          throwing as expected by the test for invalid
     860             :                 //          nodes
     861             :                 //
     862             :                 //          also... this does not work if you also cannot
     863             :                 //          create the node (i.e. I added a type, added the
     864             :                 //          parsing in the lexer, did not add the type to
     865             :                 //          the node::node() constructor)
     866             :                 //
     867             : //std::cout << "--- creating node with 'invalid' type: " << i << " || " << static_cast<int>(as2js::node_t::NODE_YIELD) << "\n";
     868         977 :                 as2js::node_t const node_type(static_cast<as2js::node_t>(i));
     869         977 :                 CATCH_REQUIRE_THROWS_MATCHES(
     870             :                       std::make_shared<as2js::node>(node_type)
     871             :                     , as2js::incompatible_type
     872             :                     , Catch::Matchers::ExceptionMessage(
     873             :                               "as2js_exception: unknown node type number, "
     874             :                             + std::to_string(i)
     875             :                             + ", used to create a node."));
     876             :             }
     877             :         }
     878           1 :     }
     879           2 :     CATCH_END_SECTION()
     880             : 
     881           2 :     CATCH_START_SECTION("node_types: node types outside the defined range")
     882             :     {
     883             :         // test with completely random numbers too (outside of the
     884             :         // standard range of node types)
     885             :         //
     886         101 :         for(size_t i(0); i < 100; ++i)
     887             :         {
     888         100 :             int32_t j((rand() << 16) ^ rand());
     889         100 :             if(j < -1 || j >= static_cast<ssize_t>(as2js::node_t::NODE_max))
     890             :             {
     891         100 :                 as2js::node_t node_type(static_cast<as2js::node_t>(j));
     892         100 :                 CATCH_REQUIRE_THROWS_MATCHES(
     893             :                       std::make_shared<as2js::node>(node_type)
     894             :                     , as2js::incompatible_type
     895             :                     , Catch::Matchers::ExceptionMessage(
     896             :                               "as2js_exception: unknown node type number, "
     897             :                             + std::to_string(j)
     898             :                             + ", used to create a node."));
     899             :             }
     900             :         }
     901             :     }
     902           2 :     CATCH_END_SECTION()
     903           2 : }
     904             : 
     905             : 
     906           1 : CATCH_TEST_CASE("node_compare", "[node][compare]")
     907             : {
     908           1 :     CATCH_START_SECTION("node_compare: NULL value")
     909             :     {
     910           1 :         as2js::node::pointer_t node1_true(std::make_shared<as2js::node>(as2js::node_t::NODE_TRUE));
     911           1 :         as2js::node::pointer_t node2_false(std::make_shared<as2js::node>(as2js::node_t::NODE_FALSE));
     912           1 :         as2js::node::pointer_t node3_true(std::make_shared<as2js::node>(as2js::node_t::NODE_TRUE));
     913           1 :         as2js::node::pointer_t node4_false(std::make_shared<as2js::node>(as2js::node_t::NODE_FALSE));
     914             : 
     915           1 :         as2js::node::pointer_t node5_33(std::make_shared<as2js::node>(as2js::node_t::NODE_INTEGER));
     916           1 :         as2js::integer i33;
     917           1 :         i33.set(33);
     918           1 :         node5_33->set_integer(i33);
     919             : 
     920           1 :         as2js::node::pointer_t node6_101(std::make_shared<as2js::node>(as2js::node_t::NODE_INTEGER));
     921           1 :         as2js::integer i101;
     922           1 :         i101.set(101);
     923           1 :         node6_101->set_integer(i101);
     924             : 
     925           1 :         as2js::node::pointer_t node7_33(std::make_shared<as2js::node>(as2js::node_t::NODE_FLOATING_POINT));
     926           1 :         as2js::floating_point f33;
     927           1 :         f33.set(3.3);
     928           1 :         node7_33->set_floating_point(f33);
     929             : 
     930           1 :         as2js::node::pointer_t node7_nearly33(std::make_shared<as2js::node>(as2js::node_t::NODE_FLOATING_POINT));
     931           1 :         as2js::floating_point fnearly33;
     932           1 :         fnearly33.set(3.300001);
     933           1 :         node7_nearly33->set_floating_point(fnearly33);
     934             : 
     935           1 :         as2js::node::pointer_t node8_101(std::make_shared<as2js::node>(as2js::node_t::NODE_FLOATING_POINT));
     936           1 :         as2js::floating_point f101;
     937           1 :         f101.set(1.01);
     938           1 :         node8_101->set_floating_point(f101);
     939             : 
     940           1 :         as2js::node::pointer_t node9_null(std::make_shared<as2js::node>(as2js::node_t::NODE_NULL));
     941           1 :         as2js::node::pointer_t node10_null(std::make_shared<as2js::node>(as2js::node_t::NODE_NULL));
     942             : 
     943           1 :         as2js::node::pointer_t node11_undefined(std::make_shared<as2js::node>(as2js::node_t::NODE_UNDEFINED));
     944           1 :         as2js::node::pointer_t node12_undefined(std::make_shared<as2js::node>(as2js::node_t::NODE_UNDEFINED));
     945             : 
     946           1 :         as2js::node::pointer_t node13_empty_string(std::make_shared<as2js::node>(as2js::node_t::NODE_STRING));
     947           1 :         as2js::node::pointer_t node14_blah(std::make_shared<as2js::node>(as2js::node_t::NODE_STRING));
     948           1 :         node14_blah->set_string("blah");
     949           1 :         as2js::node::pointer_t node15_foo(std::make_shared<as2js::node>(as2js::node_t::NODE_STRING));
     950           1 :         node15_foo->set_string("foo");
     951           1 :         as2js::node::pointer_t node16_07(std::make_shared<as2js::node>(as2js::node_t::NODE_STRING));
     952           1 :         node16_07->set_string("0.7");
     953           1 :         as2js::node::pointer_t node17_nearly33(std::make_shared<as2js::node>(as2js::node_t::NODE_STRING));
     954           1 :         node17_nearly33->set_string("3.300001");
     955             : 
     956             :         // BOOLEAN
     957           1 :         CATCH_REQUIRE(as2js::node::compare(node1_true, node1_true, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
     958           1 :         CATCH_REQUIRE(as2js::node::compare(node1_true, node3_true, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
     959           1 :         CATCH_REQUIRE(as2js::node::compare(node3_true, node1_true, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
     960           1 :         CATCH_REQUIRE(as2js::node::compare(node3_true, node3_true, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
     961             : 
     962           1 :         CATCH_REQUIRE(as2js::node::compare(node1_true, node1_true, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
     963           1 :         CATCH_REQUIRE(as2js::node::compare(node1_true, node3_true, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
     964           1 :         CATCH_REQUIRE(as2js::node::compare(node3_true, node1_true, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
     965           1 :         CATCH_REQUIRE(as2js::node::compare(node3_true, node3_true, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
     966             : 
     967           1 :         CATCH_REQUIRE(as2js::node::compare(node1_true, node1_true, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
     968           1 :         CATCH_REQUIRE(as2js::node::compare(node1_true, node3_true, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
     969           1 :         CATCH_REQUIRE(as2js::node::compare(node3_true, node1_true, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
     970           1 :         CATCH_REQUIRE(as2js::node::compare(node3_true, node3_true, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
     971             : 
     972           1 :         CATCH_REQUIRE(as2js::node::compare(node2_false, node2_false, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
     973           1 :         CATCH_REQUIRE(as2js::node::compare(node2_false, node4_false, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
     974           1 :         CATCH_REQUIRE(as2js::node::compare(node4_false, node2_false, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
     975           1 :         CATCH_REQUIRE(as2js::node::compare(node4_false, node4_false, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
     976             : 
     977           1 :         CATCH_REQUIRE(as2js::node::compare(node2_false, node2_false, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
     978           1 :         CATCH_REQUIRE(as2js::node::compare(node2_false, node4_false, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
     979           1 :         CATCH_REQUIRE(as2js::node::compare(node4_false, node2_false, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
     980           1 :         CATCH_REQUIRE(as2js::node::compare(node4_false, node4_false, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
     981             : 
     982           1 :         CATCH_REQUIRE(as2js::node::compare(node2_false, node2_false, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
     983           1 :         CATCH_REQUIRE(as2js::node::compare(node2_false, node4_false, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
     984           1 :         CATCH_REQUIRE(as2js::node::compare(node4_false, node2_false, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
     985           1 :         CATCH_REQUIRE(as2js::node::compare(node4_false, node4_false, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
     986             : 
     987           1 :         CATCH_REQUIRE(as2js::node::compare(node1_true, node2_false, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_GREATER);
     988           1 :         CATCH_REQUIRE(as2js::node::compare(node3_true, node2_false, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_GREATER);
     989           1 :         CATCH_REQUIRE(as2js::node::compare(node1_true, node4_false, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_GREATER);
     990           1 :         CATCH_REQUIRE(as2js::node::compare(node3_true, node4_false, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_GREATER);
     991             : 
     992           1 :         CATCH_REQUIRE(as2js::node::compare(node1_true, node2_false, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_GREATER);
     993           1 :         CATCH_REQUIRE(as2js::node::compare(node3_true, node2_false, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_GREATER);
     994           1 :         CATCH_REQUIRE(as2js::node::compare(node1_true, node4_false, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_GREATER);
     995           1 :         CATCH_REQUIRE(as2js::node::compare(node3_true, node4_false, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_GREATER);
     996             : 
     997           1 :         CATCH_REQUIRE(as2js::node::compare(node1_true, node2_false, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_GREATER);
     998           1 :         CATCH_REQUIRE(as2js::node::compare(node3_true, node2_false, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_GREATER);
     999           1 :         CATCH_REQUIRE(as2js::node::compare(node1_true, node4_false, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_GREATER);
    1000           1 :         CATCH_REQUIRE(as2js::node::compare(node3_true, node4_false, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_GREATER);
    1001             : 
    1002           1 :         CATCH_REQUIRE(as2js::node::compare(node2_false, node1_true, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_LESS);
    1003           1 :         CATCH_REQUIRE(as2js::node::compare(node2_false, node3_true, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_LESS);
    1004           1 :         CATCH_REQUIRE(as2js::node::compare(node4_false, node1_true, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_LESS);
    1005           1 :         CATCH_REQUIRE(as2js::node::compare(node4_false, node3_true, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_LESS);
    1006             : 
    1007           1 :         CATCH_REQUIRE(as2js::node::compare(node2_false, node1_true, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_LESS);
    1008           1 :         CATCH_REQUIRE(as2js::node::compare(node2_false, node3_true, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_LESS);
    1009           1 :         CATCH_REQUIRE(as2js::node::compare(node4_false, node1_true, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_LESS);
    1010           1 :         CATCH_REQUIRE(as2js::node::compare(node4_false, node3_true, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_LESS);
    1011             : 
    1012           1 :         CATCH_REQUIRE(as2js::node::compare(node2_false, node1_true, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_LESS);
    1013           1 :         CATCH_REQUIRE(as2js::node::compare(node2_false, node3_true, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_LESS);
    1014           1 :         CATCH_REQUIRE(as2js::node::compare(node4_false, node1_true, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_LESS);
    1015           1 :         CATCH_REQUIRE(as2js::node::compare(node4_false, node3_true, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_LESS);
    1016             : 
    1017             :         // FLOAT
    1018           1 :         CATCH_REQUIRE(as2js::node::compare(node7_33, node7_33, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
    1019           1 :         CATCH_REQUIRE(as2js::node::compare(node7_33, node7_nearly33, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_LESS);
    1020           1 :         CATCH_REQUIRE(as2js::node::compare(node7_nearly33, node7_33, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_GREATER);
    1021           1 :         CATCH_REQUIRE(as2js::node::compare(node7_33, node17_nearly33, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
    1022           1 :         CATCH_REQUIRE(as2js::node::compare(node17_nearly33, node7_33, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
    1023           1 :         CATCH_REQUIRE(as2js::node::compare(node7_33, node8_101, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_GREATER);
    1024           1 :         CATCH_REQUIRE(as2js::node::compare(node8_101, node7_33, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_LESS);
    1025           1 :         CATCH_REQUIRE(as2js::node::compare(node8_101, node8_101, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
    1026             : 
    1027           1 :         CATCH_REQUIRE(as2js::node::compare(node7_33, node7_33, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
    1028           1 :         CATCH_REQUIRE(as2js::node::compare(node7_33, node7_nearly33, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_LESS);
    1029           1 :         CATCH_REQUIRE(as2js::node::compare(node7_nearly33, node7_33, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_GREATER);
    1030           1 :         CATCH_REQUIRE(as2js::node::compare(node7_33, node17_nearly33, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_LESS);
    1031           1 :         CATCH_REQUIRE(as2js::node::compare(node17_nearly33, node7_33, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_GREATER);
    1032           1 :         CATCH_REQUIRE(as2js::node::compare(node7_33, node8_101, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_GREATER);
    1033           1 :         CATCH_REQUIRE(as2js::node::compare(node8_101, node7_33, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_LESS);
    1034           1 :         CATCH_REQUIRE(as2js::node::compare(node8_101, node8_101, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
    1035             : 
    1036           1 :         CATCH_REQUIRE(as2js::node::compare(node7_33, node7_33, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
    1037           1 :         CATCH_REQUIRE(as2js::node::compare(node7_33, node7_nearly33, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
    1038           1 :         CATCH_REQUIRE(as2js::node::compare(node7_nearly33, node7_33, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
    1039           1 :         CATCH_REQUIRE(as2js::node::compare(node7_33, node17_nearly33, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
    1040           1 :         CATCH_REQUIRE(as2js::node::compare(node17_nearly33, node7_33, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
    1041           1 :         CATCH_REQUIRE(as2js::node::compare(node7_33, node8_101, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_GREATER);
    1042           1 :         CATCH_REQUIRE(as2js::node::compare(node8_101, node7_33, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_LESS);
    1043           1 :         CATCH_REQUIRE(as2js::node::compare(node8_101, node8_101, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
    1044             : 
    1045             :         // INTEGER
    1046           1 :         CATCH_REQUIRE(as2js::node::compare(node5_33, node5_33, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
    1047           1 :         CATCH_REQUIRE(as2js::node::compare(node5_33, node6_101, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_LESS);
    1048           1 :         CATCH_REQUIRE(as2js::node::compare(node6_101, node5_33, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_GREATER);
    1049           1 :         CATCH_REQUIRE(as2js::node::compare(node6_101, node6_101, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
    1050             : 
    1051           1 :         CATCH_REQUIRE(as2js::node::compare(node5_33, node5_33, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
    1052           1 :         CATCH_REQUIRE(as2js::node::compare(node5_33, node6_101, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_LESS);
    1053           1 :         CATCH_REQUIRE(as2js::node::compare(node6_101, node5_33, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_GREATER);
    1054           1 :         CATCH_REQUIRE(as2js::node::compare(node6_101, node6_101, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
    1055             : 
    1056           1 :         CATCH_REQUIRE(as2js::node::compare(node5_33, node5_33, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
    1057           1 :         CATCH_REQUIRE(as2js::node::compare(node5_33, node6_101, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_LESS);
    1058           1 :         CATCH_REQUIRE(as2js::node::compare(node6_101, node5_33, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_GREATER);
    1059           1 :         CATCH_REQUIRE(as2js::node::compare(node6_101, node6_101, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
    1060             : 
    1061             :         // NULL
    1062           1 :         CATCH_REQUIRE(as2js::node::compare(node9_null, node9_null, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
    1063           1 :         CATCH_REQUIRE(as2js::node::compare(node9_null, node10_null, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
    1064           1 :         CATCH_REQUIRE(as2js::node::compare(node10_null, node9_null, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
    1065           1 :         CATCH_REQUIRE(as2js::node::compare(node10_null, node10_null, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
    1066             : 
    1067           1 :         CATCH_REQUIRE(as2js::node::compare(node9_null, node9_null, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
    1068           1 :         CATCH_REQUIRE(as2js::node::compare(node9_null, node10_null, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
    1069           1 :         CATCH_REQUIRE(as2js::node::compare(node10_null, node9_null, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
    1070           1 :         CATCH_REQUIRE(as2js::node::compare(node10_null, node10_null, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
    1071             : 
    1072           1 :         CATCH_REQUIRE(as2js::node::compare(node9_null, node9_null, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
    1073           1 :         CATCH_REQUIRE(as2js::node::compare(node9_null, node10_null, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
    1074           1 :         CATCH_REQUIRE(as2js::node::compare(node10_null, node9_null, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
    1075           1 :         CATCH_REQUIRE(as2js::node::compare(node10_null, node10_null, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
    1076             : 
    1077             :         // UNDEFINED
    1078           1 :         CATCH_REQUIRE(as2js::node::compare(node11_undefined, node11_undefined, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
    1079           1 :         CATCH_REQUIRE(as2js::node::compare(node11_undefined, node12_undefined, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
    1080           1 :         CATCH_REQUIRE(as2js::node::compare(node12_undefined, node11_undefined, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
    1081           1 :         CATCH_REQUIRE(as2js::node::compare(node12_undefined, node12_undefined, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
    1082             : 
    1083           1 :         CATCH_REQUIRE(as2js::node::compare(node11_undefined, node11_undefined, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
    1084           1 :         CATCH_REQUIRE(as2js::node::compare(node11_undefined, node12_undefined, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
    1085           1 :         CATCH_REQUIRE(as2js::node::compare(node12_undefined, node11_undefined, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
    1086           1 :         CATCH_REQUIRE(as2js::node::compare(node12_undefined, node12_undefined, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
    1087             : 
    1088           1 :         CATCH_REQUIRE(as2js::node::compare(node11_undefined, node11_undefined, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
    1089           1 :         CATCH_REQUIRE(as2js::node::compare(node11_undefined, node12_undefined, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
    1090           1 :         CATCH_REQUIRE(as2js::node::compare(node12_undefined, node11_undefined, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
    1091           1 :         CATCH_REQUIRE(as2js::node::compare(node12_undefined, node12_undefined, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
    1092             : 
    1093             :         // STRING
    1094           1 :         CATCH_REQUIRE(as2js::node::compare(node13_empty_string, node13_empty_string, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
    1095           1 :         CATCH_REQUIRE(as2js::node::compare(node13_empty_string, node14_blah, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_LESS);
    1096           1 :         CATCH_REQUIRE(as2js::node::compare(node13_empty_string, node15_foo, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_LESS);
    1097           1 :         CATCH_REQUIRE(as2js::node::compare(node14_blah, node13_empty_string, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_GREATER);
    1098           1 :         CATCH_REQUIRE(as2js::node::compare(node14_blah, node14_blah, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
    1099           1 :         CATCH_REQUIRE(as2js::node::compare(node14_blah, node15_foo, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_LESS);
    1100           1 :         CATCH_REQUIRE(as2js::node::compare(node15_foo, node13_empty_string, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_GREATER);
    1101           1 :         CATCH_REQUIRE(as2js::node::compare(node15_foo, node14_blah, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_GREATER);
    1102           1 :         CATCH_REQUIRE(as2js::node::compare(node15_foo, node15_foo, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
    1103             : 
    1104           1 :         CATCH_REQUIRE(as2js::node::compare(node13_empty_string, node13_empty_string, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
    1105           1 :         CATCH_REQUIRE(as2js::node::compare(node13_empty_string, node14_blah, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_LESS);
    1106           1 :         CATCH_REQUIRE(as2js::node::compare(node13_empty_string, node15_foo, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_LESS);
    1107           1 :         CATCH_REQUIRE(as2js::node::compare(node14_blah, node13_empty_string, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_GREATER);
    1108           1 :         CATCH_REQUIRE(as2js::node::compare(node14_blah, node14_blah, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
    1109           1 :         CATCH_REQUIRE(as2js::node::compare(node14_blah, node15_foo, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_LESS);
    1110           1 :         CATCH_REQUIRE(as2js::node::compare(node15_foo, node13_empty_string, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_GREATER);
    1111           1 :         CATCH_REQUIRE(as2js::node::compare(node15_foo, node14_blah, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_GREATER);
    1112           1 :         CATCH_REQUIRE(as2js::node::compare(node15_foo, node15_foo, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
    1113             : 
    1114           1 :         CATCH_REQUIRE(as2js::node::compare(node13_empty_string, node13_empty_string, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
    1115           1 :         CATCH_REQUIRE(as2js::node::compare(node13_empty_string, node14_blah, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_LESS);
    1116           1 :         CATCH_REQUIRE(as2js::node::compare(node13_empty_string, node15_foo, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_LESS);
    1117           1 :         CATCH_REQUIRE(as2js::node::compare(node14_blah, node13_empty_string, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_GREATER);
    1118           1 :         CATCH_REQUIRE(as2js::node::compare(node14_blah, node14_blah, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
    1119           1 :         CATCH_REQUIRE(as2js::node::compare(node14_blah, node15_foo, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_LESS);
    1120           1 :         CATCH_REQUIRE(as2js::node::compare(node15_foo, node13_empty_string, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_GREATER);
    1121           1 :         CATCH_REQUIRE(as2js::node::compare(node15_foo, node14_blah, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_GREATER);
    1122           1 :         CATCH_REQUIRE(as2js::node::compare(node15_foo, node15_foo, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
    1123             : 
    1124             :         // NULL vs UNDEFINED
    1125           1 :         CATCH_REQUIRE(as2js::node::compare(node9_null, node11_undefined, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
    1126           1 :         CATCH_REQUIRE(as2js::node::compare(node9_null, node12_undefined, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
    1127           1 :         CATCH_REQUIRE(as2js::node::compare(node10_null, node11_undefined, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
    1128           1 :         CATCH_REQUIRE(as2js::node::compare(node10_null, node12_undefined, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
    1129           1 :         CATCH_REQUIRE(as2js::node::compare(node11_undefined, node9_null, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
    1130           1 :         CATCH_REQUIRE(as2js::node::compare(node12_undefined, node9_null, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
    1131           1 :         CATCH_REQUIRE(as2js::node::compare(node11_undefined, node10_null, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
    1132           1 :         CATCH_REQUIRE(as2js::node::compare(node12_undefined, node10_null, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
    1133             : 
    1134           1 :         CATCH_REQUIRE(as2js::node::compare(node9_null, node11_undefined, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
    1135           1 :         CATCH_REQUIRE(as2js::node::compare(node9_null, node12_undefined, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
    1136           1 :         CATCH_REQUIRE(as2js::node::compare(node10_null, node11_undefined, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
    1137           1 :         CATCH_REQUIRE(as2js::node::compare(node10_null, node12_undefined, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
    1138           1 :         CATCH_REQUIRE(as2js::node::compare(node11_undefined, node9_null, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
    1139           1 :         CATCH_REQUIRE(as2js::node::compare(node12_undefined, node9_null, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
    1140           1 :         CATCH_REQUIRE(as2js::node::compare(node11_undefined, node10_null, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
    1141           1 :         CATCH_REQUIRE(as2js::node::compare(node12_undefined, node10_null, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
    1142             : 
    1143           1 :         CATCH_REQUIRE(as2js::node::compare(node9_null, node11_undefined, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
    1144           1 :         CATCH_REQUIRE(as2js::node::compare(node9_null, node12_undefined, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
    1145           1 :         CATCH_REQUIRE(as2js::node::compare(node10_null, node11_undefined, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
    1146           1 :         CATCH_REQUIRE(as2js::node::compare(node10_null, node12_undefined, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
    1147           1 :         CATCH_REQUIRE(as2js::node::compare(node11_undefined, node9_null, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
    1148           1 :         CATCH_REQUIRE(as2js::node::compare(node12_undefined, node9_null, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
    1149           1 :         CATCH_REQUIRE(as2js::node::compare(node11_undefined, node10_null, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
    1150           1 :         CATCH_REQUIRE(as2js::node::compare(node12_undefined, node10_null, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
    1151             : 
    1152             :         // <any> against FLOATING_POINT
    1153           1 :         CATCH_REQUIRE(as2js::node::compare(node1_true, node7_33, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
    1154           1 :         CATCH_REQUIRE(as2js::node::compare(node2_false, node7_33, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
    1155           1 :         CATCH_REQUIRE(as2js::node::compare(node5_33, node7_33, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
    1156           1 :         CATCH_REQUIRE(as2js::node::compare(node6_101, node7_33, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
    1157           1 :         CATCH_REQUIRE(as2js::node::compare(node9_null, node7_33, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
    1158           1 :         CATCH_REQUIRE(as2js::node::compare(node11_undefined, node7_33, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
    1159           1 :         CATCH_REQUIRE(as2js::node::compare(node13_empty_string, node7_33, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
    1160           1 :         CATCH_REQUIRE(as2js::node::compare(node14_blah, node7_33, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
    1161           1 :         CATCH_REQUIRE(as2js::node::compare(node16_07, node7_33, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
    1162             : 
    1163           1 :         CATCH_REQUIRE(as2js::node::compare(node1_true, node7_33, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_LESS);
    1164           1 :         CATCH_REQUIRE(as2js::node::compare(node2_false, node7_33, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_LESS);
    1165           1 :         CATCH_REQUIRE(as2js::node::compare(node5_33, node7_33, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_GREATER);
    1166           1 :         CATCH_REQUIRE(as2js::node::compare(node6_101, node7_33, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_GREATER);
    1167           1 :         CATCH_REQUIRE(as2js::node::compare(node9_null, node7_33, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_LESS);
    1168           1 :         CATCH_REQUIRE(as2js::node::compare(node11_undefined, node7_33, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_UNORDERED);
    1169           1 :         CATCH_REQUIRE(as2js::node::compare(node13_empty_string, node7_33, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_LESS);
    1170           1 :         CATCH_REQUIRE(as2js::node::compare(node14_blah, node7_33, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_UNORDERED);
    1171           1 :         CATCH_REQUIRE(as2js::node::compare(node16_07, node7_33, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_LESS);
    1172             : 
    1173           1 :         CATCH_REQUIRE(as2js::node::compare(node1_true, node7_33, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_LESS);
    1174           1 :         CATCH_REQUIRE(as2js::node::compare(node2_false, node7_33, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_LESS);
    1175           1 :         CATCH_REQUIRE(as2js::node::compare(node5_33, node7_33, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_GREATER);
    1176           1 :         CATCH_REQUIRE(as2js::node::compare(node6_101, node7_33, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_GREATER);
    1177           1 :         CATCH_REQUIRE(as2js::node::compare(node9_null, node7_33, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_LESS);
    1178           1 :         CATCH_REQUIRE(as2js::node::compare(node11_undefined, node7_33, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_UNORDERED);
    1179           1 :         CATCH_REQUIRE(as2js::node::compare(node13_empty_string, node7_33, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_LESS);
    1180           1 :         CATCH_REQUIRE(as2js::node::compare(node14_blah, node7_33, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_UNORDERED);
    1181           1 :         CATCH_REQUIRE(as2js::node::compare(node16_07, node7_33, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_LESS);
    1182             : 
    1183             :         // FLOATING_POINT against <any>
    1184           1 :         CATCH_REQUIRE(as2js::node::compare(node8_101, node1_true, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
    1185           1 :         CATCH_REQUIRE(as2js::node::compare(node8_101, node2_false, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
    1186           1 :         CATCH_REQUIRE(as2js::node::compare(node8_101, node5_33, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
    1187           1 :         CATCH_REQUIRE(as2js::node::compare(node8_101, node6_101, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
    1188           1 :         CATCH_REQUIRE(as2js::node::compare(node8_101, node9_null, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
    1189           1 :         CATCH_REQUIRE(as2js::node::compare(node8_101, node11_undefined, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
    1190           1 :         CATCH_REQUIRE(as2js::node::compare(node8_101, node13_empty_string, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
    1191           1 :         CATCH_REQUIRE(as2js::node::compare(node8_101, node14_blah, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
    1192           1 :         CATCH_REQUIRE(as2js::node::compare(node8_101, node16_07, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
    1193             : 
    1194           1 :         CATCH_REQUIRE(as2js::node::compare(node8_101, node1_true, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_GREATER);
    1195           1 :         CATCH_REQUIRE(as2js::node::compare(node8_101, node2_false, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_GREATER);
    1196           1 :         CATCH_REQUIRE(as2js::node::compare(node8_101, node5_33, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_LESS);
    1197           1 :         CATCH_REQUIRE(as2js::node::compare(node8_101, node6_101, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_LESS);
    1198           1 :         CATCH_REQUIRE(as2js::node::compare(node8_101, node9_null, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_GREATER);
    1199           1 :         CATCH_REQUIRE(as2js::node::compare(node8_101, node11_undefined, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_UNORDERED);
    1200           1 :         CATCH_REQUIRE(as2js::node::compare(node8_101, node13_empty_string, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_GREATER);
    1201           1 :         CATCH_REQUIRE(as2js::node::compare(node8_101, node14_blah, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_UNORDERED);
    1202           1 :         CATCH_REQUIRE(as2js::node::compare(node8_101, node16_07, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_GREATER);
    1203             : 
    1204           1 :         CATCH_REQUIRE(as2js::node::compare(node8_101, node2_false, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_GREATER);
    1205           1 :         CATCH_REQUIRE(as2js::node::compare(node8_101, node5_33, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_LESS);
    1206           1 :         CATCH_REQUIRE(as2js::node::compare(node8_101, node6_101, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_LESS);
    1207           1 :         CATCH_REQUIRE(as2js::node::compare(node8_101, node9_null, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_GREATER);
    1208           1 :         CATCH_REQUIRE(as2js::node::compare(node8_101, node11_undefined, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_UNORDERED);
    1209           1 :         CATCH_REQUIRE(as2js::node::compare(node8_101, node13_empty_string, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_GREATER);
    1210           1 :         CATCH_REQUIRE(as2js::node::compare(node8_101, node14_blah, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_UNORDERED);
    1211           1 :         CATCH_REQUIRE(as2js::node::compare(node8_101, node16_07, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_GREATER);
    1212           1 :     }
    1213           1 :     CATCH_END_SECTION()
    1214           1 : }
    1215             : 
    1216             : 
    1217           3 : CATCH_TEST_CASE("node_conversions", "[node][conversion]")
    1218             : {
    1219           3 :     CATCH_START_SECTION("node_conversions: simple")
    1220             :     {
    1221             :         // first test simple conversions
    1222         219 :         for(size_t i(0); i < g_node_types_size; ++i)
    1223             :         {
    1224             :             // original type
    1225         218 :             as2js::node_t original_type(g_node_types[i].f_type);
    1226             : 
    1227             :             // all nodes can be converted to UNKNOWN
    1228             :             {
    1229         218 :                 as2js::node::pointer_t node(std::make_shared<as2js::node>(original_type));
    1230             :                 {
    1231         218 :                     snapdev::ostream_to_buf<char> out(std::cerr);
    1232         436 :                     as2js::node_lock lock(node);
    1233         218 :                     CATCH_REQUIRE_THROWS_MATCHES(
    1234             :                           node->to_unknown()
    1235             :                         , as2js::locked_node
    1236             :                         , Catch::Matchers::ExceptionMessage(
    1237             :                                   "as2js_exception: trying to modify a locked node."));
    1238         218 :                     CATCH_REQUIRE(node->get_type() == original_type);
    1239         218 :                     CATCH_REQUIRE(out.str().substr(0, 65) == "error: The following node is locked and thus cannot be modified:\n");
    1240         218 :                 }
    1241         218 :                 node->to_unknown();
    1242         218 :                 CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_UNKNOWN);
    1243         218 :             }
    1244             : 
    1245             :             // CALL can be convert to AS
    1246             :             {
    1247         218 :                 as2js::node::pointer_t node(std::make_shared<as2js::node>(original_type));
    1248             :                 {
    1249         218 :                     snapdev::ostream_to_buf<char> out(std::cerr);
    1250         436 :                     as2js::node_lock lock(node);
    1251         218 :                     CATCH_REQUIRE_THROWS_MATCHES(
    1252             :                           node->to_as()
    1253             :                         , as2js::locked_node
    1254             :                         , Catch::Matchers::ExceptionMessage(
    1255             :                                   "as2js_exception: trying to modify a locked node."));
    1256         218 :                     CATCH_REQUIRE(node->get_type() == original_type);
    1257         218 :                     CATCH_REQUIRE(out.str().substr(0, 65) == "error: The following node is locked and thus cannot be modified:\n");
    1258         218 :                 }
    1259         218 :                 if(original_type == as2js::node_t::NODE_CALL)
    1260             :                 {
    1261             :                     // in this case it works
    1262           1 :                     CATCH_REQUIRE(node->to_as());
    1263           1 :                     CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_AS);
    1264             :                 }
    1265             :                 else
    1266             :                 {
    1267             :                     // in this case it fails
    1268         217 :                     CATCH_REQUIRE(!node->to_as());
    1269         217 :                     CATCH_REQUIRE(node->get_type() == original_type);
    1270             :                 }
    1271         218 :             }
    1272             : 
    1273             :             // test what would happen if we were to call to_boolean()
    1274             :             {
    1275         218 :                 as2js::node::pointer_t node(std::make_shared<as2js::node>(original_type));
    1276             :                 {
    1277         436 :                     as2js::node_lock lock(node);
    1278         218 :                     node->to_boolean_type_only();
    1279         218 :                     CATCH_REQUIRE(node->get_type() == original_type);
    1280         218 :                 }
    1281         218 :                 as2js::node_t new_type(node->to_boolean_type_only());
    1282         218 :                 switch(original_type)
    1283             :                 {
    1284           1 :                 case as2js::node_t::NODE_TRUE:
    1285           1 :                     CATCH_REQUIRE(new_type == as2js::node_t::NODE_TRUE);
    1286           1 :                     break;
    1287             : 
    1288           6 :                 case as2js::node_t::NODE_FALSE:
    1289             :                 case as2js::node_t::NODE_NULL:
    1290             :                 case as2js::node_t::NODE_UNDEFINED:
    1291             :                 case as2js::node_t::NODE_INTEGER: // by default integers are set to zero
    1292             :                 case as2js::node_t::NODE_FLOATING_POINT: // by default floating points are set to zero
    1293             :                 case as2js::node_t::NODE_STRING: // by default strings are empty
    1294           6 :                     CATCH_REQUIRE(new_type == as2js::node_t::NODE_FALSE);
    1295           6 :                     break;
    1296             : 
    1297         211 :                 default:
    1298         211 :                     CATCH_REQUIRE(new_type == as2js::node_t::NODE_UNDEFINED);
    1299         211 :                     break;
    1300             : 
    1301             :                 }
    1302         218 :             }
    1303             : 
    1304             :             // a few nodes can be converted to a boolean value
    1305             :             {
    1306         218 :                 as2js::node::pointer_t node(std::make_shared<as2js::node>(original_type));
    1307             :                 {
    1308         218 :                     snapdev::ostream_to_buf<char> out(std::cerr);
    1309         436 :                     as2js::node_lock lock(node);
    1310         218 :                     CATCH_REQUIRE_THROWS_MATCHES(
    1311             :                           node->to_boolean()
    1312             :                         , as2js::locked_node
    1313             :                         , Catch::Matchers::ExceptionMessage(
    1314             :                                   "as2js_exception: trying to modify a locked node."));
    1315         218 :                     CATCH_REQUIRE(node->get_type() == original_type);
    1316         218 :                     CATCH_REQUIRE(out.str().substr(0, 65) == "error: The following node is locked and thus cannot be modified:\n");
    1317         218 :                 }
    1318         218 :                 switch(original_type)
    1319             :                 {
    1320           1 :                 case as2js::node_t::NODE_TRUE:
    1321           1 :                     CATCH_REQUIRE(node->to_boolean());
    1322           1 :                     CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_TRUE);
    1323           1 :                     break;
    1324             : 
    1325           6 :                 case as2js::node_t::NODE_FALSE:
    1326             :                 case as2js::node_t::NODE_NULL:
    1327             :                 case as2js::node_t::NODE_UNDEFINED:
    1328             :                 case as2js::node_t::NODE_INTEGER: // by default integers are set to zero
    1329             :                 case as2js::node_t::NODE_FLOATING_POINT: // by default floating points are set to zero
    1330             :                 case as2js::node_t::NODE_STRING: // by default strings are empty
    1331           6 :                     CATCH_REQUIRE(node->to_boolean());
    1332           6 :                     CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_FALSE);
    1333           6 :                     break;
    1334             : 
    1335         211 :                 default:
    1336         211 :                     CATCH_REQUIRE(!node->to_boolean());
    1337         211 :                     CATCH_REQUIRE(node->get_type() == original_type);
    1338         211 :                     break;
    1339             : 
    1340             :                 }
    1341         218 :             }
    1342             : 
    1343             :             // a couple types of nodes can be converted to a CALL
    1344             :             {
    1345         218 :                 as2js::node::pointer_t node(std::make_shared<as2js::node>(original_type));
    1346             :                 {
    1347         218 :                     snapdev::ostream_to_buf<char> out(std::cerr);
    1348         436 :                     as2js::node_lock lock(node);
    1349         218 :                     CATCH_REQUIRE_THROWS_MATCHES(
    1350             :                           node->to_call()
    1351             :                         , as2js::locked_node
    1352             :                         , Catch::Matchers::ExceptionMessage(
    1353             :                                   "as2js_exception: trying to modify a locked node."));
    1354         218 :                     CATCH_REQUIRE(node->get_type() == original_type);
    1355         218 :                     CATCH_REQUIRE(out.str().substr(0, 65) == "error: The following node is locked and thus cannot be modified:\n");
    1356         218 :                 }
    1357         218 :                 switch(original_type)
    1358             :                 {
    1359          62 :                 case as2js::node_t::NODE_ADD:
    1360             :                 case as2js::node_t::NODE_ALMOST_EQUAL:
    1361             :                 case as2js::node_t::NODE_ARRAY:
    1362             :                 case as2js::node_t::NODE_ASSIGNMENT:
    1363             :                 case as2js::node_t::NODE_ASSIGNMENT_ADD:
    1364             :                 case as2js::node_t::NODE_ASSIGNMENT_BITWISE_AND:
    1365             :                 case as2js::node_t::NODE_ASSIGNMENT_BITWISE_OR:
    1366             :                 case as2js::node_t::NODE_ASSIGNMENT_BITWISE_XOR:
    1367             :                 case as2js::node_t::NODE_ASSIGNMENT_DIVIDE:
    1368             :                 case as2js::node_t::NODE_ASSIGNMENT_LOGICAL_AND:
    1369             :                 case as2js::node_t::NODE_ASSIGNMENT_LOGICAL_OR:
    1370             :                 case as2js::node_t::NODE_ASSIGNMENT_LOGICAL_XOR:
    1371             :                 case as2js::node_t::NODE_ASSIGNMENT_MAXIMUM:
    1372             :                 case as2js::node_t::NODE_ASSIGNMENT_MINIMUM:
    1373             :                 case as2js::node_t::NODE_ASSIGNMENT_MODULO:
    1374             :                 case as2js::node_t::NODE_ASSIGNMENT_MULTIPLY:
    1375             :                 case as2js::node_t::NODE_ASSIGNMENT_POWER:
    1376             :                 case as2js::node_t::NODE_ASSIGNMENT_ROTATE_LEFT:
    1377             :                 case as2js::node_t::NODE_ASSIGNMENT_ROTATE_RIGHT:
    1378             :                 case as2js::node_t::NODE_ASSIGNMENT_SHIFT_LEFT:
    1379             :                 case as2js::node_t::NODE_ASSIGNMENT_SHIFT_RIGHT:
    1380             :                 case as2js::node_t::NODE_ASSIGNMENT_SHIFT_RIGHT_UNSIGNED:
    1381             :                 case as2js::node_t::NODE_ASSIGNMENT_SUBTRACT:
    1382             :                 case as2js::node_t::NODE_BITWISE_AND:
    1383             :                 case as2js::node_t::NODE_BITWISE_NOT:
    1384             :                 case as2js::node_t::NODE_BITWISE_OR:
    1385             :                 case as2js::node_t::NODE_BITWISE_XOR:
    1386             :                 case as2js::node_t::NODE_COMMA:
    1387             :                 case as2js::node_t::NODE_COMPARE:
    1388             :                 case as2js::node_t::NODE_DECREMENT:
    1389             :                 case as2js::node_t::NODE_DIVIDE:
    1390             :                 case as2js::node_t::NODE_EQUAL:
    1391             :                 case as2js::node_t::NODE_GREATER:
    1392             :                 case as2js::node_t::NODE_GREATER_EQUAL:
    1393             :                 case as2js::node_t::NODE_INCREMENT:
    1394             :                 case as2js::node_t::NODE_LESS:
    1395             :                 case as2js::node_t::NODE_LESS_EQUAL:
    1396             :                 case as2js::node_t::NODE_LIST:
    1397             :                 case as2js::node_t::NODE_LOGICAL_AND:
    1398             :                 case as2js::node_t::NODE_LOGICAL_NOT:
    1399             :                 case as2js::node_t::NODE_LOGICAL_OR:
    1400             :                 case as2js::node_t::NODE_LOGICAL_XOR:
    1401             :                 case as2js::node_t::NODE_MATCH:
    1402             :                 case as2js::node_t::NODE_MAXIMUM:
    1403             :                 case as2js::node_t::NODE_MEMBER:
    1404             :                 case as2js::node_t::NODE_MINIMUM:
    1405             :                 case as2js::node_t::NODE_MODULO:
    1406             :                 case as2js::node_t::NODE_MULTIPLY:
    1407             :                 case as2js::node_t::NODE_NOT_EQUAL:
    1408             :                 case as2js::node_t::NODE_NOT_MATCH:
    1409             :                 case as2js::node_t::NODE_POST_DECREMENT:
    1410             :                 case as2js::node_t::NODE_POST_INCREMENT:
    1411             :                 case as2js::node_t::NODE_POWER:
    1412             :                 case as2js::node_t::NODE_ROTATE_LEFT:
    1413             :                 case as2js::node_t::NODE_ROTATE_RIGHT:
    1414             :                 case as2js::node_t::NODE_SHIFT_LEFT:
    1415             :                 case as2js::node_t::NODE_SHIFT_RIGHT:
    1416             :                 case as2js::node_t::NODE_SHIFT_RIGHT_UNSIGNED:
    1417             :                 case as2js::node_t::NODE_SMART_MATCH:
    1418             :                 case as2js::node_t::NODE_STRICTLY_EQUAL:
    1419             :                 case as2js::node_t::NODE_STRICTLY_NOT_EQUAL:
    1420             :                 case as2js::node_t::NODE_SUBTRACT:
    1421          62 :                     CATCH_REQUIRE(node->to_call());
    1422          62 :                     CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_CALL);
    1423          62 :                     break;
    1424             : 
    1425         156 :                 default:
    1426         156 :                     CATCH_REQUIRE(!node->to_call());
    1427         156 :                     CATCH_REQUIRE(node->get_type() == original_type);
    1428         156 :                     break;
    1429             : 
    1430             :                 }
    1431         218 :             }
    1432             : 
    1433             :             // a few types of nodes can be converted to an INTEGER
    1434             :             {
    1435         218 :                 as2js::node::pointer_t node(std::make_shared<as2js::node>(original_type));
    1436             :                 {
    1437         218 :                     snapdev::ostream_to_buf<char> out(std::cerr);
    1438         436 :                     as2js::node_lock lock(node);
    1439         218 :                     CATCH_REQUIRE_THROWS_MATCHES(
    1440             :                           node->to_integer()
    1441             :                         , as2js::locked_node
    1442             :                         , Catch::Matchers::ExceptionMessage(
    1443             :                                   "as2js_exception: trying to modify a locked node."));
    1444         218 :                     CATCH_REQUIRE(node->get_type() == original_type);
    1445         218 :                     CATCH_REQUIRE(out.str().substr(0, 65) == "error: The following node is locked and thus cannot be modified:\n");
    1446         218 :                 }
    1447         218 :                 switch(original_type)
    1448             :                 {
    1449           1 :                 case as2js::node_t::NODE_INTEGER: // no change
    1450           1 :                     CATCH_REQUIRE(node->to_integer());
    1451           1 :                     CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_INTEGER);
    1452           1 :                     break;
    1453             : 
    1454           1 :                 case as2js::node_t::NODE_FLOATING_POINT:
    1455           1 :                     CATCH_REQUIRE(node->to_integer());
    1456           1 :                     CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_INTEGER);
    1457           1 :                     break;
    1458             : 
    1459           3 :                 case as2js::node_t::NODE_FALSE:
    1460             :                 case as2js::node_t::NODE_NULL:
    1461             :                 case as2js::node_t::NODE_UNDEFINED:
    1462           3 :                     CATCH_REQUIRE(node->to_integer());
    1463           3 :                     CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_INTEGER);
    1464           3 :                     CATCH_REQUIRE(node->get_integer().get() == 0);
    1465           3 :                     break;
    1466             : 
    1467           1 :                 case as2js::node_t::NODE_STRING: // empty string to start with...
    1468           1 :                     CATCH_REQUIRE(node->to_integer());
    1469           1 :                     CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_INTEGER);
    1470           1 :                     CATCH_REQUIRE(node->get_integer().get() == 0);
    1471             : 
    1472             :                     // if not empty...
    1473             :                     {
    1474           1 :                         as2js::node::pointer_t node_str(std::make_shared<as2js::node>(original_type));
    1475           1 :                         node_str->set_string("34");
    1476           1 :                         CATCH_REQUIRE(node_str->to_integer());
    1477           1 :                         CATCH_REQUIRE(node_str->get_type() == as2js::node_t::NODE_INTEGER);
    1478           1 :                         CATCH_REQUIRE(node_str->get_integer().get() == 34);
    1479           1 :                     }
    1480             :                     {
    1481           1 :                         as2js::node::pointer_t node_str(std::make_shared<as2js::node>(original_type));
    1482           1 :                         node_str->set_string("+84");
    1483           1 :                         CATCH_REQUIRE(node_str->to_integer());
    1484           1 :                         CATCH_REQUIRE(node_str->get_type() == as2js::node_t::NODE_INTEGER);
    1485           1 :                         CATCH_REQUIRE(node_str->get_integer().get() == 84);
    1486           1 :                     }
    1487             :                     {
    1488           1 :                         as2js::node::pointer_t node_str(std::make_shared<as2js::node>(original_type));
    1489           1 :                         node_str->set_string("-37");
    1490           1 :                         CATCH_REQUIRE(node_str->to_integer());
    1491           1 :                         CATCH_REQUIRE(node_str->get_type() == as2js::node_t::NODE_INTEGER);
    1492           1 :                         CATCH_REQUIRE(node_str->get_integer().get() == -37);
    1493           1 :                     }
    1494             :                     {
    1495           1 :                         as2js::node::pointer_t node_str(std::make_shared<as2js::node>(original_type));
    1496           1 :                         node_str->set_string("3.4");
    1497           1 :                         CATCH_REQUIRE(node_str->to_integer());
    1498           1 :                         CATCH_REQUIRE(node_str->get_type() == as2js::node_t::NODE_INTEGER);
    1499           1 :                         CATCH_REQUIRE(node_str->get_integer().get() == 3);
    1500           1 :                     }
    1501             :                     {
    1502           1 :                         as2js::node::pointer_t node_str(std::make_shared<as2js::node>(original_type));
    1503           1 :                         node_str->set_string("34e+5");
    1504           1 :                         CATCH_REQUIRE(node_str->to_integer());
    1505           1 :                         CATCH_REQUIRE(node_str->get_type() == as2js::node_t::NODE_INTEGER);
    1506           1 :                         CATCH_REQUIRE(node_str->get_integer().get() == 3400000);
    1507           1 :                     }
    1508             :                     {
    1509           1 :                         as2js::node::pointer_t node_str(std::make_shared<as2js::node>(original_type));
    1510           1 :                         node_str->set_string("some NaN");
    1511           1 :                         CATCH_REQUIRE(node_str->to_integer());
    1512           1 :                         CATCH_REQUIRE(node_str->get_type() == as2js::node_t::NODE_INTEGER);
    1513           1 :                         CATCH_REQUIRE(node_str->get_integer().get() == 0);
    1514           1 :                     }
    1515             :                     break;
    1516             : 
    1517           1 :                 case as2js::node_t::NODE_TRUE:
    1518           1 :                     CATCH_REQUIRE(node->to_integer());
    1519           1 :                     CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_INTEGER);
    1520           1 :                     CATCH_REQUIRE(node->get_integer().get() == 1);
    1521           1 :                     break;
    1522             : 
    1523         211 :                 default:
    1524         211 :                     CATCH_REQUIRE(!node->to_integer());
    1525         211 :                     CATCH_REQUIRE(node->get_type() == original_type);
    1526         211 :                     break;
    1527             : 
    1528             :                 }
    1529         218 :             }
    1530             : 
    1531             :             // a few types of nodes can be converted to a FLOATING_POINT
    1532             :             {
    1533         218 :                 as2js::node::pointer_t node(std::make_shared<as2js::node>(original_type));
    1534             :                 {
    1535         218 :                     snapdev::ostream_to_buf<char> out(std::cerr);
    1536         436 :                     as2js::node_lock lock(node);
    1537         218 :                     CATCH_REQUIRE_THROWS_MATCHES(
    1538             :                           node->to_floating_point()
    1539             :                         , as2js::locked_node
    1540             :                         , Catch::Matchers::ExceptionMessage(
    1541             :                                   "as2js_exception: trying to modify a locked node."));
    1542         218 :                     CATCH_REQUIRE(node->get_type() == original_type);
    1543         218 :                     CATCH_REQUIRE(out.str().substr(0, 65) == "error: The following node is locked and thus cannot be modified:\n");
    1544         218 :                 }
    1545         218 :                 switch(original_type)
    1546             :                 {
    1547           1 :                 case as2js::node_t::NODE_INTEGER: // no change
    1548           1 :                     CATCH_REQUIRE(node->to_floating_point());
    1549           1 :                     CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_FLOATING_POINT);
    1550           1 :                     break;
    1551             : 
    1552           1 :                 case as2js::node_t::NODE_FLOATING_POINT:
    1553           1 :                     CATCH_REQUIRE(node->to_floating_point());
    1554           1 :                     CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_FLOATING_POINT);
    1555           1 :                     break;
    1556             : 
    1557           3 :                 case as2js::node_t::NODE_FALSE:
    1558             :                 case as2js::node_t::NODE_NULL:
    1559             :                 case as2js::node_t::NODE_STRING:
    1560           3 :                     CATCH_REQUIRE(node->to_floating_point());
    1561           3 :                     CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_FLOATING_POINT);
    1562             :                     {
    1563             : #pragma GCC diagnostic push
    1564             : #pragma GCC diagnostic ignored "-Wfloat-equal"
    1565           3 :                         bool const is_zero(node->get_floating_point().get() == 0.0);
    1566             : #pragma GCC diagnostic pop
    1567           3 :                         CATCH_REQUIRE(is_zero);
    1568             :                     }
    1569           3 :                     break;
    1570             : 
    1571           1 :                 case as2js::node_t::NODE_TRUE:
    1572           1 :                     CATCH_REQUIRE(node->to_floating_point());
    1573           1 :                     CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_FLOATING_POINT);
    1574             :                     {
    1575             : #pragma GCC diagnostic push
    1576             : #pragma GCC diagnostic ignored "-Wfloat-equal"
    1577           1 :                         bool const is_one(node->get_floating_point().get() == 1.0);
    1578             : #pragma GCC diagnostic pop
    1579           1 :                         CATCH_REQUIRE(is_one);
    1580             :                     }
    1581           1 :                     break;
    1582             : 
    1583           1 :                 case as2js::node_t::NODE_UNDEFINED:
    1584           1 :                     CATCH_REQUIRE(node->to_floating_point());
    1585           1 :                     CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_FLOATING_POINT);
    1586           1 :                     CATCH_REQUIRE(node->get_floating_point().is_nan());
    1587           1 :                     break;
    1588             : 
    1589         211 :                 default:
    1590         211 :                     CATCH_REQUIRE(!node->to_floating_point());
    1591         211 :                     CATCH_REQUIRE(node->get_type() == original_type);
    1592         211 :                     break;
    1593             : 
    1594             :                 }
    1595         218 :             }
    1596             : 
    1597             :             // IDENTIFIER can be converted to LABEL
    1598             :             {
    1599         218 :                 as2js::node::pointer_t node(std::make_shared<as2js::node>(original_type));
    1600             :                 {
    1601         218 :                     snapdev::ostream_to_buf<char> out(std::cerr);
    1602         436 :                     as2js::node_lock lock(node);
    1603         218 :                     CATCH_REQUIRE_THROWS_MATCHES(
    1604             :                           node->to_label()
    1605             :                         , as2js::locked_node
    1606             :                         , Catch::Matchers::ExceptionMessage(
    1607             :                                   "as2js_exception: trying to modify a locked node."));
    1608         218 :                     CATCH_REQUIRE(node->get_type() == original_type);
    1609         218 :                     CATCH_REQUIRE(out.str().substr(0, 65) == "error: The following node is locked and thus cannot be modified:\n");
    1610         218 :                 }
    1611         218 :                 if(original_type == as2js::node_t::NODE_IDENTIFIER)
    1612             :                 {
    1613             :                     // in this case it works
    1614           1 :                     node->to_label();
    1615           1 :                     CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_LABEL);
    1616             :                 }
    1617             :                 else
    1618             :                 {
    1619             :                     // this one fails with a soft error (returns false)
    1620         217 :                     CATCH_REQUIRE(!node->to_label());
    1621         217 :                     CATCH_REQUIRE(node->get_type() == original_type);
    1622             :                 }
    1623         218 :             }
    1624             : 
    1625             :             // a few types of nodes can be converted to a Number
    1626             :             {
    1627         218 :                 as2js::node::pointer_t node(std::make_shared<as2js::node>(original_type));
    1628             :                 {
    1629         218 :                     snapdev::ostream_to_buf<char> out(std::cerr);
    1630         436 :                     as2js::node_lock lock(node);
    1631         218 :                     CATCH_REQUIRE_THROWS_MATCHES(
    1632             :                           node->to_number()
    1633             :                         , as2js::locked_node
    1634             :                         , Catch::Matchers::ExceptionMessage(
    1635             :                                   "as2js_exception: trying to modify a locked node."));
    1636         218 :                     CATCH_REQUIRE(node->get_type() == original_type);
    1637         218 :                     CATCH_REQUIRE(out.str().substr(0, 65) == "error: The following node is locked and thus cannot be modified:\n");
    1638         218 :                 }
    1639         218 :                 switch(original_type)
    1640             :                 {
    1641           2 :                 case as2js::node_t::NODE_INTEGER: // no change!
    1642             :                 case as2js::node_t::NODE_FLOATING_POINT: // no change!
    1643           2 :                     CATCH_REQUIRE(node->to_number());
    1644           2 :                     CATCH_REQUIRE(node->get_type() == original_type);
    1645           2 :                     break;
    1646             : 
    1647           2 :                 case as2js::node_t::NODE_FALSE:
    1648             :                 case as2js::node_t::NODE_NULL:
    1649           2 :                     CATCH_REQUIRE(node->to_number());
    1650           2 :                     CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_INTEGER);
    1651           2 :                     CATCH_REQUIRE(node->get_integer().get() == 0);
    1652           2 :                     break;
    1653             : 
    1654           1 :                 case as2js::node_t::NODE_TRUE:
    1655           1 :                     CATCH_REQUIRE(node->to_number());
    1656           1 :                     CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_INTEGER);
    1657           1 :                     CATCH_REQUIRE(node->get_integer().get() == 1);
    1658           1 :                     break;
    1659             : 
    1660           1 :                 case as2js::node_t::NODE_STRING: // empty strings represent 0 here
    1661           1 :                     CATCH_REQUIRE(node->to_number());
    1662           1 :                     CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_FLOATING_POINT);
    1663             :                     {
    1664             : #pragma GCC diagnostic push
    1665             : #pragma GCC diagnostic ignored "-Wfloat-equal"
    1666           1 :                         bool const is_zero(node->get_floating_point().get() == 0.0);
    1667             : #pragma GCC diagnostic pop
    1668           1 :                         CATCH_REQUIRE(is_zero);
    1669             :                     }
    1670           1 :                     break;
    1671             : 
    1672           1 :                 case as2js::node_t::NODE_UNDEFINED:
    1673             : //std::cerr << " . type = " << static_cast<int>(original_type) << " / " << node->get_type_name() << "\n";
    1674           1 :                     CATCH_REQUIRE(node->to_number());
    1675           1 :                     CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_FLOATING_POINT);
    1676           1 :                     CATCH_REQUIRE(node->get_floating_point().is_nan());
    1677           1 :                     break;
    1678             : 
    1679         211 :                 default:
    1680         211 :                     CATCH_REQUIRE(!node->to_number());
    1681         211 :                     CATCH_REQUIRE(node->get_type() == original_type);
    1682         211 :                     break;
    1683             : 
    1684             :                 }
    1685         218 :             }
    1686             : 
    1687             :             // a few types of nodes can be converted to a STRING
    1688             :             {
    1689         218 :                 as2js::node::pointer_t node(std::make_shared<as2js::node>(original_type));
    1690             :                 {
    1691         218 :                     snapdev::ostream_to_buf<char> out(std::cerr);
    1692         436 :                     as2js::node_lock lock(node);
    1693         218 :                     CATCH_REQUIRE_THROWS_MATCHES(
    1694             :                           node->to_string()
    1695             :                         , as2js::locked_node
    1696             :                         , Catch::Matchers::ExceptionMessage(
    1697             :                                   "as2js_exception: trying to modify a locked node."));
    1698         218 :                     CATCH_REQUIRE(node->get_type() == original_type);
    1699         218 :                     CATCH_REQUIRE(out.str().substr(0, 65) == "error: The following node is locked and thus cannot be modified:\n");
    1700         218 :                 }
    1701         218 :                 switch(original_type)
    1702             :                 {
    1703           5 :                 case as2js::node_t::NODE_STRING:
    1704             :                 case as2js::node_t::NODE_TEMPLATE:
    1705             :                 case as2js::node_t::NODE_TEMPLATE_HEAD:
    1706             :                 case as2js::node_t::NODE_TEMPLATE_MIDDLE:
    1707             :                 case as2js::node_t::NODE_TEMPLATE_TAIL:
    1708           5 :                     CATCH_REQUIRE(node->to_string());
    1709           5 :                     CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_STRING);
    1710           5 :                     CATCH_REQUIRE(node->get_string() == "");
    1711           5 :                     break;
    1712             : 
    1713           2 :                 case as2js::node_t::NODE_FLOATING_POINT:
    1714             :                 case as2js::node_t::NODE_INTEGER:
    1715             :                     // by default numbers are zero; we have other tests
    1716             :                     // to verify the conversion
    1717           2 :                     CATCH_REQUIRE(node->to_string());
    1718           2 :                     CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_STRING);
    1719           2 :                     CATCH_REQUIRE(node->get_string() == "0");
    1720           2 :                     break;
    1721             : 
    1722           1 :                 case as2js::node_t::NODE_FALSE:
    1723           1 :                     CATCH_REQUIRE(node->to_string());
    1724           1 :                     CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_STRING);
    1725           1 :                     CATCH_REQUIRE(node->get_string() == "false");
    1726           1 :                     break;
    1727             : 
    1728           1 :                 case as2js::node_t::NODE_TRUE:
    1729           1 :                     CATCH_REQUIRE(node->to_string());
    1730           1 :                     CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_STRING);
    1731           1 :                     CATCH_REQUIRE(node->get_string() == "true");
    1732           1 :                     break;
    1733             : 
    1734           1 :                 case as2js::node_t::NODE_NULL:
    1735           1 :                     CATCH_REQUIRE(node->to_string());
    1736           1 :                     CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_STRING);
    1737           1 :                     CATCH_REQUIRE(node->get_string() == "null");
    1738           1 :                     break;
    1739             : 
    1740           1 :                 case as2js::node_t::NODE_UNDEFINED:
    1741           1 :                     CATCH_REQUIRE(node->to_string());
    1742           1 :                     CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_STRING);
    1743           1 :                     CATCH_REQUIRE(node->get_string() == "undefined");
    1744           1 :                     break;
    1745             : 
    1746           1 :                 case as2js::node_t::NODE_IDENTIFIER: // the string remains the same
    1747             :                 //case as2js::node_t::NODE_VIDENTIFIER: // should the VIDENTIFIER be supported too?
    1748           1 :                     CATCH_REQUIRE(node->to_string());
    1749           1 :                     CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_STRING);
    1750           1 :                     break;
    1751             : 
    1752         206 :                 default:
    1753         206 :                     CATCH_REQUIRE(!node->to_string());
    1754         206 :                     CATCH_REQUIRE(node->get_type() == original_type);
    1755         206 :                     break;
    1756             : 
    1757             :                 }
    1758         218 :             }
    1759             : 
    1760             :             // a few types of nodes can be converted to an IDENTIFIER
    1761             :             {
    1762         218 :                 as2js::node::pointer_t node(std::make_shared<as2js::node>(original_type));
    1763             :                 {
    1764         218 :                     snapdev::ostream_to_buf<char> out(std::cerr);
    1765         436 :                     as2js::node_lock lock(node);
    1766         218 :                     CATCH_REQUIRE_THROWS_MATCHES(
    1767             :                           node->to_identifier()
    1768             :                         , as2js::locked_node
    1769             :                         , Catch::Matchers::ExceptionMessage(
    1770             :                                   "as2js_exception: trying to modify a locked node."));
    1771         218 :                     CATCH_REQUIRE(node->get_type() == original_type);
    1772         218 :                     CATCH_REQUIRE(out.str().substr(0, 65) == "error: The following node is locked and thus cannot be modified:\n");
    1773         218 :                 }
    1774         218 :                 switch(original_type)
    1775             :                 {
    1776          59 :                 case as2js::node_t::NODE_ADD:
    1777             :                 case as2js::node_t::NODE_ALMOST_EQUAL:
    1778             :                 case as2js::node_t::NODE_ASSIGNMENT:
    1779             :                 case as2js::node_t::NODE_ASSIGNMENT_ADD:
    1780             :                 case as2js::node_t::NODE_ASSIGNMENT_BITWISE_AND:
    1781             :                 case as2js::node_t::NODE_ASSIGNMENT_BITWISE_OR:
    1782             :                 case as2js::node_t::NODE_ASSIGNMENT_BITWISE_XOR:
    1783             :                 case as2js::node_t::NODE_ASSIGNMENT_DIVIDE:
    1784             :                 case as2js::node_t::NODE_ASSIGNMENT_LOGICAL_AND:
    1785             :                 case as2js::node_t::NODE_ASSIGNMENT_LOGICAL_OR:
    1786             :                 case as2js::node_t::NODE_ASSIGNMENT_LOGICAL_XOR:
    1787             :                 case as2js::node_t::NODE_ASSIGNMENT_MAXIMUM:
    1788             :                 case as2js::node_t::NODE_ASSIGNMENT_MINIMUM:
    1789             :                 case as2js::node_t::NODE_ASSIGNMENT_MODULO:
    1790             :                 case as2js::node_t::NODE_ASSIGNMENT_MULTIPLY:
    1791             :                 case as2js::node_t::NODE_ASSIGNMENT_POWER:
    1792             :                 case as2js::node_t::NODE_ASSIGNMENT_ROTATE_LEFT:
    1793             :                 case as2js::node_t::NODE_ASSIGNMENT_ROTATE_RIGHT:
    1794             :                 case as2js::node_t::NODE_ASSIGNMENT_SHIFT_LEFT:
    1795             :                 case as2js::node_t::NODE_ASSIGNMENT_SHIFT_RIGHT:
    1796             :                 case as2js::node_t::NODE_ASSIGNMENT_SHIFT_RIGHT_UNSIGNED:
    1797             :                 case as2js::node_t::NODE_ASSIGNMENT_SUBTRACT:
    1798             :                 case as2js::node_t::NODE_BITWISE_AND:
    1799             :                 case as2js::node_t::NODE_BITWISE_NOT:
    1800             :                 case as2js::node_t::NODE_BITWISE_OR:
    1801             :                 case as2js::node_t::NODE_BITWISE_XOR:
    1802             :                 case as2js::node_t::NODE_COMMA:
    1803             :                 case as2js::node_t::NODE_COMPARE:
    1804             :                 case as2js::node_t::NODE_DECREMENT:
    1805             :                 case as2js::node_t::NODE_DIVIDE:
    1806             :                 case as2js::node_t::NODE_EQUAL:
    1807             :                 case as2js::node_t::NODE_GREATER:
    1808             :                 case as2js::node_t::NODE_GREATER_EQUAL:
    1809             :                 case as2js::node_t::NODE_INCREMENT:
    1810             :                 case as2js::node_t::NODE_LESS:
    1811             :                 case as2js::node_t::NODE_LESS_EQUAL:
    1812             :                 case as2js::node_t::NODE_LOGICAL_AND:
    1813             :                 case as2js::node_t::NODE_LOGICAL_NOT:
    1814             :                 case as2js::node_t::NODE_LOGICAL_OR:
    1815             :                 case as2js::node_t::NODE_LOGICAL_XOR:
    1816             :                 case as2js::node_t::NODE_MATCH:
    1817             :                 case as2js::node_t::NODE_MAXIMUM:
    1818             :                 case as2js::node_t::NODE_MINIMUM:
    1819             :                 case as2js::node_t::NODE_MODULO:
    1820             :                 case as2js::node_t::NODE_MULTIPLY:
    1821             :                 case as2js::node_t::NODE_NOT_EQUAL:
    1822             :                 case as2js::node_t::NODE_NOT_MATCH:
    1823             :                 case as2js::node_t::NODE_POST_DECREMENT:
    1824             :                 case as2js::node_t::NODE_POST_INCREMENT:
    1825             :                 case as2js::node_t::NODE_POWER:
    1826             :                 case as2js::node_t::NODE_ROTATE_LEFT:
    1827             :                 case as2js::node_t::NODE_ROTATE_RIGHT:
    1828             :                 case as2js::node_t::NODE_SHIFT_LEFT:
    1829             :                 case as2js::node_t::NODE_SHIFT_RIGHT:
    1830             :                 case as2js::node_t::NODE_SHIFT_RIGHT_UNSIGNED:
    1831             :                 case as2js::node_t::NODE_SMART_MATCH:
    1832             :                 case as2js::node_t::NODE_STRICTLY_EQUAL:
    1833             :                 case as2js::node_t::NODE_STRICTLY_NOT_EQUAL:
    1834             :                 case as2js::node_t::NODE_SUBTRACT:
    1835          59 :                     CATCH_REQUIRE(node->to_identifier());
    1836          59 :                     CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_IDENTIFIER);
    1837          59 :                     CATCH_REQUIRE(node->get_string() == as2js::node::operator_to_string(original_type));
    1838          59 :                     break;
    1839             : 
    1840           1 :                 case as2js::node_t::NODE_DELETE:
    1841           1 :                     CATCH_REQUIRE(node->to_identifier());
    1842           1 :                     CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_IDENTIFIER);
    1843           1 :                     CATCH_REQUIRE(node->get_string() == "delete");
    1844           1 :                     break;
    1845             : 
    1846           2 :                 case as2js::node_t::NODE_IDENTIFIER:
    1847             :                 case as2js::node_t::NODE_STRING:
    1848           2 :                     CATCH_REQUIRE(node->to_identifier());
    1849           2 :                     CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_IDENTIFIER);
    1850           2 :                     CATCH_REQUIRE(node->get_string() == "");
    1851           2 :                     break;
    1852             : 
    1853           1 :                 case as2js::node_t::NODE_PRIVATE:
    1854           1 :                     CATCH_REQUIRE(node->to_identifier());
    1855           1 :                     CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_IDENTIFIER);
    1856           1 :                     CATCH_REQUIRE(node->get_string() == "private");
    1857           1 :                     break;
    1858             : 
    1859           1 :                 case as2js::node_t::NODE_PROTECTED:
    1860           1 :                     CATCH_REQUIRE(node->to_identifier());
    1861           1 :                     CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_IDENTIFIER);
    1862           1 :                     CATCH_REQUIRE(node->get_string() == "protected");
    1863           1 :                     break;
    1864             : 
    1865           1 :                 case as2js::node_t::NODE_PUBLIC:
    1866           1 :                     CATCH_REQUIRE(node->to_identifier());
    1867           1 :                     CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_IDENTIFIER);
    1868           1 :                     CATCH_REQUIRE(node->get_string() == "public");
    1869           1 :                     break;
    1870             : 
    1871         153 :                 default:
    1872         153 : if(node->to_identifier())
    1873             : {
    1874           0 : std::cerr << "--- it worked... for " << as2js::node::type_to_string(original_type) << "\n";
    1875             : }
    1876         153 :                     CATCH_REQUIRE(!node->to_identifier());
    1877         153 :                     CATCH_REQUIRE(node->get_type() == original_type);
    1878         153 :                     break;
    1879             : 
    1880             :                 }
    1881         218 :             }
    1882             : 
    1883             :             // IDENTIFIER can be converted to VIDENTIFIER
    1884             :             {
    1885         218 :                 as2js::node::pointer_t node(std::make_shared<as2js::node>(original_type));
    1886             :                 {
    1887         218 :                     snapdev::ostream_to_buf<char> out(std::cerr);
    1888         436 :                     as2js::node_lock lock(node);
    1889         218 :                     CATCH_REQUIRE_THROWS_MATCHES(
    1890             :                           node->to_videntifier()
    1891             :                         , as2js::locked_node
    1892             :                         , Catch::Matchers::ExceptionMessage(
    1893             :                                   "as2js_exception: trying to modify a locked node."));
    1894         218 :                     CATCH_REQUIRE(node->get_type() == original_type);
    1895         218 :                     CATCH_REQUIRE(out.str().substr(0, 65) == "error: The following node is locked and thus cannot be modified:\n");
    1896         218 :                 }
    1897         218 :                 if(original_type == as2js::node_t::NODE_IDENTIFIER)
    1898             :                 {
    1899             :                     // in this case it works
    1900           1 :                     node->to_videntifier();
    1901           1 :                     CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_VIDENTIFIER);
    1902             :                 }
    1903             :                 else
    1904             :                 {
    1905             :                     // this one fails dramatically
    1906         217 :                     CATCH_REQUIRE_THROWS_MATCHES(
    1907             :                           node->to_videntifier()
    1908             :                         , as2js::internal_error
    1909             :                         , Catch::Matchers::ExceptionMessage(
    1910             :                                   "internal_error: to_videntifier() called with a node other than a \"NODE_IDENTIFIER\" node."));
    1911         217 :                     CATCH_REQUIRE(node->get_type() == original_type);
    1912             :                 }
    1913         218 :             }
    1914             : 
    1915             :             // VARIABLE can be converted to VAR_ATTRIBUTES
    1916             :             {
    1917         218 :                 as2js::node::pointer_t node(std::make_shared<as2js::node>(original_type));
    1918             :                 {
    1919         218 :                     snapdev::ostream_to_buf<char> out(std::cerr);
    1920         436 :                     as2js::node_lock lock(node);
    1921         218 :                     CATCH_REQUIRE_THROWS_MATCHES(
    1922             :                           node->to_var_attributes()
    1923             :                         , as2js::locked_node
    1924             :                         , Catch::Matchers::ExceptionMessage(
    1925             :                                   "as2js_exception: trying to modify a locked node."));
    1926         218 :                     CATCH_REQUIRE(node->get_type() == original_type);
    1927         218 :                     CATCH_REQUIRE(out.str().substr(0, 65) == "error: The following node is locked and thus cannot be modified:\n");
    1928         218 :                 }
    1929         218 :                 if(original_type == as2js::node_t::NODE_VARIABLE)
    1930             :                 {
    1931             :                     // in this case it works
    1932           1 :                     node->to_var_attributes();
    1933           1 :                     CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_VAR_ATTRIBUTES);
    1934             :                 }
    1935             :                 else
    1936             :                 {
    1937             :                     // in this case it fails
    1938         217 :                     CATCH_REQUIRE_THROWS_MATCHES(
    1939             :                           node->to_var_attributes()
    1940             :                         , as2js::internal_error
    1941             :                         , Catch::Matchers::ExceptionMessage(
    1942             :                                   "internal_error: to_var_attribute() called with a node other than a \"NODE_VARIABLE\" node."));
    1943         217 :                     CATCH_REQUIRE(node->get_type() == original_type);
    1944             :                 }
    1945         218 :             }
    1946             :         }
    1947             :     }
    1948           3 :     CATCH_END_SECTION()
    1949             : 
    1950           3 :     CATCH_START_SECTION("node_conversions: NULL value")
    1951             :     {
    1952           1 :         bool got_dot(false);
    1953         101 :         for(int i(0); i < 100; ++i)
    1954             :         {
    1955             :             // Integer to other types
    1956             :             {
    1957         100 :                 as2js::integer j((static_cast<int64_t>(rand()) << 48)
    1958         100 :                                ^ (static_cast<int64_t>(rand()) << 32)
    1959         100 :                                ^ (static_cast<int64_t>(rand()) << 16)
    1960         100 :                                ^ (static_cast<int64_t>(rand()) <<  0));
    1961             : 
    1962             :                 {
    1963         100 :                     as2js::node::pointer_t node(std::make_shared<as2js::node>(as2js::node_t::NODE_INTEGER));
    1964         100 :                     node->set_integer(j);
    1965         100 :                     as2js::floating_point invalid;
    1966         100 :                     CATCH_REQUIRE_THROWS_MATCHES(
    1967             :                           node->set_floating_point(invalid)
    1968             :                         , as2js::internal_error
    1969             :                         , Catch::Matchers::ExceptionMessage(
    1970             :                                   "internal_error: set_floating_point() called with a non-floating point node type."));
    1971         100 :                     CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_INTEGER);
    1972         100 :                     CATCH_REQUIRE(node->to_integer());
    1973             :                     // probably always true here; we had false in the loop prior
    1974         100 :                     CATCH_REQUIRE(node->get_integer().get() == j.get());
    1975         100 :                 }
    1976             : 
    1977             :                 {
    1978         100 :                     as2js::node::pointer_t node(std::make_shared<as2js::node>(as2js::node_t::NODE_INTEGER));
    1979         100 :                     node->set_integer(j);
    1980         100 :                     CATCH_REQUIRE(node->to_number());
    1981             :                     // probably always true here; we had false in the loop prior
    1982         100 :                     CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_INTEGER);
    1983         100 :                     CATCH_REQUIRE(node->get_integer().get() == j.get());
    1984         100 :                 }
    1985             : 
    1986             :                 {
    1987         100 :                     as2js::node::pointer_t node(std::make_shared<as2js::node>(as2js::node_t::NODE_INTEGER));
    1988         100 :                     node->set_integer(j);
    1989         100 :                     as2js::node_t bool_type(node->to_boolean_type_only());
    1990             :                     // probably always true here; we had false in the loop prior
    1991         100 :                     CATCH_REQUIRE(bool_type == (j.get() ? as2js::node_t::NODE_TRUE : as2js::node_t::NODE_FALSE));
    1992         100 :                 }
    1993             : 
    1994             :                 {
    1995         100 :                     as2js::node::pointer_t node(std::make_shared<as2js::node>(as2js::node_t::NODE_INTEGER));
    1996         100 :                     node->set_integer(j);
    1997         100 :                     CATCH_REQUIRE(node->to_boolean());
    1998             :                     // probably always true here; we had false in the loop prior
    1999         100 :                     CATCH_REQUIRE(node->get_type() == (j.get() ? as2js::node_t::NODE_TRUE : as2js::node_t::NODE_FALSE));
    2000         100 :                 }
    2001             : 
    2002             :                 {
    2003         100 :                     as2js::node::pointer_t node(std::make_shared<as2js::node>(as2js::node_t::NODE_INTEGER));
    2004         100 :                     node->set_integer(j);
    2005         100 :                     CATCH_REQUIRE(node->to_floating_point());
    2006             :                     // probably always true here; we had false in the loop prior
    2007         100 :                     CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_FLOATING_POINT);
    2008         100 :                     as2js::floating_point flt(j.get());
    2009         100 :                     CATCH_REQUIRE(node->get_floating_point().nearly_equal(flt, 0.0001));
    2010         100 :                 }
    2011             : 
    2012             :                 {
    2013         100 :                     as2js::node::pointer_t node(std::make_shared<as2js::node>(as2js::node_t::NODE_INTEGER));
    2014         100 :                     node->set_integer(j);
    2015         100 :                     CATCH_REQUIRE(node->to_string());
    2016             :                     // probably always true here; we had false in the loop prior
    2017         100 :                     CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_STRING);
    2018         100 :                     CATCH_REQUIRE(node->get_string() == std::string(std::to_string(j.get())));
    2019         100 :                 }
    2020             :             }
    2021             : 
    2022             :             // Floating point to other values
    2023         100 :             bool first(true);
    2024             :             do
    2025             :             {
    2026             :                 // generate a random 64 bit number
    2027             :                 //
    2028         746 :                 double s1(rand() & 1 ? -1 : 1);
    2029         746 :                 double n1(static_cast<double>((static_cast<int64_t>(rand()) << 48)
    2030         746 :                                             ^ (static_cast<int64_t>(rand()) << 32)
    2031         746 :                                             ^ (static_cast<int64_t>(rand()) << 16)
    2032         746 :                                             ^ (static_cast<int64_t>(rand()) <<  0)));
    2033         746 :                 double d1(static_cast<double>((static_cast<int64_t>(rand()) << 48)
    2034         746 :                                             ^ (static_cast<int64_t>(rand()) << 32)
    2035         746 :                                             ^ (static_cast<int64_t>(rand()) << 16)
    2036         746 :                                             ^ (static_cast<int64_t>(rand()) <<  0)));
    2037         746 :                 if(!first && n1 >= d1)
    2038             :                 {
    2039             :                     // the dot is easier to reach with very small numbers
    2040             :                     // so create a small number immediately
    2041         314 :                     std::swap(n1, d1);
    2042         314 :                     d1 *= 1e+4;
    2043             :                 }
    2044         746 :                 double r(n1 / d1 * s1);
    2045         746 :                 as2js::floating_point j(r);
    2046             : 
    2047             :                 {
    2048         746 :                     as2js::node::pointer_t node(std::make_shared<as2js::node>(as2js::node_t::NODE_FLOATING_POINT));
    2049         746 :                     node->set_floating_point(j);
    2050         746 :                     CATCH_REQUIRE(node->to_integer());
    2051         746 :                     CATCH_REQUIRE(node->get_integer().get() == static_cast<as2js::integer::value_type>(j.get()));
    2052         746 :                 }
    2053             : 
    2054             :                 {
    2055         746 :                     as2js::node::pointer_t node(std::make_shared<as2js::node>(as2js::node_t::NODE_FLOATING_POINT));
    2056         746 :                     node->set_floating_point(j);
    2057         746 :                     CATCH_REQUIRE(node->to_number());
    2058         746 :                     CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_FLOATING_POINT);
    2059             :                     {
    2060             : #pragma GCC diagnostic push
    2061             : #pragma GCC diagnostic ignored "-Wfloat-equal"
    2062         746 :                         bool const is_equal(node->get_floating_point().get() == j.get());
    2063             : #pragma GCC diagnostic pop
    2064         746 :                         CATCH_REQUIRE(is_equal);
    2065             :                     }
    2066         746 :                 }
    2067             : 
    2068             :                 {
    2069         746 :                     as2js::node::pointer_t node(std::make_shared<as2js::node>(as2js::node_t::NODE_FLOATING_POINT));
    2070         746 :                     node->set_floating_point(j);
    2071         746 :                     as2js::node_t bool_type(node->to_boolean_type_only());
    2072             :                     // probably always true here; we had false in the loop prior
    2073             : #pragma GCC diagnostic push
    2074             : #pragma GCC diagnostic ignored "-Wfloat-equal"
    2075         746 :                     bool const is_zero(j.get() == 0.0);
    2076             : #pragma GCC diagnostic pop
    2077         746 :                     CATCH_REQUIRE(bool_type == (is_zero ? as2js::node_t::NODE_FALSE : as2js::node_t::NODE_TRUE));
    2078         746 :                 }
    2079             : 
    2080             :                 {
    2081         746 :                     as2js::node::pointer_t node(std::make_shared<as2js::node>(as2js::node_t::NODE_FLOATING_POINT));
    2082         746 :                     node->set_floating_point(j);
    2083         746 :                     CATCH_REQUIRE(node->to_boolean());
    2084             :                     // probably always true here; we had false in the loop prior
    2085             : #pragma GCC diagnostic push
    2086             : #pragma GCC diagnostic ignored "-Wfloat-equal"
    2087         746 :                     bool const is_zero(j.get() == 0.0);
    2088             : #pragma GCC diagnostic pop
    2089         746 :                     CATCH_REQUIRE(node->get_type() == (is_zero ? as2js::node_t::NODE_FALSE : as2js::node_t::NODE_TRUE));
    2090             : 
    2091             :                     // also test the set_boolean() with valid values
    2092         746 :                     node->set_boolean(true);
    2093         746 :                     CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_TRUE);
    2094         746 :                     node->set_boolean(false);
    2095         746 :                     CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_FALSE);
    2096         746 :                 }
    2097             : 
    2098             :                 {
    2099         746 :                     as2js::node::pointer_t node(std::make_shared<as2js::node>(as2js::node_t::NODE_FLOATING_POINT));
    2100         746 :                     node->set_floating_point(j);
    2101         746 :                     CATCH_REQUIRE(node->to_floating_point());
    2102         746 :                     CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_FLOATING_POINT);
    2103             : #pragma GCC diagnostic push
    2104             : #pragma GCC diagnostic ignored "-Wfloat-equal"
    2105         746 :                     bool const is_equal(node->get_floating_point().get() == j.get());
    2106             : #pragma GCC diagnostic pop
    2107         746 :                     CATCH_REQUIRE(is_equal);
    2108         746 :                 }
    2109             : 
    2110             :                 {
    2111         746 :                     as2js::node::pointer_t node(std::make_shared<as2js::node>(as2js::node_t::NODE_FLOATING_POINT));
    2112         746 :                     node->set_floating_point(j);
    2113         746 :                     CATCH_REQUIRE(node->to_string());
    2114         746 :                     CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_STRING);
    2115         746 :                     std::string str(std::string(std::to_string(j.get())));
    2116         746 :                     if(str.find('.') != std::string::npos)
    2117             :                     {
    2118             :                         // remove all least significant zeroes if any
    2119         823 :                         while(str.back() == '0')
    2120             :                         {
    2121          77 :                             str.pop_back();
    2122             :                         }
    2123             :                         // make sure the number does not end with a period
    2124         746 :                         if(str.back() == '.')
    2125             :                         {
    2126           1 :                             str.pop_back();
    2127           1 :                             got_dot = true;
    2128             :                         }
    2129             :                     }
    2130         746 :                     CATCH_REQUIRE(node->get_string() == str);
    2131         746 :                 }
    2132         746 :                 first = false;
    2133             :             }
    2134         746 :             while(!got_dot);
    2135             :         }
    2136             :     }
    2137           3 :     CATCH_END_SECTION()
    2138             : 
    2139           3 :     CATCH_START_SECTION("node_conversions: special floating point values")
    2140             :     {
    2141             :         // verify special floating point values
    2142             :         //
    2143             :         { // NaN -> string
    2144           1 :             as2js::floating_point j;
    2145           1 :             as2js::node::pointer_t node(std::make_shared<as2js::node>(as2js::node_t::NODE_FLOATING_POINT));
    2146           1 :             j.set_nan();
    2147           1 :             node->set_floating_point(j);
    2148           1 :             CATCH_REQUIRE(node->to_string());
    2149           1 :             CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_STRING);
    2150           1 :             CATCH_REQUIRE(node->get_string() == "NaN");
    2151           1 :         }
    2152             :         { // NaN -> integer
    2153           1 :             as2js::floating_point j;
    2154           1 :             as2js::node::pointer_t node(std::make_shared<as2js::node>(as2js::node_t::NODE_FLOATING_POINT));
    2155           1 :             j.set_nan();
    2156           1 :             node->set_floating_point(j);
    2157           1 :             CATCH_REQUIRE(node->to_integer());
    2158           1 :             CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_INTEGER);
    2159           1 :             CATCH_REQUIRE(node->get_integer().get() == 0);
    2160           1 :         }
    2161             :         { // +Infinity
    2162           1 :             as2js::floating_point j;
    2163           1 :             as2js::node::pointer_t node(std::make_shared<as2js::node>(as2js::node_t::NODE_FLOATING_POINT));
    2164           1 :             j.set_infinity();
    2165           1 :             node->set_floating_point(j);
    2166           1 :             CATCH_REQUIRE(node->to_string());
    2167           1 :             CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_STRING);
    2168           1 :             CATCH_REQUIRE(node->get_string() == "Infinity");
    2169           1 :         }
    2170             :         { // +Infinity
    2171           1 :             as2js::floating_point j;
    2172           1 :             as2js::node::pointer_t node(std::make_shared<as2js::node>(as2js::node_t::NODE_FLOATING_POINT));
    2173           1 :             j.set_infinity();
    2174           1 :             node->set_floating_point(j);
    2175           1 :             CATCH_REQUIRE(node->to_integer());
    2176           1 :             CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_INTEGER);
    2177           1 :             CATCH_REQUIRE(node->get_integer().get() == 0);
    2178           1 :         }
    2179             :         { // -Infinity
    2180           1 :             as2js::floating_point j;
    2181           1 :             as2js::node::pointer_t node(std::make_shared<as2js::node>(as2js::node_t::NODE_FLOATING_POINT));
    2182           1 :             j.set_infinity();
    2183           1 :             j.set(-j.get());
    2184           1 :             node->set_floating_point(j);
    2185           1 :             CATCH_REQUIRE(node->to_string());
    2186           1 :             CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_STRING);
    2187           1 :             CATCH_REQUIRE(node->get_string() == "-Infinity");
    2188           1 :         }
    2189             :         { // +Infinity
    2190           1 :             as2js::floating_point j;
    2191           1 :             as2js::node::pointer_t node(std::make_shared<as2js::node>(as2js::node_t::NODE_FLOATING_POINT));
    2192           1 :             j.set_infinity();
    2193           1 :             j.set(-j.get());
    2194           1 :             node->set_floating_point(j);
    2195           1 :             CATCH_REQUIRE(node->to_integer());
    2196           1 :             CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_INTEGER);
    2197           1 :             CATCH_REQUIRE(node->get_integer().get() == 0);
    2198           1 :         }
    2199             :     }
    2200           3 :     CATCH_END_SECTION()
    2201           3 : }
    2202             : 
    2203             : 
    2204           4 : CATCH_TEST_CASE("node_tree", "[node][tree]")
    2205             : {
    2206             :     class tracked_node
    2207             :         : public as2js::node
    2208             :     {
    2209             :     public:
    2210       47774 :         tracked_node(as2js::node_t type, int & count)
    2211       47774 :             : node(type)
    2212       47774 :             , f_count(count)
    2213             :         {
    2214       47774 :             ++f_count;
    2215       47774 :         }
    2216             : 
    2217       47774 :         virtual ~tracked_node()
    2218       47774 :         {
    2219       47774 :             --f_count;
    2220       47774 :         }
    2221             : 
    2222             :     private:
    2223             :         int &       f_count;
    2224             :     };
    2225             : 
    2226             :     // a few basic tests
    2227           4 :     CATCH_START_SECTION("node_tree: basics")
    2228             :     {
    2229             :         // counter to know how many nodes we currently have allocated
    2230             :         //
    2231           1 :         int counter(0);
    2232             : 
    2233             :         {
    2234           2 :             as2js::node::pointer_t parent(std::make_shared<tracked_node>(as2js::node_t::NODE_DIRECTIVE_LIST, counter));
    2235             : 
    2236           1 :             CATCH_REQUIRE_THROWS_MATCHES(
    2237             :                   parent->get_child(-1)
    2238             :                 , as2js::out_of_range
    2239             :                 , Catch::Matchers::ExceptionMessage(
    2240             :                           "out_of_range: get_child(): index is too large for the number of children available."));
    2241           1 :             CATCH_REQUIRE_THROWS_MATCHES(
    2242             :                   parent->get_child(0)
    2243             :                 , as2js::out_of_range
    2244             :                 , Catch::Matchers::ExceptionMessage(
    2245             :                           "out_of_range: get_child(): index is too large for the number of children available."));
    2246           1 :             CATCH_REQUIRE_THROWS_MATCHES(
    2247             :                   parent->get_child(1)
    2248             :                 , as2js::out_of_range
    2249             :                 , Catch::Matchers::ExceptionMessage(
    2250             :                           "out_of_range: get_child(): index is too large for the number of children available."));
    2251             : 
    2252             :             // now we properly test whether the append_child(),
    2253             :             // insert_child(), and set_child() functions are used
    2254             :             // with a null pointer (which is considered illegal)
    2255           1 :             as2js::node::pointer_t null_pointer;
    2256           3 :             CATCH_REQUIRE_THROWS_MATCHES(
    2257             :                   parent->append_child(null_pointer)
    2258             :                 , as2js::invalid_data
    2259             :                 , Catch::Matchers::ExceptionMessage(
    2260             :                           "as2js_exception: cannot append a child if its pointer is null."));
    2261           3 :             CATCH_REQUIRE_THROWS_MATCHES(
    2262             :                   parent->insert_child(123, null_pointer)
    2263             :                 , as2js::invalid_data
    2264             :                 , Catch::Matchers::ExceptionMessage(
    2265             :                           "as2js_exception: cannot insert a child if its pointer is null."));
    2266           3 :             CATCH_REQUIRE_THROWS_MATCHES(
    2267             :                   parent->set_child(9, null_pointer)
    2268             :                 , as2js::invalid_data
    2269             :                 , Catch::Matchers::ExceptionMessage(
    2270             :                           "as2js_exception: cannot set a child if its pointer is null."));
    2271             : 
    2272          21 :             for(int i(0); i < 20; ++i)
    2273             :             {
    2274          40 :                 as2js::node::pointer_t child(std::make_shared<tracked_node>(as2js::node_t::NODE_DIRECTIVE_LIST, counter));
    2275          20 :                 parent->append_child(child);
    2276             : 
    2277          20 :                 CATCH_REQUIRE_THROWS_MATCHES(
    2278             :                       parent->get_child(-1)
    2279             :                     , as2js::out_of_range
    2280             :                     , Catch::Matchers::ExceptionMessage(
    2281             :                               "out_of_range: get_child(): index is too large for the number of children available."));
    2282         230 :                 for(int j(0); j <= i; ++j)
    2283             :                 {
    2284         210 :                     as2js::node::pointer_t c(parent->get_child(j));
    2285         210 :                     CATCH_REQUIRE(c != nullptr);
    2286         210 :                     if(i == j)
    2287             :                     {
    2288          20 :                         CATCH_REQUIRE(c == child);
    2289             :                     }
    2290             : 
    2291             :                     // set_parent() with -1 does nothing when the parent
    2292             :                     // of the child is the same
    2293             :                     //
    2294         210 :                     child->set_parent(parent, -1);
    2295         210 :                 }
    2296          20 :                 CATCH_REQUIRE_THROWS_MATCHES(
    2297             :                       parent->get_child(i + 1)
    2298             :                     , as2js::out_of_range
    2299             :                     , Catch::Matchers::ExceptionMessage(
    2300             :                               "out_of_range: get_child(): index is too large for the number of children available."));
    2301          20 :                 CATCH_REQUIRE_THROWS_MATCHES(
    2302             :                       parent->get_child(i + 2)
    2303             :                     , as2js::out_of_range
    2304             :                     , Catch::Matchers::ExceptionMessage(
    2305             :                               "out_of_range: get_child(): index is too large for the number of children available."));
    2306          20 :             }
    2307           1 :         }
    2308             : 
    2309             :         // did we deleted as many nodes as we created?
    2310             :         //
    2311           1 :         CATCH_REQUIRE(counter == 0);
    2312             :     }
    2313           4 :     CATCH_END_SECTION()
    2314             : 
    2315           4 :     CATCH_START_SECTION("node_tree: parent/child of any type")
    2316             :     {
    2317             :         // counter to know how many nodes we currently have allocated
    2318             :         //
    2319           1 :         int counter(0);
    2320             : 
    2321           1 :         as2js::node::pointer_t other_node(std::make_shared<as2js::node>(as2js::node_t::NODE_VOID));
    2322             : 
    2323             :         // first test: try with all types as the parent and children
    2324         219 :         for(size_t i(0); i < g_node_types_size; ++i)
    2325             :         {
    2326             :             // type
    2327         218 :             as2js::node_t parent_type(g_node_types[i].f_type);
    2328             : 
    2329         436 :             as2js::node::pointer_t parent(std::make_shared<tracked_node>(parent_type, counter));
    2330         218 :             CATCH_REQUIRE(parent->get_children_size() == 0);
    2331             : 
    2332         218 :             size_t valid_children(0);
    2333       47742 :             for(size_t j(0); j < g_node_types_size; ++j)
    2334             :             {
    2335       47524 :                 as2js::node_t child_type(g_node_types[j].f_type);
    2336             : 
    2337       95048 :                 as2js::node::pointer_t child(std::make_shared<tracked_node>(child_type, counter));
    2338             : 
    2339             : //std::cerr << "parent " << parent->get_type_name() << " child " << child->get_type_name() << "\n";
    2340             :                 // some nodes cannot be parents...
    2341       47524 :                 switch(parent_type)
    2342             :                 {
    2343       11990 :                 case as2js::node_t::NODE_ABSTRACT:
    2344             :                 case as2js::node_t::NODE_ASYNC:
    2345             :                 case as2js::node_t::NODE_AUTO:
    2346             :                 case as2js::node_t::NODE_AWAIT:
    2347             :                 case as2js::node_t::NODE_BOOLEAN:
    2348             :                 case as2js::node_t::NODE_BREAK:
    2349             :                 case as2js::node_t::NODE_BYTE:
    2350             :                 case as2js::node_t::NODE_CLOSE_CURVLY_BRACKET:
    2351             :                 case as2js::node_t::NODE_CLOSE_PARENTHESIS:
    2352             :                 case as2js::node_t::NODE_CLOSE_SQUARE_BRACKET:
    2353             :                 case as2js::node_t::NODE_CHAR:
    2354             :                 case as2js::node_t::NODE_COLON:
    2355             :                 case as2js::node_t::NODE_COMMA:
    2356             :                 case as2js::node_t::NODE_CONST:
    2357             :                 case as2js::node_t::NODE_CONTINUE:
    2358             :                 case as2js::node_t::NODE_DEFAULT:
    2359             :                 case as2js::node_t::NODE_DOUBLE:
    2360             :                 case as2js::node_t::NODE_ELSE:
    2361             :                 case as2js::node_t::NODE_THEN:
    2362             :                 case as2js::node_t::NODE_EMPTY:
    2363             :                 case as2js::node_t::NODE_EOF:
    2364             :                 case as2js::node_t::NODE_IDENTIFIER:
    2365             :                 case as2js::node_t::NODE_INLINE:
    2366             :                 case as2js::node_t::NODE_INTEGER:
    2367             :                 case as2js::node_t::NODE_FALSE:
    2368             :                 case as2js::node_t::NODE_FINAL:
    2369             :                 case as2js::node_t::NODE_FLOAT:
    2370             :                 case as2js::node_t::NODE_FLOATING_POINT:
    2371             :                 case as2js::node_t::NODE_GOTO:
    2372             :                 case as2js::node_t::NODE_LONG:
    2373             :                 case as2js::node_t::NODE_NATIVE:
    2374             :                 case as2js::node_t::NODE_NULL:
    2375             :                 case as2js::node_t::NODE_OPEN_CURVLY_BRACKET:
    2376             :                 case as2js::node_t::NODE_OPEN_PARENTHESIS:
    2377             :                 case as2js::node_t::NODE_OPEN_SQUARE_BRACKET:
    2378             :                 case as2js::node_t::NODE_PRIVATE:
    2379             :                 case as2js::node_t::NODE_PROTECTED:
    2380             :                 case as2js::node_t::NODE_PUBLIC:
    2381             :                 case as2js::node_t::NODE_REGULAR_EXPRESSION:
    2382             :                 case as2js::node_t::NODE_REST:
    2383             :                 case as2js::node_t::NODE_SEMICOLON:
    2384             :                 case as2js::node_t::NODE_SHORT:
    2385             :                 case as2js::node_t::NODE_STRING:
    2386             :                 case as2js::node_t::NODE_STATIC:
    2387             :                 case as2js::node_t::NODE_TEMPLATE:
    2388             :                 case as2js::node_t::NODE_TEMPLATE_HEAD:
    2389             :                 case as2js::node_t::NODE_TEMPLATE_MIDDLE:
    2390             :                 case as2js::node_t::NODE_TEMPLATE_TAIL:
    2391             :                 case as2js::node_t::NODE_THIS:
    2392             :                 case as2js::node_t::NODE_TRANSIENT:
    2393             :                 case as2js::node_t::NODE_TRUE:
    2394             :                 case as2js::node_t::NODE_UNDEFINED:
    2395             :                 case as2js::node_t::NODE_VIDENTIFIER:
    2396             :                 case as2js::node_t::NODE_VOID:
    2397             :                 case as2js::node_t::NODE_VOLATILE:
    2398             :                     // append child to parent must fail
    2399       11990 :                     if(rand() & 1)
    2400             :                     {
    2401       18099 :                         CATCH_REQUIRE_THROWS_MATCHES(
    2402             :                               parent->append_child(child)
    2403             :                             , as2js::incompatible_type
    2404             :                             , Catch::Matchers::ExceptionMessage(
    2405             :                                       "as2js_exception: invalid type: \""
    2406             :                                     + std::string(parent->get_type_name())
    2407             :                                     + "\" used as a parent node of child with type: \""
    2408             :                                     + std::string(child->get_type_name())
    2409             :                                     + "\"."));
    2410             :                     }
    2411             :                     else
    2412             :                     {
    2413       17871 :                         CATCH_REQUIRE_THROWS_MATCHES(
    2414             :                               child->set_parent(parent)
    2415             :                             , as2js::incompatible_type
    2416             :                             , Catch::Matchers::ExceptionMessage(
    2417             :                                       "as2js_exception: invalid type: \""
    2418             :                                     + std::string(parent->get_type_name())
    2419             :                                     + "\" used as a parent node of child with type: \""
    2420             :                                     + std::string(child->get_type_name())
    2421             :                                     + "\"."));
    2422             :                     }
    2423       11990 :                     break;
    2424             : 
    2425       35534 :                 default:
    2426       35534 :                     switch(child_type)
    2427             :                     {
    2428        2119 :                     case as2js::node_t::NODE_CLOSE_CURVLY_BRACKET:
    2429             :                     case as2js::node_t::NODE_CLOSE_PARENTHESIS:
    2430             :                     case as2js::node_t::NODE_CLOSE_SQUARE_BRACKET:
    2431             :                     case as2js::node_t::NODE_COLON:
    2432             :                     case as2js::node_t::NODE_COMMA:
    2433             :                     case as2js::node_t::NODE_ELSE:
    2434             :                     case as2js::node_t::NODE_THEN:
    2435             :                     case as2js::node_t::NODE_EOF:
    2436             :                     case as2js::node_t::NODE_OPEN_CURVLY_BRACKET:
    2437             :                     case as2js::node_t::NODE_OPEN_PARENTHESIS:
    2438             :                     case as2js::node_t::NODE_OPEN_SQUARE_BRACKET:
    2439             :                     case as2js::node_t::NODE_ROOT:
    2440             :                     case as2js::node_t::NODE_SEMICOLON:
    2441             :                         // append child to parent must fail
    2442        2119 :                         if(rand() & 1)
    2443             :                         {
    2444        3183 :                             CATCH_REQUIRE_THROWS_MATCHES(
    2445             :                                   parent->append_child(child)
    2446             :                                 , as2js::incompatible_type
    2447             :                                 , Catch::Matchers::ExceptionMessage(
    2448             :                                           "as2js_exception: invalid type: \""
    2449             :                                         + std::string(child->get_type_name())
    2450             :                                         + "\" used as a child node of parent type: \""
    2451             :                                         + parent->get_type_name()
    2452             :                                         + "\"."));
    2453             :                         }
    2454             :                         else
    2455             :                         {
    2456        3174 :                             CATCH_REQUIRE_THROWS_MATCHES(
    2457             :                                   child->set_parent(parent)
    2458             :                                 , as2js::incompatible_type
    2459             :                                 , Catch::Matchers::ExceptionMessage(
    2460             :                                           "as2js_exception: invalid type: \""
    2461             :                                         + std::string(child->get_type_name())
    2462             :                                         + "\" used as a child node of parent type: \""
    2463             :                                         + parent->get_type_name()
    2464             :                                         + "\"."));
    2465             :                         }
    2466        2119 :                         break;
    2467             : 
    2468       33415 :                     default:
    2469             :                         // append child to parent
    2470       33415 :                         if(rand() & 1)
    2471             :                         {
    2472       16583 :                             parent->append_child(child);
    2473             :                         }
    2474             :                         else
    2475             :                         {
    2476       16832 :                             child->set_parent(parent);
    2477             :                         }
    2478             : 
    2479       33415 :                         CATCH_REQUIRE(parent->get_children_size() == valid_children + 1);
    2480       33415 :                         CATCH_REQUIRE(child->get_parent() == parent);
    2481       33415 :                         CATCH_REQUIRE(child->get_offset() == valid_children);
    2482       33415 :                         CATCH_REQUIRE(parent->get_child(valid_children) == child);
    2483       33415 :                         CATCH_REQUIRE(parent->find_first_child(child_type) == child);
    2484       33415 :                         CATCH_REQUIRE(parent->find_next_child(child, child_type) == nullptr);
    2485             : 
    2486             :                         // test with a node which is not a child of "parent"
    2487             :                         //
    2488      100245 :                         CATCH_REQUIRE_THROWS_MATCHES(
    2489             :                               parent->find_next_child(other_node, child_type)
    2490             :                             , as2js::parent_child
    2491             :                             , Catch::Matchers::ExceptionMessage(
    2492             :                                       "as2js_exception: find_next_child() called with a child which is not a child of this node."));
    2493             : 
    2494       33415 :                         ++valid_children;
    2495       33415 :                         break;
    2496             : 
    2497             :                     }
    2498       35534 :                     break;
    2499             : 
    2500             :                 }
    2501       47524 :             }
    2502         218 :         }
    2503             : 
    2504             :         // did we deleted as many nodes as we created?
    2505             :         //
    2506           1 :         CATCH_REQUIRE(counter == 0);
    2507           1 :     }
    2508           4 :     CATCH_END_SECTION()
    2509             : 
    2510             :     // Test a more realistic tree with a few nodes and make sure we
    2511             :     // can apply certain function and that the tree exactly results
    2512             :     // in what we expect
    2513           4 :     CATCH_START_SECTION("node_tree: realistic tree")
    2514             :     {
    2515             :         // counter to know how many nodes we currently have allocated
    2516             :         //
    2517           1 :         int counter(0);
    2518             : 
    2519             :         {
    2520             :             // 1. Create the following in directive a:
    2521             :             //
    2522             :             //  // first block (directive_a)
    2523             :             //  {
    2524             :             //      a = Math.e ** 1.424;
    2525             :             //  }
    2526             :             //  // second block (directive_b)
    2527             :             //  {
    2528             :             //  }
    2529             :             //
    2530             :             // 2. Move it to directive b
    2531             :             //
    2532             :             //  // first block (directive_a)
    2533             :             //  {
    2534             :             //  }
    2535             :             //  // second block (directive_b)
    2536             :             //  {
    2537             :             //      a = Math.e ** 1.424;
    2538             :             //  }
    2539             :             //
    2540             :             // 3. Verify that it worked
    2541             :             //
    2542             : 
    2543             :             // create all the nodes as the lexer would do
    2544           2 :             as2js::node::pointer_t root(std::make_shared<tracked_node>(as2js::node_t::NODE_ROOT, counter));
    2545           1 :             as2js::position pos;
    2546           1 :             pos.reset_counters(22);
    2547           1 :             pos.set_filename("test.js");
    2548           1 :             root->set_position(pos);
    2549           2 :             as2js::node::pointer_t directive_list_a(std::make_shared<tracked_node>(as2js::node_t::NODE_DIRECTIVE_LIST, counter));
    2550           2 :             as2js::node::pointer_t directive_list_b(std::make_shared<tracked_node>(as2js::node_t::NODE_DIRECTIVE_LIST, counter));
    2551           2 :             as2js::node::pointer_t assignment(std::make_shared<tracked_node>(as2js::node_t::NODE_ASSIGNMENT, counter));
    2552           2 :             as2js::node::pointer_t identifier_a(std::make_shared<tracked_node>(as2js::node_t::NODE_IDENTIFIER, counter));
    2553           1 :             identifier_a->set_string("a");
    2554           2 :             as2js::node::pointer_t power(std::make_shared<tracked_node>(as2js::node_t::NODE_POWER, counter));
    2555           2 :             as2js::node::pointer_t member(std::make_shared<tracked_node>(as2js::node_t::NODE_MEMBER, counter));
    2556           2 :             as2js::node::pointer_t identifier_math(std::make_shared<tracked_node>(as2js::node_t::NODE_IDENTIFIER, counter));
    2557           1 :             identifier_math->set_string("Math");
    2558           2 :             as2js::node::pointer_t identifier_e(std::make_shared<tracked_node>(as2js::node_t::NODE_IDENTIFIER, counter));
    2559           1 :             identifier_e->set_string("e");
    2560           2 :             as2js::node::pointer_t literal(std::make_shared<tracked_node>(as2js::node_t::NODE_FLOATING_POINT, counter));
    2561           1 :             as2js::floating_point f;
    2562           1 :             f.set(1.424);
    2563           1 :             literal->set_floating_point(f);
    2564             : 
    2565             :             // build the tree as the parser would do
    2566           1 :             root->append_child(directive_list_a);
    2567           1 :             root->append_child(directive_list_b);
    2568           1 :             directive_list_a->append_child(assignment);
    2569           1 :             assignment->append_child(identifier_a);
    2570           1 :             assignment->insert_child(-1, power);
    2571           1 :             power->append_child(member);
    2572           3 :             CATCH_REQUIRE_THROWS_MATCHES(
    2573             :                   power->insert_child(10, literal)
    2574             :                 , as2js::out_of_range
    2575             :                 , Catch::Matchers::ExceptionMessage(
    2576             :                           "out_of_range: trying to insert a node at index 10 which is larger than 1."));
    2577           1 :             power->insert_child(1, literal);
    2578           1 :             member->append_child(identifier_e);
    2579           1 :             member->insert_child(0, identifier_math);
    2580             : 
    2581             :             // verify we can unlock mid-way
    2582           2 :             as2js::node_lock temp_lock(member);
    2583           1 :             CATCH_REQUIRE(member->is_locked());
    2584           1 :             temp_lock.unlock();
    2585           1 :             CATCH_REQUIRE(!member->is_locked());
    2586             : 
    2587             :             // as a complement to testing the lock, make sure that emptiness
    2588             :             // (i.e. null pointer) is properly handled all the way
    2589             :             {
    2590           1 :                 as2js::node::pointer_t empty;
    2591           2 :                 as2js::node_lock empty_lock(empty);
    2592           1 :             }
    2593             :             {
    2594           1 :                 as2js::node::pointer_t empty;
    2595           2 :                 as2js::node_lock empty_lock(empty);
    2596           1 :                 empty_lock.unlock();
    2597           1 :             }
    2598             : 
    2599             :             // apply some tests
    2600           1 :             CATCH_REQUIRE(root->get_children_size() == 2);
    2601           1 :             CATCH_REQUIRE(directive_list_a->get_children_size() == 1);
    2602           1 :             CATCH_REQUIRE(directive_list_a->get_child(0) == assignment);
    2603           1 :             CATCH_REQUIRE(directive_list_b->get_children_size() == 0);
    2604           1 :             CATCH_REQUIRE(assignment->get_children_size() == 2);
    2605           1 :             CATCH_REQUIRE(assignment->get_child(0) == identifier_a);
    2606           1 :             CATCH_REQUIRE(assignment->get_child(1) == power);
    2607           1 :             CATCH_REQUIRE(identifier_a->get_children_size() == 0);
    2608           1 :             CATCH_REQUIRE(power->get_children_size() == 2);
    2609           1 :             CATCH_REQUIRE(power->get_child(0) == member);
    2610           1 :             CATCH_REQUIRE(power->get_child(1) == literal);
    2611           1 :             CATCH_REQUIRE(member->get_children_size() == 2);
    2612           1 :             CATCH_REQUIRE(member->get_child(0) == identifier_math);
    2613           1 :             CATCH_REQUIRE(member->get_child(1) == identifier_e);
    2614           1 :             CATCH_REQUIRE(identifier_math->get_children_size() == 0);
    2615           1 :             CATCH_REQUIRE(identifier_e->get_children_size() == 0);
    2616           1 :             CATCH_REQUIRE(literal->get_children_size() == 0);
    2617             : 
    2618           1 :             CATCH_REQUIRE(root->has_side_effects());
    2619           1 :             CATCH_REQUIRE(directive_list_a->has_side_effects());
    2620           1 :             CATCH_REQUIRE(!directive_list_b->has_side_effects());
    2621           1 :             CATCH_REQUIRE(!power->has_side_effects());
    2622             : 
    2623             :             // now move the assignment from a to b
    2624           1 :             assignment->set_parent(directive_list_b);
    2625             : 
    2626           1 :             CATCH_REQUIRE(root->get_children_size() == 2);
    2627           1 :             CATCH_REQUIRE(directive_list_a->get_children_size() == 0);
    2628           1 :             CATCH_REQUIRE(directive_list_b->get_children_size() == 1);
    2629           1 :             CATCH_REQUIRE(directive_list_b->get_child(0) == assignment);
    2630           1 :             CATCH_REQUIRE(assignment->get_children_size() == 2);
    2631           1 :             CATCH_REQUIRE(assignment->get_child(0) == identifier_a);
    2632           1 :             CATCH_REQUIRE(assignment->get_child(1) == power);
    2633           1 :             CATCH_REQUIRE(identifier_a->get_children_size() == 0);
    2634           1 :             CATCH_REQUIRE(power->get_children_size() == 2);
    2635           1 :             CATCH_REQUIRE(power->get_child(0) == member);
    2636           1 :             CATCH_REQUIRE(power->get_child(1) == literal);
    2637           1 :             CATCH_REQUIRE(member->get_children_size() == 2);
    2638           1 :             CATCH_REQUIRE(member->get_child(0) == identifier_math);
    2639           1 :             CATCH_REQUIRE(member->get_child(1) == identifier_e);
    2640           1 :             CATCH_REQUIRE(identifier_math->get_children_size() == 0);
    2641           1 :             CATCH_REQUIRE(identifier_e->get_children_size() == 0);
    2642           1 :             CATCH_REQUIRE(literal->get_children_size() == 0);
    2643             : 
    2644           1 :             power->delete_child(0);
    2645           1 :             CATCH_REQUIRE(power->get_children_size() == 1);
    2646           1 :             CATCH_REQUIRE(power->get_child(0) == literal);
    2647             : 
    2648           1 :             power->insert_child(0, member);
    2649           1 :             CATCH_REQUIRE(power->get_children_size() == 2);
    2650           1 :             CATCH_REQUIRE(power->get_child(0) == member);
    2651           1 :             CATCH_REQUIRE(power->get_child(1) == literal);
    2652             : 
    2653           1 :             CATCH_REQUIRE(root->has_side_effects());
    2654           1 :             CATCH_REQUIRE(!directive_list_a->has_side_effects());
    2655           1 :             CATCH_REQUIRE(directive_list_b->has_side_effects());
    2656           1 :             CATCH_REQUIRE(!power->has_side_effects());
    2657             : 
    2658             :             // create a new literal
    2659           2 :             as2js::node::pointer_t literal_seven(std::make_shared<tracked_node>(as2js::node_t::NODE_FLOATING_POINT, counter));
    2660           1 :             as2js::floating_point f7;
    2661           1 :             f7.set(-7.33312);
    2662           1 :             literal_seven->set_floating_point(f7);
    2663           1 :             directive_list_a->append_child(literal_seven);
    2664           1 :             CATCH_REQUIRE(directive_list_a->get_children_size() == 1);
    2665           1 :             CATCH_REQUIRE(directive_list_a->get_child(0) == literal_seven);
    2666             : 
    2667             :             // now replace the old literal with the new one (i.e. a full move actually)
    2668           1 :             power->set_child(1, literal_seven);
    2669           1 :             CATCH_REQUIRE(power->get_children_size() == 2);
    2670           1 :             CATCH_REQUIRE(power->get_child(0) == member);
    2671           1 :             CATCH_REQUIRE(power->get_child(1) == literal_seven);
    2672             : 
    2673             :             // replace with itself should work just fine
    2674           1 :             power->set_child(0, member);
    2675           1 :             CATCH_REQUIRE(power->get_children_size() == 2);
    2676           1 :             CATCH_REQUIRE(power->get_child(0) == member);
    2677           1 :             CATCH_REQUIRE(power->get_child(1) == literal_seven);
    2678             : 
    2679             :             // verify that a replace fails if the node pointer is null
    2680           1 :             as2js::node::pointer_t null_pointer;
    2681           3 :             CATCH_REQUIRE_THROWS_MATCHES(
    2682             :                   literal_seven->replace_with(null_pointer)
    2683             :                 , as2js::invalid_data
    2684             :                 , Catch::Matchers::ExceptionMessage(
    2685             :                           "as2js_exception: cannot replace with a node if its pointer is null."));
    2686             : 
    2687             :             // replace with the old literal
    2688           1 :             literal_seven->replace_with(literal);
    2689           1 :             CATCH_REQUIRE(power->get_children_size() == 2);
    2690           1 :             CATCH_REQUIRE(power->get_child(0) == member);
    2691           1 :             CATCH_REQUIRE(power->get_child(1) == literal);
    2692             : 
    2693             :             // verify that a node without a parent generates an exception
    2694           3 :             CATCH_REQUIRE_THROWS_MATCHES(
    2695             :                   root->replace_with(literal_seven)
    2696             :                 , as2js::no_parent
    2697             :                 , Catch::Matchers::ExceptionMessage(
    2698             :                           "as2js_exception: trying to replace a node which has no parent."));
    2699             : 
    2700             :             // verify that we cannot get an offset on a node without a parent
    2701           1 :             CATCH_REQUIRE_THROWS_MATCHES(
    2702             :                   root->get_offset()
    2703             :                 , as2js::no_parent
    2704             :                 , Catch::Matchers::ExceptionMessage(
    2705             :                           "as2js_exception: get_offset() only works against nodes that have a parent."));
    2706             : 
    2707             :             // check out our tree textually
    2708             :             //std::cout << std::endl << *root << std::endl;
    2709             : 
    2710             :             // finally mark a node as unknown and call clean_tree()
    2711           1 :             CATCH_REQUIRE(!member->is_locked());
    2712             :             {
    2713           1 :                 snapdev::ostream_to_buf<char> out(std::cerr);
    2714           2 :                 as2js::node_lock lock(member);
    2715           1 :                 CATCH_REQUIRE(member->is_locked());
    2716           1 :                 CATCH_REQUIRE_THROWS_MATCHES(
    2717             :                       member->to_unknown()
    2718             :                     , as2js::locked_node
    2719             :                     , Catch::Matchers::ExceptionMessage(
    2720             :                               "as2js_exception: trying to modify a locked node."));
    2721           1 :                 CATCH_REQUIRE(member->get_type() == as2js::node_t::NODE_MEMBER);
    2722           1 :                 CATCH_REQUIRE(out.str().substr(0, 65) == "error: The following node is locked and thus cannot be modified:\n");
    2723           1 :             }
    2724           1 :             CATCH_REQUIRE(!member->is_locked());
    2725             :             // try too many unlock!
    2726           1 :             CATCH_REQUIRE_THROWS_MATCHES(
    2727             :                   member->unlock()
    2728             :                 , as2js::internal_error
    2729             :                 , Catch::Matchers::ExceptionMessage(
    2730             :                           "internal_error: somehow the node::unlock() function was called when the lock counter is zero."));
    2731           1 :             member->to_unknown();
    2732           1 :             CATCH_REQUIRE(member->get_type() == as2js::node_t::NODE_UNKNOWN);
    2733             :             {
    2734           1 :                 snapdev::ostream_to_buf<char> out(std::cerr);
    2735           2 :                 as2js::node_lock lock(member);
    2736           1 :                     CATCH_REQUIRE_THROWS_MATCHES(
    2737             :                           root->clean_tree()
    2738             :                         , as2js::locked_node
    2739             :                         , Catch::Matchers::ExceptionMessage(
    2740             :                                   "as2js_exception: trying to modify a locked node."));
    2741           1 :                 CATCH_REQUIRE(member->get_type() == as2js::node_t::NODE_UNKNOWN);
    2742           1 :                 CATCH_REQUIRE(member->get_parent());
    2743           1 :                 CATCH_REQUIRE(out.str().substr(0, 65) == "error: The following node is locked and thus cannot be modified:\n");
    2744           1 :             }
    2745           1 :             root->clean_tree();
    2746             : 
    2747             :             // check that the tree looks as expected
    2748           1 :             CATCH_REQUIRE(root->get_children_size() == 2);
    2749           1 :             CATCH_REQUIRE(directive_list_a->get_children_size() == 0);
    2750           1 :             CATCH_REQUIRE(directive_list_b->get_children_size() == 1);
    2751           1 :             CATCH_REQUIRE(directive_list_b->get_child(0) == assignment);
    2752           1 :             CATCH_REQUIRE(assignment->get_children_size() == 2);
    2753           1 :             CATCH_REQUIRE(assignment->get_child(0) == identifier_a);
    2754           1 :             CATCH_REQUIRE(assignment->get_child(1) == power);
    2755           1 :             CATCH_REQUIRE(identifier_a->get_children_size() == 0);
    2756           1 :             CATCH_REQUIRE(power->get_children_size() == 1);
    2757             :             // Although member is not in the tree anymore, its children
    2758             :             // are still there as expected (because we hold a smart pointers
    2759             :             // to all of that)
    2760             :             //CATCH_REQUIRE(power->get_child(0) == member);
    2761           1 :             CATCH_REQUIRE(power->get_child(0) == literal);
    2762           1 :             CATCH_REQUIRE(!member->get_parent());
    2763           1 :             CATCH_REQUIRE(member->get_children_size() == 2);
    2764           1 :             CATCH_REQUIRE(member->get_child(0) == identifier_math);
    2765           1 :             CATCH_REQUIRE(member->get_child(1) == identifier_e);
    2766           1 :             CATCH_REQUIRE(identifier_math->get_children_size() == 0);
    2767           1 :             CATCH_REQUIRE(identifier_math->get_parent() == member);
    2768           1 :             CATCH_REQUIRE(identifier_e->get_children_size() == 0);
    2769           1 :             CATCH_REQUIRE(identifier_e->get_parent() == member);
    2770           1 :             CATCH_REQUIRE(literal->get_children_size() == 0);
    2771           1 :         }
    2772             : 
    2773             :         // did we deleted as many nodes as we created?
    2774             :         //
    2775           1 :         CATCH_REQUIRE(counter == 0);
    2776             :     }
    2777           4 :     CATCH_END_SECTION()
    2778             : 
    2779           4 :     CATCH_START_SECTION("node_tree: verify find_next_node() properly")
    2780             :     {
    2781           1 :         as2js::node::pointer_t root(std::make_shared<as2js::node>(as2js::node_t::NODE_ROOT));
    2782           1 :         as2js::node::pointer_t list1(std::make_shared<as2js::node>(as2js::node_t::NODE_DIRECTIVE_LIST));
    2783           1 :         as2js::node::pointer_t list2(std::make_shared<as2js::node>(as2js::node_t::NODE_DIRECTIVE_LIST));
    2784           1 :         as2js::node::pointer_t list3(std::make_shared<as2js::node>(as2js::node_t::NODE_DIRECTIVE_LIST));
    2785           1 :         as2js::node::pointer_t list4(std::make_shared<as2js::node>(as2js::node_t::NODE_DIRECTIVE_LIST));
    2786           1 :         as2js::node::pointer_t list5(std::make_shared<as2js::node>(as2js::node_t::NODE_DIRECTIVE_LIST));
    2787             : 
    2788           1 :         root->append_child(list1);
    2789           1 :         root->append_child(list2);
    2790           1 :         root->append_child(list3);
    2791           1 :         root->append_child(list4);
    2792           1 :         root->append_child(list5);
    2793             : 
    2794           1 :         CATCH_REQUIRE(root->find_first_child(as2js::node_t::NODE_DIRECTIVE_LIST) == list1);
    2795           1 :         CATCH_REQUIRE(root->find_next_child(nullptr, as2js::node_t::NODE_DIRECTIVE_LIST) == list1);
    2796             : 
    2797           1 :         CATCH_REQUIRE(root->find_next_child(list1, as2js::node_t::NODE_DIRECTIVE_LIST) == list2);
    2798           1 :         CATCH_REQUIRE(root->find_next_child(list2, as2js::node_t::NODE_DIRECTIVE_LIST) == list3);
    2799           1 :         CATCH_REQUIRE(root->find_next_child(list3, as2js::node_t::NODE_DIRECTIVE_LIST) == list4);
    2800           1 :         CATCH_REQUIRE(root->find_next_child(list4, as2js::node_t::NODE_DIRECTIVE_LIST) == list5);
    2801             : 
    2802           1 :         CATCH_REQUIRE(root->find_next_child(list5, as2js::node_t::NODE_DIRECTIVE_LIST) == nullptr);
    2803           1 :     }
    2804           4 :     CATCH_END_SECTION()
    2805           4 : }
    2806             : 
    2807             : 
    2808           2 : CATCH_TEST_CASE("node_lock", "[node][lock]")
    2809             : {
    2810           2 :     CATCH_START_SECTION("node_lock: verify lock counter (proper lock/unlock)")
    2811             :     {
    2812           1 :         as2js::node::pointer_t n(std::make_shared<as2js::node>(as2js::node_t::NODE_CLASS));
    2813           1 :         CATCH_REQUIRE_FALSE(n->is_locked());
    2814           2 :         as2js::node_lock lock(n);
    2815           1 :         CATCH_REQUIRE(n->is_locked());
    2816             : 
    2817             :         // we get a double unlock error in the ~node_lock() function
    2818             :         // but have a catch() which ignores the fact...
    2819             :         //
    2820             :         // i.e. the correct way would be to instead do:
    2821             :         //
    2822             :         //        lock.unlock();
    2823             :         //
    2824           1 :         n->unlock();
    2825           1 :         CATCH_REQUIRE_FALSE(n->is_locked());
    2826           1 :     }
    2827           2 :     CATCH_END_SECTION()
    2828             : 
    2829           2 :     CATCH_START_SECTION("node_lock: verify lock counter (missing unlock)")
    2830             :     {
    2831             :         // in normal circumstances, skip that test...
    2832             :         //
    2833             :         // there is a kernel bug in older Linux versions (Ubuntu 18.04 and
    2834             :         // older for sure; kernel 4.15.0-200-generic still displayed that
    2835             :         // behavior)
    2836             :         //
    2837           1 :         if(SNAP_CATCH2_NAMESPACE::g_run_destructive)
    2838             :         {
    2839           0 :             std::cout << "info: skipping section; test can lock up in fork() on older versions of Linux; use --destructive to run the test on its own (which generally works on alls systems).\n";
    2840           0 :             CATCH_REQUIRE(true);
    2841           0 :             return;
    2842             :         }
    2843             : 
    2844             :         // manual lock, no unlock before deletion...
    2845             :         //
    2846             :         // that generates an std::terminate so we use an external test
    2847             :         // and verify that it fails with an abort() when we do not have
    2848             :         // the unlock
    2849             :         //
    2850             :         // WARNING: using system() means using a shell and that failed
    2851             :         //          so I have my own quick_exec() to skip on the shell
    2852             :         //
    2853           1 :         std::string cmd(SNAP_CATCH2_NAMESPACE::g_binary_dir());
    2854           1 :         cmd += "/tests/locked-node";
    2855             : //std::cerr << "--- system(\"" << cmd << "\"); ..." << std::endl;
    2856             :         //int r(system(cmd.c_str()));
    2857           1 :         int r(quick_exec(cmd));
    2858           1 :         CATCH_REQUIRE(r == 0);
    2859           1 :         cmd += " -u";
    2860             : //std::cerr << "--- system(\"" << cmd << "\"); ..." << std::endl;
    2861             :         //r = system(cmd.c_str());
    2862           1 :         r = quick_exec(cmd);
    2863           1 :         CATCH_REQUIRE(r == 1);
    2864             :         //if(!WIFEXITED(r))
    2865             :         //{
    2866             :         //    CATCH_REQUIRE("not exited?" == nullptr);
    2867             :         //}
    2868             :         //else if(WIFSIGNALED(r))
    2869             :         //{
    2870             :         //    CATCH_REQUIRE("signaled?" == nullptr);
    2871             :         //}
    2872             :         //else
    2873             :         //{
    2874             :         //    int const exit_code(WEXITSTATUS(r));
    2875             :         //    if(exit_code != SIGABRT + 128)
    2876             :         //    {
    2877             :         //        CATCH_REQUIRE(exit_code != SIGABRT + 128);
    2878             :         //    }
    2879             :         //}
    2880           1 :     }
    2881           2 :     CATCH_END_SECTION()
    2882             : }
    2883             : 
    2884             : 
    2885           1 : CATCH_TEST_CASE("node_parameter", "[node][parameter]")
    2886             : {
    2887           1 :     CATCH_START_SECTION("node_parameter: verify node parameters")
    2888             :     {
    2889           1 :         as2js::node::pointer_t match(std::make_shared<as2js::node>(as2js::node_t::NODE_PARAM_MATCH));
    2890             : 
    2891           1 :         CATCH_REQUIRE(match->get_param_size() == 0);
    2892             : 
    2893             :         // zero is not acceptable
    2894           1 :         CATCH_REQUIRE_THROWS_MATCHES(
    2895             :               match->set_param_size(0)
    2896             :             , as2js::internal_error
    2897             :             , Catch::Matchers::ExceptionMessage(
    2898             :                       "internal_error: set_param_size() was called with a size of zero."));
    2899             : 
    2900           1 :         match->set_param_size(5);
    2901           1 :         CATCH_REQUIRE(match->get_param_size() == 5);
    2902             : 
    2903             :         // cannot change the size once set
    2904           1 :         CATCH_REQUIRE_THROWS_MATCHES(
    2905             :               match->set_param_size(10)
    2906             :             , as2js::internal_error
    2907             :             , Catch::Matchers::ExceptionMessage(
    2908             :                       "internal_error: set_param_size() called twice."));
    2909             : 
    2910           1 :         CATCH_REQUIRE(match->get_param_size() == 5);
    2911             : 
    2912             :         // first set the depth, try with an out of range index too
    2913           6 :         for(int i(-5); i < 0; ++i)
    2914             :         {
    2915           5 :             CATCH_REQUIRE_THROWS_MATCHES(
    2916             :                   match->set_param_depth(i, rand())
    2917             :                 , as2js::out_of_range
    2918             :                 , Catch::Matchers::ExceptionMessage(
    2919             :                           "out_of_range: set_param_depth() called with an index out of range."));
    2920             :         }
    2921           1 :         ssize_t depths[5];
    2922           6 :         for(int i(0); i < 5; ++i)
    2923             :         {
    2924           5 :             depths[i] = rand();
    2925           5 :             match->set_param_depth(i, depths[i]);
    2926             :         }
    2927           7 :         for(int i(5); i <= 10; ++i)
    2928             :         {
    2929           6 :             CATCH_REQUIRE_THROWS_MATCHES(
    2930             :                   match->set_param_depth(i, rand())
    2931             :                 , as2js::out_of_range
    2932             :                 , Catch::Matchers::ExceptionMessage(
    2933             :                           "out_of_range: set_param_depth() called with an index out of range."));
    2934             :         }
    2935             : 
    2936             :         // now test that what we saved can be read back, also with some out of range
    2937           6 :         for(int i(-5); i < 0; ++i)
    2938             :         {
    2939           5 :                 CATCH_REQUIRE_THROWS_MATCHES(
    2940             :                       match->get_param_depth(i)
    2941             :                     , as2js::out_of_range
    2942             :                     , Catch::Matchers::ExceptionMessage(
    2943             :                               "out_of_range: get_param_depth() called with an out of range index."));
    2944             :         }
    2945           6 :         for(int i(0); i < 5; ++i)
    2946             :         {
    2947           5 :             CATCH_REQUIRE(match->get_param_depth(i) == depths[i]);
    2948             :         }
    2949           6 :         for(int i(5); i < 10; ++i)
    2950             :         {
    2951           5 :             CATCH_REQUIRE_THROWS_MATCHES(
    2952             :                   match->get_param_depth(i)
    2953             :                 , as2js::out_of_range
    2954             :                 , Catch::Matchers::ExceptionMessage(
    2955             :                           "out_of_range: get_param_depth() called with an out of range index."));
    2956             :         }
    2957             : 
    2958             :         // second set the index, try with an out of range index too
    2959           6 :         for(int i(-5); i < 0; ++i)
    2960             :         {
    2961           5 :             CATCH_REQUIRE_THROWS_MATCHES(
    2962             :                   match->set_param_index(i, rand() % 5)
    2963             :                 , as2js::out_of_range
    2964             :                 , Catch::Matchers::ExceptionMessage(
    2965             :                           "out_of_range: set_param_index() called with one or both indexes out of range."));
    2966           5 :             CATCH_REQUIRE_THROWS_MATCHES(
    2967             :                   match->set_param_index(i, rand())
    2968             :                 , as2js::out_of_range
    2969             :                 , Catch::Matchers::ExceptionMessage(
    2970             :                           "out_of_range: set_param_index() called with one or both indexes out of range."));
    2971             :         }
    2972           1 :         size_t index[5];
    2973           6 :         for(int i(0); i < 5; ++i)
    2974             :         {
    2975           5 :             index[i] = rand() % 5;
    2976           5 :             match->set_param_index(i, index[i]);
    2977             : 
    2978             :             // if 'j' is invalid, then just throw
    2979             :             // and do not change the valid value
    2980          55 :             for(int k(0); k < 10; ++k)
    2981             :             {
    2982          50 :                 int j(0);
    2983             :                 do
    2984             :                 {
    2985          50 :                     j = rand();
    2986             :                 }
    2987          50 :                 while(j >= 0 && j <= 5);
    2988          50 :                 CATCH_REQUIRE_THROWS_MATCHES(
    2989             :                       match->set_param_index(i, j)
    2990             :                     , as2js::out_of_range
    2991             :                     , Catch::Matchers::ExceptionMessage(
    2992             :                               "out_of_range: set_param_index() called with one or both indexes out of range."));
    2993             :             }
    2994             :         }
    2995           7 :         for(int i(5); i <= 10; ++i)
    2996             :         {
    2997           6 :             CATCH_REQUIRE_THROWS_MATCHES(
    2998             :                   match->set_param_index(i, rand() % 5)
    2999             :                 , as2js::out_of_range
    3000             :                 , Catch::Matchers::ExceptionMessage(
    3001             :                           "out_of_range: set_param_index() called with one or both indexes out of range."));
    3002           6 :             CATCH_REQUIRE_THROWS_MATCHES(
    3003             :                   match->set_param_index(i, rand())
    3004             :                 , as2js::out_of_range
    3005             :                 , Catch::Matchers::ExceptionMessage(
    3006             :                           "out_of_range: set_param_index() called with one or both indexes out of range."));
    3007             :         }
    3008             : 
    3009             :         // now test that what we saved can be read back, also with some out of range
    3010           6 :         for(int i(-5); i < 0; ++i)
    3011             :         {
    3012           5 :             CATCH_REQUIRE_THROWS_MATCHES(
    3013             :                   match->get_param_index(i)
    3014             :                 , as2js::out_of_range
    3015             :                 , Catch::Matchers::ExceptionMessage(
    3016             :                           "out_of_range: set_param_index() called with an index out of range."));
    3017             :         }
    3018           6 :         for(int i(0); i < 5; ++i)
    3019             :         {
    3020           5 :             CATCH_REQUIRE(match->get_param_index(i) == index[i]);
    3021             :         }
    3022           6 :         for(int i(5); i < 10; ++i)
    3023             :         {
    3024           5 :             CATCH_REQUIRE_THROWS_MATCHES(
    3025             :                   match->get_param_index(i)
    3026             :                 , as2js::out_of_range
    3027             :                 , Catch::Matchers::ExceptionMessage(
    3028             :                           "out_of_range: set_param_index() called with an index out of range."));
    3029             :         }
    3030           1 :     }
    3031           1 :     CATCH_END_SECTION()
    3032           1 : }
    3033             : 
    3034             : 
    3035           1 : CATCH_TEST_CASE("node_position", "[node][position]")
    3036             : {
    3037           1 :     CATCH_START_SECTION("node_position: verify position computation")
    3038             :     {
    3039           1 :         as2js::position pos;
    3040           1 :         pos.set_filename("file.js");
    3041           1 :         int total_line(1);
    3042          10 :         for(int page(1); page < 10; ++page)
    3043             :         {
    3044           9 :             int paragraphs(rand() % 10 + 10);
    3045           9 :             int page_line(1);
    3046           9 :             int paragraph(1);
    3047         900 :             for(int line(1); line < 100; ++line)
    3048             :             {
    3049         891 :                 CATCH_REQUIRE(pos.get_page() == page);
    3050         891 :                 CATCH_REQUIRE(pos.get_page_line() == page_line);
    3051         891 :                 CATCH_REQUIRE(pos.get_paragraph() == paragraph);
    3052         891 :                 CATCH_REQUIRE(pos.get_line() == total_line);
    3053             : 
    3054         891 :                 std::stringstream pos_str;
    3055         891 :                 pos_str << pos;
    3056         891 :                 std::stringstream test_str;
    3057         891 :                 test_str << "file.js:" << total_line << ":";
    3058         891 :                 CATCH_REQUIRE(pos_str.str() == test_str.str());
    3059             : 
    3060             :                 // create any valid type of node
    3061         891 :                 size_t const idx(rand() % g_node_types_size);
    3062         891 :                 as2js::node::pointer_t node(std::make_shared<as2js::node>(g_node_types[idx].f_type));
    3063             : 
    3064             :                 // set our current position in there
    3065         891 :                 node->set_position(pos);
    3066             : 
    3067             :                 // verify that the node position is equal to ours
    3068         891 :                 as2js::position const& node_pos(node->get_position());
    3069         891 :                 CATCH_REQUIRE(node_pos.get_page() == page);
    3070         891 :                 CATCH_REQUIRE(node_pos.get_page_line() == page_line);
    3071         891 :                 CATCH_REQUIRE(node_pos.get_paragraph() == paragraph);
    3072         891 :                 CATCH_REQUIRE(node_pos.get_line() == total_line);
    3073             : 
    3074         891 :                 std::stringstream node_pos_str;
    3075         891 :                 node_pos_str << node_pos;
    3076         891 :                 std::stringstream node_test_str;
    3077         891 :                 node_test_str << "file.js:" << total_line << ":";
    3078         891 :                 CATCH_REQUIRE(node_pos_str.str() == node_test_str.str());
    3079             : 
    3080             :                 // create a replacement now
    3081         891 :                 size_t const idx_replacement(rand() % g_node_types_size);
    3082         891 :                 as2js::node::pointer_t replacement(node->create_replacement(g_node_types[idx_replacement].f_type));
    3083             : 
    3084             :                 // verify that the replacement position is equal to ours
    3085             :                 // (and thus the node's)
    3086         891 :                 as2js::position const& replacement_pos(node->get_position());
    3087         891 :                 CATCH_REQUIRE(replacement_pos.get_page() == page);
    3088         891 :                 CATCH_REQUIRE(replacement_pos.get_page_line() == page_line);
    3089         891 :                 CATCH_REQUIRE(replacement_pos.get_paragraph() == paragraph);
    3090         891 :                 CATCH_REQUIRE(replacement_pos.get_line() == total_line);
    3091             : 
    3092         891 :                 std::stringstream replacement_pos_str;
    3093         891 :                 replacement_pos_str << replacement_pos;
    3094         891 :                 std::stringstream replacement_test_str;
    3095         891 :                 replacement_test_str << "file.js:" << total_line << ":";
    3096         891 :                 CATCH_REQUIRE(replacement_pos_str.str() == replacement_test_str.str());
    3097             : 
    3098             :                 // verify that the node position has not changed
    3099         891 :                 as2js::position const& node_pos2(node->get_position());
    3100         891 :                 CATCH_REQUIRE(node_pos2.get_page() == page);
    3101         891 :                 CATCH_REQUIRE(node_pos2.get_page_line() == page_line);
    3102         891 :                 CATCH_REQUIRE(node_pos2.get_paragraph() == paragraph);
    3103         891 :                 CATCH_REQUIRE(node_pos2.get_line() == total_line);
    3104             : 
    3105         891 :                 std::stringstream node_pos2_str;
    3106         891 :                 node_pos2_str << node_pos2;
    3107         891 :                 std::stringstream node_test2_str;
    3108         891 :                 node_test2_str << "file.js:" << total_line << ":";
    3109         891 :                 CATCH_REQUIRE(node_pos2_str.str() == node_test2_str.str());
    3110             : 
    3111             :                 // go to the next line, paragraph, etc.
    3112         891 :                 if(line % paragraphs == 0)
    3113             :                 {
    3114          59 :                     pos.new_paragraph();
    3115          59 :                     ++paragraph;
    3116             :                 }
    3117         891 :                 pos.new_line();
    3118         891 :                 ++total_line;
    3119         891 :                 ++page_line;
    3120         891 :             }
    3121           9 :             pos.new_page();
    3122             :         }
    3123           1 :     }
    3124           1 :     CATCH_END_SECTION()
    3125           1 : }
    3126             : 
    3127             : 
    3128           1 : CATCH_TEST_CASE("node_links", "[node][link]")
    3129             : {
    3130           1 :     CATCH_START_SECTION("node_links: verify node linking")
    3131             :     {
    3132          11 :         for(int i(0); i < 10; ++i)
    3133             :         {
    3134             :             // create any valid type of node
    3135          10 :             size_t const idx_node(rand() % g_node_types_size);
    3136          10 :             as2js::node::pointer_t node(std::make_shared<as2js::node>(g_node_types[idx_node].f_type));
    3137             : 
    3138          10 :             size_t const idx_bad_link(rand() % g_node_types_size);
    3139          10 :             as2js::node::pointer_t bad_link(std::make_shared<as2js::node>(g_node_types[idx_bad_link].f_type));
    3140             : 
    3141             :             // check various links
    3142             : 
    3143             :             { // instance
    3144          10 :                 as2js::node::pointer_t link(std::make_shared<as2js::node>(as2js::node_t::NODE_CLASS));
    3145          10 :                 node->set_instance(link);
    3146          10 :                 CATCH_REQUIRE(node->get_instance() == link);
    3147             : 
    3148          10 :                 as2js::node::pointer_t other_link(std::make_shared<as2js::node>(as2js::node_t::NODE_CLASS));
    3149          10 :                 node->set_instance(other_link);
    3150          10 :                 CATCH_REQUIRE(node->get_instance() == other_link);
    3151          10 :             }
    3152          10 :             CATCH_REQUIRE(!node->get_instance()); // weak pointer, reset to null
    3153             : 
    3154             :             { // type
    3155          10 :                 as2js::node::pointer_t link(std::make_shared<as2js::node>(as2js::node_t::NODE_IDENTIFIER));
    3156          10 :                 node->set_type_node(link);
    3157          10 :                 CATCH_REQUIRE(node->get_type_node() == link);
    3158             : 
    3159          10 :                 as2js::node::pointer_t other_link(std::make_shared<as2js::node>(as2js::node_t::NODE_IDENTIFIER));
    3160          10 :                 node->set_type_node(other_link);
    3161          10 :                 CATCH_REQUIRE(node->get_type_node() == other_link);
    3162          10 :             }
    3163          10 :             CATCH_REQUIRE(!node->get_type_node()); // weak pointer, reset to null
    3164             : 
    3165             :             { // attributes
    3166          10 :                 as2js::node::pointer_t link(std::make_shared<as2js::node>(as2js::node_t::NODE_ATTRIBUTES));
    3167          10 :                 node->set_attribute_node(link);
    3168          10 :                 CATCH_REQUIRE(node->get_attribute_node() == link);
    3169             : 
    3170          10 :                 as2js::node::pointer_t other_link(std::make_shared<as2js::node>(as2js::node_t::NODE_ATTRIBUTES));
    3171          10 :                 node->set_attribute_node(other_link);
    3172          10 :                 CATCH_REQUIRE(node->get_attribute_node() == other_link);
    3173          10 :             }
    3174          10 :             CATCH_REQUIRE(node->get_attribute_node()); // NOT a weak pointer for attributes
    3175             : 
    3176             :             { // goto exit
    3177          10 :                 as2js::node::pointer_t link(std::make_shared<as2js::node>(as2js::node_t::NODE_LABEL));
    3178          10 :                 node->set_goto_exit(link);
    3179          10 :                 CATCH_REQUIRE(node->get_goto_exit() == link);
    3180             : 
    3181          10 :                 as2js::node::pointer_t other_link(std::make_shared<as2js::node>(as2js::node_t::NODE_LABEL));
    3182          10 :                 node->set_goto_exit(other_link);
    3183          10 :                 CATCH_REQUIRE(node->get_goto_exit() == other_link);
    3184          10 :             }
    3185          10 :             CATCH_REQUIRE(!node->get_goto_exit()); // weak pointer, reset to null
    3186             : 
    3187             :             { // goto enter
    3188          10 :                 as2js::node::pointer_t link(std::make_shared<as2js::node>(as2js::node_t::NODE_LABEL));
    3189          10 :                 node->set_goto_enter(link);
    3190          10 :                 CATCH_REQUIRE(node->get_goto_enter() == link);
    3191             : 
    3192          10 :                 as2js::node::pointer_t other_link(std::make_shared<as2js::node>(as2js::node_t::NODE_LABEL));
    3193          10 :                 node->set_goto_enter(other_link);
    3194          10 :                 CATCH_REQUIRE(node->get_goto_enter() == other_link);
    3195          10 :             }
    3196          10 :             CATCH_REQUIRE(!node->get_goto_enter()); // weak pointer, reset to null
    3197          10 :         }
    3198             :     }
    3199           1 :     CATCH_END_SECTION()
    3200           1 : }
    3201             : 
    3202             : 
    3203           1 : CATCH_TEST_CASE("node_variable", "[node][variable]")
    3204             : {
    3205           1 :     CATCH_START_SECTION("node_variable: verify variables")
    3206             :     {
    3207          11 :         for(int i(0); i < 10; ++i)
    3208             :         {
    3209             :             // create any valid type of node
    3210          10 :             size_t const idx_node(rand() % g_node_types_size);
    3211          10 :             as2js::node::pointer_t node(std::make_shared<as2js::node>(g_node_types[idx_node].f_type));
    3212             : 
    3213             :             // create a node that is not a NODE_VARIABLE
    3214             :             size_t idx_bad_link;
    3215             :             do
    3216             :             {
    3217          10 :                 idx_bad_link = rand() % g_node_types_size;
    3218             :             }
    3219          10 :             while(g_node_types[idx_bad_link].f_type == as2js::node_t::NODE_VARIABLE);
    3220          10 :             as2js::node::pointer_t not_variable(std::make_shared<as2js::node>(g_node_types[idx_bad_link].f_type));
    3221          30 :             CATCH_REQUIRE_THROWS_MATCHES(
    3222             :                   node->add_variable(not_variable)
    3223             :                 , as2js::incompatible_type
    3224             :                 , Catch::Matchers::ExceptionMessage(
    3225             :                           "as2js_exception: the node parameter of the add_variable() function must be a \"NODE_VARIABLE\"."));
    3226             : 
    3227             :             // add 10 valid variables
    3228         120 :             as2js::node::pointer_t variables[10];
    3229         110 :             for(size_t j(0); j < 10; ++j)
    3230             :             {
    3231         100 :                 CATCH_REQUIRE(node->get_variable_size() == j);
    3232             : 
    3233         100 :                 variables[j].reset(new as2js::node(as2js::node_t::NODE_VARIABLE));
    3234         100 :                 node->add_variable(variables[j]);
    3235             :             }
    3236          10 :             CATCH_REQUIRE(node->get_variable_size() == 10);
    3237             : 
    3238             :             // try with offsets that are too small
    3239         110 :             for(int j(-10); j < 0; ++j)
    3240             :             {
    3241         100 :                 CATCH_REQUIRE_THROWS_MATCHES(
    3242             :                       node->get_variable(j)
    3243             :                     , as2js::out_of_range
    3244             :                     , Catch::Matchers::ExceptionMessage(
    3245             :                               "out_of_range: get_variable() called with an out of range index."));
    3246             :             }
    3247             : 
    3248             :             // then verify that the variables are indeed valid
    3249         110 :             for(int j(0); j < 10; ++j)
    3250             :             {
    3251         100 :                 CATCH_REQUIRE(node->get_variable(j) == variables[j]);
    3252             :             }
    3253             : 
    3254             :             // try with offsets that are too large
    3255         120 :             for(int j(10); j <= 20; ++j)
    3256             :             {
    3257         110 :                 CATCH_REQUIRE_THROWS_MATCHES(
    3258             :                       node->get_variable(j)
    3259             :                     , as2js::out_of_range
    3260             :                     , Catch::Matchers::ExceptionMessage(
    3261             :                               "out_of_range: get_variable() called with an out of range index."));
    3262             :             }
    3263         120 :         }
    3264             :     }
    3265           1 :     CATCH_END_SECTION()
    3266           1 : }
    3267             : 
    3268             : 
    3269           1 : CATCH_TEST_CASE("node_label", "[node][label]")
    3270             : {
    3271           1 :     CATCH_START_SECTION("node_label: verify labelling")
    3272             :     {
    3273          11 :         for(int i(0); i < 10; ++i)
    3274             :         {
    3275             :             // create a NODE_FUNCTION
    3276          10 :             as2js::node::pointer_t function(std::make_shared<as2js::node>(as2js::node_t::NODE_FUNCTION));
    3277             : 
    3278             :             // create a node that is not a NODE_LABEL
    3279             :             size_t idx_bad_label;
    3280             :             do
    3281             :             {
    3282          10 :                 idx_bad_label = rand() % g_node_types_size;
    3283             :             }
    3284          10 :             while(g_node_types[idx_bad_label].f_type == as2js::node_t::NODE_LABEL);
    3285          10 :             as2js::node::pointer_t not_label(std::make_shared<as2js::node>(g_node_types[idx_bad_label].f_type));
    3286          30 :             CATCH_REQUIRE_THROWS_MATCHES(
    3287             :                   function->add_label(not_label)
    3288             :                 , as2js::incompatible_type
    3289             :                 , Catch::Matchers::ExceptionMessage(
    3290             :                           "as2js_exception: invalid type of node to call add_label() with."));
    3291             : 
    3292         110 :             for(int j(0); j < 10; ++j)
    3293             :             {
    3294             :                 // create a node that is not a NODE_LABEL
    3295         100 :                 as2js::node::pointer_t label(std::make_shared<as2js::node>(as2js::node_t::NODE_LABEL));
    3296             : 
    3297             :                 // create a node that is not a NODE_FUNCTION
    3298             :                 size_t idx_bad_function;
    3299             :                 do
    3300             :                 {
    3301         100 :                     idx_bad_function = rand() % g_node_types_size;
    3302             :                 }
    3303         100 :                 while(g_node_types[idx_bad_function].f_type == as2js::node_t::NODE_FUNCTION);
    3304         100 :                 as2js::node::pointer_t not_function(std::make_shared<as2js::node>(g_node_types[idx_bad_function].f_type));
    3305         300 :                 CATCH_REQUIRE_THROWS_MATCHES(
    3306             :                       not_function->add_label(label)
    3307             :                     , as2js::incompatible_type
    3308             :                     , Catch::Matchers::ExceptionMessage(
    3309             :                               "as2js_exception: invalid type of node to call add_label() with."));
    3310             : 
    3311             :                 // labels need to have a name
    3312         300 :                 CATCH_REQUIRE_THROWS_MATCHES(
    3313             :                       function->add_label(label)
    3314             :                     , as2js::incompatible_data
    3315             :                     , Catch::Matchers::ExceptionMessage(
    3316             :                               "as2js_exception: a label without a valid name cannot be added to a function."));
    3317             : 
    3318             :                 // save the label with a name
    3319         200 :                 std::string label_name("label" + std::to_string(j));
    3320         100 :                 label->set_string(label_name);
    3321         100 :                 function->add_label(label);
    3322             : 
    3323             :                 // trying to add two labels (or the same) with the same name err
    3324         300 :                 CATCH_REQUIRE_THROWS_MATCHES(
    3325             :                       function->add_label(label)
    3326             :                     , as2js::already_defined
    3327             :                     , Catch::Matchers::ExceptionMessage(
    3328             :                               "as2js_exception: a label with the same name is already defined in this function."));
    3329             : 
    3330             :                 // verify that we can find that label
    3331         100 :                 CATCH_REQUIRE(function->find_label(label_name) == label);
    3332         100 :             }
    3333          10 :         }
    3334             :     }
    3335           1 :     CATCH_END_SECTION()
    3336           1 : }
    3337             : 
    3338             : 
    3339           1 : CATCH_TEST_CASE("node_attribute", "[node][attribute]")
    3340             : {
    3341           1 :     CATCH_START_SECTION("node_attribute: verify setting attributes on nodes")
    3342             :     {
    3343          11 :         for(int i(0); i < 10; ++i)
    3344             :         {
    3345             :             // create a node that is not a NODE_PROGRAM
    3346             :             // (i.e. a node that accepts all attributes)
    3347             :             size_t idx_node;
    3348             :             do
    3349             :             {
    3350          10 :                 idx_node = rand() % g_node_types_size;
    3351             :             }
    3352          10 :             while(g_node_types[idx_node].f_type == as2js::node_t::NODE_PROGRAM);
    3353          10 :             as2js::node::pointer_t node(std::make_shared<as2js::node>(g_node_types[idx_node].f_type));
    3354             : 
    3355             :             // need to test all combinatorial cases...
    3356          60 :             for(size_t j(0); j < g_groups_of_attributes_size; ++j)
    3357             :             {
    3358             :                 // go through the list of attributes that generate conflicts
    3359         190 :                 for(as2js::attribute_t const *attr_list(g_groups_of_attributes[j].f_attributes);
    3360         190 :                                              *attr_list != as2js::attribute_t::NODE_ATTR_max;
    3361             :                                              ++attr_list)
    3362             :                 {
    3363         140 :                     if(*attr_list == as2js::attribute_t::NODE_ATTR_TYPE)
    3364             :                     {
    3365           0 :                         switch(node->get_type())
    3366             :                         {
    3367           0 :                         case as2js::node_t::NODE_ADD:
    3368             :                         case as2js::node_t::NODE_ARRAY:
    3369             :                         case as2js::node_t::NODE_ARRAY_LITERAL:
    3370             :                         case as2js::node_t::NODE_AS:
    3371             :                         case as2js::node_t::NODE_ASSIGNMENT:
    3372             :                         case as2js::node_t::NODE_ASSIGNMENT_ADD:
    3373             :                         case as2js::node_t::NODE_ASSIGNMENT_BITWISE_AND:
    3374             :                         case as2js::node_t::NODE_ASSIGNMENT_BITWISE_OR:
    3375             :                         case as2js::node_t::NODE_ASSIGNMENT_BITWISE_XOR:
    3376             :                         case as2js::node_t::NODE_ASSIGNMENT_DIVIDE:
    3377             :                         case as2js::node_t::NODE_ASSIGNMENT_LOGICAL_AND:
    3378             :                         case as2js::node_t::NODE_ASSIGNMENT_LOGICAL_OR:
    3379             :                         case as2js::node_t::NODE_ASSIGNMENT_LOGICAL_XOR:
    3380             :                         case as2js::node_t::NODE_ASSIGNMENT_MAXIMUM:
    3381             :                         case as2js::node_t::NODE_ASSIGNMENT_MINIMUM:
    3382             :                         case as2js::node_t::NODE_ASSIGNMENT_MODULO:
    3383             :                         case as2js::node_t::NODE_ASSIGNMENT_MULTIPLY:
    3384             :                         case as2js::node_t::NODE_ASSIGNMENT_POWER:
    3385             :                         case as2js::node_t::NODE_ASSIGNMENT_ROTATE_LEFT:
    3386             :                         case as2js::node_t::NODE_ASSIGNMENT_ROTATE_RIGHT:
    3387             :                         case as2js::node_t::NODE_ASSIGNMENT_SHIFT_LEFT:
    3388             :                         case as2js::node_t::NODE_ASSIGNMENT_SHIFT_RIGHT:
    3389             :                         case as2js::node_t::NODE_ASSIGNMENT_SHIFT_RIGHT_UNSIGNED:
    3390             :                         case as2js::node_t::NODE_ASSIGNMENT_SUBTRACT:
    3391             :                         case as2js::node_t::NODE_BITWISE_AND:
    3392             :                         case as2js::node_t::NODE_BITWISE_NOT:
    3393             :                         case as2js::node_t::NODE_BITWISE_OR:
    3394             :                         case as2js::node_t::NODE_BITWISE_XOR:
    3395             :                         case as2js::node_t::NODE_CALL:
    3396             :                         case as2js::node_t::NODE_CONDITIONAL:
    3397             :                         case as2js::node_t::NODE_DECREMENT:
    3398             :                         case as2js::node_t::NODE_DELETE:
    3399             :                         case as2js::node_t::NODE_DIVIDE:
    3400             :                         case as2js::node_t::NODE_EQUAL:
    3401             :                         case as2js::node_t::NODE_FALSE:
    3402             :                         case as2js::node_t::NODE_FLOATING_POINT:
    3403             :                         case as2js::node_t::NODE_FUNCTION:
    3404             :                         case as2js::node_t::NODE_GREATER:
    3405             :                         case as2js::node_t::NODE_GREATER_EQUAL:
    3406             :                         case as2js::node_t::NODE_IDENTIFIER:
    3407             :                         case as2js::node_t::NODE_IN:
    3408             :                         case as2js::node_t::NODE_INCREMENT:
    3409             :                         case as2js::node_t::NODE_INSTANCEOF:
    3410             :                         case as2js::node_t::NODE_INTEGER:
    3411             :                         case as2js::node_t::NODE_IS:
    3412             :                         case as2js::node_t::NODE_LESS:
    3413             :                         case as2js::node_t::NODE_LESS_EQUAL:
    3414             :                         case as2js::node_t::NODE_LIST:
    3415             :                         case as2js::node_t::NODE_LOGICAL_AND:
    3416             :                         case as2js::node_t::NODE_LOGICAL_NOT:
    3417             :                         case as2js::node_t::NODE_LOGICAL_OR:
    3418             :                         case as2js::node_t::NODE_LOGICAL_XOR:
    3419             :                         case as2js::node_t::NODE_MATCH:
    3420             :                         case as2js::node_t::NODE_MAXIMUM:
    3421             :                         case as2js::node_t::NODE_MEMBER:
    3422             :                         case as2js::node_t::NODE_MINIMUM:
    3423             :                         case as2js::node_t::NODE_MODULO:
    3424             :                         case as2js::node_t::NODE_MULTIPLY:
    3425             :                         case as2js::node_t::NODE_NAME:
    3426             :                         case as2js::node_t::NODE_NEW:
    3427             :                         case as2js::node_t::NODE_NOT_EQUAL:
    3428             :                         case as2js::node_t::NODE_NULL:
    3429             :                         case as2js::node_t::NODE_OBJECT_LITERAL:
    3430             :                         case as2js::node_t::NODE_POST_DECREMENT:
    3431             :                         case as2js::node_t::NODE_POST_INCREMENT:
    3432             :                         case as2js::node_t::NODE_POWER:
    3433             :                         case as2js::node_t::NODE_PRIVATE:
    3434             :                         case as2js::node_t::NODE_PUBLIC:
    3435             :                         case as2js::node_t::NODE_RANGE:
    3436             :                         case as2js::node_t::NODE_ROTATE_LEFT:
    3437             :                         case as2js::node_t::NODE_ROTATE_RIGHT:
    3438             :                         case as2js::node_t::NODE_SCOPE:
    3439             :                         case as2js::node_t::NODE_SHIFT_LEFT:
    3440             :                         case as2js::node_t::NODE_SHIFT_RIGHT:
    3441             :                         case as2js::node_t::NODE_SHIFT_RIGHT_UNSIGNED:
    3442             :                         case as2js::node_t::NODE_STRICTLY_EQUAL:
    3443             :                         case as2js::node_t::NODE_STRICTLY_NOT_EQUAL:
    3444             :                         case as2js::node_t::NODE_STRING:
    3445             :                         case as2js::node_t::NODE_SUBTRACT:
    3446             :                         case as2js::node_t::NODE_SUPER:
    3447             :                         case as2js::node_t::NODE_THIS:
    3448             :                         case as2js::node_t::NODE_TRUE:
    3449             :                         case as2js::node_t::NODE_TYPEOF:
    3450             :                         case as2js::node_t::NODE_UNDEFINED:
    3451             :                         case as2js::node_t::NODE_VIDENTIFIER:
    3452             :                         case as2js::node_t::NODE_VOID:
    3453           0 :                             break;;
    3454             : 
    3455           0 :                         default:
    3456             :                             // with any other types we would get an error
    3457           0 :                             continue;
    3458             : 
    3459             :                         }
    3460             :                     }
    3461             : 
    3462         140 :                     as2js::attribute_set_t set;
    3463         140 :                     CATCH_REQUIRE(node->compare_all_attributes(set));
    3464             : 
    3465             :                     // set that one attribute first
    3466         140 :                     node->set_attribute(*attr_list, true);
    3467             : 
    3468         140 :                     CATCH_REQUIRE(!node->compare_all_attributes(set));
    3469         140 :                     set[static_cast<int>(*attr_list)] = true;
    3470         140 :                     CATCH_REQUIRE(node->compare_all_attributes(set));
    3471             : 
    3472         420 :                     std::string str(g_attribute_names[static_cast<int>(*attr_list)]);
    3473             : 
    3474             :                     // test against all the other attributes
    3475        4340 :                     for(int a(0); a < static_cast<int>(as2js::attribute_t::NODE_ATTR_max); ++a)
    3476             :                     {
    3477             :                         // no need to test with itself, we do that earlier
    3478        4200 :                         if(static_cast<as2js::attribute_t>(a) == *attr_list)
    3479             :                         {
    3480         140 :                             continue;
    3481             :                         }
    3482             : 
    3483        4060 :                         if(static_cast<as2js::attribute_t>(a) == as2js::attribute_t::NODE_ATTR_TYPE)
    3484             :                         {
    3485         140 :                             switch(node->get_type())
    3486             :                             {
    3487          84 :                             case as2js::node_t::NODE_ADD:
    3488             :                             case as2js::node_t::NODE_ARRAY:
    3489             :                             case as2js::node_t::NODE_ARRAY_LITERAL:
    3490             :                             case as2js::node_t::NODE_AS:
    3491             :                             case as2js::node_t::NODE_ASSIGNMENT:
    3492             :                             case as2js::node_t::NODE_ASSIGNMENT_ADD:
    3493             :                             case as2js::node_t::NODE_ASSIGNMENT_BITWISE_AND:
    3494             :                             case as2js::node_t::NODE_ASSIGNMENT_BITWISE_OR:
    3495             :                             case as2js::node_t::NODE_ASSIGNMENT_BITWISE_XOR:
    3496             :                             case as2js::node_t::NODE_ASSIGNMENT_DIVIDE:
    3497             :                             case as2js::node_t::NODE_ASSIGNMENT_LOGICAL_AND:
    3498             :                             case as2js::node_t::NODE_ASSIGNMENT_LOGICAL_OR:
    3499             :                             case as2js::node_t::NODE_ASSIGNMENT_LOGICAL_XOR:
    3500             :                             case as2js::node_t::NODE_ASSIGNMENT_MAXIMUM:
    3501             :                             case as2js::node_t::NODE_ASSIGNMENT_MINIMUM:
    3502             :                             case as2js::node_t::NODE_ASSIGNMENT_MODULO:
    3503             :                             case as2js::node_t::NODE_ASSIGNMENT_MULTIPLY:
    3504             :                             case as2js::node_t::NODE_ASSIGNMENT_POWER:
    3505             :                             case as2js::node_t::NODE_ASSIGNMENT_ROTATE_LEFT:
    3506             :                             case as2js::node_t::NODE_ASSIGNMENT_ROTATE_RIGHT:
    3507             :                             case as2js::node_t::NODE_ASSIGNMENT_SHIFT_LEFT:
    3508             :                             case as2js::node_t::NODE_ASSIGNMENT_SHIFT_RIGHT:
    3509             :                             case as2js::node_t::NODE_ASSIGNMENT_SHIFT_RIGHT_UNSIGNED:
    3510             :                             case as2js::node_t::NODE_ASSIGNMENT_SUBTRACT:
    3511             :                             case as2js::node_t::NODE_BITWISE_AND:
    3512             :                             case as2js::node_t::NODE_BITWISE_NOT:
    3513             :                             case as2js::node_t::NODE_BITWISE_OR:
    3514             :                             case as2js::node_t::NODE_BITWISE_XOR:
    3515             :                             case as2js::node_t::NODE_CALL:
    3516             :                             case as2js::node_t::NODE_CONDITIONAL:
    3517             :                             case as2js::node_t::NODE_DECREMENT:
    3518             :                             case as2js::node_t::NODE_DELETE:
    3519             :                             case as2js::node_t::NODE_DIVIDE:
    3520             :                             case as2js::node_t::NODE_EQUAL:
    3521             :                             case as2js::node_t::NODE_FALSE:
    3522             :                             case as2js::node_t::NODE_FLOATING_POINT:
    3523             :                             case as2js::node_t::NODE_FUNCTION:
    3524             :                             case as2js::node_t::NODE_GREATER:
    3525             :                             case as2js::node_t::NODE_GREATER_EQUAL:
    3526             :                             case as2js::node_t::NODE_IDENTIFIER:
    3527             :                             case as2js::node_t::NODE_IN:
    3528             :                             case as2js::node_t::NODE_INCREMENT:
    3529             :                             case as2js::node_t::NODE_INSTANCEOF:
    3530             :                             case as2js::node_t::NODE_INTEGER:
    3531             :                             case as2js::node_t::NODE_IS:
    3532             :                             case as2js::node_t::NODE_LESS:
    3533             :                             case as2js::node_t::NODE_LESS_EQUAL:
    3534             :                             case as2js::node_t::NODE_LIST:
    3535             :                             case as2js::node_t::NODE_LOGICAL_AND:
    3536             :                             case as2js::node_t::NODE_LOGICAL_NOT:
    3537             :                             case as2js::node_t::NODE_LOGICAL_OR:
    3538             :                             case as2js::node_t::NODE_LOGICAL_XOR:
    3539             :                             case as2js::node_t::NODE_MATCH:
    3540             :                             case as2js::node_t::NODE_MAXIMUM:
    3541             :                             case as2js::node_t::NODE_MEMBER:
    3542             :                             case as2js::node_t::NODE_MINIMUM:
    3543             :                             case as2js::node_t::NODE_MODULO:
    3544             :                             case as2js::node_t::NODE_MULTIPLY:
    3545             :                             case as2js::node_t::NODE_NAME:
    3546             :                             case as2js::node_t::NODE_NEW:
    3547             :                             case as2js::node_t::NODE_NOT_EQUAL:
    3548             :                             case as2js::node_t::NODE_NULL:
    3549             :                             case as2js::node_t::NODE_OBJECT_LITERAL:
    3550             :                             case as2js::node_t::NODE_POST_DECREMENT:
    3551             :                             case as2js::node_t::NODE_POST_INCREMENT:
    3552             :                             case as2js::node_t::NODE_POWER:
    3553             :                             case as2js::node_t::NODE_PRIVATE:
    3554             :                             case as2js::node_t::NODE_PUBLIC:
    3555             :                             case as2js::node_t::NODE_RANGE:
    3556             :                             case as2js::node_t::NODE_ROTATE_LEFT:
    3557             :                             case as2js::node_t::NODE_ROTATE_RIGHT:
    3558             :                             case as2js::node_t::NODE_SCOPE:
    3559             :                             case as2js::node_t::NODE_SHIFT_LEFT:
    3560             :                             case as2js::node_t::NODE_SHIFT_RIGHT:
    3561             :                             case as2js::node_t::NODE_SHIFT_RIGHT_UNSIGNED:
    3562             :                             case as2js::node_t::NODE_STRICTLY_EQUAL:
    3563             :                             case as2js::node_t::NODE_STRICTLY_NOT_EQUAL:
    3564             :                             case as2js::node_t::NODE_STRING:
    3565             :                             case as2js::node_t::NODE_SUBTRACT:
    3566             :                             case as2js::node_t::NODE_SUPER:
    3567             :                             case as2js::node_t::NODE_THIS:
    3568             :                             case as2js::node_t::NODE_TRUE:
    3569             :                             case as2js::node_t::NODE_TYPEOF:
    3570             :                             case as2js::node_t::NODE_UNDEFINED:
    3571             :                             case as2js::node_t::NODE_VIDENTIFIER:
    3572             :                             case as2js::node_t::NODE_VOID:
    3573          84 :                                 break;;
    3574             : 
    3575          56 :                             default:
    3576             :                                 // with any other types we would get an error
    3577          56 :                                 continue;
    3578             : 
    3579             :                             }
    3580             :                         }
    3581             : 
    3582             :                         // is attribute 'a' in conflict with attribute '*attr_list'?
    3583        4004 :                         if(in_conflict(j, *attr_list, static_cast<as2js::attribute_t>(a)))
    3584             :                         {
    3585         320 :                             test_callback c;
    3586         320 :                             c.f_expected_message_level = as2js::message_level_t::MESSAGE_LEVEL_ERROR;
    3587         320 :                             c.f_expected_error_code = as2js::err_code_t::AS_ERR_INVALID_ATTRIBUTES;
    3588         320 :                             c.f_expected_pos.set_filename("unknown-file");
    3589         320 :                             c.f_expected_pos.set_function("unknown-func");
    3590         320 :                             c.f_expected_message = "Attributes " + std::string(g_groups_of_attributes[j].f_names) + " are mutually exclusive. Only one of them can be used.";
    3591             : 
    3592             :     //std::cerr << "next conflict: " << c.f_expected_message << "\n";
    3593             :                             // if in conflict, trying to set the flag generates
    3594             :                             // an error
    3595         320 :                             CATCH_REQUIRE(!node->get_attribute(static_cast<as2js::attribute_t>(a)));
    3596         320 :                             node->set_attribute(static_cast<as2js::attribute_t>(a), true);
    3597             :                             // the set_attribute() did not change the attribute because it is
    3598             :                             // in conflict with another attribute which is set at this time...
    3599         320 :                             CATCH_REQUIRE(!node->get_attribute(static_cast<as2js::attribute_t>(a)));
    3600         320 :                         }
    3601             :                         else
    3602             :                         {
    3603             :                             // before we set it, always false
    3604             : //std::cerr << "next valid attr: " << static_cast<int>(*attr_list) << " against " << a << "\n";
    3605        3684 :                             CATCH_REQUIRE(!node->get_attribute(static_cast<as2js::attribute_t>(a)));
    3606        3684 :                             node->set_attribute(static_cast<as2js::attribute_t>(a), true);
    3607        3684 :                             CATCH_REQUIRE(node->get_attribute(static_cast<as2js::attribute_t>(a)));
    3608        3684 :                             node->set_attribute(static_cast<as2js::attribute_t>(a), false);
    3609        3684 :                             CATCH_REQUIRE(!node->get_attribute(static_cast<as2js::attribute_t>(a)));
    3610             :                         }
    3611             :                     }
    3612             : 
    3613             :                     // we are done with that loop, restore the attribute to the default
    3614         140 :                     node->set_attribute(*attr_list, false);
    3615             :                 }
    3616             :             }
    3617          10 :         }
    3618             :     }
    3619           1 :     CATCH_END_SECTION()
    3620           1 : }
    3621             : 
    3622             : 
    3623           1 : CATCH_TEST_CASE("node_attribute_tree", "[node][attribute][tree]")
    3624             : {
    3625           1 :     CATCH_START_SECTION("node_attribute_tree: check attributes in a tree")
    3626             :     {
    3627             :         // here we create a tree of nodes that we can then test with various
    3628             :         // attributes using the set_attribute_tree() function
    3629             :         //
    3630             :         // the tree is very specific to make it easier to handle the test; there
    3631             :         // is no need to test every single case (every attribute) since we do that
    3632             :         // in other tests; this test is to make sure the tree is followed as
    3633             :         // expected (all leaves are hit)
    3634             :         //
    3635           1 :         as2js::node::pointer_t root(std::make_shared<as2js::node>(as2js::node_t::NODE_ROOT));
    3636             : 
    3637             :         // block
    3638           1 :         as2js::node::pointer_t directive_list(std::make_shared<as2js::node>(as2js::node_t::NODE_DIRECTIVE_LIST));
    3639           1 :         root->append_child(directive_list);
    3640             : 
    3641             :         // { for( ...
    3642           1 :         as2js::node::pointer_t for_loop(std::make_shared<as2js::node>(as2js::node_t::NODE_FOR));
    3643           1 :         directive_list->append_child(for_loop);
    3644             : 
    3645             :         // { for( ... , ...
    3646           1 :         as2js::node::pointer_t init(std::make_shared<as2js::node>(as2js::node_t::NODE_LIST));
    3647           1 :         for_loop->append_child(init);
    3648             : 
    3649           1 :         as2js::node::pointer_t var1(std::make_shared<as2js::node>(as2js::node_t::NODE_VAR));
    3650           1 :         init->append_child(var1);
    3651             : 
    3652           1 :         as2js::node::pointer_t variable1(std::make_shared<as2js::node>(as2js::node_t::NODE_VARIABLE));
    3653           1 :         var1->append_child(variable1);
    3654             : 
    3655             :         // { for(i
    3656           1 :         as2js::node::pointer_t variable_name1(std::make_shared<as2js::node>(as2js::node_t::NODE_IDENTIFIER));
    3657           1 :         variable_name1->set_string("i");
    3658           1 :         variable1->append_child(variable_name1);
    3659             : 
    3660             :         // { for(i := 
    3661           1 :         as2js::node::pointer_t value1(std::make_shared<as2js::node>(as2js::node_t::NODE_SET));
    3662           1 :         variable1->append_child(value1);
    3663             : 
    3664             :         // { for(i := ... + ...
    3665           1 :         as2js::node::pointer_t add1(std::make_shared<as2js::node>(as2js::node_t::NODE_ADD));
    3666           1 :         value1->append_child(add1);
    3667             : 
    3668             :         // { for(i := a + ...
    3669           1 :         as2js::node::pointer_t var_a1(std::make_shared<as2js::node>(as2js::node_t::NODE_IDENTIFIER));
    3670           1 :         var_a1->set_string("a");
    3671           1 :         add1->append_child(var_a1);
    3672             : 
    3673             :         // { for(i := a + b
    3674           1 :         as2js::node::pointer_t var_b1(std::make_shared<as2js::node>(as2js::node_t::NODE_IDENTIFIER));
    3675           1 :         var_b1->set_string("b");
    3676           1 :         add1->append_child(var_b1);
    3677             : 
    3678             :         // { for(i := a + b, 
    3679           1 :         as2js::node::pointer_t var2(std::make_shared<as2js::node>(as2js::node_t::NODE_VAR));
    3680           1 :         init->append_child(var2);
    3681             : 
    3682           1 :         as2js::node::pointer_t variable2(std::make_shared<as2js::node>(as2js::node_t::NODE_VARIABLE));
    3683           1 :         var2->append_child(variable2);
    3684             : 
    3685             :         // { for(i := a + b, j
    3686           1 :         as2js::node::pointer_t variable_name2(std::make_shared<as2js::node>(as2js::node_t::NODE_IDENTIFIER));
    3687           1 :         variable_name2->set_string("j");
    3688           1 :         variable2->append_child(variable_name2);
    3689             : 
    3690             :         // { for(i := a + b, j := 
    3691           1 :         as2js::node::pointer_t value2(std::make_shared<as2js::node>(as2js::node_t::NODE_SET));
    3692           1 :         variable2->append_child(value2);
    3693             : 
    3694             :         // { for(i := a + b, j := ... / ...
    3695           1 :         as2js::node::pointer_t divide2(std::make_shared<as2js::node>(as2js::node_t::NODE_DIVIDE));
    3696           1 :         value2->append_child(divide2);
    3697             : 
    3698             :         // { for(i := a + b, j := c / ...
    3699           1 :         as2js::node::pointer_t var_a2(std::make_shared<as2js::node>(as2js::node_t::NODE_IDENTIFIER));
    3700           1 :         var_a2->set_string("c");
    3701           1 :         divide2->append_child(var_a2);
    3702             : 
    3703             :         // { for(i := a + b, j := c / d
    3704           1 :         as2js::node::pointer_t var_b2(std::make_shared<as2js::node>(as2js::node_t::NODE_IDENTIFIER));
    3705           1 :         var_b2->set_string("d");
    3706           1 :         divide2->append_child(var_b2);
    3707             : 
    3708             :         // { for(i := a + b, j := c / d; ... < ...
    3709           1 :         as2js::node::pointer_t less(std::make_shared<as2js::node>(as2js::node_t::NODE_LESS));
    3710           1 :         for_loop->append_child(less);
    3711             : 
    3712             :         // { for(i := a + b, j := c / d; i < ...
    3713           1 :         as2js::node::pointer_t var_i2(std::make_shared<as2js::node>(as2js::node_t::NODE_IDENTIFIER));
    3714           1 :         var_i2->set_string("i");
    3715           1 :         less->append_child(var_i2);
    3716             : 
    3717             :         // { for(i := a + b, j := c / d; i < 100;
    3718           1 :         as2js::node::pointer_t one_hunder(std::make_shared<as2js::node>(as2js::node_t::NODE_INTEGER));
    3719           1 :         one_hunder->set_integer(100);
    3720           1 :         less->append_child(one_hunder);
    3721             : 
    3722             :         // { for(i := a + b, j := c / d; i < 100; ++...)
    3723           1 :         as2js::node::pointer_t increment(std::make_shared<as2js::node>(as2js::node_t::NODE_INCREMENT));
    3724           1 :         for_loop->append_child(increment);
    3725             : 
    3726             :         // { for(i := a + b, j := c / d; i < 100; ++i)
    3727           1 :         as2js::node::pointer_t var_i3(std::make_shared<as2js::node>(as2js::node_t::NODE_IDENTIFIER));
    3728           1 :         var_i3->set_string("i");
    3729           1 :         increment->append_child(var_i3);
    3730             : 
    3731             :         // { for(i := a + b, j := c / d; i < 100; ++i) { ... } }
    3732           1 :         as2js::node::pointer_t block_list(std::make_shared<as2js::node>(as2js::node_t::NODE_DIRECTIVE_LIST));
    3733           1 :         for_loop->append_child(block_list);
    3734             : 
    3735             :         // { for(i := a + b, j := c / d; i < 100; ++i) { ...(...); } }
    3736           1 :         as2js::node::pointer_t func(std::make_shared<as2js::node>(as2js::node_t::NODE_CALL));
    3737           1 :         block_list->append_child(func);
    3738             : 
    3739             :         // { for(i := a + b, j := c / d; i < 100; ++i) { func(...); } }
    3740           1 :         as2js::node::pointer_t var_i4(std::make_shared<as2js::node>(as2js::node_t::NODE_IDENTIFIER));
    3741           1 :         var_i4->set_string("func");
    3742           1 :         func->append_child(var_i4);
    3743             : 
    3744             :         // { for(i := a + b, j := c / d; i < 100; ++i) { func(...); } }
    3745           1 :         as2js::node::pointer_t param_list(std::make_shared<as2js::node>(as2js::node_t::NODE_LIST));
    3746           1 :         func->append_child(param_list);
    3747             : 
    3748             :         // { for(i := a + b, j := c / d; i < 100; ++i) { func(i, ...); } }
    3749           1 :         as2js::node::pointer_t var_i5(std::make_shared<as2js::node>(as2js::node_t::NODE_IDENTIFIER));
    3750           1 :         var_i5->set_string("i");
    3751           1 :         param_list->append_child(var_i5);
    3752             : 
    3753             :         // { for(i := a + b, j := c / d; i < 100; ++i) { func(i, j); } }
    3754           1 :         as2js::node::pointer_t var_i6(std::make_shared<as2js::node>(as2js::node_t::NODE_IDENTIFIER));
    3755           1 :         var_i6->set_string("j");
    3756           1 :         param_list->append_child(var_i6);
    3757             : 
    3758             :         // since we have a tree with parents we can test an invalid parent
    3759             :         // which itself has a parent and get an error including the parent
    3760             :         // information
    3761           1 :         as2js::node::pointer_t test_list(std::make_shared<as2js::node>(as2js::node_t::NODE_DIRECTIVE_LIST));
    3762           3 :         CATCH_REQUIRE_THROWS_MATCHES(
    3763             :               test_list->set_parent(var_i5, 0)
    3764             :             , as2js::incompatible_type
    3765             :             , Catch::Matchers::ExceptionMessage(
    3766             :                       "as2js_exception: invalid type: \"IDENTIFIER\" used as a parent node of child with type: \"DIRECTIVE_LIST\"."));
    3767             : 
    3768             :         // the DEFINED attribute applies to all types of nodes so it is easy to
    3769             :         // use... (would the test benefit from testing other attributes?)
    3770           1 :         root->set_attribute_tree(as2js::attribute_t::NODE_ATTR_DEFINED, true);
    3771           1 :         CATCH_REQUIRE(root->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3772           1 :         CATCH_REQUIRE(directive_list->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3773           1 :         CATCH_REQUIRE(for_loop->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3774           1 :         CATCH_REQUIRE(init->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3775           1 :         CATCH_REQUIRE(var1->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3776           1 :         CATCH_REQUIRE(variable1->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3777           1 :         CATCH_REQUIRE(variable_name1->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3778           1 :         CATCH_REQUIRE(value1->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3779           1 :         CATCH_REQUIRE(add1->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3780           1 :         CATCH_REQUIRE(var_a1->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3781           1 :         CATCH_REQUIRE(var_b1->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3782           1 :         CATCH_REQUIRE(var2->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3783           1 :         CATCH_REQUIRE(variable2->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3784           1 :         CATCH_REQUIRE(variable_name2->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3785           1 :         CATCH_REQUIRE(value2->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3786           1 :         CATCH_REQUIRE(divide2->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3787           1 :         CATCH_REQUIRE(var_a2->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3788           1 :         CATCH_REQUIRE(var_b2->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3789           1 :         CATCH_REQUIRE(less->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3790           1 :         CATCH_REQUIRE(var_i2->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3791           1 :         CATCH_REQUIRE(one_hunder->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3792           1 :         CATCH_REQUIRE(increment->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3793           1 :         CATCH_REQUIRE(var_i3->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3794           1 :         CATCH_REQUIRE(block_list->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3795           1 :         CATCH_REQUIRE(func->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3796           1 :         CATCH_REQUIRE(var_i4->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3797           1 :         CATCH_REQUIRE(param_list->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3798           1 :         CATCH_REQUIRE(var_i5->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3799           1 :         CATCH_REQUIRE(var_i6->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3800             : 
    3801             :         // now test the clearing of the attribute
    3802           1 :         root->set_attribute_tree(as2js::attribute_t::NODE_ATTR_DEFINED, false);
    3803           1 :         CATCH_REQUIRE(!root->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3804           1 :         CATCH_REQUIRE(!directive_list->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3805           1 :         CATCH_REQUIRE(!for_loop->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3806           1 :         CATCH_REQUIRE(!init->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3807           1 :         CATCH_REQUIRE(!var1->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3808           1 :         CATCH_REQUIRE(!variable1->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3809           1 :         CATCH_REQUIRE(!variable_name1->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3810           1 :         CATCH_REQUIRE(!value1->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3811           1 :         CATCH_REQUIRE(!add1->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3812           1 :         CATCH_REQUIRE(!var_a1->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3813           1 :         CATCH_REQUIRE(!var_b1->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3814           1 :         CATCH_REQUIRE(!var2->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3815           1 :         CATCH_REQUIRE(!variable2->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3816           1 :         CATCH_REQUIRE(!variable_name2->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3817           1 :         CATCH_REQUIRE(!value2->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3818           1 :         CATCH_REQUIRE(!divide2->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3819           1 :         CATCH_REQUIRE(!var_a2->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3820           1 :         CATCH_REQUIRE(!var_b2->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3821           1 :         CATCH_REQUIRE(!less->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3822           1 :         CATCH_REQUIRE(!var_i2->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3823           1 :         CATCH_REQUIRE(!one_hunder->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3824           1 :         CATCH_REQUIRE(!increment->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3825           1 :         CATCH_REQUIRE(!var_i3->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3826           1 :         CATCH_REQUIRE(!block_list->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3827           1 :         CATCH_REQUIRE(!func->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3828           1 :         CATCH_REQUIRE(!var_i4->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3829           1 :         CATCH_REQUIRE(!param_list->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3830           1 :         CATCH_REQUIRE(!var_i5->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3831           1 :         CATCH_REQUIRE(!var_i6->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
    3832           1 :     }
    3833           1 :     CATCH_END_SECTION()
    3834           1 : }
    3835             : 
    3836             : 
    3837             : 
    3838             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.14