
/* 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/enum.c
 */

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

#include "errors.h"
#include "enum.h"
#include "mtype.h"
#include "scope.h"
#include "id.h"
#include "expression.h"
#include "module.h"
#include "declaration.h"
#include "init.h"

Expression *semantic(Expression *e, Scope *sc);

/********************************* EnumDeclaration ****************************/

EnumDeclaration::EnumDeclaration(Loc loc, Identifier *id, Type *memtype)
    : ScopeDsymbol(id)
{
    //printf("EnumDeclaration() %s\n", toChars());
    this->loc = loc;
    type = new TypeEnum(this);
    this->memtype = memtype;
    maxval = NULL;
    minval = NULL;
    defaultval = NULL;
    sinit = NULL;
    isdeprecated = false;
    protection = Prot(PROTundefined);
    parent = NULL;
    added = false;
    inuse = 0;
}

Dsymbol *EnumDeclaration::syntaxCopy(Dsymbol *s)
{
    assert(!s);
    EnumDeclaration *ed = new EnumDeclaration(loc, ident,
        memtype ? memtype->syntaxCopy() : NULL);
    return ScopeDsymbol::syntaxCopy(ed);
}

void EnumDeclaration::setScope(Scope *sc)
{
    if (semanticRun > PASSinit)
        return;
    ScopeDsymbol::setScope(sc);
}

void EnumDeclaration::addMember(Scope *sc, ScopeDsymbol *sds)
{
    /* Anonymous enum members get added to enclosing scope.
     */
    ScopeDsymbol *scopesym = isAnonymous() ? sds : this;

    if (!isAnonymous())
    {
        ScopeDsymbol::addMember(sc, sds);

        if (!symtab)
            symtab = new DsymbolTable();
    }

    if (members)
    {
        for (size_t i = 0; i < members->dim; i++)
        {
            EnumMember *em = (*members)[i]->isEnumMember();
            em->ed = this;
            //printf("add %s to scope %s\n", em->toChars(), scopesym->toChars());
            em->addMember(sc, isAnonymous() ? scopesym : this);
        }
    }
    added = true;
}


void EnumDeclaration::semantic(Scope *sc)
{
    //printf("EnumDeclaration::semantic(sd = %p, '%s') %s\n", sc->scopesym, sc->scopesym->toChars(), toChars());
    //printf("EnumDeclaration::semantic() %p %s\n", this, toChars());
    if (semanticRun >= PASSsemanticdone)
        return;             // semantic() already completed
    if (semanticRun == PASSsemantic)
    {
        assert(memtype);
        ::error(loc, "circular reference to enum base type %s", memtype->toChars());
        errors = true;
        semanticRun = PASSsemanticdone;
        return;
    }
    unsigned dprogress_save = Module::dprogress;

    Scope *scx = NULL;
    if (_scope)
    {
        sc = _scope;
        scx = _scope;            // save so we don't make redundant copies
        _scope = NULL;
    }

    parent = sc->parent;
    type = type->semantic(loc, sc);

    protection = sc->protection;
    if (sc->stc & STCdeprecated)
        isdeprecated = true;
    userAttribDecl = sc->userAttribDecl;

    semanticRun = PASSsemantic;

    if (!members && !memtype)               // enum ident;
    {
        semanticRun = PASSsemanticdone;
        return;
    }

    if (!symtab)
        symtab = new DsymbolTable();

    /* The separate, and distinct, cases are:
     *  1. enum { ... }
     *  2. enum : memtype { ... }
     *  3. enum ident { ... }
     *  4. enum ident : memtype { ... }
     *  5. enum ident : memtype;
     *  6. enum ident;
     */

    if (memtype)
    {
        memtype = memtype->semantic(loc, sc);

        /* Check to see if memtype is forward referenced
         */
        if (memtype->ty == Tenum)
        {
            EnumDeclaration *sym = (EnumDeclaration *)memtype->toDsymbol(sc);
            if (!sym->memtype || !sym->members || !sym->symtab || sym->_scope)
            {
                // memtype is forward referenced, so try again later
                _scope = scx ? scx : sc->copy();
                _scope->setNoFree();
                _scope->_module->addDeferredSemantic(this);
                Module::dprogress = dprogress_save;
                //printf("\tdeferring %s\n", toChars());
                semanticRun = PASSinit;
                return;
            }
        }
        if (memtype->ty == Tvoid)
        {
            error("base type must not be void");
            memtype = Type::terror;
        }
        if (memtype->ty == Terror)
        {
            errors = true;
            if (members)
            {
                for (size_t i = 0; i < members->dim; i++)
                {
                    Dsymbol *s = (*members)[i];
                    s->errors = true;               // poison all the members
                }
            }
            semanticRun = PASSsemanticdone;
            return;
        }
    }

    semanticRun = PASSsemanticdone;

    if (!members)               // enum ident : memtype;
        return;

    if (members->dim == 0)
    {
        error("enum %s must have at least one member", toChars());
        errors = true;
        return;
    }

    Module::dprogress++;

    Scope *sce;
    if (isAnonymous())
        sce = sc;
    else
    {
        sce = sc->push(this);
        sce->parent = this;
    }
    sce = sce->startCTFE();
    sce->setNoFree();                   // needed for getMaxMinValue()

    /* Each enum member gets the sce scope
     */
    for (size_t i = 0; i < members->dim; i++)
    {
        EnumMember *em = (*members)[i]->isEnumMember();
        if (em)
            em->_scope = sce;
    }

    if (!added)
    {
        /* addMember() is not called when the EnumDeclaration appears as a function statement,
         * so we have to do what addMember() does and install the enum members in the right symbol
         * table
         */
        ScopeDsymbol *scopesym = NULL;
        if (isAnonymous())
        {
            /* Anonymous enum members get added to enclosing scope.
             */
            for (Scope *sct = sce; 1; sct = sct->enclosing)
            {
                assert(sct);
                if (sct->scopesym)
                {
                    scopesym = sct->scopesym;
                    if (!sct->scopesym->symtab)
                        sct->scopesym->symtab = new DsymbolTable();
                    break;
                }
            }
        }
        else
        {
            // Otherwise enum members are in the EnumDeclaration's symbol table
            scopesym = this;
        }

        for (size_t i = 0; i < members->dim; i++)
        {
            EnumMember *em = (*members)[i]->isEnumMember();
            if (em)
            {
                em->ed = this;
                em->addMember(sc, scopesym);
            }
        }
    }

    for (size_t i = 0; i < members->dim; i++)
    {
        EnumMember *em = (*members)[i]->isEnumMember();
        if (em)
            em->semantic(em->_scope);
    }
    //printf("defaultval = %lld\n", defaultval);

    //if (defaultval) printf("defaultval: %s %s\n", defaultval->toChars(), defaultval->type->toChars());
    //printf("members = %s\n", members->toChars());
}

/******************************
 * Get the value of the .max/.min property as an Expression
 * Input:
 *      id      Id::max or Id::min
 */

