Skip to content
Snippets Groups Projects
Commit 349e2d68 authored by Roberto Raggi's avatar Roberto Raggi
Browse files

Initial work on unqualified and qualified name lookup.

parent 6178a44f
No related branches found
No related tags found
No related merge requests found
......@@ -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;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment