LCOV - code coverage report
Current view: top level - lib - compiler_compile.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 22 66 33.3 %
Date: 2014-11-22 Functions: 4 6 66.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* compiler_compile.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/compiler.h"
      37             : 
      38             : #include    "as2js/exceptions.h"
      39             : #include    "as2js/message.h"
      40             : 
      41             : 
      42             : namespace as2js
      43             : {
      44             : 
      45             : 
      46             : /**********************************************************************/
      47             : /**********************************************************************/
      48             : /***  COMPILE  ********************************************************/
      49             : /**********************************************************************/
      50             : /**********************************************************************/
      51             : 
      52             : /** \brief "Compile" the code, which means optimize and make compatible.
      53             :  *
      54             :  * The following functions "compile" the code:
      55             :  *
      56             :  * \li It will optimize everything it can by reducing expressions that
      57             :  *     can be computed at "compile" time;
      58             :  * \li It transforms advanced features of as2js such as classes into
      59             :  *     JavaScript compatible code such as prototypes.
      60             :  *
      61             :  * On other words, it means that the compiler (1) tries to resolve all
      62             :  * the references that are found in the current tree; (2) loads the
      63             :  * libraries referenced by the different import instructions which
      64             :  * are necessary (or at least seem to be); (3) and run the optimizer
      65             :  * against the code at various times.
      66             :  *
      67             :  * The compiler calls the optimizer for you because it is important in
      68             :  * various places and the optimizations applied will vary depending on
      69             :  * the compiler changes and further changes may be applied after the
      70             :  * optimizations. So on return the tree is expected to be 100% compatible
      71             :  * with a JavaScript all browser interpreters and optimized as much as
      72             :  * possible to be output as minimized as can be.
      73             :  *
      74             :  * \param[in,out] root  The root node or program to compile.
      75             :  *
      76             :  * \return The number of errors generated while compiling. If zero, no errors
      77             :  *         so you can proceed with the tree.
      78             :  */
      79        9339 : int Compiler::compile(Node::pointer_t& root)
      80             : {
      81        9339 :     int const errcnt(Message::error_count());
      82             : 
      83        9339 :     if(root)
      84             :     {
      85             :         // all the "use namespace ... / with ..." currently in effect
      86        9338 :         f_scope = root->create_replacement(Node::node_t::NODE_SCOPE);
      87             : 
      88        9338 :         if(root->get_type() == Node::node_t::NODE_PROGRAM)
      89             :         {
      90        8192 :             program(root);
      91             :         }
      92        1146 :         else if(root->get_type() == Node::node_t::NODE_ROOT)
      93             :         {
      94           0 :             NodeLock ln(root);
      95           0 :             size_t const max_children(root->get_children_size());
      96           0 :             for(size_t idx(0); idx < max_children; ++idx)
      97             :             {
      98           0 :                 Node::pointer_t child(root->get_child(idx));
      99           0 :                 if(child->get_type() == Node::node_t::NODE_PROGRAM)
     100             :                 {
     101           0 :                     program(child);
     102             :                 }
     103           0 :             }
     104             :         }
     105             :         else
     106             :         {
     107        1146 :             Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_INTERNAL_ERROR, root->get_position());
     108        1146 :             msg << "the Compiler::compile() function expected a root or a program node to start with.";
     109             :         }
     110             :     }
     111             : 
     112        9339 :     return Message::error_count() - errcnt;
     113             : }
     114             : 
     115             : 
     116             : 
     117             : 
     118             : 
     119             : 
     120             : 
     121             : 
     122             : 
     123             : 
     124             : 
     125             : // note that we search for labels in functions, programs, packages
     126             : // [and maybe someday classes, but for now classes can't have
     127             : // code and thus no labels]
     128       16384 : void Compiler::find_labels(Node::pointer_t function_node, Node::pointer_t node)
     129             : {
     130             :     // NOTE: function may also be a program or a package.
     131       16384 :     switch(node->get_type())
     132             :     {
     133             :     case Node::node_t::NODE_LABEL:
     134             :     {
     135           0 :         Node::pointer_t label(function_node->find_label(node->get_string()));
     136           0 :         if(label)
     137             :         {
     138             :             // TODO: test function type
     139           0 :             Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_DUPLICATES, function_node->get_position());
     140           0 :             msg << "label '" << node->get_string() << "' defined twice in the same program, package or function.";
     141             :         }
     142             :         else
     143             :         {
     144           0 :             function_node->add_label(node);
     145           0 :         }
     146             :     }
     147        8192 :         return;
     148             : 
     149             :     // sub-declarations and expressions are just skipped
     150             :     // decls:
     151             :     case Node::node_t::NODE_FUNCTION:
     152             :     case Node::node_t::NODE_CLASS:
     153             :     case Node::node_t::NODE_INTERFACE:
     154             :     case Node::node_t::NODE_VAR:
     155             :     case Node::node_t::NODE_PACKAGE:    // ?!
     156             :     case Node::node_t::NODE_PROGRAM:    // ?!
     157             :     // expr:
     158             :     case Node::node_t::NODE_ASSIGNMENT:
     159             :     case Node::node_t::NODE_ASSIGNMENT_ADD:
     160             :     case Node::node_t::NODE_ASSIGNMENT_BITWISE_AND:
     161             :     case Node::node_t::NODE_ASSIGNMENT_BITWISE_OR:
     162             :     case Node::node_t::NODE_ASSIGNMENT_BITWISE_XOR:
     163             :     case Node::node_t::NODE_ASSIGNMENT_DIVIDE:
     164             :     case Node::node_t::NODE_ASSIGNMENT_LOGICAL_AND:
     165             :     case Node::node_t::NODE_ASSIGNMENT_LOGICAL_OR:
     166             :     case Node::node_t::NODE_ASSIGNMENT_LOGICAL_XOR:
     167             :     case Node::node_t::NODE_ASSIGNMENT_MAXIMUM:
     168             :     case Node::node_t::NODE_ASSIGNMENT_MINIMUM:
     169             :     case Node::node_t::NODE_ASSIGNMENT_MODULO:
     170             :     case Node::node_t::NODE_ASSIGNMENT_MULTIPLY:
     171             :     case Node::node_t::NODE_ASSIGNMENT_POWER:
     172             :     case Node::node_t::NODE_ASSIGNMENT_ROTATE_LEFT:
     173             :     case Node::node_t::NODE_ASSIGNMENT_ROTATE_RIGHT:
     174             :     case Node::node_t::NODE_ASSIGNMENT_SHIFT_LEFT:
     175             :     case Node::node_t::NODE_ASSIGNMENT_SHIFT_RIGHT:
     176             :     case Node::node_t::NODE_ASSIGNMENT_SHIFT_RIGHT_UNSIGNED:
     177             :     case Node::node_t::NODE_ASSIGNMENT_SUBTRACT:
     178             :     case Node::node_t::NODE_CALL:
     179             :     case Node::node_t::NODE_DECREMENT:
     180             :     case Node::node_t::NODE_DELETE:
     181             :     case Node::node_t::NODE_INCREMENT:
     182             :     case Node::node_t::NODE_MEMBER:
     183             :     case Node::node_t::NODE_NEW:
     184             :     case Node::node_t::NODE_POST_DECREMENT:
     185             :     case Node::node_t::NODE_POST_INCREMENT:
     186        8192 :         return;
     187             : 
     188             :     default:
     189             :         // other nodes may have children we want to check out
     190        8192 :         break;
     191             : 
     192             :     }
     193             : 
     194        8192 :     NodeLock ln(node);
     195        8192 :     size_t max_children(node->get_children_size());
     196       16384 :     for(size_t idx(0); idx < max_children; ++idx)
     197             :     {
     198        8192 :         Node::pointer_t child(node->get_child(idx));
     199        8192 :         find_labels(function_node, child);
     200       16384 :     }
     201             : }
     202             : 
     203             : 
     204             : 
     205             : 
     206             : 
     207             : 
     208             : 
     209             : 
     210             : 
     211             : 
     212             : 
     213             : 
     214             : 
     215             : 
     216             : 
     217             : 
     218             : 
     219             : 
     220             : 
     221             : 
     222             : 
     223             : 
     224             : 
     225             : 
     226             : 
     227             : 
     228             : 
     229             : 
     230             : 
     231             : 
     232             : 
     233             : 
     234             : 
     235             : 
     236           0 : void Compiler::print_search_errors(Node::pointer_t name)
     237             : {
     238             :     // all failed, check whether we have errors...
     239           0 :     if(f_err_flags == SEARCH_ERROR_NONE)
     240             :     {
     241           0 :         return;
     242             :     }
     243             : 
     244           0 :     Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_CANNOT_MATCH, name->get_position());
     245           0 :     msg << "the name '" << name->get_string() << "' could not be resolved because:\n";
     246             : 
     247           0 :     if((f_err_flags & SEARCH_ERROR_PRIVATE) != 0)
     248             :     {
     249           0 :         msg << "   You cannot access a private class member from outside that very class.";
     250             :     }
     251           0 :     if((f_err_flags & SEARCH_ERROR_PROTECTED) != 0)
     252             :     {
     253           0 :         msg << "   You cannot access a protected class member from outside a class or its derived classes.";
     254             :     }
     255           0 :     if((f_err_flags & SEARCH_ERROR_PROTOTYPE) != 0)
     256             :     {
     257           0 :         msg << "   One or more functions were found, but none matched the input parameters.";
     258             :     }
     259           0 :     if((f_err_flags & SEARCH_ERROR_WRONG_PRIVATE) != 0)
     260             :     {
     261           0 :         msg << "   You cannot use the private attribute outside of a package or a class.";
     262             :     }
     263           0 :     if((f_err_flags & SEARCH_ERROR_WRONG_PROTECTED) != 0)
     264             :     {
     265           0 :         msg << "   You cannot use the protected attribute outside of a class.";
     266             :     }
     267           0 :     if((f_err_flags & SEARCH_ERROR_PRIVATE_PACKAGE) != 0)
     268             :     {
     269           0 :         msg << "   You cannot access a package private declaration from outside of that package.";
     270           0 :     }
     271             : }
     272             : 
     273             : 
     274             : 
     275             : 
     276             : 
     277             : 
     278             : 
     279           0 : void Compiler::resolve_internal_type(Node::pointer_t parent, char const *type, Node::pointer_t& resolution)
     280             : {
     281           0 :     Node::pointer_t id(parent->create_replacement(Node::node_t::NODE_IDENTIFIER));
     282           0 :     id->set_string(type);
     283             : 
     284             :     // create a temporary identifier
     285           0 :     int idx(parent->get_children_size());
     286           0 :     parent->append_child(id);
     287             : 
     288             :     // search for the identifier which is an internal type name
     289             :     bool r;
     290             :     {
     291           0 :         NodeLock ln(parent);
     292           0 :         r = resolve_name(id, id, resolution, Node::pointer_t(), 0);
     293             :     }
     294             : 
     295             :     // get rid of the temporary identifier
     296           0 :     parent->delete_child(idx);
     297             : 
     298           0 :     if(!r)
     299             :     {
     300             :         // if the compiler can't find an internal type, that's really bad!
     301           0 :         Message msg(message_level_t::MESSAGE_LEVEL_FATAL, err_code_t::AS_ERR_INTERNAL_ERROR, parent->get_position());
     302           0 :         msg << "cannot find internal type \"" << type << "\".";
     303           0 :         throw exception_exit(1, "cannot find internal type");
     304             :     }
     305             : 
     306           0 :     return;
     307             : }
     308             : 
     309             : 
     310             : 
     311             : 
     312             : 
     313             : 
     314             : 
     315             : 
     316             : 
     317             : 
     318             : 
     319             : 
     320             : 
     321             : 
     322             : 
     323             : 
     324             : 
     325          63 : }
     326             : // namespace as2js
     327             : 
     328             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.10