Expression *EnumDeclaration::getMaxMinValue(Loc loc, Identifier *id)
{
    //printf("EnumDeclaration::getMaxValue()\n");
    bool first = true;

    Expression **pval = (id == Id::max) ? &maxval : &minval;

    if (inuse)
    {
        error(loc, "recursive definition of .%s property", id->toChars());
        goto Lerrors;
    }
    if (*pval)
        goto Ldone;

    if (_scope)
        semantic(_scope);
    if (errors)
        goto Lerrors;
    if (semanticRun == PASSinit || !members)
    {
        if (isSpecial())
        {
            /* Allow these special enums to not need a member list
             */
            return memtype->getProperty(loc, id, 0);
        }

        error("is forward referenced looking for .%s", id->toChars());
        goto Lerrors;
    }
    if (!(memtype && memtype->isintegral()))
    {
        error(loc, "has no .%s property because base type %s is not an integral type",
                id->toChars(),
                memtype ? memtype->toChars() : "");
        goto Lerrors;
    }

    for (size_t i = 0; i < members->dim; i++)
    {
        EnumMember *em = (*members)[i]->isEnumMember();
        if (!em)
            continue;
        if (em->errors)
            goto Lerrors;

        Expression *e = em->value();
        if (first)
        {
            *pval = e;
            first = false;
        }
        else
        {
            /* In order to work successfully with UDTs,
             * build expressions to do the comparisons,
             * and let the semantic analyzer and constant
             * folder give us the result.
             */

            /* Compute:
             *   if (e > maxval)
             *      maxval = e;
             */
            Expression *ec = new CmpExp(id == Id::max ? TOKgt : TOKlt, em->loc, e, *pval);
            inuse++;
            ec = ::semantic(ec, em->_scope);
            inuse--;
            ec = ec->ctfeInterpret();
            if (ec->toInteger())
                *pval = e;
        }
    }
Ldone:
  {
    Expression *e = *pval;
    if (e->op != TOKerror)
    {
        e = e->copy();
        e->loc = loc;
    }
    return e;
  }

Lerrors:
    *pval = new ErrorExp();
    return *pval;
}

/****************
 * Determine if enum is a 'special' one.
 * Returns:
 *  true if special
 */
bool EnumDeclaration::isSpecial() const
{
    return (ident == Id::__c_long ||
            ident == Id::__c_ulong ||
            ident == Id::__c_longlong ||
            ident == Id::__c_ulonglong ||
            ident == Id::__c_long_double) && memtype;
}

Expression *EnumDeclaration::getDefaultValue(Loc loc)
{
    //printf("EnumDeclaration::getDefaultValue() %p %s\n", this, toChars());
    if (defaultval)
        return defaultval;

    if (_scope)
        semantic(_scope);
    if (errors)
        goto Lerrors;
    if (semanticRun == PASSinit || !members)
    {
        if (isSpecial())
        {
            /* Allow these special enums to not need a member list
             */
            return memtype->defaultInit(loc);
        }

        error(loc, "forward reference of %s.init", toChars());
        goto Lerrors;
    }

    for (size_t i = 0; i < members->dim; i++)
    {
        EnumMember *em = (*members)[i]->isEnumMember();
        if (em)
        {
            defaultval = em->value();
            return defaultval;
        }
    }

Lerrors:
    defaultval = new ErrorExp();
    return defaultval;
}

Type *EnumDeclaration::getMemtype(Loc loc)
{
    if (loc.linnum == 0)
        loc = this->loc;
    if (_scope)
    {
        /* Enum is forward referenced. We don't need to resolve the whole thing,
         * just the base type
         */
        if (memtype)
            memtype = memtype->semantic(loc, _scope);
        else
        {
            if (!isAnonymous() && members)
                memtype = Type::tint32;
        }
    }
    if (!memtype)
    {
        if (!isAnonymous() && members)
            memtype = Type::tint32;
        else
        {
            error(loc, "is forward referenced looking for base type");
            return Type::terror;
        }
    }
    return memtype;
}

bool EnumDeclaration::oneMember(Dsymbol **ps, Identifier *ident)
{
    if (isAnonymous())
        return Dsymbol::oneMembers(members, ps, ident);
    return Dsymbol::oneMember(ps, ident);
}

Type *EnumDeclaration::getType()
{
    return type;
}

const char *EnumDeclaration::kind() const
{
    return "enum";
}

bool EnumDeclaration::isDeprecated()
{
    return isdeprecated;
}

Prot EnumDeclaration::prot()
{
    return protection;
}

