Commit 349e2d68 authored by Roberto Raggi's avatar Roberto Raggi

Initial work on unqualified and qualified name lookup.

parent 6178a44f
......@@ -43,6 +43,8 @@
#include <Symbols.h>
#include <Literals.h>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include <cassert>
......@@ -79,6 +81,11 @@ public:
/// Returns the binding associated with the given symbol.
NamespaceBinding *findOrCreateNamespaceBinding(Namespace *symbol);
NamespaceBinding *resolveNamespace(QualifiedNameId *q, unsigned index,
unsigned count);
NamespaceBinding *resolveNamespace(Name *name, bool lookAtParent = true);
/// Helpers.
std::string qualifiedId() const;
void dump();
......@@ -96,6 +103,9 @@ public: // attributes
/// This binding's connections.
Array<NamespaceBinding *> children;
/// This binding's usings
Array<NamespaceBinding *> usings;
/// This binding's namespace symbols.
Array<Namespace *> symbols;
};
......@@ -211,6 +221,99 @@ NamespaceBinding *NamespaceBinding::findOrCreateNamespaceBinding(Namespace *symb
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
std::string NamespaceBinding::qualifiedId() const
{
......@@ -255,28 +358,38 @@ public:
Binder();
virtual ~Binder();
NamespaceBinding *operator()(Symbol *symbol)
{ return bind(symbol, 0); }
NamespaceBinding *operator()(TranslationUnit *u, Namespace *globals)
{
TranslationUnit *previousUnit = unit;
unit = u;
NamespaceBinding *binding = bind(globals, 0);
unit = previousUnit;
return binding;
}
protected:
NamespaceBinding *bind(Symbol *symbol, NamespaceBinding *binding);
NamespaceBinding *findOrCreateNamespaceBinding(Namespace *symbol);
NamespaceBinding *resolveNamespace(Name *name);
NamespaceBinding *switchNamespaceBinding(NamespaceBinding *binding);
using SymbolVisitor::visit;
virtual bool visit(Namespace *);
virtual bool visit(UsingNamespaceDirective *);
virtual bool visit(Class *);
virtual bool visit(Function *);
virtual bool visit(Block *);
private:
NamespaceBinding *namespaceBinding;
TranslationUnit *unit;
};
Binder::Binder()
: namespaceBinding(0)
: namespaceBinding(0),
unit(0)
{ }
Binder::~Binder()
......@@ -299,6 +412,15 @@ NamespaceBinding *Binder::findOrCreateNamespaceBinding(Namespace *symbol)
return namespaceBinding;
}
NamespaceBinding *Binder::resolveNamespace(Name *name)
{
if (! namespaceBinding)
return 0;
return namespaceBinding->resolveNamespace(name);
}
NamespaceBinding *Binder::switchNamespaceBinding(NamespaceBinding *binding)
{
NamespaceBinding *previousBinding = namespaceBinding;
......@@ -319,6 +441,20 @@ bool Binder::visit(Namespace *symbol)
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 *)
{ return false; }
......@@ -376,7 +512,7 @@ int main(int argc, char *argv[])
// bind
Binder bind;
NamespaceBinding *binding = bind(globalNamespace);
NamespaceBinding *binding = bind(&unit, globalNamespace);
binding->dump();
delete binding;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment