LCOV - code coverage report
Current view: top level - lib - node_type.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 60 60 100.0 %
Date: 2014-11-22 Functions: 18 18 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* node_type.cpp -- written by Alexis WILKE for Made to Order Software Corp. (c) 2005-2014 */
       2             : 
       3             : /*
       4             : 
       5             : Copyright (c) 2005-2014 Made to Order Software Corp.
       6             : 
       7             : http://snapwebsites.org/project/as2js
       8             : 
       9             : Permission is hereby granted, free of charge, to any
      10             : person obtaining a copy of this software and
      11             : associated documentation files (the "Software"), to
      12             : deal in the Software without restriction, including
      13             : without limitation the rights to use, copy, modify,
      14             : merge, publish, distribute, sublicense, and/or sell
      15             : copies of the Software, and to permit persons to whom
      16             : the Software is furnished to do so, subject to the
      17             : following conditions:
      18             : 
      19             : The above copyright notice and this permission notice
      20             : shall be included in all copies or substantial
      21             : portions of the Software.
      22             : 
      23             : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
      24             : ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
      25             : LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
      26             : FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
      27             : EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
      28             : LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
      29             : WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
      30             : ARISING FROM, OUT OF OR IN CONNECTION WITH THE
      31             : SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      32             : SOFTWARE.
      33             : 
      34             : */
      35             : 
      36             : #include    "as2js/node.h"
      37             : 
      38             : #include    "as2js/exceptions.h"
      39             : 
      40             : 
      41             : /** \file
      42             :  * \brief Implement node type functions.
      43             :  *
      44             :  * This file includes the implementation of various functions that
      45             :  * directly work against the type of a node.
      46             :  *
      47             :  * It also includes a function one can use to convert a node_t
      48             :  * into a string.
      49             :  */
      50             : 
      51             : 
      52             : namespace as2js
      53             : {
      54             : 
      55             : 
      56             : 
      57             : /**********************************************************************/
      58             : /**********************************************************************/
      59             : /***  NODE  ***********************************************************/
      60             : /**********************************************************************/
      61             : /**********************************************************************/
      62             : 
      63             : 
      64             : /** \brief Private definitions of the node type.
      65             :  *
      66             :  * Local declarations defining a table of node types and their name so
      67             :  * we can convert a node type to a string. The main purpose of which is
      68             :  * to generate meaningful errors (i.e. 'had a problem with node type #38',
      69             :  * or 'had a problem with node of type "ABSTRACT"'.)
      70             :  */
      71             : namespace
      72             : {
      73             : 
      74             : /** \brief Structure used to define the name of each node type.
      75             :  *
      76             :  * This structure includes the node type and its name. Both are
      77             :  * used to convert a numeric type to a string so one can write
      78             :  * that string in error streams.
      79             :  */
      80             : struct type_name_t
      81             : {
      82             :     /** \brief The node type.
      83             :      *
      84             :      * The node type concerned by this entry.
      85             :      */
      86             :     Node::node_t    f_type;
      87             : 
      88             :     /** \brief The name of the node type.
      89             :      *
      90             :      * This pointer defines the name of the node type.
      91             :      */
      92             :     char const *    f_name;
      93             : 
      94             :     /** \brief The line number of the definition.
      95             :      *
      96             :      * This value defines the line number where the definition is found
      97             :      * in this file. It is useful for debug purposes.
      98             :      */
      99             :     int             f_line;
     100             : };
     101             : 
     102             : /** \brief Macro used to convert parameters into strings.
     103             :  *
     104             :  * \param[in] s  An identifier to be transformed in a string.
     105             :  */
     106             : #define    TO_STR_sub(s)            #s
     107             : 
     108             : /** \brief Macro used to add a named type to the table of node types.
     109             :  *
     110             :  * \warning
     111             :  * This macro cannot be used with the NODE_EOF type because the
     112             :  * identifier EOF is generally defined to -1 and it gets replaced
     113             :  * before the macro gets called resulting in an invalid definition.
     114             :  *
     115             :  * \warning
     116             :  * This macro cannot be used with the NODE_NULL type because the
     117             :  * identifier NULL is generally defined to 0 and it gets replaced
     118             :  * before the macro gets called resulting in an invalid definition.
     119             :  *
     120             :  * \param[in] node  The name of the node type as an identifier.
     121             :  */
     122             : #define    NODE_TYPE_NAME(node)     { Node::node_t::NODE_##node, TO_STR_sub(node), __LINE__ }
     123             : 
     124             : /** \brief List of node types with their name.
     125             :  *
     126             :  * This table defines a list of node types with their corresponding name
     127             :  * defined as a string. The definitions make use of the NODE_TYPE_NAME()
     128             :  * macro to better ensure validity of each entry (i.e. the identifier
     129             :  * used with the NODE_TYPE_NAME() is transformed to a NODE_... name and
     130             :  * the corresponding string make it impossible to have either
     131             :  * non-synchronized.)
     132             :  *
     133             :  * The table is sorted by type (node_t::NODE_...). In debug mode, the
     134             :  * type_to_string() function verifies that the order remains valid.
     135             :  */
     136             : type_name_t const g_node_type_name[] =
     137             : {
     138             :     // EOF is -1 on most C/C++ computers... so we have to do this one by hand
     139             :     { Node::node_t::NODE_EOF, "EOF", __LINE__ },
     140             :     NODE_TYPE_NAME(UNKNOWN),
     141             : 
     142             :     // the one character types have to be ordered by their character
     143             :     // which means it does not match the alphabetical order we
     144             :     // generally use
     145             :     NODE_TYPE_NAME(LOGICAL_NOT),                      // 0x21
     146             :     NODE_TYPE_NAME(MODULO),                           // 0x25
     147             :     NODE_TYPE_NAME(BITWISE_AND),                      // 0x26
     148             :     NODE_TYPE_NAME(OPEN_PARENTHESIS),                 // 0x28
     149             :     NODE_TYPE_NAME(CLOSE_PARENTHESIS),                // 0x29
     150             :     NODE_TYPE_NAME(MULTIPLY),                         // 0x2A
     151             :     NODE_TYPE_NAME(ADD),                              // 0x2B
     152             :     NODE_TYPE_NAME(COMMA),                            // 0x2C
     153             :     NODE_TYPE_NAME(SUBTRACT),                         // 0x2D
     154             :     NODE_TYPE_NAME(MEMBER),                           // 0x2E
     155             :     NODE_TYPE_NAME(DIVIDE),                           // 0x2F
     156             :     NODE_TYPE_NAME(COLON),                            // 0x3A
     157             :     NODE_TYPE_NAME(SEMICOLON),                        // 0x3B
     158             :     NODE_TYPE_NAME(LESS),                             // 0x3C
     159             :     NODE_TYPE_NAME(ASSIGNMENT),                       // 0x3D
     160             :     NODE_TYPE_NAME(GREATER),                          // 0x3E
     161             :     NODE_TYPE_NAME(CONDITIONAL),                      // 0x3F
     162             :     NODE_TYPE_NAME(OPEN_SQUARE_BRACKET),              // 0x5B
     163             :     NODE_TYPE_NAME(CLOSE_SQUARE_BRACKET),             // 0x5D
     164             :     NODE_TYPE_NAME(BITWISE_XOR),                      // 0x5E
     165             :     NODE_TYPE_NAME(OPEN_CURVLY_BRACKET),              // 0x7B
     166             :     NODE_TYPE_NAME(BITWISE_OR),                       // 0x7C
     167             :     NODE_TYPE_NAME(CLOSE_CURVLY_BRACKET),             // 0x7D
     168             :     NODE_TYPE_NAME(BITWISE_NOT),                      // 0x7E
     169             : 
     170             :     NODE_TYPE_NAME(ABSTRACT),
     171             :     NODE_TYPE_NAME(ARRAY),
     172             :     NODE_TYPE_NAME(ARRAY_LITERAL),
     173             :     NODE_TYPE_NAME(AS),
     174             :     NODE_TYPE_NAME(ASSIGNMENT_ADD),
     175             :     NODE_TYPE_NAME(ASSIGNMENT_BITWISE_AND),
     176             :     NODE_TYPE_NAME(ASSIGNMENT_BITWISE_OR),
     177             :     NODE_TYPE_NAME(ASSIGNMENT_BITWISE_XOR),
     178             :     NODE_TYPE_NAME(ASSIGNMENT_DIVIDE),
     179             :     NODE_TYPE_NAME(ASSIGNMENT_LOGICAL_AND),
     180             :     NODE_TYPE_NAME(ASSIGNMENT_LOGICAL_OR),
     181             :     NODE_TYPE_NAME(ASSIGNMENT_LOGICAL_XOR),
     182             :     NODE_TYPE_NAME(ASSIGNMENT_MAXIMUM),
     183             :     NODE_TYPE_NAME(ASSIGNMENT_MINIMUM),
     184             :     NODE_TYPE_NAME(ASSIGNMENT_MODULO),
     185             :     NODE_TYPE_NAME(ASSIGNMENT_MULTIPLY),
     186             :     NODE_TYPE_NAME(ASSIGNMENT_POWER),
     187             :     NODE_TYPE_NAME(ASSIGNMENT_ROTATE_LEFT),
     188             :     NODE_TYPE_NAME(ASSIGNMENT_ROTATE_RIGHT),
     189             :     NODE_TYPE_NAME(ASSIGNMENT_SHIFT_LEFT),
     190             :     NODE_TYPE_NAME(ASSIGNMENT_SHIFT_RIGHT),
     191             :     NODE_TYPE_NAME(ASSIGNMENT_SHIFT_RIGHT_UNSIGNED),
     192             :     NODE_TYPE_NAME(ASSIGNMENT_SUBTRACT),
     193             :     NODE_TYPE_NAME(ATTRIBUTES),
     194             :     NODE_TYPE_NAME(AUTO),
     195             :     NODE_TYPE_NAME(BOOLEAN),
     196             :     NODE_TYPE_NAME(BREAK),
     197             :     NODE_TYPE_NAME(BYTE),
     198             :     NODE_TYPE_NAME(CALL),
     199             :     NODE_TYPE_NAME(CASE),
     200             :     NODE_TYPE_NAME(CATCH),
     201             :     NODE_TYPE_NAME(CHAR),
     202             :     NODE_TYPE_NAME(CLASS),
     203             :     NODE_TYPE_NAME(COMPARE),
     204             :     NODE_TYPE_NAME(CONST),
     205             :     NODE_TYPE_NAME(CONTINUE),
     206             :     NODE_TYPE_NAME(DEBUGGER),
     207             :     NODE_TYPE_NAME(DECREMENT),
     208             :     NODE_TYPE_NAME(DEFAULT),
     209             :     NODE_TYPE_NAME(DELETE),
     210             :     NODE_TYPE_NAME(DIRECTIVE_LIST),
     211             :     NODE_TYPE_NAME(DO),
     212             :     NODE_TYPE_NAME(DOUBLE),
     213             :     NODE_TYPE_NAME(ELSE),
     214             :     NODE_TYPE_NAME(EMPTY),
     215             :     NODE_TYPE_NAME(ENSURE),
     216             :     NODE_TYPE_NAME(ENUM),
     217             :     NODE_TYPE_NAME(EQUAL),
     218             :     NODE_TYPE_NAME(EXCLUDE),
     219             :     NODE_TYPE_NAME(EXTENDS),
     220             :     NODE_TYPE_NAME(EXPORT),
     221             :     NODE_TYPE_NAME(FALSE),
     222             :     NODE_TYPE_NAME(FINAL),
     223             :     NODE_TYPE_NAME(FINALLY),
     224             :     NODE_TYPE_NAME(FLOAT),
     225             :     NODE_TYPE_NAME(FLOAT64),
     226             :     NODE_TYPE_NAME(FOR),
     227             :     NODE_TYPE_NAME(FUNCTION),
     228             :     NODE_TYPE_NAME(GOTO),
     229             :     NODE_TYPE_NAME(GREATER_EQUAL),
     230             :     NODE_TYPE_NAME(IDENTIFIER),
     231             :     NODE_TYPE_NAME(IF),
     232             :     NODE_TYPE_NAME(IMPLEMENTS),
     233             :     NODE_TYPE_NAME(IMPORT),
     234             :     NODE_TYPE_NAME(IN),
     235             :     NODE_TYPE_NAME(INCLUDE),
     236             :     NODE_TYPE_NAME(INCREMENT),
     237             :     NODE_TYPE_NAME(INLINE),
     238             :     NODE_TYPE_NAME(INSTANCEOF),
     239             :     NODE_TYPE_NAME(INT64),
     240             :     NODE_TYPE_NAME(INTERFACE),
     241             :     NODE_TYPE_NAME(INVARIANT),
     242             :     NODE_TYPE_NAME(IS),
     243             :     NODE_TYPE_NAME(LABEL),
     244             :     NODE_TYPE_NAME(LESS_EQUAL),
     245             :     NODE_TYPE_NAME(LIST),
     246             :     NODE_TYPE_NAME(LOGICAL_AND),
     247             :     NODE_TYPE_NAME(LOGICAL_OR),
     248             :     NODE_TYPE_NAME(LOGICAL_XOR),
     249             :     NODE_TYPE_NAME(LONG),
     250             :     NODE_TYPE_NAME(MATCH),
     251             :     NODE_TYPE_NAME(MAXIMUM),
     252             :     NODE_TYPE_NAME(MINIMUM),
     253             :     NODE_TYPE_NAME(NAME),
     254             :     NODE_TYPE_NAME(NAMESPACE),
     255             :     NODE_TYPE_NAME(NATIVE),
     256             :     NODE_TYPE_NAME(NEW),
     257             :     NODE_TYPE_NAME(NOT_EQUAL),
     258             :     NODE_TYPE_NAME(NOT_MATCH),
     259             :     //NODE_TYPE_NAME(NULL), -- macro does not work in this case
     260             :     { Node::node_t::NODE_NULL, "NULL", __LINE__ },
     261             :     NODE_TYPE_NAME(OBJECT_LITERAL),
     262             :     NODE_TYPE_NAME(PACKAGE),
     263             :     NODE_TYPE_NAME(PARAM),
     264             :     NODE_TYPE_NAME(PARAMETERS),
     265             :     NODE_TYPE_NAME(PARAM_MATCH),
     266             :     NODE_TYPE_NAME(POST_DECREMENT),
     267             :     NODE_TYPE_NAME(POST_INCREMENT),
     268             :     NODE_TYPE_NAME(POWER),
     269             :     NODE_TYPE_NAME(PRIVATE),
     270             :     NODE_TYPE_NAME(PROGRAM),
     271             :     NODE_TYPE_NAME(PROTECTED),
     272             :     NODE_TYPE_NAME(PUBLIC),
     273             :     NODE_TYPE_NAME(RANGE),
     274             :     NODE_TYPE_NAME(REGULAR_EXPRESSION),
     275             :     NODE_TYPE_NAME(REQUIRE),
     276             :     NODE_TYPE_NAME(REST),
     277             :     NODE_TYPE_NAME(RETURN),
     278             :     NODE_TYPE_NAME(ROOT),
     279             :     NODE_TYPE_NAME(ROTATE_LEFT),
     280             :     NODE_TYPE_NAME(ROTATE_RIGHT),
     281             :     NODE_TYPE_NAME(SCOPE),
     282             :     NODE_TYPE_NAME(SET),
     283             :     NODE_TYPE_NAME(SHIFT_LEFT),
     284             :     NODE_TYPE_NAME(SHIFT_RIGHT),
     285             :     NODE_TYPE_NAME(SHIFT_RIGHT_UNSIGNED),
     286             :     NODE_TYPE_NAME(SHORT),
     287             :     NODE_TYPE_NAME(SMART_MATCH),
     288             :     NODE_TYPE_NAME(STATIC),
     289             :     NODE_TYPE_NAME(STRICTLY_EQUAL),
     290             :     NODE_TYPE_NAME(STRICTLY_NOT_EQUAL),
     291             :     NODE_TYPE_NAME(STRING),
     292             :     NODE_TYPE_NAME(SUPER),
     293             :     NODE_TYPE_NAME(SWITCH),
     294             :     NODE_TYPE_NAME(SYNCHRONIZED),
     295             :     NODE_TYPE_NAME(THEN),
     296             :     NODE_TYPE_NAME(THIS),
     297             :     NODE_TYPE_NAME(THROW),
     298             :     NODE_TYPE_NAME(THROWS),
     299             :     NODE_TYPE_NAME(TRANSIENT),
     300             :     NODE_TYPE_NAME(TRUE),
     301             :     NODE_TYPE_NAME(TRY),
     302             :     NODE_TYPE_NAME(TYPE),
     303             :     NODE_TYPE_NAME(TYPEOF),
     304             :     NODE_TYPE_NAME(UNDEFINED),
     305             :     NODE_TYPE_NAME(USE),
     306             :     NODE_TYPE_NAME(VAR),
     307             :     NODE_TYPE_NAME(VARIABLE),
     308             :     NODE_TYPE_NAME(VAR_ATTRIBUTES),
     309             :     NODE_TYPE_NAME(VIDENTIFIER),
     310             :     NODE_TYPE_NAME(VOID),
     311             :     NODE_TYPE_NAME(VOLATILE),
     312             :     NODE_TYPE_NAME(WHILE),
     313             :     NODE_TYPE_NAME(WITH),
     314             :     NODE_TYPE_NAME(YIELD),
     315             : };
     316             : 
     317             : /** \brief Define the size of the node type table.
     318             :  *
     319             :  * This parameter represents the number of node type structures. 
     320             :  */
     321             : size_t const g_node_type_name_size = sizeof(g_node_type_name) / sizeof(g_node_type_name[0]);
     322             : 
     323             : 
     324             : }
     325             : // no name namespace
     326             : 
     327             : 
     328             : /** \brief Retrieve the type of the node.
     329             :  *
     330             :  * This function gets the type of the node and returns it. The type
     331             :  * is one of the node_t::NODE_... values.
     332             :  *
     333             :  * Note the value of the node types are not all sequencial. The lower
     334             :  * portion used one to one with characters has many sparse places.
     335             :  * However, the Node constructor ensures that only valid types get
     336             :  * used.
     337             :  *
     338             :  * There are some functions available to convert a certain number of
     339             :  * Node types. These are used by the compiler and optimizer to
     340             :  * implement their functionality.
     341             :  *
     342             :  * \li to_unknown() -- change any node to NODE_UNKNOWN
     343             :  * \li to_as() -- change a NODE_CALL to a NODE_AS
     344             :  * \li to_boolean_type_only() -- check whether a node represents NODE_TRUE
     345             :  *                               or NODE_FALSE
     346             :  * \li to_boolean() -- change to a NODE_TRUE or NODE_FALSE if possible
     347             :  * \li to_call() -- change a getter or setter to a NODE_CALL
     348             :  * \li to_int64() -- force a number to a NODE_INT64
     349             :  * \li to_float64() -- force a number to a NODE_FLOAT64
     350             :  * \li to_number() -- change a string to a NODE_FLOAT64
     351             :  * \li to_string() -- change a number to a NODE_STRING
     352             :  * \li to_videntifier() -- change a NODE_IDENTIFIER to a NODE_VIDENTIFIER
     353             :  * \li to_var_attributes() -- change a NODE_VARIABLE to a NODE_VAR_ATTRIBUTES
     354             :  *
     355             :  * \return The current type of the node.
     356             :  *
     357             :  * \sa to_unknown()
     358             :  * \sa to_as()
     359             :  * \sa to_boolean()
     360             :  * \sa to_call()
     361             :  * \sa to_int64()
     362             :  * \sa to_float64()
     363             :  * \sa to_number()
     364             :  * \sa to_string()
     365             :  * \sa to_videntifier()
     366             :  * \sa to_var_attributes()
     367             :  * \sa set_boolean()
     368             :  */
     369   344455196 : Node::node_t Node::get_type() const
     370             : {
     371   344455196 :     return f_type;
     372             : }
     373             : 
     374             : 
     375             : /** \brief Convert the specified type to a string.
     376             :  *
     377             :  * The type of a Node (node_t::NODE_...) can be retrieved as
     378             :  * a string using this function. In pretty much all cases this
     379             :  * is done whenever an error occurs and not in normal circumstances.
     380             :  * It is also used to debug the node tree.
     381             :  *
     382             :  * Note that if you have a node, you probably want to call
     383             :  * get_type_name() instead.
     384             :  *
     385             :  * \exception exception_internal_error
     386             :  * If the table of node type to name is invalid, then we raise
     387             :  * this exception. Also, if the \p type parameter is not a valid
     388             :  * type (i.e. NODE_max, or an undefined number such as 999) then
     389             :  * this exception is also generated. Calling this function with
     390             :  * an invalid should not happen when you use the get_type_name()
     391             :  * function since the Node constructor prevents the use of invalid
     392             :  * node types when creating nodes.
     393             :  *
     394             :  * \return A null terminated C-like string with the node name.
     395             :  *
     396             :  * \sa get_type_name()
     397             :  */
     398    24183327 : char const *Node::type_to_string(node_t type)
     399             : {
     400             : #if defined(_DEBUG) || defined(DEBUG)
     401             :     {
     402             :         // make sure that the node types are properly sorted
     403             :         static bool checked = false;
     404    24183327 :         if(!checked)
     405             :         {
     406             :             // check only once
     407           1 :             checked = true;
     408         170 :             for(size_t idx = 1; idx < g_node_type_name_size; ++idx)
     409             :             {
     410         169 :                 if(g_node_type_name[idx].f_type <= g_node_type_name[idx - 1].f_type)
     411             :                 {
     412             :                     // if the table is properly defined then we cannot reach
     413             :                     // these lines
     414             :                     std::cerr << "INTERNAL ERROR at offset " << idx                                                     // LCOV_EXCL_LINE
     415             :                               << " (line #" << g_node_type_name[idx].f_line                                             // LCOV_EXCL_LINE
     416             :                               << ", node type " << static_cast<uint32_t>(g_node_type_name[idx].f_type)                  // LCOV_EXCL_LINE
     417             :                               << " vs. " << static_cast<uint32_t>(g_node_type_name[idx - 1].f_type)                     // LCOV_EXCL_LINE
     418             :                               << "): the g_node_type_name table is not sorted properly. We cannot binary search it."    // LCOV_EXCL_LINE
     419             :                               << std::endl;                                                                             // LCOV_EXCL_LINE
     420             :                     throw exception_internal_error("INTERNAL ERROR: node type names not properly sorted, cannot properly search for names using a binary search."); // LCOV_EXCL_LINE
     421             :                 }
     422             :             }
     423             :         }
     424             :     }
     425             : #endif
     426             : 
     427    24183327 :     size_t i(0);
     428    24183327 :     size_t j(g_node_type_name_size);
     429   192167056 :     while(i < j)
     430             :     {
     431   167983729 :         size_t p((j - i) / 2 + i);
     432   167983729 :         int r(static_cast<int>(g_node_type_name[p].f_type) - static_cast<int>(static_cast<node_t>(type)));
     433   167983729 :         if(r == 0)
     434             :         {
     435    48366654 :             return g_node_type_name[p].f_name;
     436             :         }
     437   143800402 :         if(r < 0)
     438             :         {
     439    59137282 :             i = p + 1;
     440             :         }
     441             :         else
     442             :         {
     443    84663120 :             j = p;
     444             :         }
     445             :     }
     446             : 
     447             :     throw exception_internal_error("INTERNAL ERROR: node type name not found!?."); // LCOV_EXCL_LINE
     448             : }
     449             : 
     450             : 
     451             : /** \brief Retrieve the type of this node.
     452             :  *
     453             :  * This function retrieves the type of this node.
     454             :  *
     455             :  * This function is equivalent to:
     456             :  *
     457             :  * \code
     458             :  *      char const *name(Node::type_to_string(node->get_type()));
     459             :  * \endcode
     460             :  *
     461             :  * \return The type of this node as a string.
     462             :  *
     463             :  * \sa type_to_string()
     464             :  */
     465    24134175 : char const *Node::get_type_name() const
     466             : {
     467    24134175 :     return type_to_string(f_type);
     468             : }
     469             : 
     470             : 
     471             : /** \brief Return true if Node represents a number.
     472             :  *
     473             :  * This function returns true if the node is an integer or a
     474             :  * floating point value. This is tested using the Node type
     475             :  * which should either be NODE_INT64 or NODE_FLOAT64.
     476             :  *
     477             :  * Note that means this function returns false on a string that
     478             :  * represents a valid number.
     479             :  *
     480             :  * Note that JavaScript also considered Boolean values and null as
     481             :  * valid numbers. To test such, use is_nan() instead.
     482             :  *
     483             :  * \return true if this node represents a number
     484             :  *
     485             :  * \sa is_nan()
     486             :  * \sa is_int64()
     487             :  * \sa is_boolean()
     488             :  * \sa is_float64()
     489             :  * \sa is_true()
     490             :  * \sa is_false()
     491             :  * \sa is_string()
     492             :  * \sa is_undefined()
     493             :  * \sa is_null()
     494             :  * \sa is_identifier()
     495             :  * \sa is_literal()
     496             :  */
     497         342 : bool Node::is_number() const
     498             : {
     499         342 :     return f_type == node_t::NODE_INT64 || f_type == node_t::NODE_FLOAT64;
     500             : }
     501             : 
     502             : 
     503             : /** \brief Check whether this node represents a NaN if converted to a number.
     504             :  *
     505             :  * When converting a node to a number (to_number() function) we accept a
     506             :  * certain number of parameters as numbers:
     507             :  *
     508             :  * \li integers (unchanged)
     509             :  * \li float points (unchanged)
     510             :  * \li true (1) or false (0)
     511             :  * \li null (0)
     512             :  * \li strings that represent valid numbers as a whole
     513             :  * \li undefined (NaN)
     514             :  *
     515             :  * \return true if the value could not be converted to a number other than NaN.
     516             :  *
     517             :  * \sa is_number()
     518             :  * \sa is_int64()
     519             :  * \sa is_boolean()
     520             :  * \sa is_float64()
     521             :  * \sa is_true()
     522             :  * \sa is_false()
     523             :  * \sa is_string()
     524             :  * \sa is_undefined()
     525             :  * \sa is_null()
     526             :  * \sa is_identifier()
     527             :  * \sa is_literal()
     528             :  */
     529         505 : bool Node::is_nan() const
     530             : {
     531         505 :     if(f_type == node_t::NODE_STRING)
     532             :     {
     533           3 :         return f_str.is_number();
     534             :     }
     535             : 
     536         502 :     return f_type != node_t::NODE_INT64
     537         500 :         && f_type != node_t::NODE_FLOAT64
     538         498 :         && f_type != node_t::NODE_TRUE
     539         496 :         && f_type != node_t::NODE_FALSE
     540         996 :         && f_type != node_t::NODE_NULL;
     541             : }
     542             : 
     543             : 
     544             : /** \brief Check whether a node is an integer.
     545             :  *
     546             :  * This function checks whether the type of the node is NODE_INT64.
     547             :  *
     548             :  * \return true if the node type is NODE_INT64.
     549             :  *
     550             :  * \sa is_number()
     551             :  * \sa is_boolean()
     552             :  * \sa is_float64()
     553             :  * \sa is_nan()
     554             :  * \sa is_true()
     555             :  * \sa is_false()
     556             :  * \sa is_string()
     557             :  * \sa is_undefined()
     558             :  * \sa is_null()
     559             :  * \sa is_identifier()
     560             :  * \sa is_literal()
     561             :  */
     562         373 : bool Node::is_int64() const
     563             : {
     564         373 :     return f_type == node_t::NODE_INT64;
     565             : }
     566             : 
     567             : 
     568             : /** \brief Check whether a node is a floating point.
     569             :  *
     570             :  * This function checks whether the type of the node is NODE_FLOAT64.
     571             :  *
     572             :  * \return true if the node type is NODE_FLOAT64.
     573             :  *
     574             :  * \sa is_number()
     575             :  * \sa is_boolean()
     576             :  * \sa is_int64()
     577             :  * \sa is_nan()
     578             :  * \sa is_true()
     579             :  * \sa is_false()
     580             :  * \sa is_string()
     581             :  * \sa is_undefined()
     582             :  * \sa is_null()
     583             :  * \sa is_identifier()
     584             :  * \sa is_literal()
     585             :  */
     586         351 : bool Node::is_float64() const
     587             : {
     588         351 :     return f_type == node_t::NODE_FLOAT64;
     589             : }
     590             : 
     591             : 
     592             : /** \brief Check whether a node is a Boolean value.
     593             :  *
     594             :  * This function checks whether the type of the node is NODE_TRUE or
     595             :  * NODE_FALSE.
     596             :  *
     597             :  * \return true if the node type represents a boolean value.
     598             :  *
     599             :  * \sa is_number()
     600             :  * \sa is_int64()
     601             :  * \sa is_float64()
     602             :  * \sa is_nan()
     603             :  * \sa is_true()
     604             :  * \sa is_false()
     605             :  * \sa is_string()
     606             :  * \sa is_undefined()
     607             :  * \sa is_null()
     608             :  * \sa is_identifier()
     609             :  * \sa is_literal()
     610             :  */
     611         342 : bool Node::is_boolean() const
     612             : {
     613         342 :     return f_type == node_t::NODE_TRUE || f_type == node_t::NODE_FALSE;
     614             : }
     615             : 
     616             : 
     617             : /** \brief Check whether a node represents the true Boolean value.
     618             :  *
     619             :  * This function checks whether the type of the node is NODE_TRUE.
     620             :  *
     621             :  * \return true if the node type represents true.
     622             :  *
     623             :  * \sa is_number()
     624             :  * \sa is_int64()
     625             :  * \sa is_float64()
     626             :  * \sa is_nan()
     627             :  * \sa is_boolean()
     628             :  * \sa is_false()
     629             :  * \sa is_string()
     630             :  * \sa is_undefined()
     631             :  * \sa is_null()
     632             :  * \sa is_identifier()
     633             :  * \sa is_literal()
     634             :  */
     635         341 : bool Node::is_true() const
     636             : {
     637         341 :     return f_type == node_t::NODE_TRUE;
     638             : }
     639             : 
     640             : 
     641             : /** \brief Check whether a node represents the false Boolean value.
     642             :  *
     643             :  * This function checks whether the type of the node is NODE_FALSE.
     644             :  *
     645             :  * \return true if the node type represents false.
     646             :  *
     647             :  * \sa is_number()
     648             :  * \sa is_int64()
     649             :  * \sa is_float64()
     650             :  * \sa is_nan()
     651             :  * \sa is_boolean()
     652             :  * \sa is_true()
     653             :  * \sa is_string()
     654             :  * \sa is_undefined()
     655             :  * \sa is_null()
     656             :  * \sa is_identifier()
     657             :  * \sa is_literal()
     658             :  */
     659         341 : bool Node::is_false() const
     660             : {
     661         341 :     return f_type == node_t::NODE_FALSE;
     662             : }
     663             : 
     664             : 
     665             : /** \brief Check whether a node is a string.
     666             :  *
     667             :  * This function checks whether the type of the node is NODE_STRING.
     668             :  *
     669             :  * \return true if the node type represents a string value.
     670             :  *
     671             :  * \sa is_number()
     672             :  * \sa is_int64()
     673             :  * \sa is_float64()
     674             :  * \sa is_nan()
     675             :  * \sa is_boolean()
     676             :  * \sa is_true()
     677             :  * \sa is_false()
     678             :  * \sa is_undefined()
     679             :  * \sa is_null()
     680             :  * \sa is_identifier()
     681             :  * \sa is_literal()
     682             :  */
     683         341 : bool Node::is_string() const
     684             : {
     685         341 :     return f_type == node_t::NODE_STRING;
     686             : }
     687             : 
     688             : 
     689             : /** \brief Check whether a node is the special value undefined.
     690             :  *
     691             :  * This function checks whether the type of the node is NODE_UNDEFINED.
     692             :  *
     693             :  * \return true if the node type represents the undefined value.
     694             :  *
     695             :  * \sa is_number()
     696             :  * \sa is_int64()
     697             :  * \sa is_float64()
     698             :  * \sa is_nan()
     699             :  * \sa is_boolean()
     700             :  * \sa is_true()
     701             :  * \sa is_false()
     702             :  * \sa is_string()
     703             :  * \sa is_null()
     704             :  * \sa is_identifier()
     705             :  * \sa is_literal()
     706             :  */
     707         341 : bool Node::is_undefined() const
     708             : {
     709         341 :     return f_type == node_t::NODE_UNDEFINED;
     710             : }
     711             : 
     712             : 
     713             : /** \brief Check whether a node is the special value null.
     714             :  *
     715             :  * This function checks whether the type of the node is NODE_NULL.
     716             :  *
     717             :  * \return true if the node type represents the null value.
     718             :  *
     719             :  * \sa is_number()
     720             :  * \sa is_int64()
     721             :  * \sa is_float64()
     722             :  * \sa is_nan()
     723             :  * \sa is_boolean()
     724             :  * \sa is_true()
     725             :  * \sa is_false()
     726             :  * \sa is_string()
     727             :  * \sa is_undefined()
     728             :  * \sa is_identifier()
     729             :  * \sa is_literal()
     730             :  */
     731         341 : bool Node::is_null() const
     732             : {
     733         341 :     return f_type == node_t::NODE_NULL;
     734             : }
     735             : 
     736             : 
     737             : /** \brief Check whether a node is an identifier.
     738             :  *
     739             :  * This function checks whether the type of the node is NODE_IDENTIFIER
     740             :  * or NODE_VIDENTIFIER.
     741             :  *
     742             :  * \return true if the node type represents an identifier value.
     743             :  *
     744             :  * \sa is_number()
     745             :  * \sa is_int64()
     746             :  * \sa is_float64()
     747             :  * \sa is_nan()
     748             :  * \sa is_boolean()
     749             :  * \sa is_true()
     750             :  * \sa is_false()
     751             :  * \sa is_string()
     752             :  * \sa is_undefined()
     753             :  * \sa is_null()
     754             :  * \sa is_literal()
     755             :  */
     756         342 : bool Node::is_identifier() const
     757             : {
     758         342 :     return f_type == node_t::NODE_IDENTIFIER || f_type == node_t::NODE_VIDENTIFIER;
     759             : }
     760             : 
     761             : 
     762             : /** \brief Check whether this node represents a literal.
     763             :  *
     764             :  * Literals are:
     765             :  *
     766             :  * \li true or false
     767             :  * \li floating point
     768             :  * \li integer
     769             :  * \li null
     770             :  * \li string
     771             :  * \li undefined
     772             :  *
     773             :  * If this node represents any one of those types, this function
     774             :  * returns true.
     775             :  *
     776             :  * \return true if the node is a literal.
     777             :  *
     778             :  * \sa is_number()
     779             :  * \sa is_int64()
     780             :  * \sa is_float64()
     781             :  * \sa is_nan()
     782             :  * \sa is_boolean()
     783             :  * \sa is_true()
     784             :  * \sa is_false()
     785             :  * \sa is_string()
     786             :  * \sa is_undefined()
     787             :  * \sa is_null()
     788             :  * \sa is_identifier()
     789             :  */
     790        3154 : bool Node::is_literal() const
     791             : {
     792        3154 :     switch(f_type)
     793             :     {
     794             :     case node_t::NODE_FALSE:
     795             :     case node_t::NODE_FLOAT64:
     796             :     case node_t::NODE_INT64:
     797             :     case node_t::NODE_NULL:
     798             :     case node_t::NODE_STRING:
     799             :     case node_t::NODE_TRUE:
     800             :     case node_t::NODE_UNDEFINED:
     801        1524 :         return true;
     802             : 
     803             :     default:
     804        1630 :         return false;
     805             : 
     806             :     }
     807             : }
     808             : 
     809             : 
     810             : /** \brief Check whether a node has side effects.
     811             :  *
     812             :  * This function checks whether a node, or any of its children, has a
     813             :  * side effect.
     814             :  *
     815             :  * Having a side effect means that the function of the node is to modify
     816             :  * something. For example an assignment modifies its destination which
     817             :  * is an obvious side effect. The following node types are viewed as
     818             :  * having a side effects:
     819             :  *
     820             :  * \li NODE_ASSIGNMENT[_...] -- all the assignment
     821             :  * \li NODE_CALL -- a function call
     822             :  * \li NODE_DECREMENT -- the '--' operator
     823             :  * \li NODE_DELETE -- the 'delete' operator
     824             :  * \li NODE_INCREMENT -- the '++' operator
     825             :  * \li NODE_NEW -- the 'new' operator
     826             :  * \li NODE_POST_DECREMENT -- the '--' operator
     827             :  * \li NODE_POST_INCREMENT -- the '++' operator
     828             :  *
     829             :  * The test is run against this node and all of its children because if
     830             :  * any one node implies a modification, the tree as a whole implies a
     831             :  * modification and thus the function must return true.
     832             :  *
     833             :  * For optimizations, we will still be able to remove nodes wrapping
     834             :  * nodes that have side effects. For example the following optimization
     835             :  * is perfectly valid:
     836             :  *
     837             :  * \code
     838             :  *      a + (b = 3);
     839             :  *      // can be optimized to
     840             :  *      b = 3;
     841             :  * \endcode
     842             :  *
     843             :  * The one reason the previous statement may not be optimizable is if
     844             :  * 'a' represents an object which has the '+' (addition) operator
     845             :  * defined. Anyway, in that case the optimizer sees the following code
     846             :  * which cannot be optimized:
     847             :  *
     848             :  * \code
     849             :  *      a.operator_add(b = 3);
     850             :  * \endcode
     851             :  *
     852             :  * \return true if this node has a side effect.
     853             :  */
     854         407 : bool Node::has_side_effects() const
     855             : {
     856             :     //
     857             :     // Well... I'm wondering if we can really
     858             :     // trust this current version.
     859             :     //
     860             :     // Problem I:
     861             :     //    some identifiers can be getters and
     862             :     //    they can have side effects; though
     863             :     //    a getter should be considered constant
     864             :     //    toward the object being read and thus
     865             :     //    it should be fine in 99% of cases
     866             :     //    [imagine a serial number generator
     867             :     //    though...]
     868             :     //
     869             :     // Problem II:
     870             :     //    some operators may not have been
     871             :     //    compiled yet and they could have
     872             :     //    side effects too; now this is much
     873             :     //    less likely a problem because then
     874             :     //    the programmer is most certainly
     875             :     //    creating a really weird program
     876             :     //    with all sorts of side effects that
     877             :     //    he wants no one else to know about,
     878             :     //    etc. etc. etc.
     879             :     //
     880             :     // Problem III:
     881             :     //    Note that we do not memorize whether
     882             :     //    a node has side effects because its
     883             :     //    children may change and then side
     884             :     //    effects may appear and disappear.
     885             :     //
     886             : 
     887         407 :     switch(f_type)
     888             :     {
     889             :     case node_t::NODE_ASSIGNMENT:
     890             :     case node_t::NODE_ASSIGNMENT_ADD:
     891             :     case node_t::NODE_ASSIGNMENT_BITWISE_AND:
     892             :     case node_t::NODE_ASSIGNMENT_BITWISE_OR:
     893             :     case node_t::NODE_ASSIGNMENT_BITWISE_XOR:
     894             :     case node_t::NODE_ASSIGNMENT_DIVIDE:
     895             :     case node_t::NODE_ASSIGNMENT_LOGICAL_AND:
     896             :     case node_t::NODE_ASSIGNMENT_LOGICAL_OR:
     897             :     case node_t::NODE_ASSIGNMENT_LOGICAL_XOR:
     898             :     case node_t::NODE_ASSIGNMENT_MAXIMUM:
     899             :     case node_t::NODE_ASSIGNMENT_MINIMUM:
     900             :     case node_t::NODE_ASSIGNMENT_MODULO:
     901             :     case node_t::NODE_ASSIGNMENT_MULTIPLY:
     902             :     case node_t::NODE_ASSIGNMENT_POWER:
     903             :     case node_t::NODE_ASSIGNMENT_ROTATE_LEFT:
     904             :     case node_t::NODE_ASSIGNMENT_ROTATE_RIGHT:
     905             :     case node_t::NODE_ASSIGNMENT_SHIFT_LEFT:
     906             :     case node_t::NODE_ASSIGNMENT_SHIFT_RIGHT:
     907             :     case node_t::NODE_ASSIGNMENT_SHIFT_RIGHT_UNSIGNED:
     908             :     case node_t::NODE_ASSIGNMENT_SUBTRACT:
     909             :     case node_t::NODE_CALL:
     910             :     case node_t::NODE_DECREMENT:
     911             :     case node_t::NODE_DELETE:
     912             :     case node_t::NODE_INCREMENT:
     913             :     case node_t::NODE_NEW:
     914             :     case node_t::NODE_POST_DECREMENT:
     915             :     case node_t::NODE_POST_INCREMENT:
     916          88 :         return true;
     917             : 
     918             :     //case NODE_IDENTIFIER:
     919             :     //
     920             :     // TODO: Test whether this is a reference to a [sg]etter
     921             :     //       function (needs to be compiled already...)
     922             :     //    
     923             :     //    break;
     924             : 
     925             :     default:
     926         319 :         break;
     927             : 
     928             :     }
     929             : 
     930         328 :     for(size_t idx(0); idx < f_children.size(); ++idx)
     931             :     {
     932          15 :         if(f_children[idx] && f_children[idx]->has_side_effects())
     933             :         {
     934           6 :             return true;
     935             :         }
     936             :     }
     937             : 
     938         313 :     return false;
     939             : }
     940             : 
     941             : 
     942          63 : }
     943             : // namespace as2js
     944             : 
     945             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.10