LCOV - code coverage report
Current view: top level - lib - compiler_class.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 9 480 1.9 %
Date: 2014-11-22 Functions: 3 22 13.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* compiler_class.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           0 : bool Compiler::is_dynamic_class(Node::pointer_t class_node)
      47             : {
      48             :     // can we know?
      49           0 :     if(!class_node)
      50             :     {
      51           0 :         return true;
      52             :     }
      53             : 
      54             :     // already determined?
      55           0 :     if(get_attribute(class_node, Node::attribute_t::NODE_ATTR_DYNAMIC))
      56             :     {
      57           0 :         return true;
      58             :     }
      59             : 
      60           0 :     size_t const max_children(class_node->get_children_size());
      61           0 :     for(size_t idx = 0; idx < max_children; ++idx)
      62             :     {
      63           0 :         Node::pointer_t child(class_node->get_child(idx));
      64           0 :         if(child->get_type() == Node::node_t::NODE_EXTENDS)
      65             :         {
      66             :             // TODO: once we support multiple extends, work on
      67             :             //       the list of them
      68           0 :             Node::pointer_t name(child->get_child(0));
      69           0 :             Node::pointer_t extends(name ? name->get_link(Node::link_t::LINK_INSTANCE) : name);
      70           0 :             if(extends)
      71             :             {
      72           0 :                 if(extends->get_string() == "Object")
      73             :                 {
      74             :                     // we ignore the dynamic flag of Object (that is a
      75             :                     // hack in the language reference!)
      76           0 :                     return false;
      77             :                 }
      78             :                 // continue at the next level (depth increasing)
      79           0 :                 return is_dynamic_class(extends); // recursive
      80             :             }
      81           0 :             break;
      82             :         }
      83           0 :     }
      84             : 
      85           0 :     return false;
      86             : }
      87             : 
      88             : 
      89           0 : void Compiler::check_member(Node::pointer_t ref, Node::pointer_t field, Node::pointer_t field_name)
      90             : {
      91           0 :     if(!field)
      92             :     {
      93           0 :         Node::pointer_t type(ref->get_link(Node::link_t::LINK_TYPE));
      94           0 :         if(!is_dynamic_class(type))
      95             :         {
      96           0 :             Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_STATIC, ref->get_position());
      97           0 :             msg << "'" << ref->get_string()
      98           0 :                 << ": " << type->get_string()
      99           0 :                 << "' is not dynamic and thus it cannot be used with unknown member '" << field_name->get_string()
     100           0 :                 << "'.";
     101             :         }
     102           0 :         return;
     103             :     }
     104             : 
     105           0 :     Node::pointer_t obj(ref->get_link(Node::link_t::LINK_INSTANCE));
     106           0 :     if(!obj)
     107             :     {
     108           0 :         return;
     109             :     }
     110             : 
     111             :     // If the link is directly a class or an interface
     112             :     // then the field needs to be a sub-class, sub-interface,
     113             :     // static function, static variable or constant variable.
     114           0 :     if(obj->get_type() != Node::node_t::NODE_CLASS
     115           0 :     && obj->get_type() != Node::node_t::NODE_INTERFACE)
     116             :     {
     117           0 :         return;
     118             :     }
     119             : 
     120           0 :     bool err(false);
     121           0 :     switch(field->get_type())
     122             :     {
     123             :     case Node::node_t::NODE_CLASS:
     124             :     case Node::node_t::NODE_INTERFACE:
     125           0 :         break;
     126             : 
     127             :     case Node::node_t::NODE_FUNCTION:
     128             :         //
     129             :         // note that constructors are considered static, but
     130             :         // you cannot just call a constructor...
     131             :         //
     132             :         // operators are static and thus we will be fine with
     133             :         // operators (since you need to call operators with
     134             :         // all the required inputs)
     135             :         //
     136           0 :         err = !get_attribute(field, Node::attribute_t::NODE_ATTR_STATIC)
     137           0 :            && !field->get_flag(Node::flag_t::NODE_FUNCTION_FLAG_OPERATOR);
     138           0 :         break;
     139             : 
     140             :     case Node::node_t::NODE_VARIABLE:
     141             :         // static const foo = 123; is fine
     142           0 :         err = !get_attribute(field, Node::attribute_t::NODE_ATTR_STATIC)
     143           0 :            && !field->get_flag(Node::flag_t::NODE_VARIABLE_FLAG_CONST);
     144           0 :         break;
     145             : 
     146             :     default:
     147           0 :         err = true;
     148           0 :         break;
     149             : 
     150             :     }
     151             : 
     152           0 :     if(err)
     153             :     {
     154           0 :         Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_INSTANCE_EXPECTED, ref->get_position());
     155           0 :         msg << "you cannot directly access non-static functions and non-static/constant variables in a class ('"
     156           0 :             << field->get_string()
     157           0 :             << "' here); you need to use an instance instead.";
     158           0 :     }
     159             : }
     160             : 
     161             : 
     162           0 : bool Compiler::is_constructor(Node::pointer_t function_node)
     163             : {
     164             :     // user defined constructor?
     165           0 :     if(get_attribute(function_node, Node::attribute_t::NODE_ATTR_CONSTRUCTOR))
     166             :     {
     167           0 :         return true;
     168             :     }
     169             : 
     170             :     // search the first a NODE_CLASS with the same name
     171           0 :     for(Node::pointer_t parent(function_node->get_parent()); parent; parent = parent->get_parent())
     172             :     {
     173             :         // Note: here I made a note that sub-functions cannot be
     174             :         //       constructors which is true in ActionScript, but
     175             :         //       not in JavaScript. We actually make use of a
     176             :         //       sub-function to create inheritance that works
     177             :         //       in JavaScript (older browsers required a "new Object"
     178             :         //       to generate inheritance which was a big problem.)
     179             :         //       However, in our language, we probably want people
     180             :         //       to make use of the class keyword anyway, so they
     181             :         //       could create a sub-class inside a function and
     182             :         //       we are back in business!
     183             :         //
     184           0 :         switch(parent->get_type())
     185             :         {
     186             :         case Node::node_t::NODE_PACKAGE:
     187             :         case Node::node_t::NODE_PROGRAM:
     188             :         case Node::node_t::NODE_FUNCTION:    // sub-functions cannot be constructors
     189             :         case Node::node_t::NODE_INTERFACE:
     190           0 :             return false;
     191             : 
     192             :         case Node::node_t::NODE_CLASS:
     193             :             // we found the class in question
     194           0 :             return parent->get_string() == function_node->get_string();
     195             : 
     196             :         default:
     197             :             // ignore all the other nodes
     198           0 :             break;
     199             : 
     200             :         }
     201           0 :     }
     202             : 
     203           0 :     return false;
     204             : }
     205             : 
     206             : 
     207           0 : void Compiler::check_super_validity(Node::pointer_t expr)
     208             : {
     209           0 :     if(!expr)
     210             :     {
     211           0 :         return;
     212             :     }
     213           0 :     Node::pointer_t parent(expr->get_parent());
     214           0 :     if(!parent)
     215             :     {
     216           0 :         return;
     217             :     }
     218             : 
     219           0 :     bool const needs_constructor(parent->get_type() == Node::node_t::NODE_CALL);
     220           0 :     bool first_function(true);
     221           0 :     bool continue_testing(true);
     222           0 :     for(; parent && continue_testing; parent = parent->get_parent())
     223             :     {
     224           0 :         switch(parent->get_type())
     225             :         {
     226             :         case Node::node_t::NODE_FUNCTION:
     227           0 :             if(first_function)
     228             :             {
     229             :                 // We have two super's
     230             :                 // 1) super(params) in constructors
     231             :                 // 2) super.field(params) in non-static functions
     232             :                 // case 1 is recognized as having a direct parent
     233             :                 // of type call (see at start of function!)
     234             :                 // case 2 is all other cases
     235             :                 // in both cases we need to be defined in a class
     236           0 :                 if(needs_constructor)
     237             :                 {
     238           0 :                     if(!is_constructor(parent))
     239             :                     {
     240           0 :                         Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_INVALID_EXPRESSION, expr->get_position());
     241           0 :                         msg << "'super()' cannot be used outside of a constructor function.";
     242           0 :                         return;
     243             :                     }
     244             :                 }
     245             :                 else
     246             :                 {
     247           0 :                     if(parent->get_flag(Node::flag_t::NODE_FUNCTION_FLAG_OPERATOR)
     248           0 :                     || get_attribute(parent, Node::attribute_t::NODE_ATTR_STATIC)
     249           0 :                     || get_attribute(parent, Node::attribute_t::NODE_ATTR_CONSTRUCTOR)
     250           0 :                     || is_constructor(parent))
     251             :                     {
     252           0 :                         Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_INVALID_EXPRESSION, expr->get_position());
     253           0 :                         msg << "'super.member()' cannot be used in a static function nor a constructor.";
     254           0 :                         return;
     255             :                     }
     256             :                 }
     257             :                 // TODO: Test that this is correct, it was missing...
     258             :                 //       Once false, we skip all the tests from this
     259             :                 //       block.
     260           0 :                 first_function = false;
     261             :             }
     262             :             else
     263             :             {
     264             :                 // Can it be used in sub-functions?
     265             :                 // If we arrive here then we can err if
     266             :                 // super and/or this are not available
     267             :                 // in sub-functions... TBD
     268             :             }
     269           0 :             break;
     270             : 
     271             :         case Node::node_t::NODE_CLASS:
     272             :         case Node::node_t::NODE_INTERFACE:
     273           0 :             return;
     274             : 
     275             :         case Node::node_t::NODE_PROGRAM:
     276             :         case Node::node_t::NODE_ROOT:
     277           0 :             continue_testing = false;
     278           0 :             break;
     279             : 
     280             :         default:
     281           0 :             break;
     282             : 
     283             :         }
     284             :     }
     285             : 
     286           0 :     if(needs_constructor)
     287             :     {
     288           0 :         Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_INVALID_EXPRESSION, expr->get_position());
     289           0 :         msg << "'super()' cannot be used outside a class definition.";
     290           0 :     }
     291             : #if 0
     292             :     else {
     293             : fprintf(stderr, "WARNING: 'super.member()' should only be used in a class function.\n");
     294             :     }
     295             : #endif
     296             : }
     297             : 
     298             : 
     299           0 : void Compiler::link_type(Node::pointer_t type)
     300             : {
     301             :     // already linked?
     302           0 :     Node::pointer_t link(type->get_link(Node::link_t::LINK_INSTANCE));
     303           0 :     if(link)
     304             :     {
     305           0 :         return;
     306             :     }
     307             : 
     308           0 :     if(type->get_type() != Node::node_t::NODE_IDENTIFIER
     309           0 :     && type->get_type() != Node::node_t::NODE_STRING)
     310             :     {
     311             :         // we cannot link (determine) the type at compile time
     312             :         // if we have a type expression
     313             : //fprintf(stderr, "WARNING: dynamic type?!\n");
     314           0 :         return;
     315             :     }
     316             : 
     317           0 :     if(type->get_flag(Node::flag_t::NODE_IDENTIFIER_FLAG_TYPED))
     318             :     {
     319             :         // if it failed already, fail only once...
     320           0 :         return;
     321             :     }
     322           0 :     type->set_flag(Node::flag_t::NODE_IDENTIFIER_FLAG_TYPED, true);
     323             : 
     324           0 :     Node::pointer_t object;
     325           0 :     if(!resolve_name(type, type, object, Node::pointer_t(), 0))
     326             :     {
     327             :         // unknown type?! -- should we return a link to Object?
     328           0 :         Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_INVALID_EXPRESSION, type->get_position());
     329           0 :         msg << "cannot find a class definition for type '" << type->get_string() << "'.";
     330           0 :         return;
     331             :     }
     332             : 
     333           0 :     if(object->get_type() != Node::node_t::NODE_CLASS
     334           0 :     && object->get_type() != Node::node_t::NODE_INTERFACE)
     335             :     {
     336           0 :         Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_INVALID_EXPRESSION, type->get_position());
     337           0 :         msg << "the name '" << type->get_string() << "' is not referencing a class nor an interface.";
     338           0 :         return;
     339             :     }
     340             : 
     341             :     // it worked.
     342           0 :     type->set_link(Node::link_t::LINK_INSTANCE, object);
     343             : }
     344             : 
     345             : 
     346           0 : bool Compiler::find_in_extends(Node::pointer_t link, Node::pointer_t field, int& funcs, Node::pointer_t& resolution, Node::pointer_t params, int const search_flags)
     347             : {
     348             :     // try to see if we are inheriting that field...
     349           0 :     NodeLock ln(link);
     350           0 :     size_t const max_children(link->get_children_size());
     351           0 :     size_t count(0);
     352           0 :     for(size_t idx(0); idx < max_children; ++idx)
     353             :     {
     354           0 :         Node::pointer_t extends(link->get_child(idx));
     355           0 :         if(extends->get_type() == Node::node_t::NODE_EXTENDS)
     356             :         {
     357             :             // TODO: support list of extends (see IMPLEMENTS below!)
     358           0 :             if(extends->get_children_size() == 1)
     359             :             {
     360           0 :                 Node::pointer_t type(extends->get_child(0));
     361           0 :                 link_type(type);
     362           0 :                 Node::pointer_t sub_link(type->get_link(Node::link_t::LINK_INSTANCE));
     363           0 :                 if(!sub_link)
     364             :                 {
     365             :                     // we cannot search a field in nothing...
     366           0 :                     Message msg(message_level_t::MESSAGE_LEVEL_WARNING, err_code_t::AS_ERR_TYPE_NOT_LINKED, link->get_position());
     367           0 :                     msg << "type not linked, cannot lookup member.";
     368             :                 }
     369           0 :                 else if(find_any_field(sub_link, field, funcs, resolution, params, search_flags))
     370             :                 {
     371           0 :                     ++count;
     372           0 :                 }
     373             :             }
     374             : //fprintf(stderr, "Extends existing! (%d)\n", extends.GetChildCount());
     375             :         }
     376           0 :         else if(extends->get_type() == Node::node_t::NODE_IMPLEMENTS)
     377             :         {
     378           0 :             if(extends->get_children_size() == 1)
     379             :             {
     380           0 :                 Node::pointer_t type(extends->get_child(0));
     381           0 :                 if(type->get_type() == Node::node_t::NODE_LIST)
     382             :                 {
     383           0 :                     size_t cnt(type->get_children_size());
     384           0 :                     for(size_t j(0); j < cnt; ++j)
     385             :                     {
     386           0 :                         Node::pointer_t child(type->get_child(j));
     387           0 :                         link_type(child);
     388           0 :                         Node::pointer_t sub_link(child->get_link(Node::link_t::LINK_INSTANCE));
     389           0 :                         if(!sub_link)
     390             :                         {
     391             :                             // we cannot search a field in nothing...
     392           0 :                             Message msg(message_level_t::MESSAGE_LEVEL_WARNING, err_code_t::AS_ERR_TYPE_NOT_LINKED, link->get_position());
     393           0 :                             msg << "type not linked, cannot lookup member.";
     394             :                         }
     395           0 :                         else if(find_any_field(sub_link, field, funcs, resolution, params, search_flags)) // recursive
     396             :                         {
     397           0 :                             ++count;
     398             :                         }
     399           0 :                     }
     400             :                 }
     401             :                 else
     402             :                 {
     403           0 :                     link_type(type);
     404           0 :                     Node::pointer_t sub_link(type->get_link(Node::link_t::LINK_INSTANCE));
     405           0 :                     if(!sub_link)
     406             :                     {
     407             :                         // we can't search a field in nothing...
     408           0 :                         Message msg(message_level_t::MESSAGE_LEVEL_WARNING, err_code_t::AS_ERR_TYPE_NOT_LINKED, link->get_position());
     409           0 :                         msg << "type not linked, cannot lookup member.";
     410             :                     }
     411           0 :                     else if(find_any_field(sub_link, field, funcs, resolution, params, search_flags)) // recursive
     412             :                     {
     413           0 :                         ++count;
     414           0 :                     }
     415           0 :                 }
     416             :             }
     417             :         }
     418           0 :     }
     419             : 
     420           0 :     if(count == 1 || funcs != 0)
     421             :     {
     422           0 :         return true;
     423             :     }
     424             : 
     425           0 :     if(count == 0)
     426             :     {
     427             :         // NOTE: warning? error? This actually would just turn
     428             :         //     on a flag.
     429             :         //     As far as I know I now have an error in case
     430             :         //     the left hand side expression is a static
     431             :         //     class (opposed to a dynamic class which can
     432             :         //     have members added at runtime)
     433             : //fprintf(stderr, "     field not found...\n");
     434             :     }
     435             :     else
     436             :     {
     437           0 :         Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_DUPLICATES, field->get_position());
     438           0 :         msg << "found more than one match for '" << field->get_string() << "'.";
     439             :     }
     440             : 
     441           0 :     return false;
     442             : }
     443             : 
     444             : 
     445           0 : bool Compiler::check_field(Node::pointer_t link, Node::pointer_t field, int& funcs, Node::pointer_t& resolution, Node::pointer_t params, int const search_flags)
     446             : {
     447           0 :     NodeLock link_ln(link);
     448           0 :     size_t const max_children(link->get_children_size());
     449           0 :     for(size_t idx(0); idx < max_children; ++idx)
     450             :     {
     451           0 :         Node::pointer_t list(link->get_child(idx));
     452           0 :         if(list->get_type() != Node::node_t::NODE_DIRECTIVE_LIST)
     453             :         {
     454             :             // extends, implements, empty...
     455           0 :             continue;
     456             :         }
     457             : 
     458             :         // search in this list!
     459           0 :         NodeLock list_ln(list);
     460           0 :         size_t const max_list_children(list->get_children_size());
     461           0 :         for(size_t j(0); j < max_list_children; ++j)
     462             :         {
     463             :             // if we have a sub-list, generate a recursive call
     464           0 :             Node::pointer_t child(list->get_child(j));
     465           0 :             if(child->get_type() == Node::node_t::NODE_DIRECTIVE_LIST)
     466             :             {
     467           0 :                 if(check_field(list, field, funcs, resolution, params, search_flags)) // recursive
     468             :                 {
     469           0 :                     if(funcs_name(funcs, resolution, false))
     470             :                     {
     471           0 :                         return true;
     472             :                     }
     473             :                 }
     474             :             }
     475           0 :             else if(child->get_type() != Node::node_t::NODE_EMPTY)
     476             :             {
     477           0 :                 if(check_name(list, j, resolution, field, params, search_flags))
     478             :                 {
     479           0 :                     if(funcs_name(funcs, resolution))
     480             :                     {
     481           0 :                         Node::pointer_t inst(field->get_link(Node::link_t::LINK_INSTANCE));
     482           0 :                         if(!inst)
     483             :                         {
     484           0 :                             field->set_link(Node::link_t::LINK_INSTANCE, resolution);
     485             :                         }
     486           0 :                         else if(inst != resolution)
     487             :                         {
     488             :                             // if already defined, it should be the same or
     489             :                             // we have a real problem
     490           0 :                             throw exception_internal_error("found a LINK_INSTANCE twice, but it was different each time");
     491             :                         }
     492           0 :                         return true;
     493             :                     }
     494             :                 }
     495             :             }
     496           0 :         }
     497           0 :     }
     498             : 
     499           0 :     return false;
     500             : }
     501             : 
     502             : 
     503           0 : bool Compiler::find_any_field(Node::pointer_t link, Node::pointer_t field, int& funcs, Node::pointer_t& resolution, Node::pointer_t params, int const search_flags)
     504             : {
     505             : //fprintf(stderr, "Find Any Field...\n");
     506             : 
     507           0 :     if(check_field(link, field, funcs, resolution, params, search_flags))
     508             :     {
     509             : //fprintf(stderr, "Check Field true...\n");
     510           0 :         return true;
     511             :     }
     512           0 :     if(funcs != 0)
     513             :     {
     514             :         // TODO: stronger validation of functions
     515             :         // this is wrong, we need a depth test on the best
     516             :         // functions but we need to test all the functions
     517             :         // of inherited fields too
     518             : //fprintf(stderr, "funcs != 0 true...\n");
     519           0 :         return true;
     520             :     }
     521             : 
     522             : //fprintf(stderr, "FindInExtends?!...\n");
     523           0 :     return find_in_extends(link, field, funcs, resolution, params, search_flags); // recursive
     524             : }
     525             : 
     526             : 
     527           0 : bool Compiler::find_field(Node::pointer_t link, Node::pointer_t field, int& funcs, Node::pointer_t& resolution, Node::pointer_t params, int const search_flags)
     528             : {
     529           0 :     RestoreFlags restore_flags(this);
     530             : 
     531           0 :     bool const r(find_any_field(link, field, funcs, resolution, params, search_flags));
     532           0 :     if(!r)
     533             :     {
     534           0 :         print_search_errors(field);
     535             :     }
     536             : 
     537           0 :     return r;
     538             : }
     539             : 
     540             : 
     541           0 : bool Compiler::resolve_field(Node::pointer_t object, Node::pointer_t field, Node::pointer_t& resolution, Node::pointer_t params, int const search_flags)
     542             : {
     543             :     // this is to make sure it is optimized, etc.
     544             :     //expression(field); -- we cannot have this here or it generates loops
     545             : 
     546             :     // just in case the caller is re-using the same node
     547           0 :     resolution.reset();
     548             : 
     549           0 :     Node::pointer_t link;
     550           0 :     Node::pointer_t type;
     551             : 
     552             :     // check that the object is indeed an object (i.e. a variable
     553             :     // which references a class)
     554           0 :     switch(object->get_type())
     555             :     {
     556             :     case Node::node_t::NODE_VARIABLE:
     557             :     case Node::node_t::NODE_PARAM:
     558             :         // it is a variable or a parameter, check for the type
     559             :         //NodeLock ln(object);
     560             :         {
     561           0 :             size_t const max(object->get_children_size());
     562             :             size_t idx;
     563           0 :             for(idx = 0; idx < max; ++idx)
     564             :             {
     565           0 :                 type = object->get_child(idx);
     566           0 :                 if(type->get_type() != Node::node_t::NODE_SET
     567           0 :                 && type->get_type() != Node::node_t::NODE_VAR_ATTRIBUTES)
     568             :                 {
     569             :                     // we found the type
     570           0 :                     break;
     571             :                 }
     572             :             }
     573           0 :             if(idx >= max || !type)
     574             :             {
     575             :                 // TODO: should this be an error instead?
     576           0 :                 Message msg(message_level_t::MESSAGE_LEVEL_WARNING, err_code_t::AS_ERR_INCOMPATIBLE, object->get_position());
     577           0 :                 msg << "variables and parameters without a type should not be used with members.";
     578           0 :                 return false;
     579             :             }
     580             :         }
     581             : 
     582             :         // we need to have a link to the class
     583           0 :         link_type(type);
     584           0 :         link = type->get_link(Node::link_t::LINK_INSTANCE);
     585           0 :         if(!link)
     586             :         {
     587             :             // NOTE: we can't search a field in nothing...
     588             :             //     if I'm correct, it will later bite the
     589             :             //     user if the class isn't dynamic
     590             : //fprintf(stderr, "WARNING: type not linked, cannot lookup member.\n");
     591           0 :             return false;
     592             :         }
     593           0 :         break;
     594             : 
     595             :     case Node::node_t::NODE_CLASS:
     596             :     case Node::node_t::NODE_INTERFACE:
     597           0 :         link = object;
     598           0 :         break;
     599             : 
     600             :     default:
     601             :         {
     602           0 :             Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_INVALID_TYPE, object->get_position());
     603           0 :             msg << "object of type '"
     604           0 :                 << object->get_type_name()
     605           0 :                 << "' is not known to have members.";
     606             :         }
     607           0 :         return false;
     608             : 
     609             :     }
     610             : 
     611           0 :     if(field->get_type() != Node::node_t::NODE_IDENTIFIER
     612           0 :     && field->get_type() != Node::node_t::NODE_VIDENTIFIER
     613           0 :     && field->get_type() != Node::node_t::NODE_STRING)
     614             :     {
     615             :         // we cannot determine at compile time whether a
     616             :         // dynamic field is valid...
     617             :         //std:cerr << "WARNING: cannot check a dynamic field.\n";
     618           0 :         return false;
     619             :     }
     620             : 
     621             : #if 0
     622             : char buf[256];
     623             : size_t sz = sizeof(buf);
     624             : data.f_str.ToUTF8(buf, sz);
     625             : fprintf(stderr, "DEBUG: resolving field '%s' (%d) Field: ", buf, data.f_type);
     626             : field.DisplayPtr(stderr);
     627             : fprintf(stderr, "\n");
     628             : #endif
     629             : 
     630           0 :     int funcs(0);
     631           0 :     bool const r(find_field(link, field, funcs, resolution, params, search_flags));
     632           0 :     if(!r)
     633             :     {
     634           0 :         return false;
     635             :     }
     636             : 
     637           0 :     if(funcs != 0)
     638             :     {
     639             : #if 0
     640             : fprintf(stderr, "DEBUG: field ");
     641             : field.DisplayPtr(stderr);
     642             : fprintf(stderr, " is a function.\n");
     643             : #endif
     644           0 :         resolution.reset();
     645           0 :         return select_best_func(params, resolution);
     646             :     }
     647             : 
     648           0 :     return true;
     649             : }
     650             : 
     651             : 
     652           0 : bool Compiler::find_member(Node::pointer_t member, Node::pointer_t& resolution, Node::pointer_t params, int search_flags)
     653             : {
     654             :     // Just in case the caller is re-using the same node
     655           0 :     resolution.reset();
     656             : 
     657             :     // Invalid member node? If so don't generate an error because
     658             :     // we most certainly already mentioned that to the user
     659             :     // (and if not that's a bug earlier than here).
     660           0 :     if(member->get_children_size() != 2)
     661             :     {
     662           0 :         return false;
     663             :     }
     664           0 :     NodeLock ln(member);
     665             : 
     666             : //fprintf(stderr, "Searching for Member...\n");
     667             : 
     668           0 :     bool must_find = false;
     669           0 :     Node::pointer_t object; // our sub-resolution
     670             : 
     671           0 :     Node::pointer_t name(member->get_child(0));
     672           0 :     switch(name->get_type())
     673             :     {
     674             :     case Node::node_t::NODE_MEMBER:
     675             :         // This happens when you have an expression such as:
     676             :         //        a.b.c
     677             :         // Then the child most MEMBER will be the identifier 'a'
     678           0 :         if(!find_member(name, object, params, search_flags))  // recursive
     679             :         {
     680           0 :             return false;
     681             :         }
     682             :         // If we reach here, the resolution (object variable here)
     683             :         // is the node we want to use next to resolve the field(s)
     684           0 :         break;
     685             : 
     686             :     case Node::node_t::NODE_SUPER:
     687             :     {
     688             :         // super should only be used in classes, but we can
     689             :         // find standalone functions using that keyword too...
     690             :         // here we search for the class and if we find it then
     691             :         // we try to get access to the extends. If the object
     692             :         // is Object, then we generate an error (i.e. there is
     693             :         // no super of Object).
     694             : //fprintf(stderr, "Handling super member\n");
     695           0 :         check_super_validity(name);
     696           0 :         Node::pointer_t class_node(class_of_member(member));
     697             :         // NOTE: Interfaces can use super but we can't
     698             :         //     know what it is at compile time.
     699             : //fprintf(stderr, "Parent is %s\n", parent_data->GetTypeName());
     700           0 :         if(class_node
     701           0 :         && class_node->get_type() == Node::node_t::NODE_CLASS)
     702             :         {
     703           0 :             if(class_node->get_string() == "Object")
     704             :             {
     705             :                 // this should never happen!
     706           0 :                 Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_INVALID_EXPRESSION, member->get_position());
     707           0 :                 msg << "you cannot use 'super' within the 'Object' class.";
     708             :             }
     709             :             else
     710             :             {
     711           0 :                 size_t const max_children(class_node->get_children_size());
     712             : //fprintf(stderr, "Search corresponding class (%d members)\n", max);
     713           0 :                 for(size_t idx(0); idx < max_children; ++idx)
     714             :                 {
     715           0 :                     Node::pointer_t child(class_node->get_child(idx));
     716           0 :                     if(child->get_type() == Node::node_t::NODE_EXTENDS)
     717             :                     {
     718           0 :                         if(child->get_children_size() == 1)
     719             :                         {
     720           0 :                             Node::pointer_t child_name(child->get_child(0));
     721           0 :                             object = child_name->get_link(Node::link_t::LINK_INSTANCE);
     722             : //fprintf(stderr, "Got the object! (%d)\n", idx);
     723             :                         }
     724           0 :                         if(!object)
     725             :                         {
     726             :                             // there is another error...
     727           0 :                             return false;
     728             :                         }
     729           0 :                         break;
     730             :                     }
     731           0 :                 }
     732           0 :                 if(!object)
     733             :                 {
     734             :                     // default to Object if no extends
     735           0 :                     resolve_internal_type(class_node, "Object", object);
     736             :                 }
     737           0 :                 must_find = true;
     738             :             }
     739           0 :         }
     740             :     }
     741           0 :         break;
     742             : 
     743             :     default:
     744           0 :         expression(name);
     745           0 :         break;
     746             : 
     747             :     }
     748             : 
     749             :     // do the field expression so we possibly detect more errors
     750             :     // in the field now instead of the next compile
     751           0 :     Node::pointer_t field(member->get_child(1));
     752           0 :     if(field->get_type() != Node::node_t::NODE_IDENTIFIER)
     753             :     {
     754           0 :         expression(field);
     755             :     }
     756             : 
     757           0 :     if(!object)
     758             :     {
     759             :         // TODO: this is totally wrong, what we need is the type, not
     760             :         //     just the name; this if we have a string, the type is
     761             :         //     the String class.
     762           0 :         if(name->get_type() != Node::node_t::NODE_IDENTIFIER
     763           0 :         && name->get_type() != Node::node_t::NODE_STRING)
     764             :         {
     765             :             // A dynamic name can't be resolved now; we can only
     766             :             // hope that it will be a valid name at run time.
     767             :             // However, we still want to resolve everything we
     768             :             // can in the list of field names.
     769             :             // FYI, this happens in this case:
     770             :             //    ("test_" + var).hello
     771           0 :             return true;
     772             :         }
     773             : 
     774           0 :         if(!resolve_name(name, name, object, params, search_flags))
     775             :         {
     776             :             // we can't even find the first name!
     777             :             // we won't search for fields since we need to have
     778             :             // an object for that purpose!
     779           0 :             return false;
     780             :         }
     781             :     }
     782             : 
     783             :     // we avoid errors by returning no resolution but 'success'
     784           0 :     if(object)
     785             :     {
     786           0 :         bool const result(resolve_field(object, field, resolution, params, search_flags));
     787             : 
     788             : //fprintf(stderr, "ResolveField() returned %d\n", result);
     789             : 
     790           0 :         if(!result && must_find)
     791             :         {
     792           0 :             Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_INVALID_EXPRESSION, member->get_position());
     793           0 :             msg << "'super' must name a valid field of the super class.";
     794             :         }
     795             :         else
     796             :         {
     797           0 :             check_member(name, resolution, field);
     798             :         }
     799           0 :         return result;
     800             :     }
     801             : 
     802           0 :     return true;
     803             : }
     804             : 
     805             : 
     806           0 : void Compiler::resolve_member(Node::pointer_t expr, Node::pointer_t params, int const search_flags)
     807             : {
     808           0 :     Node::pointer_t resolution;
     809           0 :     if(!find_member(expr, resolution, params, search_flags))
     810             :     {
     811             : #if 0
     812             : // with dynamic entries, this generates invalid warnings
     813             :         NodePtr& parent = expr.GetParent();
     814             :         Data& data = parent.GetData();
     815             :         if(data.f_type != NODE_ASSIGNMENT
     816             :         || parent.GetChildCount() != 2
     817             :         || !parent.GetChild(0).SameAs(expr)) {
     818             : fprintf(stderr, "WARNING: cannot find field member.\n");
     819             :         }
     820             : #endif
     821           0 :         return;
     822             :     }
     823             : 
     824             :     // we got a resolution; but dynamic names
     825             :     // cannot be fully resolved at compile time
     826           0 :     if(!resolution)
     827             :     {
     828           0 :         return;
     829             :     }
     830             : 
     831             :     // the name was fully resolved, check it out
     832             : 
     833             : //Data& d = resolution.GetData();
     834             : //fprintf(stderr, "Member resolution is %d\n", d.f_type);
     835             : 
     836           0 :     if(replace_constant_variable(expr, resolution))
     837             :     {
     838             :         // just a constant, we're done
     839           0 :         return;
     840             :     }
     841             : 
     842             :     // copy the type whenever available
     843           0 :     expr->set_link(Node::link_t::LINK_INSTANCE, resolution);
     844           0 :     Node::pointer_t type(resolution->get_link(Node::link_t::LINK_TYPE));
     845           0 :     if(type)
     846             :     {
     847           0 :         expr->set_link(Node::link_t::LINK_TYPE, type);
     848             :     }
     849             : 
     850             :     // if we have a Getter, transform the MEMBER into a CALL
     851             :     // to a MEMBER
     852           0 :     if(resolution->get_type() == Node::node_t::NODE_FUNCTION
     853           0 :     && resolution->get_flag(Node::flag_t::NODE_FUNCTION_FLAG_GETTER))
     854             :     {
     855           0 : fprintf(stderr, "CAUGHT! getter...\n");
     856             :         // so expr is a MEMBER at this time
     857             :         // it has two children
     858           0 :         Node::pointer_t left(expr->get_child(0));
     859           0 :         Node::pointer_t right(expr->get_child(1));
     860           0 :         expr->delete_child(0);
     861           0 :         expr->delete_child(0);    // 1 is now 0
     862             : 
     863             :         // create a new node since we do not want to move the
     864             :         // call (expr) node from its parent.
     865           0 :         Node::pointer_t member(expr->create_replacement(Node::node_t::NODE_MEMBER));
     866           0 :         member->set_link(Node::link_t::LINK_INSTANCE, resolution);
     867           0 :         member->set_link(Node::link_t::LINK_TYPE, type);
     868           0 :         member->append_child(left);
     869           0 :         member->append_child(right);
     870             : 
     871           0 :         expr->append_child(member);
     872             : 
     873             :         // we need to change the name to match the getter
     874             :         // NOTE: we know that the right data is an identifier,
     875             :         //       a v-identifier, or a string so the following
     876             :         //       will always work
     877           0 :         String getter_name("->");
     878           0 :         getter_name += right->get_string();
     879           0 :         right->set_string(getter_name);
     880             : 
     881             :         // the call needs a list of parameters (empty)
     882           0 :         Node::pointer_t empty_params(expr->create_replacement(Node::node_t::NODE_LIST));
     883           0 :         expr->append_child(empty_params);
     884             : 
     885             :         // and finally, we transform the member in a call!
     886           0 :         expr->to_call();
     887           0 :     }
     888             : }
     889             : 
     890             : 
     891           0 : Node::depth_t Compiler::find_class(Node::pointer_t class_type, Node::pointer_t type, Node::depth_t depth)
     892             : {
     893           0 :     NodeLock ln(class_type);
     894           0 :     size_t const max_children(class_type->get_children_size());
     895             : 
     896           0 :     for(size_t idx(0); idx < max_children; ++idx)
     897             :     {
     898           0 :         Node::pointer_t child(class_type->get_child(idx));
     899           0 :         if(child->get_type() == Node::node_t::NODE_IMPLEMENTS
     900           0 :         || child->get_type() == Node::node_t::NODE_EXTENDS)
     901             :         {
     902           0 :             if(child->get_children_size() == 0)
     903             :             {
     904             :                 // should never happen
     905           0 :                 continue;
     906             :             }
     907           0 :             NodeLock child_ln(child);
     908           0 :             Node::pointer_t super_name(child->get_child(0));
     909           0 :             Node::pointer_t super(super_name->get_link(Node::link_t::LINK_INSTANCE));
     910           0 :             if(!super)
     911             :             {
     912           0 :                 expression(super_name);
     913           0 :                 super = super_name->get_link(Node::link_t::LINK_INSTANCE);
     914             :             }
     915           0 :             if(!super)
     916             :             {
     917           0 :                 Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_INVALID_EXPRESSION, class_type->get_position());
     918           0 :                 msg << "cannot find the type named in an 'extends' or 'implements' list.";
     919           0 :                 continue;
     920             :             }
     921           0 :             if(super == type)
     922             :             {
     923           0 :                 return depth;
     924           0 :             }
     925             :         }
     926           0 :     }
     927             : 
     928           0 :     depth += 1;
     929             : 
     930           0 :     Node::depth_t result(Node::MATCH_NOT_FOUND);
     931           0 :     for(size_t idx(0); idx < max_children; ++idx)
     932             :     {
     933           0 :         Node::pointer_t child(class_type->get_child(idx));
     934           0 :         if(child->get_type() == Node::node_t::NODE_IMPLEMENTS
     935           0 :         || child->get_type() == Node::node_t::NODE_EXTENDS)
     936             :         {
     937           0 :             if(child->get_children_size() == 0)
     938             :             {
     939             :                 // should never happen
     940           0 :                 continue;
     941             :             }
     942           0 :             NodeLock child_ln(child);
     943           0 :             Node::pointer_t super_name(child->get_child(0));
     944           0 :             Node::pointer_t super(super_name->get_link(Node::link_t::LINK_INSTANCE));
     945           0 :             if(!super)
     946             :             {
     947           0 :                 continue;
     948             :             }
     949           0 :             Node::depth_t const r(find_class(super, type, depth));  // recursive
     950           0 :             if(r > result)
     951             :             {
     952           0 :                 result = r;
     953           0 :             }
     954             :         }
     955           0 :     }
     956             : 
     957           0 :     return result;
     958             : }
     959             : 
     960             : 
     961             : 
     962           0 : bool Compiler::is_derived_from(Node::pointer_t derived_class, Node::pointer_t super_class)
     963             : {
     964           0 :     if(derived_class == super_class)
     965             :     {
     966             :         // exact same object, it is "derived from"
     967           0 :         return true;
     968             :     }
     969             : 
     970           0 :     size_t const max(derived_class->get_children_size());
     971           0 :     for(size_t idx(0); idx < max; ++idx)
     972             :     {
     973           0 :         Node::pointer_t extends(derived_class->get_child(idx));
     974           0 :         if(!extends)
     975             :         {
     976           0 :             continue;
     977             :         }
     978           0 :         if(extends->get_type() != Node::node_t::NODE_EXTENDS
     979           0 :         && extends->get_type() != Node::node_t::NODE_IMPLEMENTS)
     980             :         {
     981           0 :             continue;
     982             :         }
     983           0 :         Node::pointer_t type(extends->get_child(0));
     984             :         // TODO: we probably want to accept lists of extends too
     985             :         //       because JavaScript gives us the ability to create
     986             :         //       objects with multiple derivation (not exactly
     987             :         //       100% true, but close enough and it makes a lot
     988             :         //       of things MUCH easier.)
     989           0 :         if(type->get_type() == Node::node_t::NODE_LIST
     990           0 :         && extends->get_type() == Node::node_t::NODE_IMPLEMENTS)
     991             :         {
     992             :             // IMPLEMENTS accepts lists
     993           0 :             size_t const cnt(type->get_children_size());
     994           0 :             for(size_t j(0); j < cnt; ++j)
     995             :             {
     996           0 :                 Node::pointer_t sub_type(type->get_child(j));
     997           0 :                 link_type(sub_type);
     998           0 :                 Node::pointer_t link(sub_type->get_link(Node::link_t::LINK_INSTANCE));
     999           0 :                 if(!link)
    1000             :                 {
    1001           0 :                     continue;
    1002             :                 }
    1003           0 :                 if(is_derived_from(link, super_class))
    1004             :                 {
    1005           0 :                     return true;
    1006             :                 }
    1007           0 :             }
    1008             :         }
    1009             :         else
    1010             :         {
    1011             :             // TODO: review the "extends ..." implementation so it supports
    1012             :             //       lists in the parser and then here
    1013           0 :             link_type(type);
    1014           0 :             Node::pointer_t link(type->get_link(Node::link_t::LINK_INSTANCE));
    1015           0 :             if(!link)
    1016             :             {
    1017           0 :                 continue;
    1018             :             }
    1019           0 :             if(is_derived_from(link, super_class))
    1020             :             {
    1021           0 :                 return true;
    1022           0 :             }
    1023             :         }
    1024           0 :     }
    1025             : 
    1026           0 :     return false;
    1027             : }
    1028             : 
    1029             : 
    1030             : /** \brief Search for a class or interface node.
    1031             :  *
    1032             :  * This function searches for a node of type NODE_CLASS or NODE_INTERFACE
    1033             :  * starting with \p class_node. The search checks \p class_node and all
    1034             :  * of its parents.
    1035             :  *
    1036             :  * The search stops prematuraly if a NODE_PACKAGE, NODE_PROGRAM, or
    1037             :  * NODE_ROOT is found first.
    1038             :  *
    1039             :  * \param[in] class_node  The object from which a class is to be searched.
    1040             :  *
    1041             :  * \return The class or interface, or a null pointer if not found.
    1042             :  */
    1043           0 : Node::pointer_t Compiler::class_of_member(Node::pointer_t class_node)
    1044             : {
    1045           0 :     while(class_node)
    1046             :     {
    1047           0 :         if(class_node->get_type() == Node::node_t::NODE_CLASS
    1048           0 :         || class_node->get_type() == Node::node_t::NODE_INTERFACE)
    1049             :         {
    1050             :             // got the class/interface definition
    1051           0 :             return class_node;
    1052             :         }
    1053           0 :         if(class_node->get_type() == Node::node_t::NODE_PACKAGE
    1054           0 :         || class_node->get_type() == Node::node_t::NODE_PROGRAM
    1055           0 :         || class_node->get_type() == Node::node_t::NODE_ROOT)
    1056             :         {
    1057             :             // not found, we reached one of package/program/root instead
    1058           0 :             break;
    1059             :         }
    1060           0 :         class_node = class_node->get_parent();
    1061             :     }
    1062             : 
    1063           0 :     return Node::pointer_t();
    1064             : }
    1065             : 
    1066             : 
    1067             : /** \brief Check whether derived_class is extending super_class.
    1068             :  *
    1069             :  * This function checks whether the object defined as derived_class
    1070             :  * has an extends or implements one that includes super_class.
    1071             :  *
    1072             :  * The \p the_super_class parameter is set to the class of the
    1073             :  * super_class object. This can be used to determine different
    1074             :  * types of errors.
    1075             :  *
    1076             :  * Note that if derived_class or super_class are not objects defined
    1077             :  * in a class, then the function always returns false.
    1078             :  *
    1079             :  * \param[in] derived_class  The class which is checked to know whether it
    1080             :  *                           derives from super_class.
    1081             :  * \param[in] super_class  The class that is expected to be in the extends
    1082             :  *                         or implements lists.
    1083             :  * \param[out] the_super_class  The actual class object in which super_class
    1084             :  *                              is defined.
    1085             :  *
    1086             :  * \return true if derived_class is derived from super_class.
    1087             :  */
    1088           0 : bool Compiler::are_objects_derived_from_one_another(Node::pointer_t derived_class, Node::pointer_t super_class, Node::pointer_t& the_super_class)
    1089             : {
    1090           0 :     the_super_class = class_of_member(super_class);
    1091           0 :     if(!the_super_class)
    1092             :     {
    1093           0 :         return false;
    1094             :     }
    1095           0 :     Node::pointer_t the_derived_class(class_of_member(derived_class));
    1096           0 :     if(!the_derived_class)
    1097             :     {
    1098           0 :         return false;
    1099             :     }
    1100             : 
    1101           0 :     return is_derived_from(the_derived_class, the_super_class);
    1102             : }
    1103             : 
    1104             : 
    1105           0 : void Compiler::declare_class(Node::pointer_t class_node)
    1106             : {
    1107           0 :     size_t const max_children(class_node->get_children_size());
    1108           0 :     for(size_t idx(0); idx < max_children; ++idx)
    1109             :     {
    1110             :         //NodeLock ln(class_node);
    1111           0 :         Node::pointer_t child(class_node->get_child(idx));
    1112           0 :         switch(child->get_type())
    1113             :         {
    1114             :         case Node::node_t::NODE_DIRECTIVE_LIST:
    1115           0 :             declare_class(child); // recursive!
    1116           0 :             break;
    1117             : 
    1118             :         case Node::node_t::NODE_CLASS:
    1119             :         case Node::node_t::NODE_INTERFACE:
    1120           0 :             class_directive(child);
    1121           0 :             break;
    1122             : 
    1123             :         case Node::node_t::NODE_ENUM:
    1124           0 :             enum_directive(child);
    1125           0 :             break;
    1126             : 
    1127             :         case Node::node_t::NODE_FUNCTION:
    1128           0 :             function(child);
    1129           0 :             break;
    1130             : 
    1131             :         case Node::node_t::NODE_VAR:
    1132           0 :             var(child);
    1133           0 :             break;
    1134             : 
    1135             :         default:
    1136             :             {
    1137           0 :                 Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_INVALID_NODE, child->get_position());
    1138           0 :                 msg << "the '" << child->get_type_name() << "' token cannot be a class member.";
    1139             :             }
    1140           0 :             break;
    1141             : 
    1142             :         }
    1143           0 :     }
    1144           0 : }
    1145             : 
    1146             : 
    1147           0 : void Compiler::extend_class(Node::pointer_t class_node, Node::pointer_t extend_name)
    1148             : {
    1149           0 :     expression(extend_name);
    1150             : 
    1151           0 :     Node::pointer_t super(extend_name->get_link(Node::link_t::LINK_INSTANCE));
    1152           0 :     if(super)
    1153             :     {
    1154           0 :         if(get_attribute(super, Node::attribute_t::NODE_ATTR_FINAL))
    1155             :         {
    1156           0 :             Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_FINAL, class_node->get_position());
    1157           0 :             msg << "class '" << super->get_string() << "' is marked final and it cannot be extended by '" << class_node->get_string() << "'.";
    1158             :         }
    1159           0 :     }
    1160           0 : }
    1161             : 
    1162             : 
    1163        8192 : void Compiler::class_directive(Node::pointer_t& class_node)
    1164             : {
    1165        8192 :     size_t const max(class_node->get_children_size());
    1166       16384 :     for(size_t idx(0); idx < max; ++idx)
    1167             :     {
    1168             :         //NodeLock ln(class_node);
    1169        8192 :         Node::pointer_t child(class_node->get_child(idx));
    1170        8192 :         switch(child->get_type())
    1171             :         {
    1172             :         case Node::node_t::NODE_DIRECTIVE_LIST:
    1173           0 :             declare_class(child);
    1174           0 :             break;
    1175             : 
    1176             :         case Node::node_t::NODE_EXTENDS:
    1177             :         case Node::node_t::NODE_IMPLEMENTS:
    1178           0 :             extend_class(class_node, child->get_child(0));
    1179           0 :             break;
    1180             : 
    1181             :         case Node::node_t::NODE_EMPTY:
    1182        8192 :             break;
    1183             : 
    1184             :         default:
    1185             :             {
    1186           0 :                 Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_INTERNAL_ERROR, class_node->get_position());
    1187           0 :                 msg << "invalid token '" << child->get_type_name() << "' in a class definition.";
    1188             :             }
    1189           0 :             break;
    1190             : 
    1191             :         }
    1192        8192 :     }
    1193        8192 : }
    1194             : 
    1195             : 
    1196             : /** \brief Enum directive.
    1197             :  *
    1198             :  * Enumerations are like classes defining a list of constant values.
    1199             :  *
    1200             :  * \param[in] enum_node  The enumeration node to work on.
    1201             :  */
    1202           0 : void Compiler::enum_directive(Node::pointer_t& enum_node)
    1203             : {
    1204           0 :     NodeLock ln(enum_node);
    1205           0 :     size_t const max_children(enum_node->get_children_size());
    1206           0 :     for(size_t idx(0); idx < max_children; ++idx)
    1207             :     {
    1208           0 :         Node::pointer_t entry(enum_node->get_child(idx));
    1209           0 :         if(entry->get_children_size() != 1)
    1210             :         {
    1211             :             // not valid, skip
    1212           0 :             continue;
    1213             :         }
    1214           0 :         Node::pointer_t set = entry->get_child(0);
    1215           0 :         if(set->get_children_size() != 1)
    1216             :         {
    1217             :             // not valid, skip
    1218           0 :             continue;
    1219             :         }
    1220             :         // compile the expression
    1221           0 :         expression(set->get_child(0));
    1222           0 :     }
    1223           0 : }
    1224             : 
    1225             : 
    1226             : 
    1227             : 
    1228          63 : }
    1229             : // namespace as2js
    1230             : 
    1231             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.10