Modules | Files | Inheritance Tree | Inheritance Graph | Name Index | Config
File: Synopsis/Parser/C++/syn/synopsis.cc
    1| // Synopsis C++ Parser: synopsis.cc source file
    2| // This file contains implementation for class Synopsis, which converts the
    3| // C++ AST into a Python AST.
    4| 
    5| // $Id: synopsis.cc,v 1.48 2003/01/27 06:53:37 chalky Exp $
    6| //
    7| // This file is a part of Synopsis.
    8| // Copyright (C) 2002 Stephen Davies
    9| //
   10| // Synopsis is free software; you can redistribute it and/or modify it
   11| // under the terms of the GNU General Public License as published by
   12| // the Free Software Foundation; either version 2 of the License, or
   13| // (at your option) any later version.
   14| //
   15| // This program is distributed in the hope that it will be useful,
   16| // but WITHOUT ANY WARRANTY; without even the implied warranty of
   17| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   18| // General Public License for more details.
   19| //
   20| // You should have received a copy of the GNU General Public License
   21| // along with this program; if not, write to the Free Software
   22| // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
   23| // 02111-1307, USA.
   24| 
   25| // $Log: synopsis.cc,v $
   26| // Revision 1.48  2003/01/27 06:53:37  chalky
   27| // Added macro support for C++.
   28| //
   29| // Revision 1.47  2003/01/16 17:14:10  chalky
   30| // Increase AST version number. SourceFiles store full filename. Executor/Project
   31| // uses it to check timestamp for all included files when deciding whether to
   32| // reparse input files.
   33| //
   34| // Revision 1.46  2002/12/12 17:25:34  chalky
   35| // Implemented Include support for C++ parser. A few other minor fixes.
   36| //
   37| // Revision 1.45  2002/12/09 04:01:02  chalky
   38| // Added multiple file support to parsers, changed AST datastructure to handle
   39| // new information, added a demo to demo/C++. AST Declarations now have a
   40| // reference to a SourceFile (which includes a filename) instead of a filename.
   41| //
   42| // Revision 1.44  2002/11/17 12:11:44  chalky
   43| // Reformatted all files with astyle --style=ansi, renamed fakegc.hh
   44| //
   45| // Revision 1.43  2002/10/27 12:23:55  chalky
   46| // Re-introduce forced addition of declarations to type dictionary
   47| //
   48| // Revision 1.42  2002/10/25 02:49:52  chalky
   49| // Support templated forward class declarations
   50| //
   51| // Revision 1.41  2002/10/20 15:38:10  chalky
   52| // Much improved template support, including Function Templates.
   53| //
   54| // Revision 1.40  2002/10/20 02:25:08  chalky
   55| // Remove null ptr hack - uses signal(SIGINT) to activate debugger
   56| //
   57| 
   58| #include <map>
   59| #include <set>
   60| 
   61| #include <iostream>
   62| #include <signal.h>
   63| 
   64| #include "synopsis.hh"
   65| #include "filter.hh"
   66| 
   67| #ifdef DO_TRACE
   68| int Trace::level = 0;
   69| #endif
   70| 
   71| #define assertObject(pyo) if (!pyo) PyErr_Print(); assert(pyo)
   72| 
   73| // This func is called so you can breakpoint on it
   74| void nullObj()
   75| {
   76|     std::cout << "Null ptr." << std::endl;
   77|     if (PyErr_Occurred())
   78|         PyErr_Print();
   79|     raise(SIGINT);
   80| }
   81| 
   82| // The compiler firewalled private stuff
   83| struct Synopsis::Private
   84| {
   85|     //. Constructor
   86|     Private(Synopsis* s) : m_syn(s)
   87|     {
   88|         m_cxx = PyString_InternFromString("C++");
   89|         Py_INCREF(Py_None);
   90|         add((AST::Declaration*)NULL, Py_None);
   91|         Py_INCREF(Py_None);
   92|         add((Types::Type*)NULL, Py_None);
   93|     }
   94|     //. Reference to parent synopsis object
   95|     Synopsism_syn;
   96|     //. Interned string for "C++"
   97|     PyObjectm_cxx;
   98|     //. Returns the string for "C++" as a borrowed reference
   99|     PyObjectcxx()
  100|     {
  101|         return m_cxx;
  102|     }
  103|     // Sugar
  104|     typedef std::map<void*, PyObject*> ObjMap;
  105|     // Maps from C++ objects to PyObjects
  106|     ObjMap obj_map;
  107|     // A set of builtin declarations to not to store in global namespace
  108|     std::set<AST::Declaration*> builtin_decl_set;
  109| 
  110|     // Note that these methods always succeed
  111| 
  112|     //. Return the PyObject for the given AST::SourceFile
  113|     PyObjectpy(AST::SourceFile*);
  114|     //. Return the PyObject for the given AST::Include
  115|     PyObjectpy(AST::Include*);
  116|     //. Return the PyObject for the given AST::Declaration
  117|     PyObjectpy(AST::Declaration*);
  118|     //. Return the PyObject for the given AST::Inheritance
  119|     PyObjectpy(AST::Inheritance*);
  120|     //. Return the PyObject for the given AST::Parameter
  121|     PyObjectpy(AST::Parameter*);
  122|     //. Return the PyObject for the given AST::Comment
  123|     PyObjectpy(AST::Comment*);
  124|     //. Return the PyObject for the given Types::Type
  125|     PyObjectpy(Types::Type*);
  126|     //. Return the PyObject for the given string
  127|     PyObjectpy(const std::string &);
  128| 
  129|     //. Add the given pair
  130|     void add(void* cobj, PyObject* pyobj)
  131|     {
  132|         if (!pyobj)
  133|         {
  134|             nullObj();
  135|         }
  136|         obj_map.insert(ObjMap::value_type(cobjpyobj));
  137|     }
  138| 
  139|     // Convert a vector to a List
  140|     template <class T>
  141|     PyObjectList(const std::vector<T*>& vec)
  142|     {
  143|         PyObjectlist = PyList_New(vec.size());
  144|         int index = 0;
  145|         typename std::vector<T*>::const_iterator iter = vec.begin();
  146|         while (iter != vec.end())
  147|             PyList_SET_ITEM(list, index++, py(*iter++));
  148|         return list;
  149|     }
  150| 
  151|     // Convert a vector to a Tuple
  152|     template <class T>
  153|     PyObjectTuple(const std::vector<T*>& vec)
  154|     {
  155|         PyObjecttuple = PyTuple_New(vec.size());
  156|         int index = 0;
  157|         typename std::vector<T*>::const_iterator iter = vec.begin();
  158|         while (iter != vec.end())
  159|             PyTuple_SET_ITEM(tuple, index++, py(*iter++));
  160|         return tuple;
  161|     }
  162| 
  163|     // Convert a string vector to a List
  164|     PyObjectList(const std::vector<std::string> &vec)
  165|     {
  166|         PyObjectlist = PyList_New(vec.size());
  167|         int index = 0;
  168|         std::vector<std::string>::const_iterator iter = vec.begin();
  169|         while (iter != vec.end())
  170|             PyList_SET_ITEM(list, index++, py(*iter++));
  171|         return list;
  172|     }
  173| 
  174|     // Convert a string vector to a Tuple
  175|     PyObjectTuple(const std::vector<std::string> &vec)
  176|     {
  177|         PyObjecttuple = PyTuple_New(vec.size());
  178|         int index = 0;
  179|         std::vector<std::string>::const_iterator iter = vec.begin();
  180|         while (iter != vec.end())
  181|             PyTuple_SET_ITEM(tuple, index++, py(*iter++));
  182|         return tuple;
  183|     }
  184| };
  185| // Convert a Declaration vector to a List. Declarations can return NULL
  186| // from py(), if they are not in the main file.
  187| template <>
  188| PyObject* Synopsis::Private::List(const std::vector<AST::Declaration*>& vec)
  189| {
  190|     std::vector<PyObject*> objects;
  191|     std::vector<AST::Declaration*>::const_iterator iter = vec.begin();
  192|     while (iter != vec.end())
  193|     {
  194|         PyObject* obj = py(*iter++);
  195|         if (obj != NULL)
  196|             objects.push_back(obj);
  197|     }
  198| 
  199|     PyObject* list = PyList_New(objects.size());
  200|     int index = 0;
  201|     std::vector<PyObject*>::const_iterator piter = objects.begin();
  202|     while (piter != objects.end())
  203|         PyList_SET_ITEM(list, index++, *piter++);
  204|     return list;
  205| }
  206| 
  207| PyObjectSynopsis::Private::py(AST::SourceFile* file)
  208| {
  209|     ObjMap::iterator iter = obj_map.find(file);
  210|     if (iter == obj_map.end())
  211|     {
  212|         // Need to convert object first
  213|         add(filem_syn->SourceFile(file));
  214|         iter = obj_map.find(file);
  215|         if (iter == obj_map.end())
  216|         {
  217|             std::cout << "Fatal: Still not PyObject after converting." << std::endl;
  218|             throw "Synopsis::Private::py(AST::SourceFile*)";
  219|         }
  220|     }
  221|     PyObjectobj = iter->second;
  222|     Py_INCREF(obj);
  223|     return obj;
  224| }
  225| 
  226| PyObjectSynopsis::Private::py(AST::Include* incl)
  227| {
  228|     ObjMap::iterator iter = obj_map.find(incl);
  229|     if (iter == obj_map.end())
  230|     {
  231|         // Need to convert object first
  232|         add(inclm_syn->Include(incl));
  233|         iter = obj_map.find(incl);
  234|         if (iter == obj_map.end())
  235|         {
  236|             std::cout << "Fatal: Still not PyObject after converting." << std::endl;
  237|             throw "Synopsis::Private::py(AST::Include*)";
  238|         }
  239|     }
  240|     PyObjectobj = iter->second;
  241|     Py_INCREF(obj);
  242|     return obj;
  243| }
  244| 
  245| PyObjectSynopsis::Private::py(AST::Declaration* decl)
  246| {
  247|     ObjMap::iterator iter = obj_map.find(decl);
  248|     if (iter == obj_map.end())
  249|     {
  250|         // Need to convert object first
  251|         decl->accept(m_syn);
  252|         iter = obj_map.find(decl);
  253|         if (iter == obj_map.end())
  254|         {
  255|             // Probably means it's not in the main file
  256|             return NULL;
  257|             /*
  258|             std::cout << "Fatal: Still not PyObject after converting." << std::endl;
  259|             throw "Synopsis::Private::py(AST::Declaration*)";
  260|             */
  261|         }
  262|         // Force addition of type to dictionary
  263|         PyObjectdeclared = py(decl->declared());
  264|         Py_DECREF(declared);
  265|     }
  266|     PyObjectobj = iter->second;
  267|     Py_INCREF(obj);
  268|     return obj;
  269| }
  270| 
  271| PyObjectSynopsis::Private::py(AST::Inheritance* decl)
  272| {
  273|     ObjMap::iterator iter = obj_map.find(decl);
  274|     if (iter == obj_map.end())
  275|     {
  276|         // Need to convert object first
  277|         decl->accept(m_syn);
  278|         iter = obj_map.find(decl);
  279|         if (iter == obj_map.end())
  280|         {
  281|             std::cout << "Fatal: Still not PyObject after converting." << std::endl;
  282|             throw "Synopsis::Private::py(AST::Inheritance*)";
  283|         }
  284|     }
  285|     PyObjectobj = iter->second;
  286|     Py_INCREF(obj);
  287|     return obj;
  288| }
  289| PyObjectSynopsis::Private::py(AST::Parameter* decl)
  290| {
  291|     ObjMap::iterator iter = obj_map.find(decl);
  292|     if (iter == obj_map.end())
  293|     {
  294|         // Need to convert object first
  295|         decl->accept(m_syn);
  296|         iter = obj_map.find(decl);
  297|         if (iter == obj_map.end())
  298|         {
  299|             std::cout << "Fatal: Still not PyObject after converting." << std::endl;
  300|             throw "Synopsis::Private::py(AST::Parameter*)";
  301|         }
  302|     }
  303|     PyObjectobj = iter->second;
  304|     Py_INCREF(obj);
  305|     return obj;
  306| }
  307| 
  308| PyObjectSynopsis::Private::py(AST::Comment* decl)
  309| {
  310|     ObjMap::iterator iter = obj_map.find(decl);
  311|     if (iter == obj_map.end())
  312|     {
  313|         // Need to convert object first
  314|         m_syn->visit_comment(decl);
  315|         iter = obj_map.find(decl);
  316|         if (iter == obj_map.end())
  317|         {
  318|             std::cout << "Fatal: Still not PyObject after converting." << std::endl;
  319|             throw "Synopsis::Private::py(AST::Comment*)";
  320|         }
  321|     }
  322|     PyObjectobj = iter->second;
  323|     Py_INCREF(obj);
  324|     return obj;
  325| }
  326| 
  327| 
  328| PyObjectSynopsis::Private::py(Types::Type* type)
  329| {
  330|     ObjMap::iterator iter = obj_map.find(type);
  331|     if (iter == obj_map.end())
  332|     {
  333|         // Need to convert object first
  334|         type->accept(m_syn);
  335|         iter = obj_map.find(type);
  336|         if (iter == obj_map.end())
  337|         {
  338|             std::cout << "Fatal: Still not PyObject after converting." << std::endl;
  339|             throw "Synopsis::Private::py(Types::Type*)";
  340|         }
  341|     }
  342|     PyObjectobj = iter->second;
  343|     Py_INCREF(obj);
  344|     return obj;
  345| }
  346| 
  347| PyObjectSynopsis::Private::py(const std::string &str)
  348| {
  349|     PyObjectpystr = PyString_FromStringAndSize(str.data(), str.size());
  350|     //PyString_InternInPlace(&pystr);
  351|     return pystr;
  352| }
  353| 
  354| 
  355| 
  356| 
  357| 
  358| 
  359| //
  360| // Class Synopsis
  361| //
  362| 
  363| Synopsis::Synopsis(FileFilter* filter, PyObject *decl, PyObject *dict)
  364|         : m_declarations(decl), m_dictionary(dict), m_filter(filter)
  365| {
  366|     Trace trace("Synopsis::Synopsis");
  367|     m_ast  = PyImport_ImportModule("Synopsis.Core.AST");
  368|     assertObject(m_ast);
  369|     m_type = PyImport_ImportModule("Synopsis.Core.Type");
  370|     assertObject(m_type);
  371| 
  372|     m = new Private(this);
  373| }
  374| 
  375| Synopsis::~Synopsis()
  376| {
  377|     Trace trace("Synopsis::~Synopsis");
  378|     /*
  379|     PyObject *file = PyObject_CallMethod(scopes.back(), "declarations", 0);
  380|     size_t size = PyList_Size(file);
  381|     for (size_t i = 0; i != size; i++)
  382|         PyObject_CallMethod(declarations, "append", "O", PyList_GetItem(file, i));
  383|     */
  384|     Py_DECREF(m_type);
  385|     Py_DECREF(m_ast);
  386| 
  387|     // Deref the objects we created
  388|     Private::ObjMap::iterator iter = m->obj_map.begin();
  389|     Private::ObjMap::iterator end = m->obj_map.end();
  390|     while (iter != end)
  391|     {
  392|         PyObjectobj = iter->second;
  393|         PyObjectrepr = PyObject_Repr(obj);
  394|         //std::cout << (obj->ob_refcnt-1) << " " << PyString_AsString(repr) << std::endl;
  395|         Py_DECREF(repr);
  396|         Py_DECREF(obj);
  397|         iter->second = NULL;
  398|         ++iter;
  399|     }
  400|     //std::cout << "Total: " << m->obj_map.size()<<" objects." << std::endl;
  401|     delete m;
  402| }
  403| 
  404| void Synopsis::translate(AST::Scope* scope, PyObject* ast)
  405| {
  406|     AST::Declaration::vector globals, &decls = scope->declarations();
  407|     AST::Declaration::vector::iterator it = decls.begin();
  408| 
  409|     // List all declarations not in the builtin_decl_set
  410|     for (; it != decls.end(); ++it)
  411|         if (m->builtin_decl_set.find(*it) == m->builtin_decl_set.end())
  412|             globals.push_back(*it);
  413| 
  414|     // Translate those declarations
  415|     PyObjectlist;
  416|     PyObject_CallMethod(m_declarations"extend""O",
  417|                         list = m->List(globals)
  418|                        );
  419|     Py_DECREF(list);
  420| 
  421|     // Translate the sourcefiles, making sure the declarations list is done
  422|     // for each
  423|     PyObjectpyfiles = PyObject_CallMethod(ast"files", NULL);
  424|     assertObject(pyfiles);
  425|     assert(PyDict_Check(pyfiles));
  426| 
  427|     AST::SourceFile::vector all_sourcefiles;
  428|     m_filter->get_all_sourcefiles(all_sourcefiles);
  429|     AST::SourceFile::vector::iterator file_iter = all_sourcefiles.begin();
  430|     while (file_iter != all_sourcefiles.end())
  431|     {
  432|         AST::SourceFilefile = *file_iter++;
  433| 
  434|         PyObjectdecls, *new_decls, *incls, *new_incls;
  435|         PyObjectpyfile = m->py(file);
  436| 
  437|         // Add the declarations if it's a main file
  438|         if (file->is_main())
  439|         {
  440|             decls = PyObject_CallMethod(pyfile"declarations", NULL);
  441|             assertObject(decls);
  442|             PyObject_CallMethod(decls"extend""O"new_decls = m->List(file->declarations()));
  443|             // TODO: add the includes
  444|             Py_DECREF(new_decls);
  445|             Py_DECREF(decls);
  446|         }
  447| 
  448|         // Add the includes
  449|         incls = PyObject_CallMethod(pyfile"includes", NULL);
  450|         assertObject(incls);
  451|         PyObject_CallMethod(incls"extend""O"new_incls = m->List(file->includes()));
  452|         Py_DECREF(new_incls);
  453|         Py_DECREF(incls);
  454|         
  455|         // Add to the AST
  456|         PyObjectpyfilename = PyObject_CallMethod(pyfile"filename", NULL);
  457|         PyDict_SetItem(pyfilespyfilenamepyfile);
  458|         Py_DECREF(pyfilename);
  459|         Py_DECREF(pyfile);
  460|     }
  461| 
  462|     Py_DECREF(pyfiles);
  463|         
  464| }
  465| 
  466| void Synopsis::set_builtin_decls(const AST::Declaration::vector& builtin_decls)
  467| {
  468|     // Insert Base*'s into a set for faster lookup
  469|     AST::Declaration::vector::const_iterator it = builtin_decls.begin();
  470|     while (it != builtin_decls.end())
  471|         m->builtin_decl_set.insert(*it++);
  472| }
  473| 
  474| //
  475| // Type object factories
  476| //
  477| 
  478| PyObject *Synopsis::Base(Types::Base* type)
  479| {
  480|     Trace trace("Synopsis::Base");
  481|     PyObject *name, *base;
  482|     base = PyObject_CallMethod(m_type"Base""OO",
  483|                                m->cxx(), name = m->Tuple(type->name())
  484|                               );
  485|     PyObject_SetItem(m_dictionarynamebase);
  486|     Py_DECREF(name);
  487|     return base;
  488| }
  489| 
  490| PyObject *Synopsis::Dependent(Types::Dependent* type)
  491| {
  492|     Trace trace("Synopsis::Dependent");
  493|     PyObject *name, *base;
  494|     base = PyObject_CallMethod(m_type"Dependent""OO",
  495|                                m->cxx(), name = m->Tuple(type->name())
  496|                               );
  497|     PyObject_SetItem(m_dictionarynamebase);
  498|     Py_DECREF(name);
  499|     return base;
  500| }
  501| 
  502| PyObject *Synopsis::Unknown(Types::Named* type)
  503| {
  504|     Trace trace("Synopsis::Unknown");
  505|     PyObject *name, *unknown;
  506|     unknown = PyObject_CallMethod(m_type"Unknown""OO",
  507|                                   m->cxx(), name = m->Tuple(type->name())
  508|                                  );
  509|     PyObject_SetItem(m_dictionarynameunknown);
  510|     Py_DECREF(name);
  511|     return unknown;
  512| }
  513| 
  514| PyObject *Synopsis::Declared(Types::Declared* type)
  515| {
  516|     Trace trace("Synopsis::Declared");
  517|     PyObject *name, *declared, *decl;
  518|     declared = PyObject_CallMethod(m_type"Declared""OOO",
  519|                                    m->cxx(), name = m->Tuple(type->name()), 
  520|                                    decl = m->py(type->declaration())
  521|                                   );
  522|     // Skip zero-length names (eg: dummy declarators/enumerators)
  523|     if (type->name().size())
  524|         PyObject_SetItem(m_dictionarynamedeclared);
  525|     Py_DECREF(name);
  526|     Py_DECREF(decl);
  527|     return declared;
  528| }
  529| 
  530| PyObject *Synopsis::Template(Types::Template* type)
  531| {
  532|     Trace trace("Synopsis::Template");
  533|     PyObject *name, *templ, *decl, *params;
  534|     templ = PyObject_CallMethod(m_type"Template""OOOO",
  535|                                 m->cxx(), name = m->Tuple(type->name()), 
  536|                                 decl = m->py(type->declaration()),
  537|                                 params = m->List(type->parameters())
  538|                                );
  539|     PyObject_SetItem(m_dictionarynametempl);
  540|     Py_DECREF(name);
  541|     Py_DECREF(decl);
  542|     Py_DECREF(params);
  543|     return templ;
  544| }
  545| 
  546| PyObject *Synopsis::Modifier(Types::Modifier* type)
  547| {
  548|     Trace trace("Synopsis::Modifier");
  549|     PyObject *modifier, *alias, *pre, *post;
  550|     modifier = PyObject_CallMethod(m_type"Modifier""OOOO",
  551|                                    m->cxx(), alias = m->py(type->alias()),
  552|                                    pre = m->List(type->pre()), post = m->List(type->post())
  553|                                   );
  554|     Py_DECREF(alias);
  555|     Py_DECREF(pre);
  556|     Py_DECREF(post);
  557|     return modifier;
  558| }
  559| 
  560| PyObject *Synopsis::Array(Types::Array *type)
  561| {
  562|     Trace trace("Synopsis::Array");
  563|     PyObject *array, *alias, *sizes;
  564|     array = PyObject_CallMethod(m_type"Array""OOO",
  565|                                 m->cxx(), alias = m->py(type->alias()), 
  566|                                 sizes = m->List(type->sizes()));
  567|     Py_DECREF(alias);
  568|     Py_DECREF(sizes);
  569|     return array;
  570| }
  571| 
  572| PyObject *Synopsis::Parameterized(Types::Parameterized* type)
  573| {
  574|     Trace trace("Synopsis::Parametrized");
  575|     PyObject *parametrized, *templ, *params;
  576|     parametrized = PyObject_CallMethod(m_type"Parametrized""OOO",
  577|                                        m->cxx(), templ = m->py(type->template_type()), 
  578|                                        params = m->List(type->parameters())
  579|                                       );
  580|     Py_DECREF(templ);
  581|     Py_DECREF(params);
  582|     return parametrized;
  583| }
  584| 
  585| PyObject *Synopsis::FuncPtr(Types::FuncPtr* type)
  586| {
  587|     Trace trace("Synopsis::FuncType");
  588|     PyObject *func, *ret, *pre, *params;
  589|     func = PyObject_CallMethod(m_type"Function""OOOO",
  590|                                m->cxx(), ret = m->py(type->return_type()), 
  591|                                pre = m->List(type->pre()),
  592|                                params = m->List(type->parameters())
  593|                               );
  594|     Py_DECREF(ret);
  595|     Py_DECREF(pre);
  596|     Py_DECREF(params);
  597|     return func;
  598| }
  599| 
  600| 
  601| //
  602| // AST object factories
  603| //
  604| 
  605| void Synopsis::addComments(PyObject* pydecl, AST::Declaration* cdecl)
  606| {
  607|     PyObject *comments, *new_comments;
  608|     comments = PyObject_CallMethod(pydecl"comments", NULL);
  609|     PyObject_CallMethod(comments"extend""O"new_comments = m->List(cdecl->comments()));
  610|     // Also set the accessability..
  611|     PyObject_CallMethod(pydecl"set_accessibility""i", int(cdecl->access()));
  612|     Py_DECREF(comments);
  613|     Py_DECREF(new_comments);
  614| }
  615| 
  616| PyObject *Synopsis::SourceFile(AST::SourceFile* file)
  617| {
  618|     Trace trace("Synopsis::SourceFile");
  619|     PyObject *pyfile, *filename, *full_filename;
  620|     //std::cout << " Creating SourceFile for " << file->filename() << std::endl;
  621|     pyfile = PyObject_CallMethod(m_ast"SourceFile""OOO",
  622|                                  filename = m->py(file->filename()),
  623|                                  full_filename = m->py(file->full_filename()),
  624|                                  m->cxx()
  625|                                 );
  626|     assertObject(pyfile);
  627|     PyObject_CallMethod(pyfile"set_is_main""i", (int)file->is_main());
  628|     Py_DECREF(filename);
  629|     Py_DECREF(full_filename);
  630|     return pyfile;
  631| }
  632| 
  633| PyObject *Synopsis::Include(AST::Include* include)
  634| {
  635|     Trace trace("Synopsis::Include");
  636|     PyObject *pyinclude, *target;
  637|     pyinclude = PyObject_CallMethod(m_ast"Include""Oii",
  638|                                  target = m->py(include->target()),
  639|                                  include->is_macro() ? 1 : 0,
  640|                              include->is_next() ? 1 : 0
  641|                                 );
  642|     assertObject(pyinclude);
  643|     Py_DECREF(target);
  644|     return pyinclude;
  645| }
  646| 
  647| PyObject *Synopsis::Declaration(AST::Declaration* decl)
  648| {
  649|     Trace trace("Synopsis::addDeclaration");
  650|     PyObject *pydecl, *file, *type, *name;
  651|     pydecl = PyObject_CallMethod(m_ast"Declaration""OiOOO",
  652|                                  file = m->py(decl->file()), decl->line(), m->cxx(),
  653|                                  type = m->py(decl->type()), name = m->Tuple(decl->name())
  654|                                 );
  655|     assertObject(pydecl);
  656|     addComments(pydecldecl);
  657|     Py_DECREF(file);
  658|     Py_DECREF(type);
  659|     Py_DECREF(name);
  660|     return pydecl;
  661| }
  662| 
  663| PyObject *Synopsis::Macro(AST::Macro* decl)
  664| {
  665|     Trace trace("Synopsis::Macro");
  666|     PyObject *pymacro, *file, *type, *name, *params, *text;
  667|     if (decl->parameters())
  668|         params = m->List(*decl->parameters());
  669|     else
  670|     {
  671|         params = Py_None;
  672|         Py_INCREF(Py_None);
  673|     }
  674|     pymacro = PyObject_CallMethod(m_ast"Macro""OiOOOOO",
  675|             file = m->py(decl->file()), decl->line(), m->cxx(),
  676|             type = m->py(decl->type()), name = m->Tuple(decl->name()),
  677|             paramstext = m->py(decl->text())
  678|         );
  679|     assertObject(pymacro);
  680|     addComments(pymacrodecl);
  681|     Py_DECREF(file);
  682|     Py_DECREF(type);
  683|     Py_DECREF(name);
  684|     Py_DECREF(params);
  685|     Py_DECREF(text);
  686|     return pymacro;
  687| }
  688| 
  689| PyObject *Synopsis::Forward(AST::Forward* decl)
  690| {
  691|     Trace trace("Synopsis::addForward");
  692|     PyObject *forward, *file, *type, *name;
  693|     forward = PyObject_CallMethod(m_ast"Forward""OiOOO",
  694|                                   file = m->py(decl->file()), decl->line(), m->cxx(),
  695|                                   type = m->py(decl->type()), name = m->Tuple(decl->name())
  696|                                  );
  697|     addComments(forwarddecl);
  698|     Py_DECREF(file);
  699|     Py_DECREF(type);
  700|     Py_DECREF(name);
  701|     return forward;
  702| }
  703| 
  704| PyObject *Synopsis::Comment(AST::Comment* decl)
  705| {
  706|     Trace trace("Synopsis::addComment");
  707|     std::string text_str = decl->text()+"\n";
  708|     PyObject *text = PyString_FromStringAndSize(text_str.data(), text_str.size());
  709|     PyObject *comment, *file;
  710|     comment = PyObject_CallMethod(m_ast"Comment""OOii",
  711|                                   textfile = m->py(decl->file()), 
  712|                                   decl->line(), decl->is_suspect() ? 1 : 0
  713|                                  );
  714|     Py_DECREF(text);
  715|     Py_DECREF(file);
  716|     return comment;
  717| }
  718| 
  719| PyObject *Synopsis::Scope(AST::Scope* decl)
  720| {
  721|     Trace trace("Synopsis::addScope");
  722|     PyObject *scope, *file, *type, *name;
  723|     scope = PyObject_CallMethod(m_ast"Scope""OiOOO",
  724|                                 file = m->py(decl->file()), decl->line(), m->cxx(),
  725|                                 type = m->py(decl->type()), name = m->Tuple(decl->name())
  726|                                );
  727|     PyObject *decls = PyObject_CallMethod(scope"declarations", NULL);
  728|     PyObject_CallMethod(decls"extend""O"m->List(decl->declarations()));
  729|     addComments(scopedecl);
  730|     Py_DECREF(file);
  731|     Py_DECREF(type);
  732|     Py_DECREF(name);
  733|     Py_DECREF(decls);
  734|     return scope;
  735| }
  736| 
  737| PyObject *Synopsis::Namespace(AST::Namespace* decl)
  738| {
  739|     Trace trace("Synopsis::addNamespace");
  740|     PyObject *module, *file, *type, *name;
  741|     module = PyObject_CallMethod(m_ast"Module""OiOOO",
  742|                                  file = m->py(decl->file()), decl->line(), m->cxx(),
  743|                                  type = m->py(decl->type()), name = m->Tuple(decl->name())
  744|                                 );
  745|     PyObject *decls = PyObject_CallMethod(module"declarations", NULL);
  746|     PyObject *new_decls = m->List(decl->declarations());
  747|     PyObject_CallMethod(decls"extend""O"new_decls);
  748|     addComments(moduledecl);
  749|     Py_DECREF(file);
  750|     Py_DECREF(type);
  751|     Py_DECREF(name);
  752|     Py_DECREF(decls);
  753|     Py_DECREF(new_decls);
  754|     return module;
  755| }
  756| 
  757| PyObject *Synopsis::Inheritance(AST::Inheritance* decl)
  758| {
  759|     Trace trace("Synopsis::Inheritance");
  760|     PyObject *inheritance, *parent, *attrs;
  761|     inheritance = PyObject_CallMethod(m_ast"Inheritance""sOO",
  762|                                       "inherits"parent = m->py(decl->parent()), 
  763|                                       attrs = m->List(decl->attributes())
  764|                                      );
  765|     Py_DECREF(parent);
  766|     Py_DECREF(attrs);
  767|     return inheritance;
  768| }
  769| 
  770| PyObject *Synopsis::Class(AST::Class* decl)
  771| {
  772|     Trace trace("Synopsis::addClass");
  773|     PyObject *clas, *file, *type, *name;
  774|     clas = PyObject_CallMethod(m_ast"Class""OiOOO",
  775|                                file = m->py(decl->file()), decl->line(), m->cxx(),
  776|                                type = m->py(decl->type()), name = m->Tuple(decl->name())
  777|                               );
  778|     // This is necessary to prevent inf. loops in several places
  779|     m->add(declclas);
  780|     PyObject *new_decls, *new_parents;
  781|     PyObject *decls = PyObject_CallMethod(clas"declarations", NULL);
  782|     PyObject_CallMethod(decls"extend""O"new_decls = m->List(decl->declarations()));
  783|     PyObject *parents = PyObject_CallMethod(clas"parents", NULL);
  784|     PyObject_CallMethod(parents"extend""O"new_parents = m->List(decl->parents()));
  785|     if (decl->template_type())
  786|     {
  787|         PyObjectttype;
  788|         PyObject_CallMethod(clas"set_template""O"ttype = m->py(decl->template_type()));
  789|         Py_DECREF(ttype);
  790|     }
  791|     addComments(clasdecl);
  792|     Py_DECREF(file);
  793|     Py_DECREF(type);
  794|     Py_DECREF(name);
  795|     Py_DECREF(decls);
  796|     Py_DECREF(parents);
  797|     Py_DECREF(new_decls);
  798|     Py_DECREF(new_parents);
  799|     return clas;
  800| }
  801| 
  802| PyObject *Synopsis::Typedef(AST::Typedef* decl)
  803| {
  804|     Trace trace("Synopsis::addTypedef");
  805|     // FIXME: what to do about the declarator?
  806|     PyObject *tdef, *file, *type, *name, *alias;
  807|     tdef = PyObject_CallMethod(m_ast"Typedef""OiOOOOi",
  808|                                file = m->py(decl->file()), decl->line(), m->cxx(),
  809|                                type = m->py(decl->type()), name = m->Tuple(decl->name()),
  810|                                alias = m->py(decl->alias()), decl->constructed()
  811|                               );
  812|     addComments(tdefdecl);
  813|     Py_DECREF(file);
  814|     Py_DECREF(type);
  815|     Py_DECREF(name);
  816|     Py_DECREF(alias);
  817|     return tdef;
  818| }
  819| 
  820| PyObject *Synopsis::Enumerator(AST::Enumerator* decl)
  821| {
  822|     Trace trace("Synopsis::addEnumerator");
  823|     PyObject *enumor, *file, *name;
  824|     enumor = PyObject_CallMethod(m_ast"Enumerator""OiOOs",
  825|                                  file = m->py(decl->file()), decl->line(), m->cxx(),
  826|                                  name = m->Tuple(decl->name()), decl->value().c_str()
  827|                                 );
  828|     addComments(enumordecl);
  829|     Py_DECREF(file);
  830|     Py_DECREF(name);
  831|     return enumor;
  832| }
  833| 
  834| PyObject *Synopsis::Enum(AST::Enum* decl)
  835| {
  836|     Trace trace("Synopsis::addEnum");
  837|     PyObject *enumor, *file, *enums, *name;
  838|     enumor = PyObject_CallMethod(m_ast"Enum""OiOOO",
  839|                                  file = m->py(decl->file()), decl->line(), m->cxx(),
  840|                                  name = m->Tuple(decl->name()), enums = m->List(decl->enumerators())
  841|                                 );
  842|     addComments(enumordecl);
  843|     Py_DECREF(file);
  844|     Py_DECREF(enums);
  845|     Py_DECREF(name);
  846|     return enumor;
  847| }
  848| 
  849| PyObject *Synopsis::Variable(AST::Variable* decl)
  850| {
  851|     Trace trace("Synopsis::addVariable");
  852|     PyObject *var, *file, *type, *name, *vtype;
  853|     var = PyObject_CallMethod(m_ast"Variable""OiOOOOi",
  854|                               file = m->py(decl->file()), decl->line(), m->cxx(),
  855|                               type = m->py(decl->type()), name = m->Tuple(decl->name()),
  856|                               vtype = m->py(decl->vtype()), decl->constructed()
  857|                              );
  858|     addComments(vardecl);
  859|     Py_DECREF(file);
  860|     Py_DECREF(type);
  861|     Py_DECREF(vtype);
  862|     Py_DECREF(name);
  863|     return var;
  864| }
  865| 
  866| PyObject *Synopsis::Const(AST::Const* decl)
  867| {
  868|     Trace trace("Synopsis::addConst");
  869|     PyObject *cons, *file, *type, *name, *ctype;
  870|     cons = PyObject_CallMethod(m_ast"Const""OiOOOOOs",
  871|                                file = m->py(decl->file()), decl->line(), m->cxx(),
  872|                                type = m->py(decl->type()), ctype = m->py(decl->ctype()),
  873|                                name = m->Tuple(decl->name()), decl->value().c_str()
  874|                               );
  875|     addComments(consdecl);
  876|     Py_DECREF(file);
  877|     Py_DECREF(type);
  878|     Py_DECREF(ctype);
  879|     Py_DECREF(name);
  880|     return cons;
  881| }
  882| 
  883| PyObject *Synopsis::Parameter(AST::Parameter* decl)
  884| {
  885|     Trace trace("Synopsis::Parameter");
  886|     PyObject *param, *pre, *post, *type, *value, *name;
  887|     param = PyObject_CallMethod(m_ast"Parameter""OOOOO",
  888|                                 pre = m->List(decl->premodifier()), type = m->py(decl->type()), 
  889|                                 post = m->List(decl->postmodifier()),
  890|                                 name = m->py(decl->name()), value = m->py(decl->value())
  891|                                );
  892|     Py_DECREF(pre);
  893|     Py_DECREF(post);
  894|     Py_DECREF(type);
  895|     Py_DECREF(value);
  896|     Py_DECREF(name);
  897|     return param;
  898| }
  899| 
  900| PyObject *Synopsis::Function(AST::Function* decl)
  901| {
  902|     Trace trace("Synopsis::addFunction");
  903|     PyObject *func, *file, *type, *name, *pre, *ret, *realname;
  904|     func = PyObject_CallMethod(m_ast"Function""OiOOOOOO",
  905|                                file = m->py(decl->file()), decl->line(), m->cxx(),
  906|                                type = m->py(decl->type()), pre = m->List(decl->premodifier()),
  907|                                ret = m->py(decl->return_type()),
  908|                                name = m->Tuple(decl->name()), realname = m->py(decl->realname())
  909|                               );
  910|     // This is necessary to prevent inf. loops in several places
  911|     m->add(declfunc);
  912|     PyObjectnew_params;
  913|     PyObjectparams = PyObject_CallMethod(func"parameters", NULL);
  914|     PyObject_CallMethod(params"extend""O"new_params = m->List(decl->parameters()));
  915|     if (decl->template_type())
  916|     {
  917|         PyObjectttype;
  918|         PyObject_CallMethod(func"set_template""O"ttype = m->py(decl->template_type()));
  919|         Py_DECREF(ttype);
  920|     }
  921|     addComments(funcdecl);
  922|     Py_DECREF(file);
  923|     Py_DECREF(type);
  924|     Py_DECREF(name);
  925|     Py_DECREF(pre);
  926|     Py_DECREF(ret);
  927|     Py_DECREF(realname);
  928|     Py_DECREF(params);
  929|     Py_DECREF(new_params);
  930|     return func;
  931| }
  932| 
  933| PyObject *Synopsis::Operation(AST::Operation* decl)
  934| {
  935|     Trace trace("Synopsis::addOperation");
  936|     PyObject *oper, *file, *type, *name, *pre, *ret, *realname;
  937|     oper = PyObject_CallMethod(m_ast"Operation""OiOOOOOO",
  938|                                file = m->py(decl->file()), decl->line(), m->cxx(),
  939|                                type = m->py(decl->type()), pre = m->List(decl->premodifier()),
  940|                                ret = m->py(decl->return_type()),
  941|                                name = m->Tuple(decl->name()), realname = m->py(decl->realname())
  942|                               );
  943|     // This is necessary to prevent inf. loops in several places
  944|     m->add(decloper);
  945|     PyObjectnew_params;
  946|     PyObjectparams = PyObject_CallMethod(oper"parameters", NULL);
  947|     PyObject_CallMethod(params"extend""O"new_params = m->List(decl->parameters()));
  948|     if (decl->template_type())
  949|     {
  950|         PyObjectttype;
  951|         PyObject_CallMethod(oper"set_template""O"ttype = m->py(decl->template_type()));
  952|         Py_DECREF(ttype);
  953|     }
  954|     addComments(operdecl);
  955|     Py_DECREF(file);
  956|     Py_DECREF(type);
  957|     Py_DECREF(name);
  958|     Py_DECREF(pre);
  959|     Py_DECREF(ret);
  960|     Py_DECREF(realname);
  961|     Py_DECREF(params);
  962|     Py_DECREF(new_params);
  963|     return oper;
  964| }
  965| 
  966| 
  967| 
  968| //
  969| // AST::Visitor methods
  970| //
  971| void Synopsis::visit_declaration(AST::Declaration* decl)
  972| {
  973|     // Assume this is a dummy declaration
  974|     if (m_filter->should_store(decl))
  975|         m->add(declDeclaration(decl));
  976| }
  977| void Synopsis::visit_macro(AST::Macro* decl)
  978| {
  979|     if (m_filter->should_store(decl))
  980|         m->add(declMacro(decl));
  981| }
  982| void Synopsis::visit_scope(AST::Scope* decl)
  983| {
  984|     if (m_filter->should_store(decl))
  985|         m->add(declScope(decl));
  986|     //else
  987|     //  m->add(decl, Forward(new AST::Forward(decl))
  988| }
  989| void Synopsis::visit_namespace(AST::Namespace* decl)
  990| {
  991|     // Namespaces are always included, because the Linker knows to combine
  992|     // them always. The exception are "local namespaces", those created to
  993|     // handle scopes created by braces in code.
  994|     if (decl->type() != "local")
  995|         m->add(declNamespace(decl));
  996| }
  997| void Synopsis::visit_class(AST::Class* decl)
  998| {
  999|     // Add if the class is in the main file, *or* if it has any members
 1000|     // declared in the main file (eg: forward declared nested classes which
 1001|     // are fully defined in this main file)
 1002|     if (m_filter->should_store(decl))
 1003|         m->add(declClass(decl));
 1004|     //else
 1005|     //    m->add(decl, Forward(new AST::Forward(decl)));
 1006| }
 1007| void Synopsis::visit_forward(AST::Forward* decl)
 1008| {
 1009|     if (m_filter->should_store(decl))
 1010|         m->add(declForward(decl));
 1011|     //else
 1012|     //    m->add(decl, Forward(new AST::Forward(decl)));
 1013| }
 1014| void Synopsis::visit_typedef(AST::Typedef* decl)
 1015| {
 1016|     if (m_filter->should_store(decl))
 1017|         m->add(declTypedef(decl));
 1018|     //else
 1019|     //    m->add(decl, Forward(new AST::Forward(decl)));
 1020| }
 1021| void Synopsis::visit_variable(AST::Variable* decl)
 1022| {
 1023|     if (m_filter->should_store(decl))
 1024|         m->add(declVariable(decl));
 1025|     //else
 1026|     //    m->add(decl, Forward(new AST::Forward(decl)));
 1027| }
 1028| void Synopsis::visit_const(AST::Const* decl)
 1029| {
 1030|     if (m_filter->should_store(decl))
 1031|         m->add(declConst(decl));
 1032|     //else
 1033|     //    m->add(decl, Forward(new AST::Forward(decl)));
 1034| }
 1035| void Synopsis::visit_enum(AST::Enum* decl)
 1036| {
 1037|     if (m_filter->should_store(decl))
 1038|         m->add(declEnum(decl));
 1039|     //else
 1040|     //    m->add(decl, Forward(new AST::Forward(decl)));
 1041| }
 1042| void Synopsis::visit_enumerator(AST::Enumerator* decl)
 1043| {
 1044|     m->add(declEnumerator(decl));
 1045| }
 1046| void Synopsis::visit_function(AST::Function* decl)
 1047| {
 1048|     if (m_filter->should_store(decl))
 1049|         m->add(declFunction(decl));
 1050|     //else
 1051|     //    m->add(decl, Forward(new AST::Forward(decl)));
 1052| }
 1053| void Synopsis::visit_operation(AST::Operation* decl)
 1054| {
 1055|     if (m_filter->should_store(decl))
 1056|         m->add(declOperation(decl));
 1057|     //else
 1058|     //    m->add(decl, Forward(new AST::Forward(decl)));
 1059| }
 1060| 
 1061| void Synopsis::visit_inheritance(AST::Inheritance* decl)
 1062| {
 1063|     m->add(declInheritance(decl));
 1064| }
 1065| void Synopsis::visit_parameter(AST::Parameter* decl)
 1066| {
 1067|     m->add(declParameter(decl));
 1068| }
 1069| void Synopsis::visit_comment(AST::Comment* decl)
 1070| {
 1071|     m->add(declComment(decl));
 1072| }
 1073| 
 1074| //
 1075| // Types::Visitor methods
 1076| //
 1077| /*void Synopsis::visitType(Types::Type* type) {
 1078|     m->add(type, this->Type(type));
 1079| }*/
 1080| void Synopsis::visit_unknown(Types::Unknown* type)
 1081| {
 1082|     m->add(typeUnknown(type));
 1083| }
 1084| void Synopsis::visit_dependent(Types::Dependent* type)
 1085| {
 1086|     m->add(typeDependent(type));
 1087| }
 1088| void Synopsis::visit_modifier(Types::Modifier* type)
 1089| {
 1090|     m->add(typeModifier(type));
 1091| }
 1092| void Synopsis::visit_array(Types::Array *type)
 1093| {
 1094|     m->add(typeArray(type));
 1095| }
 1096| /*void Synopsis::visitNamed(Types::Named* type) {
 1097|     m->add(type, Named(type));
 1098| }*/
 1099| void Synopsis::visit_base(Types::Base* type)
 1100| {
 1101|     m->add(typeBase(type));
 1102| }
 1103| void Synopsis::visit_declared(Types::Declared* type)
 1104| {
 1105|     if (!m_filter->should_store(type->declaration()))
 1106|         m->add(typeUnknown(type));
 1107|     else
 1108|         m->add(typeDeclared(type));
 1109| }
 1110| void Synopsis::visit_template_type(Types::Template* type)
 1111| {
 1112|     if (!m_filter->should_store(type->declaration()))
 1113|         m->add(typeUnknown(type));
 1114|     else
 1115|         m->add(typeTemplate(type));
 1116| }
 1117| void Synopsis::visit_parameterized(Types::Parameterized* type)
 1118| {
 1119|     m->add(typeParameterized(type));
 1120| }
 1121| void Synopsis::visit_func_ptr(Types::FuncPtr* type)
 1122| {
 1123|     m->add(typeFuncPtr(type));
 1124| }
 1125| 
 1126| 
 1127| // vim: set ts=8 sts=4 sw=4 et: