root/trunk/src/module.c

Revision 583, 31.0 kB (checked in by walter, 2 years ago)

workaround for another fwd reference anonymous enum bug

  • Property svn:eol-style set to native
Line 
1 // Compiler implementation of the D programming language
2 // Copyright (c) 1999-2010 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 <stdlib.h>
12 #include <assert.h>
13
14 #if (defined (__SVR4) && defined (__sun))
15 #include <alloca.h>
16 #endif
17
18 #if defined(_MSC_VER) || defined(__MINGW32__)
19 #include <malloc.h>
20 #endif
21
22 #if IN_GCC
23 #include "gdc_alloca.h"
24 #endif
25
26 #include "rmem.h"
27
28 #include "mars.h"
29 #include "module.h"
30 #include "parse.h"
31 #include "scope.h"
32 #include "identifier.h"
33 #include "id.h"
34 #include "import.h"
35 #include "dsymbol.h"
36 #include "hdrgen.h"
37 #include "lexer.h"
38
39 #define MARS 1
40 #include "html.h"
41
42 #ifdef IN_GCC
43 #include "d-dmd-gcc.h"
44 #endif
45
46 ClassDeclaration *Module::moduleinfo;
47
48 Module *Module::rootModule;
49 DsymbolTable *Module::modules;
50 Array Module::amodules;
51
52 Array Module::deferred; // deferred Dsymbol's needing semantic() run on them
53 unsigned Module::dprogress;
54
55 void Module::init()
56 {
57     modules = new DsymbolTable();
58 }
59
60 Module::Module(char *filename, Identifier *ident, int doDocComment, int doHdrGen)
61         : Package(ident)
62 {
63     FileName *srcfilename;
64     FileName *cfilename;
65     FileName *hfilename;
66     FileName *objfilename;
67     FileName *symfilename;
68
69 //    printf("Module::Module(filename = '%s', ident = '%s')\n", filename, ident->toChars());
70     this->arg = filename;
71     md = NULL;
72     errors = 0;
73     numlines = 0;
74     members = NULL;
75     isHtml = 0;
76     isDocFile = 0;
77     needmoduleinfo = 0;
78 #ifdef IN_GCC
79     strictlyneedmoduleinfo = 0;
80 #endif
81     selfimports = 0;
82     insearch = 0;
83     searchCacheIdent = NULL;
84     searchCacheSymbol = NULL;
85     searchCacheFlags = 0;
86     semanticstarted = 0;
87     semanticRun = 0;
88     decldefs = NULL;
89     vmoduleinfo = NULL;
90     massert = NULL;
91     munittest = NULL;
92     marray = NULL;
93     sictor = NULL;
94     sctor = NULL;
95     sdtor = NULL;
96     ssharedctor = NULL;
97     sshareddtor = NULL;
98     stest = NULL;
99     sfilename = NULL;
100     root = 0;
101     importedFrom = NULL;
102     srcfile = NULL;
103     docfile = NULL;
104
105     debuglevel = 0;
106     debugids = NULL;
107     debugidsNot = NULL;
108     versionlevel = 0;
109     versionids = NULL;
110     versionidsNot = NULL;
111
112     macrotable = NULL;
113     escapetable = NULL;
114     safe = FALSE;
115     doppelganger = 0;
116     cov = NULL;
117     covb = NULL;
118
119     nameoffset = 0;
120     namelen = 0;
121
122     srcfilename = FileName::defaultExt(filename, global.mars_ext);
123     if (!srcfilename->equalsExt(global.mars_ext) &&
124         !srcfilename->equalsExt(global.hdr_ext) &&
125         !srcfilename->equalsExt("dd"))
126     {
127         if (srcfilename->equalsExt("html") ||
128             srcfilename->equalsExt("htm")  ||
129             srcfilename->equalsExt("xhtml"))
130         {   if (!global.params.useDeprecated)
131                 error("html source files is deprecated %s", srcfilename->toChars());
132             isHtml = 1;
133         }
134         else
135         {   error("source file name '%s' must have .%s extension", srcfilename->toChars(), global.mars_ext);
136             fatal();
137         }
138     }
139
140     char *argobj;
141     if (global.params.objname)
142         argobj = global.params.objname;
143 #if 0
144     else if (global.params.preservePaths)
145         argobj = filename;
146     else
147         argobj = FileName::name(filename);
148     if (!FileName::absolute(argobj))
149     {
150         argobj = FileName::combine(global.params.objdir, argobj);
151     }
152 #else // Bugzilla 3547
153     else
154     {
155         if (global.params.preservePaths)
156             argobj = filename;
157         else
158             argobj = FileName::name(filename);
159         if (!FileName::absolute(argobj))
160         {
161             argobj = FileName::combine(global.params.objdir, argobj);
162         }
163     }
164 #endif
165
166     if (global.params.objname)
167         objfilename = new FileName(argobj, 0);
168     else
169         objfilename = FileName::forceExt(argobj, global.obj_ext);
170
171     symfilename = FileName::forceExt(filename, global.sym_ext);
172
173     srcfile = new File(srcfilename);
174
175     if (doDocComment)
176     {
177         setDocfile();
178     }
179
180     if (doHdrGen)
181     {
182         setHdrfile();
183     }
184
185     objfile = new File(objfilename);
186     symfile = new File(symfilename);
187 }
188
189 void Module::setDocfile()
190 {
191     FileName *docfilename;
192     char *argdoc;
193
194     if (global.params.docname)
195         argdoc = global.params.docname;
196     else if (global.params.preservePaths)
197         argdoc = (char *)arg;
198     else
199         argdoc = FileName::name((char *)arg);
200     if (!FileName::absolute(argdoc))
201     {   //FileName::ensurePathExists(global.params.docdir);
202         argdoc = FileName::combine(global.params.docdir, argdoc);
203     }
204     if (global.params.docname)
205         docfilename = new FileName(argdoc, 0);
206     else
207         docfilename = FileName::forceExt(argdoc, global.doc_ext);
208
209     if (docfilename->equals(srcfile->name))
210     {   error("Source file and documentation file have same name '%s'", srcfile->name->str);
211         fatal();
212     }
213
214     docfile = new File(docfilename);
215 }
216
217 void Module::setHdrfile()
218 {
219     FileName *hdrfilename;
220     char *arghdr;
221
222     if (global.params.hdrname)
223         arghdr = global.params.hdrname;
224     else if (global.params.preservePaths)
225         arghdr = (char *)arg;
226     else
227         arghdr = FileName::name((char *)arg);
228     if (!FileName::absolute(arghdr))
229     {   //FileName::ensurePathExists(global.params.hdrdir);
230         arghdr = FileName::combine(global.params.hdrdir, arghdr);
231     }
232     if (global.params.hdrname)
233         hdrfilename = new FileName(arghdr, 0);
234     else
235         hdrfilename = FileName::forceExt(arghdr, global.hdr_ext);
236
237     if (hdrfilename->equals(srcfile->name))
238     {   error("Source file and 'header' file have same name '%s'", srcfile->name->str);
239         fatal();
240     }
241
242     hdrfile = new File(hdrfilename);
243 }
244
245 void Module::deleteObjFile()
246 {
247     if (global.params.obj)
248         objfile->remove();
249     if (docfile)
250         docfile->remove();
251 }
252
253 Module::~Module()
254 {
255 }
256
257 const char *Module::kind()
258 {
259     return "module";
260 }
261
262 Module *Module::load(Loc loc, Array *packages, Identifier *ident)
263 {   Module *m;
264     char *filename;
265
266     //printf("Module::load(ident = '%s')\n", ident->toChars());
267
268     // Build module filename by turning:
269     //  foo.bar.baz
270     // into:
271     //  foo\bar\baz
272     filename = ident->toChars();
273     if (packages && packages->dim)
274     {
275         OutBuffer buf;
276         int i;
277
278         for (i = 0; i < packages->dim; i++)
279         {   Identifier *pid = (Identifier *)packages->data[i];
280
281             buf.writestring(pid->toChars());
282 #if _WIN32
283             buf.writeByte('\\');
284 #else
285             buf.writeByte('/');
286 #endif
287         }
288         buf.writestring(filename);
289         buf.writeByte(0);
290         filename = (char *)buf.extractData();
291     }
292
293     m = new Module(filename, ident, 0, 0);
294     m->loc = loc;
295
296     /* Search along global.path for .di file, then .d file.
297      */
298     char *result = NULL;
299     FileName *fdi = FileName::forceExt(filename, global.hdr_ext);
300     FileName *fd  = FileName::forceExt(filename, global.mars_ext);
301     char *sdi = fdi->toChars();
302     char *sd  = fd->toChars();
303
304     if (FileName::exists(sdi))
305         result = sdi;
306     else if (FileName::exists(sd))
307         result = sd;
308     else if (FileName::absolute(filename))
309         ;
310     else if (!global.path)
311         ;
312     else
313     {
314         for (size_t i = 0; i < global.path->dim; i++)
315         {
316             char *p = (char *)global.path->data[i];
317             char *n = FileName::combine(p, sdi);
318             if (FileName::exists(n))
319             {   result = n;
320                 break;
321             }
322             mem.free(n);
323             n = FileName::combine(p, sd);
324             if (FileName::exists(n))
325             {   result = n;
326                 break;
327             }
328             mem.free(n);
329         }
330     }
331     if (result)
332         m->srcfile = new File(result);
333
334     if (global.params.verbose)
335     {
336         printf("import    ");
337         if (packages)
338         {
339             for (size_t i = 0; i < packages->dim; i++)
340             {   Identifier *pid = (Identifier *)packages->data[i];
341                 printf("%s.", pid->toChars());
342             }
343         }
344         printf("%s\t(%s)\n", ident->toChars(), m->srcfile->toChars());
345     }
346
347     m->read(loc);
348     m->parse();
349
350 #ifdef IN_GCC
351     d_gcc_magic_module(m);
352 #endif
353
354     return m;
355 }
356
357 void Module::read(Loc loc)
358 {
359     //printf("Module::read('%s') file '%s'\n", toChars(), srcfile->toChars());
360     if (srcfile->read())
361     {   error(loc, "is in file '%s' which cannot be read", srcfile->toChars());
362         if (!global.gag)
363         {   /* Print path
364              */
365             if (global.path)
366             {
367                 for (int i = 0; i < global.path->dim; i++)
368                 {
369                     char *p = (char *)global.path->data[i];
370                     fprintf(stdmsg, "import path[%d] = %s\n", i, p);
371                 }
372             }
373             else
374                 fprintf(stdmsg, "Specify path to file '%s' with -I switch\n", srcfile->toChars());
375         }
376         fatal();
377     }
378 }
379
380 inline unsigned readwordLE(unsigned short *p)
381 {
382 #if __I86__
383     return *p;
384 #else
385     return (((unsigned char *)p)[1] << 8) | ((unsigned char *)p)[0];
386 #endif
387 }
388
389 inline unsigned readwordBE(unsigned short *p)
390 {
391     return (((unsigned char *)p)[0] << 8) | ((unsigned char *)p)[1];
392 }
393
394 inline unsigned readlongLE(unsigned *p)
395 {
396 #if __I86__
397     return *p;
398 #else
399     return ((unsigned char *)p)[0] |
400         (((unsigned char *)p)[1] << 8) |
401         (((unsigned char *)p)[2] << 16) |
402         (((unsigned char *)p)[3] << 24);
403 #endif
404 }
405
406 inline unsigned readlongBE(unsigned *p)
407 {
408     return ((unsigned char *)p)[3] |
409         (((unsigned char *)p)[2] << 8) |
410         (((unsigned char *)p)[1] << 16) |
411         (((unsigned char *)p)[0] << 24);
412 }
413
414 #if IN_GCC
415 void Module::parse(bool dump_source)
416 #else
417 void Module::parse()
418 #endif
419 {   char *srcname;
420     unsigned char *buf;
421     unsigned buflen;
422     unsigned le;
423     unsigned bom;
424
425     //printf("Module::parse()\n");
426
427     srcname = srcfile->name->toChars();
428     //printf("Module::parse(srcname = '%s')\n", srcname);
429
430     buf = srcfile->buffer;
431     buflen = srcfile->len;
432
433     if (buflen >= 2)
434     {
435         /* Convert all non-UTF-8 formats to UTF-8.
436          * BOM : http://www.unicode.org/faq/utf_bom.html
437          * 00 00 FE FF  UTF-32BE, big-endian
438          * FF FE 00 00  UTF-32LE, little-endian
439          * FE FF        UTF-16BE, big-endian
440          * FF FE        UTF-16LE, little-endian
441          * EF BB BF     UTF-8
442          */
443
444         bom = 1;                // assume there's a BOM
445         if (buf[0] == 0xFF && buf[1] == 0xFE)
446         {
447             if (buflen >= 4 && buf[2] == 0 && buf[3] == 0)
448             {   // UTF-32LE
449                 le = 1;
450
451             Lutf32:
452                 OutBuffer dbuf;
453                 unsigned *pu = (unsigned *)(buf);
454                 unsigned *pumax = &pu[buflen / 4];
455
456                 if (buflen & 3)
457                 {   error("odd length of UTF-32 char source %u", buflen);
458                     fatal();
459                 }
460
461                 dbuf.reserve(buflen / 4);
462                 for (pu += bom; pu < pumax; pu++)
463                 {   unsigned u;
464
465                     u = le ? readlongLE(pu) : readlongBE(pu);
466                     if (u & ~0x7F)
467                     {
468                         if (u > 0x10FFFF)
469                         {   error("UTF-32 value %08x greater than 0x10FFFF", u);
470                             fatal();
471                         }
472                         dbuf.writeUTF8(u);
473                     }
474                     else
475                         dbuf.writeByte(u);
476                 }
477                 dbuf.writeByte(0);              // add 0 as sentinel for scanner
478                 buflen = dbuf.offset - 1;       // don't include sentinel in count
479                 buf = (unsigned char *) dbuf.extractData();
480             }
481             else
482             {   // UTF-16LE (X86)
483                 // Convert it to UTF-8
484                 le = 1;
485
486             Lutf16:
487                 OutBuffer dbuf;
488                 unsigned short *pu = (unsigned short *)(buf);
489                 unsigned short *pumax = &pu[buflen / 2];
490
491                 if (buflen & 1)
492                 {   error("odd length of UTF-16 char source %u", buflen);
493                     fatal();
494                 }
495
496                 dbuf.reserve(buflen / 2);
497                 for (pu += bom; pu < pumax; pu++)
498                 {   unsigned u;
499
500                     u = le ? readwordLE(pu) : readwordBE(pu);
501                     if (u & ~0x7F)
502                     {   if (u >= 0xD800 && u <= 0xDBFF)
503                         {   unsigned u2;
504
505                             if (++pu > pumax)
506                             {   error("surrogate UTF-16 high value %04x at EOF", u);
507                                 fatal();
508                             }
509                             u2 = le ? readwordLE(pu) : readwordBE(pu);
510                             if (u2 < 0xDC00 || u2 > 0xDFFF)
511                             {   error("surrogate UTF-16 low value %04x out of range", u2);
512                                 fatal();
513                             }
514                             u = (u - 0xD7C0) << 10;
515                             u |= (u2 - 0xDC00);
516                         }
517                         else if (u >= 0xDC00 && u <= 0xDFFF)
518                         {   error("unpaired surrogate UTF-16 value %04x", u);
519                             fatal();
520                         }
521                         else if (u == 0xFFFE || u == 0xFFFF)
522                         {   error("illegal UTF-16 value %04x", u);
523                             fatal();
524                         }
525                         dbuf.writeUTF8(u);
526                     }
527                     else
528                         dbuf.writeByte(u);
529                 }
530                 dbuf.writeByte(0);              // add 0 as sentinel for scanner
531                 buflen = dbuf.offset - 1;       // don't include sentinel in count
532                 buf = (unsigned char *) dbuf.extractData();
533             }
534         }
535         else if (buf[0] == 0xFE && buf[1] == 0xFF)
536         {   // UTF-16BE
537             le = 0;
538             goto Lutf16;
539         }
540         else if (buflen >= 4 && buf[0] == 0 && buf[1] == 0 && buf[2] == 0xFE && buf[3] == 0xFF)
541         {   // UTF-32BE
542             le = 0;
543             goto Lutf32;
544         }
545         else if (buflen >= 3 && buf[0] == 0xEF && buf[1] == 0xBB && buf[2] == 0xBF)
546         {   // UTF-8
547
548             buf += 3;
549             buflen -= 3;
550         }
551         else
552         {
553             /* There is no BOM. Make use of Arcane Jill's insight that
554              * the first char of D source must be ASCII to
555              * figure out the encoding.
556              */
557
558             bom = 0;
559             if (buflen >= 4)
560             {   if (buf[1] == 0 && buf[2] == 0 && buf[3] == 0)
561                 {   // UTF-32LE
562                     le = 1;
563                     goto Lutf32;
564                 }
565                 else if (buf[0] == 0 && buf[1] == 0 && buf[2] == 0)
566                 {   // UTF-32BE
567                     le = 0;
568                     goto Lutf32;
569                 }
570             }
571             if (buflen >= 2)
572             {
573                 if (buf[1] == 0)
574                 {   // UTF-16LE
575                     le = 1;
576                     goto Lutf16;
577                 }
578                 else if (buf[0] == 0)
579                 {   // UTF-16BE
580                     le = 0;
581                     goto Lutf16;
582                 }
583             }
584
585             // It's UTF-8
586             if (buf[0] >= 0x80)
587             {   error("source file must start with BOM or ASCII character, not \\x%02X", buf[0]);
588                 fatal();
589             }
590         }
591     }
592
593 #ifdef IN_GCC
594     // dump utf-8 encoded source
595     if (dump_source)
596     {   // %% srcname could contain a path ...
597         d_gcc_dump_source(srcname, "utf-8", buf, buflen);
598     }
599 #endif
600
601     /* If it starts with the string "Ddoc", then it's a documentation
602      * source file.
603      */
604     if (buflen >= 4 && memcmp(buf, "Ddoc", 4) == 0)
605     {
606         comment = buf + 4;
607         isDocFile = 1;
608         if (!docfile)
609             setDocfile();
610         return;
611     }
612     if (isHtml)
613     {
614         OutBuffer *dbuf = new OutBuffer();
615         Html h(srcname, buf, buflen);
616         h.extractCode(dbuf);
617         buf = dbuf->data;
618         buflen = dbuf->offset;
619 #ifdef IN_GCC
620         // dump extracted source
621         if (dump_source)
622             d_gcc_dump_source(srcname, "d.utf-8", buf, buflen);
623 #endif
624     }
625     Parser p(this, buf, buflen, docfile != NULL);
626     p.nextToken();
627     members = p.parseModule();
628     md = p.md;
629     numlines = p.loc.linnum;
630
631     DsymbolTable *dst;
632
633     if (md)
634     {   this->ident = md->id;
635         this->safe = md->safe;
636         dst = Package::resolve(md->packages, &this->parent, NULL);
637     }
638     else
639     {
640         dst = modules;
641
642         /* Check to see if module name is a valid identifier
643          */
644         if (!Lexer::isValidIdentifier(this->ident->toChars()))
645             error("has non-identifier characters in filename, use module declaration instead");
646     }
647
648     // Update global list of modules
649     if (!dst->insert(this))
650     {
651         Dsymbol *prev = dst->lookup(ident);
652         assert(prev);
653         Module *mprev = prev->isModule();
654         if (mprev)
655             error(loc, "from file %s conflicts with another module %s from file %s",
656                 srcname, mprev->toChars(), mprev->srcfile->toChars());
657         else
658         {
659             Package *pkg = prev->isPackage();
660             assert(pkg);
661             error(loc, "from file %s conflicts with package name %s",
662                 srcname, pkg->toChars());
663         }
664     }
665     else
666     {
667         amodules.push(this);
668     }
669 }
670
671 void Module::importAll(Scope *prevsc)
672 {
673     //printf("+Module::importAll(this = %p, '%s'): parent = %p\n", this, toChars(), parent);
674
675     if (scope)
676         return;                 // already done
677
678     /* Note that modules get their own scope, from scratch.
679      * This is so regardless of where in the syntax a module
680      * gets imported, it is unaffected by context.
681      * Ignore prevsc.
682      */
683     Scope *sc = Scope::createGlobal(this);      // create root scope
684
685     // Add import of "object" if this module isn't "object"
686     if (ident != Id::object)
687     {
688         if (members->dim == 0 || ((Dsymbol *)members->data[0])->ident != Id::object)
689         {
690             Import *im = new Import(0, NULL, Id::object, NULL, 0);
691             members->shift(im);
692         }
693     }
694
695     if (!symtab)
696     {
697         // Add all symbols into module's symbol table
698         symtab = new DsymbolTable();
699         for (int i = 0; i < members->dim; i++)
700         {
701             Dsymbol *s = (Dsymbol *)members->data[i];
702             s->addMember(NULL, sc->scopesym, 1);
703         }
704     }
705     // anything else should be run after addMember, so version/debug symbols are defined
706
707     /* Set scope for the symbols so that if we forward reference
708      * a symbol, it can possibly be resolved on the spot.
709      * If this works out well, it can be extended to all modules
710      * before any semantic() on any of them.
711      */
712     setScope(sc);               // remember module scope for semantic
713     for (int i = 0; i < members->dim; i++)
714     {   Dsymbol *s = (Dsymbol *)members->data[i];
715         s->setScope(sc);
716     }
717
718     for (int i = 0; i < members->dim; i++)
719     {
720         Dsymbol *s = (Dsymbol *)members->data[i];
721         s->importAll(sc);
722     }
723
724     sc = sc->pop();
725     sc->pop();          // 2 pops because Scope::createGlobal() created 2
726 }
727
728 void Module::semantic()
729 {
730     if (semanticstarted)
731         return;
732
733     //printf("+Module::semantic(this = %p, '%s'): parent = %p\n", this, toChars(), parent);
734     semanticstarted = 1;
735
736     // Note that modules get their own scope, from scratch.
737     // This is so regardless of where in the syntax a module
738     // gets imported, it is unaffected by context.
739     Scope *sc = scope;                  // see if already got one from importAll()
740     if (!sc)
741     {   printf("test2\n");
742         Scope::createGlobal(this);      // create root scope
743     }
744
745     //printf("Module = %p, linkage = %d\n", sc->scopesym, sc->linkage);
746
747 #if 0
748     // Add import of "object" if this module isn't "object"
749     if (ident != Id::object)
750     {
751         Import *im = new Import(0, NULL, Id::object, NULL, 0);
752         members->shift(im);
753     }
754
755     // Add all symbols into module's symbol table
756     symtab = new DsymbolTable();
757     for (int i = 0; i < members->dim; i++)
758     {   Dsymbol *s = (Dsymbol *)members->data[i];
759         s->addMember(NULL, sc->scopesym, 1);
760     }
761
762     /* Set scope for the symbols so that if we forward reference
763      * a symbol, it can possibly be resolved on the spot.
764      * If this works out well, it can be extended to all modules
765      * before any semantic() on any of them.
766      */
767     for (int i = 0; i < members->dim; i++)
768     {   Dsymbol *s = (Dsymbol *)members->data[i];
769         s->setScope(sc);
770     }
771 #endif
772
773     // Do semantic() on members that don't depend on others
774     for (int i = 0; i < members->dim; i++)
775     {   Dsymbol *s = (Dsymbol *)members->data[i];
776
777         //printf("\tModule('%s'): '%s'.semantic0()\n", toChars(), s->toChars());
778         s->semantic0(sc);
779     }
780
781     // Pass 1 semantic routines: do public side of the definition
782     for (int i = 0; i < members->dim; i++)
783     {   Dsymbol *s = (Dsymbol *)members->data[i];
784
785         //printf("\tModule('%s'): '%s'.semantic()\n", toChars(), s->toChars());
786         s->semantic(sc);
787         runDeferredSemantic();
788     }
789
790     if (!scope)
791     {   sc = sc->pop();
792         sc->pop();              // 2 pops because Scope::createGlobal() created 2
793     }
794     semanticRun = semanticstarted;
795     //printf("-Module::semantic(this = %p, '%s'): parent = %p\n", this, toChars(), parent);
796 }
797
798 void Module::semantic2()
799 {   int i;
800
801     if (deferred.dim)
802     {
803         for (int i = 0; i < deferred.dim; i++)
804         {
805             Dsymbol *sd = (Dsymbol *)deferred.data[i];
806
807             sd->error("unable to resolve forward reference in definition");
808         }
809         return;
810     }
811     //printf("Module::semantic2('%s'): parent = %p\n", toChars(), parent);
812     if (semanticstarted >= 2)
813         return;
814     assert(semanticstarted == 1);
815     semanticstarted = 2;
816
817     // Note that modules get their own scope, from scratch.
818     // This is so regardless of where in the syntax a module
819     // gets imported, it is unaffected by context.
820     Scope *sc = Scope::createGlobal(this);      // create root scope
821     //printf("Module = %p\n", sc.scopesym);
822
823     // Pass 2 semantic routines: do initializers and function bodies
824     for (i = 0; i < members->dim; i++)
825     {   Dsymbol *s;
826
827         s = (Dsymbol *)members->data[i];
828         s->semantic2(sc);
829     }
830
831     sc = sc->pop();
832     sc->pop();
833     semanticRun = semanticstarted;
834     //printf("-Module::semantic2('%s'): parent = %p\n", toChars(), parent);
835 }
836
837 void Module::semantic3()
838 {   int i;
839
840     //printf("Module::semantic3('%s'): parent = %p\n", toChars(), parent);
841     if (semanticstarted >= 3)
842         return;
843     assert(semanticstarted == 2);
844     semanticstarted = 3;
845
846     // Note that modules get their own scope, from scratch.
847     // This is so regardless of where in the syntax a module
848     // gets imported, it is unaffected by context.
849     Scope *sc = Scope::createGlobal(this);      // create root scope
850     //printf("Module = %p\n", sc.scopesym);
851
852     // Pass 3 semantic routines: do initializers and function bodies
853     for (i = 0; i < members->dim; i++)
854     {   Dsymbol *s;
855
856         s = (Dsymbol *)members->data[i];
857         //printf("Module %s: %s.semantic3()\n", toChars(), s->toChars());
858         s->semantic3(sc);
859     }
860
861     sc = sc->pop();
862     sc->pop();
863     semanticRun = semanticstarted;
864 }
865
866 void Module::inlineScan()
867 {
868     if (semanticstarted >= 4)
869         return;
870     assert(semanticstarted == 3);
871     semanticstarted = 4;
872
873     // Note that modules get their own scope, from scratch.
874     // This is so regardless of where in the syntax a module
875     // gets imported, it is unaffected by context.
876     //printf("Module = %p\n", sc.scopesym);
877
878     for (int i = 0; i < members->dim; i++)
879     {   Dsymbol *s = (Dsymbol *)members->data[i];
880         //if (global.params.verbose)
881             //printf("inline scan symbol %s\n", s->toChars());
882
883         s->inlineScan();
884     }
885     semanticRun = semanticstarted;
886 }
887
888 /****************************************************
889  */
890
891 void Module::gensymfile()
892 {
893     OutBuffer buf;
894     HdrGenState hgs;
895
896     //printf("Module::gensymfile()\n");
897
898     buf.printf("// Sym file generated from '%s'", srcfile->toChars());
899     buf.writenl();
900
901     for (int i = 0; i < members->dim; i++)
902     {   Dsymbol *s = (Dsymbol *)members->data[i];
903
904         s->toCBuffer(&buf, &hgs);
905     }
906
907     // Transfer image to file
908     symfile->setbuffer(buf.data, buf.offset);
909     buf.data = NULL;
910
911     symfile->writev();
912 }
913
914 /**********************************
915  * Determine if we need to generate an instance of ModuleInfo
916  * for this Module.
917  */
918
919 int Module::needModuleInfo()
920 {
921     //printf("needModuleInfo() %s, %d, %d\n", toChars(), needmoduleinfo, global.params.cov);
922     return needmoduleinfo || global.params.cov;
923 }
924
925 Dsymbol *Module::search(Loc loc, Identifier *ident, int flags)
926 {
927     /* Since modules can be circularly referenced,
928      * need to stop infinite recursive searches.
929      * This is done with the cache.
930      */
931
932     //printf("%s Module::search('%s', flags = %d) insearch = %d\n", toChars(), ident->toChars(), flags, insearch);
933     Dsymbol *s;
934     if (insearch)
935         s = NULL;
936     else if (searchCacheIdent == ident && searchCacheFlags == flags)
937     {
938         s = searchCacheSymbol;
939         //printf("%s Module::search('%s', flags = %d) insearch = %d searchCacheSymbol = %s\n", toChars(), ident->toChars(), flags, insearch, searchCacheSymbol ? searchCacheSymbol->toChars() : "null");
940     }
941     else
942     {
943         insearch = 1;
944         s = ScopeDsymbol::search(loc, ident, flags);
945         insearch = 0;
946
947         searchCacheIdent = ident;
948         searchCacheSymbol = s;
949         searchCacheFlags = flags;
950     }
951     return s;
952 }
953
954 Dsymbol *Module::symtabInsert(Dsymbol *s)
955 {
956     searchCacheIdent = 0;       // symbol is inserted, so invalidate cache
957     return Package::symtabInsert(s);
958 }
959
960 void Module::clearCache()
961 {
962     for (int i = 0; i < amodules.dim; i++)
963     {   Module *m = (Module *)amodules.data[i];
964         m->searchCacheIdent = NULL;
965     }
966 }
967
968 /*******************************************
969  * Can't run semantic on s now, try again later.
970  */
971
972 void Module::addDeferredSemantic(Dsymbol *s)
973 {
974     // Don't add it if it is already there
975     for (int i = 0; i < deferred.dim; i++)
976     {
977         Dsymbol *sd = (Dsymbol *)deferred.data[i];
978
979         if (sd == s)
980             return;
981     }
982
983     //printf("Module::addDeferredSemantic('%s')\n", s->toChars());
984     deferred.push(s);
985 }
986
987
988 /******************************************
989  * Run semantic() on deferred symbols.
990  */
991
992 void Module::runDeferredSemantic()
993 {
994     if (dprogress == 0)
995         return;
996
997     static int nested;
998     if (nested)
999         return;
1000     //if (deferred.dim) printf("+Module::runDeferredSemantic('%s'), len = %d\n", toChars(), deferred.dim);
1001     nested++;
1002
1003     size_t len;
1004     do
1005     {
1006         dprogress = 0;
1007         len = deferred.dim;
1008         if (!len)
1009             break;
1010
1011         Dsymbol **todo;
1012         Dsymbol *tmp;
1013         if (len == 1)
1014         {
1015             todo = &tmp;
1016         }
1017         else
1018         {
1019             todo = (Dsymbol **)alloca(len * sizeof(Dsymbol *));
1020             assert(todo);
1021         }
1022         memcpy(todo, deferred.data, len * sizeof(Dsymbol *));
1023         deferred.setDim(0);
1024
1025         for (int i = 0; i < len; i++)
1026         {
1027             Dsymbol *s = todo[i];
1028
1029             s->semantic(NULL);
1030             //printf("deferred: %s, parent = %s\n", s->toChars(), s->parent->toChars());
1031         }
1032         //printf("\tdeferred.dim = %d, len = %d, dprogress = %d\n", deferred.dim, len, dprogress);
1033     } while (deferred.dim < len || dprogress);  // while making progress
1034     nested--;
1035     //printf("-Module::runDeferredSemantic('%s'), len = %d\n", toChars(), deferred.dim);
1036 }
1037
1038 /************************************
1039  * Recursively look at every module this module imports,
1040  * return TRUE if it imports m.
1041  * Can be used to detect circular imports.
1042  */
1043
1044 int Module::imports(Module *m)
1045 {
1046     //printf("%s Module::imports(%s)\n", toChars(), m->toChars());
1047     int aimports_dim = aimports.dim;
1048 #if 0
1049     for (int i = 0; i < aimports.dim; i++)
1050     {   Module *mi = (Module *)aimports.data[i];
1051         printf("\t[%d] %s\n", i, mi->toChars());
1052     }
1053 #endif
1054     for (int i = 0; i < aimports.dim; i++)
1055     {   Module *mi = (Module *)aimports.data[i];
1056         if (mi == m)
1057             return TRUE;
1058         if (!mi->insearch)
1059         {
1060             mi->insearch = 1;
1061             int r = mi->imports(m);
1062             if (r)
1063                 return r;
1064         }
1065     }
1066     return FALSE;
1067 }
1068
1069 /*************************************
1070  * Return !=0 if module imports itself.
1071  */
1072
1073 int Module::selfImports()
1074 {
1075     //printf("Module::selfImports() %s\n", toChars());
1076     if (!selfimports)
1077     {
1078         for (int i = 0; i < amodules.dim; i++)
1079         {   Module *mi = (Module *)amodules.data[i];
1080             //printf("\t[%d] %s\n", i, mi->toChars());
1081             mi->insearch = 0;
1082         }
1083
1084         selfimports = imports(this) + 1;
1085
1086         for (int i = 0; i < amodules.dim; i++)
1087         {   Module *mi = (Module *)amodules.data[i];
1088             //printf("\t[%d] %s\n", i, mi->toChars());
1089             mi->insearch = 0;
1090         }
1091     }
1092     return selfimports - 1;
1093 }
1094
1095
1096 /* =========================== ModuleDeclaration ===================== */
1097
1098 ModuleDeclaration::ModuleDeclaration(Array *packages, Identifier *id, bool safe)
1099 {
1100     this->packages = packages;
1101     this->id = id;
1102     this->safe = safe;
1103 }
1104
1105 char *ModuleDeclaration::toChars()
1106 {
1107     OutBuffer buf;
1108     int i;
1109
1110     if (packages && packages->dim)
1111     {
1112         for (i = 0; i < packages->dim; i++)
1113         {   Identifier *pid = (Identifier *)packages->data[i];
1114
1115             buf.writestring(pid->toChars());
1116             buf.writeByte('.');
1117         }
1118     }
1119     buf.writestring(id->toChars());
1120     buf.writeByte(0);
1121     return (char *)buf.extractData();
1122 }
1123
1124 /* =========================== Package ===================== */
1125
1126 Package::Package(Identifier *ident)
1127         : ScopeDsymbol(ident)
1128 {
1129 }
1130
1131
1132 const char *Package::kind()
1133 {
1134     return "package";
1135 }
1136
1137
1138 DsymbolTable *Package::resolve(Array *packages, Dsymbol **pparent, Package **ppkg)
1139 {
1140     DsymbolTable *dst = Module::modules;
1141     Dsymbol *parent = NULL;
1142
1143     //printf("Package::resolve()\n");
1144     if (ppkg)
1145         *ppkg = NULL;
1146
1147     if (packages)
1148     {   int i;
1149
1150         for (i = 0; i < packages->dim; i++)
1151         {   Identifier *pid = (Identifier *)packages->data[i];
1152             Dsymbol *p;
1153
1154             p = dst->lookup(pid);
1155             if (!p)
1156             {
1157                 p = new Package(pid);
1158                 dst->insert(p);
1159                 p->parent = parent;
1160                 ((ScopeDsymbol *)p)->symtab = new DsymbolTable();
1161             }
1162             else
1163             {
1164                 assert(p->isPackage());
1165 #if TARGET_NET  //dot net needs modules and packages with same name
1166 #else
1167                 if (p->isModule())
1168                 {   p->error("module and package have the same name");
1169                     fatal();
1170                     break;
1171                 }
1172 #endif
1173             }
1174             parent = p;
1175             dst = ((Package *)p)->symtab;
1176             if (ppkg && !*ppkg)
1177                 *ppkg = (Package *)p;
1178         }
1179         if (pparent)
1180         {
1181             *pparent = parent;
1182         }
1183     }
1184     return dst;
1185 }
Note: See TracBrowser for help on using the browser.