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

          Line data    Source code
       1             : /* node_display.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    <controlled_vars/controlled_vars_auto_enum_init.h>
      39             : 
      40             : #include    <iomanip>
      41             : 
      42             : 
      43             : /** \file
      44             :  * \brief Handle the display of a node.
      45             :  *
      46             :  * In order to debug the compiler, it is extremely practical to have
      47             :  * a way to display it in a console. The functions defined here are
      48             :  * used for that purpose.
      49             :  *
      50             :  * The display is pretty complicated because nodes can only have a
      51             :  * certain set of flags and attributes and calling the corresponding
      52             :  * functions to retrieve these flags and attributes throw if the
      53             :  * node type is wrong. For that reason we have a large amount of
      54             :  * very specialized code.
      55             :  *
      56             :  * The function gets 100% coverage from the Node test so we are
      57             :  * confident that it is 99.9% correct.
      58             :  *
      59             :  * The output definition let you use a Node with the standard output
      60             :  * functions of C++ as in:
      61             :  *
      62             :  * \code
      63             :  *      std::cout << my_node << std::endl;
      64             :  * \endcode
      65             :  *
      66             :  * \sa display()
      67             :  */
      68             : 
      69             : 
      70             : namespace as2js
      71             : {
      72             : 
      73             : 
      74             : /**********************************************************************/
      75             : /**********************************************************************/
      76             : /***  NODE DISPLAY  ***************************************************/
      77             : /**********************************************************************/
      78             : /**********************************************************************/
      79             : 
      80             : 
      81             : /** \brief Display a node.
      82             :  *
      83             :  * This function prints a node in the \p out stream.
      84             :  *
      85             :  * The function is smart enough to recognize the different type of nodes
      86             :  * and thus know what is saved in them and knows how to display all of
      87             :  * that information.
      88             :  *
      89             :  * This is only to display a node in a technical way. It does not attempt
      90             :  * to display things in JavaScript or any other language.
      91             :  *
      92             :  * \param[in] out  The output stream where the node is displayed.
      93             :  */
      94        9383 : void Node::display_data(std::ostream& out) const
      95             : {
      96             :     struct sub_function
      97             :     {
      98        4860 :         static void display_str(std::ostream& out, String str)
      99             :         {
     100        4860 :             out << ": '";
     101      156183 :             for(as_char_t const *s(str.c_str()); *s != '\0'; ++s)
     102             :             {
     103      151323 :                 if(*s < 0x20)
     104             :                 {
     105             :                     // show controls as ^<letter>
     106           4 :                     out << '^' << static_cast<char>(*s + '@');
     107             :                 }
     108      151319 :                 else if(*s < 0x7f)
     109             :                 {
     110          44 :                     if(*s == '\'')
     111             :                     {
     112           1 :                         out << "\\'";
     113             :                     }
     114             :                     else
     115             :                     {
     116          43 :                         out << static_cast<char>(*s);
     117             :                     }
     118             :                 }
     119      151275 :                 else if(*s < 0x100)
     120             :                 {
     121          18 :                     out << "\\x" << std::hex << *s << std::dec;
     122             :                 }
     123      151257 :                 else if(*s < 0x10000)
     124             :                 {
     125        8564 :                     out << "\\u" << std::hex << std::setfill('0') << std::setw(4) << *s << std::dec;
     126             :                 }
     127             :                 else
     128             :                 {
     129      142693 :                     out << "\\U" << std::hex << std::setfill('0') << std::setw(8) << *s << std::dec;
     130             :                 }
     131             :             }
     132        4860 :             out << "'";
     133        4860 :         }
     134             :     };
     135             : 
     136             :     // WARNING: somehow g++ views the node_t type as a Node type and thus
     137             :     //          it recursively calls this function until the stack is full
     138        9383 :     out << std::setw(4) << std::setfill('0') << static_cast<int>(static_cast<node_t>(f_type))
     139       18766 :         << std::setfill('\0') << ": " << get_type_name();
     140        9383 :     if(static_cast<int>(static_cast<node_t>(f_type)) > ' ' && static_cast<int>(static_cast<node_t>(f_type)) < 0x7F)
     141             :     {
     142          26 :         out << " = '" << static_cast<char>(static_cast<node_t>(f_type)) << "'";
     143             :     }
     144             : 
     145        9383 :     switch(f_type)
     146             :     {
     147             :     case node_t::NODE_BREAK:
     148             :     case node_t::NODE_CLASS:
     149             :     case node_t::NODE_CONTINUE:
     150             :     case node_t::NODE_GOTO:
     151             :     case node_t::NODE_INTERFACE:
     152             :     case node_t::NODE_LABEL:
     153             :     case node_t::NODE_NAMESPACE:
     154             :     case node_t::NODE_REGULAR_EXPRESSION:
     155          10 :         sub_function::display_str(out, f_str);
     156          10 :         break;
     157             : 
     158             :     case node_t::NODE_CATCH:
     159           3 :         out << ":";
     160           3 :         if(f_flags[static_cast<size_t>(flag_t::NODE_CATCH_FLAG_TYPED)])
     161             :         {
     162           1 :             out << " TYPED";
     163             :         }
     164           3 :         break;
     165             : 
     166             :     case node_t::NODE_DIRECTIVE_LIST:
     167           5 :         out << ":";
     168           5 :         if(f_flags[static_cast<size_t>(flag_t::NODE_DIRECTIVE_LIST_FLAG_NEW_VARIABLES)])
     169             :         {
     170           2 :             out << " NEW-VARIABLES";
     171             :         }
     172           5 :         break;
     173             : 
     174             :     case node_t::NODE_ENUM:
     175           3 :         sub_function::display_str(out, f_str);
     176           3 :         if(f_flags[static_cast<size_t>(flag_t::NODE_ENUM_FLAG_CLASS)])
     177             :         {
     178           1 :             out << " CLASS";
     179             :         }
     180           3 :         break;
     181             : 
     182             :     case node_t::NODE_FOR:
     183           9 :         out << ":";
     184           9 :         if(f_flags[static_cast<size_t>(flag_t::NODE_FOR_FLAG_CONST)])
     185             :         {
     186           4 :             out << " CONST";
     187             :         }
     188           9 :         if(f_flags[static_cast<size_t>(flag_t::NODE_FOR_FLAG_FOREACH)])
     189             :         {
     190           4 :             out << " FOREACH";
     191             :         }
     192           9 :         if(f_flags[static_cast<size_t>(flag_t::NODE_FOR_FLAG_IN)])
     193             :         {
     194           4 :             out << " IN";
     195             :         }
     196           9 :         break;
     197             : 
     198             :     case node_t::NODE_IDENTIFIER:
     199             :     case node_t::NODE_STRING:
     200             :     case node_t::NODE_VIDENTIFIER:
     201         609 :         sub_function::display_str(out, f_str);
     202         609 :         if(f_flags[static_cast<size_t>(flag_t::NODE_IDENTIFIER_FLAG_WITH)])
     203             :         {
     204           6 :             out << " WITH";
     205             :         }
     206         609 :         if(f_flags[static_cast<size_t>(flag_t::NODE_IDENTIFIER_FLAG_TYPED)])
     207             :         {
     208           7 :             out << " TYPED";
     209             :         }
     210         609 :         break;
     211             : 
     212             :     case node_t::NODE_IMPORT:
     213           3 :         sub_function::display_str(out, f_str);
     214           3 :         if(f_flags[static_cast<size_t>(flag_t::NODE_IMPORT_FLAG_IMPLEMENTS)])
     215             :         {
     216           1 :             out << " IMPLEMENTS";
     217             :         }
     218           3 :         break;
     219             : 
     220             :     case node_t::NODE_PACKAGE:
     221           5 :         sub_function::display_str(out, f_str);
     222           5 :         if(f_flags[static_cast<size_t>(flag_t::NODE_PACKAGE_FLAG_FOUND_LABELS)])
     223             :         {
     224           2 :             out << " FOUND-LABELS";
     225             :         }
     226           5 :         if(f_flags[static_cast<size_t>(flag_t::NODE_PACKAGE_FLAG_REFERENCED)])
     227             :         {
     228           2 :             out << " REFERENCED";
     229             :         }
     230           5 :         break;
     231             : 
     232             :     case node_t::NODE_INT64:
     233           1 :         out << ": " << f_int.get() << ", 0x" << std::hex << std::setw(16) << std::setfill('0') << f_int.get() << std::dec << std::setw(0) << std::setfill('\0');
     234           1 :         break;
     235             : 
     236             :     case node_t::NODE_FLOAT64:
     237           2 :         out << ": " << f_float.get();
     238           2 :         break;
     239             : 
     240             :     case node_t::NODE_FUNCTION:
     241         130 :         sub_function::display_str(out, f_str);
     242         130 :         if(f_flags[static_cast<size_t>(flag_t::NODE_FUNCTION_FLAG_GETTER)])
     243             :         {
     244          64 :             out << " GETTER";
     245             :         }
     246         130 :         if(f_flags[static_cast<size_t>(flag_t::NODE_FUNCTION_FLAG_SETTER)])
     247             :         {
     248          64 :             out << " SETTER";
     249             :         }
     250         130 :         if(f_flags[static_cast<size_t>(flag_t::NODE_FUNCTION_FLAG_OUT)])
     251             :         {
     252          64 :             out << " OUT";
     253             :         }
     254         130 :         if(f_flags[static_cast<size_t>(flag_t::NODE_FUNCTION_FLAG_VOID)])
     255             :         {
     256          64 :             out << " VOID";
     257             :         }
     258         130 :         if(f_flags[static_cast<size_t>(flag_t::NODE_FUNCTION_FLAG_NEVER)])
     259             :         {
     260          64 :             out << " NEVER";
     261             :         }
     262         130 :         if(f_flags[static_cast<size_t>(flag_t::NODE_FUNCTION_FLAG_NOPARAMS)])
     263             :         {
     264          64 :             out << " NOPARAMS";
     265             :         }
     266         130 :         if(f_flags[static_cast<size_t>(flag_t::NODE_FUNCTION_FLAG_OPERATOR)])
     267             :         {
     268          64 :             out << " OPERATOR";
     269             :         }
     270         130 :         break;
     271             : 
     272             :     case node_t::NODE_PARAM:
     273             :         // THIS SEEMS WRONG, We do not save a string in
     274             :         // the NODE_PARAM; so either it is wrong here or
     275             :         // we miss the necessary call(s) when parsing the
     276             :         // function list of parameters
     277             :         //sub_function::display_str(out, f_str);
     278        1025 :         out << ":";
     279        1025 :         if(f_flags[static_cast<size_t>(flag_t::NODE_PARAM_FLAG_CONST)])
     280             :         {
     281         512 :             out << " CONST";
     282             :         }
     283        1025 :         if(f_flags[static_cast<size_t>(flag_t::NODE_PARAM_FLAG_IN)])
     284             :         {
     285         512 :             out << " IN";
     286             :         }
     287        1025 :         if(f_flags[static_cast<size_t>(flag_t::NODE_PARAM_FLAG_OUT)])
     288             :         {
     289         512 :             out << " OUT";
     290             :         }
     291        1025 :         if(f_flags[static_cast<size_t>(flag_t::NODE_PARAM_FLAG_NAMED)])
     292             :         {
     293         512 :             out << " NAMED";
     294             :         }
     295        1025 :         if(f_flags[static_cast<size_t>(flag_t::NODE_PARAM_FLAG_REST)])
     296             :         {
     297         512 :             out << " REST";
     298             :         }
     299        1025 :         if(f_flags[static_cast<size_t>(flag_t::NODE_PARAM_FLAG_UNCHECKED)])
     300             :         {
     301         512 :             out << " UNCHECKED";
     302             :         }
     303        1025 :         if(f_flags[static_cast<size_t>(flag_t::NODE_PARAM_FLAG_UNPROTOTYPED)])
     304             :         {
     305         512 :             out << " UNPROTOTYPED";
     306             :         }
     307        1025 :         if(f_flags[static_cast<size_t>(flag_t::NODE_PARAM_FLAG_REFERENCED)])
     308             :         {
     309         512 :             out << " REFERENCED";
     310             :         }
     311        1025 :         if(f_flags[static_cast<size_t>(flag_t::NODE_PARAM_FLAG_PARAMREF)])
     312             :         {
     313         512 :             out << " PARAMREF";
     314             :         }
     315        1025 :         if(f_flags[static_cast<size_t>(flag_t::NODE_PARAM_FLAG_CATCH)])
     316             :         {
     317         512 :             out << " CATCH";
     318             :         }
     319        1025 :         break;
     320             : 
     321             :     case node_t::NODE_PARAM_MATCH:
     322           3 :         out << ":";
     323           3 :         if(f_flags[static_cast<size_t>(flag_t::NODE_PARAM_MATCH_FLAG_UNPROTOTYPED)])
     324             :         {
     325           1 :             out << " UNPROTOTYPED";
     326             :         }
     327           3 :         break;
     328             : 
     329             :     case node_t::NODE_SWITCH:
     330           3 :         out << ":";
     331           3 :         if(f_flags[static_cast<size_t>(flag_t::NODE_SWITCH_FLAG_DEFAULT)])
     332             :         {
     333           1 :             out << " DEFAULT";
     334             :         }
     335           3 :         break;
     336             : 
     337             :     case node_t::NODE_TYPE:
     338           3 :         out << ":";
     339           3 :         if(f_flags[static_cast<size_t>(flag_t::NODE_TYPE_FLAG_MODULO)])
     340             :         {
     341           1 :             out << " MODULO";
     342             :         }
     343           3 :         break;
     344             : 
     345             :     case node_t::NODE_VARIABLE:
     346             :     case node_t::NODE_VAR_ATTRIBUTES:
     347        4100 :         sub_function::display_str(out, f_str);
     348        4100 :         if(f_flags[static_cast<size_t>(flag_t::NODE_VARIABLE_FLAG_CONST)])
     349             :         {
     350        2048 :             out << " CONST";
     351             :         }
     352        4100 :         if(f_flags[static_cast<size_t>(flag_t::NODE_VARIABLE_FLAG_LOCAL)])
     353             :         {
     354        2048 :             out << " LOCAL";
     355             :         }
     356        4100 :         if(f_flags[static_cast<size_t>(flag_t::NODE_VARIABLE_FLAG_MEMBER)])
     357             :         {
     358        2048 :             out << " MEMBER";
     359             :         }
     360        4100 :         if(f_flags[static_cast<size_t>(flag_t::NODE_VARIABLE_FLAG_ATTRIBUTES)])
     361             :         {
     362        2048 :             out << " ATTRIBUTES";
     363             :         }
     364        4100 :         if(f_flags[static_cast<size_t>(flag_t::NODE_VARIABLE_FLAG_ENUM)])
     365             :         {
     366        2048 :             out << " ENUM";
     367             :         }
     368        4100 :         if(f_flags[static_cast<size_t>(flag_t::NODE_VARIABLE_FLAG_COMPILED)])
     369             :         {
     370        2048 :             out << " COMPILED";
     371             :         }
     372        4100 :         if(f_flags[static_cast<size_t>(flag_t::NODE_VARIABLE_FLAG_INUSE)])
     373             :         {
     374        2048 :             out << " INUSE";
     375             :         }
     376        4100 :         if(f_flags[static_cast<size_t>(flag_t::NODE_VARIABLE_FLAG_ATTRS)])
     377             :         {
     378        2048 :             out << " ATTRS";
     379             :         }
     380        4100 :         if(f_flags[static_cast<size_t>(flag_t::NODE_VARIABLE_FLAG_DEFINED)])
     381             :         {
     382        2048 :             out << " DEFINED";
     383             :         }
     384        4100 :         if(f_flags[static_cast<size_t>(flag_t::NODE_VARIABLE_FLAG_DEFINING)])
     385             :         {
     386        2048 :             out << " DEFINING";
     387             :         }
     388        4100 :         if(f_flags[static_cast<size_t>(flag_t::NODE_VARIABLE_FLAG_TOADD)])
     389             :         {
     390        2048 :             out << " TOADD";
     391             :         }
     392        4100 :         break;
     393             : 
     394             :     default:
     395        3469 :         break;
     396             : 
     397             :     }
     398        9383 : }
     399             : 
     400             : 
     401             : /** \brief Display a node tree.
     402             :  *
     403             :  * This function displays this node, its children, its children's children,
     404             :  * etc. until all the nodes in the tree were displayed.
     405             :  *
     406             :  * Note that the function knows about the node links, variables, and labels
     407             :  * which also get displayed.
     408             :  *
     409             :  * Because the tree cannot generate loops (the set_parent() function
     410             :  * prevents such), we do not have anything that would break the
     411             :  * recursivity of the function.
     412             :  *
     413             :  * The character used to start the string (\p c) changes depending on what
     414             :  * we are showing to the user. That way we know whether it is the root (.),
     415             :  * a child (-), a variable (=), or a label (:).
     416             :  *
     417             :  * \param[in,out] out  The output stream.
     418             :  * \param[in] indent  The current indentation. We start with 2.
     419             :  * \param[in] c  A character to start each line of output.
     420             :  */
     421        9383 : void Node::display(std::ostream& out, int indent, char c) const
     422             : {
     423             :     // this pointer and indentation
     424        9383 :     out << this << ": " << std::setfill('0') << std::setw(2) << indent << std::setfill(' ') << c << std::setw(indent) << "";
     425             : 
     426             :     // display node data (integer, string, float, etc.)
     427        9383 :     display_data(out);
     428             : 
     429             :     // display information about the links
     430        9383 :     bool first = true;
     431        9393 :     for(size_t lnk(0); lnk < f_link.size(); ++lnk)
     432             :     {
     433          10 :         if(f_link[lnk])
     434             :         {
     435           3 :             if(first)
     436             :             {
     437           2 :                 first = false;
     438           2 :                 out << " Lnk:";
     439             :             }
     440           3 :             out << " [" << lnk << "]=" << f_link[lnk].get();
     441             :         }
     442             :     }
     443             : 
     444             :     // display the different attributes if any
     445             :     struct display_attributes
     446             :     {
     447        9383 :         display_attributes(std::ostream& out, attribute_set_t attrs)
     448             :             : f_out(out)
     449        9383 :             , f_attributes(attrs)
     450             :         {
     451        9383 :             display_attribute(attribute_t::NODE_ATTR_PUBLIC);
     452        9383 :             display_attribute(attribute_t::NODE_ATTR_PRIVATE);
     453        9383 :             display_attribute(attribute_t::NODE_ATTR_PROTECTED);
     454        9383 :             display_attribute(attribute_t::NODE_ATTR_INTERNAL);
     455        9383 :             display_attribute(attribute_t::NODE_ATTR_TRANSIENT);
     456        9383 :             display_attribute(attribute_t::NODE_ATTR_VOLATILE);
     457             : 
     458        9383 :             display_attribute(attribute_t::NODE_ATTR_STATIC);
     459        9383 :             display_attribute(attribute_t::NODE_ATTR_ABSTRACT);
     460        9383 :             display_attribute(attribute_t::NODE_ATTR_VIRTUAL);
     461        9383 :             display_attribute(attribute_t::NODE_ATTR_ARRAY);
     462        9383 :             display_attribute(attribute_t::NODE_ATTR_INLINE);
     463             : 
     464        9383 :             display_attribute(attribute_t::NODE_ATTR_REQUIRE_ELSE);
     465        9383 :             display_attribute(attribute_t::NODE_ATTR_ENSURE_THEN);
     466             : 
     467        9383 :             display_attribute(attribute_t::NODE_ATTR_NATIVE);
     468             : 
     469        9383 :             display_attribute(attribute_t::NODE_ATTR_DEPRECATED);
     470        9383 :             display_attribute(attribute_t::NODE_ATTR_UNSAFE);
     471             : 
     472        9383 :             display_attribute(attribute_t::NODE_ATTR_CONSTRUCTOR);
     473             : 
     474             :             //display_attribute(attribute_t::NODE_ATTR_CONST); -- this is a flag, not needed here
     475        9383 :             display_attribute(attribute_t::NODE_ATTR_FINAL);
     476        9383 :             display_attribute(attribute_t::NODE_ATTR_ENUMERABLE);
     477             : 
     478        9383 :             display_attribute(attribute_t::NODE_ATTR_TRUE);
     479        9383 :             display_attribute(attribute_t::NODE_ATTR_FALSE);
     480        9383 :             display_attribute(attribute_t::NODE_ATTR_UNUSED);
     481             : 
     482        9383 :             display_attribute(attribute_t::NODE_ATTR_DYNAMIC);
     483             : 
     484        9383 :             display_attribute(attribute_t::NODE_ATTR_FOREACH);
     485        9383 :             display_attribute(attribute_t::NODE_ATTR_NOBREAK);
     486        9383 :             display_attribute(attribute_t::NODE_ATTR_AUTOBREAK);
     487             : 
     488        9383 :             display_attribute(attribute_t::NODE_ATTR_DEFINED);
     489        9383 :         }
     490             : 
     491      253341 :         void display_attribute(attribute_t a)
     492             :         {
     493      253341 :             if(f_attributes[static_cast<size_t>(a)])
     494             :             {
     495        6642 :                 if(f_first)
     496             :                 {
     497        3322 :                     f_first = false;
     498        3322 :                     f_out << " attrs:";
     499             :                 }
     500        6642 :                 f_out << " " << Node::attribute_to_string(a);
     501             :             }
     502      253341 :         }
     503             : 
     504             :         std::ostream&               f_out;
     505             :         controlled_vars::tbool_t    f_first;
     506             :         attribute_set_t             f_attributes;
     507        9383 :     } display_attr(out, f_attributes);
     508             : 
     509             :     // end the line with our position
     510        9383 :     out << " (" << f_position << ")" << std::endl;
     511             : 
     512             :     // now print children
     513        9396 :     for(size_t idx(0); idx < f_children.size(); ++idx)
     514             :     {
     515          13 :         f_children[idx]->display(out, indent + 1, '-');
     516             :     }
     517             : 
     518             :     // now print variables
     519        9384 :     for(size_t idx(0); idx < f_variables.size(); ++idx)
     520             :     {
     521           1 :         f_variables[idx]->display(out, indent + 1, '=');
     522             :     }
     523             : 
     524             :     // now print labels
     525       28152 :     for(map_of_pointers_t::const_iterator it(f_labels.begin());
     526       18768 :                                           it != f_labels.end();
     527             :                                           ++it)
     528             :     {
     529           1 :         it->second->display(out, indent + 1, ':');
     530             :     }
     531        9383 : }
     532             : 
     533             : 
     534             : /** \brief Send a node to the specified output stream.
     535             :  *
     536             :  * This function prints a node to the output stream. The printing is very
     537             :  * technical and mainly used to debug the node tree while parsing,
     538             :  * compiling, optimizing, and generating the final output.
     539             :  *
     540             :  * \param[in,out] out  The output stream.
     541             :  * \param[in] node  The node to print in the output stream.
     542             :  *
     543             :  * \return A reference to the output stream.
     544             :  */
     545        9368 : std::ostream& operator << (std::ostream& out, Node const& node)
     546             : {
     547        9368 :     node.display(out, 2, '.');
     548        9368 :     return out;
     549             : }
     550             : 
     551             : 
     552          63 : }
     553             : // namespace as2js
     554             : 
     555             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.10