ASTimpl.cxx

Go to the documentation of this file.
00001 /**************************************************************************
00002  *
00003  * Copyright (C) 2010, Jonathan S. Shapiro
00004  * Portions Copyright (C) 2008, Johns Hopkins University.
00005  * All rights reserved.
00006  *
00007  * Redistribution and use in source and binary forms, with or
00008  * without modification, are permitted provided that the following
00009  * conditions are met:
00010  *
00011  *   - Redistributions of source code must contain the above
00012  *     copyright notice, this list of conditions, and the following
00013  *     disclaimer.
00014  *
00015  *   - Redistributions in binary form must reproduce the above
00016  *     copyright notice, this list of conditions, and the following
00017  *     disclaimer in the documentation and/or other materials
00018  *     provided with the distribution.
00019  *
00020  *   - Neither the names of the copyright holders nor the names of any
00021  *     of any contributors may be used to endorse or promote products
00022  *     derived from this software without specific prior written
00023  *     permission.
00024  *
00025  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00026  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00027  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00028  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
00029  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00030  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00031  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00032  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00033  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00034  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00035  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036  *
00037  **************************************************************************/
00038 
00039 #include <assert.h>
00040 #include <stdint.h>
00041 #include <stdlib.h>
00042 #include <dirent.h>
00043 #include <fstream>
00044 #include <iostream>
00045 #include <string>
00046 #include <sstream>
00047 
00048 #include "UocInfo.hxx"
00049 #include "AST.hxx"
00050 #include "Type.hxx"
00051 #include "TypeInfer.hxx"
00052 #include "inter-pass.hxx"
00053 #include "FQName.hxx"
00054 #include "inter-pass.hxx"
00055 
00056 using namespace boost;
00057 using namespace sherpa;
00058 
00059 shared_ptr<AST>
00060 AST::makeBoolLit(const sherpa::LToken &tok)
00061 {
00062   shared_ptr<AST> ast = AST::make(at_boolLiteral, tok);
00063   if (tok.str == "#t" || tok.str == "true")
00064     ast->litValue.b = true;
00065   else
00066     ast->litValue.b = false;
00067   ast->litValue.litType = lt_bool;
00068 
00069   return ast;
00070 }
00071 
00072 shared_ptr<AST>
00073 AST::makeCharLit(const sherpa::LToken &tok)
00074 {
00075   // FIX: (shap) This needs to convert to ordinal representation
00076   // and use a more appropriate element type.
00077 
00078   shared_ptr<AST> ast = AST::make(at_charLiteral, tok);
00079   //  mpz_init_set_str(ast->litValue.i, tok.is.c_str(), 0);
00080 
00081   ast->litValue.c = LitValue::DecodeCharacter(tok.str);
00082   ast->litValue.litType = lt_char;
00083 
00084   return ast;
00085 }
00086 
00089 shared_ptr<AST>
00090 AST::makeIntLit(const sherpa::LToken &tok)
00091 {
00092   shared_ptr<AST> ast = AST::make(at_intLiteral, tok);
00093   std::string num = "";
00094   bool negative = false;
00095 
00096   /* Forgetting the sign, base information in the lexer, and
00097      rediscovering it here is a little stupid. */
00098 
00099   if (tok.str[0] == '-') {
00100     num = tok.str.substr(1, tok.str.size());
00101     negative = true;
00102   }
00103   else {
00104     num = tok.str.substr(0, tok.str.size());
00105   }
00106 
00107   ast->litBase = 10;
00108 
00109   if (num.size() > 1) {
00110     if (num[0] == '0' && num[1] == 'x') {
00111       ast->litBase = 16;
00112       num = num.substr(2, num.size());
00113     }
00114     else if (num[0] == '0' && num[1] == 'o') {
00115       ast->litBase = 8;
00116       num = num.substr(2, num.size());
00117     }
00118     else if (num[0] == '0' && num[1] == 'b') {
00119       ast->litBase = 2;
00120       num = num.substr(2, num.size());
00121     }
00122     else if (num[0] == '0') {
00123       ast->litBase = 8;
00124       // No need to adjust num in this case.
00125     }
00126   }
00127 
00128   ast->litValue.i = BigNum(num, ast->litBase);
00129 
00130   // Sign is not being considered by bignum implementation
00131   if (negative)
00132     ast->litValue.i = -ast->litValue.i;
00133 
00134   ast->litValue.litType = lt_int;
00135 
00136   return ast;
00137 }
00138 
00142 shared_ptr<AST>
00143 AST::makeFloatLit(const sherpa::LToken &tok)
00144 {
00145   shared_ptr<AST> ast = AST::make(at_floatLiteral, tok);
00146   ast->litBase = 10;
00147   ast->litValue.d = strtod(tok.str.c_str(), 0);
00148 
00149   ast->litValue.litType = lt_float;
00150   return ast;
00151 }
00152 
00153 shared_ptr<AST>
00154 AST::makeStringLit(const sherpa::LToken &tok)
00155 {
00156   shared_ptr<AST> ast = AST::make(at_stringLiteral, tok);
00157   ast->litValue.s = tok.str;
00158   ast->litValue.litType = lt_string;
00159 
00160   return ast;
00161 }
00162 
00163 std::string
00164 AST::atKwd() const
00165 {
00166   std::string s = old_atKwd();
00167   if (s != printName()) {
00168     std::cerr << s << " != " << printName() << std::endl;
00169     assert(old_atKwd() == printName());
00170   }
00171 
00172   return printName();
00173 }
00174 
00175 std::string
00176 AST::old_atKwd() const
00177 {
00178   switch(astType) {
00179   case at_Null:
00180     return "NULL";
00181 
00182   case at_mixfix:
00183     return "<mixfix>";
00184 
00185   case at_docString:
00186     return "<doccomment>";
00187 
00188   case at_ident:
00189     return "<ident>";
00190 
00191   case at_ifident:
00192     return "<ifident>";
00193 
00194   case at_boolLiteral:
00195     return "<boolLiteral>";
00196 
00197   case at_charLiteral:
00198     return "<charLiteral>";
00199 
00200   case at_intLiteral:
00201     return "<intLiteral>";
00202 
00203   case at_floatLiteral:
00204     return "<floatLiteral>";
00205 
00206   case at_stringLiteral:
00207     return "<stringLiteral>";
00208 
00209   case at_module:
00210     return "module";
00211 
00212   case at_interface:
00213     return "interface";
00214 
00215   case at_defunion:
00216   case at_declunion:
00217     return "union";
00218 
00219   case at_declrepr:
00220   case at_defrepr:
00221     return "repr";
00222 
00223     //   case at_reprbody:
00224     //     return "<reprbody>";
00225     //   case at_reprcase:
00226     //     return "<reprcase>";
00227     //   case at_reprcaselegR:
00228     //     return "<reprcaseleg>";
00229     //   case at_reprtag:
00230     //     return "<reprtag>";
00231 
00232 
00233   case at_defstruct:
00234   case at_declstruct:
00235     return "struct";
00236 
00237   case at_defobject:
00238     return "object";
00239 
00240   case at_define:
00241   case at_recdef:
00242     return "def";
00243 
00244   case at_declares:
00245     return "<declares>";
00246 
00247   case at_declare:
00248     return "declare";
00249 
00250   case at_tvlist:
00251     return "<tvlist>";
00252 
00253   case at_constructors:
00254     return "<constructors>";
00255 
00256   case at_constructor:
00257     return "<constructor>";
00258 
00259   case at_reprctrs:
00260     return "<reprctrs>";
00261 
00262   case at_reprctr:
00263     return "<reprctr>";
00264 
00265   case at_reprrepr:
00266     return "<reprrepr>";
00267 
00268   case at_fields:
00269     return "<fields>";
00270 
00271   case at_field:
00272     return "<field>";
00273 
00274   case at_methdecl:
00275     return "<methdecl>";
00276 
00277   case at_fill:
00278     return "fill";
00279 
00280   case at_bitfieldType:
00281     return "bitfield";
00282 
00283   case at_byRefType:
00284     return "ByRef";
00285 
00286   case at_arrayRefType:
00287     return "ArrayRef";
00288 
00289   case at_boxedType:
00290     return "boxed";
00291 
00292   case at_unboxedType:
00293     return "unboxed";
00294 
00295   case at_fn:
00296     return "fn";
00297 
00298   case at_methType:
00299     return "method";
00300 
00301   case at_fieldType:
00302     return "<field>";
00303     
00304 //   case at_closureType:
00305 //     return "closure";
00306 
00307   case at_primaryType:
00308     return "<primaryType>";
00309 
00310   case at_argVec:
00311     return "<argVec>";
00312 
00313   case at_fnargVec:
00314     return "<fnargVec>";
00315 
00316   case at_arrayType:
00317     return "array";
00318 
00319   case at_vectorType:
00320     return "vector";
00321 
00322   case at_typeapp:
00323     return "<typeapp>";
00324 
00325   case at_mutableType:
00326     return "mutable";
00327 
00328   case at_constType:
00329     return "const";
00330 
00331   case at_identPattern:
00332     return "<identPattern>";
00333 
00334   case at_typeAnnotation:
00335     return "<typeAnnotation>";
00336 
00337   case at_suspend:
00338     return "suspend";
00339 
00340   case at_unit:
00341     return "()";
00342 
00343   case at_letGather:
00344     return "<letgather>";
00345 
00346   case at_allocREF:
00347     return "<allocREF>";
00348 
00349   case at_mkClosure:
00350     return "<mkClosure>";
00351 
00352   case at_mkArrayRef:
00353     return "<mkArrayRef>";
00354 
00355   case at_copyREF:
00356     return "<copyREF>";
00357 
00358   case at_setClosure:
00359     return "<setClosure>";
00360 
00361   case at_dup:
00362     return "dup";
00363 
00364   case at_MakeVector:
00365     return "MakeVector";
00366 
00367   case at_vector:
00368     return "vector";
00369 
00370   case at_array:
00371     return "array";
00372 
00373 #ifdef HAVE_INDEXABLE_LENGTH_OPS
00374   case at_array_length:
00375     return "array-length";
00376 
00377   case at_array_ref_length:
00378     return "array-ref-length";
00379 
00380   case at_vector_length:
00381     return "vector-length";
00382 #endif
00383 
00384   case at_begin:
00385     return "begin";
00386 
00387   case at_labeledBlock:
00388     return "label";
00389 
00390   case at_return_from:
00391     return "<return_from>";
00392 
00393   case at_loop:
00394     return "loop";
00395 
00396   case at_looptest:
00397     return "<looptest>";
00398 
00399   case at_select:
00400     return "<select>";
00401 
00402   case at_fqCtr:
00403     return "<fqCtr>";
00404 
00405   case at_sel_ctr:
00406     return "<sel_ctr>";
00407 
00408   case at_usesel:
00409     return "<usesel>";
00410 
00411   case at_lambda:
00412     return "lambda";
00413 
00414   case at_apply:
00415     return "<apply>";
00416 
00417   case at_if:
00418     return "if";
00419 
00420   case at_when:
00421     return "when";
00422 
00423   case at_unless:
00424     return "unless";
00425 
00426   case at_and:
00427     return "and";
00428 
00429   case at_or:
00430     return "or";
00431 
00432   case at_cond:
00433     return "cond";
00434 
00435   case at_cond_legs:
00436     return "<cond_legs>";
00437 
00438   case at_cond_leg:
00439     return "<cond_leg>";
00440 
00441   case at_otherwise:
00442     return "otherwise";
00443 
00444   case at_condelse:
00445     return "otherwise";
00446 
00447   case at_uswitch:
00448     return "switch";
00449 
00450   case at_usw_legs:
00451     return "<sw_legs>";
00452 
00453   case at_usw_leg:
00454     return "case";
00455 
00456   case at_setbang:
00457     return "set!";
00458 
00459   case at_deref:
00460     return "deref";
00461 
00462   case at_inner_ref:
00463     return "inner_ref";
00464 
00465   case at_try:
00466     return "try";
00467 
00468   case at_throw:
00469     return "throw";
00470 
00471   case at_let:
00472     return "let";
00473 
00474   case at_letStar:
00475     return "<letStar>";
00476 
00477   case at_letbindings:
00478     return "<letbindings>";
00479 
00480   case at_letbinding:
00481     return "letbinding";
00482 
00483   case at_loopbindings:
00484     return "<loopbindings>";
00485 
00486   case at_loopbinding:
00487     return "loopbinding";
00488 
00489   case at_letrec:
00490     return "letrec";
00491 
00492   case at_deftypeclass:
00493     return "trait";
00494 
00495   case at_definstance:
00496     return "instance";
00497 
00498   case at_defexception:
00499     return "exception";
00500 
00501   case at_exceptionType:
00502     return "exception";
00503 
00504   case at_dummyType:
00505     return "#dummy#";
00506 
00507   case at_importAs:
00508     return "import";
00509 
00510   case at_provide:
00511     return "provide";
00512 
00513   case at_import:
00514     return "import";
00515 
00516   case at_ifsel:
00517     return "<ifsel>";
00518 
00519   case at_proclaim:
00520     return "def";
00521 
00522   case at_array_nth:
00523     return "<array_nth>";
00524 
00525   case at_array_ref_nth:
00526     return "<array_ref_nth>";
00527 
00528   case at_vector_nth:
00529     return "<vector_nth>";
00530 
00531   case at_tcdecls:
00532     return "<tc_decls>";
00533 
00534   case at_method_decls:
00535     return "<method_decls>";
00536 
00537   case at_method_decl:
00538     return "<method_decl>";
00539 
00540   case at_tcmethods:
00541     return "<methods>";
00542 
00543   case at_tcmethod_binding:
00544     return "<method_bindings>";
00545 
00546   case at_tyfn:
00547     return "tyfn";
00548 
00549   case at_tcapp:
00550     return "<tcapp>";
00551 
00552   case at_oc_closed:
00553     return "closed";
00554     
00555   case at_oc_open:
00556     return "open";
00557     
00558   case at_unboxedCat:
00559     return "unboxed";
00560 
00561   case at_boxedCat:
00562     return "boxed";
00563 
00564   case at_opaqueCat:
00565     return "opaque";
00566 
00567   case at_qualType:
00568     return "forall";
00569 
00570   case at_sizeof:
00571     return "sizeof";
00572 
00573   case at_bitsizeof:
00574     return "bitsizeof";
00575 
00576   case at_constraints:
00577     return "<constraints>";
00578 
00579   case at_struct_apply:
00580     return "<struct_apply>";
00581 
00582   case at_object_apply:
00583     return "<object_apply>";
00584 
00585   case at_ucon_apply:
00586     return "<ucon_apply>";
00587 
00588   case at_localFrame:
00589     return "<local_frame>";
00590 
00591   case at_frameBindings:
00592     return "<frame_bindings>";
00593 
00594   case at_identList:
00595     return "<identList>";
00596 
00597   case at_container:
00598     return "<container>";
00599 
00600   case at_AnyGroup:
00601   case agt_uselhs:
00602   case agt_var:
00603   case agt_literal:
00604   case agt_tvar:
00605   case agt_CompilationUnit:
00606   case agt_definition:
00607   case agt_type_definition:
00608   case agt_tc_definition:
00609   case agt_value_definition:
00610   case agt_if_definition:
00611   case agt_category:
00612   case agt_qtype:
00613   case agt_fielditem:
00614   case agt_type:
00615   case agt_expr:
00616   case agt_expr_or_define:
00617   case agt_eform:
00618   case agt_ow:
00619   case agt_openclosed:
00620     //case agt_reprbodyitem:
00621   case agt_ucon:
00622     return "<GROUP>";
00623   }
00624 
00625   // Impossible to reach here.
00626   assert(false);
00627 
00628   // Satisfy the compiler
00629   return "<IMPOSSIBLE>";
00630 }
00631 
00632 std::string
00633 identTypeToString(IdentType id)
00634 {
00635   switch (id) {
00636   case id_block:
00637     return "block";
00638   case id_unresolved:
00639     return "unresolved";
00640   case id_tvar:
00641     return "type-variable";
00642   case id_union:
00643     return "union";
00644   case id_struct:
00645     return "struct";
00646   case id_object:
00647     return "object";
00648   case id_typeclass:
00649     return "typeclass";
00650   case id_tcmethod:
00651     return "method";
00652   case id_method:
00653     return "method";
00654   case id_field:
00655     return "field";
00656   case id_interface:
00657     return "interface";
00658   case id_value:
00659     return "value";
00660   case id_ucon:
00661     return "union-ctr";
00662   case id_ucon0:
00663     return "union-ctr0";
00664   case idc_type:
00665     return "Type";
00666   case idc_value:
00667     return "Value";
00668   case idc_ctor:
00669     return "Constructor";
00670   case idc_uctor:
00671     return "Union-ctor";
00672   case idc_apply:
00673     return "Applicable-value";
00674   case idc_usesel_lhs:
00675     return "Usesel-lhs";
00676   }
00677   return "IMPOSSIBLE";
00678 }
00679 
00680 void
00681 AST::disown(size_t s)
00682 {
00683   children.erase(children.begin() + s);
00684 }
00685 
00686 bool
00687 AST::isTopLevelForm()
00688 {
00689   switch(astType) {
00690   case at_define:
00691   case at_recdef:
00692   case at_defstruct:
00693   case at_defunion:
00694   case at_declunion:
00695   case at_declstruct:
00696   case at_proclaim:
00697   case at_declare:
00698   case at_importAs:
00699   case at_provide:
00700   case at_defexception:
00701     return true;
00702 
00703   default:
00704     return false;
00705   }
00706 }
00707 
00708 bool
00709 AST::leadsToTopLevelForm()
00710 {
00711   switch(astType) {
00712   case at_module:
00713   case at_interface:
00714   case at_define:
00715   case at_recdef:
00716   case at_defstruct:
00717   case at_defunion:
00718   case at_declunion:
00719   case at_declstruct:
00720   case at_proclaim:
00721   case at_declare:
00722   case at_importAs:
00723   case at_provide:
00724   case at_defexception:
00725     return true;
00726 
00727   default:
00728     return false;
00729   }
00730 }
00731 
00732 void
00733 AST::clearTypes() {
00734   symType = GC_NULL;
00735   scheme = GC_NULL;
00736   for (size_t i=0; i<children.size(); i++)
00737     child(i)->clearTypes();
00738 }
00739 
00740 
00741 void
00742 AST::getIds(std::ostream &errStream,
00743             std::vector<shared_ptr<AST> >& ids,
00744             bool getPattern)
00745 {
00746   switch(astType) {
00747   case at_identPattern:
00748     if (getPattern)
00749       ids.push_back(shared_from_this());
00750     else
00751       ids.push_back(child(0));
00752     break;
00753 
00754   default:
00755     errStream << loc << ": Internal Compiler Error,"
00756               << " getIds routine obtained the wrong "
00757               << "AST TYPE " << tagName()
00758               << std::endl;
00759   }
00760 }
00761 
00762 shared_ptr<AST>
00763 AST::getID()
00764 {
00765   switch(astType) {
00766   case at_define:
00767   case at_recdef:
00768   case at_letbinding:
00769   case at_loopbinding:
00770     return child(0)->child(0);
00771 
00772   case at_defstruct:
00773   case at_defunion:
00774   case at_declstruct:
00775   case at_declunion:
00776   case at_proclaim:
00777   case at_defexception:
00778   case at_deftypeclass:
00779     return child(0);
00780 
00781   default:
00782     return GC_NULL;
00783   }
00784 }
00785 
00786 shared_ptr<AST>
00787 AST::getInstanceMethod(std::string s)
00788 {
00789   assert(astType == at_definstance);
00790   shared_ptr<AST> methods = child(1);
00791   
00792   for(size_t c=0; c < methods->children.size(); c++) {
00793     shared_ptr<AST> method = methods->child(c);
00794     shared_ptr<AST> method_name = method->child(0);
00795     shared_ptr<AST> method_val = method->child(1);
00796 
00797     if(method_name->s == s) 
00798       return method_val;
00799   }
00800 
00801   return GC_NULL;
00802 }
00803 
00804 
00805 bool
00806 AST::isUnionLeg()
00807 {
00808   assert(astType == at_ident);
00809   return isIdentType(idc_uctor);
00810 }
00811 
00812 bool
00813 AST::isTcMethod()
00814 {
00815   if ((astType == at_ident) && isIdentType(id_tcmethod))
00816     return true;
00817   else
00818     return false;
00819 }
00820 
00821 shared_ptr<AST>
00822 AST::getCtr()
00823 {
00824   if (astType == at_ident)
00825     return shared_from_this();
00826 
00827   if (astType == at_fqCtr)
00828     return child(1);
00829 
00830   assert(false);
00831   return GC_NULL;
00832 }
00833 
00834 /* Rename identifier `from' to `to' in `ast' */
00835 void
00836 AST::rename(shared_ptr<AST> from, std::string newName)
00837 {
00838   shared_ptr<AST> me = shared_from_this();
00839   switch(astType) {
00840   case at_ident:
00841     if (me == from || symbolDef == from)
00842       s = newName;
00843     break;
00844 
00845     // switched identifier also gets renamed in
00846     // the encoded at_switch and at_try positions here
00847 
00848   default:
00849     for (size_t c = 0; c < children.size(); c++)
00850       child(c)->rename(from, newName);
00851     break;
00852   }
00853 }
00854 
00855 bool
00856 AST::isLiteral()
00857 {
00858   switch (astType) {
00859   case at_boolLiteral:
00860   case at_charLiteral:
00861   case at_intLiteral:
00862   case at_floatLiteral:
00863   case at_stringLiteral:
00864     return true;
00865 
00866   default:
00867     return false;
00868   }
00869 }
00870 
00871 bool
00872 AST::isIdentType(IdentType t)
00873 {
00874   return ((identType == t) ||
00875           ((t == idc_type) && ((identType == id_tvar) ||
00876                                (identType == id_union) ||
00877                                (identType == id_struct) ||
00878                                (identType == id_object))) ||
00879           ((t == idc_value) && ((identType == id_value) ||
00880                                 (identType == id_ucon0) ||
00881                                 (identType == id_tcmethod))) ||
00882           ((t == idc_ctor)  && ((identType == id_struct) ||
00883                                 (identType == id_object) ||
00884                                 (identType == id_ucon) ||
00885                                 (identType == id_ucon0))) ||
00886           ((t == idc_uctor) && ((identType == id_ucon) ||
00887                                 (identType == id_ucon0))) ||
00888           // The idc_apply case is written as a recursive call and not
00889           // as disjunction of various id_* cases since in the case
00890           // where we are applying a valye that was proclaimed, the
00891           // identType would still be idc_value, and not id_value.
00892           ((t == idc_apply) && (isIdentType(idc_value) ||
00893                                 isIdentType(idc_ctor) ||
00894                                 isIdentType(id_method))) ||
00895           ((t == idc_usesel_lhs) && ((identType == id_interface) ||
00896                                      (identType == id_struct) ||
00897                                      (identType == id_object))));
00898 }
00899 
00900 int
00901 AST::precedence() const
00902 {
00903   switch(astType) {
00904 
00905   case at_usesel:
00906   case at_ident:
00907   case at_select:
00908   case at_primaryType:
00909   case at_exceptionType:
00910     return 0;
00911 
00912   case at_typeapp:
00913     return 1;
00914 
00915     /* blk_permqual_type */
00916   case at_mutableType:
00917   case at_constType:
00918     return 2;
00919 
00920     /* blk_postfix_type */
00921   case at_boxedType:
00922   case at_arrayType:
00923   case at_vectorType:
00924     return 3;
00925 
00926   default:
00927     return -1;                  // no particular precedence
00928   }
00929 }

Generated on Sat Feb 4 23:59:28 2012 for BitC Compiler by  doxygen 1.4.7