comparison dmd2/dsymbol.c @ 758:f04dde6e882c

Added initial D2 support, D2 frontend and changes to codegen to make things compile.
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Tue, 11 Nov 2008 01:38:48 +0100
parents
children 356e65836fb5
comparison
equal deleted inserted replaced
757:2c730d530c98 758:f04dde6e882c
1
2 // Compiler implementation of the D programming language
3 // Copyright (c) 1999-2008 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 #include "attrib.h"
32
33 #include "../gen/enums.h"
34
35 /****************************** Dsymbol ******************************/
36
37 Dsymbol::Dsymbol()
38 {
39 //printf("Dsymbol::Dsymbol(%p)\n", this);
40 this->ident = NULL;
41 this->c_ident = NULL;
42 this->parent = NULL;
43 this->csym = NULL;
44 this->isym = NULL;
45 this->loc = 0;
46 this->comment = NULL;
47
48 this->llvmInternal = LLVMnone;
49 }
50
51 Dsymbol::Dsymbol(Identifier *ident)
52 {
53 //printf("Dsymbol::Dsymbol(%p, ident)\n", this);
54 this->ident = ident;
55 this->c_ident = NULL;
56 this->parent = NULL;
57 this->csym = NULL;
58 this->isym = NULL;
59 this->loc = 0;
60 this->comment = NULL;
61
62 this->llvmInternal = LLVMnone;
63 }
64
65 int Dsymbol::equals(Object *o)
66 { Dsymbol *s;
67
68 if (this == o)
69 return TRUE;
70 s = (Dsymbol *)(o);
71 if (s && ident->equals(s->ident))
72 return TRUE;
73 return FALSE;
74 }
75
76 /**************************************
77 * Copy the syntax.
78 * Used for template instantiations.
79 * If s is NULL, allocate the new object, otherwise fill it in.
80 */
81
82 Dsymbol *Dsymbol::syntaxCopy(Dsymbol *s)
83 {
84 print();
85 printf("%s %s\n", kind(), toChars());
86 assert(0);
87 return NULL;
88 }
89
90 /**************************************
91 * Determine if this symbol is only one.
92 * Returns:
93 * FALSE, *ps = NULL: There are 2 or more symbols
94 * TRUE, *ps = NULL: There are zero symbols
95 * TRUE, *ps = symbol: The one and only one symbol
96 */
97
98 int Dsymbol::oneMember(Dsymbol **ps)
99 {
100 //printf("Dsymbol::oneMember()\n");
101 *ps = this;
102 return TRUE;
103 }
104
105 /*****************************************
106 * Same as Dsymbol::oneMember(), but look at an array of Dsymbols.
107 */
108
109 int Dsymbol::oneMembers(Array *members, Dsymbol **ps)
110 {
111 //printf("Dsymbol::oneMembers() %d\n", members ? members->dim : 0);
112 Dsymbol *s = NULL;
113
114 if (members)
115 {
116 for (int i = 0; i < members->dim; i++)
117 { Dsymbol *sx = (Dsymbol *)members->data[i];
118
119 int x = sx->oneMember(ps);
120 //printf("\t[%d] kind %s = %d, s = %p\n", i, sx->kind(), x, *ps);
121 if (!x)
122 {
123 //printf("\tfalse 1\n");
124 assert(*ps == NULL);
125 return FALSE;
126 }
127 if (*ps)
128 {
129 if (s) // more than one symbol
130 { *ps = NULL;
131 //printf("\tfalse 2\n");
132 return FALSE;
133 }
134 s = *ps;
135 }
136 }
137 }
138 *ps = s; // s is the one symbol, NULL if none
139 //printf("\ttrue\n");
140 return TRUE;
141 }
142
143 /*****************************************
144 * Is Dsymbol a variable that contains pointers?
145 */
146
147 int Dsymbol::hasPointers()
148 {
149 //printf("Dsymbol::hasPointers() %s\n", toChars());
150 return 0;
151 }
152
153 char *Dsymbol::toChars()
154 {
155 return ident ? ident->toChars() : (char *)"__anonymous";
156 }
157
158 char *Dsymbol::toPrettyChars()
159 { Dsymbol *p;
160 char *s;
161 char *q;
162 size_t len;
163
164 //printf("Dsymbol::toPrettyChars() '%s'\n", toChars());
165 if (!parent)
166 return toChars();
167
168 len = 0;
169 for (p = this; p; p = p->parent)
170 len += strlen(p->toChars()) + 1;
171
172 s = (char *)mem.malloc(len);
173 q = s + len - 1;
174 *q = 0;
175 for (p = this; p; p = p->parent)
176 {
177 char *t = p->toChars();
178 len = strlen(t);
179 q -= len;
180 memcpy(q, t, len);
181 if (q == s)
182 break;
183 q--;
184 *q = '.';
185 }
186 return s;
187 }
188
189 char *Dsymbol::locToChars()
190 {
191 OutBuffer buf;
192 char *p;
193
194 Module *m = getModule();
195
196 if (m && m->srcfile)
197 loc.filename = m->srcfile->toChars();
198 return loc.toChars();
199 }
200
201 const char *Dsymbol::kind()
202 {
203 return "symbol";
204 }
205
206 /*********************************
207 * If this symbol is really an alias for another,
208 * return that other.
209 */
210
211 Dsymbol *Dsymbol::toAlias()
212 {
213 return this;
214 }
215
216 Dsymbol *Dsymbol::toParent()
217 {
218 return parent ? parent->pastMixin() : NULL;
219 }
220
221 Dsymbol *Dsymbol::pastMixin()
222 {
223 Dsymbol *s = this;
224
225 //printf("Dsymbol::pastMixin() %s\n", toChars());
226 while (s && s->isTemplateMixin())
227 s = s->parent;
228 return s;
229 }
230
231 /**********************************
232 * Use this instead of toParent() when looking for the
233 * 'this' pointer of the enclosing function/class.
234 */
235
236 Dsymbol *Dsymbol::toParent2()
237 {
238 Dsymbol *s = parent;
239 while (s && s->isTemplateInstance())
240 s = s->parent;
241 return s;
242 }
243
244 TemplateInstance *Dsymbol::inTemplateInstance()
245 {
246 for (Dsymbol *parent = this->parent; parent; parent = parent->parent)
247 {
248 TemplateInstance *ti = parent->isTemplateInstance();
249 if (ti)
250 return ti;
251 }
252 return NULL;
253 }
254
255 int Dsymbol::isAnonymous()
256 {
257 return ident ? 0 : 1;
258 }
259
260 void Dsymbol::semantic(Scope *sc)
261 {
262 error("%p has no semantic routine", this);
263 }
264
265 void Dsymbol::semantic2(Scope *sc)
266 {
267 // Most Dsymbols have no further semantic analysis needed
268 }
269
270 void Dsymbol::semantic3(Scope *sc)
271 {
272 // Most Dsymbols have no further semantic analysis needed
273 }
274
275 void Dsymbol::inlineScan()
276 {
277 // Most Dsymbols have no further semantic analysis needed
278 }
279
280 /*********************************************
281 * Search for ident as member of s.
282 * Input:
283 * flags: 1 don't find private members
284 * 2 don't give error messages
285 * 4 return NULL if ambiguous
286 * Returns:
287 * NULL if not found
288 */
289
290 Dsymbol *Dsymbol::search(Loc loc, Identifier *ident, int flags)
291 {
292 //printf("Dsymbol::search(this=%p,%s, ident='%s')\n", this, toChars(), ident->toChars());
293 return NULL;
294 }
295
296 /***************************************
297 * Search for identifier id as a member of 'this'.
298 * id may be a template instance.
299 * Returns:
300 * symbol found, NULL if not
301 */
302
303 Dsymbol *Dsymbol::searchX(Loc loc, Scope *sc, Identifier *id)
304 {
305 //printf("Dsymbol::searchX(this=%p,%s, ident='%s')\n", this, toChars(), ident->toChars());
306 Dsymbol *s = toAlias();
307 Dsymbol *sm;
308
309 switch (id->dyncast())
310 {
311 case DYNCAST_IDENTIFIER:
312 sm = s->search(loc, id, 0);
313 break;
314
315 case DYNCAST_DSYMBOL:
316 { // It's a template instance
317 //printf("\ttemplate instance id\n");
318 Dsymbol *st = (Dsymbol *)id;
319 TemplateInstance *ti = st->isTemplateInstance();
320 id = ti->name;
321 sm = s->search(loc, id, 0);
322 if (!sm)
323 { error("template identifier %s is not a member of %s %s",
324 id->toChars(), s->kind(), s->toChars());
325 return NULL;
326 }
327 sm = sm->toAlias();
328 TemplateDeclaration *td = sm->isTemplateDeclaration();
329 if (!td)
330 {
331 error("%s is not a template, it is a %s", id->toChars(), sm->kind());
332 return NULL;
333 }
334 ti->tempdecl = td;
335 if (!ti->semanticdone)
336 ti->semantic(sc);
337 sm = ti->toAlias();
338 break;
339 }
340
341 default:
342 assert(0);
343 }
344 return sm;
345 }
346
347 int Dsymbol::overloadInsert(Dsymbol *s)
348 {
349 //printf("Dsymbol::overloadInsert('%s')\n", s->toChars());
350 return FALSE;
351 }
352
353 void Dsymbol::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
354 {
355 buf->writestring(toChars());
356 }
357
358 unsigned Dsymbol::size(Loc loc)
359 {
360 error("Dsymbol '%s' has no size\n", toChars());
361 return 0;
362 }
363
364 int Dsymbol::isforwardRef()
365 {
366 return FALSE;
367 }
368
369 AggregateDeclaration *Dsymbol::isThis()
370 {
371 return NULL;
372 }
373
374 ClassDeclaration *Dsymbol::isClassMember() // are we a member of a class?
375 {
376 Dsymbol *parent = toParent();
377 if (parent && parent->isClassDeclaration())
378 return (ClassDeclaration *)parent;
379 return NULL;
380 }
381
382 void Dsymbol::defineRef(Dsymbol *s)
383 {
384 assert(0);
385 }
386
387 int Dsymbol::isExport()
388 {
389 return FALSE;
390 }
391
392 int Dsymbol::isImportedSymbol()
393 {
394 return FALSE;
395 }
396
397 int Dsymbol::isDeprecated()
398 {
399 return FALSE;
400 }
401
402 int Dsymbol::isOverloadable()
403 {
404 return 0;
405 }
406
407 LabelDsymbol *Dsymbol::isLabel() // is this a LabelDsymbol()?
408 {
409 return NULL;
410 }
411
412 AggregateDeclaration *Dsymbol::isMember() // is this a member of an AggregateDeclaration?
413 {
414 //printf("Dsymbol::isMember() %s\n", toChars());
415 Dsymbol *parent = toParent();
416 //printf("parent is %s %s\n", parent->kind(), parent->toChars());
417 return parent ? parent->isAggregateDeclaration() : NULL;
418 }
419
420 Type *Dsymbol::getType()
421 {
422 return NULL;
423 }
424
425 int Dsymbol::needThis()
426 {
427 return FALSE;
428 }
429
430 int Dsymbol::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
431 {
432 //printf("Dsymbol::addMember('%s')\n", toChars());
433 //printf("Dsymbol::addMember(this = %p, '%s' scopesym = '%s')\n", this, toChars(), sd->toChars());
434 //printf("Dsymbol::addMember(this = %p, '%s' sd = %p, sd->symtab = %p)\n", this, toChars(), sd, sd->symtab);
435 parent = sd;
436 if (!isAnonymous()) // no name, so can't add it to symbol table
437 {
438 if (!sd->symtab->insert(this)) // if name is already defined
439 {
440 Dsymbol *s2;
441
442 s2 = sd->symtab->lookup(ident);
443 if (!s2->overloadInsert(this))
444 {
445 sd->multiplyDefined(0, this, s2);
446 }
447 }
448 if (sd->isAggregateDeclaration() || sd->isEnumDeclaration())
449 {
450 if (ident == Id::__sizeof || ident == Id::alignof || ident == Id::mangleof)
451 error(".%s property cannot be redefined", ident->toChars());
452 }
453 return 1;
454 }
455 return 0;
456 }
457
458 void Dsymbol::error(const char *format, ...)
459 {
460 //printf("Dsymbol::error()\n");
461 if (!global.gag)
462 {
463 char *p = locToChars();
464
465 if (*p)
466 fprintf(stdmsg, "%s: ", p);
467 mem.free(p);
468
469 fprintf(stdmsg, "Error: ");
470 if (isAnonymous())
471 fprintf(stdmsg, "%s ", kind());
472 else
473 fprintf(stdmsg, "%s %s ", kind(), toPrettyChars());
474
475 va_list ap;
476 va_start(ap, format);
477 vfprintf(stdmsg, format, ap);
478 va_end(ap);
479
480 fprintf(stdmsg, "\n");
481 fflush(stdmsg);
482 }
483 global.errors++;
484
485 //fatal();
486 }
487
488 void Dsymbol::error(Loc loc, const char *format, ...)
489 {
490 if (!global.gag)
491 {
492 char *p = loc.toChars();
493 if (!*p)
494 p = locToChars();
495
496 if (*p)
497 fprintf(stdmsg, "%s: ", p);
498 mem.free(p);
499
500 fprintf(stdmsg, "Error: ");
501 fprintf(stdmsg, "%s %s ", kind(), toPrettyChars());
502
503 va_list ap;
504 va_start(ap, format);
505 vfprintf(stdmsg, format, ap);
506 va_end(ap);
507
508 fprintf(stdmsg, "\n");
509 fflush(stdmsg);
510 }
511
512 global.errors++;
513
514 //fatal();
515 }
516
517 void Dsymbol::checkDeprecated(Loc loc, Scope *sc)
518 {
519 if (!global.params.useDeprecated && isDeprecated())
520 {
521 // Don't complain if we're inside a deprecated symbol's scope
522 for (Dsymbol *sp = sc->parent; sp; sp = sp->parent)
523 { if (sp->isDeprecated())
524 return;
525 }
526
527 for (; sc; sc = sc->enclosing)
528 {
529 if (sc->scopesym && sc->scopesym->isDeprecated())
530 return;
531
532 // If inside a StorageClassDeclaration that is deprecated
533 if (sc->stc & STCdeprecated)
534 return;
535 }
536
537 error(loc, "is deprecated");
538 }
539 }
540
541 /**********************************
542 * Determine which Module a Dsymbol is in.
543 */
544
545 Module *Dsymbol::getModule()
546 {
547 Module *m;
548 Dsymbol *s;
549
550 //printf("Dsymbol::getModule()\n");
551 s = this;
552 while (s)
553 {
554 //printf("\ts = '%s'\n", s->toChars());
555 m = s->isModule();
556 if (m)
557 return m;
558 s = s->parent;
559 }
560 return NULL;
561 }
562
563 /*************************************
564 */
565
566 enum PROT Dsymbol::prot()
567 {
568 return PROTpublic;
569 }
570
571 /*************************************
572 * Do syntax copy of an array of Dsymbol's.
573 */
574
575
576 Array *Dsymbol::arraySyntaxCopy(Array *a)
577 {
578
579 Array *b = NULL;
580 if (a)
581 {
582 b = a->copy();
583 for (int i = 0; i < b->dim; i++)
584 {
585 Dsymbol *s = (Dsymbol *)b->data[i];
586
587 s = s->syntaxCopy(NULL);
588 b->data[i] = (void *)s;
589 }
590 }
591 return b;
592 }
593
594
595 /****************************************
596 * Add documentation comment to Dsymbol.
597 * Ignore NULL comments.
598 */
599
600 void Dsymbol::addComment(unsigned char *comment)
601 {
602 //if (comment)
603 //printf("adding comment '%s' to symbol %p '%s'\n", comment, this, toChars());
604
605 if (!this->comment)
606 this->comment = comment;
607 #if 1
608 else if (comment && strcmp((char *)comment, (char *)this->comment))
609 { // Concatenate the two
610 this->comment = Lexer::combineComments(this->comment, comment);
611 }
612 #endif
613 }
614
615 /********************************* OverloadSet ****************************/
616
617 OverloadSet::OverloadSet()
618 : Dsymbol()
619 {
620 }
621
622 void OverloadSet::push(Dsymbol *s)
623 {
624 a.push(s);
625 }
626
627 const char *OverloadSet::kind()
628 {
629 return "overloadset";
630 }
631
632
633 /********************************* ScopeDsymbol ****************************/
634
635 ScopeDsymbol::ScopeDsymbol()
636 : Dsymbol()
637 {
638 members = NULL;
639 symtab = NULL;
640 imports = NULL;
641 prots = NULL;
642 }
643
644 ScopeDsymbol::ScopeDsymbol(Identifier *id)
645 : Dsymbol(id)
646 {
647 members = NULL;
648 symtab = NULL;
649 imports = NULL;
650 prots = NULL;
651 }
652
653 Dsymbol *ScopeDsymbol::syntaxCopy(Dsymbol *s)
654 {
655 //printf("ScopeDsymbol::syntaxCopy('%s')\n", toChars());
656
657 ScopeDsymbol *sd;
658 if (s)
659 sd = (ScopeDsymbol *)s;
660 else
661 sd = new ScopeDsymbol(ident);
662 sd->members = arraySyntaxCopy(members);
663 return sd;
664 }
665
666 Dsymbol *ScopeDsymbol::search(Loc loc, Identifier *ident, int flags)
667 {
668 //printf("%s->ScopeDsymbol::search(ident='%s', flags=x%x)\n", toChars(), ident->toChars(), flags);
669
670 // Look in symbols declared in this module
671 Dsymbol *s = symtab ? symtab->lookup(ident) : NULL;
672
673 // hide private nonlocal symbols
674 if (flags & 1 && s && s->prot() == PROTprivate)
675 s = NULL;
676
677 if (s)
678 {
679 //printf("\ts = '%s.%s'\n",toChars(),s->toChars());
680 }
681 else if (imports)
682 {
683 OverloadSet *a = NULL;
684
685 // Look in imported modules
686 for (int i = 0; i < imports->dim; i++)
687 { ScopeDsymbol *ss = (ScopeDsymbol *)imports->data[i];
688 Dsymbol *s2;
689
690 // If private import, don't search it
691 if (flags & 1 && prots[i] == PROTprivate)
692 continue;
693
694 //printf("\tscanning import '%s', prots = %d, isModule = %p, isImport = %p\n", ss->toChars(), prots[i], ss->isModule(), ss->isImport());
695 /* Don't find private members if ss is a module
696 */
697 s2 = ss->search(loc, ident, ss->isModule() ? 1 : 0);
698 if (!s)
699 s = s2;
700 else if (s2 && s != s2)
701 {
702 if (s->toAlias() == s2->toAlias())
703 {
704 /* After following aliases, we found the same symbol,
705 * so it's not an ambiguity.
706 * But if one alias is deprecated, prefer the other.
707 */
708 if (s->isDeprecated())
709 s = s2;
710 }
711 else
712 {
713 /* Two imports of the same module should be regarded as
714 * the same.
715 */
716 Import *i1 = s->isImport();
717 Import *i2 = s2->isImport();
718 if (!(i1 && i2 &&
719 (i1->mod == i2->mod ||
720 (!i1->parent->isImport() && !i2->parent->isImport() &&
721 i1->ident->equals(i2->ident))
722 )
723 )
724 )
725 {
726 /* If both s2 and s are overloadable (though we only
727 * need to check s once)
728 */
729 if (s2->isOverloadable() && (a || s->isOverloadable()))
730 { if (!a)
731 a = new OverloadSet();
732 /* Don't add to a[] if s2 is alias of previous sym
733 */
734 for (int j = 0; j < a->a.dim; j++)
735 { Dsymbol *s3 = (Dsymbol *)a->a.data[j];
736 if (s2->toAlias() == s3->toAlias())
737 {
738 if (s3->isDeprecated())
739 a->a.data[j] = (void *)s2;
740 goto Lcontinue;
741 }
742 }
743 a->push(s2);
744 Lcontinue:
745 continue;
746 }
747 if (flags & 4) // if return NULL on ambiguity
748 return NULL;
749 if (!(flags & 2))
750 ss->multiplyDefined(loc, s, s2);
751 break;
752 }
753 }
754 }
755 }
756
757 /* Build special symbol if we had multiple finds
758 */
759 if (a)
760 { assert(s);
761 a->push(s);
762 s = a;
763 }
764
765 if (s)
766 {
767 Declaration *d = s->isDeclaration();
768 if (d && d->protection == PROTprivate &&
769 !d->parent->isTemplateMixin() &&
770 !(flags & 2))
771 error("%s is private", d->toPrettyChars());
772 }
773 }
774 return s;
775 }
776
777 void ScopeDsymbol::importScope(ScopeDsymbol *s, enum PROT protection)
778 {
779 //printf("%s->ScopeDsymbol::importScope(%s, %d)\n", toChars(), s->toChars(), protection);
780
781 // No circular or redundant import's
782 if (s != this)
783 {
784 if (!imports)
785 imports = new Array();
786 else
787 {
788 for (int i = 0; i < imports->dim; i++)
789 { ScopeDsymbol *ss;
790
791 ss = (ScopeDsymbol *) imports->data[i];
792 if (ss == s)
793 {
794 if (protection > prots[i])
795 prots[i] = protection; // upgrade access
796 return;
797 }
798 }
799 }
800 imports->push(s);
801 prots = (unsigned char *)mem.realloc(prots, imports->dim * sizeof(prots[0]));
802 prots[imports->dim - 1] = protection;
803 }
804 }
805
806 int ScopeDsymbol::isforwardRef()
807 {
808 return (members == NULL);
809 }
810
811 void ScopeDsymbol::defineRef(Dsymbol *s)
812 {
813 ScopeDsymbol *ss;
814
815 ss = s->isScopeDsymbol();
816 members = ss->members;
817 ss->members = NULL;
818 }
819
820 void ScopeDsymbol::multiplyDefined(Loc loc, Dsymbol *s1, Dsymbol *s2)
821 {
822 #if 0
823 printf("ScopeDsymbol::multiplyDefined()\n");
824 printf("s1 = %p, '%s' kind = '%s', parent = %s\n", s1, s1->toChars(), s1->kind(), s1->parent ? s1->parent->toChars() : "");
825 printf("s2 = %p, '%s' kind = '%s', parent = %s\n", s2, s2->toChars(), s2->kind(), s2->parent ? s2->parent->toChars() : "");
826 #endif
827 if (loc.filename)
828 { ::error(loc, "%s at %s conflicts with %s at %s",
829 s1->toPrettyChars(),
830 s1->locToChars(),
831 s2->toPrettyChars(),
832 s2->locToChars());
833 }
834 else
835 {
836 s1->error(loc, "conflicts with %s %s at %s",
837 s2->kind(),
838 s2->toPrettyChars(),
839 s2->locToChars());
840 }
841 halt();
842 }
843
844 Dsymbol *ScopeDsymbol::nameCollision(Dsymbol *s)
845 {
846 Dsymbol *sprev;
847
848 // Look to see if we are defining a forward referenced symbol
849
850 sprev = symtab->lookup(s->ident);
851 assert(sprev);
852 if (s->equals(sprev)) // if the same symbol
853 {
854 if (s->isforwardRef()) // if second declaration is a forward reference
855 return sprev;
856 if (sprev->isforwardRef())
857 {
858 sprev->defineRef(s); // copy data from s into sprev
859 return sprev;
860 }
861 }
862 multiplyDefined(0, s, sprev);
863 return sprev;
864 }
865
866 const char *ScopeDsymbol::kind()
867 {
868 return "ScopeDsymbol";
869 }
870
871
872 /***************************************
873 * Determine number of Dsymbols, folding in AttribDeclaration members.
874 */
875
876 size_t ScopeDsymbol::dim(Array *members)
877 {
878 size_t n = 0;
879 if (members)
880 {
881 for (size_t i = 0; i < members->dim; i++)
882 { Dsymbol *s = (Dsymbol *)members->data[i];
883 AttribDeclaration *a = s->isAttribDeclaration();
884
885 if (a)
886 {
887 n += dim(a->decl);
888 }
889 else
890 n++;
891 }
892 }
893 return n;
894 }
895
896 /***************************************
897 * Get nth Dsymbol, folding in AttribDeclaration members.
898 * Returns:
899 * Dsymbol* nth Dsymbol
900 * NULL not found, *pn gets incremented by the number
901 * of Dsymbols
902 */
903
904 Dsymbol *ScopeDsymbol::getNth(Array *members, size_t nth, size_t *pn)
905 {
906 if (!members)
907 return NULL;
908
909 size_t n = 0;
910 for (size_t i = 0; i < members->dim; i++)
911 { Dsymbol *s = (Dsymbol *)members->data[i];
912 AttribDeclaration *a = s->isAttribDeclaration();
913
914 if (a)
915 {
916 s = getNth(a->decl, nth - n, &n);
917 if (s)
918 return s;
919 }
920 else if (n == nth)
921 return s;
922 else
923 n++;
924 }
925
926 if (pn)
927 *pn += n;
928 return NULL;
929 }
930
931 /*******************************************
932 * Look for member of the form:
933 * const(MemberInfo)[] getMembers(string);
934 * Returns NULL if not found
935 */
936
937 #if DMDV2
938 FuncDeclaration *ScopeDsymbol::findGetMembers()
939 {
940 Dsymbol *s = search_function(this, Id::getmembers);
941 FuncDeclaration *fdx = s ? s->isFuncDeclaration() : NULL;
942
943 #if 0 // Finish
944 static TypeFunction *tfgetmembers;
945
946 if (!tfgetmembers)
947 {
948 Scope sc;
949 Arguments *arguments = new Arguments;
950 Arguments *arg = new Argument(STCin, Type::tchar->constOf()->arrayOf(), NULL, NULL);
951 arguments->push(arg);
952
953 Type *tret = NULL;
954 tfgetmembers = new TypeFunction(arguments, tret, 0, LINKd);
955 tfgetmembers = (TypeFunction *)tfgetmembers->semantic(0, &sc);
956 }
957 if (fdx)
958 fdx = fdx->overloadExactMatch(tfgetmembers);
959 #endif
960 if (fdx && fdx->isVirtual())
961 fdx = NULL;
962
963 return fdx;
964 }
965 #endif
966
967
968 /****************************** WithScopeSymbol ******************************/
969
970 WithScopeSymbol::WithScopeSymbol(WithStatement *withstate)
971 : ScopeDsymbol()
972 {
973 this->withstate = withstate;
974 }
975
976 Dsymbol *WithScopeSymbol::search(Loc loc, Identifier *ident, int flags)
977 {
978 // Acts as proxy to the with class declaration
979 return withstate->exp->type->toDsymbol(NULL)->search(loc, ident, 0);
980 }
981
982 /****************************** ArrayScopeSymbol ******************************/
983
984 ArrayScopeSymbol::ArrayScopeSymbol(Scope *sc, Expression *e)
985 : ScopeDsymbol()
986 {
987 assert(e->op == TOKindex || e->op == TOKslice);
988 exp = e;
989 type = NULL;
990 td = NULL;
991 this->sc = sc;
992 }
993
994 ArrayScopeSymbol::ArrayScopeSymbol(Scope *sc, TypeTuple *t)
995 : ScopeDsymbol()
996 {
997 exp = NULL;
998 type = t;
999 td = NULL;
1000 this->sc = sc;
1001 }
1002
1003 ArrayScopeSymbol::ArrayScopeSymbol(Scope *sc, TupleDeclaration *s)
1004 : ScopeDsymbol()
1005 {
1006 exp = NULL;
1007 type = NULL;
1008 td = s;
1009 this->sc = sc;
1010 }
1011
1012 Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags)
1013 {
1014 //printf("ArrayScopeSymbol::search('%s', flags = %d)\n", ident->toChars(), flags);
1015 if (ident == Id::length || ident == Id::dollar)
1016 { VarDeclaration **pvar;
1017 Expression *ce;
1018
1019 L1:
1020
1021 if (td)
1022 {
1023 VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL);
1024 Expression *e = new IntegerExp(0, td->objects->dim, Type::tsize_t);
1025 v->init = new ExpInitializer(0, e);
1026 v->storage_class |= STCstatic | STCconst;
1027 v->semantic(sc);
1028 return v;
1029 }
1030
1031 if (type)
1032 {
1033 VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL);
1034 Expression *e = new IntegerExp(0, type->arguments->dim, Type::tsize_t);
1035 v->init = new ExpInitializer(0, e);
1036 v->storage_class |= STCstatic | STCconst;
1037 v->semantic(sc);
1038 return v;
1039 }
1040
1041 if (exp->op == TOKindex)
1042 {
1043 IndexExp *ie = (IndexExp *)exp;
1044
1045 pvar = &ie->lengthVar;
1046 ce = ie->e1;
1047 }
1048 else if (exp->op == TOKslice)
1049 {
1050 SliceExp *se = (SliceExp *)exp;
1051
1052 pvar = &se->lengthVar;
1053 ce = se->e1;
1054 }
1055 else
1056 return NULL;
1057
1058 if (ce->op == TOKtype)
1059 {
1060 Type *t = ((TypeExp *)ce)->type;
1061 if (t->ty == Ttuple)
1062 { type = (TypeTuple *)t;
1063 goto L1;
1064 }
1065 }
1066
1067 if (!*pvar)
1068 {
1069 VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL);
1070
1071 if (ce->op == TOKvar)
1072 { // if ce is const, get its initializer
1073 ce = fromConstInitializer(WANTvalue | WANTinterpret, ce);
1074 }
1075
1076 if (ce->op == TOKstring)
1077 { /* It is for a string literal, so the
1078 * length will be a const.
1079 */
1080 Expression *e = new IntegerExp(0, ((StringExp *)ce)->len, Type::tsize_t);
1081 v->init = new ExpInitializer(0, e);
1082 v->storage_class |= STCstatic | STCconst;
1083 }
1084 else if (ce->op == TOKarrayliteral)
1085 { /* It is for an array literal, so the
1086 * length will be a const.
1087 */
1088 Expression *e = new IntegerExp(0, ((ArrayLiteralExp *)ce)->elements->dim, Type::tsize_t);
1089 v->init = new ExpInitializer(0, e);
1090 v->storage_class |= STCstatic | STCconst;
1091 }
1092 else if (ce->op == TOKtuple)
1093 { /* It is for an expression tuple, so the
1094 * length will be a const.
1095 */
1096 Expression *e = new IntegerExp(0, ((TupleExp *)ce)->exps->dim, Type::tsize_t);
1097 v->init = new ExpInitializer(0, e);
1098 v->storage_class |= STCstatic | STCconst;
1099 }
1100 *pvar = v;
1101 }
1102 (*pvar)->semantic(sc);
1103 return (*pvar);
1104 }
1105 return NULL;
1106 }
1107
1108
1109 /****************************** DsymbolTable ******************************/
1110
1111 DsymbolTable::DsymbolTable()
1112 {
1113 tab = new StringTable;
1114 }
1115
1116 DsymbolTable::~DsymbolTable()
1117 {
1118 delete tab;
1119 }
1120
1121 Dsymbol *DsymbolTable::lookup(Identifier *ident)
1122 { StringValue *sv;
1123
1124 #ifdef DEBUG
1125 assert(ident);
1126 assert(tab);
1127 #endif
1128 sv = tab->lookup((char*)ident->string, ident->len);
1129 return (Dsymbol *)(sv ? sv->ptrvalue : NULL);
1130 }
1131
1132 Dsymbol *DsymbolTable::insert(Dsymbol *s)
1133 { StringValue *sv;
1134 Identifier *ident;
1135
1136 //printf("DsymbolTable::insert(this = %p, '%s')\n", this, s->ident->toChars());
1137 ident = s->ident;
1138 #ifdef DEBUG
1139 assert(ident);
1140 assert(tab);
1141 #endif
1142 sv = tab->insert(ident->toChars(), ident->len);
1143 if (!sv)
1144 return NULL; // already in table
1145 sv->ptrvalue = s;
1146 return s;
1147 }
1148
1149 Dsymbol *DsymbolTable::insert(Identifier *ident, Dsymbol *s)
1150 { StringValue *sv;
1151
1152 //printf("DsymbolTable::insert()\n");
1153 sv = tab->insert(ident->toChars(), ident->len);
1154 if (!sv)
1155 return NULL; // already in table
1156 sv->ptrvalue = s;
1157 return s;
1158 }
1159
1160 Dsymbol *DsymbolTable::update(Dsymbol *s)
1161 { StringValue *sv;
1162 Identifier *ident;
1163
1164 ident = s->ident;
1165 sv = tab->update(ident->toChars(), ident->len);
1166 sv->ptrvalue = s;
1167 return s;
1168 }
1169
1170
1171
1172