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

Initial work on the binder.

parent 01faad42
No related branches found
No related tags found
No related merge requests found
QT = QT =
macx:CONFIG -= app_bundle macx:CONFIG -= app_bundle
TARGET = cplusplus0 TARGET = cplusplus0
*-g++*:QMAKE_CXXFLAGS += -fno-rtti \ *-g++*:QMAKE_CXXFLAGS += -fno-rtti \
-fno-exceptions \ -fno-exceptions
-O2
include(../../../src/shared/cplusplus/cplusplus.pri) include(../../../src/shared/cplusplus/cplusplus.pri)
# Input
SOURCES += main.cpp \
LinkedNamespace.cpp
unix { unix {
debug:OBJECTS_DIR = $${OUT_PWD}/.obj/debug-shared debug:OBJECTS_DIR = $${OUT_PWD}/.obj/debug-shared
release:OBJECTS_DIR = $${OUT_PWD}/.obj/release-shared release:OBJECTS_DIR = $${OUT_PWD}/.obj/release-shared
...@@ -17,4 +17,6 @@ unix { ...@@ -17,4 +17,6 @@ unix {
RCC_DIR = $${OUT_PWD}/.rcc/ RCC_DIR = $${OUT_PWD}/.rcc/
UI_DIR = $${OUT_PWD}/.uic/ UI_DIR = $${OUT_PWD}/.uic/
} }
HEADERS += LinkedNamespace.h
# Input
SOURCES += main.cpp
...@@ -38,6 +38,10 @@ ...@@ -38,6 +38,10 @@
#include <Semantic.h> #include <Semantic.h>
#include <TranslationUnit.h> #include <TranslationUnit.h>
#include <PrettyPrinter.h> #include <PrettyPrinter.h>
#include <Symbolvisitor.h>
#include <Names.h>
#include <Symbols.h>
#include <Literals.h>
#include <cstdio> #include <cstdio>
#include <cstdlib> #include <cstdlib>
...@@ -46,6 +50,288 @@ ...@@ -46,6 +50,288 @@
#include <fstream> #include <fstream>
#include <sstream> #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() static int usage()
{ {
std::cerr << "cplusplus0: no input files" << std::endl; std::cerr << "cplusplus0: no input files" << std::endl;
...@@ -82,11 +368,17 @@ int main(int argc, char *argv[]) ...@@ -82,11 +368,17 @@ int main(int argc, char *argv[])
TranslationUnitAST *ast = unit.ast()->asTranslationUnit(); TranslationUnitAST *ast = unit.ast()->asTranslationUnit();
assert(ast != 0); assert(ast != 0);
Scope globalScope; Namespace *globalNamespace = control.newNamespace(0, 0); // namespace symbol for `::'
Semantic sem(&control); Semantic sem(&control);
for (DeclarationAST *decl = ast->declarations; decl; decl = decl->next) { 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; return EXIT_SUCCESS;
} }
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