LCOV - code coverage report
Current view: top level - lib - compiler_expression.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1 638 0.2 %
Date: 2014-11-22 Functions: 2 16 12.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* compiler_compile.cpp -- written by Alexis WILKE for Made to Order Software Corp. (c) 2005-2014 */
       2             : 
       3             : /*
       4             : 
       5             : Copyright (c) 2005-2014 Made to Order Software Corp.
       6             : 
       7             : http://snapwebsites.org/project/as2js
       8             : 
       9             : Permission is hereby granted, free of charge, to any
      10             : person obtaining a copy of this software and
      11             : associated documentation files (the "Software"), to
      12             : deal in the Software without restriction, including
      13             : without limitation the rights to use, copy, modify,
      14             : merge, publish, distribute, sublicense, and/or sell
      15             : copies of the Software, and to permit persons to whom
      16             : the Software is furnished to do so, subject to the
      17             : following conditions:
      18             : 
      19             : The above copyright notice and this permission notice
      20             : shall be included in all copies or substantial
      21             : portions of the Software.
      22             : 
      23             : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
      24             : ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
      25             : LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
      26             : FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
      27             : EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
      28             : LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
      29             : WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
      30             : ARISING FROM, OUT OF OR IN CONNECTION WITH THE
      31             : SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      32             : SOFTWARE.
      33             : 
      34             : */
      35             : 
      36             : #include    "as2js/compiler.h"
      37             : 
      38             : #include    "as2js/exceptions.h"
      39             : #include    "as2js/message.h"
      40             : 
      41             : 
      42             : namespace as2js
      43             : {
      44             : 
      45             : 
      46             : 
      47             : 
      48             : 
      49           0 : bool Compiler::expression_new(Node::pointer_t new_node)
      50             : {
      51             :     //
      52             :     // handle the special case of:
      53             :     //    VAR name := NEW class()
      54             :     //
      55             : 
      56           0 :     if(new_node->get_children_size() == 0)
      57             :     {
      58           0 :         return false;
      59             :     }
      60             : 
      61             : //fprintf(stderr, "BEFORE:\n");
      62             : //new_node.Display(stderr);
      63           0 :     Node::pointer_t call(new_node->get_child(0));
      64           0 :     if(!call)
      65             :     {
      66           0 :         return false;
      67             :     }
      68             : 
      69           0 :     if(call->get_type() != Node::node_t::NODE_CALL
      70           0 :     || call->get_children_size() != 2)
      71             :     {
      72           0 :         return false;
      73             :     }
      74             : 
      75             :     // get the function name
      76           0 :     Node::pointer_t id(call->get_child(0));
      77           0 :     if(id->get_type() != Node::node_t::NODE_IDENTIFIER)
      78             :     {
      79           0 :         return false;
      80             :     }
      81             : 
      82             :     // determine the types of the parameters to search a corresponding object or function
      83           0 :     Node::pointer_t params(call->get_child(1));
      84           0 :     size_t const count(params->get_children_size());
      85             : //fprintf(stderr, "ResolveCall() with %d expressions\n", count);
      86             : //new_node.Display(stderr);
      87           0 :     for(size_t idx(0); idx < count; ++idx)
      88             :     {
      89           0 :         expression(params->get_child(idx));
      90             :     }
      91             : 
      92             :     // resolve what is named
      93           0 :     Node::pointer_t resolution;
      94           0 :     if(!resolve_name(id, id, resolution, params, SEARCH_FLAG_GETTER))
      95             :     {
      96             :         // an error is generated later if this is a call and no function can be found
      97           0 :         return false;
      98             :     }
      99             : 
     100             :     // is the name a class or interface?
     101           0 :     if(resolution->get_type() != Node::node_t::NODE_CLASS
     102           0 :     && resolution->get_type() != Node::node_t::NODE_INTERFACE)
     103             :     {
     104           0 :         return false;
     105             :     }
     106             : 
     107             :     // move the nodes under CALL up one level
     108           0 :     Node::pointer_t type(call->get_child(0));
     109           0 :     Node::pointer_t expr(call->get_child(1));
     110           0 :     new_node->delete_child(0);      // remove the CALL
     111           0 :     new_node->append_child(type);   // replace with TYPE + parameters (LIST)
     112           0 :     new_node->append_child(expr);
     113             : 
     114             : //fprintf(stderr, "CHANGED TO:\n");
     115             : //new_node.Display(stderr);
     116             : 
     117           0 :     return true;
     118             : }
     119             : 
     120             : 
     121           0 : bool Compiler::is_function_abstract(Node::pointer_t function_node)
     122             : {
     123           0 :     size_t const max_children(function_node->get_children_size());
     124           0 :     for(size_t idx(0); idx < max_children; ++idx)
     125             :     {
     126           0 :         Node::pointer_t child(function_node->get_child(idx));
     127           0 :         if(child->get_type() == Node::node_t::NODE_DIRECTIVE_LIST)
     128             :         {
     129           0 :             return false;
     130             :         }
     131           0 :     }
     132             : 
     133           0 :     return true;
     134             : }
     135             : 
     136             : 
     137           0 : bool Compiler::find_overloaded_function(Node::pointer_t class_node, Node::pointer_t function_node)
     138             : {
     139           0 :     size_t const max_children(class_node->get_children_size());
     140           0 :     for(size_t idx(0); idx < max_children; ++idx)
     141             :     {
     142           0 :         Node::pointer_t child(class_node->get_child(idx));
     143           0 :         switch(child->get_type())
     144             :         {
     145             :         case Node::node_t::NODE_EXTENDS:
     146             :         case Node::node_t::NODE_IMPLEMENTS:
     147             :         {
     148           0 :             Node::pointer_t names(child->get_child(0));
     149           0 :             if(names->get_type() != Node::node_t::NODE_LIST)
     150             :             {
     151           0 :                 names = child;
     152             :             }
     153           0 :             size_t const max_names(names->get_children_size());
     154           0 :             for(size_t j(0); j < max_names; ++j)
     155             :             {
     156           0 :                 Node::pointer_t super(names->get_child(j)->get_link(Node::link_t::LINK_INSTANCE));
     157           0 :                 if(super)
     158             :                 {
     159           0 :                     if(is_function_overloaded(super, function_node))
     160             :                     {
     161           0 :                         return true;
     162             :                     }
     163             :                 }
     164           0 :             }
     165             :         }
     166           0 :             break;
     167             : 
     168             :         case Node::node_t::NODE_DIRECTIVE_LIST:
     169           0 :             if(find_overloaded_function(child, function_node))
     170             :             {
     171           0 :                 return true;
     172             :             }
     173           0 :             break;
     174             : 
     175             :         case Node::node_t::NODE_FUNCTION:
     176           0 :             if(function_node->get_string() == child->get_string())
     177             :             {
     178             :                 // found a function with the same name
     179           0 :                 if(compare_parameters(function_node, child))
     180             :                 {
     181             :                     // yes! it is overloaded!
     182           0 :                     return true;
     183             :                 }
     184             :             }
     185           0 :             break;
     186             : 
     187             :         default:
     188           0 :             break;
     189             : 
     190             :         }
     191           0 :     }
     192             : 
     193           0 :     return false;
     194             : }
     195             : 
     196             : 
     197           0 : bool Compiler::is_function_overloaded(Node::pointer_t class_node, Node::pointer_t function_node)
     198             : {
     199           0 :     Node::pointer_t parent(class_of_member(function_node));
     200           0 :     if(!parent)
     201             :     {
     202           0 :         throw exception_internal_error("the parent of a function being checked for overload is not defined in a class");
     203             :     }
     204           0 :     if(parent->get_type() != Node::node_t::NODE_CLASS
     205           0 :     && parent->get_type() != Node::node_t::NODE_INTERFACE)
     206             :     {
     207           0 :         throw exception_internal_error("somehow the class of member is not a class or interface");
     208             :     }
     209           0 :     if(parent == class_node)
     210             :     {
     211           0 :         return false;
     212             :     }
     213             : 
     214           0 :     return find_overloaded_function(class_node, function_node);
     215             : }
     216             : 
     217             : 
     218           0 : bool Compiler::has_abstract_functions(Node::pointer_t class_node, Node::pointer_t list, Node::pointer_t& func)
     219             : {
     220           0 :     size_t max_children(list->get_children_size());
     221           0 :     for(size_t idx(0); idx < max_children; ++idx)
     222             :     {
     223           0 :         Node::pointer_t child(list->get_child(idx));
     224           0 :         switch(child->get_type())
     225             :         {
     226             :         case Node::node_t::NODE_EXTENDS:
     227             :         case Node::node_t::NODE_IMPLEMENTS:
     228             :         {
     229           0 :             Node::pointer_t names(child->get_child(0));
     230           0 :             if(names->get_type() != Node::node_t::NODE_LIST)
     231             :             {
     232           0 :                 names = child;
     233             :             }
     234           0 :             size_t const max_names(names->get_children_size());
     235           0 :             for(size_t j(0); j < max_names; ++j)
     236             :             {
     237           0 :                 Node::pointer_t super(names->get_child(j)->get_link(Node::link_t::LINK_INSTANCE));
     238           0 :                 if(super)
     239             :                 {
     240           0 :                     if(has_abstract_functions(class_node, super, func))
     241             :                     {
     242           0 :                         return true;
     243             :                     }
     244             :                 }
     245           0 :             }
     246             :         }
     247           0 :             break;
     248             : 
     249             :         case Node::node_t::NODE_DIRECTIVE_LIST:
     250           0 :             if(has_abstract_functions(class_node, child, func))
     251             :             {
     252           0 :                 return true;
     253             :             }
     254           0 :             break;
     255             : 
     256             :         case Node::node_t::NODE_FUNCTION:
     257           0 :             if(is_function_abstract(child))
     258             :             {
     259             :                 // see whether it was overloaded
     260           0 :                 if(!is_function_overloaded(class_node, child))
     261             :                 {
     262             :                     // not overloaded, this class cannot
     263             :                     // be instantiated!
     264           0 :                     func = child;
     265           0 :                     return true;
     266             :                 }
     267             :             }
     268           0 :             break;
     269             : 
     270             :         default:
     271           0 :             break;
     272             : 
     273             :         }
     274           0 :     }
     275             : 
     276           0 :     return false;
     277             : }
     278             : 
     279             : 
     280           0 : void Compiler::can_instantiate_type(Node::pointer_t expr)
     281             : {
     282           0 :     if(expr->get_type() != Node::node_t::NODE_IDENTIFIER)
     283             :     {
     284             :         // dynamic, cannot test at compile time...
     285           0 :         return;
     286             :     }
     287             : 
     288           0 :     Node::pointer_t inst(expr->get_link(Node::link_t::LINK_INSTANCE));
     289           0 :     if(inst->get_type() == Node::node_t::NODE_INTERFACE)
     290             :     {
     291           0 :         Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_INVALID_EXPRESSION, expr->get_position());
     292           0 :         msg << "you can only instantiate an object from a class. '" << expr->get_string() << "' is an interface.";
     293           0 :         return;
     294             :     }
     295           0 :     if(inst->get_type() != Node::node_t::NODE_CLASS)
     296             :     {
     297           0 :         Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_INVALID_EXPRESSION, expr->get_position());
     298           0 :         msg << "you can only instantiate an object from a class. '" << expr->get_string() << "' does not seem to be a class.";
     299           0 :         return;
     300             :     }
     301             : 
     302             :     // check all the functions and make sure none are [still] abstract
     303             :     // in this class...
     304           0 :     Node::pointer_t func;
     305           0 :     if(has_abstract_functions(inst, inst, func))
     306             :     {
     307           0 :         Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_ABSTRACT, expr->get_position());
     308           0 :         msg << "the class '"
     309           0 :             << expr->get_string()
     310           0 :             << "' has an abstract function '"
     311           0 :             << func->get_string()
     312           0 :             << "' in file '"
     313           0 :             << func->get_position().get_filename()
     314           0 :             << "' at line #"
     315           0 :             << func->get_position().get_line()
     316           0 :             << " and cannot be instantiated. (If you have an overloaded version of that function it may have the wrong prototype.)";
     317           0 :         return;
     318           0 :     }
     319             : 
     320             :     // we're fine...
     321             : }
     322             : 
     323             : 
     324           0 : void Compiler::check_this_validity(Node::pointer_t expr)
     325             : {
     326           0 :     Node::pointer_t parent(expr);
     327             :     for(;;)
     328             :     {
     329           0 :         parent = parent->get_parent();
     330           0 :         if(!parent)
     331             :         {
     332           0 :             return;
     333             :         }
     334           0 :         switch(parent->get_type())
     335             :         {
     336             :         case Node::node_t::NODE_FUNCTION:
     337             :             // If we are in a static function, then we
     338             :             // don't have access to 'this'. Note that
     339             :             // it doesn't matter whether we're in a
     340             :             // class or not...
     341           0 :             if(parent->get_flag(Node::flag_t::NODE_FUNCTION_FLAG_OPERATOR)
     342           0 :             || get_attribute(parent, Node::attribute_t::NODE_ATTR_STATIC)
     343           0 :             || get_attribute(parent, Node::attribute_t::NODE_ATTR_CONSTRUCTOR)
     344           0 :             || is_constructor(parent))
     345             :             {
     346           0 :                 Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_STATIC, expr->get_position());
     347           0 :                 msg << "'this' cannot be used in a static function nor a constructor.";
     348             :             }
     349           0 :             return;
     350             : 
     351             :         case Node::node_t::NODE_CLASS:
     352             :         case Node::node_t::NODE_INTERFACE:
     353             :         case Node::node_t::NODE_PROGRAM:
     354             :         case Node::node_t::NODE_ROOT:
     355           0 :             return;
     356             : 
     357             :         default:
     358           0 :             break;
     359             : 
     360             :         }
     361           0 :     }
     362             : }
     363             : 
     364             : 
     365           0 : void Compiler::unary_operator(Node::pointer_t expr)
     366             : {
     367           0 :     if(expr->get_children_size() != 1)
     368             :     {
     369           0 :         return;
     370             :     }
     371             : 
     372           0 :     char const *op(expr->operator_to_string(expr->get_type()));
     373           0 :     if(!op)
     374             :     {
     375           0 :         throw exception_internal_error("operator_to_string() returned an empty string for a unary operator");
     376             :     }
     377             : 
     378           0 :     Node::pointer_t left(expr->get_child(0));
     379           0 :     Node::pointer_t type(left->get_link(Node::link_t::LINK_TYPE));
     380           0 :     if(!type)
     381             :     {
     382             : //fprintf(stderr, "WARNING: operand of unary operator isn't typed.\n");
     383           0 :         return;
     384             :     }
     385             : 
     386           0 :     Node::pointer_t l(expr->create_replacement(Node::node_t::NODE_IDENTIFIER));
     387           0 :     l->set_string("left");
     388             : 
     389           0 :     Node::pointer_t params(expr->create_replacement(Node::node_t::NODE_LIST));
     390           0 :     params->append_child(l);
     391             : 
     392           0 :     Node::pointer_t id(expr->create_replacement(Node::node_t::NODE_IDENTIFIER));
     393           0 :     id->set_string(op);
     394           0 :     id->append_child(params);
     395             : 
     396           0 :     size_t const del(expr->get_children_size());
     397           0 :     expr->append_child(id);
     398             : 
     399           0 :     Node::pointer_t resolution;
     400           0 :     int funcs = 0;
     401             :     bool result;
     402             :     {
     403           0 :         NodeLock ln(expr);
     404           0 :         result = find_field(type, id, funcs, resolution, params, 0);
     405             :     }
     406             : 
     407           0 :     expr->delete_child(del);
     408           0 :     if(!result)
     409             :     {
     410           0 :         Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_INVALID_OPERATOR, expr->get_position());
     411           0 :         msg << "cannot apply operator '" << op << "' to this object.";
     412           0 :         return;
     413             :     }
     414             : 
     415             : //fprintf(stderr, "Found operator!!!\n");
     416             : 
     417           0 :     Node::pointer_t op_type(resolution->get_link(Node::link_t::LINK_TYPE));
     418             : 
     419           0 :     if(get_attribute(resolution, Node::attribute_t::NODE_ATTR_NATIVE))
     420             :     {
     421           0 :         switch(expr->get_type())
     422             :         {
     423             :         case Node::node_t::NODE_INCREMENT:
     424             :         case Node::node_t::NODE_DECREMENT:
     425             :         case Node::node_t::NODE_POST_INCREMENT:
     426             :         case Node::node_t::NODE_POST_DECREMENT:
     427             :             {
     428           0 :                 Node::pointer_t var_node(left->get_link(Node::link_t::LINK_INSTANCE));
     429           0 :                 if(var_node)
     430             :                 {
     431           0 :                     if((var_node->get_type() == Node::node_t::NODE_PARAM || var_node->get_type() == Node::node_t::NODE_VARIABLE)
     432           0 :                     && var_node->get_flag(Node::flag_t::NODE_VARIABLE_FLAG_CONST))
     433             :                     {
     434           0 :                         Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_CANNOT_OVERWRITE_CONST, expr->get_position());
     435           0 :                         msg << "cannot increment or decrement a constant variable or function parameters.";
     436             :                     }
     437           0 :                 }
     438             :             }
     439           0 :             break;
     440             : 
     441             :         default:
     442           0 :             break;
     443             : 
     444             :         }
     445             :         // we keep intrinsic operators as is
     446             : //fprintf(stderr, "It is intrinsic...\n");
     447           0 :         expr->set_link(Node::link_t::LINK_INSTANCE, resolution);
     448           0 :         expr->set_link(Node::link_t::LINK_TYPE, op_type);
     449           0 :         return;
     450             :     }
     451             : //fprintf(stderr, "Not intrinsic...\n");
     452             : 
     453           0 :     id->set_link(Node::link_t::LINK_INSTANCE, resolution);
     454             : 
     455             :     // if not intrinsic, we need to transform the code
     456             :     // to a CALL instead because the lower layer won't
     457             :     // otherwise understand this operator!
     458           0 :     id->delete_child(0);
     459           0 :     id->set_link(Node::link_t::LINK_TYPE, op_type);
     460             : 
     461             :     // move operand in the new expression
     462           0 :     expr->delete_child(0);
     463             : 
     464             :     // TODO:
     465             :     // if the unary operator is post increment or decrement
     466             :     // then we need a temporary variable to save the current
     467             :     // value of the expression, compute the expression + 1
     468             :     // and restore the temporary
     469             : 
     470           0 :     Node::pointer_t post_list;
     471           0 :     Node::pointer_t assignment;
     472           0 :     bool const is_post = expr->get_type() == Node::node_t::NODE_POST_DECREMENT
     473           0 :                       || expr->get_type() == Node::node_t::NODE_POST_INCREMENT;
     474           0 :     if(is_post)
     475             :     {
     476           0 :         post_list = expr->create_replacement(Node::node_t::NODE_LIST);
     477             :         // TODO: should the list get the input type instead?
     478           0 :         post_list->set_link(Node::link_t::LINK_TYPE, op_type);
     479             : 
     480           0 :         Node::pointer_t temp_var(expr->create_replacement(Node::node_t::NODE_IDENTIFIER));
     481           0 :         temp_var->set_string("#temp_var#");
     482             : 
     483             :         // Save that name for next reference!
     484           0 :         assignment = expr->create_replacement(Node::node_t::NODE_ASSIGNMENT);
     485           0 :         assignment->append_child(temp_var);
     486           0 :         assignment->append_child(left);
     487             : 
     488           0 :         post_list->append_child(assignment);
     489             :     }
     490             : 
     491           0 :     Node::pointer_t call(expr->create_replacement(Node::node_t::NODE_CALL));
     492           0 :     call->set_link(Node::link_t::LINK_TYPE, op_type);
     493           0 :     Node::pointer_t member(expr->create_replacement(Node::node_t::NODE_MEMBER));
     494           0 :     Node::pointer_t function_node;
     495           0 :     resolve_internal_type(expr, "Function", function_node);
     496           0 :     member->set_link(Node::link_t::LINK_TYPE, function_node);
     497           0 :     call->append_child(member);
     498             : 
     499             :     // we need a function to get the name of 'type'
     500             :     //Data& type_data = type.GetData();
     501             :     //NodePtr object;
     502             :     //object.CreateNode(NODE_IDENTIFIER);
     503             :     //Data& obj_data = object.GetData();
     504             :     //obj_data.f_str = type_data.f_str;
     505           0 :     if(is_post)
     506             :     {
     507             :         // TODO: we MUST call the object defined
     508             :         //       by the left expression and NOT what
     509             :         //       I'm doing here; that's all wrong!!!
     510             :         //       for that we either need a "clone"
     511             :         //       function or a dual (or more)
     512             :         //       parenting...
     513           0 :         Node::pointer_t r(expr->create_replacement(Node::node_t::NODE_IDENTIFIER));
     514           0 :         if(left->get_type() == Node::node_t::NODE_IDENTIFIER)
     515             :         {
     516           0 :             r->set_string(left->get_string());
     517             :             // TODO: copy the links, flags, etc.
     518             :         }
     519             :         else
     520             :         {
     521             :             // TODO: use the same "temp var#" name
     522           0 :             r->set_string("#temp_var#");
     523             :         }
     524             : 
     525           0 :         member->append_child(r);
     526             :     }
     527             :     else
     528             :     {
     529           0 :         member->append_child(left);
     530             :     }
     531           0 :     member->append_child(id);
     532             : 
     533             : //fprintf(stderr, "NOTE: add a list (no params)\n");
     534           0 :     Node::pointer_t list(expr->create_replacement(Node::node_t::NODE_LIST));
     535           0 :     list->set_link(Node::link_t::LINK_TYPE, op_type);
     536           0 :     call->append_child(list);
     537             : 
     538           0 :     if(is_post)
     539             :     {
     540           0 :         post_list->append_child(call);
     541             : 
     542           0 :         Node::pointer_t temp_var(expr->create_replacement(Node::node_t::NODE_IDENTIFIER));
     543             :         // TODO: use the same name as used in the 1st temp_var#
     544           0 :         temp_var->set_string("#temp_var#");
     545           0 :         post_list->append_child(temp_var);
     546             : 
     547           0 :         expr->get_parent()->set_child(expr->get_offset(), post_list);
     548             :         //expr = post_list;
     549             :     }
     550             :     else
     551             :     {
     552           0 :         expr->get_parent()->set_child(expr->get_offset(), call);
     553             :         //expr = call;
     554           0 :     }
     555             : 
     556             : //expr.Display(stderr);
     557             : }
     558             : 
     559             : 
     560           0 : void Compiler::binary_operator(Node::pointer_t& expr)
     561             : {
     562           0 :     if(expr->get_children_size() != 2)
     563             :     {
     564           0 :         return;
     565             :     }
     566             : 
     567           0 :     char const *op = expr->operator_to_string(expr->get_type());
     568           0 :     if(!op)
     569             :     {
     570           0 :         throw exception_internal_error("operator_to_string() returned an empty string for a binary operator");
     571             :     }
     572             : 
     573           0 :     Node::pointer_t left(expr->get_child(0));
     574           0 :     Node::pointer_t ltype(left->get_link(Node::link_t::LINK_TYPE));
     575           0 :     if(!ltype)
     576             :     {
     577           0 :         return;
     578             :     }
     579             : 
     580           0 :     Node::pointer_t right(expr->get_child(1));
     581           0 :     Node::pointer_t rtype(right->get_link(Node::link_t::LINK_TYPE));
     582           0 :     if(!rtype)
     583             :     {
     584           0 :         return;
     585             :     }
     586             : 
     587           0 :     Node::pointer_t l(expr->create_replacement(Node::node_t::NODE_IDENTIFIER));
     588           0 :     l->set_string("left");
     589           0 :     Node::pointer_t r(expr->create_replacement(Node::node_t::NODE_IDENTIFIER));
     590           0 :     r->set_string("right");
     591             : 
     592           0 :     l->set_link(Node::link_t::LINK_TYPE, ltype);
     593           0 :     r->set_link(Node::link_t::LINK_TYPE, rtype);
     594             : 
     595           0 :     Node::pointer_t params(expr->create_replacement(Node::node_t::NODE_LIST));
     596           0 :     params->append_child(l);
     597           0 :     params->append_child(r);
     598             : 
     599           0 :     Node::pointer_t id(expr->create_replacement(Node::node_t::NODE_IDENTIFIER));
     600           0 :     id->set_string(op);
     601           0 :     id->append_child(params);
     602             : 
     603             :     // temporarily add a child to expr
     604           0 :     size_t const del(expr->get_children_size());
     605           0 :     expr->append_child(id);
     606             : 
     607           0 :     Node::pointer_t resolution;
     608           0 :     int funcs = 0;
     609             :     bool result;
     610             :     {
     611           0 :         NodeLock ln(expr);
     612           0 :         result = find_field(ltype, id, funcs, resolution, params, 0);
     613           0 :         if(!result)
     614             :         {
     615           0 :             result = find_field(rtype, id, funcs, resolution, params, 0);
     616           0 :         }
     617             :     }
     618             : 
     619           0 :     expr->delete_child(del);
     620           0 :     if(!result)
     621             :     {
     622           0 :         Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_INVALID_OPERATOR, expr->get_position());
     623           0 :         msg << "cannot apply operator '" << op << "' to these objects.";
     624           0 :         return;
     625             :     }
     626             : 
     627           0 :     Node::pointer_t op_type(resolution->get_link(Node::link_t::LINK_TYPE));
     628             : 
     629           0 :     if(get_attribute(resolution, Node::attribute_t::NODE_ATTR_NATIVE))
     630             :     {
     631             :         // we keep intrinsic operators as is
     632           0 :         expr->set_link(Node::link_t::LINK_INSTANCE, resolution);
     633           0 :         expr->set_link(Node::link_t::LINK_TYPE, op_type);
     634           0 :         return;
     635             :     }
     636             : 
     637           0 :     id->set_link(Node::link_t::LINK_INSTANCE, resolution);
     638             : 
     639             :     // if not intrinsic, we need to transform the code
     640             :     // to a CALL instead because the lower layer won't
     641             :     // otherwise understand this operator!
     642             : //fprintf(stderr, "Not intrinsic...\n");
     643           0 :     id->delete_child(0);
     644           0 :     id->set_link(Node::link_t::LINK_TYPE, op_type);
     645             : 
     646             :     // move left and right in the new expression
     647           0 :     expr->delete_child(1);
     648           0 :     expr->delete_child(0);
     649             : 
     650           0 :     Node::pointer_t call(expr->create_replacement(Node::node_t::NODE_CALL));
     651           0 :     call->set_link(Node::link_t::LINK_TYPE, op_type);
     652           0 :     Node::pointer_t member(expr->create_replacement(Node::node_t::NODE_MEMBER));;
     653           0 :     Node::pointer_t function_node;
     654           0 :     resolve_internal_type(expr, "Function", function_node);
     655           0 :     member->set_link(Node::link_t::LINK_TYPE, function_node);
     656           0 :     call->append_child(member);
     657             : 
     658             :     // we need a function to get the name of 'type'
     659             :     //Data& type_data = type.GetData();
     660             :     //NodePtr object;
     661             :     //object.CreateNode(NODE_IDENTIFIER);
     662             :     //Data& obj_data = object.GetData();
     663             :     //obj_data.f_str = type_data.f_str;
     664           0 :     member->append_child(left);
     665           0 :     member->append_child(id);
     666             : 
     667             : //fprintf(stderr, "NOTE: add list (right param)\n");
     668           0 :     Node::pointer_t list;
     669           0 :     list->create_replacement(Node::node_t::NODE_LIST);
     670           0 :     list->set_link(Node::link_t::LINK_TYPE, op_type);
     671           0 :     list->append_child(right);
     672           0 :     call->append_child(list);
     673             : 
     674             : //call.Display(stderr);
     675             : 
     676           0 :     expr->replace_with(call);
     677             : }
     678             : 
     679             : 
     680           0 : bool Compiler::special_identifier(Node::pointer_t expr)
     681             : {
     682             :     // all special identifiers are defined as "__...__"
     683             :     // that means they are at least 5 characters and they need to
     684             :     // start with '__'
     685             : 
     686             : //fprintf(stderr, "ID [%.*S]\n", data.f_str.GetLength(), data.f_str.Get());
     687           0 :     String id(expr->get_string());
     688           0 :     if(id.length() < 5)
     689             :     {
     690           0 :         return false;
     691             :     }
     692           0 :     if(id[0] != '_' || id[1] != '_')
     693             :     {
     694           0 :         return false;
     695             :     }
     696             : 
     697             :     // in case an error occurs
     698           0 :     const char *what = "?";
     699             : 
     700           0 :     Node::pointer_t parent(expr);
     701           0 :     String result;
     702           0 :     if(id == "__FUNCTION__")
     703             :     {
     704           0 :         what = "a function";
     705             :         for(;;)
     706             :         {
     707           0 :             parent = parent->get_parent();
     708           0 :             if(!parent)
     709             :             {
     710           0 :                 break;
     711             :             }
     712           0 :             if(parent->get_type() == Node::node_t::NODE_PACKAGE
     713           0 :             || parent->get_type() == Node::node_t::NODE_PROGRAM
     714           0 :             || parent->get_type() == Node::node_t::NODE_ROOT
     715           0 :             || parent->get_type() == Node::node_t::NODE_INTERFACE
     716           0 :             || parent->get_type() == Node::node_t::NODE_CLASS)
     717             :             {
     718           0 :                 parent.reset();
     719           0 :                 break;
     720             :             }
     721           0 :             if(parent->get_type() == Node::node_t::NODE_FUNCTION)
     722             :             {
     723           0 :                 break;
     724             :             }
     725             :         }
     726             :     }
     727           0 :     else if(id == "__CLASS__")
     728             :     {
     729           0 :         what = "a class";
     730             :         for(;;)
     731             :         {
     732           0 :             parent = parent->get_parent();
     733           0 :             if(!parent)
     734             :             {
     735           0 :                 break;
     736             :             }
     737           0 :             if(parent->get_type() == Node::node_t::NODE_PACKAGE
     738           0 :             || parent->get_type() == Node::node_t::NODE_PROGRAM
     739           0 :             || parent->get_type() == Node::node_t::NODE_ROOT)
     740             :             {
     741           0 :                 parent.reset();
     742           0 :                 break;
     743             :             }
     744           0 :             if(parent->get_type() == Node::node_t::NODE_CLASS)
     745             :             {
     746           0 :                 break;
     747             :             }
     748             :         }
     749             :     }
     750           0 :     else if(id == "__INTERFACE__")
     751             :     {
     752           0 :         what = "an interface";
     753             :         for(;;)
     754             :         {
     755           0 :             parent = parent->get_parent();
     756           0 :             if(!parent)
     757             :             {
     758           0 :                 break;
     759             :             }
     760           0 :             if(parent->get_type() == Node::node_t::NODE_PACKAGE
     761           0 :             || parent->get_type() == Node::node_t::NODE_PROGRAM
     762           0 :             || parent->get_type() == Node::node_t::NODE_ROOT)
     763             :             {
     764           0 :                 parent.reset();
     765           0 :                 break;
     766             :             }
     767           0 :             if(parent->get_type() == Node::node_t::NODE_INTERFACE)
     768             :             {
     769           0 :                 break;
     770             :             }
     771             :         }
     772             :     }
     773           0 :     else if(id == "__PACKAGE__")
     774             :     {
     775           0 :         what = "a package";
     776             :         for(;;)
     777             :         {
     778           0 :             parent = parent->get_parent();
     779           0 :             if(!parent)
     780             :             {
     781           0 :                 break;
     782             :             }
     783           0 :             if(parent->get_type() == Node::node_t::NODE_PROGRAM
     784           0 :             || parent->get_type() == Node::node_t::NODE_ROOT)
     785             :             {
     786           0 :                 parent.reset();
     787           0 :                 break;
     788             :             }
     789           0 :             if(parent->get_type() == Node::node_t::NODE_PACKAGE)
     790             :             {
     791           0 :                 break;
     792             :             }
     793             :         }
     794             :     }
     795           0 :     else if(id == "__NAME__")
     796             :     {
     797           0 :         what = "any function, class, interface or package";
     798             :         for(;;)
     799             :         {
     800           0 :             parent = parent->get_parent();
     801           0 :             if(!parent)
     802             :             {
     803           0 :                 break;
     804             :             }
     805           0 :             if(parent->get_type() == Node::node_t::NODE_PROGRAM
     806           0 :             || parent->get_type() == Node::node_t::NODE_ROOT)
     807             :             {
     808           0 :                 parent.reset();
     809           0 :                 break;
     810             :             }
     811           0 :             if(parent->get_type() == Node::node_t::NODE_FUNCTION
     812           0 :             || parent->get_type() == Node::node_t::NODE_CLASS
     813           0 :             || parent->get_type() == Node::node_t::NODE_INTERFACE
     814           0 :             || parent->get_type() == Node::node_t::NODE_PACKAGE)
     815             :             {
     816           0 :                 if(result.empty())
     817             :                 {
     818           0 :                     result = parent->get_string();
     819             :                 }
     820             :                 else
     821             :                 {
     822             :                     // TODO: create the + operator
     823             :                     //       on String.
     824           0 :                     String p(parent->get_string());
     825           0 :                     p += ".";
     826           0 :                     p += result;
     827           0 :                     result = p;
     828             :                 }
     829           0 :                 if(parent->get_type() == Node::node_t::NODE_PACKAGE)
     830             :                 {
     831             :                     // we do not really care if we
     832             :                     // are yet in another package
     833             :                     // at this time...
     834           0 :                     break;
     835             :                 }
     836             :             }
     837           0 :         }
     838             :     }
     839           0 :     else if(id == "__TIME__")
     840             :     {
     841             :         //what = "time";
     842             :         char buf[256];
     843             :         struct tm *t;
     844           0 :         time_t now(f_time);
     845           0 :         t = localtime(&now);
     846           0 :         strftime(buf, sizeof(buf) - 1, "%T", t);
     847           0 :         buf[sizeof(buf) - 1] = '\0';
     848           0 :         result = buf;
     849             :     }
     850           0 :     else if(id == "__DATE__")
     851             :     {
     852             :         //what = "date";
     853             :         char buf[256];
     854             :         struct tm *t;
     855           0 :         time_t now(f_time);
     856           0 :         t = localtime(&now);
     857           0 :         strftime(buf, sizeof(buf) - 1, "%Y-%m-%d", t);
     858           0 :         buf[sizeof(buf) - 1] = '\0';
     859           0 :         result = buf;
     860             :     }
     861           0 :     else if(id == "__UNIXTIME__")
     862             :     {
     863           0 :         expr->to_int64();
     864           0 :         Int64 integer;
     865           0 :         time_t now(f_time);
     866           0 :         integer.set(now);
     867           0 :         expr->set_int64(integer);
     868           0 :         return true;
     869             :     }
     870           0 :     else if(id == "__UTCTIME__")
     871             :     {
     872             :         //what = "utctime";
     873             :         char buf[256];
     874             :         struct tm *t;
     875           0 :         time_t now(f_time);
     876           0 :         t = gmtime(&now);
     877           0 :         strftime(buf, sizeof(buf) - 1, "%T", t);
     878           0 :         buf[sizeof(buf) - 1] = '\0';
     879           0 :         result = buf;
     880             :     }
     881           0 :     else if(id == "__UTCDATE__")
     882             :     {
     883             :         //what = "utcdate";
     884             :         char buf[256];
     885             :         struct tm *t;
     886           0 :         time_t now(f_time);
     887           0 :         t = gmtime(&now);
     888           0 :         strftime(buf, sizeof(buf) - 1, "%Y-%m-%d", t);
     889           0 :         buf[sizeof(buf) - 1] = '\0';
     890           0 :         result = buf;
     891             :     }
     892           0 :     else if(id == "__DATE822__")
     893             :     {
     894             :         // Sun, 06 Nov 2005 11:57:59 -0800
     895             :         //what = "utcdate";
     896             :         char buf[256];
     897             :         struct tm *t;
     898           0 :         time_t now(f_time);
     899           0 :         t = localtime(&now);
     900           0 :         strftime(buf, sizeof(buf) - 1, "%a, %d %b %Y %T %z", t);
     901           0 :         buf[sizeof(buf) - 1] = '\0';
     902           0 :         result = buf;
     903             :     }
     904             :     else
     905             :     {
     906             :         // not a special identifier
     907           0 :         return false;
     908             :     }
     909             : 
     910             :     // even if it fails, we convert this expression into a string
     911           0 :     expr->to_string();
     912           0 :     if(!result.empty())
     913             :     {
     914           0 :         expr->set_string(result);
     915             : 
     916             : //fprintf(stderr, "SpecialIdentifier Result = [%.*S]\n", result.GetLength(), result.Get());
     917             : 
     918             :     }
     919           0 :     else if(!parent)
     920             :     {
     921           0 :         Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_INVALID_EXPRESSION, expr->get_position());
     922           0 :         msg << "'" << expr->get_string() << "' was used outside " << what << ".";
     923             :         // we keep the string as is!
     924             :     }
     925             :     else
     926             :     {
     927           0 :         expr->set_string(parent->get_string());
     928             :     }
     929             : 
     930           0 :     return true;
     931             : }
     932             : 
     933             : 
     934           0 : void Compiler::type_expr(Node::pointer_t expr)
     935             : {
     936             :     // already typed?
     937           0 :     if(expr->get_link(Node::link_t::LINK_TYPE))
     938             :     {
     939           0 :         return;
     940             :     }
     941             : 
     942           0 :     Node::pointer_t resolution;
     943             : 
     944           0 :     switch(expr->get_type())
     945             :     {
     946             :     case Node::node_t::NODE_STRING:
     947           0 :         resolve_internal_type(expr, "String", resolution);
     948           0 :         expr->set_link(Node::link_t::LINK_TYPE, resolution);
     949           0 :         break;
     950             : 
     951             :     case Node::node_t::NODE_INT64:
     952           0 :         resolve_internal_type(expr, "Integer", resolution);
     953           0 :         expr->set_link(Node::link_t::LINK_TYPE, resolution);
     954           0 :         break;
     955             : 
     956             :     case Node::node_t::NODE_FLOAT64:
     957           0 :         resolve_internal_type(expr, "Double", resolution);
     958           0 :         expr->set_link(Node::link_t::LINK_TYPE, resolution);
     959           0 :         break;
     960             : 
     961             :     case Node::node_t::NODE_TRUE:
     962             :     case Node::node_t::NODE_FALSE:
     963           0 :         resolve_internal_type(expr, "Boolean", resolution);
     964           0 :         expr->set_link(Node::link_t::LINK_TYPE, resolution);
     965           0 :         break;
     966             : 
     967             :     case Node::node_t::NODE_OBJECT_LITERAL:
     968           0 :         resolve_internal_type(expr, "Object", resolution);
     969           0 :         expr->set_link(Node::link_t::LINK_TYPE, resolution);
     970           0 :         break;
     971             : 
     972             :     case Node::node_t::NODE_ARRAY_LITERAL:
     973           0 :         resolve_internal_type(expr, "Array", resolution);
     974           0 :         expr->set_link(Node::link_t::LINK_TYPE, resolution);
     975           0 :         break;
     976             : 
     977             :     default:
     978             :     {
     979           0 :         Node::pointer_t node(expr->get_link(Node::link_t::LINK_INSTANCE));
     980           0 :         if(!node)
     981             :         {
     982           0 :             break;
     983             :         }
     984           0 :         if(node->get_type() != Node::node_t::NODE_VARIABLE
     985           0 :         || node->get_children_size() == 0)
     986             :         {
     987           0 :             break;
     988             :         }
     989           0 :         Node::pointer_t type(node->get_child(0));
     990           0 :         if(type->get_type() == Node::node_t::NODE_SET)
     991             :         {
     992           0 :             break;
     993             :         }
     994           0 :         Node::pointer_t instance(type->get_link(Node::link_t::LINK_INSTANCE));
     995           0 :         if(!instance)
     996             :         {
     997             :             // TODO: resolve that if not done yet (it should
     998             :             //       always already be at this time)
     999           0 :             Message msg(message_level_t::MESSAGE_LEVEL_FATAL, err_code_t::AS_ERR_INTERNAL_ERROR, expr->get_position());
    1000           0 :             msg << "type is missing when it should not.";
    1001           0 :             throw exception_exit(1, "missing a required type.");
    1002             :         }
    1003           0 :         expr->set_link(Node::link_t::LINK_TYPE, instance);
    1004             :     }
    1005           0 :         break;
    1006             : 
    1007             :     }
    1008             : 
    1009           0 :     return;
    1010             : }
    1011             : 
    1012             : 
    1013           0 : void Compiler::object_literal(Node::pointer_t expr)
    1014             : {
    1015             :     // define the type of the literal (i.e. Object)
    1016           0 :     type_expr(expr);
    1017             : 
    1018             :     // go through the list of names and
    1019             :     //    1) make sure property names are unique
    1020             :     //    2) make sure property names are proper
    1021             :     //    3) compile expressions
    1022           0 :     size_t const max_children(expr->get_children_size());
    1023           0 :     if((max_children & 1) != 0)
    1024             :     {
    1025             :         // invalid?!
    1026             :         // the number of children must be even to support pairs of
    1027             :         // names and a values
    1028           0 :         return;
    1029             :     }
    1030             : 
    1031           0 :     for(size_t idx(0); idx < max_children; idx += 2)
    1032             :     {
    1033           0 :         Node::pointer_t name(expr->get_child(idx));
    1034           0 :         size_t const cnt(name->get_children_size());
    1035           0 :         if(name->get_type() == Node::node_t::NODE_TYPE)
    1036             :         {
    1037             :             // the first child is a dynamic name(space)
    1038           0 :             expression(name->get_child(0));
    1039           0 :             if(cnt == 2)
    1040             :             {
    1041             :                 // TODO: this is a scope
    1042             :                 //    name.GetChild(0) :: name.GetChild(1)
    1043             :                 // ...
    1044           0 :                 Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_NOT_SUPPORTED, name->get_position());
    1045           0 :                 msg << "scopes not supported yet. (1)";
    1046             :             }
    1047             :         }
    1048           0 :         else if(cnt == 1)
    1049             :         {
    1050             :             // TODO: this is a scope
    1051             :             //    name :: name->get_child(0)
    1052             :             // Here name is IDENTIFIER, PRIVATE or PUBLIC
    1053             :             // ...
    1054           0 :             Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_NOT_SUPPORTED, name->get_position());
    1055           0 :             msg << "scopes not supported yet. (2)";
    1056             :         }
    1057             : 
    1058             :         // compile the value
    1059           0 :         Node::pointer_t value(expr->get_child(idx + 1));
    1060           0 :         expression(value);
    1061           0 :     }
    1062             : }
    1063             : 
    1064             : 
    1065           0 : void Compiler::assignment_operator(Node::pointer_t expr)
    1066             : {
    1067           0 :     bool is_var = false;
    1068             : 
    1069           0 :     Node::pointer_t var_node;    // in case this assignment is also a definition
    1070             : 
    1071           0 :     Node::pointer_t left(expr->get_child(0));
    1072           0 :     if(left->get_type() == Node::node_t::NODE_IDENTIFIER)
    1073             :     {
    1074             :         // this may be like a VAR <name> = ...
    1075           0 :         Node::pointer_t resolution;
    1076           0 :         if(resolve_name(left, left, resolution, Node::pointer_t(), 0))
    1077             :         {
    1078           0 :             bool valid(false);
    1079           0 :             if(resolution->get_type() == Node::node_t::NODE_VARIABLE)
    1080             :             {
    1081           0 :                 if(resolution->get_flag(Node::flag_t::NODE_VARIABLE_FLAG_CONST))
    1082             :                 {
    1083           0 :                     Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_CANNOT_OVERWRITE_CONST, left->get_position());
    1084           0 :                     msg << "you cannot assign a value to the constant variable '" << resolution->get_string() << "'.";
    1085             :                 }
    1086             :                 else
    1087             :                 {
    1088           0 :                     valid = true;
    1089             :                 }
    1090             :             }
    1091           0 :             else if(resolution->get_type() == Node::node_t::NODE_PARAM)
    1092             :             {
    1093           0 :                 if(resolution->get_flag(Node::flag_t::NODE_PARAM_FLAG_CONST))
    1094             :                 {
    1095           0 :                     Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_CANNOT_OVERWRITE_CONST, left->get_position());
    1096           0 :                     msg << "you cannot assign a value to the constant function parameter '" << resolution->get_string() << "'.";
    1097             :                 }
    1098             :                 else
    1099             :                 {
    1100           0 :                     valid = true;
    1101             :                 }
    1102             :             }
    1103             :             else
    1104             :             {
    1105           0 :                 Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_CANNOT_OVERLOAD, left->get_position());
    1106           0 :                 msg << "you cannot assign but a variable or a function parameter.";
    1107             :             }
    1108           0 :             if(valid)
    1109             :             {
    1110           0 :                 left->set_link(Node::link_t::LINK_INSTANCE, resolution);
    1111           0 :                 left->set_link(Node::link_t::LINK_TYPE, resolution->get_link(Node::link_t::LINK_TYPE));
    1112             :             }
    1113             :         }
    1114             :         else
    1115             :         {
    1116             :             // it is a missing VAR!
    1117           0 :             is_var = true;
    1118             : 
    1119             :             // we need to put this variable in the function
    1120             :             // in which it is encapsulated, if there is
    1121             :             // such a function so it can be marked as local
    1122             :             // for that we create a var ourselves
    1123           0 :             Node::pointer_t variable_node;
    1124           0 :             Node::pointer_t set;
    1125           0 :             var_node = expr->create_replacement(Node::node_t::NODE_VAR);
    1126           0 :             var_node->set_flag(Node::flag_t::NODE_VARIABLE_FLAG_TOADD, true);
    1127           0 :             var_node->set_flag(Node::flag_t::NODE_VARIABLE_FLAG_DEFINING, true);
    1128           0 :             variable_node = expr->create_replacement(Node::node_t::NODE_VARIABLE);
    1129           0 :             var_node->append_child(variable_node);
    1130           0 :             variable_node->set_string(left->get_string());
    1131           0 :             Node::pointer_t parent(left);
    1132           0 :             Node::pointer_t last_directive;
    1133             :             for(;;)
    1134             :             {
    1135           0 :                 parent = parent->get_parent();
    1136           0 :                 if(parent->get_type() == Node::node_t::NODE_DIRECTIVE_LIST)
    1137             :                 {
    1138           0 :                     last_directive = parent;
    1139             :                 }
    1140           0 :                 else if(parent->get_type() == Node::node_t::NODE_FUNCTION)
    1141             :                 {
    1142           0 :                     variable_node->set_flag(Node::flag_t::NODE_VARIABLE_FLAG_LOCAL, true);
    1143           0 :                     parent->add_variable(variable_node);
    1144           0 :                     break;
    1145             :                 }
    1146           0 :                 else if(parent->get_type() == Node::node_t::NODE_PROGRAM
    1147           0 :                      || parent->get_type() == Node::node_t::NODE_CLASS
    1148           0 :                      || parent->get_type() == Node::node_t::NODE_INTERFACE
    1149           0 :                      || parent->get_type() == Node::node_t::NODE_PACKAGE)
    1150             :                 {
    1151             :                     // not found?!
    1152           0 :                     break;
    1153             :                 }
    1154             :             }
    1155           0 :             left->set_link(Node::link_t::LINK_INSTANCE, variable_node);
    1156             : 
    1157             :             // We cannot call InsertChild()
    1158             :             // here since it would be in our
    1159             :             // locked parent. So instead we
    1160             :             // only add it to the list of
    1161             :             // variables of the directive list
    1162             :             // and later we will also add it
    1163             :             // at the top of the list
    1164           0 :             if(last_directive)
    1165             :             {
    1166             :                 //parent->insert_child(0, var_node);
    1167           0 :                 last_directive->add_variable(variable_node);
    1168           0 :                 last_directive->set_flag(Node::flag_t::NODE_DIRECTIVE_LIST_FLAG_NEW_VARIABLES, true);
    1169           0 :             }
    1170           0 :         }
    1171             :     }
    1172           0 :     else if(left->get_type() == Node::node_t::NODE_MEMBER)
    1173             :     {
    1174             :         // we parsed?
    1175           0 :         if(!left->get_link(Node::link_t::LINK_TYPE))
    1176             :         {
    1177             :             // try to optimize the expression before to compile it
    1178             :             // (it can make a huge difference!)
    1179           0 :             Optimizer::optimize(left);
    1180             :             //Node::pointer_t right(expr->get_child(1));
    1181             : 
    1182           0 :             resolve_member(left, 0, SEARCH_FLAG_SETTER);
    1183             : 
    1184             :             // setters have to be treated here because within ResolveMember()
    1185             :             // we do not have access to the assignment and that's what needs
    1186             :             // to change to a call.
    1187           0 :             Node::pointer_t resolution(left->get_link(Node::link_t::LINK_INSTANCE));
    1188           0 :             if(resolution)
    1189             :             {
    1190           0 :                 if(resolution->get_type() == Node::node_t::NODE_FUNCTION
    1191           0 :                 && resolution->get_flag(Node::flag_t::NODE_FUNCTION_FLAG_SETTER))
    1192             :                 {
    1193             :                     // TODO: handle setters -- this is an old comment
    1194             :                     //       maybe it was not deleted? I do not think
    1195             :                     //       that these work properly yet, but it looks
    1196             :                     //       like I already started work on those.
    1197           0 : std::cerr << "CAUGHT! setter...\n";
    1198             :                     // so expr is a MEMBER at this time
    1199             :                     // it has two children
    1200             :                     //NodePtr left = expr.GetChild(0);
    1201           0 :                     Node::pointer_t right(expr->get_child(1));
    1202             :                     //expr.DeleteChild(0);
    1203             :                     //expr.DeleteChild(1);    // 1 is now 0
    1204             : 
    1205             :                     // create a new node since we don't want to move the
    1206             :                     // call (expr) node from its parent.
    1207             :                     //NodePtr member;
    1208             :                     //member.CreateNode(NODE_MEMBER);
    1209             :                     //member.SetLink(NodePtr::LINK_INSTANCE, resolution);
    1210             :                     //member.AddChild(left);
    1211             :                     //member.AddChild(right);
    1212             :                     //member.SetLink(NodePtr::LINK_TYPE, type);
    1213             : 
    1214             :                     //expr.AddChild(left);
    1215             : 
    1216             :                     // we need to change the name to match the getter
    1217             :                     // NOTE: we know that the field data is an identifier
    1218             :                     //     a v-identifier or a string so the following
    1219             :                     //     will always work
    1220           0 :                     Node::pointer_t field(left->get_child(1));
    1221           0 :                     String getter_name("<-");
    1222           0 :                     getter_name += field->get_string();
    1223           0 :                     field->set_string(getter_name);
    1224             : 
    1225             :                     // the call needs a list of parameters (1 parameter)
    1226           0 :                     Node::pointer_t params(expr->create_replacement(Node::node_t::NODE_LIST));
    1227             :                     /*
    1228             :                     NodePtr this_expr;
    1229             :                     this_expr.CreateNode(NODE_THIS);
    1230             :                     params.AddChild(this_expr);
    1231             :                     */
    1232           0 :                     expr->set_child(1, params);
    1233             : 
    1234           0 :                     params->append_child(right);
    1235             : 
    1236             : 
    1237             :                     // and finally, we transform the member in a call!
    1238           0 :                     expr->to_call();
    1239             :                 }
    1240           0 :             }
    1241             :         }
    1242             :     }
    1243             :     else
    1244             :     {
    1245             :         // Is this really acceptable?!
    1246             :         // We can certainly make it work in Macromedia Flash...
    1247             :         // If the expression is resolved as a string which is
    1248             :         // also a valid variable name.
    1249           0 :         expression(left);
    1250             :     }
    1251             : 
    1252           0 :     Node::pointer_t right(expr->get_child(1));
    1253           0 :     expression(right);
    1254             : 
    1255           0 :     if(var_node)
    1256             :     {
    1257           0 :         var_node->set_flag(Node::flag_t::NODE_VARIABLE_FLAG_DEFINING, false);
    1258             :     }
    1259             : 
    1260           0 :     Node::pointer_t type(left->get_link(Node::link_t::LINK_TYPE));
    1261           0 :     if(type)
    1262             :     {
    1263           0 :         expr->set_link(Node::link_t::LINK_TYPE, type);
    1264           0 :         return;
    1265             :     }
    1266             : 
    1267           0 :     if(!is_var)
    1268             :     {
    1269             :         // if left not typed, use right type!
    1270             :         // (the assignment is this type of special case...)
    1271           0 :         expr->set_link(Node::link_t::LINK_TYPE, right->get_link(Node::link_t::LINK_TYPE));
    1272           0 :     }
    1273             : }
    1274             : 
    1275             : 
    1276           0 : void Compiler::expression(Node::pointer_t expr, Node::pointer_t params)
    1277             : {
    1278             :     // we already came here on that one?
    1279           0 :     if(expr->get_link(Node::link_t::LINK_TYPE))
    1280             :     {
    1281           0 :         return;
    1282             :     }
    1283             : 
    1284             :     // try to optimize the expression before to compile it
    1285             :     // (it can make a huge difference!)
    1286           0 :     Optimizer::optimize(expr);
    1287             : 
    1288           0 :     switch(expr->get_type())
    1289             :     {
    1290             :     case Node::node_t::NODE_STRING:
    1291             :     case Node::node_t::NODE_INT64:
    1292             :     case Node::node_t::NODE_FLOAT64:
    1293             :     case Node::node_t::NODE_TRUE:
    1294             :     case Node::node_t::NODE_FALSE:
    1295           0 :         type_expr(expr);
    1296           0 :         return;
    1297             : 
    1298             :     case Node::node_t::NODE_ARRAY_LITERAL:
    1299           0 :         type_expr(expr);
    1300           0 :         break;
    1301             : 
    1302             :     case Node::node_t::NODE_OBJECT_LITERAL:
    1303           0 :         object_literal(expr);
    1304           0 :         return;
    1305             : 
    1306             :     case Node::node_t::NODE_NULL:
    1307             :     case Node::node_t::NODE_PUBLIC:
    1308             :     case Node::node_t::NODE_PRIVATE:
    1309             :     case Node::node_t::NODE_UNDEFINED:
    1310           0 :         return;
    1311             : 
    1312             :     case Node::node_t::NODE_SUPER:
    1313           0 :         check_super_validity(expr);
    1314           0 :         return;
    1315             : 
    1316             :     case Node::node_t::NODE_THIS:
    1317           0 :         check_this_validity(expr);
    1318           0 :         return;
    1319             : 
    1320             :     case Node::node_t::NODE_ADD:
    1321             :     case Node::node_t::NODE_ARRAY:
    1322             :     case Node::node_t::NODE_AS:
    1323             :     case Node::node_t::NODE_ASSIGNMENT_ADD:
    1324             :     case Node::node_t::NODE_ASSIGNMENT_BITWISE_AND:
    1325             :     case Node::node_t::NODE_ASSIGNMENT_BITWISE_OR:
    1326             :     case Node::node_t::NODE_ASSIGNMENT_BITWISE_XOR:
    1327             :     case Node::node_t::NODE_ASSIGNMENT_DIVIDE:
    1328             :     case Node::node_t::NODE_ASSIGNMENT_LOGICAL_AND:
    1329             :     case Node::node_t::NODE_ASSIGNMENT_LOGICAL_OR:
    1330             :     case Node::node_t::NODE_ASSIGNMENT_LOGICAL_XOR:
    1331             :     case Node::node_t::NODE_ASSIGNMENT_MAXIMUM:
    1332             :     case Node::node_t::NODE_ASSIGNMENT_MINIMUM:
    1333             :     case Node::node_t::NODE_ASSIGNMENT_MODULO:
    1334             :     case Node::node_t::NODE_ASSIGNMENT_MULTIPLY:
    1335             :     case Node::node_t::NODE_ASSIGNMENT_POWER:
    1336             :     case Node::node_t::NODE_ASSIGNMENT_ROTATE_LEFT:
    1337             :     case Node::node_t::NODE_ASSIGNMENT_ROTATE_RIGHT:
    1338             :     case Node::node_t::NODE_ASSIGNMENT_SHIFT_LEFT:
    1339             :     case Node::node_t::NODE_ASSIGNMENT_SHIFT_RIGHT:
    1340             :     case Node::node_t::NODE_ASSIGNMENT_SHIFT_RIGHT_UNSIGNED:
    1341             :     case Node::node_t::NODE_ASSIGNMENT_SUBTRACT:
    1342             :     case Node::node_t::NODE_BITWISE_AND:
    1343             :     case Node::node_t::NODE_BITWISE_NOT:
    1344             :     case Node::node_t::NODE_BITWISE_OR:
    1345             :     case Node::node_t::NODE_BITWISE_XOR:
    1346             :     case Node::node_t::NODE_CONDITIONAL:
    1347             :     case Node::node_t::NODE_DECREMENT:
    1348             :     case Node::node_t::NODE_DELETE:
    1349             :     case Node::node_t::NODE_DIVIDE:
    1350             :     case Node::node_t::NODE_EQUAL:
    1351             :     case Node::node_t::NODE_GREATER:
    1352             :     case Node::node_t::NODE_GREATER_EQUAL:
    1353             :     case Node::node_t::NODE_IN:
    1354             :     case Node::node_t::NODE_INCREMENT:
    1355             :     case Node::node_t::NODE_INSTANCEOF:
    1356             :     case Node::node_t::NODE_TYPEOF:
    1357             :     case Node::node_t::NODE_IS:
    1358             :     case Node::node_t::NODE_LESS:
    1359             :     case Node::node_t::NODE_LESS_EQUAL:
    1360             :     case Node::node_t::NODE_LIST:
    1361             :     case Node::node_t::NODE_LOGICAL_AND:
    1362             :     case Node::node_t::NODE_LOGICAL_NOT:
    1363             :     case Node::node_t::NODE_LOGICAL_OR:
    1364             :     case Node::node_t::NODE_LOGICAL_XOR:
    1365             :     case Node::node_t::NODE_MATCH:
    1366             :     case Node::node_t::NODE_MAXIMUM:
    1367             :     case Node::node_t::NODE_MINIMUM:
    1368             :     case Node::node_t::NODE_MODULO:
    1369             :     case Node::node_t::NODE_MULTIPLY:
    1370             :     case Node::node_t::NODE_NOT_EQUAL:
    1371             :     case Node::node_t::NODE_POST_DECREMENT:
    1372             :     case Node::node_t::NODE_POST_INCREMENT:
    1373             :     case Node::node_t::NODE_POWER:
    1374             :     case Node::node_t::NODE_RANGE:
    1375             :     case Node::node_t::NODE_ROTATE_LEFT:
    1376             :     case Node::node_t::NODE_ROTATE_RIGHT:
    1377             :     case Node::node_t::NODE_SCOPE:
    1378             :     case Node::node_t::NODE_SHIFT_LEFT:
    1379             :     case Node::node_t::NODE_SHIFT_RIGHT:
    1380             :     case Node::node_t::NODE_SHIFT_RIGHT_UNSIGNED:
    1381             :     case Node::node_t::NODE_STRICTLY_EQUAL:
    1382             :     case Node::node_t::NODE_STRICTLY_NOT_EQUAL:
    1383             :     case Node::node_t::NODE_SUBTRACT:
    1384           0 :         break;
    1385             : 
    1386             :     case Node::node_t::NODE_NEW:
    1387             :         // TBD: we later check whether we can instantiate this 'expr'
    1388             :         //      object; but if we return here, then that test will
    1389             :         //      be skipped (unless the return is inapropriate or
    1390             :         //      we should have if(!expression_new(expr)) ...
    1391           0 :         if(expression_new(expr))
    1392             :         {
    1393           0 :             return;
    1394             :         }
    1395           0 :         break;
    1396             : 
    1397             :     case Node::node_t::NODE_VOID:
    1398             :         // If the expression has no side effect (i.e. doesn't
    1399             :         // call a function, doesn't use ++ or --, etc.) then
    1400             :         // we don't even need to keep it! Instead we replace
    1401             :         // the void by undefined.
    1402           0 :         if(expr->has_side_effects())
    1403             :         {
    1404             :             // we need to keep some of this expression
    1405             :             //
    1406             :             // TODO: we need to optimize better; this
    1407             :             // should only keep expressions with side
    1408             :             // effects and not all expressions; for
    1409             :             // instance:
    1410             :             //    void (a + b(c));
    1411             :             // should become:
    1412             :             //    void b(c);
    1413             :             // (assuming that 'a' isn't a call to a getter
    1414             :             // function which could have a side effect)
    1415           0 :             break;
    1416             :         }
    1417             :         // this is what void returns, assuming the expression
    1418             :         // had no side effect, that's all we need here
    1419           0 :         expr = expr->create_replacement(Node::node_t::NODE_UNDEFINED);
    1420           0 :         return;
    1421             : 
    1422             :     case Node::node_t::NODE_ASSIGNMENT:
    1423           0 :         assignment_operator(expr);
    1424           0 :         return;
    1425             : 
    1426             :     case Node::node_t::NODE_FUNCTION:
    1427           0 :         function(expr);
    1428           0 :         return;
    1429             : 
    1430             :     case Node::node_t::NODE_MEMBER:
    1431           0 :         resolve_member(expr, params, SEARCH_FLAG_GETTER);
    1432           0 :         return;
    1433             : 
    1434             :     case Node::node_t::NODE_IDENTIFIER:
    1435             :     case Node::node_t::NODE_VIDENTIFIER:
    1436           0 :         if(!special_identifier(expr))
    1437             :         {
    1438           0 :             Node::pointer_t resolution;
    1439           0 :             if(resolve_name(expr, expr, resolution, params, SEARCH_FLAG_GETTER))
    1440             :             {
    1441           0 :                 if(!replace_constant_variable(expr, resolution))
    1442             :                 {
    1443           0 :                     Node::pointer_t current(expr->get_link(Node::link_t::LINK_INSTANCE));
    1444           0 :                     if(current)
    1445             :                     {
    1446             :                         // TBD: I'm not exactly sure what this does right now, we
    1447             :                         //      probably can ameliorate the error message, although
    1448             :                         //      we should actually never get it!
    1449           0 :                         throw exception_internal_error("The link instance of this VIDENTIFIER was already defined...");
    1450             :                     }
    1451           0 :                     expr->set_link(Node::link_t::LINK_INSTANCE, resolution);
    1452           0 :                     Node::pointer_t type(resolution->get_link(Node::link_t::LINK_TYPE));
    1453           0 :                     if(type)
    1454             :                     {
    1455           0 :                         expr->set_link(Node::link_t::LINK_TYPE, type);
    1456           0 :                     }
    1457             :                 }
    1458             :             }
    1459             :             else
    1460             :             {
    1461           0 :                 Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_NOT_FOUND, expr->get_position());
    1462           0 :                 msg << "cannot find any variable or class declaration for: '" << expr->get_string() << "'.";
    1463           0 :             }
    1464             :         }
    1465           0 :         return;
    1466             : 
    1467             :     case Node::node_t::NODE_CALL:
    1468           0 :         resolve_call(expr);
    1469           0 :         return;
    1470             : 
    1471             :     default:
    1472             :         {
    1473           0 :             Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_INTERNAL_ERROR, expr->get_position());
    1474           0 :             msg << "unhandled expression data type \"" << expr->get_type_name() << "\".";
    1475             :         }
    1476           0 :         return;
    1477             : 
    1478             :     }
    1479             : 
    1480             : // When not returned yet, we want that expression to
    1481             : // compile all the children nodes as expressions.
    1482           0 :     size_t const max_children(expr->get_children_size());
    1483             :     {
    1484           0 :         NodeLock ln(expr);
    1485           0 :         for(size_t idx(0); idx < max_children; ++idx)
    1486             :         {
    1487           0 :             Node::pointer_t child(expr->get_child(idx));
    1488             :             // skip labels
    1489           0 :             if(child->get_type() != Node::node_t::NODE_NAME)
    1490             :             {
    1491           0 :                 expression(child); // recursive!
    1492             :             }
    1493             :             // TODO:
    1494             :             // Do we want/have to do the following?
    1495             :             //else if(child->get_children_size() > 0)
    1496             :             //{
    1497             :             //    Node::pointer_t sub_expr(child->get_child(0));
    1498             :             //    expression(sub_expr);
    1499             :             //}
    1500           0 :         }
    1501             :     }
    1502             : 
    1503             : // Now check for operators to give them a type
    1504           0 :     switch(expr->get_type())
    1505             :     {
    1506             :     case Node::node_t::NODE_ADD:
    1507             :     case Node::node_t::NODE_SUBTRACT:
    1508           0 :         if(max_children == 1)
    1509             :         {
    1510           0 :             unary_operator(expr);
    1511             :         }
    1512             :         else
    1513             :         {
    1514           0 :             binary_operator(expr);
    1515             :         }
    1516           0 :         break;
    1517             : 
    1518             :     case Node::node_t::NODE_BITWISE_NOT:
    1519             :     case Node::node_t::NODE_DECREMENT:
    1520             :     case Node::node_t::NODE_INCREMENT:
    1521             :     case Node::node_t::NODE_LOGICAL_NOT:
    1522             :     case Node::node_t::NODE_POST_DECREMENT:
    1523             :     case Node::node_t::NODE_POST_INCREMENT:
    1524           0 :         unary_operator(expr);
    1525           0 :         break;
    1526             : 
    1527             :     case Node::node_t::NODE_BITWISE_AND:
    1528             :     case Node::node_t::NODE_BITWISE_OR:
    1529             :     case Node::node_t::NODE_BITWISE_XOR:
    1530             :     case Node::node_t::NODE_DIVIDE:
    1531             :     case Node::node_t::NODE_EQUAL:
    1532             :     case Node::node_t::NODE_GREATER:
    1533             :     case Node::node_t::NODE_GREATER_EQUAL:
    1534             :     case Node::node_t::NODE_LESS:
    1535             :     case Node::node_t::NODE_LESS_EQUAL:
    1536             :     case Node::node_t::NODE_LOGICAL_AND:
    1537             :     case Node::node_t::NODE_LOGICAL_OR:
    1538             :     case Node::node_t::NODE_LOGICAL_XOR:
    1539             :     case Node::node_t::NODE_MATCH:
    1540             :     case Node::node_t::NODE_MAXIMUM:
    1541             :     case Node::node_t::NODE_MINIMUM:
    1542             :     case Node::node_t::NODE_MODULO:
    1543             :     case Node::node_t::NODE_MULTIPLY:
    1544             :     case Node::node_t::NODE_NOT_EQUAL:
    1545             :     case Node::node_t::NODE_POWER:
    1546             :     case Node::node_t::NODE_RANGE:
    1547             :     case Node::node_t::NODE_ROTATE_LEFT:
    1548             :     case Node::node_t::NODE_ROTATE_RIGHT:
    1549             :     case Node::node_t::NODE_SCOPE:
    1550             :     case Node::node_t::NODE_SHIFT_LEFT:
    1551             :     case Node::node_t::NODE_SHIFT_RIGHT:
    1552             :     case Node::node_t::NODE_SHIFT_RIGHT_UNSIGNED:
    1553             :     case Node::node_t::NODE_STRICTLY_EQUAL:
    1554             :     case Node::node_t::NODE_STRICTLY_NOT_EQUAL:
    1555           0 :         binary_operator(expr);
    1556           0 :         break;
    1557             : 
    1558             :     case Node::node_t::NODE_IN:
    1559             :     case Node::node_t::NODE_CONDITIONAL:    // cannot be overwritten!
    1560           0 :         break;
    1561             : 
    1562             :     case Node::node_t::NODE_ARRAY:
    1563             :     case Node::node_t::NODE_ARRAY_LITERAL:
    1564             :     case Node::node_t::NODE_AS:
    1565             :     case Node::node_t::NODE_DELETE:
    1566             :     case Node::node_t::NODE_INSTANCEOF:
    1567             :     case Node::node_t::NODE_IS:
    1568             :     case Node::node_t::NODE_TYPEOF:
    1569             :     case Node::node_t::NODE_VOID:
    1570             :         // nothing special we can do here...
    1571           0 :         break;
    1572             : 
    1573             :     case Node::node_t::NODE_NEW:
    1574           0 :         can_instantiate_type(expr->get_child(0));
    1575           0 :         break;
    1576             : 
    1577             :     case Node::node_t::NODE_LIST:
    1578             :         {
    1579             :             // this is the type of the last entry
    1580           0 :             Node::pointer_t child(expr->get_child(max_children - 1));
    1581           0 :             expr->set_link(Node::link_t::LINK_TYPE, child->get_link(Node::link_t::LINK_TYPE));
    1582             :         }
    1583           0 :         break;
    1584             : 
    1585             :     case Node::node_t::NODE_ASSIGNMENT_ADD:
    1586             :     case Node::node_t::NODE_ASSIGNMENT_BITWISE_AND:
    1587             :     case Node::node_t::NODE_ASSIGNMENT_BITWISE_OR:
    1588             :     case Node::node_t::NODE_ASSIGNMENT_BITWISE_XOR:
    1589             :     case Node::node_t::NODE_ASSIGNMENT_DIVIDE:
    1590             :     case Node::node_t::NODE_ASSIGNMENT_LOGICAL_AND:
    1591             :     case Node::node_t::NODE_ASSIGNMENT_LOGICAL_OR:
    1592             :     case Node::node_t::NODE_ASSIGNMENT_LOGICAL_XOR:
    1593             :     case Node::node_t::NODE_ASSIGNMENT_MAXIMUM:
    1594             :     case Node::node_t::NODE_ASSIGNMENT_MINIMUM:
    1595             :     case Node::node_t::NODE_ASSIGNMENT_MODULO:
    1596             :     case Node::node_t::NODE_ASSIGNMENT_MULTIPLY:
    1597             :     case Node::node_t::NODE_ASSIGNMENT_POWER:
    1598             :     case Node::node_t::NODE_ASSIGNMENT_ROTATE_LEFT:
    1599             :     case Node::node_t::NODE_ASSIGNMENT_ROTATE_RIGHT:
    1600             :     case Node::node_t::NODE_ASSIGNMENT_SHIFT_LEFT:
    1601             :     case Node::node_t::NODE_ASSIGNMENT_SHIFT_RIGHT:
    1602             :     case Node::node_t::NODE_ASSIGNMENT_SHIFT_RIGHT_UNSIGNED:
    1603             :     case Node::node_t::NODE_ASSIGNMENT_SUBTRACT:
    1604             :         // TODO: we need to replace the intrinsic special
    1605             :         //       assignment ops with a regular assignment
    1606             :         //       (i.e. a += b becomes a = a + (b))
    1607           0 :         binary_operator(expr);
    1608           0 :         break;
    1609             : 
    1610             :     default:
    1611           0 :         throw exception_internal_error("error: there is a missing entry in the 2nd switch of Compiler::expression()");
    1612             : 
    1613             :     }
    1614             : }
    1615             : 
    1616             : 
    1617             : 
    1618          63 : }
    1619             : // namespace as2js
    1620             : 
    1621             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.10