LCOV - code coverage report
Current view: top level - as2js/lib - node_attribute.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 87 87 100.0 %
Date: 2014-08-10 Functions: 6 6 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* node_attribute.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             : #include    "as2js/message.h"
      40             : 
      41             : 
      42             : namespace as2js
      43             : {
      44             : 
      45             : 
      46             : 
      47             : /**********************************************************************/
      48             : /**********************************************************************/
      49             : /***  NODE ATTRIBUTE  *************************************************/
      50             : /**********************************************************************/
      51             : /**********************************************************************/
      52             : 
      53             : namespace
      54             : {
      55             : 
      56             : enum
      57             : {
      58             :     ATTRIBUTES_GROUP_CONDITIONAL_COMPILATION,
      59             :     ATTRIBUTES_GROUP_FUNCTION_TYPE,
      60             :     ATTRIBUTES_GROUP_FUNCTION_CONTRACT,
      61             :     ATTRIBUTES_GROUP_SWITCH_TYPE,
      62             :     ATTRIBUTES_GROUP_MEMBER_VISIBILITY
      63             : };
      64             : char const *g_attribute_groups[] =
      65             : {
      66             :     [ATTRIBUTES_GROUP_CONDITIONAL_COMPILATION] = "true and false",
      67             :     [ATTRIBUTES_GROUP_FUNCTION_TYPE] = "static, abstract, virtual, and constructor; also abstract and native",
      68             :     [ATTRIBUTES_GROUP_FUNCTION_CONTRACT] = "require else and ensure then",
      69             :     [ATTRIBUTES_GROUP_SWITCH_TYPE] = "foreach, nobreak, and autobreak",
      70             :     [ATTRIBUTES_GROUP_MEMBER_VISIBILITY] = "public, private, and protected"
      71             : };
      72             : 
      73             : }
      74             : // no name namesoace
      75             : 
      76             : 
      77             : /** \brief Get the current status of an attribute.
      78             :  *
      79             :  * This function returns true or false depending on the current status
      80             :  * of the specified attribute.
      81             :  *
      82             :  * The function verifies that the specified attribute (\p a) corresponds to
      83             :  * the type of data you are dealing with.
      84             :  *
      85             :  * If the attribute was never set, this function returns false.
      86             :  *
      87             :  * \param[in] a  The attribute to retrieve.
      88             :  *
      89             :  * \return true if the attribute was set, false otherwise.
      90             :  */
      91   524594701 : bool Node::get_attribute(attribute_t a) const
      92             : {
      93   524594701 :     verify_attribute(a);
      94   524592817 :     return f_attributes[static_cast<size_t>(a)];
      95             : }
      96             : 
      97             : 
      98             : /** \brief Set an attribute.
      99             :  *
     100             :  * This function sets the specified attribute \p a to the specified value \p v
     101             :  * in this Node object.
     102             :  *
     103             :  * The function verifies that the specified attribute (\p a) corresponds to
     104             :  * the type of data you are dealing with.
     105             :  *
     106             :  * \param[in] a  The flag to set.
     107             :  * \param[in] v  The new value for the flag.
     108             :  */
     109       42584 : void Node::set_attribute(attribute_t a, bool v)
     110             : {
     111       42584 :     verify_attribute(a);
     112       38816 :     if(v)
     113             :     {
     114             :         // exclusive attributes do not generate an exception, instead
     115             :         // we test the return value and if two exclusive attribute flags
     116             :         // were to be set simultaneously, we prevent the second one from
     117             :         // being set
     118       27747 :         if(!verify_exclusive_attributes(a))
     119             :         {
     120         290 :             return;
     121             :         }
     122             :     }
     123       38526 :     f_attributes[static_cast<size_t>(a)] = v;
     124             : }
     125             : 
     126             : 
     127             : /** \brief Verify that f corresponds to the data type.
     128             :  *
     129             :  * This function verifies that f corresponds to a valid flag according
     130             :  * to the type of this Node object.
     131             :  *
     132             :  * \param[in] a  The flag or attribute to check.
     133             :  */
     134   524637285 : void Node::verify_attribute(attribute_t a) const
     135             : {
     136   524637285 :     switch(a)
     137             :     {
     138             :     // member visibility
     139             :     case attribute_t::NODE_ATTR_PUBLIC:
     140             :     case attribute_t::NODE_ATTR_PRIVATE:
     141             :     case attribute_t::NODE_ATTR_PROTECTED:
     142             :     case attribute_t::NODE_ATTR_INTERNAL:
     143             :     case attribute_t::NODE_ATTR_TRANSIENT:
     144             :     case attribute_t::NODE_ATTR_VOLATILE:
     145             : 
     146             :     // function member type
     147             :     case attribute_t::NODE_ATTR_STATIC:
     148             :     case attribute_t::NODE_ATTR_ABSTRACT:
     149             :     case attribute_t::NODE_ATTR_VIRTUAL:
     150             :     case attribute_t::NODE_ATTR_ARRAY:
     151             : 
     152             :     // function contracts
     153             :     case attribute_t::NODE_ATTR_REQUIRE_ELSE:
     154             :     case attribute_t::NODE_ATTR_ENSURE_THEN:
     155             : 
     156             :     // function/variable is defined in your system (execution env.)
     157             :     case attribute_t::NODE_ATTR_NATIVE:
     158             : 
     159             :     // function/variable will be removed in future releases, do not use
     160             :     case attribute_t::NODE_ATTR_DEPRECATED:
     161             :     case attribute_t::NODE_ATTR_UNSAFE:
     162             : 
     163             :     // operator overload (function member)
     164             :     case attribute_t::NODE_ATTR_CONSTRUCTOR:
     165             : 
     166             :     // function & member constrains
     167             :     case attribute_t::NODE_ATTR_FINAL:
     168             :     case attribute_t::NODE_ATTR_ENUMERABLE:
     169             : 
     170             :     // conditional compilation
     171             :     case attribute_t::NODE_ATTR_TRUE:
     172             :     case attribute_t::NODE_ATTR_FALSE:
     173             :     case attribute_t::NODE_ATTR_UNUSED:                      // if definition is used, error!
     174             : 
     175             :     // class attribute (whether a class can be enlarged at run time)
     176             :     case attribute_t::NODE_ATTR_DYNAMIC:
     177             : 
     178             :     // switch attributes
     179             :     case attribute_t::NODE_ATTR_FOREACH:
     180             :     case attribute_t::NODE_ATTR_NOBREAK:
     181             :     case attribute_t::NODE_ATTR_AUTOBREAK:
     182             :         // TBD -- we'll need to see whether we want to limit the attributes
     183             :         //        on a per node type basis and how we can do that properly
     184   504454133 :         if(f_type != node_t::NODE_PROGRAM)
     185             :         {
     186   504454058 :             return;
     187             :         }
     188          75 :         break;
     189             : 
     190             :     // attributes were defined
     191             :     case attribute_t::NODE_ATTR_DEFINED:
     192             :         // all nodes can receive this flag
     193    20177575 :         return;
     194             : 
     195             :     case attribute_t::NODE_ATTR_max:
     196         507 :         break;
     197             : 
     198             :     // default: -- do not define so the compiler can tell us if
     199             :     //             an enumeration is missing in this case
     200             :     }
     201             : 
     202   524637285 :     throw exception_internal_error("attribute / type missmatch in Node::verify_attribute()");
     203             : }
     204             : 
     205             : 
     206             : /** \brief Verify that we can indeed set an attribute.
     207             :  *
     208             :  * Many attributes are mutually exclusive. This function checks that
     209             :  * only one of a group of attributes gets set.
     210             :  *
     211             :  * This function is not called if you clear an attribute since in that
     212             :  * case the default applies.
     213             :  *
     214             :  * \param[in] a  The attribute being set.
     215             :  *
     216             :  * \return true if the flags are not in conflict.
     217             :  */
     218       27747 : bool Node::verify_exclusive_attributes(attribute_t a) const
     219             : {
     220       27747 :     bool conflict(false);
     221             :     char const *names;
     222       27747 :     switch(a)
     223             :     {
     224             :     case attribute_t::NODE_ATTR_ARRAY:
     225             :     case attribute_t::NODE_ATTR_DEFINED:
     226             :     case attribute_t::NODE_ATTR_DEPRECATED:
     227             :     case attribute_t::NODE_ATTR_DYNAMIC:
     228             :     case attribute_t::NODE_ATTR_ENUMERABLE:
     229             :     case attribute_t::NODE_ATTR_FINAL:
     230             :     case attribute_t::NODE_ATTR_INTERNAL:
     231             :     case attribute_t::NODE_ATTR_TRANSIENT:
     232             :     case attribute_t::NODE_ATTR_UNSAFE:
     233             :     case attribute_t::NODE_ATTR_UNUSED:
     234             :     case attribute_t::NODE_ATTR_VOLATILE:
     235             :         // these attributes have no conflicts
     236        4929 :         return true;
     237             : 
     238             :     case attribute_t::NODE_ATTR_REQUIRE_ELSE:
     239        8631 :         conflict = f_attributes[static_cast<size_t>(attribute_t::NODE_ATTR_ENSURE_THEN)];
     240        8631 :         names = g_attribute_groups[ATTRIBUTES_GROUP_FUNCTION_CONTRACT];
     241        8631 :         break;
     242             : 
     243             :     case attribute_t::NODE_ATTR_ENSURE_THEN:
     244        8631 :         conflict = f_attributes[static_cast<size_t>(attribute_t::NODE_ATTR_REQUIRE_ELSE)];
     245        8631 :         names = g_attribute_groups[ATTRIBUTES_GROUP_FUNCTION_CONTRACT];
     246        8631 :         break;
     247             : 
     248             :     case attribute_t::NODE_ATTR_NATIVE:
     249         439 :         conflict = f_attributes[static_cast<size_t>(attribute_t::NODE_ATTR_ABSTRACT)];
     250         439 :         names = g_attribute_groups[ATTRIBUTES_GROUP_FUNCTION_TYPE];
     251         439 :         break;
     252             : 
     253             :     // member visibility
     254             :     case attribute_t::NODE_ATTR_PUBLIC:
     255         428 :         conflict = f_attributes[static_cast<size_t>(attribute_t::NODE_ATTR_PRIVATE)]
     256         428 :                 || f_attributes[static_cast<size_t>(attribute_t::NODE_ATTR_PROTECTED)];
     257         428 :         names = g_attribute_groups[ATTRIBUTES_GROUP_MEMBER_VISIBILITY];
     258         428 :         break;
     259             : 
     260             :     case attribute_t::NODE_ATTR_PRIVATE:
     261         428 :         conflict = f_attributes[static_cast<size_t>(attribute_t::NODE_ATTR_PUBLIC)]
     262         428 :                 || f_attributes[static_cast<size_t>(attribute_t::NODE_ATTR_PROTECTED)];
     263         428 :         names = g_attribute_groups[ATTRIBUTES_GROUP_MEMBER_VISIBILITY];
     264         428 :         break;
     265             : 
     266             :     case attribute_t::NODE_ATTR_PROTECTED:
     267         428 :         conflict = f_attributes[static_cast<size_t>(attribute_t::NODE_ATTR_PUBLIC)]
     268         428 :                 || f_attributes[static_cast<size_t>(attribute_t::NODE_ATTR_PRIVATE)];
     269         428 :         names = g_attribute_groups[ATTRIBUTES_GROUP_MEMBER_VISIBILITY];
     270         428 :         break;
     271             : 
     272             :     // function type group
     273             :     case attribute_t::NODE_ATTR_STATIC:
     274         418 :         conflict = f_attributes[static_cast<size_t>(attribute_t::NODE_ATTR_ABSTRACT)]
     275         408 :                 || f_attributes[static_cast<size_t>(attribute_t::NODE_ATTR_CONSTRUCTOR)]
     276         826 :                 || f_attributes[static_cast<size_t>(attribute_t::NODE_ATTR_VIRTUAL)];
     277         418 :         names = g_attribute_groups[ATTRIBUTES_GROUP_FUNCTION_TYPE];
     278         418 :         break;
     279             : 
     280             :     case attribute_t::NODE_ATTR_ABSTRACT:
     281         418 :         conflict = f_attributes[static_cast<size_t>(attribute_t::NODE_ATTR_STATIC)]
     282         408 :                 || f_attributes[static_cast<size_t>(attribute_t::NODE_ATTR_CONSTRUCTOR)]
     283         398 :                 || f_attributes[static_cast<size_t>(attribute_t::NODE_ATTR_VIRTUAL)]
     284         826 :                 || f_attributes[static_cast<size_t>(attribute_t::NODE_ATTR_NATIVE)];
     285         418 :         names = g_attribute_groups[ATTRIBUTES_GROUP_FUNCTION_TYPE];
     286         418 :         break;
     287             : 
     288             :     case attribute_t::NODE_ATTR_VIRTUAL:
     289         418 :         conflict = f_attributes[static_cast<size_t>(attribute_t::NODE_ATTR_STATIC)]
     290         408 :                 || f_attributes[static_cast<size_t>(attribute_t::NODE_ATTR_CONSTRUCTOR)]
     291         826 :                 || f_attributes[static_cast<size_t>(attribute_t::NODE_ATTR_ABSTRACT)];
     292         418 :         names = g_attribute_groups[ATTRIBUTES_GROUP_FUNCTION_TYPE];
     293         418 :         break;
     294             : 
     295             :     case attribute_t::NODE_ATTR_CONSTRUCTOR:
     296         418 :         conflict = f_attributes[static_cast<size_t>(attribute_t::NODE_ATTR_STATIC)]
     297         408 :                 || f_attributes[static_cast<size_t>(attribute_t::NODE_ATTR_VIRTUAL)]
     298         826 :                 || f_attributes[static_cast<size_t>(attribute_t::NODE_ATTR_ABSTRACT)];
     299         418 :         names = g_attribute_groups[ATTRIBUTES_GROUP_FUNCTION_TYPE];
     300         418 :         break;
     301             : 
     302             :     // switch type group
     303             :     case attribute_t::NODE_ATTR_FOREACH:
     304         428 :         conflict = f_attributes[static_cast<size_t>(attribute_t::NODE_ATTR_NOBREAK)]
     305         428 :                 || f_attributes[static_cast<size_t>(attribute_t::NODE_ATTR_AUTOBREAK)];
     306         428 :         names = g_attribute_groups[ATTRIBUTES_GROUP_SWITCH_TYPE];
     307         428 :         break;
     308             : 
     309             :     case attribute_t::NODE_ATTR_NOBREAK:
     310         428 :         conflict = f_attributes[static_cast<size_t>(attribute_t::NODE_ATTR_FOREACH)]
     311         428 :                 || f_attributes[static_cast<size_t>(attribute_t::NODE_ATTR_AUTOBREAK)];
     312         428 :         names = g_attribute_groups[ATTRIBUTES_GROUP_SWITCH_TYPE];
     313         428 :         break;
     314             : 
     315             :     case attribute_t::NODE_ATTR_AUTOBREAK:
     316         428 :         conflict = f_attributes[static_cast<size_t>(attribute_t::NODE_ATTR_FOREACH)]
     317         428 :                 || f_attributes[static_cast<size_t>(attribute_t::NODE_ATTR_NOBREAK)];
     318         428 :         names = g_attribute_groups[ATTRIBUTES_GROUP_SWITCH_TYPE];
     319         428 :         break;
     320             : 
     321             :     // conditional compilation group
     322             :     case attribute_t::NODE_ATTR_TRUE:
     323         439 :         conflict = f_attributes[static_cast<size_t>(attribute_t::NODE_ATTR_FALSE)];
     324         439 :         names = g_attribute_groups[ATTRIBUTES_GROUP_CONDITIONAL_COMPILATION];
     325         439 :         break;
     326             : 
     327             :     case attribute_t::NODE_ATTR_FALSE:
     328         438 :         conflict = f_attributes[static_cast<size_t>(attribute_t::NODE_ATTR_TRUE)];
     329         438 :         names = g_attribute_groups[ATTRIBUTES_GROUP_CONDITIONAL_COMPILATION];
     330         438 :         break;
     331             : 
     332             :     case attribute_t::NODE_ATTR_max:
     333             :         // this should already have been caught in the verify_attribute() function
     334             :         throw exception_internal_error("invalid attribute / flag in Node::verify_attribute()"); // LCOV_EXCL_LINE
     335             : 
     336             :     // default: -- do not define so the compiler can tell us if
     337             :     //             an enumeration is missing in this case
     338             :     // note: verify_attribute(() is called before this function
     339             :     //       and it catches completely invalid attribute numbers
     340             :     //       (i.e. negative, larger than NODE_ATTR_max)
     341             :     }
     342             : 
     343       22818 :     if(conflict)
     344             :     {
     345             :         // this can be a user error so we emit an error instead of throwing
     346         290 :         Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_INVALID_ATTRIBUTES, f_position);
     347         290 :         msg << "Attributes " << names << " are mutually exclusive. Only one of them can be used.";
     348         290 :         return false;
     349             :     }
     350             : 
     351       27747 :     return true;
     352             : }
     353             : 
     354             : 
     355          20 : }
     356             : // namespace as2js
     357             : 
     358             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.9