LCOV - code coverage report
Current view: top level - lib - compiler_variable.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1 102 1.0 %
Date: 2014-11-22 Functions: 2 6 33.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* compiler_variable.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/message.h"
      39             : 
      40             : 
      41             : namespace as2js
      42             : {
      43             : 
      44             : 
      45             : 
      46             : 
      47             : 
      48             : // we can simplify constant variables with their content whenever it is
      49             : // a string, number or other non-dynamic constant
      50           0 : bool Compiler::replace_constant_variable(Node::pointer_t& replace, Node::pointer_t resolution)
      51             : {
      52           0 :     if(resolution->get_type() != Node::node_t::NODE_VARIABLE)
      53             :     {
      54           0 :         return false;
      55             :     }
      56             : 
      57           0 :     if(!resolution->get_flag(Node::flag_t::NODE_VARIABLE_FLAG_CONST))
      58             :     {
      59           0 :         return false;
      60             :     }
      61             : 
      62           0 :     NodeLock resolution_ln(resolution);
      63           0 :     size_t const max_children(resolution->get_children_size());
      64           0 :     for(size_t idx(0); idx < max_children; ++idx)
      65             :     {
      66           0 :         Node::pointer_t set(resolution->get_child(idx));
      67           0 :         if(set->get_type() != Node::node_t::NODE_SET)
      68             :         {
      69           0 :             continue;
      70             :         }
      71             : 
      72           0 :         Optimizer::optimize(set);
      73             : 
      74           0 :         if(set->get_children_size() != 1)
      75             :         {
      76           0 :             return false;
      77             :         }
      78           0 :         NodeLock set_ln(set);
      79             : 
      80           0 :         Node::pointer_t value(set->get_child(0));
      81           0 :         type_expr(value);
      82             : 
      83           0 :         switch(value->get_type())
      84             :         {
      85             :         case Node::node_t::NODE_STRING:
      86             :         case Node::node_t::NODE_INT64:
      87             :         case Node::node_t::NODE_FLOAT64:
      88             :         case Node::node_t::NODE_TRUE:
      89             :         case Node::node_t::NODE_FALSE:
      90             :         case Node::node_t::NODE_NULL:
      91             :         case Node::node_t::NODE_UNDEFINED:
      92             :         case Node::node_t::NODE_REGULAR_EXPRESSION:
      93             : 
      94             : #if 0
      95             : {
      96             : Data& d = replace.GetData();
      97             : fprintf(stderr, "Replace is of type %d\n", d.f_type);
      98             : replace.Display(stderr, 2);
      99             : }
     100             : #endif
     101             : 
     102           0 :             replace->replace_with(value);
     103           0 :             return true;
     104             : 
     105             :         default:
     106             :             // dynamic expression, can't
     107             :             // be resolved at compile time...
     108           0 :             return false;
     109             : 
     110             :         }
     111             :         /*NOTREACHED*/
     112             :     }
     113             : 
     114           0 :     return false;
     115             : }
     116             : 
     117             : 
     118           0 : void Compiler::var(Node::pointer_t var_node)
     119             : {
     120             :     // when variables are used, they are initialized
     121             :     // here, we initialize them only if they have
     122             :     // side effects; this is because a variable can
     123             :     // be used as an attribute and it would often
     124             :     // end up as an error (i.e. attributes not
     125             :     // found as identifier(s) defining another
     126             :     // object)
     127           0 :     NodeLock ln(var_node);
     128           0 :     size_t const vcnt(var_node->get_children_size());
     129           0 :     for(size_t v(0); v < vcnt; ++v)
     130             :     {
     131           0 :         Node::pointer_t variable_node(var_node->get_child(v));
     132           0 :         variable(variable_node, true);
     133           0 :     }
     134           0 : }
     135             : 
     136             : 
     137           0 : void Compiler::variable(Node::pointer_t variable_node, bool const side_effects_only)
     138             : {
     139           0 :     size_t const max_children(variable_node->get_children_size());
     140             : 
     141             :     // if we already have a type, we have been parsed
     142           0 :     if(variable_node->get_flag(Node::flag_t::NODE_VARIABLE_FLAG_DEFINED)
     143           0 :     || variable_node->get_flag(Node::flag_t::NODE_VARIABLE_FLAG_ATTRIBUTES))
     144             :     {
     145           0 :         if(!side_effects_only)
     146             :         {
     147           0 :             if(!variable_node->get_flag(Node::flag_t::NODE_VARIABLE_FLAG_COMPILED))
     148             :             {
     149           0 :                 for(size_t idx(0); idx < max_children; ++idx)
     150             :                 {
     151           0 :                     Node::pointer_t child(variable_node->get_child(idx));
     152           0 :                     if(child->get_type() == Node::node_t::NODE_SET)
     153             :                     {
     154           0 :                         Node::pointer_t expr(child->get_child(0));
     155           0 :                         expression(expr);
     156           0 :                         variable_node->set_flag(Node::flag_t::NODE_VARIABLE_FLAG_COMPILED, true);
     157           0 :                         break;
     158             :                     }
     159           0 :                 }
     160             :             }
     161           0 :             variable_node->set_flag(Node::flag_t::NODE_VARIABLE_FLAG_INUSE, true);
     162             :         }
     163           0 :         return;
     164             :     }
     165             : 
     166           0 :     variable_node->set_flag(Node::flag_t::NODE_VARIABLE_FLAG_DEFINED, true);
     167           0 :     variable_node->set_flag(Node::flag_t::NODE_VARIABLE_FLAG_INUSE, !side_effects_only);
     168             : 
     169           0 :     bool const constant(variable_node->get_flag(Node::flag_t::NODE_VARIABLE_FLAG_CONST));
     170             : 
     171             :     // make sure to get the attributes before the node gets locked
     172             :     // (we know that the result is true in this case)
     173           0 :     get_attribute(variable_node, Node::attribute_t::NODE_ATTR_DEFINED);
     174             : 
     175           0 :     NodeLock ln(variable_node);
     176           0 :     int set(0);
     177             : 
     178           0 :     for(size_t idx(0); idx < max_children; ++idx)
     179             :     {
     180           0 :         Node::pointer_t child(variable_node->get_child(idx));
     181           0 :         switch(child->get_type())
     182             :         {
     183             :         case Node::node_t::NODE_UNKNOWN:
     184           0 :             break;
     185             : 
     186             :         case Node::node_t::NODE_SET:
     187             :             {
     188           0 :                 Node::pointer_t expr(child->get_child(0));
     189           0 :                 if(expr->get_type() == Node::node_t::NODE_PRIVATE
     190           0 :                 || expr->get_type() == Node::node_t::NODE_PUBLIC)
     191             :                 {
     192             :                     // this is a list of attributes
     193           0 :                     ++set;
     194             :                 }
     195           0 :                 else if(set == 0
     196           0 :                      && (!side_effects_only || expr->has_side_effects()))
     197             :                 {
     198           0 :                     expression(expr);
     199           0 :                     variable_node->set_flag(Node::flag_t::NODE_VARIABLE_FLAG_COMPILED, true);
     200           0 :                     variable_node->set_flag(Node::flag_t::NODE_VARIABLE_FLAG_INUSE, true);
     201             :                 }
     202           0 :                 ++set;
     203             :             }
     204           0 :             break;
     205             : 
     206             :         default:
     207             :             // define the variable type in this case
     208           0 :             expression(child);
     209           0 :             if(!variable_node->get_link(Node::link_t::LINK_TYPE))
     210             :             {
     211           0 :                 variable_node->set_link(Node::link_t::LINK_TYPE, child->get_link(Node::link_t::LINK_INSTANCE));
     212             :             }
     213           0 :             break;
     214             : 
     215             :         }
     216           0 :     }
     217             : 
     218           0 :     if(set > 1)
     219             :     {
     220           0 :         variable_node->to_var_attributes();
     221           0 :         if(!constant)
     222             :         {
     223           0 :             Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_NEED_CONST, variable_node->get_position());
     224           0 :             msg << "a variable cannot be a list of attributes unless it is made constant and '" << variable_node->get_string() << "' is not constant.";
     225             :         }
     226             :     }
     227             :     else
     228             :     {
     229             :         // read the initializer (we're expecting an expression, but
     230             :         // if this is only one identifier or PUBLIC or PRIVATE then
     231             :         // we're in a special case...)
     232           0 :         add_variable(variable_node);
     233           0 :     }
     234             : }
     235             : 
     236             : 
     237           0 : void Compiler::add_variable(Node::pointer_t variable_node)
     238             : {
     239             :     // For variables, we want to save a link in the
     240             :     // first directive list; this is used to clear
     241             :     // all the variables whenever a frame is left
     242             :     // and enables us to declare local variables as
     243             :     // such in functions
     244             :     //
     245             :     // [i.e. local variables defined in a frame are
     246             :     // undefined once you quit that frame; we do that
     247             :     // because the Flash instructions don't give us
     248             :     // correct frame management and a goto inside a
     249             :     // frame would otherwise possibly use the wrong
     250             :     // variable value!]
     251           0 :     Node::pointer_t parent(variable_node);
     252           0 :     bool first(true);
     253             :     for(;;)
     254             :     {
     255           0 :         parent = parent->get_parent();
     256           0 :         switch(parent->get_type())
     257             :         {
     258             :         case Node::node_t::NODE_DIRECTIVE_LIST:
     259           0 :             if(first)
     260             :             {
     261           0 :                 first = false;
     262           0 :                 parent->add_variable(variable_node);
     263             :             }
     264           0 :             break;
     265             : 
     266             :         case Node::node_t::NODE_FUNCTION:
     267             :             // mark the variable as local
     268           0 :             variable_node->set_flag(Node::flag_t::NODE_VARIABLE_FLAG_LOCAL, true);
     269           0 :             if(first)
     270             :             {
     271           0 :                 parent->add_variable(variable_node);
     272             :             }
     273           0 :             return;
     274             : 
     275             :         case Node::node_t::NODE_CLASS:
     276             :         case Node::node_t::NODE_INTERFACE:
     277             :             // mark the variable as a member of this class or interface
     278           0 :             variable_node->set_flag(Node::flag_t::NODE_VARIABLE_FLAG_MEMBER, true);
     279           0 :             if(first)
     280             :             {
     281           0 :                 parent->add_variable(variable_node);
     282             :             }
     283           0 :             return;
     284             : 
     285             :         case Node::node_t::NODE_PROGRAM:
     286             :         case Node::node_t::NODE_PACKAGE:
     287             :             // variable is global
     288           0 :             if(first)
     289             :             {
     290           0 :                 parent->add_variable(variable_node);
     291             :             }
     292           0 :             return;
     293             : 
     294             :         default:
     295           0 :             break;
     296             : 
     297             :         }
     298           0 :     }
     299             : }
     300             : 
     301             : 
     302             : 
     303             : 
     304          63 : }
     305             : // namespace as2js
     306             : 
     307             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.10