Dsymbol *EnumDeclaration::search(const Loc &loc, Identifier *ident, int flags)
{
    //printf("%s.EnumDeclaration::search('%s')\n", toChars(), ident->toChars());
    if (_scope)
    {
        // Try one last time to resolve this enum
        semantic(_scope);
    }

    if (!members || !symtab || _scope)
    {
        error("is forward referenced when looking for '%s'", ident->toChars());
        //*(char*)0=0;
        return NULL;
    }

    Dsymbol *s = ScopeDsymbol::search(loc, ident, flags);
    return s;
}

/********************************* EnumMember ****************************/

EnumMember::EnumMember(Loc loc, Identifier *id, Expression *value, Type *origType)
    : VarDeclaration(loc, NULL, id ? id : Id::empty, new ExpInitializer(loc, value))
{
    this->ed = NULL;
    this->origValue = value;
    this->origType = origType;
}

Expression *&EnumMember::value()
{
    return ((ExpInitializer*)_init)->exp;
}

Dsymbol *EnumMember::syntaxCopy(Dsymbol *s)
{
    assert(!s);
    return new EnumMember(loc, ident,
        value() ? value()->syntaxCopy() : NULL,
        origType ? origType->syntaxCopy() : NULL);
}

const char *EnumMember::kind() const
{
    return "enum member";
}

