예제 #1
0
파일: init.c 프로젝트: develop32/dmd
Initializer *ArrayInitializer::semantic(Scope *sc, Type *t, NeedInterpret needInterpret)
{
    size_t length;
    const unsigned amax = 0x80000000;
    bool errors = false;

    //printf("ArrayInitializer::semantic(%s)\n", t->toChars());
    if (sem)                            // if semantic() already run
        return this;
    sem = 1;
    type = t;
    Initializer *aa = NULL;
    t = t->toBasetype();
    switch (t->ty)
    {
        case Tpointer:
        case Tsarray:
        case Tarray:
            break;

        case Tvector:
            t = ((TypeVector *)t)->basetype;
            break;

        case Taarray:
            // was actually an associative array literal
            aa = new ExpInitializer(loc, toAssocArrayLiteral());
            return aa->semantic(sc, t, needInterpret);

        default:
            error(loc, "cannot use array to initialize %s", type->toChars());
            goto Lerr;
    }

    length = 0;
    for (size_t i = 0; i < index.dim; i++)
    {
        Expression *idx = index[i];
        if (idx)
        {   idx = idx->ctfeSemantic(sc);
            idx = idx->ctfeInterpret();
            index[i] = idx;
            length = idx->toInteger();
            if (idx->op == TOKerror)
                errors = true;
        }

        Initializer *val = value[i];
        ExpInitializer *ei = val->isExpInitializer();
        if (ei && !idx)
            ei->expandTuples = 1;
        val = val->semantic(sc, t->nextOf(), needInterpret);
        if (val->isErrorInitializer())
            errors = true;

        ei = val->isExpInitializer();
        // found a tuple, expand it
        if (ei && ei->exp->op == TOKtuple)
        {
            TupleExp *te = (TupleExp *)ei->exp;
            index.remove(i);
            value.remove(i);

            for (size_t j = 0; j < te->exps->dim; ++j)
            {
                Expression *e = (*te->exps)[j];
                index.insert(i + j, (Expression *)NULL);
                value.insert(i + j, new ExpInitializer(e->loc, e));
            }
            i--;
            continue;
        }
        else
        {
            value[i] = val;
        }

        length++;
        if (length == 0)
        {   error(loc, "array dimension overflow");
            goto Lerr;
        }
        if (length > dim)
            dim = length;
    }
    if (t->ty == Tsarray)
    {
        dinteger_t edim = ((TypeSArray *)t)->dim->toInteger();
        if (dim > edim)
        {
            error(loc, "array initializer has %u elements, but array length is %lld", dim, edim);
            goto Lerr;
        }
    }
    if (errors)
        goto Lerr;

    if ((uinteger_t) dim * t->nextOf()->size() >= amax)
    {   error(loc, "array dimension %u exceeds max of %u", (unsigned) dim, (unsigned)(amax / t->nextOf()->size()));
        goto Lerr;
    }
    return this;

Lerr:
    return new ErrorInitializer();
}
예제 #2
0
파일: init.c 프로젝트: develop32/dmd
Initializer *StructInitializer::semantic(Scope *sc, Type *t, NeedInterpret needInterpret)
{
    int errors = 0;

    //printf("StructInitializer::semantic(t = %s) %s\n", t->toChars(), toChars());
    vars.setDim(field.dim);
    t = t->toBasetype();
    if (t->ty == Tsarray && t->nextOf()->toBasetype()->ty == Tstruct)
        t = t->nextOf()->toBasetype();
    if (t->ty == Tstruct)
    {
        size_t fieldi = 0;

        TypeStruct *ts = (TypeStruct *)t;
        ad = ts->sym;
        if (ad->ctor)
            error(loc, "%s %s has constructors, cannot use { initializers }, use %s( initializers ) instead",
                ad->kind(), ad->toChars(), ad->toChars());
        StructDeclaration *sd = ad->isStructDeclaration();
        assert(sd);
        sd->size(loc);
        if (sd->sizeok != SIZEOKdone)
        {
            error(loc, "struct %s is forward referenced", sd->toChars());
            errors = 1;
            goto Lerror;
        }
        size_t nfields = sd->fields.dim - sd->isNested();
        for (size_t i = 0; i < field.dim; i++)
        {
            Identifier *id = field[i];
            Initializer *val = value[i];
            Dsymbol *s;
            VarDeclaration *v;

            if (id == NULL)
            {
                if (fieldi >= nfields)
                {   error(loc, "too many initializers for %s", ad->toChars());
                    errors = 1;
                    field.remove(i);
                    i--;
                    continue;
                }
                else
                {
                    s = ad->fields[fieldi];
                }
            }
            else
            {
                //s = ad->symtab->lookup(id);
                s = ad->search(loc, id, 0);
                if (!s)
                {
                    s = ad->search_correct(id);
                    if (s)
                        error(loc, "'%s' is not a member of '%s', did you mean '%s %s'?",
                              id->toChars(), t->toChars(), s->kind(), s->toChars());
                    else
                        error(loc, "'%s' is not a member of '%s'", id->toChars(), t->toChars());
                    errors = 1;
                    continue;
                }
                s = s->toAlias();

                // Find out which field index it is
                for (fieldi = 0; 1; fieldi++)
                {
                    if (fieldi >= nfields)
                    {
                        error(loc, "%s.%s is not a per-instance initializable field",
                            t->toChars(), s->toChars());
                        errors = 1;
                        break;
                    }
                    if (s == ad->fields[fieldi])
                        break;
                }
            }
            if (s && (v = s->isVarDeclaration()) != NULL)
            {
                val = val->semantic(sc, v->type->addMod(t->mod), needInterpret);
                value[i] = val;
                vars[i] = v;
                if (val->isErrorInitializer())
                    errors = 1;
            }
            else
            {   error(loc, "%s is not a field of %s", id ? id->toChars() : s->toChars(), ad->toChars());
                errors = 1;
            }
            fieldi++;
        }
    }
    else if (t->ty == Tdelegate && value.dim == 0)
    {   /* Rewrite as empty delegate literal { }
         */
        Parameters *arguments = new Parameters;
        Type *tf = new TypeFunction(arguments, NULL, 0, LINKd);
        FuncLiteralDeclaration *fd = new FuncLiteralDeclaration(loc, Loc(), tf, TOKdelegate, NULL);
        fd->fbody = new CompoundStatement(loc, new Statements());
        fd->endloc = loc;
        Expression *e = new FuncExp(loc, fd);
        ExpInitializer *ie = new ExpInitializer(loc, e);
        return ie->semantic(sc, t, needInterpret);
    }
    else
    {
        error(loc, "a struct is not a valid initializer for a %s", t->toChars());
        errors = 1;
    }
Lerror:
    if (errors)
    {
        return new ErrorInitializer();
    }
    return this;
}
예제 #3
0
파일: init.c 프로젝트: dreamsxin/GDC
Initializer *ArrayInitializer::semantic(Scope *sc, Type *t, NeedInterpret needInterpret)
{
    size_t length;
    const unsigned amax = 0x80000000;
    bool errors = false;

    //printf("ArrayInitializer::semantic(%s)\n", t->toChars());
    if (sem)                            // if semantic() already run
        return this;
    sem = true;
    t = t->toBasetype();
    switch (t->ty)
    {
        case Tsarray:
        case Tarray:
            break;

        case Tvector:
            t = ((TypeVector *)t)->basetype;
            break;

        case Taarray:
        case Tstruct:   // consider implicit constructor call
        {
            Expression *e;
            // note: MyStruct foo = [1:2, 3:4] is correct code if MyStruct has a this(int[int])
            if (t->ty == Taarray || isAssociativeArray())
                e = toAssocArrayLiteral();
            else
                e = toExpression();
            if (!e) // Bugzilla 13987
            {
                error(loc, "cannot use array to initialize %s", t->toChars());
                goto Lerr;
            }
            ExpInitializer *ei = new ExpInitializer(e->loc, e);
            return ei->semantic(sc, t, needInterpret);
        }
        case Tpointer:
            if (t->nextOf()->ty != Tfunction)
                break;

        default:
            error(loc, "cannot use array to initialize %s", t->toChars());
            goto Lerr;
    }

    type = t;

    length = 0;
    for (size_t i = 0; i < index.dim; i++)
    {
        Expression *idx = index[i];
        if (idx)
        {
            sc = sc->startCTFE();
            idx = idx->semantic(sc);
            sc = sc->endCTFE();
            idx = idx->ctfeInterpret();
            index[i] = idx;
            length = (size_t)idx->toInteger();
            if (idx->op == TOKerror)
                errors = true;
        }

        Initializer *val = value[i];
        ExpInitializer *ei = val->isExpInitializer();
        if (ei && !idx)
            ei->expandTuples = true;
        val = val->semantic(sc, t->nextOf(), needInterpret);
        if (val->isErrorInitializer())
            errors = true;

        ei = val->isExpInitializer();
        // found a tuple, expand it
        if (ei && ei->exp->op == TOKtuple)
        {
            TupleExp *te = (TupleExp *)ei->exp;
            index.remove(i);
            value.remove(i);

            for (size_t j = 0; j < te->exps->dim; ++j)
            {
                Expression *e = (*te->exps)[j];
                index.insert(i + j, (Expression *)NULL);
                value.insert(i + j, new ExpInitializer(e->loc, e));
            }
            i--;
            continue;
        }
        else
        {
            value[i] = val;
        }

        length++;
        if (length == 0)
        {
            error(loc, "array dimension overflow");
            goto Lerr;
        }
        if (length > dim)
            dim = length;
    }
    if (t->ty == Tsarray)
    {
        dinteger_t edim = ((TypeSArray *)t)->dim->toInteger();
        if (dim > edim)
        {
            error(loc, "array initializer has %u elements, but array length is %lld", dim, edim);
            goto Lerr;
        }
    }
    if (errors)
        goto Lerr;

    if ((uinteger_t) dim * t->nextOf()->size() >= amax)
    {
        error(loc, "array dimension %u exceeds max of %u", (unsigned) dim, (unsigned)(amax / t->nextOf()->size()));
        goto Lerr;
    }
    return this;

Lerr:
    return new ErrorInitializer();
}
예제 #4
0
파일: init.c 프로젝트: NativeAPI/dmd
Initializer *ArrayInitializer::inferType(Scope *sc)
{
    //printf("ArrayInitializer::inferType() %s\n", toChars());
    Expressions *keys = NULL;
    Expressions *values;
    if (isAssociativeArray())
    {
        keys = new Expressions();
        keys->setDim(value.dim);
        values = new Expressions();
        values->setDim(value.dim);

        for (size_t i = 0; i < value.dim; i++)
        {
            Expression *e = index[i];
            if (!e)
                goto Lno;
            (*keys)[i] = e;

            Initializer *iz = value[i];
            if (!iz)
                goto Lno;
            iz = iz->inferType(sc);
            if (iz->isErrorInitializer())
                return iz;
            assert(iz->isExpInitializer());
            (*values)[i] = ((ExpInitializer *)iz)->exp;
            assert((*values)[i]->op != TOKerror);
        }

        Expression *e = new AssocArrayLiteralExp(loc, keys, values);
        ExpInitializer *ei = new ExpInitializer(loc, e);
        return ei->inferType(sc);
    }
    else
    {
        Expressions *elements = new Expressions();
        elements->setDim(value.dim);
        elements->zero();

        for (size_t i = 0; i < value.dim; i++)
        {
            assert(!index[i]);  // already asserted by isAssociativeArray()

            Initializer *iz = value[i];
            if (!iz)
                goto Lno;
            iz = iz->inferType(sc);
            if (iz->isErrorInitializer())
                return iz;
            assert(iz->isExpInitializer());
            (*elements)[i] = ((ExpInitializer *)iz)->exp;
            assert((*elements)[i]->op != TOKerror);
        }

        Expression *e = new ArrayLiteralExp(loc, elements);
        ExpInitializer *ei = new ExpInitializer(loc, e);
        return ei->inferType(sc);
    }
Lno:
    if (keys)
    {
        delete keys;
        delete values;
        error(loc, "not an associative array initializer");
    }
    else
    {
        error(loc, "cannot infer type from array initializer");
    }
    return new ErrorInitializer();
}
예제 #5
0
파일: init.c 프로젝트: timotheecour/dmd
Initializer *ArrayInitializer::inferType(Scope *sc, Type *tx)
{
    //printf("ArrayInitializer::inferType() %s\n", toChars());
    Expressions *keys = NULL;
    Expressions *values;
    if (tx ? (tx->ty == Taarray ||
              tx->ty != Tarray && tx->ty != Tsarray && isAssociativeArray())
           : isAssociativeArray())
    {
        Type *tidx = NULL;
        Type *tval = NULL;
        if (tx && tx->ty == Taarray)
        {
            tidx = ((TypeAArray *)tx)->index;
            tval = ((TypeAArray *)tx)->next;
        }

        keys = new Expressions();
        keys->setDim(value.dim);
        values = new Expressions();
        values->setDim(value.dim);

        for (size_t i = 0; i < value.dim; i++)
        {
            Expression *e = index[i];
            if (!e)
                goto Lno;
            if (tidx)
            {
                e = ::inferType(e, tidx);
                e = e->semantic(sc);
                e = resolveProperties(sc, e);
                if (tidx->deco) // tidx may be partial type
                    e = e->implicitCastTo(sc, tidx);
            }
            (*keys)[i] = e;

            Initializer *iz = value[i];
            if (!iz)
                goto Lno;
            iz = iz->inferType(sc, tval);
            if (iz->isErrorInitializer())
                return iz;
            assert(iz->isExpInitializer());
            (*values)[i] = ((ExpInitializer *)iz)->exp;
            assert((*values)[i]->op != TOKerror);
        }

        Expression *e = new AssocArrayLiteralExp(loc, keys, values);
        ExpInitializer *ei = new ExpInitializer(loc, e);
        return ei->inferType(sc, tx);
    }
    else
    {
        Type *tn = NULL;
        if (tx && (tx->ty == Tarray || tx->ty == Tsarray))
            tn = ((TypeNext *)tx)->next;

        Expressions *elements = new Expressions();
        elements->setDim(value.dim);
        elements->zero();

        for (size_t i = 0; i < value.dim; i++)
        {
            assert(!index[i]);  // already asserted by isAssociativeArray()

            Initializer *iz = value[i];
            if (!iz)
                goto Lno;
            iz = iz->inferType(sc, tn);
            if (iz->isErrorInitializer())
                return iz;
            assert(iz->isExpInitializer());
            (*elements)[i] = ((ExpInitializer *)iz)->exp;
            assert((*elements)[i]->op != TOKerror);
        }

        Expression *e = new ArrayLiteralExp(loc, elements);
        ExpInitializer *ei = new ExpInitializer(loc, e);
        return ei->inferType(sc, tx);
    }
Lno:
    if (keys)
    {
        delete keys;
        delete values;
        error(loc, "not an associative array initializer");
    }
    else
    {
        error(loc, "cannot infer type from array initializer");
    }
    return new ErrorInitializer();
}