Synopsis - Cross-Reference

File: src/Synopsis/SymbolLookup/Walker.cc
  1//
  2// Copyright (C) 2004 Stefan Seefeld
  3// All rights reserved.
  4// Licensed to the public under the terms of the GNU LGPL (>= 2),
  5// see the file COPYING for details.
  6//
  7#include <Synopsis/SymbolLookup/Walker.hh>
  8#include <Synopsis/PTree/Lists.hh>
  9#include <Synopsis/PTree/TypeVisitor.hh>
 10#include <Synopsis/Trace.hh>
 11#include <Synopsis/PTree/Display.hh>
 12#include <Synopsis/SymbolLookup/Scopes.hh>
 13
 14using namespace Synopsis;
 15using namespace SymbolLookup;
 16
 17Walker::Walker(Scope *scope)
 18{
 19  Trace trace("Walker::Walker", Trace::SYMBOLLOOKUP);
 20  my_scopes.push(scope->ref());
 21}
 22
 23Walker::~Walker() 
 24{
 25  Trace trace("Walker::~Walker", Trace::SYMBOLLOOKUP);
 26  Scope *scope = my_scopes.top();
 27  scope->unref();
 28  my_scopes.pop();
 29}
 30
 31void Walker::visit(PTree::List *node)
 32{
 33  Trace trace("Walker::visit(List)", Trace::SYMBOLLOOKUP);
 34  if (node->car()) node->car()->accept(this);
 35  if (node->cdr()) node->cdr()->accept(this);
 36}
 37
 38void Walker::visit(PTree::Block *node)
 39{
 40  Trace trace("Walker::visit(Block)", Trace::SYMBOLLOOKUP);
 41  Scope *scope = my_scopes.top()->find_scope(node);
 42  if (!scope)
 43  {
 44    // Not all Blocks represent a scope...
 45    visit_block(node);
 46  }
 47  else
 48  {
 49    scope->ref();
 50    my_scopes.push(scope);
 51    visit_block(node);
 52    leave_scope();
 53  }  
 54}
 55
 56void Walker::visit(PTree::TemplateDecl *tdecl)
 57{
 58  Trace trace("Walker::visit(TemplateDecl)", Trace::SYMBOLLOOKUP);
 59  traverse_parameters(tdecl);
 60  // If we are in a template template parameter, the following
 61  // is just the 'class' keyword.
 62  // Else it is a Declaration, which we want to traverse.
 63  PTree::Node *decl = PTree::nth(tdecl, 4);
 64  if (!decl->is_atom()) decl->accept(this);
 65  else
 66  {
 67    std::cout << "length " << PTree::length(tdecl) << std::endl;
 68  }
 69}
 70
 71void Walker::visit(PTree::NamespaceSpec *spec)
 72{
 73  Trace trace("Walker::visit(NamespaceSpec)", Trace::SYMBOLLOOKUP);
 74  traverse_body(spec);
 75}
 76
 77void Walker::visit(PTree::FunctionDefinition *def)
 78{
 79  Trace trace("Walker::visit(FunctionDefinition)", Trace::SYMBOLLOOKUP);
 80  PTree::Node *decl = PTree::third(def);
 81  visit(static_cast<PTree::Declarator *>(decl)); // visit the declarator
 82  traverse_body(def);
 83}
 84
 85void Walker::visit(PTree::ClassSpec *spec)
 86{
 87  Trace trace("Walker::visit(ClassSpec)", Trace::SYMBOLLOOKUP);
 88  traverse_body(spec);
 89}
 90
 91void Walker::visit(PTree::DotMemberExpr *)
 92{
 93  Trace trace("Walker::visit(DotMemberExpr)", Trace::SYMBOLLOOKUP);
 94  std::cout << "Sorry: dot member expression (<postfix>.<name>) not yet supported" << std::endl;
 95}
 96
 97void Walker::visit(PTree::ArrowMemberExpr *)
 98{
 99  Trace trace("Walker::visit(ArrowMemberExpr)", Trace::SYMBOLLOOKUP);
100  std::cout << "Sorry: arrow member expression (<postfix>-><name>) not yet supported" << std::endl;
101}
102
103void Walker::traverse_body(PTree::NamespaceSpec *spec)
104{
105  Trace trace("Walker::traverse_body(NamespaceSpec)", Trace::SYMBOLLOOKUP);
106  Scope *scope = my_scopes.top()->find_scope(spec);
107  assert(scope);
108  scope->ref();
109  my_scopes.push(scope);
110  PTree::tail(spec, 2)->car()->accept(this);
111  leave_scope();
112}
113
114void Walker::traverse_body(PTree::ClassSpec *spec)
115{
116  Trace trace("Walker::traverse_body(ClassSpec)", Trace::SYMBOLLOOKUP);
117  if (PTree::ClassBody *body = spec->body())
118  {
119    Scope *scope = my_scopes.top()->find_scope(spec);
120    assert(scope);
121    scope->ref();
122    my_scopes.push(scope);
123    body->accept(this);
124    leave_scope();
125  }
126}
127
128void Walker::traverse_parameters(PTree::TemplateDecl *decl)
129{
130  Trace trace("Walker::traverse_body(TemplateDecl)", Trace::SYMBOLLOOKUP);
131  Scope *scope = my_scopes.top()->find_scope(decl);
132  scope->ref();
133  my_scopes.push(scope);
134  // list of template parameters (TypeParameter or ParameterDeclaration)
135  PTree::third(decl)->accept(this);
136  leave_scope();
137}
138
139void Walker::traverse_body(PTree::FunctionDefinition *def)
140{
141  Trace trace("Walker::traverse_body(FunctionDefinition)", Trace::SYMBOLLOOKUP);
142  PTree::Node *decl = PTree::third(def);
143
144  Scope *scope = my_scopes.top();
145  PTree::Encoding name = decl->encoded_name();
146  if (name.is_qualified())
147  {
148    SymbolSet symbols = scope->lookup(name, Scope::DECLARATION);
149    assert(!symbols.empty());
150    // FIXME: We need type analysis / overload resolution
151    //        here to take the right symbol / scope.
152    FunctionName const *symbol = dynamic_cast<FunctionName const *>(*symbols.begin());
153    assert(symbol);
154    scope = symbol->as_scope();
155  }
156  else
157    scope = my_scopes.top()->find_scope(def);
158  assert(scope);
159  scope->ref();
160  my_scopes.push(scope);
161  visit_block(static_cast<PTree::Block *>(PTree::nth(def, 3)));
162  leave_scope();
163}
164
165void Walker::visit_block(PTree::Block *node)
166{
167  Trace trace("Walker::visit_block(Block)", Trace::SYMBOLLOOKUP);
168  visit(static_cast<PTree::List *>(node));
169}
170
171void Walker::leave_scope()
172{
173  Trace trace("Walker::leave_scope", Trace::SYMBOLLOOKUP);
174  Scope *top = my_scopes.top();
175  my_scopes.pop();
176  top->unref();
177}