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

Generated by: LCOV version 1.14