comparison dmd/init.c @ 1:c53b6e3fe49a trunk

[svn r5] Initial commit. Most things are very rough.
author lindquist
date Sat, 01 Sep 2007 21:43:27 +0200
parents
children 788401029ecf
comparison
equal deleted inserted replaced
0:a9e71648e74d 1:c53b6e3fe49a
1
2 // Compiler implementation of the D programming language
3 // Copyright (c) 1999-2006 by Digital Mars
4 // All Rights Reserved
5 // written by Walter Bright
6 // http://www.digitalmars.com
7 // License for redistribution is by either the Artistic License
8 // in artistic.txt, or the GNU General Public License in gnu.txt.
9 // See the included readme.txt for details.
10
11 #include <stdio.h>
12 #include <assert.h>
13
14 #include "mars.h"
15 #include "init.h"
16 #include "expression.h"
17 #include "statement.h"
18 #include "identifier.h"
19 #include "declaration.h"
20 #include "aggregate.h"
21 #include "scope.h"
22 #include "mtype.h"
23 #include "hdrgen.h"
24
25 /********************************** Initializer *******************************/
26
27 Initializer::Initializer(Loc loc)
28 {
29 this->loc = loc;
30 }
31
32 Initializer *Initializer::syntaxCopy()
33 {
34 return this;
35 }
36
37 Initializer *Initializer::semantic(Scope *sc, Type *t)
38 {
39 return this;
40 }
41
42 Type *Initializer::inferType(Scope *sc)
43 {
44 error(loc, "cannot infer type from initializer");
45 return Type::terror;
46 }
47
48 Initializers *Initializer::arraySyntaxCopy(Initializers *ai)
49 { Initializers *a = NULL;
50
51 if (ai)
52 {
53 a = new Initializers();
54 a->setDim(ai->dim);
55 for (int i = 0; i < a->dim; i++)
56 { Initializer *e = (Initializer *)ai->data[i];
57
58 e = e->syntaxCopy();
59 a->data[i] = e;
60 }
61 }
62 return a;
63 }
64
65 char *Initializer::toChars()
66 { OutBuffer *buf;
67 HdrGenState hgs;
68
69 memset(&hgs, 0, sizeof(hgs));
70 buf = new OutBuffer();
71 toCBuffer(buf, &hgs);
72 return buf->toChars();
73 }
74
75 /********************************** VoidInitializer ***************************/
76
77 VoidInitializer::VoidInitializer(Loc loc)
78 : Initializer(loc)
79 {
80 type = NULL;
81 }
82
83
84 Initializer *VoidInitializer::syntaxCopy()
85 {
86 return new VoidInitializer(loc);
87 }
88
89
90 Initializer *VoidInitializer::semantic(Scope *sc, Type *t)
91 {
92 //printf("VoidInitializer::semantic(t = %p)\n", t);
93 type = t;
94 return this;
95 }
96
97
98 Expression *VoidInitializer::toExpression()
99 {
100 error(loc, "void initializer has no value");
101 return new IntegerExp(0);
102 }
103
104
105 void VoidInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
106 {
107 buf->writestring("void");
108 }
109
110
111 /********************************** StructInitializer *************************/
112
113 StructInitializer::StructInitializer(Loc loc)
114 : Initializer(loc)
115 {
116 ad = NULL;
117 }
118
119 Initializer *StructInitializer::syntaxCopy()
120 {
121 StructInitializer *ai = new StructInitializer(loc);
122
123 assert(field.dim == value.dim);
124 ai->field.setDim(field.dim);
125 ai->value.setDim(value.dim);
126 for (int i = 0; i < field.dim; i++)
127 {
128 ai->field.data[i] = field.data[i];
129
130 Initializer *init = (Initializer *)value.data[i];
131 init = init->syntaxCopy();
132 ai->value.data[i] = init;
133 }
134 return ai;
135 }
136
137 void StructInitializer::addInit(Identifier *field, Initializer *value)
138 {
139 //printf("StructInitializer::addInit(field = %p, value = %p)\n", field, value);
140 this->field.push(field);
141 this->value.push(value);
142 }
143
144 Initializer *StructInitializer::semantic(Scope *sc, Type *t)
145 {
146 TypeStruct *ts;
147 int errors = 0;
148
149 //printf("StructInitializer::semantic(t = %s) %s\n", t->toChars(), toChars());
150 vars.setDim(field.dim);
151 t = t->toBasetype();
152 if (t->ty == Tstruct)
153 { unsigned i;
154 unsigned fieldi = 0;
155
156 ts = (TypeStruct *)t;
157 ad = ts->sym;
158 for (i = 0; i < field.dim; i++)
159 {
160 Identifier *id = (Identifier *)field.data[i];
161 Initializer *val = (Initializer *)value.data[i];
162 Dsymbol *s;
163 VarDeclaration *v;
164
165 if (id == NULL)
166 {
167 if (fieldi >= ad->fields.dim)
168 { error(loc, "too many initializers for %s", ad->toChars());
169 continue;
170 }
171 else
172 {
173 s = (Dsymbol *)ad->fields.data[fieldi];
174 }
175 }
176 else
177 {
178 //s = ad->symtab->lookup(id);
179 s = ad->search(loc, id, 0);
180 if (!s)
181 {
182 error("'%s' is not a member of '%s'", id->toChars(), t->toChars());
183 continue;
184 }
185
186 // Find out which field index it is
187 for (fieldi = 0; 1; fieldi++)
188 {
189 if (fieldi >= ad->fields.dim)
190 {
191 s->error("is not a per-instance initializable field");
192 break;
193 }
194 if (s == (Dsymbol *)ad->fields.data[fieldi])
195 break;
196 }
197 }
198 if (s && (v = s->isVarDeclaration()) != NULL)
199 {
200 val = val->semantic(sc, v->type);
201 value.data[i] = (void *)val;
202 vars.data[i] = (void *)v;
203 }
204 else
205 { error(loc, "%s is not a field of %s", id ? id->toChars() : s->toChars(), ad->toChars());
206 errors = 1;
207 }
208 fieldi++;
209 }
210 }
211 else if (t->ty == Tdelegate && value.dim == 0)
212 { /* Rewrite as empty delegate literal { }
213 */
214 Arguments *arguments = new Arguments;
215 Type *tf = new TypeFunction(arguments, NULL, 0, LINKd);
216 FuncLiteralDeclaration *fd = new FuncLiteralDeclaration(loc, 0, tf, TOKdelegate, NULL);
217 fd->fbody = new CompoundStatement(loc, new Statements());
218 fd->endloc = loc;
219 Expression *e = new FuncExp(loc, fd);
220 ExpInitializer *ie = new ExpInitializer(loc, e);
221 return ie->semantic(sc, t);
222 }
223 else
224 {
225 error(loc, "a struct is not a valid initializer for a %s", t->toChars());
226 errors = 1;
227 }
228 if (errors)
229 {
230 field.setDim(0);
231 value.setDim(0);
232 vars.setDim(0);
233 }
234 return this;
235 }
236
237
238 Expression *StructInitializer::toExpression()
239 {
240 return NULL; // cannot do it
241 }
242
243
244 void StructInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
245 {
246 //printf("StructInitializer::toCBuffer()\n");
247 buf->writebyte('{');
248 for (int i = 0; i < field.dim; i++)
249 {
250 if (i > 0)
251 buf->writebyte(',');
252 Identifier *id = (Identifier *)field.data[i];
253 if (id)
254 {
255 buf->writestring(id->toChars());
256 buf->writebyte(':');
257 }
258 Initializer *iz = (Initializer *)value.data[i];
259 if (iz)
260 iz->toCBuffer(buf, hgs);
261 }
262 buf->writebyte('}');
263 }
264
265 /********************************** ArrayInitializer ************************************/
266
267 ArrayInitializer::ArrayInitializer(Loc loc)
268 : Initializer(loc)
269 {
270 dim = 0;
271 type = NULL;
272 sem = 0;
273 }
274
275 Initializer *ArrayInitializer::syntaxCopy()
276 {
277 //printf("ArrayInitializer::syntaxCopy()\n");
278
279 ArrayInitializer *ai = new ArrayInitializer(loc);
280
281 assert(index.dim == value.dim);
282 ai->index.setDim(index.dim);
283 ai->value.setDim(value.dim);
284 for (int i = 0; i < ai->value.dim; i++)
285 { Expression *e = (Expression *)index.data[i];
286 if (e)
287 e = e->syntaxCopy();
288 ai->index.data[i] = e;
289
290 Initializer *init = (Initializer *)value.data[i];
291 init = init->syntaxCopy();
292 ai->value.data[i] = init;
293 }
294 return ai;
295 }
296
297 void ArrayInitializer::addInit(Expression *index, Initializer *value)
298 {
299 this->index.push(index);
300 this->value.push(value);
301 dim = 0;
302 type = NULL;
303 }
304
305 Initializer *ArrayInitializer::semantic(Scope *sc, Type *t)
306 { unsigned i;
307 unsigned length;
308
309 //printf("ArrayInitializer::semantic(%s)\n", t->toChars());
310 if (sem) // if semantic() already run
311 return this;
312 sem = 1;
313 type = t;
314 t = t->toBasetype();
315 switch (t->ty)
316 {
317 case Tpointer:
318 case Tsarray:
319 case Tarray:
320 break;
321
322 default:
323 error(loc, "cannot use array to initialize %s", type->toChars());
324 return this;
325 }
326
327 length = 0;
328 for (i = 0; i < index.dim; i++)
329 { Expression *idx;
330 Initializer *val;
331
332 idx = (Expression *)index.data[i];
333 if (idx)
334 { idx = idx->semantic(sc);
335 idx = idx->optimize(WANTvalue | WANTinterpret);
336 index.data[i] = (void *)idx;
337 length = idx->toInteger();
338 }
339
340 val = (Initializer *)value.data[i];
341 val = val->semantic(sc, t->next);
342 value.data[i] = (void *)val;
343 length++;
344 if (length == 0)
345 error("array dimension overflow");
346 if (length > dim)
347 dim = length;
348 }
349 unsigned long amax = 0x80000000;
350 if ((unsigned long) dim * t->next->size() >= amax)
351 error(loc, "array dimension %u exceeds max of %ju", dim, amax / t->next->size());
352 return this;
353 }
354
355 /********************************
356 * If possible, convert array initializer to array literal.
357 */
358
359 Expression *ArrayInitializer::toExpression()
360 { Expressions *elements;
361 Expression *e;
362
363 //printf("ArrayInitializer::toExpression()\n");
364 //static int i; if (++i == 2) halt();
365 elements = new Expressions();
366 for (size_t i = 0; i < value.dim; i++)
367 {
368 if (index.data[i])
369 goto Lno;
370 Initializer *iz = (Initializer *)value.data[i];
371 if (!iz)
372 goto Lno;
373 Expression *ex = iz->toExpression();
374 if (!ex)
375 goto Lno;
376 elements->push(ex);
377 }
378 e = new ArrayLiteralExp(loc, elements);
379 e->type = type;
380 return e;
381
382 Lno:
383 delete elements;
384 error(loc, "array initializers as expressions are not allowed");
385 return NULL;
386 }
387
388
389 /********************************
390 * If possible, convert array initializer to associative array initializer.
391 */
392
393 Initializer *ArrayInitializer::toAssocArrayInitializer()
394 { Expressions *keys;
395 Expressions *values;
396 Expression *e;
397
398 //printf("ArrayInitializer::toAssocArrayInitializer()\n");
399 //static int i; if (++i == 2) halt();
400 keys = new Expressions();
401 keys->setDim(value.dim);
402 values = new Expressions();
403 values->setDim(value.dim);
404
405 for (size_t i = 0; i < value.dim; i++)
406 {
407 e = (Expression *)index.data[i];
408 if (!e)
409 goto Lno;
410 keys->data[i] = (void *)e;
411
412 Initializer *iz = (Initializer *)value.data[i];
413 if (!iz)
414 goto Lno;
415 e = iz->toExpression();
416 if (!e)
417 goto Lno;
418 values->data[i] = (void *)e;
419 }
420 e = new AssocArrayLiteralExp(loc, keys, values);
421 return new ExpInitializer(loc, e);
422
423 Lno:
424 delete keys;
425 delete values;
426 error(loc, "not an associative array initializer");
427 return this;
428 }
429
430
431 Type *ArrayInitializer::inferType(Scope *sc)
432 {
433 for (size_t i = 0; i < value.dim; i++)
434 {
435 if (index.data[i])
436 goto Lno;
437 }
438 if (value.dim)
439 {
440 Initializer *iz = (Initializer *)value.data[0];
441 if (iz)
442 { Type *t = iz->inferType(sc);
443 t = new TypeSArray(t, new IntegerExp(value.dim));
444 t = t->semantic(loc, sc);
445 return t;
446 }
447 }
448
449 Lno:
450 error(loc, "cannot infer type from this array initializer");
451 return Type::terror;
452 }
453
454
455 void ArrayInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
456 {
457 buf->writebyte('[');
458 for (int i = 0; i < index.dim; i++)
459 {
460 if (i > 0)
461 buf->writebyte(',');
462 Expression *ex = (Expression *)index.data[i];
463 if (ex)
464 {
465 ex->toCBuffer(buf, hgs);
466 buf->writebyte(':');
467 }
468 Initializer *iz = (Initializer *)value.data[i];
469 if (iz)
470 iz->toCBuffer(buf, hgs);
471 }
472 buf->writebyte(']');
473 }
474
475
476 /********************************** ExpInitializer ************************************/
477
478 ExpInitializer::ExpInitializer(Loc loc, Expression *exp)
479 : Initializer(loc)
480 {
481 this->exp = exp;
482 }
483
484 Initializer *ExpInitializer::syntaxCopy()
485 {
486 return new ExpInitializer(loc, exp->syntaxCopy());
487 }
488
489 Initializer *ExpInitializer::semantic(Scope *sc, Type *t)
490 {
491 //printf("ExpInitializer::semantic(%s), type = %s\n", exp->toChars(), t->toChars());
492 exp = exp->semantic(sc);
493 Type *tb = t->toBasetype();
494
495 /* Look for case of initializing a static array with a too-short
496 * string literal, such as:
497 * char[5] foo = "abc";
498 * Allow this by doing an explicit cast, which will lengthen the string
499 * literal.
500 */
501 if (exp->op == TOKstring && tb->ty == Tsarray && exp->type->ty == Tsarray)
502 { StringExp *se = (StringExp *)exp;
503
504 if (!se->committed && se->type->ty == Tsarray &&
505 ((TypeSArray *)se->type)->dim->toInteger() <
506 ((TypeSArray *)t)->dim->toInteger())
507 {
508 exp = se->castTo(sc, t);
509 goto L1;
510 }
511 }
512
513 // Look for the case of statically initializing an array
514 // with a single member.
515 if (tb->ty == Tsarray &&
516 !tb->next->equals(exp->type->toBasetype()->next) &&
517 exp->implicitConvTo(tb->next)
518 )
519 {
520 t = tb->next;
521 }
522
523 exp = exp->implicitCastTo(sc, t);
524 L1:
525 exp = exp->optimize(WANTvalue | WANTinterpret);
526 //printf("-ExpInitializer::semantic(): "); exp->print();
527 return this;
528 }
529
530 Type *ExpInitializer::inferType(Scope *sc)
531 {
532 //printf("ExpInitializer::inferType() %s\n", toChars());
533 exp = exp->semantic(sc);
534 exp = resolveProperties(sc, exp);
535 return exp->type;
536 }
537
538 Expression *ExpInitializer::toExpression()
539 {
540 return exp;
541 }
542
543
544 void ExpInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
545 {
546 exp->toCBuffer(buf, hgs);
547 }
548
549
550