blob: dc785418db8e154a7fc8e38467c820a34224a460 [file] [log] [blame]
// Compiler implementation of the D programming language
// Copyright: Copyright (C) 2014-2019 by The D Language Foundation, All Rights Reserved
// Authors: Walter Bright, http://www.digitalmars.com
// License: http://boost.org/LICENSE_1_0.txt
// Source: https://github.com/D-Programming-Language/dmd/blob/master/src/nspace.c
#include "root/dsystem.h"
#include "mars.h"
#include "dsymbol.h"
#include "nspace.h"
#include "identifier.h"
#include "scope.h"
/* This implements namespaces.
*/
Nspace::Nspace(Loc loc, Identifier *ident, Dsymbols *members, bool mangleOnly)
: ScopeDsymbol(ident)
{
//printf("Nspace::Nspace(ident = %s)\n", ident->toChars());
this->loc = loc;
this->members = members;
// Determines whether the symbol for this namespace should be included in
// the symbol table.
this->mangleOnly = mangleOnly;
}
Dsymbol *Nspace::syntaxCopy(Dsymbol *)
{
Nspace *ns = new Nspace(loc, ident, NULL, mangleOnly);
return ScopeDsymbol::syntaxCopy(ns);
}
void Nspace::addMember(Scope *sc, ScopeDsymbol *sds)
{
if (mangleOnly)
parent = sds;
else
ScopeDsymbol::addMember(sc, sds);
if (members)
{
if (!symtab)
symtab = new DsymbolTable();
// The namespace becomes 'imported' into the enclosing scope
for (Scope *sce = sc; 1; sce = sce->enclosing)
{
ScopeDsymbol *sds2 = sce->scopesym;
if (sds2)
{
sds2->importScope(this, Prot(PROTpublic));
break;
}
}
assert(sc);
sc = sc->push(this);
sc->linkage = LINKcpp; // namespaces default to C++ linkage
sc->parent = this;
for (size_t i = 0; i < members->dim; i++)
{
Dsymbol *s = (*members)[i];
//printf("add %s to scope %s\n", s->toChars(), toChars());
s->addMember(sc, this);
}
sc->pop();
}
}
void Nspace::setScope(Scope *sc)
{
ScopeDsymbol::setScope(sc);
if (members)
{
assert(sc);
sc = sc->push(this);
sc->linkage = LINKcpp; // namespaces default to C++ linkage
sc->parent = this;
for (size_t i = 0; i < members->dim; i++)
{
Dsymbol *s = (*members)[i];
s->setScope(sc);
}
sc->pop();
}
}
void Nspace::semantic(Scope *sc)
{
if (semanticRun != PASSinit)
return;
if (_scope)
{
sc = _scope;
_scope = NULL;
}
if (!sc)
return;
semanticRun = PASSsemantic;
parent = sc->parent;
if (members)
{
assert(sc);
sc = sc->push(this);
sc->linkage = LINKcpp; // note that namespaces imply C++ linkage
sc->parent = this;
for (size_t i = 0; i < members->dim; i++)
{
Dsymbol *s = (*members)[i];
s->importAll(sc);
}
for (size_t i = 0; i < members->dim; i++)
{
Dsymbol *s = (*members)[i];
s->semantic(sc);
}
sc->pop();
}
semanticRun = PASSsemanticdone;
}
void Nspace::semantic2(Scope *sc)
{
if (semanticRun >= PASSsemantic2)
return;
semanticRun = PASSsemantic2;
if (members)
{
assert(sc);
sc = sc->push(this);
sc->linkage = LINKcpp;
for (size_t i = 0; i < members->dim; i++)
{
Dsymbol *s = (*members)[i];
s->semantic2(sc);
}
sc->pop();
}
}
void Nspace::semantic3(Scope *sc)
{
if (semanticRun >= PASSsemantic3)
return;
semanticRun = PASSsemantic3;
if (members)
{
sc = sc->push(this);
sc->linkage = LINKcpp;
for (size_t i = 0; i < members->dim; i++)
{
Dsymbol *s = (*members)[i];
s->semantic3(sc);
}
sc->pop();
}
}
const char *Nspace::kind() const
{
return "namespace";
}
bool Nspace::oneMember(Dsymbol **ps, Identifier *ident)
{
return Dsymbol::oneMember(ps, ident);
}
Dsymbol *Nspace::search(const Loc &loc, Identifier *ident, int flags)
{
//printf("%s::Nspace::search('%s')\n", toChars(), ident->toChars());
if (_scope && !symtab)
semantic(_scope);
if (!members || !symtab) // opaque or semantic() is not yet called
{
error("is forward referenced when looking for '%s'", ident->toChars());
return NULL;
}
return ScopeDsymbol::search(loc, ident, flags);
}
int Nspace::apply(Dsymbol_apply_ft_t fp, void *param)
{
if (members)
{
for (size_t i = 0; i < members->dim; i++)
{
Dsymbol *s = (*members)[i];
if (s)
{
if (s->apply(fp, param))
return 1;
}
}
}
return 0;
}
bool Nspace::hasPointers()
{
//printf("Nspace::hasPointers() %s\n", toChars());
if (members)
{
for (size_t i = 0; i < members->dim; i++)
{
Dsymbol *s = (*members)[i];
//printf(" s = %s %s\n", s->kind(), s->toChars());
if (s->hasPointers())
{
return true;
}
}
}
return false;
}
void Nspace::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion)
{
//printf("Nspace::setFieldOffset() %s\n", toChars());
if (_scope) // if fwd reference
semantic(NULL); // try to resolve it
if (members)
{
for (size_t i = 0; i < members->dim; i++)
{
Dsymbol *s = (*members)[i];
//printf("\t%s\n", s->toChars());
s->setFieldOffset(ad, poffset, isunion);
}
}
}