root/trunk/src/init.c

Revision 569, 17.9 kB (checked in by walter, 2 years ago)

more 64 bit gen support, dmd now buildable as 64 bit app on Linux

  • Property svn:eol-style set to native
Line 
1 // Compiler implementation of the D programming language
2 // Copyright (c) 1999-2009 by Digital Mars
3 // All Rights Reserved
4 // written by Walter Bright
5 // http://www.digitalmars.com
6 // License for redistribution is by either the Artistic License
7 // in artistic.txt, or the GNU General Public License in gnu.txt.
8 // See the included readme.txt for details.
9
10 #include <stdio.h>
11 #include <assert.h>
12
13 #include "mars.h"
14 #include "init.h"
15 #include "expression.h"
16 #include "statement.h"
17 #include "identifier.h"
18 #include "declaration.h"
19 #include "aggregate.h"
20 #include "scope.h"
21 #include "mtype.h"
22 #include "hdrgen.h"
23
24 /********************************** Initializer *******************************/
25
26 Initializer::Initializer(Loc loc)
27 {
28     this->loc = loc;
29 }
30
31 Initializer *Initializer::syntaxCopy()
32 {
33     return this;
34 }
35
36 Initializer *Initializer::semantic(Scope *sc, Type *t)
37 {
38     return this;
39 }
40
41 Type *Initializer::inferType(Scope *sc)
42 {
43     error(loc, "cannot infer type from initializer");
44     return Type::terror;
45 }
46
47 Initializers *Initializer::arraySyntaxCopy(Initializers *ai)
48 {   Initializers *a = NULL;
49
50     if (ai)
51     {
52         a = new Initializers();
53         a->setDim(ai->dim);
54         for (int i = 0; i < a->dim; i++)
55         {   Initializer *e = (Initializer *)ai->data[i];
56
57             e = e->syntaxCopy();
58             a->data[i] = e;
59         }
60     }
61     return a;
62 }
63
64 char *Initializer::toChars()
65 {   OutBuffer *buf;
66     HdrGenState hgs;
67
68     memset(&hgs, 0, sizeof(hgs));
69     buf = new OutBuffer();
70     toCBuffer(buf, &hgs);
71     return buf->toChars();
72 }
73
74 /********************************** VoidInitializer ***************************/
75
76 VoidInitializer::VoidInitializer(Loc loc)
77     : Initializer(loc)
78 {
79     type = NULL;
80 }
81
82
83 Initializer *VoidInitializer::syntaxCopy()
84 {
85     return new VoidInitializer(loc);
86 }
87
88
89 Initializer *VoidInitializer::semantic(Scope *sc, Type *t)
90 {
91     //printf("VoidInitializer::semantic(t = %p)\n", t);
92     type = t;
93     return this;
94 }
95
96
97 Expression *VoidInitializer::toExpression()
98 {
99     error(loc, "void initializer has no value");
100     return new IntegerExp(0);
101 }
102
103
104 void VoidInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
105 {
106     buf->writestring("void");
107 }
108
109
110 /********************************** StructInitializer *************************/
111
112 StructInitializer::StructInitializer(Loc loc)
113     : Initializer(loc)
114 {
115     ad = NULL;
116 }
117
118 Initializer *StructInitializer::syntaxCopy()
119 {
120     StructInitializer *ai = new StructInitializer(loc);
121
122     assert(field.dim == value.dim);
123     ai->field.setDim(field.dim);
124     ai->value.setDim(value.dim);
125     for (int i = 0; i < field.dim; i++)
126     {
127         ai->field.data[i] = field.data[i];
128
129         Initializer *init = (Initializer *)value.data[i];
130         init = init->syntaxCopy();
131         ai->value.data[i] = init;
132     }
133     return ai;
134 }
135
136 void StructInitializer::addInit(Identifier *field, Initializer *value)
137 {
138     //printf("StructInitializer::addInit(field = %p, value = %p)\n", field, value);
139     this->field.push(field);
140     this->value.push(value);
141 }
142
143 Initializer *StructInitializer::semantic(Scope *sc, Type *t)
144 {
145     int errors = 0;
146
147     //printf("StructInitializer::semantic(t = %s) %s\n", t->toChars(), toChars());
148     vars.setDim(field.dim);
149     t = t->toBasetype();
150     if (t->ty == Tstruct)
151     {
152         unsigned fieldi = 0;
153
154         TypeStruct *ts = (TypeStruct *)t;
155         ad = ts->sym;
156         if (ad->ctor)
157             error(loc, "%s %s has constructors, cannot use { initializers }, use %s( initializers ) instead",
158                 ad->kind(), ad->toChars(), ad->toChars());
159         for (size_t i = 0; i < field.dim; i++)
160         {
161             Identifier *id = (Identifier *)field.data[i];
162             Initializer *val = (Initializer *)value.data[i];
163             Dsymbol *s;
164             VarDeclaration *v;
165
166             if (id == NULL)
167             {
168                 if (fieldi >= ad->fields.dim)
169                 {   error(loc, "too many initializers for %s", ad->toChars());
170                     field.remove(i);
171                     i--;
172                     continue;
173                 }
174                 else
175                 {
176                     s = (Dsymbol *)ad->fields.data[fieldi];
177                 }
178             }
179             else
180             {
181                 //s = ad->symtab->lookup(id);
182                 s = ad->search(loc, id, 0);
183                 if (!s)
184                 {
185                     error(loc, "'%s' is not a member of '%s'", id->toChars(), t->toChars());
186                     continue;
187                 }
188
189                 // Find out which field index it is
190                 for (fieldi = 0; 1; fieldi++)
191                 {
192                     if (fieldi >= ad->fields.dim)
193                     {
194                         s->error("is not a per-instance initializable field");
195                         break;
196                     }
197                     if (s == (Dsymbol *)ad->fields.data[fieldi])
198                         break;
199                 }
200             }
201             if (s && (v = s->isVarDeclaration()) != NULL)
202             {
203                 val = val->semantic(sc, v->type);
204                 value.data[i] = (void *)val;
205                 vars.data[i] = (void *)v;
206             }
207             else
208             {   error(loc, "%s is not a field of %s", id ? id->toChars() : s->toChars(), ad->toChars());
209                 errors = 1;
210             }
211             fieldi++;
212         }
213     }
214     else if (t->ty == Tdelegate && value.dim == 0)
215     {   /* Rewrite as empty delegate literal { }
216          */
217         Parameters *arguments = new Parameters;
218         Type *tf = new TypeFunction(arguments, NULL, 0, LINKd);
219         FuncLiteralDeclaration *fd = new FuncLiteralDeclaration(loc, 0, tf, TOKdelegate, NULL);
220         fd->fbody = new CompoundStatement(loc, new Statements());
221         fd->endloc = loc;
222         Expression *e = new FuncExp(loc, fd);
223         ExpInitializer *ie = new ExpInitializer(loc, e);
224         return ie->semantic(sc, t);
225     }
226     else
227     {
228         error(loc, "a struct is not a valid initializer for a %s", t->toChars());
229         errors = 1;
230     }
231     if (errors)
232     {
233         field.setDim(0);
234         value.setDim(0);
235         vars.setDim(0);
236     }
237     return this;
238 }
239
240
241 /***************************************
242  * This works by transforming a struct initializer into
243  * a struct literal. In the future, the two should be the
244  * same thing.
245  */
246 Expression *StructInitializer::toExpression()
247 {   Expression *e;
248
249     //printf("StructInitializer::toExpression() %s\n", toChars());
250     if (!ad)                            // if fwd referenced
251     {
252         return NULL;
253     }
254     StructDeclaration *sd = ad->isStructDeclaration();
255     if (!sd)
256         return NULL;
257     Expressions *elements = new Expressions();
258     for (size_t i = 0; i < value.dim; i++)
259     {
260         if (field.data[i])
261             goto Lno;
262         Initializer *iz = (Initializer *)value.data[i];
263         if (!iz)
264             goto Lno;
265         Expression *ex = iz->toExpression();
266         if (!ex)
267             goto Lno;
268         elements->push(ex);
269     }
270     e = new StructLiteralExp(loc, sd, elements);
271     e->type = sd->type;
272     return e;
273
274 Lno:
275     delete elements;
276     //error(loc, "struct initializers as expressions are not allowed");
277     return NULL;
278 }
279
280
281 void StructInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
282 {
283     //printf("StructInitializer::toCBuffer()\n");
284     buf->writebyte('{');
285     for (int i = 0; i < field.dim; i++)
286     {
287         if (i > 0)
288             buf->writebyte(',');
289         Identifier *id = (Identifier *)field.data[i];
290         if (id)
291         {
292             buf->writestring(id->toChars());
293             buf->writebyte(':');
294         }
295         Initializer *iz = (Initializer *)value.data[i];
296         if (iz)
297             iz->toCBuffer(buf, hgs);
298     }
299     buf->writebyte('}');
300 }
301
302 /********************************** ArrayInitializer ************************************/
303
304 ArrayInitializer::ArrayInitializer(Loc loc)
305     : Initializer(loc)
306 {
307     dim = 0;
308     type = NULL;
309     sem = 0;
310 }
311
312 Initializer *ArrayInitializer::syntaxCopy()
313 {
314     //printf("ArrayInitializer::syntaxCopy()\n");
315
316     ArrayInitializer *ai = new ArrayInitializer(loc);
317
318     assert(index.dim == value.dim);
319     ai->index.setDim(index.dim);
320     ai->value.setDim(value.dim);
321     for (int i = 0; i < ai->value.dim; i++)
322     {   Expression *e = (Expression *)index.data[i];
323         if (e)
324             e = e->syntaxCopy();
325         ai->index.data[i] = e;
326
327         Initializer *init = (Initializer *)value.data[i];
328         init = init->syntaxCopy();
329         ai->value.data[i] = init;
330     }
331     return ai;
332 }
333
334 void ArrayInitializer::addInit(Expression *index, Initializer *value)
335 {
336     this->index.push(index);
337     this->value.push(value);
338     dim = 0;
339     type = NULL;
340 }
341
342 Initializer *ArrayInitializer::semantic(Scope *sc, Type *t)
343 {   unsigned i;
344     unsigned length;
345     const unsigned amax = 0x80000000;
346
347     //printf("ArrayInitializer::semantic(%s)\n", t->toChars());
348     if (sem)                            // if semantic() already run
349         return this;
350     sem = 1;
351     type = t;
352     t = t->toBasetype();
353     switch (t->ty)
354     {
355         case Tpointer:
356         case Tsarray:
357         case Tarray:
358             break;
359
360         default:
361             error(loc, "cannot use array to initialize %s", type->toChars());
362             goto Lerr;
363     }
364
365     length = 0;
366     for (i = 0; i < index.dim; i++)
367     {
368         Expression *idx = (Expression *)index.data[i];
369         if (idx)
370         {   idx = idx->semantic(sc);
371             idx = idx->optimize(WANTvalue | WANTinterpret);
372             index.data[i] = (void *)idx;
373             length = idx->toInteger();
374         }
375
376         Initializer *val = (Initializer *)value.data[i];
377         val = val->semantic(sc, t->nextOf());
378         value.data[i] = (void *)val;
379         length++;
380         if (length == 0)
381         {   error(loc, "array dimension overflow");
382             goto Lerr;
383         }
384         if (length > dim)
385             dim = length;
386     }
387     if (t->ty == Tsarray)
388     {
389         dinteger_t edim = ((TypeSArray *)t)->dim->toInteger();
390         if (dim > edim)
391         {
392             error(loc, "array initializer has %u elements, but array length is %jd", dim, edim);
393             goto Lerr;
394         }
395     }
396
397     if ((unsigned long) dim * t->nextOf()->size() >= amax)
398     {   error(loc, "array dimension %u exceeds max of %u", dim, amax / t->nextOf()->size());
399         goto Lerr;
400     }
401     return this;
402
403 Lerr:
404     return new ExpInitializer(loc, new ErrorExp());
405 }
406
407 /********************************
408  * If possible, convert array initializer to array literal.
409  * Otherwise return NULL.
410  */
411
412 Expression *ArrayInitializer::toExpression()
413 {   Expressions *elements;
414     Expression *e;
415
416     //printf("ArrayInitializer::toExpression(), dim = %d\n", dim);
417     //static int i; if (++i == 2) halt();
418
419     size_t edim;
420     Type *t = NULL;
421     if (type)
422     {
423         if (type == Type::terror)
424             return new ErrorExp();
425
426         t = type->toBasetype();
427         switch (t->ty)
428         {
429            case Tsarray:
430                edim = ((TypeSArray *)t)->dim->toInteger();
431                break;
432
433            case Tpointer:
434            case Tarray:
435                 edim = dim;
436                 break;
437
438            default:
439                assert(0);
440         }
441     }
442     else
443     {
444         edim = value.dim;
445         for (size_t i = 0, j = 0; i < value.dim; i++, j++)
446         {
447             if (index.data[i])
448                 j = ((Expression *)index.data[i])->toInteger();
449             if (j >= edim)
450                 edim = j + 1;
451         }
452     }
453
454     elements = new Expressions();
455     elements->setDim(edim);
456     elements->zero();
457     for (size_t i = 0, j = 0; i < value.dim; i++, j++)
458     {
459         if (index.data[i])
460             j = ((Expression *)index.data[i])->toInteger();
461         assert(j < edim);
462         Initializer *iz = (Initializer *)value.data[i];
463         if (!iz)
464             goto Lno;
465         Expression *ex = iz->toExpression();
466         if (!ex)
467         {
468             goto Lno;
469         }
470         elements->data[j] = ex;
471     }
472
473     /* Fill in any missing elements with the default initializer
474      */
475     {
476     Expression *init = NULL;
477     for (size_t i = 0; i < edim; i++)
478     {
479         if (!elements->data[i])
480         {
481             if (!type)
482                 goto Lno;
483             if (!init)
484                 init = ((TypeNext *)t)->next->defaultInit();
485             elements->data[i] = init;
486         }
487     }
488
489     Expression *e = new ArrayLiteralExp(loc, elements);
490     e->type = type;
491     return e;
492     }
493
494 Lno:
495     return NULL;
496 }
497
498
499 /********************************
500  * If possible, convert array initializer to associative array initializer.
501  */
502
503 Expression *ArrayInitializer::toAssocArrayLiteral()
504 {
505     Expression *e;
506
507     //printf("ArrayInitializer::toAssocArrayInitializer()\n");
508     //static int i; if (++i == 2) halt();
509     Expressions *keys = new Expressions();
510     keys->setDim(value.dim);
511     Expressions *values = new Expressions();
512     values->setDim(value.dim);
513
514     for (size_t i = 0; i < value.dim; i++)
515     {
516         e = (Expression *)index.data[i];
517         if (!e)
518             goto Lno;
519         keys->data[i] = (void *)e;
520
521         Initializer *iz = (Initializer *)value.data[i];
522         if (!iz)
523             goto Lno;
524         e = iz->toExpression();
525         if (!e)
526             goto Lno;
527         values->data[i] = (void *)e;
528     }
529     e = new AssocArrayLiteralExp(loc, keys, values);
530     return e;
531
532 Lno:
533     delete keys;
534     delete values;
535     error(loc, "not an associative array initializer");
536     return new ErrorExp();
537 }
538
539 int ArrayInitializer::isAssociativeArray()
540 {
541     for (size_t i = 0; i < value.dim; i++)
542     {
543         if (index.data[i])
544             return 1;
545     }
546     return 0;
547 }
548
549 Type *ArrayInitializer::inferType(Scope *sc)
550 {
551     //printf("ArrayInitializer::inferType() %s\n", toChars());
552     assert(0);
553     return NULL;
554 #if 0
555     type = Type::terror;
556     for (size_t i = 0; i < value.dim; i++)
557     {
558         if (index.data[i])
559             goto Laa;
560     }
561     for (size_t i = 0; i < value.dim; i++)
562     {
563         Initializer *iz = (Initializer *)value.data[i];
564         if (iz)
565         {   Type *t = iz->inferType(sc);
566             if (i == 0)
567             {   /* BUG: This gets the type from the first element.
568                  * Fix to use all the elements to figure out the type.
569                  */
570                 t = new TypeSArray(t, new IntegerExp(value.dim));
571                 t = t->semantic(loc, sc);
572                 type = t;
573             }
574         }
575     }
576     return type;
577
578 Laa:
579     /* It's possibly an associative array initializer.
580      * BUG: inferring type from first member.
581      */
582     Initializer *iz = (Initializer *)value.data[0];
583     Expression *indexinit = (Expression *)index.data[0];
584     if (iz && indexinit)
585     {   Type *t = iz->inferType(sc);
586         indexinit = indexinit->semantic(sc);
587         Type *indext = indexinit->type;
588         t = new TypeAArray(t, indext);
589         type = t->semantic(loc, sc);
590     }
591     else
592         error(loc, "cannot infer type from this array initializer");
593     return type;
594 #endif
595 }
596
597
598 void ArrayInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
599 {
600     buf->writebyte('[');
601     for (int i = 0; i < index.dim; i++)
602     {
603         if (i > 0)
604             buf->writebyte(',');
605         Expression *ex = (Expression *)index.data[i];
606         if (ex)
607         {
608             ex->toCBuffer(buf, hgs);
609             buf->writebyte(':');
610         }
611         Initializer *iz = (Initializer *)value.data[i];
612         if (iz)
613             iz->toCBuffer(buf, hgs);
614     }
615     buf->writebyte(']');
616 }
617
618
619 /********************************** ExpInitializer ************************************/
620
621 ExpInitializer::ExpInitializer(Loc loc, Expression *exp)
622     : Initializer(loc)
623 {
624     this->exp = exp;
625 }
626
627 Initializer *ExpInitializer::syntaxCopy()
628 {
629     return new ExpInitializer(loc, exp->syntaxCopy());
630 }
631
632 Initializer *ExpInitializer::semantic(Scope *sc, Type *t)
633 {
634     //printf("ExpInitializer::semantic(%s), type = %s\n", exp->toChars(), t->toChars());
635     exp = exp->semantic(sc);
636     exp = resolveProperties(sc, exp);
637     exp = exp->optimize(WANTvalue | WANTinterpret);
638     Type *tb = t->toBasetype();
639
640     /* Look for case of initializing a static array with a too-short
641      * string literal, such as:
642      *  char[5] foo = "abc";
643      * Allow this by doing an explicit cast, which will lengthen the string
644      * literal.
645      */
646     if (exp->op == TOKstring && tb->ty == Tsarray && exp->type->ty == Tsarray)
647     {   StringExp *se = (StringExp *)exp;
648
649         if (!se->committed && se->type->ty == Tsarray &&
650             ((TypeSArray *)se->type)->dim->toInteger() <
651             ((TypeSArray *)t)->dim->toInteger())
652         {
653             exp = se->castTo(sc, t);
654             goto L1;
655         }
656     }
657
658     // Look for the case of statically initializing an array
659     // with a single member.
660     if (tb->ty == Tsarray &&
661         !tb->nextOf()->equals(exp->type->toBasetype()->nextOf()) &&
662         exp->implicitConvTo(tb->nextOf())
663        )
664     {
665         t = tb->nextOf();
666     }
667
668     exp = exp->implicitCastTo(sc, t);
669 L1:
670     exp = exp->optimize(WANTvalue | WANTinterpret);
671     //printf("-ExpInitializer::semantic(): "); exp->print();
672     return this;
673 }
674
675 Type *ExpInitializer::inferType(Scope *sc)
676 {
677     //printf("ExpInitializer::inferType() %s\n", toChars());
678     exp = exp->semantic(sc);
679     exp = resolveProperties(sc, exp);
680
681     // Give error for overloaded function addresses
682     if (exp->op == TOKsymoff)
683     {   SymOffExp *se = (SymOffExp *)exp;
684         if (se->hasOverloads && !se->var->isFuncDeclaration()->isUnique())
685             exp->error("cannot infer type from overloaded function symbol %s", exp->toChars());
686     }
687
688     // Give error for overloaded function addresses
689     if (exp->op == TOKdelegate)
690     {   DelegateExp *se = (DelegateExp *)exp;
691         if (
692             se->func->isFuncDeclaration() &&
693             !se->func->isFuncDeclaration()->isUnique())
694             exp->error("cannot infer type from overloaded function symbol %s", exp->toChars());
695     }
696
697     Type *t = exp->type;
698     if (!t)
699         t = Initializer::inferType(sc);
700     return t;
701 }
702
703 Expression *ExpInitializer::toExpression()
704 {
705     return exp;
706 }
707
708
709 void ExpInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
710 {
711     exp->toCBuffer(buf, hgs);
712 }
Note: See TracBrowser for help on using the browser.