Initial work on unqualified and qualified name lookup.

This commit is contained in:
Roberto Raggi
2009-02-19 17:30:48 +01:00
parent 6178a44fc2
commit 349e2d68bf

View File

@@ -43,6 +43,8 @@
#include <Symbols.h> #include <Symbols.h>
#include <Literals.h> #include <Literals.h>
#include <vector>
#include <cstdio> #include <cstdio>
#include <cstdlib> #include <cstdlib>
#include <cassert> #include <cassert>
@@ -79,6 +81,11 @@ public:
/// Returns the binding associated with the given symbol. /// Returns the binding associated with the given symbol.
NamespaceBinding *findOrCreateNamespaceBinding(Namespace *symbol); NamespaceBinding *findOrCreateNamespaceBinding(Namespace *symbol);
NamespaceBinding *resolveNamespace(QualifiedNameId *q, unsigned index,
unsigned count);
NamespaceBinding *resolveNamespace(Name *name, bool lookAtParent = true);
/// Helpers. /// Helpers.
std::string qualifiedId() const; std::string qualifiedId() const;
void dump(); void dump();
@@ -96,6 +103,9 @@ public: // attributes
/// This binding's connections. /// This binding's connections.
Array<NamespaceBinding *> children; Array<NamespaceBinding *> children;
/// This binding's usings
Array<NamespaceBinding *> usings;
/// This binding's namespace symbols. /// This binding's namespace symbols.
Array<Namespace *> symbols; Array<Namespace *> symbols;
}; };
@@ -211,6 +221,99 @@ NamespaceBinding *NamespaceBinding::findOrCreateNamespaceBinding(Namespace *symb
return binding; return binding;
} }
static void closure(NamespaceBinding *binding, Name *name,
Array<NamespaceBinding *> *bindings)
{
for (unsigned i = 0; i < bindings->size(); ++i) {
NamespaceBinding *b = bindings->at(i);
if (b == binding)
return;
}
bindings->push_back(binding);
assert(name->isNameId());
Identifier *id = name->asNameId()->identifier();
bool ignoreUsingDirectives = false;
for (unsigned i = 0; i < binding->symbols.size(); ++i) {
Namespace *symbol = binding->symbols.at(i);
Scope *scope = symbol->members();
for (Symbol *symbol = scope->lookat(id); symbol; symbol = symbol->next()) {
if (symbol->isUsingDeclaration() || symbol->isUsingNamespaceDirective())
continue;
//printf("found declaration at %s:%d\n", symbol->fileName(), symbol->line());
// ### FIXME: ignoreUsingDirectives = true;
break;
}
}
if (ignoreUsingDirectives)
return;
for (unsigned i = 0; i < binding->usings.size(); ++i) {
NamespaceBinding *u = binding->usings.at(i);
closure(u, name, bindings);
}
}
NamespaceBinding *NamespaceBinding::resolveNamespace(Name *name, bool lookAtParent)
{
if (! name)
return 0;
else if (NameId *nameId = name->asNameId()) {
Array<NamespaceBinding *> bindings;
closure(this, nameId, &bindings);
Array<NamespaceBinding *> results;
for (unsigned i = 0; i < bindings.size(); ++i) {
NamespaceBinding *binding = bindings.at(i);
if (NamespaceBinding *b = binding->findNamespaceBinding(nameId))
results.push_back(b);
}
if (results.size() == 1)
return results.at(0);
else if (results.size() > 1) {
// ### FIXME: return 0;
return results.at(0);
}
else if (parent && lookAtParent)
return parent->resolveNamespace(name);
} else if (QualifiedNameId *q = name->asQualifiedNameId()) {
if (q->nameCount() == 1) {
assert(q->isGlobal());
return globalNamespaceBinding()->resolveNamespace(q->nameAt(0));
}
NamespaceBinding *current = this;
if (q->isGlobal())
current = globalNamespaceBinding();
current = current->resolveNamespace(q->nameAt(0));
for (unsigned i = 1; current && i < q->nameCount(); ++i)
current = current->resolveNamespace(q->nameAt(i), false);
return current;
}
return 0;
}
// ### rewrite me // ### rewrite me
std::string NamespaceBinding::qualifiedId() const std::string NamespaceBinding::qualifiedId() const
{ {
@@ -255,28 +358,38 @@ public:
Binder(); Binder();
virtual ~Binder(); virtual ~Binder();
NamespaceBinding *operator()(Symbol *symbol) NamespaceBinding *operator()(TranslationUnit *u, Namespace *globals)
{ return bind(symbol, 0); } {
TranslationUnit *previousUnit = unit;
unit = u;
NamespaceBinding *binding = bind(globals, 0);
unit = previousUnit;
return binding;
}
protected: protected:
NamespaceBinding *bind(Symbol *symbol, NamespaceBinding *binding); NamespaceBinding *bind(Symbol *symbol, NamespaceBinding *binding);
NamespaceBinding *findOrCreateNamespaceBinding(Namespace *symbol); NamespaceBinding *findOrCreateNamespaceBinding(Namespace *symbol);
NamespaceBinding *resolveNamespace(Name *name);
NamespaceBinding *switchNamespaceBinding(NamespaceBinding *binding); NamespaceBinding *switchNamespaceBinding(NamespaceBinding *binding);
using SymbolVisitor::visit; using SymbolVisitor::visit;
virtual bool visit(Namespace *); virtual bool visit(Namespace *);
virtual bool visit(UsingNamespaceDirective *);
virtual bool visit(Class *); virtual bool visit(Class *);
virtual bool visit(Function *); virtual bool visit(Function *);
virtual bool visit(Block *); virtual bool visit(Block *);
private: private:
NamespaceBinding *namespaceBinding; NamespaceBinding *namespaceBinding;
TranslationUnit *unit;
}; };
Binder::Binder() Binder::Binder()
: namespaceBinding(0) : namespaceBinding(0),
unit(0)
{ } { }
Binder::~Binder() Binder::~Binder()
@@ -299,6 +412,15 @@ NamespaceBinding *Binder::findOrCreateNamespaceBinding(Namespace *symbol)
return namespaceBinding; return namespaceBinding;
} }
NamespaceBinding *Binder::resolveNamespace(Name *name)
{
if (! namespaceBinding)
return 0;
return namespaceBinding->resolveNamespace(name);
}
NamespaceBinding *Binder::switchNamespaceBinding(NamespaceBinding *binding) NamespaceBinding *Binder::switchNamespaceBinding(NamespaceBinding *binding)
{ {
NamespaceBinding *previousBinding = namespaceBinding; NamespaceBinding *previousBinding = namespaceBinding;
@@ -319,6 +441,20 @@ bool Binder::visit(Namespace *symbol)
return false; return false;
} }
bool Binder::visit(UsingNamespaceDirective *u)
{
NamespaceBinding *resolved = resolveNamespace(u->name());
if (! resolved) {
unit->error(u->sourceLocation(), "expected namespace-name");
return false;
}
namespaceBinding->usings.push_back(resolved);
return false;
}
bool Binder::visit(Class *) bool Binder::visit(Class *)
{ return false; } { return false; }
@@ -376,7 +512,7 @@ int main(int argc, char *argv[])
// bind // bind
Binder bind; Binder bind;
NamespaceBinding *binding = bind(globalNamespace); NamespaceBinding *binding = bind(&unit, globalNamespace);
binding->dump(); binding->dump();
delete binding; delete binding;