comparison dmd/dsymbol.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-2007 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 <string.h>
13 #include <assert.h>
14
15 #include "mem.h"
16
17 #include "mars.h"
18 #include "dsymbol.h"
19 #include "aggregate.h"
20 #include "identifier.h"
21 #include "module.h"
22 #include "mtype.h"
23 #include "expression.h"
24 #include "statement.h"
25 #include "declaration.h"
26 #include "id.h"
27 #include "scope.h"
28 #include "init.h"
29 #include "import.h"
30 #include "template.h"
31
32 #include "../gen/enums.h"
33
34 /****************************** Dsymbol ******************************/
35
36 Dsymbol::Dsymbol()
37 {
38 //printf("Dsymbol::Dsymbol(%p)\n", this);
39 this->ident = NULL;
40 this->c_ident = NULL;
41 this->parent = NULL;
42 this->csym = NULL;
43 this->isym = NULL;
44 this->loc = 0;
45 this->comment = NULL;
46 this->llvmInternal = LLVMnone;
47 this->llvmInternal1 = NULL;
48 this->llvmInternal2 = NULL;
49 this->llvmValue = NULL;
50 }
51
52 Dsymbol::Dsymbol(Identifier *ident)
53 {
54 //printf("Dsymbol::Dsymbol(%p, ident)\n", this);
55 this->ident = ident;
56 this->c_ident = NULL;
57 this->parent = NULL;
58 this->csym = NULL;
59 this->isym = NULL;
60 this->loc = 0;
61 this->comment = NULL;
62 this->llvmInternal = LLVMnone;
63 this->llvmInternal1 = NULL;
64 this->llvmInternal2 = NULL;
65 this->llvmValue = NULL;
66 this->llvmDModule = NULL;
67 }
68
69 int Dsymbol::equals(Object *o)
70 { Dsymbol *s;
71
72 if (this == o)
73 return TRUE;
74 s = (Dsymbol *)(o);
75 if (s && ident->equals(s->ident))
76 return TRUE;
77 return FALSE;
78 }
79
80 /**************************************
81 * Copy the syntax.
82 * Used for template instantiations.
83 * If s is NULL, allocate the new object, otherwise fill it in.
84 */
85
86 Dsymbol *Dsymbol::syntaxCopy(Dsymbol *s)
87 {
88 print();
89 printf("%s %s\n", kind(), toChars());
90 assert(0);
91 return NULL;
92 }
93
94 /**************************************
95 * Determine if this symbol is only one.
96 * Returns:
97 * FALSE, *ps = NULL: There are 2 or more symbols
98 * TRUE, *ps = NULL: There are zero symbols
99 * TRUE, *ps = symbol: The one and only one symbol
100 */
101
102 int Dsymbol::oneMember(Dsymbol **ps)
103 {
104 //printf("Dsymbol::oneMember()\n");
105 *ps = this;
106 return TRUE;
107 }
108
109 /*****************************************
110 * Same as Dsymbol::oneMember(), but look at an array of Dsymbols.
111 */
112
113 int Dsymbol::oneMembers(Array *members, Dsymbol **ps)
114 {
115 //printf("Dsymbol::oneMembers() %d\n", members ? members->dim : 0);
116 Dsymbol *s = NULL;
117
118 if (members)
119 {
120 for (int i = 0; i < members->dim; i++)
121 { Dsymbol *sx = (Dsymbol *)members->data[i];
122
123 int x = sx->oneMember(ps);
124 //printf("\t[%d] kind %s = %d, s = %p\n", i, sx->kind(), x, *ps);
125 if (!x)
126 {
127 //printf("\tfalse 1\n");
128 assert(*ps == NULL);
129 return FALSE;
130 }
131 if (*ps)
132 {
133 if (s) // more than one symbol
134 { *ps = NULL;
135 //printf("\tfalse 2\n");
136 return FALSE;
137 }
138 s = *ps;
139 }
140 }
141 }
142 *ps = s; // s is the one symbol, NULL if none
143 //printf("\ttrue\n");
144 return TRUE;
145 }
146
147 /*****************************************
148 * Is Dsymbol a variable that contains pointers?
149 */
150
151 int Dsymbol::hasPointers()
152 {
153 //printf("Dsymbol::hasPointers() %s\n", toChars());
154 return 0;
155 }
156
157 char *Dsymbol::toChars()
158 {
159 return ident ? ident->toChars() : (char *)"__anonymous";
160 }
161
162 char *Dsymbol::toPrettyChars()
163 { Dsymbol *p;
164 char *s;
165 char *q;
166 size_t len;
167
168 //printf("Dsymbol::toPrettyChars() '%s'\n", toChars());
169 if (!parent)
170 return toChars();
171
172 len = 0;
173 for (p = this; p; p = p->parent)
174 len += strlen(p->toChars()) + 1;
175
176 s = (char *)mem.malloc(len);
177 q = s + len - 1;
178 *q = 0;
179 for (p = this; p; p = p->parent)
180 {
181 char *t = p->toChars();
182 len = strlen(t);
183 q -= len;
184 memcpy(q, t, len);
185 if (q == s)
186 break;
187 q--;
188 *q = '.';
189 }
190 return s;
191 }
192
193 char *Dsymbol::locToChars()
194 {
195 OutBuffer buf;
196 char *p;
197
198 Module *m = getModule();
199
200 if (m && m->srcfile)
201 loc.filename = m->srcfile->toChars();
202 return loc.toChars();
203 }
204
205 char *Dsymbol::kind()
206 {
207 return "symbol";
208 }
209
210 /*********************************
211 * If this symbol is really an alias for another,
212 * return that other.
213 */
214
215 Dsymbol *Dsymbol::toAlias()
216 {
217 return this;
218 }
219
220 Dsymbol *Dsymbol::toParent()
221 {
222 return parent ? parent->pastMixin() : NULL;
223 }
224
225 Dsymbol *Dsymbol::pastMixin()
226 {
227 Dsymbol *s = this;
228
229 //printf("Dsymbol::pastMixin() %s\n", toChars());
230 while (s && s->isTemplateMixin())
231 s = s->parent;
232 return s;
233 }
234
235 /**********************************
236 * Use this instead of toParent() when looking for the
237 * 'this' pointer of the enclosing function/class.
238 */
239
240 Dsymbol *Dsymbol::toParent2()
241 {
242 Dsymbol *s = parent;
243 while (s && s->isTemplateInstance())
244 s = s->parent;
245 return s;
246 }
247
248
249 int Dsymbol::isAnonymous()
250 {
251 return ident ? 0 : 1;
252 }
253
254 void Dsymbol::semantic(Scope *sc)
255 {
256 error("%p has no semantic routine", this);
257 }
258
259 void Dsymbol::semantic2(Scope *sc)
260 {
261 // Most Dsymbols have no further semantic analysis needed
262 }
263
264 void Dsymbol::semantic3(Scope *sc)
265 {
266 // Most Dsymbols have no further semantic analysis needed
267 }
268
269 void Dsymbol::inlineScan()
270 {
271 // Most Dsymbols have no further semantic analysis needed
272 }
273
274 Dsymbol *Dsymbol::search(Loc loc, Identifier *ident, int flags)
275 {
276 //printf("Dsymbol::search(this=%p,%s, ident='%s')\n", this, toChars(), ident->toChars());
277 return NULL;
278 }
279
280 /***************************************
281 * Search for identifier id as a member of 'this'.
282 * id may be a template instance.
283 * Returns:
284 * symbol found, NULL if not
285 */
286
287 Dsymbol *Dsymbol::searchX(Loc loc, Scope *sc, Identifier *id)
288 {
289 //printf("Dsymbol::searchX(this=%p,%s, ident='%s')\n", this, toChars(), ident->toChars());
290 Dsymbol *s = toAlias();
291 Dsymbol *sm;
292
293 switch (id->dyncast())
294 {
295 case DYNCAST_IDENTIFIER:
296 sm = s->search(loc, id, 0);
297 break;
298
299 case DYNCAST_DSYMBOL:
300 { // It's a template instance
301 //printf("\ttemplate instance id\n");
302 Dsymbol *st = (Dsymbol *)id;
303 TemplateInstance *ti = st->isTemplateInstance();
304 id = ti->name;
305 sm = s->search(loc, id, 0);
306 if (!sm)
307 { error("template identifier %s is not a member of %s %s",
308 id->toChars(), s->kind(), s->toChars());
309 return NULL;
310 }
311 sm = sm->toAlias();
312 TemplateDeclaration *td = sm->isTemplateDeclaration();
313 if (!td)
314 {
315 error("%s is not a template, it is a %s", id->toChars(), sm->kind());
316 return NULL;
317 }
318 ti->tempdecl = td;
319 if (!ti->semanticdone)
320 ti->semantic(sc);
321 sm = ti->toAlias();
322 break;
323 }
324
325 default:
326 assert(0);
327 }
328 return sm;
329 }
330
331 int Dsymbol::overloadInsert(Dsymbol *s)
332 {
333 //printf("Dsymbol::overloadInsert('%s')\n", s->toChars());
334 return FALSE;
335 }
336
337 void Dsymbol::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
338 {
339 buf->writestring(toChars());
340 }
341
342 unsigned Dsymbol::size(Loc loc)
343 {
344 error("Dsymbol '%s' has no size\n", toChars());
345 return 0;
346 }
347
348 int Dsymbol::isforwardRef()
349 {
350 return FALSE;
351 }
352
353 AggregateDeclaration *Dsymbol::isThis()
354 {
355 return NULL;
356 }
357
358 ClassDeclaration *Dsymbol::isClassMember() // are we a member of a class?
359 {
360 Dsymbol *parent = toParent();
361 if (parent && parent->isClassDeclaration())
362 return (ClassDeclaration *)parent;
363 return NULL;
364 }
365
366 void Dsymbol::defineRef(Dsymbol *s)
367 {
368 assert(0);
369 }
370
371 int Dsymbol::isExport()
372 {
373 return FALSE;
374 }
375
376 int Dsymbol::isImportedSymbol()
377 {
378 return FALSE;
379 }
380
381 int Dsymbol::isDeprecated()
382 {
383 return FALSE;
384 }
385
386 LabelDsymbol *Dsymbol::isLabel() // is this a LabelDsymbol()?
387 {
388 return NULL;
389 }
390
391 AggregateDeclaration *Dsymbol::isMember() // is this a member of an AggregateDeclaration?
392 {
393 Dsymbol *parent = toParent();
394 return parent ? parent->isAggregateDeclaration() : NULL;
395 }
396
397 Type *Dsymbol::getType()
398 {
399 return NULL;
400 }
401
402 int Dsymbol::needThis()
403 {
404 return FALSE;
405 }
406
407 int Dsymbol::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
408 {
409 //printf("Dsymbol::addMember('%s')\n", toChars());
410 //printf("Dsymbol::addMember(this = %p, '%s' scopesym = '%s')\n", this, toChars(), sd->toChars());
411 //printf("Dsymbol::addMember(this = %p, '%s' sd = %p, sd->symtab = %p)\n", this, toChars(), sd, sd->symtab);
412 parent = sd;
413 if (!isAnonymous()) // no name, so can't add it to symbol table
414 {
415 if (!sd->symtab->insert(this)) // if name is already defined
416 {
417 Dsymbol *s2;
418
419 s2 = sd->symtab->lookup(ident);
420 if (!s2->overloadInsert(this))
421 {
422 sd->multiplyDefined(0, this, s2);
423 }
424 }
425 if (sd->isAggregateDeclaration() || sd->isEnumDeclaration())
426 {
427 if (ident == Id::__sizeof || ident == Id::alignof || ident == Id::mangleof)
428 error(".%s property cannot be redefined", ident->toChars());
429 }
430 return 1;
431 }
432 return 0;
433 }
434
435 void Dsymbol::error(const char *format, ...)
436 {
437 //printf("Dsymbol::error()\n");
438 if (!global.gag)
439 {
440 char *p = locToChars();
441
442 if (*p)
443 fprintf(stdmsg, "%s: ", p);
444 mem.free(p);
445
446 if (isAnonymous())
447 fprintf(stdmsg, "%s ", kind());
448 else
449 fprintf(stdmsg, "%s %s ", kind(), toPrettyChars());
450
451 va_list ap;
452 va_start(ap, format);
453 vfprintf(stdmsg, format, ap);
454 va_end(ap);
455
456 fprintf(stdmsg, "\n");
457 fflush(stdmsg);
458 }
459 global.errors++;
460
461 //fatal();
462 }
463
464 void Dsymbol::error(Loc loc, const char *format, ...)
465 {
466 if (!global.gag)
467 {
468 char *p = loc.toChars();
469 if (!*p)
470 p = locToChars();
471
472 if (*p)
473 fprintf(stdmsg, "%s: ", p);
474 mem.free(p);
475
476 fprintf(stdmsg, "%s %s ", kind(), toPrettyChars());
477
478 va_list ap;
479 va_start(ap, format);
480 vfprintf(stdmsg, format, ap);
481 va_end(ap);
482
483 fprintf(stdmsg, "\n");
484 fflush(stdmsg);
485 }
486
487 global.errors++;
488
489 //fatal();
490 }
491
492 void Dsymbol::checkDeprecated(Loc loc, Scope *sc)
493 {
494 if (!global.params.useDeprecated && isDeprecated())
495 {
496 // Don't complain if we're inside a deprecated symbol's scope
497 for (Dsymbol *sp = sc->parent; sp; sp = sp->parent)
498 { if (sp->isDeprecated())
499 return;
500 }
501
502 for (; sc; sc = sc->enclosing)
503 {
504 if (sc->scopesym && sc->scopesym->isDeprecated())
505 return;
506 }
507
508 error(loc, "is deprecated");
509 }
510 }
511
512 /**********************************
513 * Determine which Module a Dsymbol is in.
514 */
515
516 Module *Dsymbol::getModule()
517 {
518 Module *m;
519 Dsymbol *s;
520
521 //printf("Dsymbol::getModule()\n");
522 s = this;
523 while (s)
524 {
525 //printf("\ts = '%s'\n", s->toChars());
526 m = s->isModule();
527 if (m)
528 return m;
529 s = s->parent;
530 }
531 return NULL;
532 }
533
534 /*************************************
535 */
536
537 enum PROT Dsymbol::prot()
538 {
539 return PROTpublic;
540 }
541
542 /*************************************
543 * Do syntax copy of an array of Dsymbol's.
544 */
545
546
547 Array *Dsymbol::arraySyntaxCopy(Array *a)
548 {
549
550 Array *b = NULL;
551 if (a)
552 {
553 b = a->copy();
554 for (int i = 0; i < b->dim; i++)
555 {
556 Dsymbol *s = (Dsymbol *)b->data[i];
557
558 s = s->syntaxCopy(NULL);
559 b->data[i] = (void *)s;
560 }
561 }
562 return b;
563 }
564
565
566 /****************************************
567 * Add documentation comment to Dsymbol.
568 * Ignore NULL comments.
569 */
570
571 void Dsymbol::addComment(unsigned char *comment)
572 {
573 // if (comment)
574 // printf("adding comment '%s' to symbol %p '%s'\n", comment, this, toChars());
575
576 if (!this->comment)
577 this->comment = comment;
578 #if 1
579 else if (comment && strcmp((char *)comment, (char *)this->comment))
580 { // Concatenate the two
581 this->comment = Lexer::combineComments(this->comment, comment);
582 }
583 #endif
584 }
585
586
587 /********************************* ScopeDsymbol ****************************/
588
589 ScopeDsymbol::ScopeDsymbol()
590 : Dsymbol()
591 {
592 members = NULL;
593 symtab = NULL;
594 imports = NULL;
595 prots = NULL;
596 }
597
598 ScopeDsymbol::ScopeDsymbol(Identifier *id)
599 : Dsymbol(id)
600 {
601 members = NULL;
602 symtab = NULL;
603 imports = NULL;
604 prots = NULL;
605 }
606
607 Dsymbol *ScopeDsymbol::syntaxCopy(Dsymbol *s)
608 {
609 //printf("ScopeDsymbol::syntaxCopy('%s')\n", toChars());
610
611 ScopeDsymbol *sd;
612 if (s)
613 sd = (ScopeDsymbol *)s;
614 else
615 sd = new ScopeDsymbol(ident);
616 sd->members = arraySyntaxCopy(members);
617 return sd;
618 }
619
620 Dsymbol *ScopeDsymbol::search(Loc loc, Identifier *ident, int flags)
621 { Dsymbol *s;
622 int i;
623
624 //printf("%s->ScopeDsymbol::search(ident='%s', flags=x%x)\n", toChars(), ident->toChars(), flags);
625 // Look in symbols declared in this module
626 s = symtab ? symtab->lookup(ident) : NULL;
627 if (s)
628 {
629 //printf("\ts = '%s.%s'\n",toChars(),s->toChars());
630 }
631 else if (imports)
632 {
633 // Look in imported modules
634 for (i = 0; i < imports->dim; i++)
635 { ScopeDsymbol *ss = (ScopeDsymbol *)imports->data[i];
636 Dsymbol *s2;
637
638 // If private import, don't search it
639 if (flags & 1 && prots[i] == PROTprivate)
640 continue;
641
642 //printf("\tscanning import '%s', prots = %d, isModule = %p, isImport = %p\n", ss->toChars(), prots[i], ss->isModule(), ss->isImport());
643 s2 = ss->search(loc, ident, ss->isModule() ? 1 : 0);
644 if (!s)
645 s = s2;
646 else if (s2 && s != s2)
647 {
648 if (s->toAlias() == s2->toAlias())
649 {
650 if (s->isDeprecated())
651 s = s2;
652 }
653 else
654 {
655 /* Two imports of the same module should be regarded as
656 * the same.
657 */
658 Import *i1 = s->isImport();
659 Import *i2 = s2->isImport();
660 if (!(i1 && i2 &&
661 (i1->mod == i2->mod ||
662 (!i1->parent->isImport() && !i2->parent->isImport() &&
663 i1->ident->equals(i2->ident))
664 )
665 )
666 )
667 {
668 ss->multiplyDefined(loc, s, s2);
669 break;
670 }
671 }
672 }
673 }
674 if (s)
675 {
676 Declaration *d = s->isDeclaration();
677 if (d && d->protection == PROTprivate && !d->parent->isTemplateMixin())
678 error("%s is private", d->toPrettyChars());
679 }
680 }
681 return s;
682 }
683
684 void ScopeDsymbol::importScope(ScopeDsymbol *s, enum PROT protection)
685 {
686 //printf("%s->ScopeDsymbol::importScope(%s, %d)\n", toChars(), s->toChars(), protection);
687
688 // No circular or redundant import's
689 if (s != this)
690 {
691 if (!imports)
692 imports = new Array();
693 else
694 {
695 for (int i = 0; i < imports->dim; i++)
696 { ScopeDsymbol *ss;
697
698 ss = (ScopeDsymbol *) imports->data[i];
699 if (ss == s)
700 {
701 if (protection > prots[i])
702 prots[i] = protection; // upgrade access
703 return;
704 }
705 }
706 }
707 imports->push(s);
708 prots = (unsigned char *)mem.realloc(prots, imports->dim * sizeof(prots[0]));
709 prots[imports->dim - 1] = protection;
710 }
711 }
712
713 int ScopeDsymbol::isforwardRef()
714 {
715 return (members == NULL);
716 }
717
718 void ScopeDsymbol::defineRef(Dsymbol *s)
719 {
720 ScopeDsymbol *ss;
721
722 ss = s->isScopeDsymbol();
723 members = ss->members;
724 ss->members = NULL;
725 }
726
727 void ScopeDsymbol::multiplyDefined(Loc loc, Dsymbol *s1, Dsymbol *s2)
728 {
729 #if 0
730 printf("ScopeDsymbol::multiplyDefined()\n");
731 printf("s1 = %p, '%s' kind = '%s', parent = %s\n", s1, s1->toChars(), s1->kind(), s1->parent ? s1->parent->toChars() : "");
732 printf("s2 = %p, '%s' kind = '%s', parent = %s\n", s2, s2->toChars(), s2->kind(), s2->parent ? s2->parent->toChars() : "");
733 #endif
734 if (loc.filename)
735 { ::error(loc, "%s at %s conflicts with %s at %s",
736 s1->toPrettyChars(),
737 s1->locToChars(),
738 s2->toPrettyChars(),
739 s2->locToChars());
740 }
741 else
742 {
743 s1->error(loc, "conflicts with %s %s at %s",
744 s2->kind(),
745 s2->toPrettyChars(),
746 s2->locToChars());
747 }
748 }
749
750 Dsymbol *ScopeDsymbol::nameCollision(Dsymbol *s)
751 {
752 Dsymbol *sprev;
753
754 // Look to see if we are defining a forward referenced symbol
755
756 sprev = symtab->lookup(s->ident);
757 assert(sprev);
758 if (s->equals(sprev)) // if the same symbol
759 {
760 if (s->isforwardRef()) // if second declaration is a forward reference
761 return sprev;
762 if (sprev->isforwardRef())
763 {
764 sprev->defineRef(s); // copy data from s into sprev
765 return sprev;
766 }
767 }
768 multiplyDefined(0, s, sprev);
769 return sprev;
770 }
771
772 char *ScopeDsymbol::kind()
773 {
774 return "ScopeDsymbol";
775 }
776
777
778 /****************************** WithScopeSymbol ******************************/
779
780 WithScopeSymbol::WithScopeSymbol(WithStatement *withstate)
781 : ScopeDsymbol()
782 {
783 this->withstate = withstate;
784 }
785
786 Dsymbol *WithScopeSymbol::search(Loc loc, Identifier *ident, int flags)
787 {
788 // Acts as proxy to the with class declaration
789 return withstate->exp->type->toDsymbol(NULL)->search(loc, ident, 0);
790 }
791
792 /****************************** ArrayScopeSymbol ******************************/
793
794 ArrayScopeSymbol::ArrayScopeSymbol(Expression *e)
795 : ScopeDsymbol()
796 {
797 assert(e->op == TOKindex || e->op == TOKslice);
798 exp = e;
799 type = NULL;
800 td = NULL;
801 }
802
803 ArrayScopeSymbol::ArrayScopeSymbol(TypeTuple *t)
804 : ScopeDsymbol()
805 {
806 exp = NULL;
807 type = t;
808 td = NULL;
809 }
810
811 ArrayScopeSymbol::ArrayScopeSymbol(TupleDeclaration *s)
812 : ScopeDsymbol()
813 {
814 exp = NULL;
815 type = NULL;
816 td = s;
817 }
818
819 Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags)
820 {
821 //printf("ArrayScopeSymbol::search('%s', flags = %d)\n", ident->toChars(), flags);
822 if (ident == Id::length || ident == Id::dollar)
823 { VarDeclaration **pvar;
824 Expression *ce;
825
826 L1:
827
828 if (td)
829 {
830 VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL);
831 Expression *e = new IntegerExp(0, td->objects->dim, Type::tsize_t);
832 v->init = new ExpInitializer(0, e);
833 v->storage_class |= STCconst;
834 return v;
835 }
836
837 if (type)
838 {
839 VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL);
840 Expression *e = new IntegerExp(0, type->arguments->dim, Type::tsize_t);
841 v->init = new ExpInitializer(0, e);
842 v->storage_class |= STCconst;
843 return v;
844 }
845
846 if (exp->op == TOKindex)
847 {
848 IndexExp *ie = (IndexExp *)exp;
849
850 pvar = &ie->lengthVar;
851 ce = ie->e1;
852 }
853 else if (exp->op == TOKslice)
854 {
855 SliceExp *se = (SliceExp *)exp;
856
857 pvar = &se->lengthVar;
858 ce = se->e1;
859 }
860 else
861 return NULL;
862
863 if (ce->op == TOKtype)
864 {
865 Type *t = ((TypeExp *)ce)->type;
866 if (t->ty == Ttuple)
867 { type = (TypeTuple *)t;
868 goto L1;
869 }
870 }
871
872 if (!*pvar)
873 {
874 VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL);
875
876 if (ce->op == TOKstring)
877 { /* It is for a string literal, so the
878 * length will be a const.
879 */
880 Expression *e = new IntegerExp(0, ((StringExp *)ce)->len, Type::tsize_t);
881 v->init = new ExpInitializer(0, e);
882 v->storage_class |= STCconst;
883 }
884 else if (ce->op == TOKarrayliteral)
885 { /* It is for an array literal, so the
886 * length will be a const.
887 */
888 Expression *e = new IntegerExp(0, ((ArrayLiteralExp *)ce)->elements->dim, Type::tsize_t);
889 v->init = new ExpInitializer(0, e);
890 v->storage_class |= STCconst;
891 }
892 else if (ce->op == TOKtuple)
893 { /* It is for an expression tuple, so the
894 * length will be a const.
895 */
896 Expression *e = new IntegerExp(0, ((TupleExp *)ce)->exps->dim, Type::tsize_t);
897 v->init = new ExpInitializer(0, e);
898 v->storage_class |= STCconst;
899 }
900 *pvar = v;
901 }
902 return (*pvar);
903 }
904 return NULL;
905 }
906
907
908 /****************************** DsymbolTable ******************************/
909
910 DsymbolTable::DsymbolTable()
911 {
912 tab = new StringTable;
913 }
914
915 DsymbolTable::~DsymbolTable()
916 {
917 delete tab;
918 }
919
920 Dsymbol *DsymbolTable::lookup(Identifier *ident)
921 { StringValue *sv;
922
923 #ifdef DEBUG
924 assert(ident);
925 assert(tab);
926 #endif
927 sv = tab->lookup((char*)ident->string, ident->len);
928 return (Dsymbol *)(sv ? sv->ptrvalue : NULL);
929 }
930
931 Dsymbol *DsymbolTable::insert(Dsymbol *s)
932 { StringValue *sv;
933 Identifier *ident;
934
935 //printf("DsymbolTable::insert(this = %p, '%s')\n", this, s->ident->toChars());
936 ident = s->ident;
937 #ifdef DEBUG
938 assert(ident);
939 assert(tab);
940 #endif
941 sv = tab->insert(ident->toChars(), ident->len);
942 if (!sv)
943 return NULL; // already in table
944 sv->ptrvalue = s;
945 return s;
946 }
947
948 Dsymbol *DsymbolTable::insert(Identifier *ident, Dsymbol *s)
949 { StringValue *sv;
950
951 //printf("DsymbolTable::insert()\n");
952 sv = tab->insert(ident->toChars(), ident->len);
953 if (!sv)
954 return NULL; // already in table
955 sv->ptrvalue = s;
956 return s;
957 }
958
959 Dsymbol *DsymbolTable::update(Dsymbol *s)
960 { StringValue *sv;
961 Identifier *ident;
962
963 ident = s->ident;
964 sv = tab->update(ident->toChars(), ident->len);
965 sv->ptrvalue = s;
966 return s;
967 }
968
969
970
971