Mercurial > projects > ldc
annotate dmd/module.c @ 109:5ab8e92611f9 trunk
[svn r113] Added initial support for associative arrays (AAs).
Fixed some problems with the string runtime support functions.
Fixed initialization of array of structs.
Fixed slice assignment where LHS is slice but RHS is dynamic array.
Fixed problems with result of assignment expressions.
Fixed foreach problems with key type mismatches.
author | lindquist |
---|---|
date | Wed, 21 Nov 2007 04:13:15 +0100 |
parents | 61615fa85940 |
children | a7dfa0ed966c |
rev | line source |
---|---|
1 | 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 <stdlib.h> | |
13 #include <assert.h> | |
14 | |
15 #ifdef _MSC_VER | |
16 #include <malloc.h> | |
17 #endif | |
18 | |
19 #if IN_GCC | |
20 #include "gdc_alloca.h" | |
21 #endif | |
22 | |
23 #include "mem.h" | |
24 | |
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 | |
36 #define MARS 1 | |
37 #include "html.h" | |
38 | |
39 #ifdef IN_GCC | |
40 #include "d-dmd-gcc.h" | |
41 #endif | |
42 | |
43 ClassDeclaration *Module::moduleinfo; | |
44 | |
45 Module *Module::rootModule; | |
46 DsymbolTable *Module::modules; | |
47 Array Module::amodules; | |
48 | |
49 Array Module::deferred; // deferred Dsymbol's needing semantic() run on them | |
50 unsigned Module::dprogress; | |
51 | |
52 void Module::init() | |
53 { | |
54 modules = new DsymbolTable(); | |
55 } | |
56 | |
57 Module::Module(char *filename, Identifier *ident, int doDocComment, int doHdrGen) | |
58 : Package(ident) | |
59 { | |
60 FileName *srcfilename; | |
61 FileName *cfilename; | |
62 FileName *hfilename; | |
63 FileName *objfilename; | |
64 FileName *llfilename; | |
65 FileName *bcfilename; | |
66 FileName *symfilename; | |
67 | |
68 // printf("Module::Module(filename = '%s', ident = '%s')\n", filename, ident->toChars()); | |
69 this->arg = filename; | |
70 md = NULL; | |
71 errors = 0; | |
72 numlines = 0; | |
73 members = NULL; | |
74 isHtml = 0; | |
75 isDocFile = 0; | |
76 needmoduleinfo = 0; | |
77 #ifdef IN_GCC | |
78 strictlyneedmoduleinfo = 0; | |
79 #endif | |
80 insearch = 0; | |
81 searchCacheIdent = NULL; | |
82 searchCacheSymbol = NULL; | |
83 searchCacheFlags = 0; | |
84 semanticstarted = 0; | |
85 semanticdone = 0; | |
86 decldefs = NULL; | |
87 vmoduleinfo = NULL; | |
88 massert = NULL; | |
89 marray = 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; | |
98 | |
99 debuglevel = 0; | |
100 debugids = NULL; | |
101 debugidsNot = NULL; | |
102 versionlevel = 0; | |
103 versionids = NULL; | |
104 versionidsNot = NULL; | |
105 | |
106 macrotable = NULL; | |
107 escapetable = NULL; | |
108 cov = NULL; | |
109 covb = NULL; | |
110 | |
111 srcfilename = FileName::defaultExt(filename, global.mars_ext); | |
112 if (!srcfilename->equalsExt(global.mars_ext)) | |
113 { | |
114 if (srcfilename->equalsExt("html") || | |
115 srcfilename->equalsExt("htm") || | |
116 srcfilename->equalsExt("xhtml")) | |
117 isHtml = 1; | |
118 else | |
119 { error("source file name '%s' must have .%s extension", srcfilename->toChars(), global.mars_ext); | |
120 fatal(); | |
121 } | |
122 } | |
123 | |
124 char *argobj; | |
125 if (global.params.objname) | |
126 argobj = global.params.objname; | |
127 else if (global.params.preservePaths) | |
128 argobj = filename; | |
129 else | |
130 argobj = FileName::name(filename); | |
131 if (!FileName::absolute(argobj)) | |
132 { | |
133 argobj = FileName::combine(global.params.objdir, argobj); | |
134 } | |
135 | |
136 if (global.params.objname) | |
137 objfilename = new FileName(argobj, 0); | |
138 else | |
139 objfilename = FileName::forceExt(argobj, global.obj_ext); | |
140 | |
141 llfilename = FileName::forceExt(argobj, global.ll_ext); | |
142 bcfilename = FileName::forceExt(argobj, global.bc_ext); | |
143 | |
144 symfilename = FileName::forceExt(filename, global.sym_ext); | |
145 | |
146 srcfile = new File(srcfilename); | |
147 | |
148 if (doDocComment) | |
149 { | |
150 setDocfile(); | |
151 } | |
152 | |
153 if (doHdrGen) | |
154 { | |
155 setHdrfile(); | |
156 } | |
157 | |
158 objfile = new File(objfilename); | |
159 bcfile = new File(bcfilename); | |
52 | 160 llfile = new File(llfilename); |
1 | 161 symfile = new File(symfilename); |
94
61615fa85940
[svn r98] Added support for std.c.stdlib.alloca via pragma(LLVM_internal, "alloca").
lindquist
parents:
52
diff
changeset
|
162 |
61615fa85940
[svn r98] Added support for std.c.stdlib.alloca via pragma(LLVM_internal, "alloca").
lindquist
parents:
52
diff
changeset
|
163 // LLVMDC |
61615fa85940
[svn r98] Added support for std.c.stdlib.alloca via pragma(LLVM_internal, "alloca").
lindquist
parents:
52
diff
changeset
|
164 llvmCompileUnit = 0; |
1 | 165 } |
166 | |
167 void Module::setDocfile() | |
168 { | |
169 FileName *docfilename; | |
170 char *argdoc; | |
171 | |
172 if (global.params.docname) | |
173 argdoc = global.params.docname; | |
174 else if (global.params.preservePaths) | |
175 argdoc = (char *)arg; | |
176 else | |
177 argdoc = FileName::name((char *)arg); | |
178 if (!FileName::absolute(argdoc)) | |
179 { //FileName::ensurePathExists(global.params.docdir); | |
180 argdoc = FileName::combine(global.params.docdir, argdoc); | |
181 } | |
182 if (global.params.docname) | |
183 docfilename = new FileName(argdoc, 0); | |
184 else | |
185 docfilename = FileName::forceExt(argdoc, global.doc_ext); | |
186 | |
187 if (docfilename->equals(srcfile->name)) | |
188 { error("Source file and documentation file have same name '%s'", srcfile->name->str); | |
189 fatal(); | |
190 } | |
191 | |
192 docfile = new File(docfilename); | |
193 } | |
194 | |
195 void Module::setHdrfile() | |
196 { | |
197 FileName *hdrfilename; | |
198 char *arghdr; | |
199 | |
200 if (global.params.hdrname) | |
201 arghdr = global.params.hdrname; | |
202 else if (global.params.preservePaths) | |
203 arghdr = (char *)arg; | |
204 else | |
205 arghdr = FileName::name((char *)arg); | |
206 if (!FileName::absolute(arghdr)) | |
207 { //FileName::ensurePathExists(global.params.hdrdir); | |
208 arghdr = FileName::combine(global.params.hdrdir, arghdr); | |
209 } | |
210 if (global.params.hdrname) | |
211 hdrfilename = new FileName(arghdr, 0); | |
212 else | |
213 hdrfilename = FileName::forceExt(arghdr, global.hdr_ext); | |
214 | |
215 if (hdrfilename->equals(srcfile->name)) | |
216 { error("Source file and 'header' file have same name '%s'", srcfile->name->str); | |
217 fatal(); | |
218 } | |
219 | |
220 hdrfile = new File(hdrfilename); | |
221 } | |
222 | |
223 void Module::deleteObjFile() | |
224 { | |
225 if (global.params.obj) | |
226 objfile->remove(); | |
227 //if (global.params.llvmBC) | |
228 bcfile->remove(); | |
229 if (docfile) | |
230 docfile->remove(); | |
231 } | |
232 | |
233 Module::~Module() | |
234 { | |
235 } | |
236 | |
237 char *Module::kind() | |
238 { | |
239 return "module"; | |
240 } | |
241 | |
242 Module *Module::load(Loc loc, Array *packages, Identifier *ident) | |
243 { Module *m; | |
244 char *filename; | |
245 | |
246 //printf("Module::load(ident = '%s')\n", ident->toChars()); | |
247 | |
248 // Build module filename by turning: | |
249 // foo.bar.baz | |
250 // into: | |
251 // foo\bar\baz | |
252 filename = ident->toChars(); | |
253 if (packages && packages->dim) | |
254 { | |
255 OutBuffer buf; | |
256 int i; | |
257 | |
258 for (i = 0; i < packages->dim; i++) | |
259 { Identifier *pid = (Identifier *)packages->data[i]; | |
260 | |
261 buf.writestring(pid->toChars()); | |
262 #if _WIN32 | |
263 buf.writeByte('\\'); | |
264 #else | |
265 buf.writeByte('/'); | |
266 #endif | |
267 } | |
268 buf.writestring(filename); | |
269 buf.writeByte(0); | |
270 filename = (char *)buf.extractData(); | |
271 } | |
272 | |
273 m = new Module(filename, ident, 0, 0); | |
274 m->loc = loc; | |
275 | |
276 /* Search along global.path for .di file, then .d file. | |
277 */ | |
278 char *result = NULL; | |
279 FileName *fdi = FileName::forceExt(filename, global.hdr_ext); | |
280 FileName *fd = FileName::forceExt(filename, global.mars_ext); | |
281 char *sdi = fdi->toChars(); | |
282 char *sd = fd->toChars(); | |
283 | |
284 if (FileName::exists(sdi)) | |
285 result = sdi; | |
286 else if (FileName::exists(sd)) | |
287 result = sd; | |
288 else if (FileName::absolute(filename)) | |
289 ; | |
290 else if (!global.path) | |
291 ; | |
292 else | |
293 { | |
294 for (size_t i = 0; i < global.path->dim; i++) | |
295 { | |
296 char *p = (char *)global.path->data[i]; | |
297 char *n = FileName::combine(p, sdi); | |
298 if (FileName::exists(n)) | |
299 { result = n; | |
300 break; | |
301 } | |
302 mem.free(n); | |
303 n = FileName::combine(p, sd); | |
304 if (FileName::exists(n)) | |
305 { result = n; | |
306 break; | |
307 } | |
308 mem.free(n); | |
309 } | |
310 } | |
311 if (result) | |
312 m->srcfile = new File(result); | |
313 | |
314 if (global.params.verbose) | |
315 { | |
316 printf("import "); | |
317 if (packages) | |
318 { | |
319 for (size_t i = 0; i < packages->dim; i++) | |
320 { Identifier *pid = (Identifier *)packages->data[i]; | |
321 printf("%s.", pid->toChars()); | |
322 } | |
323 } | |
324 printf("%s\t(%s)\n", ident->toChars(), m->srcfile->toChars()); | |
325 } | |
326 | |
327 m->read(loc); | |
328 m->parse(); | |
329 | |
330 #ifdef IN_GCC | |
331 d_gcc_magic_module(m); | |
332 #endif | |
333 | |
334 return m; | |
335 } | |
336 | |
337 void Module::read(Loc loc) | |
338 { | |
339 //printf("Module::read('%s') file '%s'\n", toChars(), srcfile->toChars()); | |
340 if (srcfile->read()) | |
341 { error(loc, "cannot read file '%s'", srcfile->toChars()); | |
342 fatal(); | |
343 } | |
344 } | |
345 | |
346 inline unsigned readwordLE(unsigned short *p) | |
347 { | |
348 #if __I86__ | |
349 return *p; | |
350 #else | |
351 return (((unsigned char *)p)[1] << 8) | ((unsigned char *)p)[0]; | |
352 #endif | |
353 } | |
354 | |
355 inline unsigned readwordBE(unsigned short *p) | |
356 { | |
357 return (((unsigned char *)p)[0] << 8) | ((unsigned char *)p)[1]; | |
358 } | |
359 | |
360 inline unsigned readlongLE(unsigned *p) | |
361 { | |
362 #if __I86__ | |
363 return *p; | |
364 #else | |
365 return ((unsigned char *)p)[0] | | |
366 (((unsigned char *)p)[1] << 8) | | |
367 (((unsigned char *)p)[2] << 16) | | |
368 (((unsigned char *)p)[3] << 24); | |
369 #endif | |
370 } | |
371 | |
372 inline unsigned readlongBE(unsigned *p) | |
373 { | |
374 return ((unsigned char *)p)[3] | | |
375 (((unsigned char *)p)[2] << 8) | | |
376 (((unsigned char *)p)[1] << 16) | | |
377 (((unsigned char *)p)[0] << 24); | |
378 } | |
379 | |
380 #if IN_GCC | |
381 void Module::parse(bool dump_source) | |
382 #else | |
383 void Module::parse() | |
384 #endif | |
385 { char *srcname; | |
386 unsigned char *buf; | |
387 unsigned buflen; | |
388 unsigned le; | |
389 unsigned bom; | |
390 | |
391 //printf("Module::parse()\n"); | |
392 | |
393 srcname = srcfile->name->toChars(); | |
394 //printf("Module::parse(srcname = '%s')\n", srcname); | |
395 | |
396 buf = srcfile->buffer; | |
397 buflen = srcfile->len; | |
398 | |
399 if (buflen >= 2) | |
400 { | |
401 /* Convert all non-UTF-8 formats to UTF-8. | |
402 * BOM : http://www.unicode.org/faq/utf_bom.html | |
403 * 00 00 FE FF UTF-32BE, big-endian | |
404 * FF FE 00 00 UTF-32LE, little-endian | |
405 * FE FF UTF-16BE, big-endian | |
406 * FF FE UTF-16LE, little-endian | |
407 * EF BB BF UTF-8 | |
408 */ | |
409 | |
410 bom = 1; // assume there's a BOM | |
411 if (buf[0] == 0xFF && buf[1] == 0xFE) | |
412 { | |
413 if (buflen >= 4 && buf[2] == 0 && buf[3] == 0) | |
414 { // UTF-32LE | |
415 le = 1; | |
416 | |
417 Lutf32: | |
418 OutBuffer dbuf; | |
419 unsigned *pu = (unsigned *)(buf); | |
420 unsigned *pumax = &pu[buflen / 4]; | |
421 | |
422 if (buflen & 3) | |
423 { error("odd length of UTF-32 char source %u", buflen); | |
424 fatal(); | |
425 } | |
426 | |
427 dbuf.reserve(buflen / 4); | |
428 for (pu += bom; pu < pumax; pu++) | |
429 { unsigned u; | |
430 | |
431 u = le ? readlongLE(pu) : readlongBE(pu); | |
432 if (u & ~0x7F) | |
433 { | |
434 if (u > 0x10FFFF) | |
435 { error("UTF-32 value %08x greater than 0x10FFFF", u); | |
436 fatal(); | |
437 } | |
438 dbuf.writeUTF8(u); | |
439 } | |
440 else | |
441 dbuf.writeByte(u); | |
442 } | |
443 dbuf.writeByte(0); // add 0 as sentinel for scanner | |
444 buflen = dbuf.offset - 1; // don't include sentinel in count | |
445 buf = (unsigned char *) dbuf.extractData(); | |
446 } | |
447 else | |
448 { // UTF-16LE (X86) | |
449 // Convert it to UTF-8 | |
450 le = 1; | |
451 | |
452 Lutf16: | |
453 OutBuffer dbuf; | |
454 unsigned short *pu = (unsigned short *)(buf); | |
455 unsigned short *pumax = &pu[buflen / 2]; | |
456 | |
457 if (buflen & 1) | |
458 { error("odd length of UTF-16 char source %u", buflen); | |
459 fatal(); | |
460 } | |
461 | |
462 dbuf.reserve(buflen / 2); | |
463 for (pu += bom; pu < pumax; pu++) | |
464 { unsigned u; | |
465 | |
466 u = le ? readwordLE(pu) : readwordBE(pu); | |
467 if (u & ~0x7F) | |
468 { if (u >= 0xD800 && u <= 0xDBFF) | |
469 { unsigned u2; | |
470 | |
471 if (++pu > pumax) | |
472 { error("surrogate UTF-16 high value %04x at EOF", u); | |
473 fatal(); | |
474 } | |
475 u2 = le ? readwordLE(pu) : readwordBE(pu); | |
476 if (u2 < 0xDC00 || u2 > 0xDFFF) | |
477 { error("surrogate UTF-16 low value %04x out of range", u2); | |
478 fatal(); | |
479 } | |
480 u = (u - 0xD7C0) << 10; | |
481 u |= (u2 - 0xDC00); | |
482 } | |
483 else if (u >= 0xDC00 && u <= 0xDFFF) | |
484 { error("unpaired surrogate UTF-16 value %04x", u); | |
485 fatal(); | |
486 } | |
487 else if (u == 0xFFFE || u == 0xFFFF) | |
488 { error("illegal UTF-16 value %04x", u); | |
489 fatal(); | |
490 } | |
491 dbuf.writeUTF8(u); | |
492 } | |
493 else | |
494 dbuf.writeByte(u); | |
495 } | |
496 dbuf.writeByte(0); // add 0 as sentinel for scanner | |
497 buflen = dbuf.offset - 1; // don't include sentinel in count | |
498 buf = (unsigned char *) dbuf.extractData(); | |
499 } | |
500 } | |
501 else if (buf[0] == 0xFE && buf[1] == 0xFF) | |
502 { // UTF-16BE | |
503 le = 0; | |
504 goto Lutf16; | |
505 } | |
506 else if (buflen >= 4 && buf[0] == 0 && buf[1] == 0 && buf[2] == 0xFE && buf[3] == 0xFF) | |
507 { // UTF-32BE | |
508 le = 0; | |
509 goto Lutf32; | |
510 } | |
511 else if (buflen >= 3 && buf[0] == 0xEF && buf[1] == 0xBB && buf[2] == 0xBF) | |
512 { // UTF-8 | |
513 | |
514 buf += 3; | |
515 buflen -= 3; | |
516 } | |
517 else | |
518 { | |
519 /* There is no BOM. Make use of Arcane Jill's insight that | |
520 * the first char of D source must be ASCII to | |
521 * figure out the encoding. | |
522 */ | |
523 | |
524 bom = 0; | |
525 if (buflen >= 4) | |
526 { if (buf[1] == 0 && buf[2] == 0 && buf[3] == 0) | |
527 { // UTF-32LE | |
528 le = 1; | |
529 goto Lutf32; | |
530 } | |
531 else if (buf[0] == 0 && buf[1] == 0 && buf[2] == 0) | |
532 { // UTF-32BE | |
533 le = 0; | |
534 goto Lutf32; | |
535 } | |
536 } | |
537 if (buflen >= 2) | |
538 { | |
539 if (buf[1] == 0) | |
540 { // UTF-16LE | |
541 le = 1; | |
542 goto Lutf16; | |
543 } | |
544 else if (buf[0] == 0) | |
545 { // UTF-16BE | |
546 le = 0; | |
547 goto Lutf16; | |
548 } | |
549 } | |
550 | |
551 // It's UTF-8 | |
552 if (buf[0] >= 0x80) | |
553 { error("source file must start with BOM or ASCII character, not \\x%02X", buf[0]); | |
554 fatal(); | |
555 } | |
556 } | |
557 } | |
558 | |
559 #ifdef IN_GCC | |
560 // dump utf-8 encoded source | |
561 if (dump_source) | |
562 { // %% srcname could contain a path ... | |
563 d_gcc_dump_source(srcname, "utf-8", buf, buflen); | |
564 } | |
565 #endif | |
566 | |
567 /* If it starts with the string "Ddoc", then it's a documentation | |
568 * source file. | |
569 */ | |
570 if (buflen >= 4 && memcmp(buf, "Ddoc", 4) == 0) | |
571 { | |
572 comment = buf + 4; | |
573 isDocFile = 1; | |
574 if (!docfile) | |
575 setDocfile(); | |
576 return; | |
577 } | |
578 if (isHtml) | |
579 { | |
580 OutBuffer *dbuf = new OutBuffer(); | |
581 Html h(srcname, buf, buflen); | |
582 h.extractCode(dbuf); | |
583 buf = dbuf->data; | |
584 buflen = dbuf->offset; | |
585 #ifdef IN_GCC | |
586 // dump extracted source | |
587 if (dump_source) | |
588 d_gcc_dump_source(srcname, "d.utf-8", buf, buflen); | |
589 #endif | |
590 } | |
591 Parser p(this, buf, buflen, docfile != NULL); | |
592 p.nextToken(); | |
593 members = p.parseModule(); | |
594 md = p.md; | |
595 numlines = p.loc.linnum; | |
596 | |
597 DsymbolTable *dst; | |
598 | |
599 if (md) | |
600 { this->ident = md->id; | |
601 dst = Package::resolve(md->packages, &this->parent, NULL); | |
602 } | |
603 else | |
604 { | |
605 dst = modules; | |
606 | |
607 /* Check to see if module name is a valid identifier | |
608 */ | |
609 if (!Lexer::isValidIdentifier(this->ident->toChars())) | |
610 error("has non-identifier characters in filename, use module declaration instead"); | |
611 } | |
612 | |
613 // Update global list of modules | |
614 if (!dst->insert(this)) | |
615 { | |
616 if (md) | |
617 error(loc, "is in multiple packages %s", md->toChars()); | |
618 else | |
619 error(loc, "is in multiple defined"); | |
620 } | |
621 else | |
622 { | |
623 amodules.push(this); | |
624 } | |
625 } | |
626 | |
627 void Module::semantic() | |
628 { int i; | |
629 | |
630 if (semanticstarted) | |
631 return; | |
632 | |
633 //printf("+Module::semantic(this = %p, '%s'): parent = %p\n", this, toChars(), parent); | |
634 semanticstarted = 1; | |
635 | |
636 // Note that modules get their own scope, from scratch. | |
637 // This is so regardless of where in the syntax a module | |
638 // gets imported, it is unaffected by context. | |
639 Scope *sc = Scope::createGlobal(this); // create root scope | |
640 | |
641 //printf("Module = %p, linkage = %d\n", sc->scopesym, sc->linkage); | |
642 | |
643 // Add import of "object" if this module isn't "object" | |
644 if (ident != Id::object) | |
645 { | |
646 Import *im = new Import(0, NULL, Id::object, NULL, 0); | |
647 members->shift(im); | |
648 } | |
649 | |
650 // Add all symbols into module's symbol table | |
651 symtab = new DsymbolTable(); | |
652 for (i = 0; i < members->dim; i++) | |
653 { Dsymbol *s; | |
654 | |
655 s = (Dsymbol *)members->data[i]; | |
656 s->addMember(NULL, sc->scopesym, 1); | |
657 } | |
658 | |
659 // Pass 1 semantic routines: do public side of the definition | |
660 for (i = 0; i < members->dim; i++) | |
661 { Dsymbol *s; | |
662 | |
663 s = (Dsymbol *)members->data[i]; | |
664 //printf("\tModule('%s'): '%s'.semantic()\n", toChars(), s->toChars()); | |
665 s->semantic(sc); | |
666 runDeferredSemantic(); | |
667 } | |
668 | |
669 sc = sc->pop(); | |
670 sc->pop(); | |
671 semanticdone = semanticstarted; | |
672 //printf("-Module::semantic(this = %p, '%s'): parent = %p\n", this, toChars(), parent); | |
673 } | |
674 | |
675 void Module::semantic2() | |
676 { int i; | |
677 | |
678 if (deferred.dim) | |
679 { | |
680 for (int i = 0; i < deferred.dim; i++) | |
681 { | |
682 Dsymbol *sd = (Dsymbol *)deferred.data[i]; | |
683 | |
684 sd->error("unable to resolve forward reference in definition"); | |
685 } | |
686 return; | |
687 } | |
688 //printf("Module::semantic2('%s'): parent = %p\n", toChars(), parent); | |
689 if (semanticstarted >= 2) | |
690 return; | |
691 assert(semanticstarted == 1); | |
692 semanticstarted = 2; | |
693 | |
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 //printf("Module = %p\n", sc.scopesym); | |
699 | |
700 // Pass 2 semantic routines: do initializers and function bodies | |
701 for (i = 0; i < members->dim; i++) | |
702 { Dsymbol *s; | |
703 | |
704 s = (Dsymbol *)members->data[i]; | |
705 s->semantic2(sc); | |
706 } | |
707 | |
708 sc = sc->pop(); | |
709 sc->pop(); | |
710 semanticdone = semanticstarted; | |
711 //printf("-Module::semantic2('%s'): parent = %p\n", toChars(), parent); | |
712 } | |
713 | |
714 void Module::semantic3() | |
715 { int i; | |
716 | |
717 //printf("Module::semantic3('%s'): parent = %p\n", toChars(), parent); | |
718 if (semanticstarted >= 3) | |
719 return; | |
720 assert(semanticstarted == 2); | |
721 semanticstarted = 3; | |
722 | |
723 // Note that modules get their own scope, from scratch. | |
724 // This is so regardless of where in the syntax a module | |
725 // gets imported, it is unaffected by context. | |
726 Scope *sc = Scope::createGlobal(this); // create root scope | |
727 //printf("Module = %p\n", sc.scopesym); | |
728 | |
729 // Pass 3 semantic routines: do initializers and function bodies | |
730 for (i = 0; i < members->dim; i++) | |
731 { Dsymbol *s; | |
732 | |
733 s = (Dsymbol *)members->data[i]; | |
734 //printf("Module %s: %s.semantic3()\n", toChars(), s->toChars()); | |
735 s->semantic3(sc); | |
736 } | |
737 | |
738 sc = sc->pop(); | |
739 sc->pop(); | |
740 semanticdone = semanticstarted; | |
741 } | |
742 | |
743 void Module::inlineScan() | |
744 { int i; | |
745 | |
746 if (semanticstarted >= 4) | |
747 return; | |
748 assert(semanticstarted == 3); | |
749 semanticstarted = 4; | |
750 | |
751 // Note that modules get their own scope, from scratch. | |
752 // This is so regardless of where in the syntax a module | |
753 // gets imported, it is unaffected by context. | |
754 //printf("Module = %p\n", sc.scopesym); | |
755 | |
756 for (i = 0; i < members->dim; i++) | |
757 { Dsymbol *s; | |
758 | |
759 s = (Dsymbol *)members->data[i]; | |
760 //if (global.params.verbose) | |
761 //printf("inline scan symbol %s\n", s->toChars()); | |
762 | |
763 s->inlineScan(); | |
764 } | |
765 semanticdone = semanticstarted; | |
766 } | |
767 | |
768 /**************************************************** | |
769 */ | |
770 | |
771 void Module::gensymfile() | |
772 { | |
773 OutBuffer buf; | |
774 HdrGenState hgs; | |
775 int i; | |
776 | |
777 //printf("Module::gensymfile()\n"); | |
778 | |
779 buf.printf("// Sym file generated from '%s'", srcfile->toChars()); | |
780 buf.writenl(); | |
781 | |
782 for (i = 0; i < members->dim; i++) | |
783 { | |
784 Dsymbol *s; | |
785 | |
786 s = (Dsymbol *)members->data[i]; | |
787 s->toCBuffer(&buf, &hgs); | |
788 } | |
789 | |
790 // Transfer image to file | |
791 symfile->setbuffer(buf.data, buf.offset); | |
792 buf.data = NULL; | |
793 | |
794 symfile->writev(); | |
795 } | |
796 | |
797 /********************************** | |
798 * Determine if we need to generate an instance of ModuleInfo | |
799 * for this Module. | |
800 */ | |
801 | |
802 int Module::needModuleInfo() | |
803 { | |
804 return needmoduleinfo || global.params.cov; | |
805 } | |
806 | |
807 Dsymbol *Module::search(Loc loc, Identifier *ident, int flags) | |
808 { | |
809 /* Since modules can be circularly referenced, | |
810 * need to stop infinite recursive searches. | |
811 */ | |
812 | |
813 //printf("%s Module::search('%s', flags = %d) insearch = %d\n", toChars(), ident->toChars(), flags, insearch); | |
814 Dsymbol *s; | |
815 if (insearch) | |
816 s = NULL; | |
817 else if (searchCacheIdent == ident && searchCacheFlags == flags) | |
818 s = searchCacheSymbol; | |
819 else | |
820 { | |
821 insearch = 1; | |
822 s = ScopeDsymbol::search(loc, ident, flags); | |
823 insearch = 0; | |
824 | |
825 searchCacheIdent = ident; | |
826 searchCacheSymbol = s; | |
827 searchCacheFlags = flags; | |
828 } | |
829 return s; | |
830 } | |
831 | |
832 /******************************************* | |
833 * Can't run semantic on s now, try again later. | |
834 */ | |
835 | |
836 void Module::addDeferredSemantic(Dsymbol *s) | |
837 { | |
838 // Don't add it if it is already there | |
839 for (int i = 0; i < deferred.dim; i++) | |
840 { | |
841 Dsymbol *sd = (Dsymbol *)deferred.data[i]; | |
842 | |
843 if (sd == s) | |
844 return; | |
845 } | |
846 | |
847 //printf("Module::addDeferredSemantic('%s')\n", s->toChars()); | |
848 deferred.push(s); | |
849 } | |
850 | |
851 | |
852 /****************************************** | |
853 * Run semantic() on deferred symbols. | |
854 */ | |
855 | |
856 void Module::runDeferredSemantic() | |
857 { | |
858 size_t len; | |
859 | |
860 static int nested; | |
861 if (nested) | |
862 return; | |
863 //if (deferred.dim) printf("+Module::runDeferredSemantic('%s'), len = %d\n", toChars(), deferred.dim); | |
864 nested++; | |
865 | |
866 do | |
867 { | |
868 dprogress = 0; | |
869 len = deferred.dim; | |
870 if (!len) | |
871 break; | |
872 | |
873 Dsymbol **todo; | |
874 Dsymbol *tmp; | |
875 if (len == 1) | |
876 { | |
877 todo = &tmp; | |
878 } | |
879 else | |
880 { | |
881 todo = (Dsymbol **)alloca(len * sizeof(Dsymbol *)); | |
882 assert(todo); | |
883 } | |
884 memcpy(todo, deferred.data, len * sizeof(Dsymbol *)); | |
885 deferred.setDim(0); | |
886 | |
887 for (int i = 0; i < len; i++) | |
888 { | |
889 Dsymbol *s = todo[i]; | |
890 | |
891 s->semantic(NULL); | |
892 //printf("deferred: %s, parent = %s\n", s->toChars(), s->parent->toChars()); | |
893 } | |
894 //printf("\tdeferred.dim = %d, len = %d, dprogress = %d\n", deferred.dim, len, dprogress); | |
895 } while (deferred.dim < len || dprogress); // while making progress | |
896 nested--; | |
897 //printf("-Module::runDeferredSemantic('%s'), len = %d\n", toChars(), deferred.dim); | |
898 } | |
899 | |
900 /* =========================== ModuleDeclaration ===================== */ | |
901 | |
902 ModuleDeclaration::ModuleDeclaration(Array *packages, Identifier *id) | |
903 { | |
904 this->packages = packages; | |
905 this->id = id; | |
906 } | |
907 | |
908 char *ModuleDeclaration::toChars() | |
909 { | |
910 OutBuffer buf; | |
911 int i; | |
912 | |
913 if (packages && packages->dim) | |
914 { | |
915 for (i = 0; i < packages->dim; i++) | |
916 { Identifier *pid = (Identifier *)packages->data[i]; | |
917 | |
918 buf.writestring(pid->toChars()); | |
919 buf.writeByte('.'); | |
920 } | |
921 } | |
922 buf.writestring(id->toChars()); | |
923 buf.writeByte(0); | |
924 return (char *)buf.extractData(); | |
925 } | |
926 | |
927 /* =========================== Package ===================== */ | |
928 | |
929 Package::Package(Identifier *ident) | |
930 : ScopeDsymbol(ident) | |
931 { | |
932 } | |
933 | |
934 | |
935 char *Package::kind() | |
936 { | |
937 return "package"; | |
938 } | |
939 | |
940 | |
941 DsymbolTable *Package::resolve(Array *packages, Dsymbol **pparent, Package **ppkg) | |
942 { | |
943 DsymbolTable *dst = Module::modules; | |
944 Dsymbol *parent = NULL; | |
945 | |
946 //printf("Package::resolve()\n"); | |
947 if (ppkg) | |
948 *ppkg = NULL; | |
949 | |
950 if (packages) | |
951 { int i; | |
952 | |
953 for (i = 0; i < packages->dim; i++) | |
954 { Identifier *pid = (Identifier *)packages->data[i]; | |
955 Dsymbol *p; | |
956 | |
957 p = dst->lookup(pid); | |
958 if (!p) | |
959 { | |
960 p = new Package(pid); | |
961 dst->insert(p); | |
962 p->parent = parent; | |
963 ((ScopeDsymbol *)p)->symtab = new DsymbolTable(); | |
964 } | |
965 else | |
966 { | |
967 assert(p->isPackage()); | |
968 if (p->isModule()) | |
969 { p->error("module and package have the same name"); | |
970 fatal(); | |
971 break; | |
972 } | |
973 } | |
974 parent = p; | |
975 dst = ((Package *)p)->symtab; | |
976 if (ppkg && !*ppkg) | |
977 *ppkg = (Package *)p; | |
978 } | |
979 if (pparent) | |
980 { | |
981 *pparent = parent; | |
982 } | |
983 } | |
984 return dst; | |
985 } |