diff dmd2/scope.c @ 758:f04dde6e882c

Added initial D2 support, D2 frontend and changes to codegen to make things compile.
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Tue, 11 Nov 2008 01:38:48 +0100
parents
children 638d16625da2
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd2/scope.c	Tue Nov 11 01:38:48 2008 +0100
@@ -0,0 +1,364 @@
+
+// Copyright (c) 1999-2005 by Digital Mars
+// All Rights Reserved
+// written by Walter Bright
+// http://www.digitalmars.com
+// License for redistribution is by either the Artistic License
+// in artistic.txt, or the GNU General Public License in gnu.txt.
+// See the included readme.txt for details.
+
+#include <stdio.h>
+#include <assert.h>
+
+#include "root.h"
+
+#include "mars.h"
+#include "init.h"
+#include "identifier.h"
+#include "attrib.h"
+#include "dsymbol.h"
+#include "scope.h"
+#include "declaration.h"
+#include "aggregate.h"
+#include "module.h"
+#include "id.h"
+
+Scope *Scope::freelist = NULL;
+
+void *Scope::operator new(size_t size)
+{
+    if (freelist)
+    {
+	Scope *s = freelist;
+	freelist = s->enclosing;
+	//printf("freelist %p\n", s);
+	assert(s->flags & SCOPEfree);
+	s->flags &= ~SCOPEfree;
+	return s;
+    }
+
+    void *p = ::operator new(size);
+    //printf("new %p\n", p);
+    return p;
+}
+
+Scope::Scope()
+{   // Create root scope
+
+    //printf("Scope::Scope() %p\n", this);
+    this->module = NULL;
+    this->scopesym = NULL;
+    this->sd = NULL;
+    this->enclosing = NULL;
+    this->parent = NULL;
+    this->sw = NULL;
+    this->tf = NULL;
+    this->tfOfTry = NULL;
+    this->tinst = NULL;
+    this->sbreak = NULL;
+    this->scontinue = NULL;
+    this->fes = NULL;
+    this->structalign = global.structalign;
+    this->func = NULL;
+    this->slabel = NULL;
+    this->linkage = LINKd;
+    this->protection = PROTpublic;
+    this->explicitProtection = 0;
+    this->stc = 0;
+    this->offset = 0;
+    this->inunion = 0;
+    this->incontract = 0;
+    this->nofree = 0;
+    this->noctor = 0;
+    this->noaccesscheck = 0;
+    this->intypeof = 0;
+    this->parameterSpecialization = 0;
+    this->callSuper = 0;
+    this->flags = 0;
+    this->anonAgg = NULL;
+    this->lastdc = NULL;
+    this->lastoffset = 0;
+    this->docbuf = NULL;
+}
+
+Scope::Scope(Scope *enclosing)
+{
+    //printf("Scope::Scope(enclosing = %p) %p\n", enclosing, this);
+    assert(!(enclosing->flags & SCOPEfree));
+    this->module = enclosing->module;
+    this->func   = enclosing->func;
+    this->parent = enclosing->parent;
+    this->scopesym = NULL;
+    this->sd = NULL;
+    this->sw = enclosing->sw;
+    this->tf = enclosing->tf;
+    this->tfOfTry = enclosing->tfOfTry;
+    this->tinst = enclosing->tinst;
+    this->sbreak = enclosing->sbreak;
+    this->scontinue = enclosing->scontinue;
+    this->fes = enclosing->fes;
+    this->structalign = enclosing->structalign;
+    this->enclosing = enclosing;
+#ifdef DEBUG
+    if (enclosing->enclosing)
+	assert(!(enclosing->enclosing->flags & SCOPEfree));
+    if (this == enclosing->enclosing)
+    {
+	printf("this = %p, enclosing = %p, enclosing->enclosing = %p\n", this, enclosing, enclosing->enclosing);
+    }
+    assert(this != enclosing->enclosing);
+#endif
+    this->slabel = NULL;
+    this->linkage = enclosing->linkage;
+    this->protection = enclosing->protection;
+    this->explicitProtection = enclosing->explicitProtection;
+    this->stc = enclosing->stc;
+    this->offset = 0;
+    this->inunion = enclosing->inunion;
+    this->incontract = enclosing->incontract;
+    this->nofree = 0;
+    this->noctor = enclosing->noctor;
+    this->noaccesscheck = enclosing->noaccesscheck;
+    this->intypeof = enclosing->intypeof;
+    this->parameterSpecialization = enclosing->parameterSpecialization;
+    this->callSuper = enclosing->callSuper;
+    this->flags = 0;
+    this->anonAgg = NULL;
+    this->lastdc = NULL;
+    this->lastoffset = 0;
+    this->docbuf = enclosing->docbuf;
+    assert(this != enclosing);
+}
+
+Scope *Scope::createGlobal(Module *module)
+{
+    Scope *sc;
+
+    sc = new Scope();
+    sc->module = module;
+    sc->scopesym = new ScopeDsymbol();
+    sc->scopesym->symtab = new DsymbolTable();
+
+    // Add top level package as member of this global scope
+    Dsymbol *m = module;
+    while (m->parent)
+	m = m->parent;
+    m->addMember(NULL, sc->scopesym, 1);
+    m->parent = NULL;			// got changed by addMember()
+
+    // Create the module scope underneath the global scope
+    sc = sc->push(module);
+    sc->parent = module;
+    return sc;
+}
+
+Scope *Scope::push()
+{
+    //printf("Scope::push()\n");
+    Scope *s = new Scope(this);
+    assert(this != s);
+    return s;
+}
+
+Scope *Scope::push(ScopeDsymbol *ss)
+{
+    //printf("Scope::push(%s)\n", ss->toChars());
+    Scope *s = push();
+    s->scopesym = ss;
+    return s;
+}
+
+Scope *Scope::pop()
+{
+    //printf("Scope::pop() %p nofree = %d\n", this, nofree);
+    Scope *enc = enclosing;
+
+    if (enclosing)
+	enclosing->callSuper |= callSuper;
+
+    if (!nofree)
+    {	enclosing = freelist;
+	freelist = this;
+	flags |= SCOPEfree;
+    }
+
+    return enc;
+}
+
+void Scope::mergeCallSuper(Loc loc, unsigned cs)
+{
+    // This does a primitive flow analysis to support the restrictions
+    // regarding when and how constructors can appear.
+    // It merges the results of two paths.
+    // The two paths are callSuper and cs; the result is merged into callSuper.
+
+    if (cs != callSuper)
+    {	int a;
+	int b;
+
+	callSuper |= cs & (CSXany_ctor | CSXlabel);
+	if (cs & CSXreturn)
+	{
+	}
+	else if (callSuper & CSXreturn)
+	{
+	    callSuper = cs | (callSuper & (CSXany_ctor | CSXlabel));
+	}
+	else
+	{
+	    a = (cs        & (CSXthis_ctor | CSXsuper_ctor)) != 0;
+	    b = (callSuper & (CSXthis_ctor | CSXsuper_ctor)) != 0;
+	    if (a != b)
+		error(loc, "one path skips constructor");
+	    callSuper |= cs;
+	}
+    }
+}
+
+Dsymbol *Scope::search(Loc loc, Identifier *ident, Dsymbol **pscopesym)
+{   Dsymbol *s;
+    Scope *sc;
+
+    //printf("Scope::search(%p, '%s')\n", this, ident->toChars());
+    if (ident == Id::empty)
+    {
+	// Look for module scope
+	for (sc = this; sc; sc = sc->enclosing)
+	{
+	    assert(sc != sc->enclosing);
+	    if (sc->scopesym)
+	    {
+		s = sc->scopesym->isModule();
+		if (s)
+		{
+		    //printf("\tfound %s.%s\n", s->parent ? s->parent->toChars() : "", s->toChars());
+		    if (pscopesym)
+			*pscopesym = sc->scopesym;
+		    return s;
+		}
+	    }
+	}
+	return NULL;
+    }
+
+    for (sc = this; sc; sc = sc->enclosing)
+    {
+	assert(sc != sc->enclosing);
+	if (sc->scopesym)
+	{
+	    //printf("\tlooking in scopesym '%s', kind = '%s'\n", sc->scopesym->toChars(), sc->scopesym->kind());
+	    s = sc->scopesym->search(loc, ident, 0);
+	    if (s)
+	    {
+		if ((global.params.warnings ||
+		    global.params.Dversion > 1) &&
+		    ident == Id::length &&
+		    sc->scopesym->isArrayScopeSymbol() &&
+		    sc->enclosing &&
+		    sc->enclosing->search(loc, ident, NULL))
+		{
+            // WTF ?
+		    if (global.params.warnings)
+			fprintf(stdmsg, "warning - ");
+		    error(s->loc, "array 'length' hides other 'length' name in outer scope");
+		}
+
+		//printf("\tfound %s.%s, kind = '%s'\n", s->parent ? s->parent->toChars() : "", s->toChars(), s->kind());
+		if (pscopesym)
+		    *pscopesym = sc->scopesym;
+		return s;
+	    }
+	}
+    }
+
+    return NULL;
+}
+
+Dsymbol *Scope::insert(Dsymbol *s)
+{   Scope *sc;
+
+    for (sc = this; sc; sc = sc->enclosing)
+    {
+	//printf("\tsc = %p\n", sc);
+	if (sc->scopesym)
+	{
+	    //printf("\t\tsc->scopesym = %p\n", sc->scopesym);
+	    if (!sc->scopesym->symtab)
+		sc->scopesym->symtab = new DsymbolTable();
+	    return sc->scopesym->symtab->insert(s);
+	}
+    }
+    assert(0);
+    return NULL;
+}
+
+/********************************************
+ * Search enclosing scopes for ClassDeclaration.
+ */
+
+ClassDeclaration *Scope::getClassScope()
+{   Scope *sc;
+
+    for (sc = this; sc; sc = sc->enclosing)
+    {
+	ClassDeclaration *cd;
+	
+	if (sc->scopesym)
+	{
+	    cd = sc->scopesym->isClassDeclaration();
+	    if (cd)
+		return cd;
+	}
+    }
+    return NULL;
+}
+
+/********************************************
+ * Search enclosing scopes for ClassDeclaration.
+ */
+
+AggregateDeclaration *Scope::getStructClassScope()
+{   Scope *sc;
+
+    for (sc = this; sc; sc = sc->enclosing)
+    {
+	AggregateDeclaration *ad;
+	
+	if (sc->scopesym)
+	{
+	    ad = sc->scopesym->isClassDeclaration();
+	    if (ad)
+		return ad;
+	    else
+	    {	ad = sc->scopesym->isStructDeclaration();
+		if (ad)
+		    return ad;
+	    }
+	}
+    }
+    return NULL;
+}
+
+/*******************************************
+ * For TemplateDeclarations, we need to remember the Scope
+ * where it was declared. So mark the Scope as not
+ * to be free'd.
+ */
+
+void Scope::setNoFree()
+{   Scope *sc;
+    //int i = 0;
+
+    //printf("Scope::setNoFree(this = %p)\n", this);
+    for (sc = this; sc; sc = sc->enclosing)
+    {
+	//printf("\tsc = %p\n", sc);
+	sc->nofree = 1;
+
+	assert(!(flags & SCOPEfree));
+	//assert(sc != sc->enclosing);
+	//assert(!sc->enclosing || sc != sc->enclosing->enclosing);
+	//if (++i == 10)
+	    //assert(0);
+    }
+}