
/* Compiler implementation of the D programming language
 * Copyright (C) 1999-2019 by The D Language Foundation, All Rights Reserved
 * written by Walter Bright
 * http://www.digitalmars.com
 * Distributed under the Boost Software License, Version 1.0.
 * http://www.boost.org/LICENSE_1_0.txt
 * https://github.com/D-Programming-Language/dmd/blob/master/src/version.c
 */

#include "root/dsystem.h"
#include "root/root.h"

#include "identifier.h"
#include "dsymbol.h"
#include "cond.h"
#include "version.h"
#include "module.h"

void checkReserved(Loc loc, const char *ident);

/* ================================================== */

/* DebugSymbol's happen for statements like:
 *      debug = identifier;
 *      debug = integer;
 */

DebugSymbol::DebugSymbol(Loc loc, Identifier *ident)
    : Dsymbol(ident)
{
    this->loc = loc;
}

DebugSymbol::DebugSymbol(Loc loc, unsigned level)
    : Dsymbol()
{
    this->level = level;
    this->loc = loc;
}

const char *DebugSymbol::toChars()
{
    if (ident)
        return ident->toChars();
    else
    {
        OutBuffer buf;
        buf.printf("%d", level);
        return buf.extractString();
    }
}

Dsymbol *DebugSymbol::syntaxCopy(Dsymbol *s)
{
    assert(!s);
    DebugSymbol *ds = new DebugSymbol(loc, ident);
    ds->level = level;
    return ds;
}

void DebugSymbol::addMember(Scope *, ScopeDsymbol *sds)
{
    //printf("DebugSymbol::addMember('%s') %s\n", sds->toChars(), toChars());
    Module *m = sds->isModule();

    // Do not add the member to the symbol table,
    // just make sure subsequent debug declarations work.
    if (ident)
    {
        if (!m)
        {
            error("declaration must be at module level");
            errors = true;
        }
        else
        {
            if (findCondition(m->debugidsNot, ident))
            {
                error("defined after use");
                errors = true;
            }
            if (!m->debugids)
                m->debugids = new Strings();
            m->debugids->push(ident->toChars());
        }
    }
    else
    {
        if (!m)
        {
            error("level declaration must be at module level");
            errors = true;
        }
        else
            m->debuglevel = level;
    }
}

void DebugSymbol::semantic(Scope *)
{
    //printf("DebugSymbol::semantic() %s\n", toChars());
    if (semanticRun < PASSsemanticdone)
        semanticRun = PASSsemanticdone;
}

const char *DebugSymbol::kind() const
{
    return "debug";
}

/* ================================================== */

/* VersionSymbol's happen for statements like:
 *      version = identifier;
 *      version = integer;
 */

VersionSymbol::VersionSymbol(Loc loc, Identifier *ident)
    : Dsymbol(ident)
{
    this->loc = loc;
}

VersionSymbol::VersionSymbol(Loc loc, unsigned level)
    : Dsymbol()
{
    this->level = level;
    this->loc = loc;
}

const char *VersionSymbol::toChars()
{
    if (ident)
        return ident->toChars();
    else
    {
        OutBuffer buf;
        buf.printf("%d", level);
        return buf.extractString();
    }
}

Dsymbol *VersionSymbol::syntaxCopy(Dsymbol *s)
{
    assert(!s);
    VersionSymbol *ds = ident ? new VersionSymbol(loc, ident)
                              : new VersionSymbol(loc, level);
    return ds;
}

void VersionSymbol::addMember(Scope *, ScopeDsymbol *sds)
{
    //printf("VersionSymbol::addMember('%s') %s\n", sds->toChars(), toChars());
    Module *m = sds->isModule();

    // Do not add the member to the symbol table,
    // just make sure subsequent debug declarations work.
    if (ident)
    {
        checkReserved(loc, ident->toChars());
        if (!m)
        {
            error("declaration must be at module level");
            errors = true;
        }
        else
        {
            if (findCondition(m->versionidsNot, ident))
            {
                error("defined after use");
                errors = true;
            }
            if (!m->versionids)
                m->versionids = new Strings();
            m->versionids->push(ident->toChars());
        }
    }
    else
    {
        if (!m)
        {
            error("level declaration must be at module level");
            errors = true;
        }
        else
            m->versionlevel = level;
    }
}

void VersionSymbol::semantic(Scope *)
{
    if (semanticRun < PASSsemanticdone)
        semanticRun = PASSsemanticdone;
}

const char *VersionSymbol::kind() const
{
    return "version";
}
