summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Raggi <roberto.raggi@nokia.com>2009-02-19 12:09:38 +0100
committerRoberto Raggi <roberto.raggi@nokia.com>2009-02-19 12:21:11 +0100
commit764379deb72cb07d6704327d9b2577075b0f35d9 (patch)
treeae0b721501549c782efd990bca902ac1d4dac77b
parent01faad422841f17517ae70e62ada65825b0a370a (diff)
downloadqt-creator-764379deb72cb07d6704327d9b2577075b0f35d9.tar.gz
Initial work on the binder.
-rw-r--r--tests/manual/binding/binding.pro14
-rw-r--r--tests/manual/binding/main.cpp296
2 files changed, 302 insertions, 8 deletions
diff --git a/tests/manual/binding/binding.pro b/tests/manual/binding/binding.pro
index 56741107c2..2ac26f337a 100644
--- a/tests/manual/binding/binding.pro
+++ b/tests/manual/binding/binding.pro
@@ -1,14 +1,14 @@
QT =
+
macx:CONFIG -= app_bundle
+
TARGET = cplusplus0
+
*-g++*:QMAKE_CXXFLAGS += -fno-rtti \
- -fno-exceptions \
- -O2
+ -fno-exceptions
+
include(../../../src/shared/cplusplus/cplusplus.pri)
-# Input
-SOURCES += main.cpp \
- LinkedNamespace.cpp
unix {
debug:OBJECTS_DIR = $${OUT_PWD}/.obj/debug-shared
release:OBJECTS_DIR = $${OUT_PWD}/.obj/release-shared
@@ -17,4 +17,6 @@ unix {
RCC_DIR = $${OUT_PWD}/.rcc/
UI_DIR = $${OUT_PWD}/.uic/
}
-HEADERS += LinkedNamespace.h
+
+# Input
+SOURCES += main.cpp
diff --git a/tests/manual/binding/main.cpp b/tests/manual/binding/main.cpp
index 451d7f1420..8e889b6b51 100644
--- a/tests/manual/binding/main.cpp
+++ b/tests/manual/binding/main.cpp
@@ -38,6 +38,10 @@
#include <Semantic.h>
#include <TranslationUnit.h>
#include <PrettyPrinter.h>
+#include <Symbolvisitor.h>
+#include <Names.h>
+#include <Symbols.h>
+#include <Literals.h>
#include <cstdio>
#include <cstdlib>
@@ -46,6 +50,288 @@
#include <fstream>
#include <sstream>
+
+////////////////////////////////////////////////////////////////////////////////
+// NamespaceBinding
+////////////////////////////////////////////////////////////////////////////////
+
+class NamespaceBinding
+{
+public:
+ /// Constructs a binding with the given parent.
+ NamespaceBinding(NamespaceBinding *parent = 0);
+
+ /// Destroys the binding.
+ ~NamespaceBinding();
+
+ /// Returns this binding's name.
+ NameId *name() const;
+
+ /// Returns this binding's identifier.
+ Identifier *identifier() const;
+
+ /// Returns the binding for the global namespace (aka ::).
+ NamespaceBinding *globalNamespaceBinding();
+
+ /// Returns the binding for the given namespace symbol.
+ NamespaceBinding *findNamespaceBinding(Name *name);
+
+ /// Returns the binding associated with the given symbol.
+ NamespaceBinding *findOrCreateNamespaceBinding(Namespace *symbol);
+
+ /// Helpers.
+ std::string qualifiedId() const;
+ void dump();
+
+private:
+ NamespaceBinding *findNamespaceBindingForNameId(NameId *name);
+
+public: // attributes
+ /// This binding's parent.
+ NamespaceBinding *parent;
+
+ /// Binding for anonymous namespace symbols.
+ NamespaceBinding *anonymousNamespaceBinding;
+
+ /// This binding's connections.
+ Array<NamespaceBinding *> children;
+
+ /// This binding's namespace symbols.
+ Array<Namespace *> symbols;
+};
+
+NamespaceBinding::NamespaceBinding(NamespaceBinding *parent)
+ : parent(parent),
+ anonymousNamespaceBinding(0)
+{
+ if (parent)
+ parent->children.push_back(this);
+}
+
+NamespaceBinding::~NamespaceBinding()
+{
+ for (unsigned i = 0; i < children.size(); ++i) {
+ NamespaceBinding *binding = children.at(i);
+
+ delete binding;
+ }
+}
+
+NameId *NamespaceBinding::name() const
+{
+ if (symbols.size()) {
+ if (Name *name = symbols.at(0)->name()) {
+ NameId *nameId = name->asNameId();
+ assert(nameId != 0);
+
+ return nameId;
+ }
+ }
+
+ return 0;
+}
+
+Identifier *NamespaceBinding::identifier() const
+{
+ if (NameId *nameId = name())
+ return nameId->identifier();
+
+ return 0;
+}
+
+NamespaceBinding *NamespaceBinding::globalNamespaceBinding()
+{
+ NamespaceBinding *it = this;
+
+ for (; it; it = it->parent) {
+ if (! it->parent)
+ break;
+ }
+
+ return it;
+}
+
+NamespaceBinding *NamespaceBinding::findNamespaceBinding(Name *name)
+{
+ if (! name)
+ return anonymousNamespaceBinding;
+
+ else if (NameId *nameId = name->asNameId())
+ return findNamespaceBindingForNameId(nameId);
+
+ // invalid binding
+ return 0;
+}
+
+NamespaceBinding *NamespaceBinding::findNamespaceBindingForNameId(NameId *name)
+{
+ for (unsigned i = 0; i < children.size(); ++i) {
+ NamespaceBinding *binding = children.at(i);
+ Name *bindingName = binding->name();
+
+ if (! bindingName)
+ continue;
+
+ if (NameId *bindingNameId = bindingName->asNameId()) {
+ if (name->isEqualTo(bindingNameId))
+ return binding;
+ }
+ }
+
+ return 0;
+}
+
+NamespaceBinding *NamespaceBinding::findOrCreateNamespaceBinding(Namespace *symbol)
+{
+ if (NamespaceBinding *binding = findNamespaceBinding(symbol->name())) {
+ unsigned index = 0;
+
+ for (; index < binding->symbols.size(); ++index) {
+ Namespace *ns = binding->symbols.at(index);
+
+ if (ns == symbol)
+ break;
+ }
+
+ if (index == binding->symbols.size())
+ binding->symbols.push_back(symbol);
+
+ return binding;
+ }
+
+ NamespaceBinding *binding = new NamespaceBinding(this);
+ binding->symbols.push_back(symbol);
+
+ if (! symbol->name()) {
+ assert(! anonymousNamespaceBinding);
+
+ anonymousNamespaceBinding = binding;
+ }
+
+ return binding;
+}
+
+// ### rewrite me
+std::string NamespaceBinding::qualifiedId() const
+{
+ if (! parent)
+ return "<root>";
+
+ std::string s;
+
+ s.append(parent->qualifiedId());
+ s.append("::");
+
+ if (Identifier *id = identifier())
+ s.append(id->chars(), id->size());
+
+ else
+ s.append("<anonymous>");
+
+ return s;
+}
+
+void NamespaceBinding::dump()
+{
+ static int depth;
+
+ std::cout << std::string(depth, ' ') << qualifiedId()
+ << " # " << symbols.size() << std::endl;
+ ++depth;
+
+ for (unsigned i = 0; i < children.size(); ++i)
+ children.at(i)->dump();
+
+ --depth;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Binder
+////////////////////////////////////////////////////////////////////////////////
+
+class Binder: protected SymbolVisitor
+{
+public:
+ Binder();
+ virtual ~Binder();
+
+ NamespaceBinding *operator()(Symbol *symbol)
+ { return bind(symbol, 0); }
+
+protected:
+ NamespaceBinding *bind(Symbol *symbol, NamespaceBinding *binding);
+ NamespaceBinding *findOrCreateNamespaceBinding(Namespace *symbol);
+
+ NamespaceBinding *switchNamespaceBinding(NamespaceBinding *binding);
+
+ using SymbolVisitor::visit;
+
+ virtual bool visit(Namespace *);
+ virtual bool visit(Class *);
+ virtual bool visit(Function *);
+ virtual bool visit(Block *);
+
+private:
+ NamespaceBinding *namespaceBinding;
+};
+
+Binder::Binder()
+ : namespaceBinding(0)
+{ }
+
+Binder::~Binder()
+{ }
+
+NamespaceBinding *Binder::bind(Symbol *symbol, NamespaceBinding *binding)
+{
+ NamespaceBinding *previousBinding = switchNamespaceBinding(binding);
+ accept(symbol);
+ return switchNamespaceBinding(previousBinding);
+}
+
+NamespaceBinding *Binder::findOrCreateNamespaceBinding(Namespace *symbol)
+{
+ if (namespaceBinding)
+ return namespaceBinding->findOrCreateNamespaceBinding(symbol);
+
+ namespaceBinding = new NamespaceBinding;
+ namespaceBinding->symbols.push_back(symbol);
+ return namespaceBinding;
+}
+
+NamespaceBinding *Binder::switchNamespaceBinding(NamespaceBinding *binding)
+{
+ NamespaceBinding *previousBinding = namespaceBinding;
+ namespaceBinding = binding;
+ return previousBinding;
+}
+
+bool Binder::visit(Namespace *symbol)
+{
+ NamespaceBinding *binding = findOrCreateNamespaceBinding(symbol);
+
+ for (unsigned i = 0; i < symbol->memberCount(); ++i) {
+ Symbol *member = symbol->memberAt(i);
+
+ bind(member, binding);
+ }
+
+ return false;
+}
+
+bool Binder::visit(Class *)
+{ return false; }
+
+bool Binder::visit(Function *)
+{ return false; }
+
+bool Binder::visit(Block *)
+{ return false; }
+
+////////////////////////////////////////////////////////////////////////////////
+// Entry point
+////////////////////////////////////////////////////////////////////////////////
+
static int usage()
{
std::cerr << "cplusplus0: no input files" << std::endl;
@@ -82,11 +368,17 @@ int main(int argc, char *argv[])
TranslationUnitAST *ast = unit.ast()->asTranslationUnit();
assert(ast != 0);
- Scope globalScope;
+ Namespace *globalNamespace = control.newNamespace(0, 0); // namespace symbol for `::'
Semantic sem(&control);
for (DeclarationAST *decl = ast->declarations; decl; decl = decl->next) {
- sem.check(decl, &globalScope);
+ sem.check(decl, globalNamespace->members());
}
+ // bind
+ Binder bind;
+ NamespaceBinding *binding = bind(globalNamespace);
+ binding->dump();
+ delete binding;
+
return EXIT_SUCCESS;
}