args type is now "string[]"
[delight/core.git] / dmd2 / module.c
blobb41d86ae98db33435042782a807dc91a5108ec47
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.
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <assert.h>
15 #ifdef _MSC_VER
16 #include <malloc.h>
17 #endif
19 #if IN_GCC
20 #include "gdc_alloca.h"
21 #endif
23 #include "mem.h"
25 #include "mars.h"
26 #include "module.h"
27 #include "parse.h"
28 #include "scope.h"
29 #include "identifier.h"
30 #include "id.h"
31 #include "import.h"
32 #include "dsymbol.h"
33 #include "hdrgen.h"
34 #include "lexer.h"
35 #include "init.h"
37 #define MARS 1
38 #include "html.h"
40 #ifdef IN_GCC
41 #include "d-dmd-gcc.h"
42 #endif
44 ClassDeclaration *Module::moduleinfo;
46 Module *Module::rootModule;
47 DsymbolTable *Module::modules;
48 Array Module::amodules;
50 Array Module::deferred; // deferred Dsymbol's needing semantic() run on them
51 unsigned Module::dprogress;
53 void Module::init()
55 modules = new DsymbolTable();
58 Module::Module(char *filename, Identifier *ident, int doDocComment, int doHdrGen, int isDltFile)
59 : Package(ident), isDltFile(isDltFile)
61 FileName *srcfilename;
62 FileName *cfilename;
63 FileName *hfilename;
64 FileName *objfilename;
65 FileName *symfilename;
67 // printf("Module::Module(filename = '%s', ident = '%s')\n", filename, ident->toChars());
68 this->arg = filename;
69 md = NULL;
70 errors = 0;
71 numlines = 0;
72 members = NULL;
73 isHtml = 0;
74 isDocFile = 0;
75 needmoduleinfo = 0;
76 #ifdef IN_GCC
77 strictlyneedmoduleinfo = 0;
78 #endif
79 insearch = 0;
80 searchCacheIdent = NULL;
81 searchCacheSymbol = NULL;
82 searchCacheFlags = 0;
83 semanticstarted = 0;
84 semanticdone = 0;
85 decldefs = NULL;
86 vmoduleinfo = NULL;
87 massert = NULL;
88 marray = NULL;
89 sictor = NULL;
90 sctor = NULL;
91 sdtor = NULL;
92 stest = NULL;
93 sfilename = NULL;
94 root = 0;
95 importedFrom = NULL;
96 srcfile = NULL;
97 docfile = NULL;
99 debuglevel = 0;
100 debugids = NULL;
101 debugidsNot = NULL;
102 versionlevel = 0;
103 versionids = NULL;
104 versionidsNot = NULL;
106 macrotable = NULL;
107 escapetable = NULL;
108 doppelganger = 0;
109 cov = NULL;
110 covb = NULL;
112 srcfilename = FileName::defaultExt(filename, global.dlt_ext);
113 if (!srcfilename->equalsExt(global.mars_ext) &&
114 !srcfilename->equalsExt(global.dlt_ext) &&
115 !srcfilename->equalsExt("dd"))
117 if (srcfilename->equalsExt("html") ||
118 srcfilename->equalsExt("htm") ||
119 srcfilename->equalsExt("xhtml"))
120 { if (!global.params.useDeprecated)
121 error("html source files is deprecated %s", srcfilename->toChars());
122 isHtml = 1;
124 else
125 { error("source file name '%s' must have .%s extension", srcfilename->toChars(), global.dlt_ext);
126 fatal();
130 char *argobj;
131 if (global.params.objname)
132 argobj = global.params.objname;
133 else if (global.params.preservePaths)
134 argobj = filename;
135 else
136 argobj = FileName::name(filename);
137 if (!FileName::absolute(argobj))
139 argobj = FileName::combine(global.params.objdir, argobj);
142 if (global.params.objname)
143 objfilename = new FileName(argobj, 0);
144 else
145 objfilename = FileName::forceExt(argobj, global.obj_ext);
147 symfilename = FileName::forceExt(filename, global.sym_ext);
149 srcfile = new File(srcfilename);
151 if (doDocComment)
153 setDocfile();
156 if (doHdrGen)
158 setHdrfile();
161 objfile = new File(objfilename);
162 symfile = new File(symfilename);
165 void Module::setDocfile()
167 FileName *docfilename;
168 char *argdoc;
170 if (global.params.docname)
171 argdoc = global.params.docname;
172 else if (global.params.preservePaths)
173 argdoc = (char *)arg;
174 else
175 argdoc = FileName::name((char *)arg);
176 if (!FileName::absolute(argdoc))
177 { //FileName::ensurePathExists(global.params.docdir);
178 argdoc = FileName::combine(global.params.docdir, argdoc);
180 if (global.params.docname)
181 docfilename = new FileName(argdoc, 0);
182 else
183 docfilename = FileName::forceExt(argdoc, global.doc_ext);
185 if (docfilename->equals(srcfile->name))
186 { error("Source file and documentation file have same name '%s'", srcfile->name->str);
187 fatal();
190 docfile = new File(docfilename);
193 void Module::setHdrfile()
195 FileName *hdrfilename;
196 char *arghdr;
198 if (global.params.hdrname)
199 arghdr = global.params.hdrname;
200 else if (global.params.preservePaths)
201 arghdr = (char *)arg;
202 else
203 arghdr = FileName::name((char *)arg);
204 if (!FileName::absolute(arghdr))
205 { //FileName::ensurePathExists(global.params.hdrdir);
206 arghdr = FileName::combine(global.params.hdrdir, arghdr);
208 if (global.params.hdrname)
209 hdrfilename = new FileName(arghdr, 0);
210 else
211 hdrfilename = FileName::forceExt(arghdr, global.hdr_ext);
213 if (hdrfilename->equals(srcfile->name))
214 { error("Source file and 'header' file have same name '%s'", srcfile->name->str);
215 fatal();
218 hdrfile = new File(hdrfilename);
221 void Module::deleteObjFile()
223 if (global.params.obj)
224 objfile->remove();
225 if (docfile)
226 docfile->remove();
229 Module::~Module()
233 char *Module::kind()
235 return "module";
238 Module *Module::load(Loc loc, Array *packages, Identifier *ident)
239 { Module *m;
240 char *filename;
241 bool dltSyntax = false;
243 //printf("Module::load(ident = '%s')\n", ident->toChars());
245 // Build module filename by turning:
246 // foo.bar.baz
247 // into:
248 // foo\bar\baz
249 filename = ident->toChars();
250 if (packages && packages->dim)
252 OutBuffer buf;
253 int i;
255 for (i = 0; i < packages->dim; i++)
256 { Identifier *pid = (Identifier *)packages->data[i];
258 buf.writestring(pid->toChars());
259 #if _WIN32
260 buf.writeByte('\\');
261 #else
262 buf.writeByte('/');
263 #endif
265 buf.writestring(filename);
266 buf.writeByte(0);
267 filename = (char *)buf.extractData();
270 /* Search along global.path for a .dlt file, then a .di file, then a .d file.
272 char *result = NULL;
273 FileName *fdlt = FileName::forceExt(filename, global.dlt_ext);
274 FileName *fdi = FileName::forceExt(filename, global.hdr_ext);
275 FileName *fd = FileName::forceExt(filename, global.mars_ext);
276 char *sdlt = fdlt->toChars();
277 char *sdi = fdi->toChars();
278 char *sd = fd->toChars();
280 if (FileName::exists(sdlt))
282 result = sdlt;
283 dltSyntax = true;
285 else if (FileName::exists(sdi))
286 result = sdi;
287 else if (FileName::exists(sd))
288 result = sd;
289 else if (FileName::absolute(filename))
291 else if (!global.path)
293 else
295 for (size_t i = 0; i < global.path->dim; i++)
297 char *p = (char *)global.path->data[i];
298 char *n;
300 n = FileName::combine(p, sdlt);
301 if (FileName::exists(n))
302 { result = n;
303 dltSyntax = true;
304 break;
306 mem.free(n);
308 n = FileName::combine(p, sdi);
309 if (FileName::exists(n))
310 { result = n;
311 break;
313 mem.free(n);
315 n = FileName::combine(p, sd);
316 if (FileName::exists(n))
317 { result = n;
318 break;
320 mem.free(n);
324 m = new Module(filename, ident, 0, 0, dltSyntax);
325 m->loc = loc;
327 if (result)
328 m->srcfile = new File(result);
330 if (global.params.verbose)
332 printf("import ");
333 if (packages)
335 for (size_t i = 0; i < packages->dim; i++)
336 { Identifier *pid = (Identifier *)packages->data[i];
337 printf("%s.", pid->toChars());
340 printf("%s\t(%s)\n", ident->toChars(), m->srcfile->toChars());
343 m->read(loc);
344 m->parse();
346 #ifdef IN_GCC
347 d_gcc_magic_module(m);
348 #endif
350 return m;
353 void Module::read(Loc loc)
355 //printf("Module::read('%s') file '%s'\n", toChars(), srcfile->toChars());
356 if (srcfile->read())
357 { error(loc, "cannot read file '%s'", srcfile->toChars());
358 fatal();
362 inline unsigned readwordLE(unsigned short *p)
364 #if __I86__
365 return *p;
366 #else
367 return (((unsigned char *)p)[1] << 8) | ((unsigned char *)p)[0];
368 #endif
371 inline unsigned readwordBE(unsigned short *p)
373 return (((unsigned char *)p)[0] << 8) | ((unsigned char *)p)[1];
376 inline unsigned readlongLE(unsigned *p)
378 #if __I86__
379 return *p;
380 #else
381 return ((unsigned char *)p)[0] |
382 (((unsigned char *)p)[1] << 8) |
383 (((unsigned char *)p)[2] << 16) |
384 (((unsigned char *)p)[3] << 24);
385 #endif
388 inline unsigned readlongBE(unsigned *p)
390 return ((unsigned char *)p)[3] |
391 (((unsigned char *)p)[2] << 8) |
392 (((unsigned char *)p)[1] << 16) |
393 (((unsigned char *)p)[0] << 24);
396 #if IN_GCC
397 void Module::parse(bool dump_source)
398 #else
399 void Module::parse()
400 #endif
401 { char *srcname;
402 unsigned char *buf;
403 unsigned buflen;
404 unsigned le;
405 unsigned bom;
407 //printf("Module::parse()\n");
409 srcname = srcfile->name->toChars();
410 //printf("Module::parse(srcname = '%s')\n", srcname);
412 buf = srcfile->buffer;
413 buflen = srcfile->len;
415 if (buflen >= 2)
417 /* Convert all non-UTF-8 formats to UTF-8.
418 * BOM : http://www.unicode.org/faq/utf_bom.html
419 * 00 00 FE FF UTF-32BE, big-endian
420 * FF FE 00 00 UTF-32LE, little-endian
421 * FE FF UTF-16BE, big-endian
422 * FF FE UTF-16LE, little-endian
423 * EF BB BF UTF-8
426 bom = 1; // assume there's a BOM
427 if (buf[0] == 0xFF && buf[1] == 0xFE)
429 if (buflen >= 4 && buf[2] == 0 && buf[3] == 0)
430 { // UTF-32LE
431 le = 1;
433 Lutf32:
434 OutBuffer dbuf;
435 unsigned *pu = (unsigned *)(buf);
436 unsigned *pumax = &pu[buflen / 4];
438 if (buflen & 3)
439 { error("odd length of UTF-32 char source %u", buflen);
440 fatal();
443 dbuf.reserve(buflen / 4);
444 for (pu += bom; pu < pumax; pu++)
445 { unsigned u;
447 u = le ? readlongLE(pu) : readlongBE(pu);
448 if (u & ~0x7F)
450 if (u > 0x10FFFF)
451 { error("UTF-32 value %08x greater than 0x10FFFF", u);
452 fatal();
454 dbuf.writeUTF8(u);
456 else
457 dbuf.writeByte(u);
459 dbuf.writeByte(0); // add 0 as sentinel for scanner
460 buflen = dbuf.offset - 1; // don't include sentinel in count
461 buf = (unsigned char *) dbuf.extractData();
463 else
464 { // UTF-16LE (X86)
465 // Convert it to UTF-8
466 le = 1;
468 Lutf16:
469 OutBuffer dbuf;
470 unsigned short *pu = (unsigned short *)(buf);
471 unsigned short *pumax = &pu[buflen / 2];
473 if (buflen & 1)
474 { error("odd length of UTF-16 char source %u", buflen);
475 fatal();
478 dbuf.reserve(buflen / 2);
479 for (pu += bom; pu < pumax; pu++)
480 { unsigned u;
482 u = le ? readwordLE(pu) : readwordBE(pu);
483 if (u & ~0x7F)
484 { if (u >= 0xD800 && u <= 0xDBFF)
485 { unsigned u2;
487 if (++pu > pumax)
488 { error("surrogate UTF-16 high value %04x at EOF", u);
489 fatal();
491 u2 = le ? readwordLE(pu) : readwordBE(pu);
492 if (u2 < 0xDC00 || u2 > 0xDFFF)
493 { error("surrogate UTF-16 low value %04x out of range", u2);
494 fatal();
496 u = (u - 0xD7C0) << 10;
497 u |= (u2 - 0xDC00);
499 else if (u >= 0xDC00 && u <= 0xDFFF)
500 { error("unpaired surrogate UTF-16 value %04x", u);
501 fatal();
503 else if (u == 0xFFFE || u == 0xFFFF)
504 { error("illegal UTF-16 value %04x", u);
505 fatal();
507 dbuf.writeUTF8(u);
509 else
510 dbuf.writeByte(u);
512 dbuf.writeByte(0); // add 0 as sentinel for scanner
513 buflen = dbuf.offset - 1; // don't include sentinel in count
514 buf = (unsigned char *) dbuf.extractData();
517 else if (buf[0] == 0xFE && buf[1] == 0xFF)
518 { // UTF-16BE
519 le = 0;
520 goto Lutf16;
522 else if (buflen >= 4 && buf[0] == 0 && buf[1] == 0 && buf[2] == 0xFE && buf[3] == 0xFF)
523 { // UTF-32BE
524 le = 0;
525 goto Lutf32;
527 else if (buflen >= 3 && buf[0] == 0xEF && buf[1] == 0xBB && buf[2] == 0xBF)
528 { // UTF-8
530 buf += 3;
531 buflen -= 3;
533 else
535 /* There is no BOM. Make use of Arcane Jill's insight that
536 * the first char of D source must be ASCII to
537 * figure out the encoding.
540 bom = 0;
541 if (buflen >= 4)
542 { if (buf[1] == 0 && buf[2] == 0 && buf[3] == 0)
543 { // UTF-32LE
544 le = 1;
545 goto Lutf32;
547 else if (buf[0] == 0 && buf[1] == 0 && buf[2] == 0)
548 { // UTF-32BE
549 le = 0;
550 goto Lutf32;
553 if (buflen >= 2)
555 if (buf[1] == 0)
556 { // UTF-16LE
557 le = 1;
558 goto Lutf16;
560 else if (buf[0] == 0)
561 { // UTF-16BE
562 le = 0;
563 goto Lutf16;
567 // It's UTF-8
568 if (buf[0] >= 0x80)
569 { error("source file must start with BOM or ASCII character, not \\x%02X", buf[0]);
570 fatal();
575 #ifdef IN_GCC
576 // dump utf-8 encoded source
577 if (dump_source)
578 { // %% srcname could contain a path ...
579 d_gcc_dump_source(srcname, "utf-8", buf, buflen);
581 #endif
583 /* If it starts with the string "Ddoc", then it's a documentation
584 * source file.
586 if (buflen >= 4 && memcmp(buf, "Ddoc", 4) == 0)
588 comment = buf + 4;
589 isDocFile = 1;
590 if (!docfile)
591 setDocfile();
592 return;
594 if (isHtml)
596 OutBuffer *dbuf = new OutBuffer();
597 Html h(srcname, buf, buflen);
598 h.extractCode(dbuf);
599 buf = dbuf->data;
600 buflen = dbuf->offset;
601 #ifdef IN_GCC
602 // dump extracted source
603 if (dump_source)
604 d_gcc_dump_source(srcname, "d.utf-8", buf, buflen);
605 #endif
608 if (isDltFile)
610 DltParser p(this, buf, buflen, docfile != NULL);
611 p.nextToken();
612 members = p.parseModule();
613 md = p.md;
614 numlines = p.loc.linnum;
616 else
618 Parser p(this, buf, buflen, docfile != NULL);
619 p.nextToken();
620 members = p.parseModule();
621 md = p.md;
622 numlines = p.loc.linnum;
625 DsymbolTable *dst;
627 if (md)
628 { this->ident = md->id;
629 dst = Package::resolve(md->packages, &this->parent, NULL);
631 else
633 dst = modules;
635 /* Check to see if module name is a valid identifier
637 if (!Lexer::isValidIdentifier(this->ident->toChars()))
638 error("has non-identifier characters in filename, use module declaration instead");
641 // Update global list of modules
642 if (!dst->insert(this))
644 if (md)
645 error(loc, "is in multiple packages %s", md->toChars());
646 else
647 error(loc, "is in multiple defined");
649 else
651 amodules.push(this);
655 static FuncDeclaration *addMainFunction(Dsymbol *mainClass) {
656 ClassDeclaration *klass = mainClass->isClassDeclaration();
657 if (klass == NULL) {
658 // Just ignore it then?
659 error("'Main' is not a class!");
660 return NULL;
663 Loc loc = mainClass->loc;
665 // Create a main(string[] args) function
666 Arguments *arguments = new Arguments();
668 Type *tstr = new TypeDArray(Type::tchar->invariantOf());
669 Type *targv = new TypeDArray(tstr);
671 Argument *a = new Argument(0, targv, Id::args, NULL);
672 arguments->push(a);
674 TypeFunction *ta = new TypeFunction(arguments, new Type(Tvoid), 0, LINKc);
675 FuncDeclaration *f = new FuncDeclaration(loc, 0, Id::main, STCundefined, ta);
677 f->fbody = new InjectorMainBody(loc, klass);
679 return f;
682 void Module::semantic()
683 { int i;
685 if (semanticstarted)
686 return;
688 Array *dlt_package = new Array();
689 dlt_package->push(Id::dlt);
691 //printf("+Module::semantic(this = %p, '%s'): parent = %p\n", this, toChars(), parent);
692 semanticstarted = 1;
694 // Note that modules get their own scope, from scratch.
695 // This is so regardless of where in the syntax a module
696 // gets imported, it is unaffected by context.
697 Scope *sc = Scope::createGlobal(this); // create root scope
698 sc->fromDcode = !isDltFile;
700 //printf("Module = %p, linkage = %d\n", sc->scopesym, sc->linkage);
702 // Find Main class
703 for (i = 0; i < members->dim; i++)
704 { Dsymbol *s;
706 s = (Dsymbol *)members->data[i];
708 if (s->ident && s->ident == Id::Main) {
709 Dsymbol *mainFn = addMainFunction(s);
710 if (!mainFn)
711 return;
712 members->push(mainFn);
714 Import *im = new Import(0, dlt_package, Id::_externals, NULL, true);
715 members->shift(im);
717 break;
721 // Add import of "object" if this module isn't "object"
722 if (ident != Id::object || parent)
724 Import *im = new Import(0, NULL, Id::object, NULL, 0);
725 members->shift(im);
727 /* If this is not dlt.core ... */
728 if (isDltFile && (ident != Id::core ||
729 parent == NULL || parent->parent || parent->ident != Id::dlt)) {
730 Import *im = new Import(0, dlt_package, Id::core, NULL, 0);
731 members->shift(im);
734 #ifdef IN_GCC
735 else
737 /* va_list is a pain. If va_list involves a struct, add the
738 struct declaration to the "object" module. This depends on
739 the GCC backend not naming the struct something that will
740 cause a conflict or define "va_list" without going through
741 std.stdarg. */
742 Type * t = d_gcc_builtin_va_list_d_type;
743 while (t) {
744 if (t->ty == Tstruct) {
745 StructDeclaration * sd = ((TypeStruct *) t)->sym;
746 sd->parent = this;
747 members->push(sd);
748 break;
750 t = t->nextOf();
753 #endif
755 // Add all symbols into module's symbol table
756 symtab = new DsymbolTable();
757 for (i = 0; i < members->dim; i++)
758 { Dsymbol *s;
760 s = (Dsymbol *)members->data[i];
761 s->addMember(NULL, sc->scopesym, 1);
764 // Pass 1 semantic routines: do public side of the definition
765 for (i = 0; i < members->dim; i++)
766 { Dsymbol *s;
768 s = (Dsymbol *)members->data[i];
769 //printf("\tModule('%s'): '%s'.semantic()\n", toChars(), s->toChars());
770 s->semantic(sc);
771 runDeferredSemantic();
774 sc = sc->pop();
775 sc->pop();
776 semanticdone = semanticstarted;
777 //printf("-Module::semantic(this = %p, '%s'): parent = %p\n", this, toChars(), parent);
780 void Module::semantic2()
781 { int i;
783 if (deferred.dim)
785 for (int i = 0; i < deferred.dim; i++)
787 Dsymbol *sd = (Dsymbol *)deferred.data[i];
789 sd->error("unable to resolve forward reference in definition");
791 return;
793 //printf("Module::semantic2('%s'): parent = %p\n", toChars(), parent);
794 if (semanticstarted >= 2)
795 return;
796 assert(semanticstarted == 1);
797 semanticstarted = 2;
799 // Note that modules get their own scope, from scratch.
800 // This is so regardless of where in the syntax a module
801 // gets imported, it is unaffected by context.
802 Scope *sc = Scope::createGlobal(this); // create root scope
803 //printf("Module = %p\n", sc.scopesym);
805 // Pass 2 semantic routines: do initializers and function bodies
806 for (i = 0; i < members->dim; i++)
807 { Dsymbol *s;
809 s = (Dsymbol *)members->data[i];
810 s->semantic2(sc);
813 sc = sc->pop();
814 sc->pop();
815 semanticdone = semanticstarted;
816 //printf("-Module::semantic2('%s'): parent = %p\n", toChars(), parent);
819 void Module::semantic3()
820 { int i;
822 //printf("Module::semantic3('%s'): parent = %p\n", toChars(), parent);
823 if (semanticstarted >= 3)
824 return;
825 assert(semanticstarted == 2);
826 semanticstarted = 3;
828 // Note that modules get their own scope, from scratch.
829 // This is so regardless of where in the syntax a module
830 // gets imported, it is unaffected by context.
831 Scope *sc = Scope::createGlobal(this); // create root scope
832 //printf("Module = %p\n", sc.scopesym);
834 // Pass 3 semantic routines: do initializers and function bodies
835 for (i = 0; i < members->dim; i++)
836 { Dsymbol *s;
838 s = (Dsymbol *)members->data[i];
839 //printf("Module %s: %s.semantic3()\n", toChars(), s->toChars());
840 s->semantic3(sc);
843 sc = sc->pop();
844 sc->pop();
845 semanticdone = semanticstarted;
848 void Module::inlineScan()
849 { int i;
851 if (semanticstarted >= 4)
852 return;
853 assert(semanticstarted == 3);
854 semanticstarted = 4;
856 // Note that modules get their own scope, from scratch.
857 // This is so regardless of where in the syntax a module
858 // gets imported, it is unaffected by context.
859 //printf("Module = %p\n", sc.scopesym);
861 for (i = 0; i < members->dim; i++)
862 { Dsymbol *s;
864 s = (Dsymbol *)members->data[i];
865 //if (global.params.verbose)
866 //printf("inline scan symbol %s\n", s->toChars());
868 s->inlineScan();
870 semanticdone = semanticstarted;
873 /****************************************************
876 void Module::gensymfile()
878 OutBuffer buf;
879 HdrGenState hgs;
881 //printf("Module::gensymfile()\n");
883 buf.printf("// Sym file generated from '%s'", srcfile->toChars());
884 buf.writenl();
886 for (int i = 0; i < members->dim; i++)
887 { Dsymbol *s = (Dsymbol *)members->data[i];
889 s->toCBuffer(&buf, &hgs);
892 // Transfer image to file
893 symfile->setbuffer(buf.data, buf.offset);
894 buf.data = NULL;
896 symfile->writev();
899 /**********************************
900 * Determine if we need to generate an instance of ModuleInfo
901 * for this Module.
904 int Module::needModuleInfo()
906 return needmoduleinfo || global.params.cov;
909 Dsymbol *Module::search(Loc loc, Identifier *ident, int flags)
911 /* Since modules can be circularly referenced,
912 * need to stop infinite recursive searches.
915 //printf("%s Module::search('%s', flags = %d) insearch = %d\n", toChars(), ident->toChars(), flags, insearch);
916 Dsymbol *s;
917 if (insearch)
918 s = NULL;
919 else if (searchCacheIdent == ident && searchCacheFlags == flags)
920 s = searchCacheSymbol;
921 else
923 insearch = 1;
924 s = ScopeDsymbol::search(loc, ident, flags);
925 insearch = 0;
927 searchCacheIdent = ident;
928 searchCacheSymbol = s;
929 searchCacheFlags = flags;
931 return s;
934 /*******************************************
935 * Can't run semantic on s now, try again later.
938 void Module::addDeferredSemantic(Dsymbol *s)
940 // Don't add it if it is already there
941 for (int i = 0; i < deferred.dim; i++)
943 Dsymbol *sd = (Dsymbol *)deferred.data[i];
945 if (sd == s)
946 return;
949 //printf("Module::addDeferredSemantic('%s')\n", s->toChars());
950 deferred.push(s);
954 /******************************************
955 * Run semantic() on deferred symbols.
958 void Module::runDeferredSemantic()
960 size_t len;
962 static int nested;
963 if (nested)
964 return;
965 //if (deferred.dim) printf("+Module::runDeferredSemantic('%s'), len = %d\n", toChars(), deferred.dim);
966 nested++;
970 dprogress = 0;
971 len = deferred.dim;
972 if (!len)
973 break;
975 Dsymbol **todo;
976 Dsymbol *tmp;
977 if (len == 1)
979 todo = &tmp;
981 else
983 todo = (Dsymbol **)alloca(len * sizeof(Dsymbol *));
984 assert(todo);
986 memcpy(todo, deferred.data, len * sizeof(Dsymbol *));
987 deferred.setDim(0);
989 for (int i = 0; i < len; i++)
991 Dsymbol *s = todo[i];
993 s->semantic(NULL);
994 //printf("deferred: %s, parent = %s\n", s->toChars(), s->parent->toChars());
996 //printf("\tdeferred.dim = %d, len = %d, dprogress = %d\n", deferred.dim, len, dprogress);
997 } while (deferred.dim < len || dprogress); // while making progress
998 nested--;
999 //printf("-Module::runDeferredSemantic('%s'), len = %d\n", toChars(), deferred.dim);
1002 /* =========================== ModuleDeclaration ===================== */
1004 ModuleDeclaration::ModuleDeclaration(Array *packages, Identifier *id)
1006 this->packages = packages;
1007 this->id = id;
1010 char *ModuleDeclaration::toChars()
1012 OutBuffer buf;
1013 int i;
1015 if (packages && packages->dim)
1017 for (i = 0; i < packages->dim; i++)
1018 { Identifier *pid = (Identifier *)packages->data[i];
1020 buf.writestring(pid->toChars());
1021 buf.writeByte('.');
1024 buf.writestring(id->toChars());
1025 buf.writeByte(0);
1026 return (char *)buf.extractData();
1029 /* =========================== Package ===================== */
1031 Package::Package(Identifier *ident)
1032 : ScopeDsymbol(ident)
1037 char *Package::kind()
1039 return "package";
1043 DsymbolTable *Package::resolve(Array *packages, Dsymbol **pparent, Package **ppkg)
1045 DsymbolTable *dst = Module::modules;
1046 Dsymbol *parent = NULL;
1048 //printf("Package::resolve()\n");
1049 if (ppkg)
1050 *ppkg = NULL;
1052 if (packages)
1053 { int i;
1055 for (i = 0; i < packages->dim; i++)
1056 { Identifier *pid = (Identifier *)packages->data[i];
1057 Dsymbol *p;
1059 p = dst->lookup(pid);
1060 if (!p)
1062 p = new Package(pid);
1063 dst->insert(p);
1064 p->parent = parent;
1065 ((ScopeDsymbol *)p)->symtab = new DsymbolTable();
1067 else
1069 assert(p->isPackage());
1070 if (p->isModule())
1071 { p->error("module and package have the same name");
1072 fatal();
1073 break;
1076 parent = p;
1077 dst = ((Package *)p)->symtab;
1078 if (ppkg && !*ppkg)
1079 *ppkg = (Package *)p;
1081 if (pparent)
1083 *pparent = parent;
1086 return dst;