forked from qt-creator/qt-creator
Initial work on unqualified and qualified name lookup.
This commit is contained in:
@@ -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;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user