void EnumMember::semantic(Scope *sc)
{
    //printf("EnumMember::semantic() %s\n", toChars());
    if (errors || semanticRun >= PASSsemanticdone)
        return;
    if (semanticRun == PASSsemantic)
    {
        error("circular reference to enum member");
    Lerrors:
        errors = true;
        semanticRun = PASSsemanticdone;
        return;
    }
    assert(ed);
    ed->semantic(sc);
    if (ed->errors)
        goto Lerrors;

    if (errors || semanticRun >= PASSsemanticdone)
        return;

    if (_scope)
        sc = _scope;
    if (!sc)
        return;

    semanticRun = PASSsemantic;

    protection = ed->isAnonymous() ? ed->protection : Prot(PROTpublic);
    linkage = LINKd;
    storage_class = STCmanifest;
    userAttribDecl = ed->isAnonymous() ? ed->userAttribDecl : NULL;

    // The first enum member is special
    bool first = (this == (*ed->members)[0]);

    if (origType)
    {
        origType = origType->semantic(loc, sc);
        type = origType;
        assert(value());          // "type id;" is not a valid enum member declaration
    }

    if (value())
    {
        Expression *e = value();
        assert(e->dyncast() == DYNCAST_EXPRESSION);
        e = ::semantic(e, sc);
        e = resolveProperties(sc, e);
        e = e->ctfeInterpret();
        if (e->op == TOKerror)
            goto Lerrors;
        if (first && !ed->memtype && !ed->isAnonymous())
        {
            ed->memtype = e->type;
            if (ed->memtype->ty == Terror)
            {
                ed->errors = true;
                goto Lerrors;
            }
            if (ed->memtype->ty != Terror)
            {
                /* Bugzilla 11746: All of named enum members should have same type
                 * with the first member. If the following members were referenced
                 * during the first member semantic, their types should be unified.
                 */
                for (size_t i = 0; i < ed->members->dim; i++)
                {
                    EnumMember *em = (*ed->members)[i]->isEnumMember();
                    if (!em || em == this || em->semanticRun < PASSsemanticdone || em->origType)
                        continue;

                    //printf("[%d] em = %s, em->semanticRun = %d\n", i, toChars(), em->semanticRun);
                    Expression *ev = em->value();
                    ev = ev->implicitCastTo(sc, ed->memtype);
                    ev = ev->ctfeInterpret();
                    ev = ev->castTo(sc, ed->type);
                    if (ev->op == TOKerror)
                        ed->errors = true;
                    em->value() = ev;
                }
                if (ed->errors)
                {
                    ed->memtype = Type::terror;
                    goto Lerrors;
                }
            }
        }

        if (ed->memtype && !origType)
        {
            e = e->implicitCastTo(sc, ed->memtype);
            e = e->ctfeInterpret();

            // save origValue for better json output
            origValue = e;

            if (!ed->isAnonymous())
            {
                e = e->castTo(sc, ed->type);
                e = e->ctfeInterpret();
            }
        }
        else if (origType)
        {
            e = e->implicitCastTo(sc, origType);
            e = e->ctfeInterpret();
            assert(ed->isAnonymous());

            // save origValue for better json output
            origValue = e;
        }
        value() = e;
    }
    else if (first)
    {
        Type *t;
        if (ed->memtype)
            t = ed->memtype;
        else
        {
            t = Type::tint32;
            if (!ed->isAnonymous())
                ed->memtype = t;
        }
        Expression *e = new IntegerExp(loc, 0, Type::tint32);
        e = e->implicitCastTo(sc, t);
        e = e->ctfeInterpret();

        // save origValue for better json output
        origValue = e;

        if (!ed->isAnonymous())
        {
            e = e->castTo(sc, ed->type);
            e = e->ctfeInterpret();
        }
        value() = e;
    }
    else
    {
        /* Find the previous enum member,
         * and set this to be the previous value + 1
         */
        EnumMember *emprev = NULL;
        for (size_t i = 0; i < ed->members->dim; i++)
        {
            EnumMember *em = (*ed->members)[i]->isEnumMember();
            if (em)
            {
                if (em == this)
                    break;
                emprev = em;
            }
        }
        assert(emprev);
        if (emprev->semanticRun < PASSsemanticdone)    // if forward reference
            emprev->semantic(emprev->_scope);    // resolve it
        if (emprev->errors)
            goto Lerrors;

        Expression *eprev = emprev->value();
        Type *tprev = eprev->type->equals(ed->type) ? ed->memtype : eprev->type;

        Expression *emax = tprev->getProperty(ed->loc, Id::max, 0);
        emax = ::semantic(emax, sc);
        emax = emax->ctfeInterpret();

        // Set value to (eprev + 1).
        // But first check that (eprev != emax)
        assert(eprev);
        Expression *e = new EqualExp(TOKequal, loc, eprev, emax);
        e = ::semantic(e, sc);
        e = e->ctfeInterpret();
        if (e->toInteger())
        {
            error("initialization with (%s.%s + 1) causes overflow for type '%s'", emprev->ed->toChars(), emprev->toChars(), ed->type->toBasetype()->toChars());
            goto Lerrors;
        }

        // Now set e to (eprev + 1)
        e = new AddExp(loc, eprev, new IntegerExp(loc, 1, Type::tint32));
        e = ::semantic(e, sc);
        e = e->castTo(sc, eprev->type);
        e = e->ctfeInterpret();

        // save origValue (without cast) for better json output
        if (e->op != TOKerror)  // avoid duplicate diagnostics
        {
            assert(emprev->origValue);
            origValue = new AddExp(loc, emprev->origValue, new IntegerExp(loc, 1, Type::tint32));
            origValue = ::semantic(origValue, sc);
            origValue = origValue->ctfeInterpret();
        }

        if (e->op == TOKerror)
            goto Lerrors;
        if (e->type->isfloating())
        {
            // Check that e != eprev (not always true for floats)
            Expression *etest = new EqualExp(TOKequal, loc, e, eprev);
            etest = ::semantic(etest, sc);
            etest = etest->ctfeInterpret();
            if (etest->toInteger())
            {
                error("has inexact value, due to loss of precision");
                goto Lerrors;
            }
        }
        value() = e;
    }
    if (!origType)
        type = value()->type;

    assert(origValue);
    semanticRun = PASSsemanticdone;
}

Expression *EnumMember::getVarExp(Loc loc, Scope *sc)
{
    semantic(sc);
    if (errors)
        return new ErrorExp();
    Expression *e = new VarExp(loc, this);
    return ::semantic(e, sc);
}
