Expression *ArrayInitializer::toAssocArrayLiteral() { Expression *e; //printf("ArrayInitializer::toAssocArrayInitializer()\n"); //static int i; if (++i == 2) halt(); Expressions *keys = new Expressions(); keys->setDim(value.dim); Expressions *values = new Expressions(); values->setDim(value.dim); for (size_t i = 0; i < value.dim; i++) { e = index.tdata()[i]; if (!e) goto Lno; keys->tdata()[i] = e; Initializer *iz = value.tdata()[i]; if (!iz) goto Lno; e = iz->toExpression(); if (!e) goto Lno; values->tdata()[i] = e; } e = new AssocArrayLiteralExp(loc, keys, values); return e; Lno: delete keys; delete values; error(loc, "not an associative array initializer"); return new ErrorExp(); }
Expressions *arrayExpressiondoInline(Expressions *a, InlineDoState *ids) { Expressions *newa = NULL; if (a) { newa = new Expressions(); newa->setDim(a->dim); for (size_t i = 0; i < a->dim; i++) { Expression *e = a->tdata()[i]; if (e) e = e->doInline(ids); newa->tdata()[i] = e; } } return newa; }
Expression *ArrayInitializer::toExpression() { Expressions *elements; //printf("ArrayInitializer::toExpression(), dim = %d\n", dim); //static int i; if (++i == 2) halt(); size_t edim; Type *t = NULL; if (type) { if (type == Type::terror) return new ErrorExp(); t = type->toBasetype(); switch (t->ty) { case Tsarray: edim = ((TypeSArray *)t)->dim->toInteger(); break; case Tpointer: case Tarray: edim = dim; break; default: assert(0); } } else { edim = value.dim; for (size_t i = 0, j = 0; i < value.dim; i++, j++) { if (index.tdata()[i]) j = index.tdata()[i]->toInteger(); if (j >= edim) edim = j + 1; } } elements = new Expressions(); elements->setDim(edim); elements->zero(); for (size_t i = 0, j = 0; i < value.dim; i++, j++) { if (index.tdata()[i]) j = (index.tdata()[i])->toInteger(); assert(j < edim); Initializer *iz = value.tdata()[i]; if (!iz) goto Lno; Expression *ex = iz->toExpression(); if (!ex) { goto Lno; } elements->tdata()[j] = ex; } /* Fill in any missing elements with the default initializer */ { Expression *init = NULL; for (size_t i = 0; i < edim; i++) { if (!elements->tdata()[i]) { if (!type) goto Lno; if (!init) init = ((TypeNext *)t)->next->defaultInit(); elements->tdata()[i] = init; } } Expression *e = new ArrayLiteralExp(loc, elements); e->type = type; return e; } Lno: return NULL; }
/*************************************** * This works by transforming a struct initializer into * a struct literal. In the future, the two should be the * same thing. */ Expression *StructInitializer::toExpression() { Expression *e; size_t offset; //printf("StructInitializer::toExpression() %s\n", toChars()); if (!ad) // if fwd referenced { return NULL; } StructDeclaration *sd = ad->isStructDeclaration(); if (!sd) return NULL; Expressions *elements = new Expressions(); size_t nfields = ad->fields.dim; #if DMDV2 if (sd->isnested) nfields--; #endif elements->setDim(nfields); for (size_t i = 0; i < elements->dim; i++) { elements->tdata()[i] = NULL; } unsigned fieldi = 0; for (size_t i = 0; i < value.dim; i++) { Identifier *id = field.tdata()[i]; if (id) { Dsymbol * s = ad->search(loc, id, 0); if (!s) { error(loc, "'%s' is not a member of '%s'", id->toChars(), sd->toChars()); goto Lno; } // Find out which field index it is for (fieldi = 0; 1; fieldi++) { if (fieldi >= nfields) { s->error("is not a per-instance initializable field"); goto Lno; } if (s == ad->fields.tdata()[fieldi]) break; } } else if (fieldi >= nfields) { error(loc, "too many initializers for '%s'", ad->toChars()); goto Lno; } Initializer *iz = value.tdata()[i]; if (!iz) goto Lno; Expression *ex = iz->toExpression(); if (!ex) goto Lno; if (elements->tdata()[fieldi]) { error(loc, "duplicate initializer for field '%s'", ad->fields.tdata()[fieldi]->toChars()); goto Lno; } elements->tdata()[fieldi] = ex; ++fieldi; } // Now, fill in any missing elements with default initializers. // We also need to validate any anonymous unions offset = 0; for (size_t i = 0; i < elements->dim; ) { VarDeclaration * vd = ad->fields.tdata()[i]->isVarDeclaration(); //printf("test2 [%d] : %s %d %d\n", i, vd->toChars(), (int)offset, (int)vd->offset); if (vd->offset < offset) { // Only the first field of a union can have an initializer if (elements->tdata()[i]) goto Lno; } else { if (!elements->tdata()[i]) // Default initialize elements->tdata()[i] = vd->type->defaultInit(); } offset = vd->offset + vd->type->size(); i++; #if 0 int unionSize = ad->numFieldsInUnion(i); if (unionSize == 1) { // Not a union -- default initialize if missing if (!elements->tdata()[i]) elements->tdata()[i] = vd->type->defaultInit(); } else { // anonymous union -- check for errors int found = -1; // index of the first field with an initializer for (int j = i; j < i + unionSize; ++j) { if (!elements->tdata()[j]) continue; if (found >= 0) { VarDeclaration * v1 = ((Dsymbol *)ad->fields.data[found])->isVarDeclaration(); VarDeclaration * v = ((Dsymbol *)ad->fields.data[j])->isVarDeclaration(); error(loc, "%s cannot have initializers for fields %s and %s in same union", ad->toChars(), v1->toChars(), v->toChars()); goto Lno; } found = j; } if (found == -1) { error(loc, "no initializer for union that contains field %s", vd->toChars()); goto Lno; } } i += unionSize; #endif } e = new StructLiteralExp(loc, sd, elements); e->type = sd->type; return e; Lno: delete elements; return NULL; }
Expression *BinExp::arrayOp(Scope *sc) { //printf("BinExp::arrayOp() %s\n", toChars()); Type *tb = type->toBasetype(); assert(tb->ty == Tarray || tb->ty == Tsarray); if (tb->nextOf()->toBasetype()->ty == Tvoid) { error("Cannot perform array operations on void[] arrays"); return new ErrorExp(); } if (!isArrayOpValid(e2)) { e2->error("invalid array operation %s (did you forget a [] ?)", toChars()); return new ErrorExp(); } Expressions *arguments = new Expressions(); /* The expression to generate an array operation for is mangled * into a name to use as the array operation function name. * Mangle in the operands and operators in RPN order, and type. */ OutBuffer buf; buf.writestring("_array"); buildArrayIdent(&buf, arguments); buf.writeByte('_'); /* Append deco of array element type */ #if DMDV2 buf.writestring(type->toBasetype()->nextOf()->toBasetype()->mutableOf()->deco); #else buf.writestring(type->toBasetype()->nextOf()->toBasetype()->deco); #endif size_t namelen = buf.offset; buf.writeByte(0); char *name = buf.toChars(); Identifier *ident = Lexer::idPool(name); /* Look up name in hash table */ FuncDeclaration **pfd = (FuncDeclaration **)_aaGet(&arrayfuncs, ident); FuncDeclaration *fd = (FuncDeclaration *)*pfd; if (!fd) { /* Some of the array op functions are written as library functions, * presumably to optimize them with special CPU vector instructions. * List those library functions here, in alpha order. */ static const char *libArrayopFuncs[] = { "_arrayExpSliceAddass_a", "_arrayExpSliceAddass_d", // T[]+=T "_arrayExpSliceAddass_f", // T[]+=T "_arrayExpSliceAddass_g", "_arrayExpSliceAddass_h", "_arrayExpSliceAddass_i", "_arrayExpSliceAddass_k", "_arrayExpSliceAddass_s", "_arrayExpSliceAddass_t", "_arrayExpSliceAddass_u", "_arrayExpSliceAddass_w", "_arrayExpSliceDivass_d", // T[]/=T "_arrayExpSliceDivass_f", // T[]/=T "_arrayExpSliceMinSliceAssign_a", "_arrayExpSliceMinSliceAssign_d", // T[]=T-T[] "_arrayExpSliceMinSliceAssign_f", // T[]=T-T[] "_arrayExpSliceMinSliceAssign_g", "_arrayExpSliceMinSliceAssign_h", "_arrayExpSliceMinSliceAssign_i", "_arrayExpSliceMinSliceAssign_k", "_arrayExpSliceMinSliceAssign_s", "_arrayExpSliceMinSliceAssign_t", "_arrayExpSliceMinSliceAssign_u", "_arrayExpSliceMinSliceAssign_w", "_arrayExpSliceMinass_a", "_arrayExpSliceMinass_d", // T[]-=T "_arrayExpSliceMinass_f", // T[]-=T "_arrayExpSliceMinass_g", "_arrayExpSliceMinass_h", "_arrayExpSliceMinass_i", "_arrayExpSliceMinass_k", "_arrayExpSliceMinass_s", "_arrayExpSliceMinass_t", "_arrayExpSliceMinass_u", "_arrayExpSliceMinass_w", "_arrayExpSliceMulass_d", // T[]*=T "_arrayExpSliceMulass_f", // T[]*=T "_arrayExpSliceMulass_i", "_arrayExpSliceMulass_k", "_arrayExpSliceMulass_s", "_arrayExpSliceMulass_t", "_arrayExpSliceMulass_u", "_arrayExpSliceMulass_w", "_arraySliceExpAddSliceAssign_a", "_arraySliceExpAddSliceAssign_d", // T[]=T[]+T "_arraySliceExpAddSliceAssign_f", // T[]=T[]+T "_arraySliceExpAddSliceAssign_g", "_arraySliceExpAddSliceAssign_h", "_arraySliceExpAddSliceAssign_i", "_arraySliceExpAddSliceAssign_k", "_arraySliceExpAddSliceAssign_s", "_arraySliceExpAddSliceAssign_t", "_arraySliceExpAddSliceAssign_u", "_arraySliceExpAddSliceAssign_w", "_arraySliceExpDivSliceAssign_d", // T[]=T[]/T "_arraySliceExpDivSliceAssign_f", // T[]=T[]/T "_arraySliceExpMinSliceAssign_a", "_arraySliceExpMinSliceAssign_d", // T[]=T[]-T "_arraySliceExpMinSliceAssign_f", // T[]=T[]-T "_arraySliceExpMinSliceAssign_g", "_arraySliceExpMinSliceAssign_h", "_arraySliceExpMinSliceAssign_i", "_arraySliceExpMinSliceAssign_k", "_arraySliceExpMinSliceAssign_s", "_arraySliceExpMinSliceAssign_t", "_arraySliceExpMinSliceAssign_u", "_arraySliceExpMinSliceAssign_w", "_arraySliceExpMulSliceAddass_d", // T[] += T[]*T "_arraySliceExpMulSliceAddass_f", "_arraySliceExpMulSliceAddass_r", "_arraySliceExpMulSliceAssign_d", // T[]=T[]*T "_arraySliceExpMulSliceAssign_f", // T[]=T[]*T "_arraySliceExpMulSliceAssign_i", "_arraySliceExpMulSliceAssign_k", "_arraySliceExpMulSliceAssign_s", "_arraySliceExpMulSliceAssign_t", "_arraySliceExpMulSliceAssign_u", "_arraySliceExpMulSliceAssign_w", "_arraySliceExpMulSliceMinass_d", // T[] -= T[]*T "_arraySliceExpMulSliceMinass_f", "_arraySliceExpMulSliceMinass_r", "_arraySliceSliceAddSliceAssign_a", "_arraySliceSliceAddSliceAssign_d", // T[]=T[]+T[] "_arraySliceSliceAddSliceAssign_f", // T[]=T[]+T[] "_arraySliceSliceAddSliceAssign_g", "_arraySliceSliceAddSliceAssign_h", "_arraySliceSliceAddSliceAssign_i", "_arraySliceSliceAddSliceAssign_k", "_arraySliceSliceAddSliceAssign_r", // T[]=T[]+T[] "_arraySliceSliceAddSliceAssign_s", "_arraySliceSliceAddSliceAssign_t", "_arraySliceSliceAddSliceAssign_u", "_arraySliceSliceAddSliceAssign_w", "_arraySliceSliceAddass_a", "_arraySliceSliceAddass_d", // T[]+=T[] "_arraySliceSliceAddass_f", // T[]+=T[] "_arraySliceSliceAddass_g", "_arraySliceSliceAddass_h", "_arraySliceSliceAddass_i", "_arraySliceSliceAddass_k", "_arraySliceSliceAddass_s", "_arraySliceSliceAddass_t", "_arraySliceSliceAddass_u", "_arraySliceSliceAddass_w", "_arraySliceSliceMinSliceAssign_a", "_arraySliceSliceMinSliceAssign_d", // T[]=T[]-T[] "_arraySliceSliceMinSliceAssign_f", // T[]=T[]-T[] "_arraySliceSliceMinSliceAssign_g", "_arraySliceSliceMinSliceAssign_h", "_arraySliceSliceMinSliceAssign_i", "_arraySliceSliceMinSliceAssign_k", "_arraySliceSliceMinSliceAssign_r", // T[]=T[]-T[] "_arraySliceSliceMinSliceAssign_s", "_arraySliceSliceMinSliceAssign_t", "_arraySliceSliceMinSliceAssign_u", "_arraySliceSliceMinSliceAssign_w", "_arraySliceSliceMinass_a", "_arraySliceSliceMinass_d", // T[]-=T[] "_arraySliceSliceMinass_f", // T[]-=T[] "_arraySliceSliceMinass_g", "_arraySliceSliceMinass_h", "_arraySliceSliceMinass_i", "_arraySliceSliceMinass_k", "_arraySliceSliceMinass_s", "_arraySliceSliceMinass_t", "_arraySliceSliceMinass_u", "_arraySliceSliceMinass_w", "_arraySliceSliceMulSliceAssign_d", // T[]=T[]*T[] "_arraySliceSliceMulSliceAssign_f", // T[]=T[]*T[] "_arraySliceSliceMulSliceAssign_i", "_arraySliceSliceMulSliceAssign_k", "_arraySliceSliceMulSliceAssign_s", "_arraySliceSliceMulSliceAssign_t", "_arraySliceSliceMulSliceAssign_u", "_arraySliceSliceMulSliceAssign_w", "_arraySliceSliceMulass_d", // T[]*=T[] "_arraySliceSliceMulass_f", // T[]*=T[] "_arraySliceSliceMulass_i", "_arraySliceSliceMulass_k", "_arraySliceSliceMulass_s", "_arraySliceSliceMulass_t", "_arraySliceSliceMulass_u", "_arraySliceSliceMulass_w", }; int i = binary(name, libArrayopFuncs, sizeof(libArrayopFuncs) / sizeof(char *)); if (i == -1) { #ifdef DEBUG // Make sure our array is alphabetized for (i = 0; i < sizeof(libArrayopFuncs) / sizeof(char *); i++) { if (strcmp(name, libArrayopFuncs[i]) == 0) assert(0); } #endif /* Not in library, so generate it. * Construct the function body: * foreach (i; 0 .. p.length) for (size_t i = 0; i < p.length; i++) * loopbody; * return p; */ Parameters *fparams = new Parameters(); Expression *loopbody = buildArrayLoop(fparams); Parameter *p = (*fparams)[0 /*fparams->dim - 1*/]; #if DMDV1 // for (size_t i = 0; i < p.length; i++) Initializer *init = new ExpInitializer(0, new IntegerExp(0, 0, Type::tsize_t)); Dsymbol *d = new VarDeclaration(0, Type::tsize_t, Id::p, init); Statement *s1 = new ForStatement(0, new DeclarationStatement(0, d), new CmpExp(TOKlt, 0, new IdentifierExp(0, Id::p), new ArrayLengthExp(0, new IdentifierExp(0, p->ident))), new PostExp(TOKplusplus, 0, new IdentifierExp(0, Id::p)), new ExpStatement(0, loopbody)); #else // foreach (i; 0 .. p.length) Statement *s1 = new ForeachRangeStatement(0, TOKforeach, new Parameter(0, NULL, Id::p, NULL), new IntegerExp(0, 0, Type::tint32), new ArrayLengthExp(0, new IdentifierExp(0, p->ident)), new ExpStatement(0, loopbody)); #endif Statement *s2 = new ReturnStatement(0, new IdentifierExp(0, p->ident)); //printf("s2: %s\n", s2->toChars()); Statement *fbody = new CompoundStatement(0, s1, s2); /* Construct the function */ TypeFunction *ftype = new TypeFunction(fparams, type, 0, LINKc); //printf("ftype: %s\n", ftype->toChars()); fd = new FuncDeclaration(loc, 0, ident, STCundefined, ftype); fd->fbody = fbody; fd->protection = PROTpublic; fd->linkage = LINKc; fd->isArrayOp = 1; sc->module->importedFrom->members->push(fd); sc = sc->push(); sc->parent = sc->module->importedFrom; sc->stc = 0; sc->linkage = LINKc; fd->semantic(sc); fd->semantic2(sc); fd->semantic3(sc); sc->pop(); } else { /* In library, refer to it. */ fd = FuncDeclaration::genCfunc(type, ident); #ifdef IN_GCC /* Setup function parameters for GCC backend */ TypeFunction * tf = (TypeFunction *) fd->type; Parameters * targs = new Parameters; targs->setDim(arguments->dim); for (unsigned i = 0; i < arguments->dim; i++) { targs->tdata()[i] = new Parameter(STCin, (arguments->tdata()[i])->type, NULL, NULL); } tf->parameters = targs; #endif } *pfd = fd; // cache symbol in hash table } /* Call the function fd(arguments) */ Expression *ec = new VarExp(0, fd); Expression *e = new CallExp(loc, ec, arguments); e->type = type; return e; }