LCOV - code coverage report
Current view: top level - lib - compiler_package.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 107 480 22.3 %
Date: 2014-11-22 Functions: 11 20 55.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* compiler_package.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             : #include    "as2js/parser.h"
      41             : 
      42             : // private classes
      43             : #include    "db.h"
      44             : #include    "rc.h"
      45             : 
      46             : #include    <controlled_vars/controlled_vars_auto_enum_init.h>
      47             : 
      48             : #include    <algorithm>
      49             : 
      50             : #include    <dirent.h>
      51             : #include    <cstring>
      52             : 
      53             : 
      54             : namespace as2js
      55             : {
      56             : 
      57             : 
      58             : namespace
      59             : {
      60             : 
      61             : 
      62             : // The following globals are read only once and you can compile
      63             : // many times without having to reload them.
      64             : //
      65             : // the resource file information
      66             : //
      67          21 : rc_t                        g_rc;
      68             : 
      69             : // the global imports (those which are automatic and
      70             : // define the intrinsic functions and types of the language)
      71             : //
      72          21 : Node::pointer_t             g_global_import;
      73             : 
      74             : // the system imports (this is specific to the system you
      75             : // are using this compiler for; it defines the system)
      76             : //
      77          21 : Node::pointer_t             g_system_import;
      78             : 
      79             : // the native imports (this is specific to your system
      80             : // environment, it defines objects in your environment)
      81             : //
      82          21 : Node::pointer_t             g_native_import;
      83             : 
      84             : // the database handling all the packages and their name
      85             : // so we can quickly find which package to import when
      86             : // a given name is used
      87             : //
      88          21 : Database::pointer_t         g_db;
      89             : 
      90             : // whether the database was loaded (true) or not (false)
      91             : //
      92          21 : controlled_vars::fbool_t    g_db_loaded;
      93             : 
      94             : // Search for a named element:
      95             : // <package name>{.<package name>}.<class, function, variable name>
      96             : // TODO: add support for '*' in <package name>
      97           0 : Database::Element::pointer_t find_element(String const& package_name, String const& element_name, char const *type)
      98             : {
      99           0 :     Database::package_vector_t packages(g_db->find_packages(package_name));
     100           0 :     for(auto pt(packages.begin()); pt != packages.end(); ++pt)
     101             :     {
     102           0 :         Database::element_vector_t elements((*pt)->find_elements(element_name));
     103           0 :         for(auto et(elements.begin()); et != elements.end(); ++et)
     104             :         {
     105           0 :             if(!type
     106           0 :             || (*et)->get_type() == type)
     107             :             {
     108           0 :                 return *et;
     109             :             }
     110             :         }
     111           0 :     }
     112             : 
     113           0 :     return Database::Element::pointer_t();
     114             : }
     115             : 
     116             : 
     117          18 : void add_element(String const& package_name, String const& element_name, Node::pointer_t element, char const *type)
     118             : {
     119          18 :     Database::Package::pointer_t p(g_db->add_package(package_name));
     120          36 :     Database::Element::pointer_t e(p->add_element(element_name));
     121          18 :     e->set_type(type);
     122          18 :     e->set_filename(element->get_position().get_filename());
     123          36 :     e->set_line(element->get_position().get_line());
     124          18 : }
     125             : 
     126             : 
     127             : }
     128             : // no name namespace
     129             : 
     130             : 
     131             : 
     132             : 
     133             : 
     134             : 
     135             : 
     136             : /** \brief Get the filename of a package.
     137             :  *
     138             :  */
     139           0 : String Compiler::get_package_filename(char const *package_info)
     140             : {
     141           0 :     for(int cnt(0); *package_info != '\0';)
     142             :     {
     143           0 :         ++package_info;
     144           0 :         if(package_info[-1] == ' ')
     145             :         {
     146           0 :             ++cnt;
     147           0 :             if(cnt >= 3)
     148             :             {
     149           0 :                 break;
     150             :             }
     151             :         }
     152             :     }
     153           0 :     if(*package_info != '"')
     154             :     {
     155           0 :         return "";
     156             :     }
     157           0 :     ++package_info;
     158           0 :     char const *name = package_info;
     159           0 :     while(*package_info != '"' && *package_info != '\0')
     160             :     {
     161           0 :         ++package_info;
     162             :     }
     163             : 
     164           0 :     String result;
     165           0 :     result.from_utf8(name, package_info - name);
     166             : 
     167           0 :     return result;
     168             : }
     169             : 
     170             : 
     171             : /** \brief Find a module, load it if necessary.
     172             :  *
     173             :  * If the module was already loaded, return a pointer to the existing
     174             :  * tree of nodes.
     175             :  *
     176             :  * If the module was not yet loaded, try to load it. If the file cannot
     177             :  * be found or the file cannot be compiled, a fatal error is emitted
     178             :  * and the process stops.
     179             :  *
     180             :  * \note
     181             :  * At this point this function either returns true because it found
     182             :  * the named module, or it throws exception_exit. So the
     183             :  * \p result parameter is always set on a normal return.
     184             :  *
     185             :  * \param[in] filename  The name of the module to be loaded
     186             :  * \param[in,out] result  The shared pointer to the resulting root node.
     187             :  *
     188             :  * \return true if the module was found.
     189             :  */
     190        9351 : bool Compiler::find_module(String const& filename, Node::pointer_t& result)
     191             : {
     192             :     // module already loaded?
     193        9351 :     module_map_t::const_iterator existing_module(f_modules.find(filename));
     194        9351 :     if(existing_module != f_modules.end())
     195             :     {
     196           1 :         result = existing_module->second;
     197           1 :         return true;
     198             :     }
     199             : 
     200             :     // we could not find this module, try to load it
     201        9350 :     Input::pointer_t in;
     202        9350 :     if(f_input_retriever)
     203             :     {
     204           0 :         in = f_input_retriever->retrieve(filename);
     205             :     }
     206        9350 :     if(!in)
     207             :     {
     208        9350 :         in.reset(new FileInput());
     209             :         // 'in' is just a 'class Input' so we need to cast
     210        9350 :         if(!static_cast<FileInput&>(*in).open(filename))
     211             :         {
     212           0 :             Message msg(message_level_t::MESSAGE_LEVEL_FATAL, err_code_t::AS_ERR_NOT_FOUND, in->get_position());
     213           0 :             msg << "cannot open module file \"" << filename << "\".";
     214           0 :             throw exception_exit(1, "cannot open module file");
     215             :         }
     216             :     }
     217             : 
     218             :     // Parse the file in result
     219       18700 :     Parser::pointer_t parser(new Parser(in, f_options));
     220        9350 :     result = parser->parse();
     221        9350 :     parser.reset();
     222             : 
     223             : #if 0
     224             : std::cerr << "+++++\n \"" << filename << "\" module:\n" << *result << "\n+++++\n";
     225             : #endif
     226             : 
     227        9350 :     if(!result)
     228             :     {
     229           0 :         Message msg(message_level_t::MESSAGE_LEVEL_FATAL, err_code_t::AS_ERR_CANNOT_COMPILE, in->get_position());
     230           0 :         msg << "could not compile module file \"" << filename << "\".";
     231           0 :         throw exception_exit(1, "could not compile module file");
     232             :     }
     233             : 
     234             :     // save the newly loaded module
     235        9350 :     f_modules[filename] = result;
     236             : 
     237       18700 :     return true;
     238             : }
     239             : 
     240             : 
     241             : 
     242             : /** \brief Load a module as specified by \p module and \p file.
     243             :  *
     244             :  * This function loads the specified module. The filename is defined
     245             :  * as the path found in the .rc file, followed by the module name,
     246             :  * followed by the file name:
     247             :  *
     248             :  * \code
     249             :  * <rc.path>/<module>/<file>
     250             :  * \endcode
     251             :  *
     252             :  * The function always returns a pointer. If the module cannot be
     253             :  * loaded, an error is generated and the compiler exists with a
     254             :  * fatal error.
     255             :  *
     256             :  * \param[in] module  The name of the module to be loaded.
     257             :  * \param[in] file  The name of the file to load from that module.
     258             :  *
     259             :  * \return The pointer to the module loaded.
     260             :  */
     261        9351 : Node::pointer_t Compiler::load_module(char const *module, char const *file)
     262             : {
     263             :     // create the path to the module
     264        9351 :     String path(g_rc.get_scripts());
     265        9351 :     path += "/";
     266        9351 :     path += module;
     267        9351 :     path += "/";
     268        9351 :     path += file;
     269             : 
     270        9351 :     Node::pointer_t result;
     271        9351 :     find_module(path, result);
     272        9351 :     return result;
     273             : }
     274             : 
     275             : 
     276             : 
     277             : 
     278          18 : void Compiler::find_packages_add_database_entry(String const& package_name, Node::pointer_t& element, char const *type)
     279             : {
     280             :     // here, we totally ignore internal, private
     281             :     // and false entries right away
     282          72 :     if(get_attribute(element, Node::attribute_t::NODE_ATTR_PRIVATE)
     283          36 :     || get_attribute(element, Node::attribute_t::NODE_ATTR_FALSE)
     284          90 :     || get_attribute(element, Node::attribute_t::NODE_ATTR_INTERNAL))
     285             :     {
     286          18 :         return;
     287             :     }
     288             : 
     289          18 :     add_element(package_name, element->get_string(), element, type);
     290             : }
     291             : 
     292             : 
     293             : 
     294             : // This function searches a list of directives for class, functions
     295             : // and variables which are defined in a package. Their names are
     296             : // then saved in the import database for fast search.
     297          11 : void Compiler::find_packages_save_package_elements(Node::pointer_t package, String const& package_name)
     298             : {
     299          11 :     size_t const max_children(package->get_children_size());
     300          30 :     for(size_t idx = 0; idx < max_children; ++idx)
     301             :     {
     302          19 :         Node::pointer_t child(package->get_child(idx));
     303          19 :         if(child->get_type() == Node::node_t::NODE_DIRECTIVE_LIST)
     304             :         {
     305           0 :             find_packages_save_package_elements(child, package_name); // recursive
     306             :         }
     307          19 :         else if(child->get_type() == Node::node_t::NODE_CLASS)
     308             :         {
     309             :             find_packages_add_database_entry(
     310             :                     package_name,
     311             :                     child,
     312             :                     "class"
     313          18 :                 );
     314             :         }
     315           1 :         else if(child->get_type() == Node::node_t::NODE_FUNCTION)
     316             :         {
     317             :             // we do not save prototypes, that is tested later
     318             :             const char *type;
     319           0 :             if(child->get_flag(Node::flag_t::NODE_FUNCTION_FLAG_GETTER))
     320             :             {
     321           0 :                 type = "getter";
     322             :             }
     323           0 :             else if(child->get_flag(Node::flag_t::NODE_FUNCTION_FLAG_SETTER))
     324             :             {
     325           0 :                 type = "setter";
     326             :             }
     327             :             else
     328             :             {
     329           0 :                 type = "function";
     330             :             }
     331             :             find_packages_add_database_entry(
     332             :                     package_name,
     333             :                     child,
     334             :                     type
     335           0 :                 );
     336             :         }
     337           1 :         else if(child->get_type() == Node::node_t::NODE_VAR)
     338             :         {
     339           0 :             size_t const vcnt(child->get_children_size());
     340           0 :             for(size_t v(0); v < vcnt; ++v)
     341             :             {
     342           0 :                 Node::pointer_t variable_node(child->get_child(v));
     343             :                 // we do not save the variable type,
     344             :                 // it would not help resolution
     345             :                 find_packages_add_database_entry(
     346             :                         package_name,
     347             :                         variable_node,
     348             :                         "variable"
     349           0 :                     );
     350           0 :             }
     351             :         }
     352           1 :         else if(child->get_type() == Node::node_t::NODE_PACKAGE)
     353             :         {
     354             :             // sub packages
     355           0 :             Node::pointer_t list(child->get_child(0));
     356           0 :             String name(package_name);
     357           0 :             name += ".";
     358           0 :             name += child->get_string();
     359           0 :             find_packages_save_package_elements(list, name); // recursive
     360             :         }
     361          19 :     }
     362          11 : }
     363             : 
     364             : 
     365             : // this function searches the tree for packages (it stops at classes,
     366             : // functions, and other such blocks)
     367          24 : void Compiler::find_packages_directive_list(Node::pointer_t list)
     368             : {
     369          24 :     size_t const max_children(list->get_children_size());
     370          48 :     for(size_t idx(0); idx < max_children; ++idx)
     371             :     {
     372          24 :         Node::pointer_t child(list->get_child(idx));
     373          24 :         if(child->get_type() == Node::node_t::NODE_DIRECTIVE_LIST)
     374             :         {
     375          12 :             find_packages_directive_list(child);
     376             :         }
     377          12 :         else if(child->get_type() == Node::node_t::NODE_PACKAGE)
     378             :         {
     379             :             // Found a package! Save all the functions
     380             :             // variables and classes in the database
     381             :             // if not there yet.
     382          11 :             Node::pointer_t directive_list_node(child->get_child(0));
     383          11 :             find_packages_save_package_elements(directive_list_node, child->get_string());
     384             :         }
     385          24 :     }
     386          24 : }
     387             : 
     388             : 
     389          12 : void Compiler::find_packages(Node::pointer_t program_node)
     390             : {
     391          12 :     if(program_node->get_type() != Node::node_t::NODE_PROGRAM)
     392             :     {
     393          12 :         return;
     394             :     }
     395             : 
     396          12 :     find_packages_directive_list(program_node);
     397             : }
     398             : 
     399             : 
     400           1 : void Compiler::load_internal_packages(char const *module)
     401             : {
     402             :     // TODO: create sub-class to handle the directory
     403             : 
     404           1 :     std::string path(g_rc.get_scripts().to_utf8());
     405           1 :     path += "/";
     406           1 :     path += module;
     407           1 :     DIR *dir(opendir(path.c_str()));
     408           1 :     if(dir == nullptr)
     409             :     {
     410             :         // could not read this directory
     411           0 :         Position pos;
     412           0 :         pos.set_filename(path);
     413           0 :         Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_INSTALLATION, pos);
     414           0 :         msg << "cannot read directory \"" << path << "\".\n";
     415           0 :         throw exception_exit(1, "cannot read directory");
     416             :     }
     417             : 
     418             :     for(;;)
     419             :     {
     420          15 :         struct dirent *ent(readdir(dir));
     421          15 :         if(!ent)
     422             :         {
     423             :             // no more files in directory
     424           1 :             break;
     425             :         }
     426          14 :         char const *s = ent->d_name;
     427          14 :         char const *e = nullptr;  // extension position
     428         135 :         while(*s != '\0')
     429             :         {
     430         107 :             if(*s == '.')
     431             :             {
     432          15 :                 e = s;
     433             :             }
     434         107 :             s++;
     435             :         }
     436             :         // only interested by .js files except
     437             :         // the as2js_init.js file
     438          14 :         if(e == nullptr || strcmp(e, ".js") != 0
     439          12 :         || strcmp(ent->d_name, "as2js_init.js") == 0)
     440             :         {
     441           2 :             continue;
     442             :         }
     443             :         // we got a file of interest
     444             :         // TODO: we want to keep this package in RAM since
     445             :         //       we already parsed it!
     446          12 :         Node::pointer_t p(load_module(module, ent->d_name));
     447             :         // now we can search the package in the actual code
     448          12 :         find_packages(p);
     449          12 :     }
     450             : 
     451             :     // avoid leaks
     452           2 :     closedir(dir);
     453           1 : }
     454             : 
     455             : 
     456           0 : void Compiler::import(Node::pointer_t& import_node)
     457             : {
     458             :     // If we have the IMPLEMENTS flag set, then we must make sure
     459             :     // that the corresponding package is compiled.
     460           0 :     if(!import_node->get_flag(Node::flag_t::NODE_IMPORT_FLAG_IMPLEMENTS))
     461             :     {
     462           0 :         return;
     463             :     }
     464             : 
     465             :     // find the package
     466           0 :     Node::pointer_t package;
     467             : 
     468             :     // search in this program
     469           0 :     package = find_package(f_program, import_node->get_string());
     470           0 :     if(!package)
     471             :     {
     472             :         // not in this program, search externals
     473           0 :         Node::pointer_t program_node;
     474           0 :         String any_name("*");
     475           0 :         if(find_external_package(import_node, any_name, program_node))
     476             :         {
     477             :             // got externals, search those now
     478           0 :             package = find_package(program_node, import_node->get_string());
     479             :         }
     480           0 :         if(!package)
     481             :         {
     482           0 :             Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_NOT_FOUND, import_node->get_position());
     483           0 :             msg << "cannot find package '" << import_node->get_string() << "'.";
     484           0 :             return;
     485           0 :         }
     486             :     }
     487             : 
     488             :     // make sure it is compiled (once)
     489           0 :     bool const was_referenced(package->get_flag(Node::flag_t::NODE_PACKAGE_FLAG_REFERENCED));
     490           0 :     package->set_flag(Node::flag_t::NODE_PACKAGE_FLAG_REFERENCED, true);
     491           0 :     if(was_referenced)
     492             :     {
     493           0 :         directive_list(package);
     494           0 :     }
     495             : }
     496             : 
     497             : 
     498             : 
     499             : 
     500             : 
     501             : 
     502           0 : Node::pointer_t Compiler::find_package(Node::pointer_t list, String const& name)
     503             : {
     504           0 :     NodeLock ln(list);
     505           0 :     size_t const max_children(list->get_children_size());
     506           0 :     for(size_t idx(0); idx < max_children; ++idx)
     507             :     {
     508           0 :         Node::pointer_t child(list->get_child(idx));
     509           0 :         if(child->get_type() == Node::node_t::NODE_DIRECTIVE_LIST)
     510             :         {
     511           0 :             Node::pointer_t package(find_package(child, name));  // recursive
     512           0 :             if(package)
     513             :             {
     514           0 :                 return package;
     515           0 :             }
     516             :         }
     517           0 :         else if(child->get_type() == Node::node_t::NODE_PACKAGE)
     518             :         {
     519           0 :             if(child->get_string() == name)
     520             :             {
     521             :                 // found it!
     522           0 :                 return child;
     523             :             }
     524             :         }
     525           0 :     }
     526             : 
     527             :     // not found
     528           0 :     return Node::pointer_t();
     529             : }
     530             : 
     531             : 
     532           0 : bool Compiler::find_external_package(Node::pointer_t import_node, String const& name, Node::pointer_t& program_node)
     533             : {
     534             :     // search a package which has an element named 'name'
     535             :     // and has a name which match the identifier specified in 'import'
     536           0 :     Database::Element::pointer_t e(find_element(import_node->get_string(), name, nullptr));
     537           0 :     if(!e)
     538             :     {
     539             :         // not found!
     540           0 :         return false;
     541             :     }
     542             : 
     543           0 :     String filename(e->get_filename());
     544             : 
     545             :     // found it, lets get a node for it
     546           0 :     find_module(filename, program_node);
     547             : 
     548             :     // at this time this will not happen because if the find_module()
     549             :     // function fails, it throws exception_exit(1, ...);
     550           0 :     if(!program_node)
     551             :     {
     552           0 :         return false;
     553             :     }
     554             : 
     555           0 :     return true;
     556             : }
     557             : 
     558             : 
     559           0 : bool Compiler::check_import(Node::pointer_t& import_node, Node::pointer_t& resolution, String const& name, Node::pointer_t params, int search_flags)
     560             : {
     561             : //fprintf(stderr, "CheckImport(... [%.*S] ..., %d)\n", name.GetLength(), name.Get(), search_flags);
     562             :     // search for a package within this program
     563             :     // (I'm not too sure, but according to the spec. you can very well
     564             :     // have a package within any script file)
     565           0 :     if(find_package_item(f_program, import_node, resolution, name, params, search_flags))
     566             :     {
     567           0 :         return true;
     568             :     }
     569             : 
     570             : //fprintf(stderr, "Search for an external package instead.\n");
     571           0 :     Node::pointer_t program_node;
     572           0 :     if(!find_external_package(import_node, name, program_node))
     573             :     {
     574           0 :         return false;
     575             :     }
     576             : 
     577           0 :     return find_package_item(program_node, import_node, resolution, name, params, search_flags | SEARCH_FLAG_PACKAGE_MUST_EXIST);
     578             : }
     579             : 
     580             : 
     581           0 : bool Compiler::find_package_item(Node::pointer_t program_node, Node::pointer_t import_node, Node::pointer_t& resolution, String const& name, Node::pointer_t params, int const search_flags)
     582             : {
     583           0 :     Node::pointer_t package_node(find_package(program_node, import_node->get_string()));
     584             : 
     585           0 :     if(!package_node)
     586             :     {
     587           0 :         if((search_flags & SEARCH_FLAG_PACKAGE_MUST_EXIST) != 0)
     588             :         {
     589             :             // this is a bad error! we should always find the
     590             :             // packages in this case (i.e. when looking using the
     591             :             // database.)
     592           0 :             Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_INTERNAL_ERROR, import_node->get_position());
     593           0 :             msg << "cannot find package '" << import_node->get_string() << "' in any of the previously registered packages.";
     594           0 :             throw exception_exit(1, "cannot find package");
     595             :         }
     596           0 :         return false;
     597             :     }
     598             : 
     599           0 :     if(package_node->get_children_size() == 0)
     600             :     {
     601           0 :         return false;
     602             :     }
     603             : 
     604             :     // setup labels (only the first time around)
     605           0 :     if(!package_node->get_flag(Node::flag_t::NODE_PACKAGE_FLAG_FOUND_LABELS))
     606             :     {
     607           0 :         package_node->set_flag(Node::flag_t::NODE_PACKAGE_FLAG_FOUND_LABELS, true);
     608           0 :         Node::pointer_t child(package_node->get_child(0));
     609           0 :         find_labels(package_node, child);
     610             :     }
     611             : 
     612             :     // search the name of the class/function/variable we're
     613             :     // searching for in this package:
     614             : 
     615             :     // TODO: Hmmm... could we have the actual node instead?
     616           0 :     Node::pointer_t id(package_node->create_replacement(Node::node_t::NODE_IDENTIFIER));
     617           0 :     id->set_string(name);
     618             : 
     619           0 :     int funcs = 0;
     620           0 :     if(!find_field(package_node, id, funcs, resolution, params, search_flags))
     621             :     {
     622           0 :         return false;
     623             :     }
     624             : 
     625             :     // TODO: Can we have an empty resolution here?!
     626           0 :     if(resolution)
     627             :     {
     628           0 :         if(get_attribute(resolution, Node::attribute_t::NODE_ATTR_PRIVATE))
     629             :         {
     630             :             // it is private, we cannot use this item
     631             :             // from outside whether it is in the
     632             :             // package or a sub-class
     633           0 :             return false;
     634             :         }
     635             : 
     636           0 :         if(get_attribute(resolution, Node::attribute_t::NODE_ATTR_INTERNAL))
     637             :         {
     638             :             // it is internal we can only use it from
     639             :             // another package
     640           0 :             Node::pointer_t parent(import_node);
     641             :             for(;;)
     642             :             {
     643           0 :                 parent = parent->get_parent();
     644           0 :                 if(!parent)
     645             :                 {
     646           0 :                     return false;
     647             :                 }
     648           0 :                 if(parent->get_type() == Node::node_t::NODE_PACKAGE)
     649             :                 {
     650             :                     // found the package mark
     651           0 :                     break;
     652             :                 }
     653           0 :                 if(parent->get_type() == Node::node_t::NODE_ROOT
     654           0 :                 || parent->get_type() == Node::node_t::NODE_PROGRAM)
     655             :                 {
     656           0 :                     return false;
     657             :                 }
     658           0 :             }
     659             :         }
     660             :     }
     661             : 
     662             :     // make sure it is compiled (once)
     663           0 :     bool was_referenced(package_node->get_flag(Node::flag_t::NODE_PACKAGE_FLAG_REFERENCED));
     664           0 :     package_node->set_flag(Node::flag_t::NODE_PACKAGE_FLAG_REFERENCED, true);
     665           0 :     if(was_referenced)
     666             :     {
     667           0 :         directive_list(package_node);
     668             :     }
     669             : 
     670           0 :     return true;
     671             : }
     672             : 
     673             : 
     674        9339 : void Compiler::internal_imports()
     675             : {
     676        9339 :     if(!g_global_import)
     677             :     {
     678             :         // read the resource file
     679        9339 :         g_rc.init_rc(static_cast<bool>(f_input_retriever));
     680             : 
     681             :         // TBD: at this point we only have native scripts
     682             :         //      we need browser scripts, for sure...
     683             :         //      and possibly some definitions of extensions such as jQuery
     684             :         //      however, at this point we do not have a global or system
     685             :         //      set of modules
     686             :         //g_global_import = load_module("global", "as_init.js");
     687             :         //g_system_import = load_module("system", "as_init.js");
     688        9339 :         g_native_import = load_module("native", "as_init.js");
     689             :     }
     690             : 
     691        9339 :     if(!g_db)
     692             :     {
     693           1 :         g_db.reset(new Database);
     694             :     }
     695        9339 :     if(!g_db->load(g_rc.get_db()))
     696             :     {
     697           0 :         Message msg(message_level_t::MESSAGE_LEVEL_FATAL, err_code_t::AS_ERR_UNEXPECTED_DATABASE);
     698           0 :         msg << "Failed reading the compiler database. You may need to delete it and try again or fix the resource file to point to the right file.";
     699        9339 :         return;
     700             :     }
     701             : 
     702        9339 :     if(!g_db_loaded)
     703             :     {
     704           1 :         g_db_loaded = true;
     705             : 
     706             :         // global defines the basic JavaScript classes such
     707             :         // as Object and String.
     708             :         //load_internal_packages("global");
     709             : 
     710             :         // the system defines Browser classes such as XMLNode
     711             :         //load_internal_packages("system");
     712             : 
     713             :         // the ECMAScript low level definitions
     714           1 :         load_internal_packages("native");
     715             : 
     716             :         // this saves the internal packages info for fast query
     717             :         // on next invocations
     718           1 :         g_db->save();
     719             :     }
     720             : }
     721             : 
     722             : 
     723           0 : bool Compiler::check_name(Node::pointer_t list, int idx, Node::pointer_t& resolution, Node::pointer_t id, Node::pointer_t params, int const search_flags)
     724             : {
     725           0 :     Node::pointer_t child(list->get_child(idx));
     726             : 
     727             :     // turned off?
     728             :     //if(get_attribute(child, Node::attribute_t::NODE_ATTR_FALSE))
     729             :     //{
     730             :     //    return false;
     731             :     //}
     732             : 
     733           0 :     bool result = false;
     734           0 :     switch(child->get_type())
     735             :     {
     736             :     case Node::node_t::NODE_VAR:    // a VAR is composed of VARIABLEs
     737             :         {
     738           0 :             NodeLock ln(child);
     739           0 :             size_t const max_children(child->get_children_size());
     740           0 :             for(size_t j(0); j < max_children; ++j)
     741             :             {
     742           0 :                 Node::pointer_t variable_node(child->get_child(j));
     743           0 :                 if(variable_node->get_string() == id->get_string())
     744             :                 {
     745             :                     // that's a variable!
     746             :                     // make sure it was parsed
     747           0 :                     if((search_flags & SEARCH_FLAG_NO_PARSING) == 0)
     748             :                     {
     749           0 :                         variable(variable_node, false);
     750             :                     }
     751           0 :                     if(params)
     752             :                     {
     753             :                         // check whether we are in a call
     754             :                         // because if we are the resolution
     755             :                         // is the "()" operator instead
     756             :                     }
     757           0 :                     resolution = variable_node;
     758           0 :                     result = true;
     759           0 :                     break;
     760             :                 }
     761           0 :             }
     762             :         }
     763           0 :         break;
     764             : 
     765             :     case Node::node_t::NODE_PARAM:
     766           0 :         if(child->get_string() == id->get_string())
     767             :         {
     768           0 :             resolution = child;
     769           0 :             resolution->set_flag(Node::flag_t::NODE_PARAM_FLAG_REFERENCED, true);
     770           0 :             return true;
     771             :         }
     772           0 :         break;
     773             : 
     774             :     case Node::node_t::NODE_FUNCTION:
     775           0 :         result = check_function(child, resolution, id->get_string(), params, search_flags);
     776           0 :         break;
     777             : 
     778             :     case Node::node_t::NODE_CLASS:
     779             :     case Node::node_t::NODE_INTERFACE:
     780           0 :         if(child->get_string() == id->get_string())
     781             :         {
     782             :             // That is a class name! (good for a typedef, etc.)
     783           0 :             resolution = child;
     784           0 :             result = true;
     785             :         }
     786           0 :         break;
     787             : 
     788             :     case Node::node_t::NODE_ENUM:
     789             :     {
     790             :         // first we check whether the name of the enum is what
     791             :         // is being referenced (i.e. the type)
     792           0 :         if(child->get_string() == id->get_string())
     793             :         {
     794           0 :             resolution = list;
     795           0 :             resolution->set_flag(Node::flag_t::NODE_VARIABLE_FLAG_INUSE, true);
     796           0 :             return true;
     797             :         }
     798             : 
     799             :         // inside an enum we have references to other
     800             :         // identifiers of that enum and these need to be
     801             :         // checked here
     802           0 :         size_t const max(child->get_children_size());
     803           0 :         for(size_t j(0); j < max; ++j)
     804             :         {
     805           0 :             Node::pointer_t entry(child->get_child(j));
     806           0 :             if(entry->get_string() == id->get_string())
     807             :             {
     808             :                 // this can't be a function, right?
     809           0 :                 resolution = entry;
     810           0 :                 resolution->set_flag(Node::flag_t::NODE_VARIABLE_FLAG_INUSE, true);
     811           0 :                 return true;
     812             :             }
     813           0 :         }
     814             :     }
     815           0 :         break;
     816             : 
     817             :     case Node::node_t::NODE_PACKAGE:
     818           0 :         if(child->get_string() == id->get_string())
     819             :         {
     820             :             // That is a package... we have to see packages
     821             :             // like classes, to search for more, you need
     822             :             // to search inside this package and none other.
     823           0 :             resolution = child;
     824           0 :             return true;
     825             :         }
     826             : #if 0
     827             :         // TODO: auto-import? this works, but I do not think we
     828             :         //       want an automatic import of even internal packages?
     829             :         //       do we?
     830             :         //
     831             :         //       At this point I would say that we do for the
     832             :         //       internal packages only. That being said, the
     833             :         //       Google closure compiler does that for all
     834             :         //       browser related declarations.
     835             :         //
     836             :         // if it is not the package itself, it could be an
     837             :         // element inside the package
     838             :         {
     839             :             int funcs(0);
     840             :             if(!find_field(child, id, funcs, resolution, params, search_flags))
     841             :             {
     842             :                 break;
     843             :             }
     844             :         }
     845             :         result = true;
     846             : //std::cerr << "Found inside package! [" << id->get_string() << "]\n";
     847             :         if(!child->get_flag(Node::flag_t::NODE_PACKAGE_FLAG_REFERENCED))
     848             :         {
     849             : //std::cerr << "Compile package now!\n";
     850             :             directive_list(child);
     851             :             child->set_flag(Node::flag_t::NODE_PACKAGE_FLAG_REFERENCED);
     852             :         }
     853             : #endif
     854           0 :         break;
     855             : 
     856             :     case Node::node_t::NODE_IMPORT:
     857           0 :         return check_import(child, resolution, id->get_string(), params, search_flags);
     858             : 
     859             :     default:
     860             :         // ignore anything else for now
     861           0 :         break;
     862             : 
     863             :     }
     864             : 
     865           0 :     if(!result)
     866             :     {
     867           0 :         return false;
     868             :     }
     869             : 
     870           0 :     if(!resolution)
     871             :     {
     872             :         // this is kind of bad since we cannot test for
     873             :         // the scope...
     874           0 :         return true;
     875             :     }
     876             : 
     877           0 :     if(get_attribute(resolution, Node::attribute_t::NODE_ATTR_PRIVATE))
     878             :     {
     879             :         // Note that an interface and a package
     880             :         // can also have private members
     881           0 :         Node::pointer_t the_resolution_class(class_of_member(resolution));
     882           0 :         if(!the_resolution_class)
     883             :         {
     884           0 :             f_err_flags |= SEARCH_ERROR_PRIVATE;
     885           0 :             resolution.reset();
     886           0 :             return false;
     887             :         }
     888           0 :         if(the_resolution_class->get_type() == Node::node_t::NODE_PACKAGE)
     889             :         {
     890           0 :             f_err_flags |= SEARCH_ERROR_PRIVATE_PACKAGE;
     891           0 :             resolution.reset();
     892           0 :             return false;
     893             :         }
     894           0 :         if(the_resolution_class->get_type() != Node::node_t::NODE_CLASS
     895           0 :         && the_resolution_class->get_type() != Node::node_t::NODE_INTERFACE)
     896             :         {
     897           0 :             f_err_flags |= SEARCH_ERROR_WRONG_PRIVATE;
     898           0 :             resolution.reset();
     899           0 :             return false;
     900             :         }
     901           0 :         Node::pointer_t the_id_class(class_of_member(id));
     902           0 :         if(!the_id_class)
     903             :         {
     904           0 :             f_err_flags |= SEARCH_ERROR_PRIVATE;
     905           0 :             resolution.reset();
     906           0 :             return false;
     907             :         }
     908           0 :         if(the_id_class != the_resolution_class)
     909             :         {
     910           0 :             f_err_flags |= SEARCH_ERROR_PRIVATE;
     911           0 :             resolution.reset();
     912           0 :             return false;
     913           0 :         }
     914             :     }
     915             : 
     916           0 :     if(get_attribute(resolution, Node::attribute_t::NODE_ATTR_PROTECTED))
     917             :     {
     918             :         // Note that an interface can also have protected members
     919           0 :         Node::pointer_t the_super_class;
     920           0 :         if(!are_objects_derived_from_one_another(id, resolution, the_super_class))
     921             :         {
     922           0 :             if(the_super_class
     923           0 :             && the_super_class->get_type() != Node::node_t::NODE_CLASS
     924           0 :             && the_super_class->get_type() != Node::node_t::NODE_INTERFACE)
     925             :             {
     926           0 :                 f_err_flags |= SEARCH_ERROR_WRONG_PROTECTED;
     927             :             }
     928             :             else
     929             :             {
     930           0 :                 f_err_flags |= SEARCH_ERROR_PROTECTED;
     931             :             }
     932           0 :             resolution.reset();
     933           0 :             return false;
     934           0 :         }
     935             :     }
     936             : 
     937           0 :     if(child->get_type() == Node::node_t::NODE_FUNCTION && params)
     938             :     {
     939           0 :         if(check_function_with_params(child, params) < 0)
     940             :         {
     941           0 :             return false;
     942             :         }
     943             :     }
     944             : 
     945           0 :     return true;
     946             : }
     947             : 
     948             : 
     949           0 : bool Compiler::resolve_name(Node::pointer_t list, Node::pointer_t id, Node::pointer_t& resolution, Node::pointer_t params, int const search_flags)
     950             : {
     951           0 :     RestoreFlags restore_flags(this);
     952             : 
     953             :     // just in case the caller is reusing the same node
     954           0 :     resolution.reset();
     955             : 
     956             :     // in some cases we may want to resolve a name specified in a string
     957             :     // (i.e. test["me"])
     958           0 :     if(id->get_type() != Node::node_t::NODE_IDENTIFIER
     959           0 :     && id->get_type() != Node::node_t::NODE_VIDENTIFIER
     960           0 :     && id->get_type() != Node::node_t::NODE_STRING)
     961             :     {
     962           0 :         throw exception_internal_error("Compiler::resolve_name() was called with an 'identifier node' which is not a NODE_[V]IDENTIFIER or NODE_STRING");
     963             :     }
     964             : 
     965             :     //
     966             :     // Search for the parent list of directives; in that list, search
     967             :     // for the identifier; if not found, try again with the parent
     968             :     // of that list of directives (unless we find an import in which
     969             :     // case we first try the import)
     970             :     //
     971             :     // Note that the currently effective with()'s and use namespace's
     972             :     // are defined in the f_scope variable. This is used here to know
     973             :     // whether the name matches an entry or not.
     974             :     //
     975             : 
     976             :     // a list of functions whenever the name resolves to a function
     977           0 :     int funcs(0);
     978             : 
     979           0 :     Node::pointer_t parent(list->get_parent());
     980           0 :     if(parent->get_type() == Node::node_t::NODE_WITH)
     981             :     {
     982             :         // we are currently defining the WITH object, skip the
     983             :         // WITH itself!
     984           0 :         list = parent;
     985             :     }
     986           0 :     int module(0);        // 0 is user module being compiled
     987             :     for(;;)
     988             :     {
     989             :         // we will start searching at this offset; first backward
     990             :         // and then forward
     991           0 :         size_t offset(0);
     992             : 
     993             :         // This function should never be called from program()
     994             :         // also, 'id' cannot be a directive list (it has to be an
     995             :         // identifier, a member or a string!)
     996             :         //
     997             :         // For these reasons, we can start the following loop with
     998             :         // a get_parent() in all cases.
     999             :         //
    1000           0 :         if(module == 0)
    1001             :         {
    1002             :             // when we were inside the function parameter
    1003             :             // list we don't want to check out the function
    1004             :             // otherwise we could have a forward search of
    1005             :             // the parameters which we disallow (only backward
    1006             :             // search is allowed in that list)
    1007           0 :             if(list->get_type() == Node::node_t::NODE_PARAMETERS)
    1008             :             {
    1009             : //fprintf(stderr, "Skipping parameters?!\n");
    1010           0 :                 list = list->get_parent();
    1011             :             }
    1012             : 
    1013           0 :             bool more(true);
    1014           0 :             for(; list && more;)
    1015             :             {
    1016           0 :                 offset = list->get_offset();
    1017           0 :                 list = list->get_parent();
    1018             :                 // TBD: should we verify that list is not a null pointer?
    1019           0 :                 switch(list->get_type())
    1020             :                 {
    1021             :                 case Node::node_t::NODE_ROOT:
    1022           0 :                     throw exception_internal_error("Compiler::resolve_name() found the NODE_ROOT while searching for a parent.");
    1023             : 
    1024             :                 case Node::node_t::NODE_EXTENDS:
    1025             :                 case Node::node_t::NODE_IMPLEMENTS:
    1026           0 :                     list = list->get_parent();
    1027             :                     // TBD: this is used to skip one node, but should we
    1028             :                     //      check for the null pointer?
    1029           0 :                     break;
    1030             : 
    1031             :                 case Node::node_t::NODE_DIRECTIVE_LIST:
    1032             :                 case Node::node_t::NODE_FOR:
    1033             :                 case Node::node_t::NODE_WITH:
    1034             :                 //case Node::node_t::NODE_PACKAGE: -- not necessary, the first item is a NODE_DIRECTIVE_LIST
    1035             :                 case Node::node_t::NODE_PROGRAM:
    1036             :                 case Node::node_t::NODE_FUNCTION:
    1037             :                 case Node::node_t::NODE_PARAMETERS:
    1038             :                 case Node::node_t::NODE_ENUM:
    1039             :                 case Node::node_t::NODE_CATCH:
    1040             :                 case Node::node_t::NODE_CLASS:
    1041             :                 case Node::node_t::NODE_INTERFACE:
    1042           0 :                     more = false;
    1043           0 :                     break;
    1044             : 
    1045             :                 default:
    1046           0 :                     break;
    1047             : 
    1048             :                 }
    1049             :             }
    1050             :         }
    1051             : 
    1052           0 :         if(list->get_type() == Node::node_t::NODE_PROGRAM
    1053           0 :         || module != 0)
    1054             :         {
    1055             :             // not resolved
    1056           0 :             switch(module)
    1057             :             {
    1058             :             case 0:
    1059           0 :                 module = 1;
    1060           0 :                 if(g_global_import
    1061           0 :                 && g_global_import->get_children_size() > 0)
    1062             :                 {
    1063           0 :                     list = g_global_import->get_child(0);
    1064           0 :                     break;
    1065             :                 }
    1066             :                 /*FALLTHROUGH*/
    1067             :             case 1:
    1068           0 :                 module = 2;
    1069           0 :                 if(g_system_import
    1070           0 :                 && g_system_import->get_children_size() > 0)
    1071             :                 {
    1072           0 :                     list = g_system_import->get_child(0);
    1073           0 :                     break;
    1074             :                 }
    1075             :                 /*FALLTHROUGH*/
    1076             :             case 2:
    1077           0 :                 module = 3;
    1078           0 :                 if(g_native_import
    1079           0 :                 && g_native_import->get_children_size() > 0)
    1080             :                 {
    1081           0 :                     list = g_native_import->get_child(0);
    1082           0 :                     break;
    1083             :                 }
    1084             :                 /*FALLTHROUGH*/
    1085             :             case 3:
    1086             :                 // no more default list of directives...
    1087           0 :                 module = 4;
    1088           0 :                 break;
    1089             : 
    1090             :             }
    1091             :             // TODO: here somehow we change the list parameter, but
    1092             :             //       not the offset; I am now thinking it should be
    1093             :             //       reset to zero:
    1094             :             //offset = 0;
    1095             :         }
    1096           0 :         if(module == 4)
    1097             :         {
    1098             :             // didn't find a variable and such, but
    1099             :             // we may have found a function (see below
    1100             :             // after the forever loop breaking here)
    1101           0 :             break;
    1102             :         }
    1103             : 
    1104           0 :         NodeLock ln(list);
    1105           0 :         size_t const max_children(list->get_children_size());
    1106           0 :         switch(list->get_type())
    1107             :         {
    1108             :         case Node::node_t::NODE_DIRECTIVE_LIST:
    1109             :         {
    1110             :             // okay! we've got a list of directives
    1111             :             // backward loop up first since in 99% of cases that
    1112             :             // will be enough...
    1113           0 :             if(offset >= max_children)
    1114             :             {
    1115           0 :                 throw exception_internal_error("somehow an offset is out of range");
    1116             :             }
    1117           0 :             size_t idx(offset);
    1118           0 :             while(idx > 0)
    1119             :             {
    1120           0 :                 idx--;
    1121           0 :                 if(check_name(list, idx, resolution, id, params, search_flags))
    1122             :                 {
    1123           0 :                     if(funcs_name(funcs, resolution))
    1124             :                     {
    1125           0 :                         return true;
    1126             :                     }
    1127             :                 }
    1128             :             }
    1129             : 
    1130             :             // forward look up is also available in ECMAScript...
    1131             :             // (necessary in case function A calls function B
    1132             :             // and function B calls function A).
    1133           0 :             for(idx = offset; idx < max_children; ++idx)
    1134             :             {
    1135           0 :                 if(check_name(list, idx, resolution, id, params, search_flags))
    1136             :                 {
    1137             :                     // TODO: if it is a variable it needs
    1138             :                     //     to be a constant...
    1139           0 :                     if(funcs_name(funcs, resolution))
    1140             :                     {
    1141             : #if 0
    1142             : fprintf(stderr, "DEBUG: in a DIRECTIVE_LIST resolution is = ");
    1143             : resolution.DisplayPtr(stderr);
    1144             : fprintf(stderr, "\n");
    1145             : #endif
    1146           0 :                         return true;
    1147             :                     }
    1148             :                 }
    1149             :             }
    1150             :         }
    1151           0 :             break;
    1152             : 
    1153             :         case Node::node_t::NODE_FOR:
    1154             :         {
    1155             :             // the first member of a for can include variable
    1156             :             // definitions
    1157             : 
    1158             : #if 0
    1159             : NodePtr& var = list.GetChild(0);
    1160             : Data& d = var.GetData();
    1161             : fprintf(stderr, "FOR vars in ");
    1162             : var.DisplayPtr(stderr);
    1163             : fprintf(stderr, " [Type = %d]\n", d.f_type);
    1164             : #endif
    1165             : 
    1166           0 :             if(max_children > 0 && check_name(list, 0, resolution, id, params, search_flags))
    1167             :             {
    1168           0 :                 if(funcs_name(funcs, resolution))
    1169             :                 {
    1170           0 :                     return true;
    1171             :                 }
    1172             :             }
    1173             :         }
    1174           0 :             break;
    1175             : 
    1176             : #if 0
    1177             :         case Node::node_t::NODE_PACKAGE:
    1178             :             // From inside a package, we have an implicit
    1179             :             //    IMPORT <package name>;
    1180             :             //
    1181             :             // This is required to enable a multiple files
    1182             :             // package definition which ease the development
    1183             :             // of really large packages.
    1184             :             if(check_import(list, resolution, id->get_string(), params, search_flags))
    1185             :             {
    1186             :                 return true;
    1187             :             }
    1188             :             break;
    1189             : #endif
    1190             : 
    1191             :         case Node::node_t::NODE_WITH:
    1192             :         {
    1193           0 :             if(max_children != 2)
    1194             :             {
    1195           0 :                 break;
    1196             :             }
    1197             :             // ha! we found a valid WITH instruction, let's
    1198             :             // search for this name in the corresponding
    1199             :             // object type instead (i.e. a field of the object)
    1200           0 :             Node::pointer_t type(list->get_child(0));
    1201           0 :             if(type)
    1202             :             {
    1203           0 :                 Node::pointer_t link(type->get_link(Node::link_t::LINK_INSTANCE));
    1204           0 :                 if(link)
    1205             :                 {
    1206           0 :                     if(resolve_field(link, id, resolution, params, search_flags))
    1207             :                     {
    1208             :                         // Mark this identifier as a
    1209             :                         // reference to a WITH object
    1210           0 :                         id->set_flag(Node::flag_t::NODE_IDENTIFIER_FLAG_WITH, true);
    1211             : 
    1212             :                         // TODO: we certainly want to compare
    1213             :                         //       all the field functions and the
    1214             :                         //       other functions... at this time,
    1215             :                         //       err if we get a field function
    1216             :                         //       and others are ignored!
    1217           0 :                         if(funcs != 0)
    1218             :                         {
    1219           0 :                             throw exception_internal_error("at this time we do not support functions here (under a with)");
    1220             :                         }
    1221           0 :                         return true;
    1222             :                     }
    1223           0 :                 }
    1224           0 :             }
    1225             :         }
    1226           0 :             break;
    1227             : 
    1228             :         case Node::node_t::NODE_FUNCTION:
    1229             :         {
    1230             :             // search the list of parameters for a corresponding name
    1231           0 :             for(size_t idx(0); idx < max_children; ++idx)
    1232             :             {
    1233           0 :                 Node::pointer_t parameters_node(list->get_child(idx));
    1234           0 :                 if(parameters_node->get_type() == Node::node_t::NODE_PARAMETERS)
    1235             :                 {
    1236           0 :                     NodeLock parameters_ln(parameters_node);
    1237           0 :                     size_t const cnt(parameters_node->get_children_size());
    1238           0 :                     for(size_t j(0); j < cnt; ++j)
    1239             :                     {
    1240           0 :                         if(check_name(parameters_node, j, resolution, id, params, search_flags))
    1241             :                         {
    1242           0 :                             if(funcs_name(funcs, resolution))
    1243             :                             {
    1244             : #if 0
    1245             : fprintf(stderr, "DEBUG: in a FUNCTION resolution is = ");
    1246             : resolution.DisplayPtr(stderr);
    1247             : fprintf(stderr, "\n");
    1248             : #endif
    1249           0 :                                 return true;
    1250             :                             }
    1251             :                         }
    1252             :                     }
    1253           0 :                     break;
    1254             :                 }
    1255           0 :             }
    1256             :         }
    1257           0 :             break;
    1258             : 
    1259             :         case Node::node_t::NODE_PARAMETERS:
    1260             :         {
    1261             :             // Wow! I cannot believe I am implementing this...
    1262             :             // So we will be able to reference the previous
    1263             :             // parameters in the default value of the following
    1264             :             // parameters; and that makes sense, it is available
    1265             :             // in C++ templates, right?!
    1266             :             // And guess what, that is just this little loop.
    1267             :             // That is it. Big deal, hey?! 8-)
    1268           0 :             if(offset >= max_children)
    1269             :             {
    1270           0 :                 throw exception_internal_error("somehow an offset is out of range");
    1271             :             }
    1272           0 :             size_t idx(offset);
    1273           0 :             while(idx > 0)
    1274             :             {
    1275           0 :                 idx--;
    1276           0 :                 if(check_name(list, idx, resolution, id, params, search_flags))
    1277             :                 {
    1278           0 :                     if(funcs_name(funcs, resolution))
    1279             :                     {
    1280           0 :                         return true;
    1281             :                     }
    1282             :                 }
    1283             :             }
    1284             :         }
    1285           0 :             break;
    1286             : 
    1287             :         case Node::node_t::NODE_CATCH:
    1288             :         {
    1289             :             // a catch can have a parameter of its own
    1290           0 :             Node::pointer_t parameters_node(list->get_child(0));
    1291           0 :             if(parameters_node->get_children_size() > 0)
    1292             :             {
    1293           0 :                 if(check_name(parameters_node, 0, resolution, id, params, search_flags))
    1294             :                 {
    1295           0 :                     if(funcs_name(funcs, resolution))
    1296             :                     {
    1297           0 :                         return true;
    1298             :                     }
    1299             :                 }
    1300           0 :             }
    1301             :         }
    1302           0 :             break;
    1303             : 
    1304             :         case Node::node_t::NODE_ENUM:
    1305             :             // first we check whether the name of the enum is what
    1306             :             // is being referenced (i.e. the type)
    1307           0 :             if(id->get_string() == list->get_string())
    1308             :             {
    1309           0 :                 resolution = list;
    1310           0 :                 resolution->set_flag(Node::flag_t::NODE_VARIABLE_FLAG_INUSE, true);
    1311           0 :                 return true;
    1312             :             }
    1313             : 
    1314             :             // inside an enum we have references to other
    1315             :             // identifiers of that enum and these need to be
    1316             :             // checked here
    1317             :             //
    1318             :             // And note that these are not in any way affected
    1319             :             // by scope attributes
    1320           0 :             for(size_t idx(0); idx < max_children; ++idx)
    1321             :             {
    1322           0 :                 Node::pointer_t entry(list->get_child(idx));
    1323           0 :                 if(id->get_string() == entry->get_string())
    1324             :                 {
    1325             :                     // this can't be a function, right?
    1326           0 :                     resolution = entry;
    1327           0 :                     if(funcs_name(funcs, resolution))
    1328             :                     {
    1329           0 :                         resolution->set_flag(Node::flag_t::NODE_VARIABLE_FLAG_INUSE, true);
    1330           0 :                         return true;
    1331             :                     }
    1332             :                 }
    1333           0 :             }
    1334           0 :             break;
    1335             : 
    1336             :         case Node::node_t::NODE_CLASS:
    1337             :         case Node::node_t::NODE_INTERFACE:
    1338             :             // We need to search the extends and implements
    1339           0 :             if(find_in_extends(list, id, funcs, resolution, params, search_flags))
    1340             :             {
    1341           0 :                 if(funcs_name(funcs, resolution))
    1342             :                 {
    1343           0 :                     return true;
    1344             :                 }
    1345             :             }
    1346           0 :             break;
    1347             : 
    1348             :         default:
    1349             :             // this could happen if our tree was to change and we do not
    1350             :             // properly update this function
    1351           0 :             throw exception_internal_error("unhandled type in Compiler::resolve_name()");
    1352             : 
    1353             :         }
    1354           0 :     }
    1355             : 
    1356           0 :     resolution.reset();
    1357             : 
    1358           0 :     if(funcs != 0)
    1359             :     {
    1360           0 :         if(select_best_func(params, resolution))
    1361             :         {
    1362           0 :             return true;
    1363             :         }
    1364             :     }
    1365             : 
    1366           0 :     print_search_errors(id);
    1367             : 
    1368           0 :     return false;
    1369             : }
    1370             : 
    1371             : 
    1372          63 : }
    1373             : // namespace as2js
    1374             : 
    1375             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.10