]>
Commit | Line | Data |
---|---|---|
b4c522fa IB |
1 | |
2 | /* Compiler implementation of the D programming language | |
a3b38b77 | 3 | * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved |
b4c522fa IB |
4 | * written by Dave Fladebo |
5 | * http://www.digitalmars.com | |
6 | * Distributed under the Boost Software License, Version 1.0. | |
7 | * http://www.boost.org/LICENSE_1_0.txt | |
8 | * https://github.com/D-Programming-Language/dmd/blob/master/src/hdrgen.c | |
9 | */ | |
10 | ||
11 | // Routines to emit header files | |
12 | ||
f9ab59ff | 13 | #include "root/dsystem.h" |
b4c522fa IB |
14 | #include "root/rmem.h" |
15 | ||
16 | #include "mars.h" | |
17 | #include "id.h" | |
18 | #include "init.h" | |
19 | ||
20 | #include "attrib.h" | |
21 | #include "cond.h" | |
22 | #include "doc.h" | |
23 | #include "enum.h" | |
24 | #include "import.h" | |
25 | #include "module.h" | |
26 | #include "mtype.h" | |
27 | #include "parse.h" | |
28 | #include "scope.h" | |
29 | #include "staticassert.h" | |
30 | #include "target.h" | |
31 | #include "template.h" | |
32 | #include "utf.h" | |
33 | #include "version.h" | |
34 | ||
35 | #include "declaration.h" | |
36 | #include "aggregate.h" | |
37 | #include "expression.h" | |
38 | #include "ctfe.h" | |
39 | #include "statement.h" | |
40 | #include "aliasthis.h" | |
41 | #include "nspace.h" | |
42 | #include "hdrgen.h" | |
43 | ||
44 | void linkageToBuffer(OutBuffer *buf, LINK linkage); | |
45 | void MODtoBuffer(OutBuffer *buf, MOD mod); | |
46 | ||
47 | void genhdrfile(Module *m) | |
48 | { | |
49 | OutBuffer buf; | |
50 | buf.doindent = 1; | |
51 | ||
52 | buf.printf("// D import file generated from '%s'", m->srcfile->toChars()); | |
53 | buf.writenl(); | |
54 | ||
55 | HdrGenState hgs; | |
56 | hgs.hdrgen = true; | |
57 | ||
58 | toCBuffer(m, &buf, &hgs); | |
59 | ||
60 | // Transfer image to file | |
d103f336 | 61 | m->hdrfile->setbuffer(buf.slice().ptr, buf.length()); |
b4c522fa IB |
62 | buf.extractData(); |
63 | ||
64 | ensurePathToNameExists(Loc(), m->hdrfile->toChars()); | |
65 | writeFile(m->loc, m->hdrfile); | |
66 | } | |
67 | ||
68 | /** | |
69 | * Dumps the full contents of module `m` to `buf`. | |
70 | * Params: | |
71 | * buf = buffer to write to. | |
72 | * m = module to visit all members of. | |
73 | */ | |
74 | void moduleToBuffer(OutBuffer *buf, Module *m) | |
75 | { | |
76 | HdrGenState hgs; | |
77 | hgs.fullDump = true; | |
78 | toCBuffer(m, buf, &hgs); | |
79 | } | |
80 | ||
81 | class PrettyPrintVisitor : public Visitor | |
82 | { | |
83 | public: | |
84 | OutBuffer *buf; | |
85 | HdrGenState *hgs; | |
86 | bool declstring; // set while declaring alias for string,wstring or dstring | |
87 | EnumDeclaration *inEnumDecl; | |
88 | ||
89 | PrettyPrintVisitor(OutBuffer *buf, HdrGenState *hgs) | |
90 | : buf(buf), hgs(hgs), declstring(false), inEnumDecl(NULL) | |
91 | { | |
92 | } | |
93 | ||
94 | void visit(Statement *) | |
95 | { | |
96 | buf->printf("Statement::toCBuffer()"); | |
97 | buf->writenl(); | |
98 | assert(0); | |
99 | } | |
100 | ||
101 | void visit(ErrorStatement *) | |
102 | { | |
103 | buf->printf("__error__"); | |
104 | buf->writenl(); | |
105 | } | |
106 | ||
107 | void visit(ExpStatement *s) | |
108 | { | |
109 | if (s->exp && s->exp->op == TOKdeclaration) | |
110 | { | |
111 | // bypass visit(DeclarationExp) | |
112 | ((DeclarationExp *)s->exp)->declaration->accept(this); | |
113 | return; | |
114 | } | |
115 | if (s->exp) | |
116 | s->exp->accept(this); | |
117 | buf->writeByte(';'); | |
118 | if (!hgs->forStmtInit) | |
119 | buf->writenl(); | |
120 | } | |
121 | ||
122 | void visit(CompileStatement *s) | |
123 | { | |
124 | buf->writestring("mixin("); | |
125 | s->exp->accept(this); | |
126 | buf->writestring(");"); | |
127 | if (!hgs->forStmtInit) | |
128 | buf->writenl(); | |
129 | } | |
130 | ||
131 | void visit(CompoundStatement *s) | |
132 | { | |
2cbc99d1 | 133 | for (size_t i = 0; i < s->statements->length; i++) |
b4c522fa IB |
134 | { |
135 | Statement *sx = (*s->statements)[i]; | |
136 | if (sx) | |
137 | sx->accept(this); | |
138 | } | |
139 | } | |
140 | ||
141 | void visit(CompoundDeclarationStatement *s) | |
142 | { | |
143 | bool anywritten = false; | |
2cbc99d1 | 144 | for (size_t i = 0; i < s->statements->length; i++) |
b4c522fa IB |
145 | { |
146 | Statement *sx = (*s->statements)[i]; | |
147 | ExpStatement *ds = sx ? sx->isExpStatement() : NULL; | |
148 | if (ds && ds->exp->op == TOKdeclaration) | |
149 | { | |
150 | Dsymbol *d = ((DeclarationExp *)ds->exp)->declaration; | |
151 | assert(d->isDeclaration()); | |
152 | if (VarDeclaration *v = d->isVarDeclaration()) | |
153 | visitVarDecl(v, anywritten); | |
154 | else | |
155 | d->accept(this); | |
156 | anywritten = true; | |
157 | } | |
158 | } | |
159 | buf->writeByte(';'); | |
160 | if (!hgs->forStmtInit) | |
161 | buf->writenl(); | |
162 | } | |
163 | ||
164 | void visit(UnrolledLoopStatement *s) | |
165 | { | |
166 | buf->writestring("unrolled {"); | |
167 | buf->writenl(); | |
168 | buf->level++; | |
169 | ||
2cbc99d1 | 170 | for (size_t i = 0; i < s->statements->length; i++) |
b4c522fa IB |
171 | { |
172 | Statement *sx = (*s->statements)[i]; | |
173 | if (sx) | |
174 | sx->accept(this); | |
175 | } | |
176 | ||
177 | buf->level--; | |
178 | buf->writeByte('}'); | |
179 | buf->writenl(); | |
180 | } | |
181 | ||
182 | void visit(ScopeStatement *s) | |
183 | { | |
184 | buf->writeByte('{'); | |
185 | buf->writenl(); | |
186 | buf->level++; | |
187 | ||
188 | if (s->statement) | |
189 | s->statement->accept(this); | |
190 | ||
191 | buf->level--; | |
192 | buf->writeByte('}'); | |
193 | buf->writenl(); | |
194 | } | |
195 | ||
196 | void visit(WhileStatement *s) | |
197 | { | |
198 | buf->writestring("while ("); | |
199 | s->condition->accept(this); | |
200 | buf->writeByte(')'); | |
201 | buf->writenl(); | |
202 | if (s->_body) | |
203 | s->_body->accept(this); | |
204 | } | |
205 | ||
206 | void visit(DoStatement *s) | |
207 | { | |
208 | buf->writestring("do"); | |
209 | buf->writenl(); | |
210 | if (s->_body) | |
211 | s->_body->accept(this); | |
212 | buf->writestring("while ("); | |
213 | s->condition->accept(this); | |
214 | buf->writestring(");"); | |
215 | buf->writenl(); | |
216 | } | |
217 | ||
218 | void visit(ForStatement *s) | |
219 | { | |
220 | buf->writestring("for ("); | |
221 | if (s->_init) | |
222 | { | |
223 | hgs->forStmtInit++; | |
224 | s->_init->accept(this); | |
225 | hgs->forStmtInit--; | |
226 | } | |
227 | else | |
228 | buf->writeByte(';'); | |
229 | if (s->condition) | |
230 | { | |
231 | buf->writeByte(' '); | |
232 | s->condition->accept(this); | |
233 | } | |
234 | buf->writeByte(';'); | |
235 | if (s->increment) | |
236 | { | |
237 | buf->writeByte(' '); | |
238 | s->increment->accept(this); | |
239 | } | |
240 | buf->writeByte(')'); | |
241 | buf->writenl(); | |
242 | buf->writeByte('{'); | |
243 | buf->writenl(); | |
244 | buf->level++; | |
245 | if (s->_body) | |
246 | s->_body->accept(this); | |
247 | buf->level--; | |
248 | buf->writeByte('}'); | |
249 | buf->writenl(); | |
250 | } | |
251 | ||
5b74dd0a | 252 | void foreachWithoutBody(ForeachStatement *s) |
b4c522fa IB |
253 | { |
254 | buf->writestring(Token::toChars(s->op)); | |
255 | buf->writestring(" ("); | |
2cbc99d1 | 256 | for (size_t i = 0; i < s->parameters->length; i++) |
b4c522fa IB |
257 | { |
258 | Parameter *p = (*s->parameters)[i]; | |
259 | if (i) | |
260 | buf->writestring(", "); | |
261 | if (stcToBuffer(buf, p->storageClass)) | |
262 | buf->writeByte(' '); | |
263 | if (p->type) | |
264 | typeToBuffer(p->type, p->ident); | |
265 | else | |
266 | buf->writestring(p->ident->toChars()); | |
267 | } | |
268 | buf->writestring("; "); | |
269 | s->aggr->accept(this); | |
270 | buf->writeByte(')'); | |
271 | buf->writenl(); | |
5b74dd0a IB |
272 | } |
273 | ||
274 | void visit(ForeachStatement *s) | |
275 | { | |
276 | foreachWithoutBody(s); | |
b4c522fa IB |
277 | buf->writeByte('{'); |
278 | buf->writenl(); | |
279 | buf->level++; | |
280 | if (s->_body) | |
281 | s->_body->accept(this); | |
282 | buf->level--; | |
283 | buf->writeByte('}'); | |
284 | buf->writenl(); | |
285 | } | |
286 | ||
5b74dd0a | 287 | void foreachRangeWithoutBody(ForeachRangeStatement *s) |
b4c522fa IB |
288 | { |
289 | buf->writestring(Token::toChars(s->op)); | |
290 | buf->writestring(" ("); | |
291 | ||
292 | if (s->prm->type) | |
293 | typeToBuffer(s->prm->type, s->prm->ident); | |
294 | else | |
295 | buf->writestring(s->prm->ident->toChars()); | |
296 | ||
297 | buf->writestring("; "); | |
298 | s->lwr->accept(this); | |
299 | buf->writestring(" .. "); | |
300 | s->upr->accept(this); | |
301 | buf->writeByte(')'); | |
302 | buf->writenl(); | |
303 | buf->writeByte('{'); | |
304 | buf->writenl(); | |
5b74dd0a IB |
305 | } |
306 | ||
307 | void visit(ForeachRangeStatement *s) | |
308 | { | |
309 | foreachRangeWithoutBody(s); | |
b4c522fa IB |
310 | buf->level++; |
311 | if (s->_body) | |
312 | s->_body->accept(this); | |
313 | buf->level--; | |
314 | buf->writeByte('}'); | |
315 | buf->writenl(); | |
316 | } | |
317 | ||
5b74dd0a IB |
318 | void visit(StaticForeachStatement *s) |
319 | { | |
320 | buf->writestring("static "); | |
321 | if (s->sfe->aggrfe) | |
322 | { | |
323 | visit(s->sfe->aggrfe); | |
324 | } | |
325 | else | |
326 | { | |
327 | assert(s->sfe->rangefe); | |
328 | visit(s->sfe->rangefe); | |
329 | } | |
330 | } | |
331 | ||
b4c522fa IB |
332 | void visit(IfStatement *s) |
333 | { | |
334 | buf->writestring("if ("); | |
335 | if (Parameter *p = s->prm) | |
336 | { | |
337 | StorageClass stc = p->storageClass; | |
338 | if (!p->type && !stc) | |
339 | stc = STCauto; | |
340 | if (stcToBuffer(buf, stc)) | |
341 | buf->writeByte(' '); | |
342 | if (p->type) | |
343 | typeToBuffer(p->type, p->ident); | |
344 | else | |
345 | buf->writestring(p->ident->toChars()); | |
346 | buf->writestring(" = "); | |
347 | } | |
348 | s->condition->accept(this); | |
349 | buf->writeByte(')'); | |
350 | buf->writenl(); | |
351 | if (s->ifbody->isScopeStatement()) | |
352 | { | |
353 | s->ifbody->accept(this); | |
354 | } | |
355 | else | |
356 | { | |
357 | buf->level++; | |
358 | s->ifbody->accept(this); | |
359 | buf->level--; | |
360 | } | |
361 | if (s->elsebody) | |
362 | { | |
363 | buf->writestring("else"); | |
364 | if (!s->elsebody->isIfStatement()) | |
365 | { | |
366 | buf->writenl(); | |
367 | } | |
368 | else | |
369 | { | |
370 | buf->writeByte(' '); | |
371 | } | |
372 | if (s->elsebody->isScopeStatement() || s->elsebody->isIfStatement()) | |
373 | { | |
374 | s->elsebody->accept(this); | |
375 | } | |
376 | else | |
377 | { | |
378 | buf->level++; | |
379 | s->elsebody->accept(this); | |
380 | buf->level--; | |
381 | } | |
382 | } | |
383 | } | |
384 | ||
385 | void visit(ConditionalStatement *s) | |
386 | { | |
387 | s->condition->accept(this); | |
388 | buf->writenl(); | |
389 | buf->writeByte('{'); | |
390 | buf->writenl(); | |
391 | buf->level++; | |
392 | if (s->ifbody) | |
393 | s->ifbody->accept(this); | |
394 | buf->level--; | |
395 | buf->writeByte('}'); | |
396 | buf->writenl(); | |
397 | if (s->elsebody) | |
398 | { | |
399 | buf->writestring("else"); | |
400 | buf->writenl(); | |
401 | buf->writeByte('{'); | |
402 | buf->level++; | |
403 | buf->writenl(); | |
404 | s->elsebody->accept(this); | |
405 | buf->level--; | |
406 | buf->writeByte('}'); | |
407 | } | |
408 | buf->writenl(); | |
409 | } | |
410 | ||
411 | void visit(PragmaStatement *s) | |
412 | { | |
413 | buf->writestring("pragma ("); | |
414 | buf->writestring(s->ident->toChars()); | |
2cbc99d1 | 415 | if (s->args && s->args->length) |
b4c522fa IB |
416 | { |
417 | buf->writestring(", "); | |
418 | argsToBuffer(s->args); | |
419 | } | |
420 | buf->writeByte(')'); | |
421 | if (s->_body) | |
422 | { | |
423 | buf->writenl(); | |
424 | buf->writeByte('{'); | |
425 | buf->writenl(); | |
426 | buf->level++; | |
427 | ||
428 | s->_body->accept(this); | |
429 | ||
430 | buf->level--; | |
431 | buf->writeByte('}'); | |
432 | buf->writenl(); | |
433 | } | |
434 | else | |
435 | { | |
436 | buf->writeByte(';'); | |
437 | buf->writenl(); | |
438 | } | |
439 | } | |
440 | ||
441 | void visit(StaticAssertStatement *s) | |
442 | { | |
443 | s->sa->accept(this); | |
444 | } | |
445 | ||
446 | void visit(SwitchStatement *s) | |
447 | { | |
448 | buf->writestring(s->isFinal ? "final switch (" : "switch ("); | |
449 | s->condition->accept(this); | |
450 | buf->writeByte(')'); | |
451 | buf->writenl(); | |
452 | if (s->_body) | |
453 | { | |
454 | if (!s->_body->isScopeStatement()) | |
455 | { | |
456 | buf->writeByte('{'); | |
457 | buf->writenl(); | |
458 | buf->level++; | |
459 | s->_body->accept(this); | |
460 | buf->level--; | |
461 | buf->writeByte('}'); | |
462 | buf->writenl(); | |
463 | } | |
464 | else | |
465 | { | |
466 | s->_body->accept(this); | |
467 | } | |
468 | } | |
469 | } | |
470 | ||
471 | void visit(CaseStatement *s) | |
472 | { | |
473 | buf->writestring("case "); | |
474 | s->exp->accept(this); | |
475 | buf->writeByte(':'); | |
476 | buf->writenl(); | |
477 | s->statement->accept(this); | |
478 | } | |
479 | ||
480 | void visit(CaseRangeStatement *s) | |
481 | { | |
482 | buf->writestring("case "); | |
483 | s->first->accept(this); | |
484 | buf->writestring(": .. case "); | |
485 | s->last->accept(this); | |
486 | buf->writeByte(':'); | |
487 | buf->writenl(); | |
488 | s->statement->accept(this); | |
489 | } | |
490 | ||
491 | void visit(DefaultStatement *s) | |
492 | { | |
493 | buf->writestring("default:"); | |
494 | buf->writenl(); | |
495 | s->statement->accept(this); | |
496 | } | |
497 | ||
498 | void visit(GotoDefaultStatement *) | |
499 | { | |
500 | buf->writestring("goto default;"); | |
501 | buf->writenl(); | |
502 | } | |
503 | ||
504 | void visit(GotoCaseStatement *s) | |
505 | { | |
506 | buf->writestring("goto case"); | |
507 | if (s->exp) | |
508 | { | |
509 | buf->writeByte(' '); | |
510 | s->exp->accept(this); | |
511 | } | |
512 | buf->writeByte(';'); | |
513 | buf->writenl(); | |
514 | } | |
515 | ||
516 | void visit(SwitchErrorStatement *) | |
517 | { | |
518 | buf->writestring("SwitchErrorStatement::toCBuffer()"); | |
519 | buf->writenl(); | |
520 | } | |
521 | ||
522 | void visit(ReturnStatement *s) | |
523 | { | |
524 | buf->printf("return "); | |
525 | if (s->exp) | |
526 | s->exp->accept(this); | |
527 | buf->writeByte(';'); | |
528 | buf->writenl(); | |
529 | } | |
530 | ||
531 | void visit(BreakStatement *s) | |
532 | { | |
533 | buf->writestring("break"); | |
534 | if (s->ident) | |
535 | { | |
536 | buf->writeByte(' '); | |
537 | buf->writestring(s->ident->toChars()); | |
538 | } | |
539 | buf->writeByte(';'); | |
540 | buf->writenl(); | |
541 | } | |
542 | ||
543 | void visit(ContinueStatement *s) | |
544 | { | |
545 | buf->writestring("continue"); | |
546 | if (s->ident) | |
547 | { | |
548 | buf->writeByte(' '); | |
549 | buf->writestring(s->ident->toChars()); | |
550 | } | |
551 | buf->writeByte(';'); | |
552 | buf->writenl(); | |
553 | } | |
554 | ||
555 | void visit(SynchronizedStatement *s) | |
556 | { | |
557 | buf->writestring("synchronized"); | |
558 | if (s->exp) | |
559 | { | |
560 | buf->writeByte('('); | |
561 | s->exp->accept(this); | |
562 | buf->writeByte(')'); | |
563 | } | |
564 | if (s->_body) | |
565 | { | |
566 | buf->writeByte(' '); | |
567 | s->_body->accept(this); | |
568 | } | |
569 | } | |
570 | ||
571 | void visit(WithStatement *s) | |
572 | { | |
573 | buf->writestring("with ("); | |
574 | s->exp->accept(this); | |
575 | buf->writestring(")"); | |
576 | buf->writenl(); | |
577 | if (s->_body) | |
578 | s->_body->accept(this); | |
579 | } | |
580 | ||
581 | void visit(TryCatchStatement *s) | |
582 | { | |
583 | buf->writestring("try"); | |
584 | buf->writenl(); | |
585 | if (s->_body) | |
586 | s->_body->accept(this); | |
2cbc99d1 | 587 | for (size_t i = 0; i < s->catches->length; i++) |
b4c522fa IB |
588 | { |
589 | Catch *c = (*s->catches)[i]; | |
590 | visit(c); | |
591 | } | |
592 | } | |
593 | ||
594 | void visit(TryFinallyStatement *s) | |
595 | { | |
596 | buf->writestring("try"); | |
597 | buf->writenl(); | |
598 | buf->writeByte('{'); | |
599 | buf->writenl(); | |
600 | buf->level++; | |
601 | s->_body->accept(this); | |
602 | buf->level--; | |
603 | buf->writeByte('}'); | |
604 | buf->writenl(); | |
605 | buf->writestring("finally"); | |
606 | buf->writenl(); | |
607 | if (s->finalbody->isScopeStatement()) | |
608 | { | |
609 | s->finalbody->accept(this); | |
610 | } | |
611 | else | |
612 | { | |
613 | buf->level++; | |
614 | s->finalbody->accept(this); | |
615 | buf->level--; | |
616 | } | |
617 | buf->writeByte('}'); | |
618 | buf->writenl(); | |
619 | } | |
620 | ||
72acf751 | 621 | void visit(ScopeGuardStatement *s) |
b4c522fa IB |
622 | { |
623 | buf->writestring(Token::toChars(s->tok)); | |
624 | buf->writeByte(' '); | |
625 | s->statement->accept(this); | |
626 | } | |
627 | ||
628 | void visit(ThrowStatement *s) | |
629 | { | |
630 | buf->printf("throw "); | |
631 | s->exp->accept(this); | |
632 | buf->writeByte(';'); | |
633 | buf->writenl(); | |
634 | } | |
635 | ||
636 | void visit(DebugStatement *s) | |
637 | { | |
638 | if (s->statement) | |
639 | { | |
640 | s->statement->accept(this); | |
641 | } | |
642 | } | |
643 | ||
644 | void visit(GotoStatement *s) | |
645 | { | |
646 | buf->writestring("goto "); | |
647 | buf->writestring(s->ident->toChars()); | |
648 | buf->writeByte(';'); | |
649 | buf->writenl(); | |
650 | } | |
651 | ||
652 | void visit(LabelStatement *s) | |
653 | { | |
654 | buf->writestring(s->ident->toChars()); | |
655 | buf->writeByte(':'); | |
656 | buf->writenl(); | |
657 | if (s->statement) | |
658 | s->statement->accept(this); | |
659 | } | |
660 | ||
661 | void visit(AsmStatement *s) | |
662 | { | |
663 | buf->writestring("asm { "); | |
664 | Token *t = s->tokens; | |
665 | buf->level++; | |
666 | while (t) | |
667 | { | |
668 | buf->writestring(t->toChars()); | |
669 | if (t->next && | |
670 | t->value != TOKmin && | |
671 | t->value != TOKcomma && t->next->value != TOKcomma && | |
672 | t->value != TOKlbracket && t->next->value != TOKlbracket && | |
673 | t->next->value != TOKrbracket && | |
674 | t->value != TOKlparen && t->next->value != TOKlparen && | |
675 | t->next->value != TOKrparen && | |
676 | t->value != TOKdot && t->next->value != TOKdot) | |
677 | { | |
678 | buf->writeByte(' '); | |
679 | } | |
680 | t = t->next; | |
681 | } | |
682 | buf->level--; | |
683 | buf->writestring("; }"); | |
684 | buf->writenl(); | |
685 | } | |
686 | ||
687 | void visit(ImportStatement *s) | |
688 | { | |
2cbc99d1 | 689 | for (size_t i = 0; i < s->imports->length; i++) |
b4c522fa IB |
690 | { |
691 | Dsymbol *imp = (*s->imports)[i]; | |
692 | imp->accept(this); | |
693 | } | |
694 | } | |
695 | ||
696 | void visit(Catch *c) | |
697 | { | |
698 | buf->writestring("catch"); | |
699 | if (c->type) | |
700 | { | |
701 | buf->writeByte('('); | |
702 | typeToBuffer(c->type, c->ident); | |
703 | buf->writeByte(')'); | |
704 | } | |
705 | buf->writenl(); | |
706 | buf->writeByte('{'); | |
707 | buf->writenl(); | |
708 | buf->level++; | |
709 | if (c->handler) | |
710 | c->handler->accept(this); | |
711 | buf->level--; | |
712 | buf->writeByte('}'); | |
713 | buf->writenl(); | |
714 | } | |
715 | ||
716 | //////////////////////////////////////////////////////////////////////////// | |
717 | ||
718 | /************************************************** | |
719 | * An entry point to pretty-print type. | |
720 | */ | |
721 | void typeToBuffer(Type *t, Identifier *ident) | |
722 | { | |
723 | if (t->ty == Tfunction) | |
724 | { | |
725 | visitFuncIdentWithPrefix((TypeFunction *)t, ident, NULL); | |
726 | return; | |
727 | } | |
728 | ||
729 | visitWithMask(t, 0); | |
730 | ||
731 | if (ident) | |
732 | { | |
733 | buf->writeByte(' '); | |
734 | buf->writestring(ident->toChars()); | |
735 | } | |
736 | } | |
737 | ||
738 | void visitWithMask(Type *t, unsigned char modMask) | |
739 | { | |
740 | // Tuples and functions don't use the type constructor syntax | |
741 | if (modMask == t->mod || | |
742 | t->ty == Tfunction || | |
743 | t->ty == Ttuple) | |
744 | { | |
745 | t->accept(this); | |
746 | } | |
747 | else | |
748 | { | |
749 | unsigned char m = t->mod & ~(t->mod & modMask); | |
750 | if (m & MODshared) | |
751 | { | |
752 | MODtoBuffer(buf, MODshared); | |
753 | buf->writeByte('('); | |
754 | } | |
755 | if (m & MODwild) | |
756 | { | |
757 | MODtoBuffer(buf, MODwild); | |
758 | buf->writeByte('('); | |
759 | } | |
760 | if (m & (MODconst | MODimmutable)) | |
761 | { | |
762 | MODtoBuffer(buf, m & (MODconst | MODimmutable)); | |
763 | buf->writeByte('('); | |
764 | } | |
765 | ||
766 | t->accept(this); | |
767 | ||
768 | if (m & (MODconst | MODimmutable)) | |
769 | buf->writeByte(')'); | |
770 | if (m & MODwild) | |
771 | buf->writeByte(')'); | |
772 | if (m & MODshared) | |
773 | buf->writeByte(')'); | |
774 | } | |
775 | } | |
776 | ||
777 | void visit(Type *t) | |
778 | { | |
779 | printf("t = %p, ty = %d\n", t, t->ty); | |
780 | assert(0); | |
781 | } | |
782 | ||
783 | void visit(TypeError *) | |
784 | { | |
785 | buf->writestring("_error_"); | |
786 | } | |
787 | ||
788 | void visit(TypeBasic *t) | |
789 | { | |
790 | //printf("TypeBasic::toCBuffer2(t->mod = %d)\n", t->mod); | |
791 | buf->writestring(t->dstring); | |
792 | } | |
793 | ||
5b74dd0a IB |
794 | void visit(TypeTraits *t) |
795 | { | |
796 | //printf("TypeBasic::toCBuffer2(t.mod = %d)\n", t.mod); | |
797 | t->exp->accept(this); | |
798 | } | |
799 | ||
b4c522fa IB |
800 | void visit(TypeVector *t) |
801 | { | |
802 | //printf("TypeVector::toCBuffer2(t->mod = %d)\n", t->mod); | |
803 | buf->writestring("__vector("); | |
804 | visitWithMask(t->basetype, t->mod); | |
805 | buf->writestring(")"); | |
806 | } | |
807 | ||
808 | void visit(TypeSArray *t) | |
809 | { | |
810 | visitWithMask(t->next, t->mod); | |
811 | buf->writeByte('['); | |
812 | sizeToBuffer(t->dim); | |
813 | buf->writeByte(']'); | |
814 | } | |
815 | ||
816 | void visit(TypeDArray *t) | |
817 | { | |
818 | Type *ut = t->castMod(0); | |
819 | if (declstring) | |
820 | goto L1; | |
821 | if (ut->equals(Type::tstring)) | |
822 | buf->writestring("string"); | |
823 | else if (ut->equals(Type::twstring)) | |
824 | buf->writestring("wstring"); | |
825 | else if (ut->equals(Type::tdstring)) | |
826 | buf->writestring("dstring"); | |
827 | else | |
828 | { | |
829 | L1: | |
830 | visitWithMask(t->next, t->mod); | |
831 | buf->writestring("[]"); | |
832 | } | |
833 | } | |
834 | ||
835 | void visit(TypeAArray *t) | |
836 | { | |
837 | visitWithMask(t->next, t->mod); | |
838 | buf->writeByte('['); | |
839 | visitWithMask(t->index, 0); | |
840 | buf->writeByte(']'); | |
841 | } | |
842 | ||
843 | void visit(TypePointer *t) | |
844 | { | |
845 | //printf("TypePointer::toCBuffer2() next = %d\n", t->next->ty); | |
846 | if (t->next->ty == Tfunction) | |
847 | visitFuncIdentWithPostfix((TypeFunction *)t->next, "function"); | |
848 | else | |
849 | { | |
850 | visitWithMask(t->next, t->mod); | |
851 | buf->writeByte('*'); | |
852 | } | |
853 | } | |
854 | ||
855 | void visit(TypeReference *t) | |
856 | { | |
857 | visitWithMask(t->next, t->mod); | |
858 | buf->writeByte('&'); | |
859 | } | |
860 | ||
861 | void visit(TypeFunction *t) | |
862 | { | |
863 | //printf("TypeFunction::toCBuffer2() t = %p, ref = %d\n", t, t->isref); | |
864 | visitFuncIdentWithPostfix(t, NULL); | |
865 | } | |
866 | ||
867 | // callback for TypeFunction::attributesApply | |
868 | struct PrePostAppendStrings | |
869 | { | |
870 | OutBuffer *buf; | |
871 | bool isPostfixStyle; | |
872 | bool isCtor; | |
873 | ||
874 | static int fp(void *param, const char *str) | |
875 | { | |
876 | PrePostAppendStrings *p = (PrePostAppendStrings *)param; | |
877 | ||
878 | // don't write 'ref' for ctors | |
879 | if (p->isCtor && strcmp(str, "ref") == 0) | |
880 | return 0; | |
881 | ||
882 | if ( p->isPostfixStyle) p->buf->writeByte(' '); | |
883 | p->buf->writestring(str); | |
884 | if (!p->isPostfixStyle) p->buf->writeByte(' '); | |
885 | return 0; | |
886 | } | |
887 | }; | |
888 | ||
889 | void visitFuncIdentWithPostfix(TypeFunction *t, const char *ident) | |
890 | { | |
891 | if (t->inuse) | |
892 | { | |
893 | t->inuse = 2; // flag error to caller | |
894 | return; | |
895 | } | |
896 | t->inuse++; | |
897 | ||
898 | PrePostAppendStrings pas; | |
899 | pas.buf = buf; | |
900 | pas.isCtor = false; | |
901 | pas.isPostfixStyle = true; | |
902 | ||
903 | if (t->linkage > LINKd && hgs->ddoc != 1 && !hgs->hdrgen) | |
904 | { | |
905 | linkageToBuffer(buf, t->linkage); | |
906 | buf->writeByte(' '); | |
907 | } | |
908 | ||
909 | if (t->next) | |
910 | { | |
911 | typeToBuffer(t->next, NULL); | |
912 | if (ident) | |
913 | buf->writeByte(' '); | |
914 | } | |
915 | else if (hgs->ddoc) | |
916 | buf->writestring("auto "); | |
917 | ||
918 | if (ident) | |
919 | buf->writestring(ident); | |
920 | ||
c3a2ba10 | 921 | parametersToBuffer(t->parameterList.parameters, t->parameterList.varargs); |
b4c522fa IB |
922 | |
923 | /* Use postfix style for attributes | |
924 | */ | |
925 | if (t->mod) | |
926 | { | |
927 | buf->writeByte(' '); | |
928 | MODtoBuffer(buf, t->mod); | |
929 | } | |
930 | t->attributesApply(&pas, &PrePostAppendStrings::fp); | |
931 | ||
932 | t->inuse--; | |
933 | } | |
934 | void visitFuncIdentWithPrefix(TypeFunction *t, Identifier *ident, TemplateDeclaration *td) | |
935 | { | |
936 | if (t->inuse) | |
937 | { | |
938 | t->inuse = 2; // flag error to caller | |
939 | return; | |
940 | } | |
941 | t->inuse++; | |
942 | ||
943 | PrePostAppendStrings pas; | |
944 | pas.buf = buf; | |
945 | pas.isCtor = (ident == Id::ctor); | |
946 | pas.isPostfixStyle = false; | |
947 | ||
948 | /* Use 'storage class' (prefix) style for attributes | |
949 | */ | |
950 | if (t->mod) | |
951 | { | |
952 | MODtoBuffer(buf, t->mod); | |
953 | buf->writeByte(' '); | |
954 | } | |
955 | t->attributesApply(&pas, &PrePostAppendStrings::fp); | |
956 | ||
957 | if (t->linkage > LINKd && hgs->ddoc != 1 && !hgs->hdrgen) | |
958 | { | |
959 | linkageToBuffer(buf, t->linkage); | |
960 | buf->writeByte(' '); | |
961 | } | |
962 | ||
963 | if (ident && ident->toHChars2() != ident->toChars()) | |
964 | { | |
965 | // Don't print return type for ctor, dtor, unittest, etc | |
966 | } | |
967 | else if (t->next) | |
968 | { | |
969 | typeToBuffer(t->next, NULL); | |
970 | if (ident) | |
971 | buf->writeByte(' '); | |
972 | } | |
973 | else if (hgs->ddoc) | |
974 | buf->writestring("auto "); | |
975 | ||
976 | if (ident) | |
977 | buf->writestring(ident->toHChars2()); | |
978 | ||
979 | if (td) | |
980 | { | |
981 | buf->writeByte('('); | |
2cbc99d1 | 982 | for (size_t i = 0; i < td->origParameters->length; i++) |
b4c522fa IB |
983 | { |
984 | TemplateParameter *p = (*td->origParameters)[i]; | |
985 | if (i) | |
986 | buf->writestring(", "); | |
987 | p->accept(this); | |
988 | } | |
989 | buf->writeByte(')'); | |
990 | } | |
c3a2ba10 | 991 | parametersToBuffer(t->parameterList.parameters, t->parameterList.varargs); |
b4c522fa IB |
992 | |
993 | t->inuse--; | |
994 | } | |
995 | ||
996 | void visit(TypeDelegate *t) | |
997 | { | |
998 | visitFuncIdentWithPostfix((TypeFunction *)t->next, "delegate"); | |
999 | } | |
1000 | ||
1001 | void visitTypeQualifiedHelper(TypeQualified *t) | |
1002 | { | |
2cbc99d1 | 1003 | for (size_t i = 0; i < t->idents.length; i++) |
b4c522fa IB |
1004 | { |
1005 | RootObject *id = t->idents[i]; | |
1006 | ||
1007 | if (id->dyncast() == DYNCAST_DSYMBOL) | |
1008 | { | |
1009 | buf->writeByte('.'); | |
1010 | TemplateInstance *ti = (TemplateInstance *)id; | |
1011 | ti->accept(this); | |
1012 | } | |
1013 | else if (id->dyncast() == DYNCAST_EXPRESSION) | |
1014 | { | |
1015 | buf->writeByte('['); | |
1016 | ((Expression *)id)->accept(this); | |
1017 | buf->writeByte(']'); | |
1018 | } | |
1019 | else if (id->dyncast() == DYNCAST_TYPE) | |
1020 | { | |
1021 | buf->writeByte('['); | |
1022 | ((Type *)id)->accept(this); | |
1023 | buf->writeByte(']'); | |
1024 | } | |
1025 | else | |
1026 | { | |
1027 | buf->writeByte('.'); | |
1028 | buf->writestring(id->toChars()); | |
1029 | } | |
1030 | } | |
1031 | } | |
1032 | ||
1033 | void visit(TypeIdentifier *t) | |
1034 | { | |
1035 | buf->writestring(t->ident->toChars()); | |
1036 | visitTypeQualifiedHelper(t); | |
1037 | } | |
1038 | ||
1039 | void visit(TypeInstance *t) | |
1040 | { | |
1041 | t->tempinst->accept(this); | |
1042 | visitTypeQualifiedHelper(t); | |
1043 | } | |
1044 | ||
1045 | void visit(TypeTypeof *t) | |
1046 | { | |
1047 | buf->writestring("typeof("); | |
1048 | t->exp->accept(this); | |
1049 | buf->writeByte(')'); | |
1050 | visitTypeQualifiedHelper(t); | |
1051 | } | |
1052 | ||
1053 | void visit(TypeReturn *t) | |
1054 | { | |
1055 | buf->writestring("typeof(return)"); | |
1056 | visitTypeQualifiedHelper(t); | |
1057 | } | |
1058 | ||
1059 | void visit(TypeEnum *t) | |
1060 | { | |
1061 | buf->writestring(t->sym->toChars()); | |
1062 | } | |
1063 | ||
1064 | void visit(TypeStruct *t) | |
1065 | { | |
1066 | // Bugzilla 13776: Don't use ti->toAlias() to avoid forward reference error | |
1067 | // while printing messages. | |
1068 | TemplateInstance *ti = t->sym->parent ? t->sym->parent->isTemplateInstance() : NULL; | |
1069 | if (ti && ti->aliasdecl == t->sym) | |
1070 | buf->writestring(hgs->fullQual ? ti->toPrettyChars() : ti->toChars()); | |
1071 | else | |
1072 | buf->writestring(hgs->fullQual ? t->sym->toPrettyChars() : t->sym->toChars()); | |
1073 | } | |
1074 | ||
1075 | void visit(TypeClass *t) | |
1076 | { | |
1077 | // Bugzilla 13776: Don't use ti->toAlias() to avoid forward reference error | |
1078 | // while printing messages. | |
1079 | TemplateInstance *ti = t->sym->parent->isTemplateInstance(); | |
1080 | if (ti && ti->aliasdecl == t->sym) | |
1081 | buf->writestring(hgs->fullQual ? ti->toPrettyChars() : ti->toChars()); | |
1082 | else | |
1083 | buf->writestring(hgs->fullQual ? t->sym->toPrettyChars() : t->sym->toChars()); | |
1084 | } | |
1085 | ||
1086 | void visit(TypeTuple *t) | |
1087 | { | |
1088 | parametersToBuffer(t->arguments, 0); | |
1089 | } | |
1090 | ||
1091 | void visit(TypeSlice *t) | |
1092 | { | |
1093 | visitWithMask(t->next, t->mod); | |
1094 | ||
1095 | buf->writeByte('['); | |
1096 | sizeToBuffer(t->lwr); | |
1097 | buf->writestring(" .. "); | |
1098 | sizeToBuffer(t->upr); | |
1099 | buf->writeByte(']'); | |
1100 | } | |
1101 | ||
1102 | void visit(TypeNull *) | |
1103 | { | |
1104 | buf->writestring("typeof(null)"); | |
1105 | } | |
1106 | ||
1107 | //////////////////////////////////////////////////////////////////////////// | |
1108 | ||
1109 | void visit(Dsymbol *s) | |
1110 | { | |
1111 | buf->writestring(s->toChars()); | |
1112 | } | |
1113 | ||
1114 | void visit(StaticAssert *s) | |
1115 | { | |
1116 | buf->writestring(s->kind()); | |
1117 | buf->writeByte('('); | |
1118 | s->exp->accept(this); | |
1119 | if (s->msg) | |
1120 | { | |
1121 | buf->writestring(", "); | |
1122 | s->msg->accept(this); | |
1123 | } | |
1124 | buf->writestring(");"); | |
1125 | buf->writenl(); | |
1126 | } | |
1127 | ||
1128 | void visit(DebugSymbol *s) | |
1129 | { | |
1130 | buf->writestring("debug = "); | |
1131 | if (s->ident) | |
1132 | buf->writestring(s->ident->toChars()); | |
1133 | else | |
1134 | buf->printf("%u", s->level); | |
1135 | buf->writestring(";"); | |
1136 | buf->writenl(); | |
1137 | } | |
1138 | ||
1139 | void visit(VersionSymbol *s) | |
1140 | { | |
1141 | buf->writestring("version = "); | |
1142 | if (s->ident) | |
1143 | buf->writestring(s->ident->toChars()); | |
1144 | else | |
1145 | buf->printf("%u", s->level); | |
1146 | buf->writestring(";"); | |
1147 | buf->writenl(); | |
1148 | } | |
1149 | ||
1150 | void visit(EnumMember *em) | |
1151 | { | |
1152 | if (em->type) | |
1153 | typeToBuffer(em->type, em->ident); | |
1154 | else | |
1155 | buf->writestring(em->ident->toChars()); | |
1156 | if (em->value()) | |
1157 | { | |
1158 | buf->writestring(" = "); | |
1159 | em->value()->accept(this); | |
1160 | } | |
1161 | } | |
1162 | ||
1163 | void visit(Import *imp) | |
1164 | { | |
1165 | if (hgs->hdrgen && imp->id == Id::object) | |
1166 | return; // object is imported by default | |
1167 | ||
1168 | if (imp->isstatic) | |
1169 | buf->writestring("static "); | |
1170 | buf->writestring("import "); | |
1171 | if (imp->aliasId) | |
1172 | { | |
1173 | buf->printf("%s = ", imp->aliasId->toChars()); | |
1174 | } | |
2cbc99d1 | 1175 | if (imp->packages && imp->packages->length) |
b4c522fa | 1176 | { |
2cbc99d1 | 1177 | for (size_t i = 0; i < imp->packages->length; i++) |
b4c522fa IB |
1178 | { |
1179 | Identifier *pid = (*imp->packages)[i]; | |
1180 | buf->printf("%s.", pid->toChars()); | |
1181 | } | |
1182 | } | |
1183 | buf->printf("%s", imp->id->toChars()); | |
2cbc99d1 | 1184 | if (imp->names.length) |
b4c522fa IB |
1185 | { |
1186 | buf->writestring(" : "); | |
2cbc99d1 | 1187 | for (size_t i = 0; i < imp->names.length; i++) |
b4c522fa IB |
1188 | { |
1189 | if (i) | |
1190 | buf->writestring(", "); | |
1191 | ||
1192 | Identifier *name = imp->names[i]; | |
1193 | Identifier *alias = imp->aliases[i]; | |
1194 | if (alias) | |
1195 | buf->printf("%s = %s", alias->toChars(), name->toChars()); | |
1196 | else | |
1197 | buf->printf("%s", name->toChars()); | |
1198 | } | |
1199 | } | |
1200 | buf->printf(";"); | |
1201 | buf->writenl(); | |
1202 | } | |
1203 | ||
1204 | void visit(AliasThis *d) | |
1205 | { | |
1206 | buf->writestring("alias "); | |
1207 | buf->writestring(d->ident->toChars()); | |
1208 | buf->writestring(" this;\n"); | |
1209 | } | |
1210 | ||
1211 | void visit(AttribDeclaration *d) | |
1212 | { | |
1213 | if (!d->decl) | |
1214 | { | |
1215 | buf->writeByte(';'); | |
1216 | buf->writenl(); | |
1217 | return; | |
1218 | } | |
1219 | ||
2cbc99d1 | 1220 | if (d->decl->length == 0) |
b4c522fa | 1221 | buf->writestring("{}"); |
2cbc99d1 | 1222 | else if (hgs->hdrgen && d->decl->length == 1 && (*d->decl)[0]->isUnitTestDeclaration()) |
b4c522fa IB |
1223 | { |
1224 | // hack for bugzilla 8081 | |
1225 | buf->writestring("{}"); | |
1226 | } | |
2cbc99d1 | 1227 | else if (d->decl->length == 1) |
b4c522fa IB |
1228 | { |
1229 | ((*d->decl)[0])->accept(this); | |
1230 | return; | |
1231 | } | |
1232 | else | |
1233 | { | |
1234 | buf->writenl(); | |
1235 | buf->writeByte('{'); | |
1236 | buf->writenl(); | |
1237 | buf->level++; | |
2cbc99d1 | 1238 | for (size_t i = 0; i < d->decl->length; i++) |
b4c522fa IB |
1239 | { |
1240 | Dsymbol *de = (*d->decl)[i]; | |
1241 | de->accept(this); | |
1242 | } | |
1243 | buf->level--; | |
1244 | buf->writeByte('}'); | |
1245 | } | |
1246 | buf->writenl(); | |
1247 | } | |
1248 | ||
1249 | void visit(StorageClassDeclaration *d) | |
1250 | { | |
1251 | if (stcToBuffer(buf, d->stc)) | |
1252 | buf->writeByte(' '); | |
1253 | visit((AttribDeclaration *)d); | |
1254 | } | |
1255 | ||
1256 | void visit(DeprecatedDeclaration *d) | |
1257 | { | |
1258 | buf->writestring("deprecated("); | |
1259 | d->msg->accept(this); | |
1260 | buf->writestring(") "); | |
1261 | visit((AttribDeclaration *)d); | |
1262 | } | |
1263 | ||
1264 | void visit(LinkDeclaration *d) | |
1265 | { | |
1266 | const char *p; | |
1267 | ||
1268 | switch (d->linkage) | |
1269 | { | |
1270 | case LINKd: p = "D"; break; | |
1271 | case LINKc: p = "C"; break; | |
1272 | case LINKcpp: p = "C++"; break; | |
1273 | case LINKwindows: p = "Windows"; break; | |
b4c522fa IB |
1274 | case LINKobjc: p = "Objective-C"; break; |
1275 | default: | |
1276 | assert(0); | |
1277 | break; | |
1278 | } | |
1279 | buf->writestring("extern ("); | |
1280 | buf->writestring(p); | |
1281 | buf->writestring(") "); | |
1282 | visit((AttribDeclaration *)d); | |
1283 | } | |
1284 | ||
1285 | void visit(CPPMangleDeclaration *d) | |
1286 | { | |
1287 | const char *p; | |
1288 | ||
1289 | switch (d->cppmangle) | |
1290 | { | |
1291 | case CPPMANGLEclass: p = "class"; break; | |
1292 | case CPPMANGLEstruct: p = "struct"; break; | |
1293 | default: | |
1294 | assert(0); | |
1295 | break; | |
1296 | } | |
1297 | buf->writestring("extern (C++, "); | |
1298 | buf->writestring(p); | |
1299 | buf->writestring(") "); | |
1300 | visit((AttribDeclaration *)d); | |
1301 | } | |
1302 | ||
1303 | void visit(ProtDeclaration *d) | |
1304 | { | |
1305 | protectionToBuffer(buf, d->protection); | |
1306 | buf->writeByte(' '); | |
1307 | visit((AttribDeclaration *)d); | |
1308 | } | |
1309 | ||
1310 | void visit(AlignDeclaration *d) | |
1311 | { | |
1312 | if (!d->ealign) | |
1313 | buf->printf("align "); | |
1314 | else | |
1315 | buf->printf("align (%s)", d->ealign->toChars()); | |
1316 | visit((AttribDeclaration *)d); | |
1317 | } | |
1318 | ||
1319 | void visit(AnonDeclaration *d) | |
1320 | { | |
1321 | buf->printf(d->isunion ? "union" : "struct"); | |
1322 | buf->writenl(); | |
1323 | buf->writestring("{"); | |
1324 | buf->writenl(); | |
1325 | buf->level++; | |
1326 | if (d->decl) | |
1327 | { | |
2cbc99d1 | 1328 | for (size_t i = 0; i < d->decl->length; i++) |
b4c522fa IB |
1329 | { |
1330 | Dsymbol *de = (*d->decl)[i]; | |
1331 | de->accept(this); | |
1332 | } | |
1333 | } | |
1334 | buf->level--; | |
1335 | buf->writestring("}"); | |
1336 | buf->writenl(); | |
1337 | } | |
1338 | ||
1339 | void visit(PragmaDeclaration *d) | |
1340 | { | |
1341 | buf->printf("pragma (%s", d->ident->toChars()); | |
2cbc99d1 | 1342 | if (d->args && d->args->length) |
b4c522fa IB |
1343 | { |
1344 | buf->writestring(", "); | |
1345 | argsToBuffer(d->args); | |
1346 | } | |
1347 | buf->writeByte(')'); | |
1348 | visit((AttribDeclaration *)d); | |
1349 | } | |
1350 | ||
1351 | void visit(ConditionalDeclaration *d) | |
1352 | { | |
1353 | d->condition->accept(this); | |
1354 | if (d->decl || d->elsedecl) | |
1355 | { | |
1356 | buf->writenl(); | |
1357 | buf->writeByte('{'); | |
1358 | buf->writenl(); | |
1359 | buf->level++; | |
1360 | if (d->decl) | |
1361 | { | |
2cbc99d1 | 1362 | for (size_t i = 0; i < d->decl->length; i++) |
b4c522fa IB |
1363 | { |
1364 | Dsymbol *de = (*d->decl)[i]; | |
1365 | de->accept(this); | |
1366 | } | |
1367 | } | |
1368 | buf->level--; | |
1369 | buf->writeByte('}'); | |
1370 | if (d->elsedecl) | |
1371 | { | |
1372 | buf->writenl(); | |
1373 | buf->writestring("else"); | |
1374 | buf->writenl(); | |
1375 | buf->writeByte('{'); | |
1376 | buf->writenl(); | |
1377 | buf->level++; | |
2cbc99d1 | 1378 | for (size_t i = 0; i < d->elsedecl->length; i++) |
b4c522fa IB |
1379 | { |
1380 | Dsymbol *de = (*d->elsedecl)[i]; | |
1381 | de->accept(this); | |
1382 | } | |
1383 | buf->level--; | |
1384 | buf->writeByte('}'); | |
1385 | } | |
1386 | } | |
1387 | else | |
1388 | buf->writeByte(':'); | |
1389 | buf->writenl(); | |
1390 | } | |
1391 | ||
5b74dd0a IB |
1392 | void visit(ForwardingStatement *s) |
1393 | { | |
1394 | s->statement->accept(this); | |
1395 | } | |
1396 | ||
1397 | void visit(StaticForeachDeclaration *s) | |
1398 | { | |
1399 | buf->writestring("static "); | |
1400 | if (s->sfe->aggrfe) | |
1401 | { | |
1402 | foreachWithoutBody(s->sfe->aggrfe); | |
1403 | } | |
1404 | else | |
1405 | { | |
1406 | assert(s->sfe->rangefe); | |
1407 | foreachRangeWithoutBody(s->sfe->rangefe); | |
1408 | } | |
1409 | buf->writeByte('{'); | |
1410 | buf->writenl(); | |
1411 | buf->level++; | |
1412 | visit((AttribDeclaration *)s); | |
1413 | buf->level--; | |
1414 | buf->writeByte('}'); | |
1415 | buf->writenl(); | |
1416 | } | |
1417 | ||
b4c522fa IB |
1418 | void visit(CompileDeclaration *d) |
1419 | { | |
1420 | buf->writestring("mixin("); | |
1421 | d->exp->accept(this); | |
1422 | buf->writestring(");"); | |
1423 | buf->writenl(); | |
1424 | } | |
1425 | ||
1426 | void visit(UserAttributeDeclaration *d) | |
1427 | { | |
1428 | buf->writestring("@("); | |
1429 | argsToBuffer(d->atts); | |
1430 | buf->writeByte(')'); | |
1431 | visit((AttribDeclaration *)d); | |
1432 | } | |
1433 | ||
1434 | void visit(TemplateDeclaration *d) | |
1435 | { | |
1436 | if ((hgs->hdrgen || hgs->fullDump) && visitEponymousMember(d)) | |
1437 | return; | |
1438 | ||
1439 | if (hgs->ddoc) | |
1440 | buf->writestring(d->kind()); | |
1441 | else | |
1442 | buf->writestring("template"); | |
1443 | buf->writeByte(' '); | |
1444 | buf->writestring(d->ident->toChars()); | |
1445 | buf->writeByte('('); | |
1446 | visitTemplateParameters(hgs->ddoc ? d->origParameters : d->parameters); | |
1447 | buf->writeByte(')'); | |
1448 | visitTemplateConstraint(d->constraint); | |
1449 | ||
1450 | if (hgs->hdrgen || hgs->fullDump) | |
1451 | { | |
1452 | hgs->tpltMember++; | |
1453 | buf->writenl(); | |
1454 | buf->writeByte('{'); | |
1455 | buf->writenl(); | |
1456 | buf->level++; | |
2cbc99d1 | 1457 | for (size_t i = 0; i < d->members->length; i++) |
b4c522fa IB |
1458 | { |
1459 | Dsymbol *s = (*d->members)[i]; | |
1460 | s->accept(this); | |
1461 | } | |
1462 | buf->level--; | |
1463 | buf->writeByte('}'); | |
1464 | buf->writenl(); | |
1465 | hgs->tpltMember--; | |
1466 | } | |
1467 | } | |
1468 | ||
1469 | bool visitEponymousMember(TemplateDeclaration *d) | |
1470 | { | |
2cbc99d1 | 1471 | if (!d->members || d->members->length != 1) |
b4c522fa IB |
1472 | return false; |
1473 | ||
1474 | Dsymbol *onemember = (*d->members)[0]; | |
1475 | if (onemember->ident != d->ident) | |
1476 | return false; | |
1477 | ||
1478 | if (FuncDeclaration *fd = onemember->isFuncDeclaration()) | |
1479 | { | |
1480 | assert(fd->type); | |
1481 | if (stcToBuffer(buf, fd->storage_class)) | |
1482 | buf->writeByte(' '); | |
1483 | functionToBufferFull((TypeFunction *)fd->type, buf, d->ident, hgs, d); | |
1484 | visitTemplateConstraint(d->constraint); | |
1485 | ||
1486 | hgs->tpltMember++; | |
1487 | bodyToBuffer(fd); | |
1488 | hgs->tpltMember--; | |
1489 | return true; | |
1490 | } | |
1491 | if (AggregateDeclaration *ad = onemember->isAggregateDeclaration()) | |
1492 | { | |
1493 | buf->writestring(ad->kind()); | |
1494 | buf->writeByte(' '); | |
1495 | buf->writestring(ad->ident->toChars()); | |
1496 | buf->writeByte('('); | |
1497 | visitTemplateParameters(hgs->ddoc ? d->origParameters : d->parameters); | |
1498 | buf->writeByte(')'); | |
1499 | visitTemplateConstraint(d->constraint); | |
1500 | visitBaseClasses(ad->isClassDeclaration()); | |
1501 | ||
1502 | hgs->tpltMember++; | |
1503 | if (ad->members) | |
1504 | { | |
1505 | buf->writenl(); | |
1506 | buf->writeByte('{'); | |
1507 | buf->writenl(); | |
1508 | buf->level++; | |
2cbc99d1 | 1509 | for (size_t i = 0; i < ad->members->length; i++) |
b4c522fa IB |
1510 | { |
1511 | Dsymbol *s = (*ad->members)[i]; | |
1512 | s->accept(this); | |
1513 | } | |
1514 | buf->level--; | |
1515 | buf->writeByte('}'); | |
1516 | } | |
1517 | else | |
1518 | buf->writeByte(';'); | |
1519 | buf->writenl(); | |
1520 | hgs->tpltMember--; | |
1521 | return true; | |
1522 | } | |
1523 | if (VarDeclaration *vd = onemember->isVarDeclaration()) | |
1524 | { | |
1525 | if (d->constraint) | |
1526 | return false; | |
1527 | ||
1528 | if (stcToBuffer(buf, vd->storage_class)) | |
1529 | buf->writeByte(' '); | |
1530 | if (vd->type) | |
1531 | typeToBuffer(vd->type, vd->ident); | |
1532 | else | |
1533 | buf->writestring(vd->ident->toChars()); | |
1534 | ||
1535 | buf->writeByte('('); | |
1536 | visitTemplateParameters(hgs->ddoc ? d->origParameters : d->parameters); | |
1537 | buf->writeByte(')'); | |
1538 | ||
1539 | if (vd->_init) | |
1540 | { | |
1541 | buf->writestring(" = "); | |
1542 | ExpInitializer *ie = vd->_init->isExpInitializer(); | |
1543 | if (ie && (ie->exp->op == TOKconstruct || ie->exp->op == TOKblit)) | |
1544 | ((AssignExp *)ie->exp)->e2->accept(this); | |
1545 | else | |
1546 | vd->_init->accept(this); | |
1547 | } | |
1548 | buf->writeByte(';'); | |
1549 | buf->writenl(); | |
1550 | return true; | |
1551 | } | |
1552 | ||
1553 | return false; | |
1554 | } | |
1555 | void visitTemplateParameters(TemplateParameters *parameters) | |
1556 | { | |
2cbc99d1 | 1557 | if (!parameters || !parameters->length) |
b4c522fa | 1558 | return; |
2cbc99d1 | 1559 | for (size_t i = 0; i < parameters->length; i++) |
b4c522fa IB |
1560 | { |
1561 | TemplateParameter *p = (*parameters)[i]; | |
1562 | if (i) | |
1563 | buf->writestring(", "); | |
1564 | p->accept(this); | |
1565 | } | |
1566 | } | |
1567 | void visitTemplateConstraint(Expression *constraint) | |
1568 | { | |
1569 | if (!constraint) | |
1570 | return; | |
1571 | buf->writestring(" if ("); | |
1572 | constraint->accept(this); | |
1573 | buf->writeByte(')'); | |
1574 | } | |
1575 | ||
1576 | void visit(TemplateInstance *ti) | |
1577 | { | |
1578 | buf->writestring(ti->name->toChars()); | |
1579 | tiargsToBuffer(ti); | |
1580 | ||
1581 | if (hgs->fullDump) | |
1582 | { | |
1583 | buf->writenl(); | |
1584 | if (ti->aliasdecl) | |
1585 | { | |
1586 | // the ti.aliasDecl is the instantiated body | |
1587 | // if we have it, print it. | |
1588 | ti->aliasdecl->accept(this); | |
1589 | } | |
1590 | } | |
1591 | } | |
1592 | ||
1593 | void visit(TemplateMixin *tm) | |
1594 | { | |
1595 | buf->writestring("mixin "); | |
1596 | ||
1597 | typeToBuffer(tm->tqual, NULL); | |
1598 | tiargsToBuffer(tm); | |
1599 | ||
1600 | if (tm->ident && memcmp(tm->ident->toChars(), "__mixin", 7) != 0) | |
1601 | { | |
1602 | buf->writeByte(' '); | |
1603 | buf->writestring(tm->ident->toChars()); | |
1604 | } | |
1605 | buf->writeByte(';'); | |
1606 | buf->writenl(); | |
1607 | } | |
1608 | ||
1609 | void tiargsToBuffer(TemplateInstance *ti) | |
1610 | { | |
1611 | buf->writeByte('!'); | |
1612 | if (ti->nest) | |
1613 | { | |
1614 | buf->writestring("(...)"); | |
1615 | return; | |
1616 | } | |
1617 | if (!ti->tiargs) | |
1618 | { | |
1619 | buf->writestring("()"); | |
1620 | return; | |
1621 | } | |
1622 | ||
2cbc99d1 | 1623 | if (ti->tiargs->length == 1) |
b4c522fa IB |
1624 | { |
1625 | RootObject *oarg = (*ti->tiargs)[0]; | |
1626 | if (Type *t = isType(oarg)) | |
1627 | { | |
1628 | if (t->equals(Type::tstring) || | |
1629 | t->equals(Type::twstring) || | |
1630 | t->equals(Type::tdstring) || | |
1631 | (t->mod == 0 && | |
1632 | (t->isTypeBasic() || | |
2cbc99d1 | 1633 | (t->ty == Tident && ((TypeIdentifier *)t)->idents.length == 0)))) |
b4c522fa IB |
1634 | { |
1635 | buf->writestring(t->toChars()); | |
1636 | return; | |
1637 | } | |
1638 | } | |
1639 | else if (Expression *e = isExpression(oarg)) | |
1640 | { | |
1641 | if (e->op == TOKint64 || | |
1642 | e->op == TOKfloat64 || | |
1643 | e->op == TOKnull || | |
1644 | e->op == TOKstring || | |
1645 | e->op == TOKthis) | |
1646 | { | |
1647 | buf->writestring(e->toChars()); | |
1648 | return; | |
1649 | } | |
1650 | } | |
1651 | } | |
1652 | buf->writeByte('('); | |
1653 | ti->nest++; | |
2cbc99d1 | 1654 | for (size_t i = 0; i < ti->tiargs->length; i++) |
b4c522fa IB |
1655 | { |
1656 | RootObject *arg = (*ti->tiargs)[i]; | |
1657 | if (i) | |
1658 | buf->writestring(", "); | |
1659 | objectToBuffer(arg); | |
1660 | } | |
1661 | ti->nest--; | |
1662 | buf->writeByte(')'); | |
1663 | } | |
1664 | ||
1665 | /**************************************** | |
1666 | * This makes a 'pretty' version of the template arguments. | |
1667 | * It's analogous to genIdent() which makes a mangled version. | |
1668 | */ | |
1669 | void objectToBuffer(RootObject *oarg) | |
1670 | { | |
1671 | //printf("objectToBuffer()\n"); | |
1672 | ||
1673 | /* The logic of this should match what genIdent() does. The _dynamic_cast() | |
1674 | * function relies on all the pretty strings to be unique for different classes | |
1675 | * (see Bugzilla 7375). | |
1676 | * Perhaps it would be better to demangle what genIdent() does. | |
1677 | */ | |
1678 | if (Type *t = isType(oarg)) | |
1679 | { | |
1680 | //printf("\tt: %s ty = %d\n", t->toChars(), t->ty); | |
1681 | typeToBuffer(t, NULL); | |
1682 | } | |
1683 | else if (Expression *e = isExpression(oarg)) | |
1684 | { | |
1685 | if (e->op == TOKvar) | |
1686 | e = e->optimize(WANTvalue); // added to fix Bugzilla 7375 | |
1687 | e->accept(this); | |
1688 | } | |
1689 | else if (Dsymbol *s = isDsymbol(oarg)) | |
1690 | { | |
1691 | const char *p = s->ident ? s->ident->toChars() : s->toChars(); | |
1692 | buf->writestring(p); | |
1693 | } | |
1694 | else if (Tuple *v = isTuple(oarg)) | |
1695 | { | |
1696 | Objects *args = &v->objects; | |
2cbc99d1 | 1697 | for (size_t i = 0; i < args->length; i++) |
b4c522fa IB |
1698 | { |
1699 | RootObject *arg = (*args)[i]; | |
1700 | if (i) | |
1701 | buf->writestring(", "); | |
1702 | objectToBuffer(arg); | |
1703 | } | |
1704 | } | |
1705 | else if (!oarg) | |
1706 | { | |
1707 | buf->writestring("NULL"); | |
1708 | } | |
1709 | else | |
1710 | { | |
1711 | assert(0); | |
1712 | } | |
1713 | } | |
1714 | ||
1715 | void visit(EnumDeclaration *d) | |
1716 | { | |
1717 | EnumDeclaration *oldInEnumDecl = inEnumDecl; | |
1718 | inEnumDecl = d; | |
1719 | buf->writestring("enum "); | |
1720 | if (d->ident) | |
1721 | { | |
1722 | buf->writestring(d->ident->toChars()); | |
1723 | buf->writeByte(' '); | |
1724 | } | |
1725 | if (d->memtype) | |
1726 | { | |
1727 | buf->writestring(": "); | |
1728 | typeToBuffer(d->memtype, NULL); | |
1729 | } | |
1730 | if (!d->members) | |
1731 | { | |
1732 | buf->writeByte(';'); | |
1733 | buf->writenl(); | |
1734 | inEnumDecl = oldInEnumDecl; | |
1735 | return; | |
1736 | } | |
1737 | buf->writenl(); | |
1738 | buf->writeByte('{'); | |
1739 | buf->writenl(); | |
1740 | buf->level++; | |
2cbc99d1 | 1741 | for (size_t i = 0; i < d->members->length; i++) |
b4c522fa IB |
1742 | { |
1743 | EnumMember *em = (*d->members)[i]->isEnumMember(); | |
1744 | if (!em) | |
1745 | continue; | |
1746 | em->accept(this); | |
1747 | buf->writeByte(','); | |
1748 | buf->writenl(); | |
1749 | } | |
1750 | buf->level--; | |
1751 | buf->writeByte('}'); | |
1752 | buf->writenl(); | |
1753 | inEnumDecl = oldInEnumDecl; | |
1754 | } | |
1755 | ||
1756 | void visit(Nspace *d) | |
1757 | { | |
1758 | buf->writestring("extern (C++, "); | |
1759 | buf->writestring(d->ident->toChars()); | |
1760 | buf->writeByte(')'); | |
1761 | buf->writenl(); | |
1762 | buf->writeByte('{'); | |
1763 | buf->writenl(); | |
1764 | buf->level++; | |
2cbc99d1 | 1765 | for (size_t i = 0; i < d->members->length; i++) |
b4c522fa IB |
1766 | { |
1767 | Dsymbol *s = (*d->members)[i]; | |
1768 | s->accept(this); | |
1769 | } | |
1770 | buf->level--; | |
1771 | buf->writeByte('}'); | |
1772 | buf->writenl(); | |
1773 | } | |
1774 | ||
1775 | void visit(StructDeclaration *d) | |
1776 | { | |
1777 | buf->printf("%s ", d->kind()); | |
1778 | if (!d->isAnonymous()) | |
1779 | buf->writestring(d->toChars()); | |
1780 | if (!d->members) | |
1781 | { | |
1782 | buf->writeByte(';'); | |
1783 | buf->writenl(); | |
1784 | return; | |
1785 | } | |
1786 | buf->writenl(); | |
1787 | buf->writeByte('{'); | |
1788 | buf->writenl(); | |
1789 | buf->level++; | |
2cbc99d1 | 1790 | for (size_t i = 0; i < d->members->length; i++) |
b4c522fa IB |
1791 | { |
1792 | Dsymbol *s = (*d->members)[i]; | |
1793 | s->accept(this); | |
1794 | } | |
1795 | buf->level--; | |
1796 | buf->writeByte('}'); | |
1797 | buf->writenl(); | |
1798 | } | |
1799 | ||
1800 | void visit(ClassDeclaration *d) | |
1801 | { | |
1802 | if (!d->isAnonymous()) | |
1803 | { | |
1804 | buf->writestring(d->kind()); | |
1805 | buf->writeByte(' '); | |
1806 | buf->writestring(d->ident->toChars()); | |
1807 | } | |
1808 | visitBaseClasses(d); | |
1809 | if (d->members) | |
1810 | { | |
1811 | buf->writenl(); | |
1812 | buf->writeByte('{'); | |
1813 | buf->writenl(); | |
1814 | buf->level++; | |
2cbc99d1 | 1815 | for (size_t i = 0; i < d->members->length; i++) |
b4c522fa IB |
1816 | { |
1817 | Dsymbol *s = (*d->members)[i]; | |
1818 | s->accept(this); | |
1819 | } | |
1820 | buf->level--; | |
1821 | buf->writeByte('}'); | |
1822 | } | |
1823 | else | |
1824 | buf->writeByte(';'); | |
1825 | buf->writenl(); | |
1826 | } | |
1827 | ||
1828 | void visitBaseClasses(ClassDeclaration *d) | |
1829 | { | |
2cbc99d1 | 1830 | if (!d || !d->baseclasses->length) |
b4c522fa IB |
1831 | return; |
1832 | ||
1833 | buf->writestring(" : "); | |
2cbc99d1 | 1834 | for (size_t i = 0; i < d->baseclasses->length; i++) |
b4c522fa IB |
1835 | { |
1836 | if (i) | |
1837 | buf->writestring(", "); | |
1838 | BaseClass *b = (*d->baseclasses)[i]; | |
1839 | typeToBuffer(b->type, NULL); | |
1840 | } | |
1841 | } | |
1842 | ||
1843 | void visit(AliasDeclaration *d) | |
1844 | { | |
5b74dd0a IB |
1845 | if (d->storage_class & STClocal) |
1846 | return; | |
b4c522fa IB |
1847 | buf->writestring("alias "); |
1848 | if (d->aliassym) | |
1849 | { | |
1850 | buf->writestring(d->ident->toChars()); | |
1851 | buf->writestring(" = "); | |
1852 | if (stcToBuffer(buf, d->storage_class)) | |
1853 | buf->writeByte(' '); | |
1854 | d->aliassym->accept(this); | |
1855 | } | |
1856 | else if (d->type->ty == Tfunction) | |
1857 | { | |
1858 | if (stcToBuffer(buf, d->storage_class)) | |
1859 | buf->writeByte(' '); | |
1860 | typeToBuffer(d->type, d->ident); | |
1861 | } | |
1862 | else | |
1863 | { | |
1864 | declstring = (d->ident == Id::string || d->ident == Id::wstring || d->ident == Id::dstring); | |
1865 | buf->writestring(d->ident->toChars()); | |
1866 | buf->writestring(" = "); | |
1867 | if (stcToBuffer(buf, d->storage_class)) | |
1868 | buf->writeByte(' '); | |
1869 | typeToBuffer(d->type, NULL); | |
1870 | declstring = false; | |
1871 | } | |
1872 | buf->writeByte(';'); | |
1873 | buf->writenl(); | |
1874 | } | |
1875 | ||
1876 | void visit(VarDeclaration *d) | |
1877 | { | |
5b74dd0a IB |
1878 | if (d->storage_class & STClocal) |
1879 | return; | |
b4c522fa IB |
1880 | visitVarDecl(d, false); |
1881 | buf->writeByte(';'); | |
1882 | buf->writenl(); | |
1883 | } | |
1884 | void visitVarDecl(VarDeclaration *v, bool anywritten) | |
1885 | { | |
1886 | if (anywritten) | |
1887 | { | |
1888 | buf->writestring(", "); | |
1889 | buf->writestring(v->ident->toChars()); | |
1890 | } | |
1891 | else | |
1892 | { | |
1893 | if (stcToBuffer(buf, v->storage_class)) | |
1894 | buf->writeByte(' '); | |
1895 | if (v->type) | |
1896 | typeToBuffer(v->type, v->ident); | |
1897 | else | |
1898 | buf->writestring(v->ident->toChars()); | |
1899 | } | |
1900 | if (v->_init) | |
1901 | { | |
1902 | buf->writestring(" = "); | |
1903 | ExpInitializer *ie = v->_init->isExpInitializer(); | |
1904 | if (ie && (ie->exp->op == TOKconstruct || ie->exp->op == TOKblit)) | |
1905 | ((AssignExp *)ie->exp)->e2->accept(this); | |
1906 | else | |
1907 | v->_init->accept(this); | |
1908 | } | |
1909 | } | |
1910 | ||
1911 | void visit(FuncDeclaration *f) | |
1912 | { | |
1913 | //printf("FuncDeclaration::toCBuffer() '%s'\n", f->toChars()); | |
1914 | ||
1915 | if (stcToBuffer(buf, f->storage_class)) | |
1916 | buf->writeByte(' '); | |
1917 | TypeFunction *tf = (TypeFunction *)f->type; | |
1918 | typeToBuffer(tf, f->ident); | |
1919 | if (hgs->hdrgen) | |
1920 | { | |
1921 | // if the return type is missing (e.g. ref functions or auto) | |
1922 | if (!tf->next || f->storage_class & STCauto) | |
1923 | { | |
1924 | hgs->autoMember++; | |
1925 | bodyToBuffer(f); | |
1926 | hgs->autoMember--; | |
1927 | } | |
1928 | else if (hgs->tpltMember == 0 && global.params.hdrStripPlainFunctions) | |
1929 | { | |
1930 | buf->writeByte(';'); | |
1931 | buf->writenl(); | |
1932 | } | |
1933 | else | |
1934 | bodyToBuffer(f); | |
1935 | } | |
1936 | else | |
1937 | bodyToBuffer(f); | |
1938 | } | |
1939 | ||
1940 | void bodyToBuffer(FuncDeclaration *f) | |
1941 | { | |
1942 | if (!f->fbody || (hgs->hdrgen && global.params.hdrStripPlainFunctions && !hgs->autoMember && !hgs->tpltMember)) | |
1943 | { | |
1944 | buf->writeByte(';'); | |
1945 | buf->writenl(); | |
1946 | return; | |
1947 | } | |
1948 | ||
1949 | int savetlpt = hgs->tpltMember; | |
1950 | int saveauto = hgs->autoMember; | |
1951 | hgs->tpltMember = 0; | |
1952 | hgs->autoMember = 0; | |
b4c522fa | 1953 | buf->writenl(); |
acae7b21 | 1954 | bool requireDo = false; |
b4c522fa | 1955 | // in{} |
acae7b21 | 1956 | if (f->frequires) |
b4c522fa | 1957 | { |
acae7b21 IB |
1958 | for (size_t i = 0; i < f->frequires->length; i++) |
1959 | { | |
1960 | Statement *frequire = (*f->frequires)[i]; | |
1961 | buf->writestring("in"); | |
1962 | if (ExpStatement *es = frequire->isExpStatement()) | |
1963 | { | |
1964 | assert(es->exp && es->exp->op == TOKassert); | |
1965 | buf->writestring(" ("); | |
1966 | ((AssertExp *)es->exp)->e1->accept(this); | |
1967 | buf->writeByte(')'); | |
1968 | buf->writenl(); | |
1969 | requireDo = false; | |
1970 | } | |
1971 | else | |
1972 | { | |
1973 | buf->writenl(); | |
1974 | frequire->accept(this); | |
1975 | requireDo = true; | |
1976 | } | |
1977 | } | |
b4c522fa IB |
1978 | } |
1979 | ||
1980 | // out{} | |
acae7b21 | 1981 | if (f->fensures) |
b4c522fa | 1982 | { |
acae7b21 | 1983 | for (size_t i = 0; i < f->fensures->length; i++) |
b4c522fa | 1984 | { |
acae7b21 IB |
1985 | Ensure fensure = (*f->fensures)[i]; |
1986 | buf->writestring("out"); | |
1987 | if (ExpStatement *es = fensure.ensure->isExpStatement()) | |
1988 | { | |
1989 | assert(es->exp && es->exp->op == TOKassert); | |
1990 | buf->writestring(" ("); | |
1991 | if (fensure.id) | |
1992 | { | |
1993 | buf->writestring(fensure.id->toChars()); | |
1994 | } | |
1995 | buf->writestring("; "); | |
1996 | ((AssertExp *)es->exp)->e1->accept(this); | |
1997 | buf->writeByte(')'); | |
1998 | buf->writenl(); | |
1999 | requireDo = false; | |
2000 | } | |
2001 | else | |
2002 | { | |
2003 | if (fensure.id) | |
2004 | { | |
2005 | buf->writeByte('('); | |
2006 | buf->writestring(fensure.id->toChars()); | |
2007 | buf->writeByte(')'); | |
2008 | } | |
2009 | buf->writenl(); | |
2010 | fensure.ensure->accept(this); | |
2011 | requireDo = true; | |
2012 | } | |
b4c522fa | 2013 | } |
b4c522fa IB |
2014 | } |
2015 | ||
acae7b21 | 2016 | if (requireDo) |
b4c522fa IB |
2017 | { |
2018 | buf->writestring("body"); | |
2019 | buf->writenl(); | |
2020 | } | |
2021 | ||
2022 | buf->writeByte('{'); | |
2023 | buf->writenl(); | |
2024 | buf->level++; | |
2025 | f->fbody->accept(this); | |
2026 | buf->level--; | |
2027 | buf->writeByte('}'); | |
2028 | buf->writenl(); | |
2029 | ||
2030 | hgs->tpltMember = savetlpt; | |
2031 | hgs->autoMember = saveauto; | |
2032 | } | |
2033 | ||
2034 | void visit(FuncLiteralDeclaration *f) | |
2035 | { | |
2036 | if (f->type->ty == Terror) | |
2037 | { | |
2038 | buf->writestring("__error"); | |
2039 | return; | |
2040 | } | |
2041 | ||
2042 | if (f->tok != TOKreserved) | |
2043 | { | |
2044 | buf->writestring(f->kind()); | |
2045 | buf->writeByte(' '); | |
2046 | } | |
2047 | ||
2048 | TypeFunction *tf = (TypeFunction *)f->type; | |
2049 | // Don't print tf->mod, tf->trust, and tf->linkage | |
2050 | if (!f->inferRetType && tf->next) | |
2051 | typeToBuffer(tf->next, NULL); | |
c3a2ba10 | 2052 | parametersToBuffer(tf->parameterList.parameters, tf->parameterList.varargs); |
b4c522fa IB |
2053 | |
2054 | CompoundStatement *cs = f->fbody->isCompoundStatement(); | |
2055 | Statement *s1; | |
2056 | if (f->semanticRun >= PASSsemantic3done && cs) | |
2057 | { | |
2cbc99d1 | 2058 | s1 = (*cs->statements)[cs->statements->length - 1]; |
b4c522fa IB |
2059 | } |
2060 | else | |
2061 | s1 = !cs ? f->fbody : NULL; | |
2062 | ReturnStatement *rs = s1 ? s1->isReturnStatement() : NULL; | |
2063 | if (rs && rs->exp) | |
2064 | { | |
2065 | buf->writestring(" => "); | |
2066 | rs->exp->accept(this); | |
2067 | } | |
2068 | else | |
2069 | { | |
2070 | hgs->tpltMember++; | |
2071 | bodyToBuffer(f); | |
2072 | hgs->tpltMember--; | |
2073 | } | |
2074 | } | |
2075 | ||
2076 | void visit(PostBlitDeclaration *d) | |
2077 | { | |
2078 | if (stcToBuffer(buf, d->storage_class)) | |
2079 | buf->writeByte(' '); | |
2080 | buf->writestring("this(this)"); | |
2081 | bodyToBuffer(d); | |
2082 | } | |
2083 | ||
2084 | void visit(DtorDeclaration *d) | |
2085 | { | |
2086 | if (d->storage_class & STCtrusted) | |
2087 | buf->writestring("@trusted "); | |
2088 | if (d->storage_class & STCsafe) | |
2089 | buf->writestring("@safe "); | |
2090 | if (d->storage_class & STCnogc) | |
2091 | buf->writestring("@nogc "); | |
2092 | if (d->storage_class & STCdisable) | |
2093 | buf->writestring("@disable "); | |
2094 | ||
2095 | buf->writestring("~this()"); | |
2096 | bodyToBuffer(d); | |
2097 | } | |
2098 | ||
2099 | void visit(StaticCtorDeclaration *d) | |
2100 | { | |
2101 | if (stcToBuffer(buf, d->storage_class & ~STCstatic)) | |
2102 | buf->writeByte(' '); | |
2103 | if (d->isSharedStaticCtorDeclaration()) | |
2104 | buf->writestring("shared "); | |
2105 | buf->writestring("static this()"); | |
2106 | if (hgs->hdrgen && !hgs->tpltMember) | |
2107 | { | |
2108 | buf->writeByte(';'); | |
2109 | buf->writenl(); | |
2110 | } | |
2111 | else | |
2112 | bodyToBuffer(d); | |
2113 | } | |
2114 | ||
2115 | void visit(StaticDtorDeclaration *d) | |
2116 | { | |
2117 | if (hgs->hdrgen) | |
2118 | return; | |
2119 | if (stcToBuffer(buf, d->storage_class & ~STCstatic)) | |
2120 | buf->writeByte(' '); | |
2121 | if (d->isSharedStaticDtorDeclaration()) | |
2122 | buf->writestring("shared "); | |
2123 | buf->writestring("static ~this()"); | |
2124 | bodyToBuffer(d); | |
2125 | } | |
2126 | ||
2127 | void visit(InvariantDeclaration *d) | |
2128 | { | |
2129 | if (hgs->hdrgen) | |
2130 | return; | |
2131 | if (stcToBuffer(buf, d->storage_class)) | |
2132 | buf->writeByte(' '); | |
2133 | buf->writestring("invariant"); | |
acae7b21 IB |
2134 | if (ExpStatement *es = d->fbody->isExpStatement()) |
2135 | { | |
2136 | assert(es->exp && es->exp->op == TOKassert); | |
2137 | buf->writestring(" ("); | |
2138 | ((AssertExp *)es->exp)->e1->accept(this); | |
2139 | buf->writestring(");"); | |
2140 | buf->writenl(); | |
2141 | } | |
2142 | else | |
2143 | { | |
2144 | bodyToBuffer(d); | |
2145 | } | |
b4c522fa IB |
2146 | } |
2147 | ||
2148 | void visit(UnitTestDeclaration *d) | |
2149 | { | |
2150 | if (hgs->hdrgen) | |
2151 | return; | |
2152 | if (stcToBuffer(buf, d->storage_class)) | |
2153 | buf->writeByte(' '); | |
2154 | buf->writestring("unittest"); | |
2155 | bodyToBuffer(d); | |
2156 | } | |
2157 | ||
2158 | void visit(NewDeclaration *d) | |
2159 | { | |
2160 | if (stcToBuffer(buf, d->storage_class & ~STCstatic)) | |
2161 | buf->writeByte(' '); | |
2162 | buf->writestring("new"); | |
2163 | parametersToBuffer(d->parameters, d->varargs); | |
2164 | bodyToBuffer(d); | |
2165 | } | |
2166 | ||
2167 | void visit(DeleteDeclaration *d) | |
2168 | { | |
2169 | if (stcToBuffer(buf, d->storage_class & ~STCstatic)) | |
2170 | buf->writeByte(' '); | |
2171 | buf->writestring("delete"); | |
2172 | parametersToBuffer(d->parameters, 0); | |
2173 | bodyToBuffer(d); | |
2174 | } | |
2175 | ||
2176 | //////////////////////////////////////////////////////////////////////////// | |
2177 | ||
2178 | void visit(ErrorInitializer *) | |
2179 | { | |
2180 | buf->writestring("__error__"); | |
2181 | } | |
2182 | ||
2183 | void visit(VoidInitializer *) | |
2184 | { | |
2185 | buf->writestring("void"); | |
2186 | } | |
2187 | ||
2188 | void visit(StructInitializer *si) | |
2189 | { | |
2190 | //printf("StructInitializer::toCBuffer()\n"); | |
2191 | buf->writeByte('{'); | |
2cbc99d1 | 2192 | for (size_t i = 0; i < si->field.length; i++) |
b4c522fa IB |
2193 | { |
2194 | if (i) | |
2195 | buf->writestring(", "); | |
2196 | if (Identifier *id = si->field[i]) | |
2197 | { | |
2198 | buf->writestring(id->toChars()); | |
2199 | buf->writeByte(':'); | |
2200 | } | |
2201 | if (Initializer *iz = si->value[i]) | |
2202 | iz->accept(this); | |
2203 | } | |
2204 | buf->writeByte('}'); | |
2205 | } | |
2206 | ||
2207 | void visit(ArrayInitializer *ai) | |
2208 | { | |
2209 | buf->writeByte('['); | |
2cbc99d1 | 2210 | for (size_t i = 0; i < ai->index.length; i++) |
b4c522fa IB |
2211 | { |
2212 | if (i) | |
2213 | buf->writestring(", "); | |
2214 | if (Expression *ex = ai->index[i]) | |
2215 | { | |
2216 | ex->accept(this); | |
2217 | buf->writeByte(':'); | |
2218 | } | |
2219 | if (Initializer *iz = ai->value[i]) | |
2220 | iz->accept(this); | |
2221 | } | |
2222 | buf->writeByte(']'); | |
2223 | } | |
2224 | ||
2225 | void visit(ExpInitializer *ei) | |
2226 | { | |
2227 | ei->exp->accept(this); | |
2228 | } | |
2229 | ||
2230 | //////////////////////////////////////////////////////////////////////////// | |
2231 | ||
2232 | /************************************************** | |
2233 | * Write out argument list to buf. | |
2234 | */ | |
2235 | void argsToBuffer(Expressions *expressions, Expression *basis = NULL) | |
2236 | { | |
2cbc99d1 | 2237 | if (!expressions || !expressions->length) |
b4c522fa IB |
2238 | return; |
2239 | ||
2cbc99d1 | 2240 | for (size_t i = 0; i < expressions->length; i++) |
b4c522fa IB |
2241 | { |
2242 | Expression *el = (*expressions)[i]; | |
2243 | if (i) | |
2244 | buf->writestring(", "); | |
2245 | if (!el) | |
2246 | el = basis; | |
2247 | if (el) | |
2248 | expToBuffer(el, PREC_assign); | |
2249 | } | |
2250 | } | |
2251 | ||
2252 | void sizeToBuffer(Expression *e) | |
2253 | { | |
2254 | if (e->type == Type::tsize_t) | |
2255 | { | |
2256 | Expression *ex = (e->op == TOKcast ? ((CastExp *)e)->e1 : e); | |
2257 | ex = ex->optimize(WANTvalue); | |
2258 | ||
2259 | dinteger_t uval = ex->op == TOKint64 ? ex->toInteger() : (dinteger_t)-1; | |
2260 | if ((sinteger_t)uval >= 0) | |
2261 | { | |
2262 | dinteger_t sizemax; | |
5905cbdb | 2263 | if (target.ptrsize == 8) |
b4c522fa | 2264 | sizemax = 0xFFFFFFFFFFFFFFFFULL; |
5905cbdb | 2265 | else if (target.ptrsize == 4) |
de83a4c1 | 2266 | sizemax = 0xFFFFFFFFUL; |
5905cbdb | 2267 | else if (target.ptrsize == 2) |
de83a4c1 | 2268 | sizemax = 0xFFFFUL; |
b4c522fa IB |
2269 | else |
2270 | assert(0); | |
2271 | if (uval <= sizemax && uval <= 0x7FFFFFFFFFFFFFFFULL) | |
2272 | { | |
2273 | buf->printf("%llu", uval); | |
2274 | return; | |
2275 | } | |
2276 | } | |
2277 | } | |
2278 | expToBuffer(e, PREC_assign); | |
2279 | } | |
2280 | ||
2281 | /************************************************** | |
2282 | * Write expression out to buf, but wrap it | |
2283 | * in ( ) if its precedence is less than pr. | |
2284 | */ | |
2285 | void expToBuffer(Expression *e, PREC pr) | |
2286 | { | |
2287 | assert(precedence[e->op] != PREC_zero); | |
2288 | assert(pr != PREC_zero); | |
2289 | ||
2290 | //if (precedence[e->op] == 0) e->print(); | |
2291 | /* Despite precedence, we don't allow a<b<c expressions. | |
2292 | * They must be parenthesized. | |
2293 | */ | |
2294 | if (precedence[e->op] < pr || | |
2295 | (pr == PREC_rel && precedence[e->op] == pr)) | |
2296 | { | |
2297 | buf->writeByte('('); | |
2298 | e->accept(this); | |
2299 | buf->writeByte(')'); | |
2300 | } | |
2301 | else | |
2302 | e->accept(this); | |
2303 | } | |
2304 | ||
2305 | void visit(Expression *e) | |
2306 | { | |
2307 | buf->writestring(Token::toChars(e->op)); | |
2308 | } | |
2309 | ||
2310 | void visit(IntegerExp *e) | |
2311 | { | |
2312 | dinteger_t v = e->toInteger(); | |
2313 | ||
2314 | if (e->type) | |
2315 | { | |
2316 | Type *t = e->type; | |
2317 | L1: | |
2318 | switch (t->ty) | |
2319 | { | |
2320 | case Tenum: | |
2321 | { | |
2322 | TypeEnum *te = (TypeEnum *)t; | |
2323 | if (hgs->fullDump) | |
2324 | { | |
2325 | EnumDeclaration *sym = te->sym; | |
2326 | if (inEnumDecl != sym) | |
2327 | { | |
2cbc99d1 | 2328 | for (size_t i = 0; i < sym->members->length; i++) |
b4c522fa IB |
2329 | { |
2330 | EnumMember *em = (EnumMember *)(*sym->members)[i]; | |
2331 | if (em->value()->toInteger() == v) | |
2332 | { | |
2333 | buf->printf("%s.%s", sym->toChars(), em->ident->toChars()); | |
2334 | return; | |
2335 | } | |
2336 | } | |
2337 | } | |
2338 | } | |
2339 | buf->printf("cast(%s)", te->sym->toChars()); | |
2340 | t = te->sym->memtype; | |
2341 | goto L1; | |
2342 | } | |
2343 | ||
2344 | case Twchar: // BUG: need to cast(wchar) | |
2345 | case Tdchar: // BUG: need to cast(dchar) | |
2346 | if ((uinteger_t)v > 0xFF) | |
2347 | { | |
2348 | buf->printf("'\\U%08x'", v); | |
2349 | break; | |
2350 | } | |
2351 | /* fall through */ | |
2352 | case Tchar: | |
2353 | { | |
d103f336 | 2354 | size_t o = buf->length(); |
b4c522fa IB |
2355 | if (v == '\'') |
2356 | buf->writestring("'\\''"); | |
2357 | else if (isprint((int)v) && v != '\\') | |
2358 | buf->printf("'%c'", (int)v); | |
2359 | else | |
2360 | buf->printf("'\\x%02x'", (int)v); | |
2361 | if (hgs->ddoc) | |
2362 | escapeDdocString(buf, o); | |
2363 | break; | |
2364 | } | |
2365 | ||
2366 | case Tint8: | |
2367 | buf->writestring("cast(byte)"); | |
2368 | goto L2; | |
2369 | ||
2370 | case Tint16: | |
2371 | buf->writestring("cast(short)"); | |
2372 | goto L2; | |
2373 | ||
2374 | case Tint32: | |
2375 | L2: | |
2376 | buf->printf("%d", (int)v); | |
2377 | break; | |
2378 | ||
2379 | case Tuns8: | |
2380 | buf->writestring("cast(ubyte)"); | |
2381 | goto L3; | |
2382 | ||
2383 | case Tuns16: | |
2384 | buf->writestring("cast(ushort)"); | |
2385 | goto L3; | |
2386 | ||
2387 | case Tuns32: | |
2388 | L3: | |
2389 | buf->printf("%uu", (unsigned)v); | |
2390 | break; | |
2391 | ||
2392 | case Tint64: | |
2393 | buf->printf("%lldL", v); | |
2394 | break; | |
2395 | ||
2396 | case Tuns64: | |
2397 | L4: | |
2398 | buf->printf("%lluLU", v); | |
2399 | break; | |
2400 | ||
2401 | case Tbool: | |
2402 | buf->writestring(v ? "true" : "false"); | |
2403 | break; | |
2404 | ||
2405 | case Tpointer: | |
2406 | buf->writestring("cast("); | |
2407 | buf->writestring(t->toChars()); | |
2408 | buf->writeByte(')'); | |
5905cbdb | 2409 | if (target.ptrsize == 8) |
b4c522fa IB |
2410 | goto L4; |
2411 | else | |
de83a4c1 | 2412 | goto L3; |
b4c522fa IB |
2413 | |
2414 | default: | |
2415 | /* This can happen if errors, such as | |
2416 | * the type is painted on like in fromConstInitializer(). | |
2417 | */ | |
2418 | if (!global.errors) | |
2419 | { | |
2420 | assert(0); | |
2421 | } | |
2422 | break; | |
2423 | } | |
2424 | } | |
2425 | else if (v & 0x8000000000000000LL) | |
2426 | buf->printf("0x%llx", v); | |
2427 | else | |
2428 | buf->printf("%lld", v); | |
2429 | } | |
2430 | ||
2431 | void visit(ErrorExp *) | |
2432 | { | |
2433 | buf->writestring("__error"); | |
2434 | } | |
2435 | ||
2436 | void floatToBuffer(Type *type, real_t value) | |
2437 | { | |
2438 | /** sizeof(value)*3 is because each byte of mantissa is max | |
2439 | of 256 (3 characters). The string will be "-M.MMMMe-4932". | |
2440 | (ie, 8 chars more than mantissa). Plus one for trailing \0. | |
2441 | Plus one for rounding. */ | |
2442 | const size_t BUFFER_LEN = sizeof(value) * 3 + 8 + 1 + 1; | |
f9ab59ff IB |
2443 | char buffer[BUFFER_LEN]; |
2444 | memset(buffer, 0, BUFFER_LEN); | |
b4c522fa IB |
2445 | CTFloat::sprint(buffer, 'g', value); |
2446 | assert(strlen(buffer) < BUFFER_LEN); | |
2447 | ||
2448 | if (hgs->hdrgen) | |
2449 | { | |
2450 | real_t r = CTFloat::parse(buffer); | |
2451 | if (r != value) // if exact duplication | |
2452 | CTFloat::sprint(buffer, 'a', value); | |
2453 | } | |
2454 | buf->writestring(buffer); | |
2455 | ||
2456 | if (type) | |
2457 | { | |
2458 | Type *t = type->toBasetype(); | |
2459 | switch (t->ty) | |
2460 | { | |
2461 | case Tfloat32: | |
2462 | case Timaginary32: | |
2463 | case Tcomplex32: | |
2464 | buf->writeByte('F'); | |
2465 | break; | |
2466 | ||
2467 | case Tfloat80: | |
2468 | case Timaginary80: | |
2469 | case Tcomplex80: | |
2470 | buf->writeByte('L'); | |
2471 | break; | |
2472 | ||
2473 | default: | |
2474 | break; | |
2475 | } | |
2476 | if (t->isimaginary()) | |
2477 | buf->writeByte('i'); | |
2478 | } | |
2479 | } | |
2480 | ||
2481 | void visit(RealExp *e) | |
2482 | { | |
2483 | floatToBuffer(e->type, e->value); | |
2484 | } | |
2485 | ||
2486 | void visit(ComplexExp *e) | |
2487 | { | |
2488 | /* Print as: | |
2489 | * (re+imi) | |
2490 | */ | |
2491 | buf->writeByte('('); | |
2492 | floatToBuffer(e->type, creall(e->value)); | |
2493 | buf->writeByte('+'); | |
2494 | floatToBuffer(e->type, cimagl(e->value)); | |
2495 | buf->writestring("i)"); | |
2496 | } | |
2497 | ||
2498 | void visit(IdentifierExp *e) | |
2499 | { | |
2500 | if (hgs->hdrgen || hgs->ddoc) | |
2501 | buf->writestring(e->ident->toHChars2()); | |
2502 | else | |
2503 | buf->writestring(e->ident->toChars()); | |
2504 | } | |
2505 | ||
2506 | void visit(DsymbolExp *e) | |
2507 | { | |
2508 | buf->writestring(e->s->toChars()); | |
2509 | } | |
2510 | ||
2511 | void visit(ThisExp *) | |
2512 | { | |
2513 | buf->writestring("this"); | |
2514 | } | |
2515 | ||
2516 | void visit(SuperExp *) | |
2517 | { | |
2518 | buf->writestring("super"); | |
2519 | } | |
2520 | ||
2521 | void visit(NullExp *) | |
2522 | { | |
2523 | buf->writestring("null"); | |
2524 | } | |
2525 | ||
2526 | void visit(StringExp *e) | |
2527 | { | |
2528 | buf->writeByte('"'); | |
d103f336 | 2529 | size_t o = buf->length(); |
b4c522fa IB |
2530 | for (size_t i = 0; i < e->len; i++) |
2531 | { | |
2532 | unsigned c = e->charAt(i); | |
2533 | switch (c) | |
2534 | { | |
2535 | case '"': | |
2536 | case '\\': | |
2537 | buf->writeByte('\\'); | |
2538 | /* fall through */ | |
2539 | default: | |
2540 | if (c <= 0xFF) | |
2541 | { | |
2542 | if (c <= 0x7F && isprint(c)) | |
2543 | buf->writeByte(c); | |
2544 | else | |
2545 | buf->printf("\\x%02x", c); | |
2546 | } | |
2547 | else if (c <= 0xFFFF) | |
2548 | buf->printf("\\x%02x\\x%02x", c & 0xFF, c >> 8); | |
2549 | else | |
2550 | buf->printf("\\x%02x\\x%02x\\x%02x\\x%02x", | |
2551 | c & 0xFF, (c >> 8) & 0xFF, (c >> 16) & 0xFF, c >> 24); | |
2552 | break; | |
2553 | } | |
2554 | } | |
2555 | if (hgs->ddoc) | |
2556 | escapeDdocString(buf, o); | |
2557 | buf->writeByte('"'); | |
2558 | if (e->postfix) | |
2559 | buf->writeByte(e->postfix); | |
2560 | } | |
2561 | ||
2562 | void visit(ArrayLiteralExp *e) | |
2563 | { | |
2564 | buf->writeByte('['); | |
2565 | argsToBuffer(e->elements, e->basis); | |
2566 | buf->writeByte(']'); | |
2567 | } | |
2568 | ||
2569 | void visit(AssocArrayLiteralExp *e) | |
2570 | { | |
2571 | buf->writeByte('['); | |
2cbc99d1 | 2572 | for (size_t i = 0; i < e->keys->length; i++) |
b4c522fa IB |
2573 | { |
2574 | Expression *key = (*e->keys)[i]; | |
2575 | Expression *value = (*e->values)[i]; | |
2576 | ||
2577 | if (i) | |
2578 | buf->writestring(", "); | |
2579 | expToBuffer(key, PREC_assign); | |
2580 | buf->writeByte(':'); | |
2581 | expToBuffer(value, PREC_assign); | |
2582 | } | |
2583 | buf->writeByte(']'); | |
2584 | } | |
2585 | ||
2586 | void visit(StructLiteralExp *e) | |
2587 | { | |
2588 | buf->writestring(e->sd->toChars()); | |
2589 | buf->writeByte('('); | |
2590 | ||
2591 | // CTFE can generate struct literals that contain an AddrExp pointing | |
2592 | // to themselves, need to avoid infinite recursion: | |
2593 | // struct S { this(int){ this.s = &this; } S* s; } | |
2594 | // const foo = new S(0); | |
2595 | if (e->stageflags & stageToCBuffer) | |
2596 | buf->writestring("<recursion>"); | |
2597 | else | |
2598 | { | |
2599 | int old = e->stageflags; | |
2600 | e->stageflags |= stageToCBuffer; | |
2601 | argsToBuffer(e->elements); | |
2602 | e->stageflags = old; | |
2603 | } | |
2604 | ||
2605 | buf->writeByte(')'); | |
2606 | } | |
2607 | ||
2608 | void visit(TypeExp *e) | |
2609 | { | |
2610 | typeToBuffer(e->type, NULL); | |
2611 | } | |
2612 | ||
2613 | void visit(ScopeExp *e) | |
2614 | { | |
2615 | if (e->sds->isTemplateInstance()) | |
2616 | { | |
2617 | e->sds->accept(this); | |
2618 | } | |
2619 | else if (hgs != NULL && hgs->ddoc) | |
2620 | { | |
2621 | // fixes bug 6491 | |
2622 | Module *m = e->sds->isModule(); | |
2623 | if (m) | |
2624 | buf->writestring(m->md->toChars()); | |
2625 | else | |
2626 | buf->writestring(e->sds->toChars()); | |
2627 | } | |
2628 | else | |
2629 | { | |
2630 | buf->writestring(e->sds->kind()); | |
2631 | buf->writeByte(' '); | |
2632 | buf->writestring(e->sds->toChars()); | |
2633 | } | |
2634 | } | |
2635 | ||
2636 | void visit(TemplateExp *e) | |
2637 | { | |
2638 | buf->writestring(e->td->toChars()); | |
2639 | } | |
2640 | ||
2641 | void visit(NewExp *e) | |
2642 | { | |
2643 | if (e->thisexp) | |
2644 | { | |
2645 | expToBuffer(e->thisexp, PREC_primary); | |
2646 | buf->writeByte('.'); | |
2647 | } | |
2648 | buf->writestring("new "); | |
2cbc99d1 | 2649 | if (e->newargs && e->newargs->length) |
b4c522fa IB |
2650 | { |
2651 | buf->writeByte('('); | |
2652 | argsToBuffer(e->newargs); | |
2653 | buf->writeByte(')'); | |
2654 | } | |
2655 | typeToBuffer(e->newtype, NULL); | |
2cbc99d1 | 2656 | if (e->arguments && e->arguments->length) |
b4c522fa IB |
2657 | { |
2658 | buf->writeByte('('); | |
2659 | argsToBuffer(e->arguments); | |
2660 | buf->writeByte(')'); | |
2661 | } | |
2662 | } | |
2663 | ||
2664 | void visit(NewAnonClassExp *e) | |
2665 | { | |
2666 | if (e->thisexp) | |
2667 | { | |
2668 | expToBuffer(e->thisexp, PREC_primary); | |
2669 | buf->writeByte('.'); | |
2670 | } | |
2671 | buf->writestring("new"); | |
2cbc99d1 | 2672 | if (e->newargs && e->newargs->length) |
b4c522fa IB |
2673 | { |
2674 | buf->writeByte('('); | |
2675 | argsToBuffer(e->newargs); | |
2676 | buf->writeByte(')'); | |
2677 | } | |
2678 | buf->writestring(" class "); | |
2cbc99d1 | 2679 | if (e->arguments && e->arguments->length) |
b4c522fa IB |
2680 | { |
2681 | buf->writeByte('('); | |
2682 | argsToBuffer(e->arguments); | |
2683 | buf->writeByte(')'); | |
2684 | } | |
2685 | if (e->cd) | |
2686 | e->cd->accept(this); | |
2687 | } | |
2688 | ||
2689 | void visit(SymOffExp *e) | |
2690 | { | |
2691 | if (e->offset) | |
2692 | buf->printf("(& %s+%u)", e->var->toChars(), e->offset); | |
2693 | else if (e->var->isTypeInfoDeclaration()) | |
2694 | buf->printf("%s", e->var->toChars()); | |
2695 | else | |
2696 | buf->printf("& %s", e->var->toChars()); | |
2697 | } | |
2698 | ||
2699 | void visit(VarExp *e) | |
2700 | { | |
2701 | buf->writestring(e->var->toChars()); | |
2702 | } | |
2703 | ||
2704 | void visit(OverExp *e) | |
2705 | { | |
2706 | buf->writestring(e->vars->ident->toChars()); | |
2707 | } | |
2708 | ||
2709 | void visit(TupleExp *e) | |
2710 | { | |
2711 | if (e->e0) | |
2712 | { | |
2713 | buf->writeByte('('); | |
2714 | e->e0->accept(this); | |
2715 | buf->writestring(", tuple("); | |
2716 | argsToBuffer(e->exps); | |
2717 | buf->writestring("))"); | |
2718 | } | |
2719 | else | |
2720 | { | |
2721 | buf->writestring("tuple("); | |
2722 | argsToBuffer(e->exps); | |
2723 | buf->writeByte(')'); | |
2724 | } | |
2725 | } | |
2726 | ||
2727 | void visit(FuncExp *e) | |
2728 | { | |
2729 | e->fd->accept(this); | |
2730 | //buf->writestring(e->fd->toChars()); | |
2731 | } | |
2732 | ||
2733 | void visit(DeclarationExp *e) | |
2734 | { | |
2735 | /* Normal dmd execution won't reach here - regular variable declarations | |
2736 | * are handled in visit(ExpStatement), so here would be used only when | |
2737 | * we'll directly call Expression::toChars() for debugging. | |
2738 | */ | |
2739 | if (VarDeclaration *v = e->declaration->isVarDeclaration()) | |
2740 | { | |
2741 | // For debugging use: | |
2742 | // - Avoid printing newline. | |
2743 | // - Intentionally use the format (Type var;) | |
2744 | // which isn't correct as regular D code. | |
2745 | buf->writeByte('('); | |
2746 | visitVarDecl(v, false); | |
2747 | buf->writeByte(';'); | |
2748 | buf->writeByte(')'); | |
2749 | } | |
2750 | else | |
2751 | e->declaration->accept(this); | |
2752 | } | |
2753 | ||
2754 | void visit(TypeidExp *e) | |
2755 | { | |
2756 | buf->writestring("typeid("); | |
2757 | objectToBuffer(e->obj); | |
2758 | buf->writeByte(')'); | |
2759 | } | |
2760 | ||
2761 | void visit(TraitsExp *e) | |
2762 | { | |
2763 | buf->writestring("__traits("); | |
5b74dd0a IB |
2764 | if (e->ident) |
2765 | buf->writestring(e->ident->toChars()); | |
b4c522fa IB |
2766 | if (e->args) |
2767 | { | |
2cbc99d1 | 2768 | for (size_t i = 0; i < e->args->length; i++) |
b4c522fa IB |
2769 | { |
2770 | RootObject *arg = (*e->args)[i]; | |
2771 | buf->writestring(", "); | |
2772 | objectToBuffer(arg); | |
2773 | } | |
2774 | } | |
2775 | buf->writeByte(')'); | |
2776 | } | |
2777 | ||
2778 | void visit(HaltExp *) | |
2779 | { | |
2780 | buf->writestring("halt"); | |
2781 | } | |
2782 | ||
2783 | void visit(IsExp *e) | |
2784 | { | |
2785 | buf->writestring("is("); | |
2786 | typeToBuffer(e->targ, e->id); | |
2787 | if (e->tok2 != TOKreserved) | |
2788 | { | |
2789 | buf->printf(" %s %s", Token::toChars(e->tok), Token::toChars(e->tok2)); | |
2790 | } | |
2791 | else if (e->tspec) | |
2792 | { | |
2793 | if (e->tok == TOKcolon) | |
2794 | buf->writestring(" : "); | |
2795 | else | |
2796 | buf->writestring(" == "); | |
2797 | typeToBuffer(e->tspec, NULL); | |
2798 | } | |
2cbc99d1 | 2799 | if (e->parameters && e->parameters->length) |
b4c522fa IB |
2800 | { |
2801 | buf->writestring(", "); | |
2802 | visitTemplateParameters(e->parameters); | |
2803 | } | |
2804 | buf->writeByte(')'); | |
2805 | } | |
2806 | ||
2807 | void visit(UnaExp *e) | |
2808 | { | |
2809 | buf->writestring(Token::toChars(e->op)); | |
2810 | expToBuffer(e->e1, precedence[e->op]); | |
2811 | } | |
2812 | ||
2813 | void visit(BinExp *e) | |
2814 | { | |
2815 | expToBuffer(e->e1, precedence[e->op]); | |
2816 | buf->writeByte(' '); | |
2817 | buf->writestring(Token::toChars(e->op)); | |
2818 | buf->writeByte(' '); | |
2819 | expToBuffer(e->e2, (PREC)(precedence[e->op] + 1)); | |
2820 | } | |
2821 | ||
2822 | void visit(CompileExp *e) | |
2823 | { | |
2824 | buf->writestring("mixin("); | |
2825 | expToBuffer(e->e1, PREC_assign); | |
2826 | buf->writeByte(')'); | |
2827 | } | |
2828 | ||
2829 | void visit(ImportExp *e) | |
2830 | { | |
2831 | buf->writestring("import("); | |
2832 | expToBuffer(e->e1, PREC_assign); | |
2833 | buf->writeByte(')'); | |
2834 | } | |
2835 | ||
2836 | void visit(AssertExp *e) | |
2837 | { | |
2838 | buf->writestring("assert("); | |
2839 | expToBuffer(e->e1, PREC_assign); | |
2840 | if (e->msg) | |
2841 | { | |
2842 | buf->writestring(", "); | |
2843 | expToBuffer(e->msg, PREC_assign); | |
2844 | } | |
2845 | buf->writeByte(')'); | |
2846 | } | |
2847 | ||
2848 | void visit(DotIdExp *e) | |
2849 | { | |
2850 | expToBuffer(e->e1, PREC_primary); | |
2851 | buf->writeByte('.'); | |
2852 | buf->writestring(e->ident->toChars()); | |
2853 | } | |
2854 | ||
2855 | void visit(DotTemplateExp *e) | |
2856 | { | |
2857 | expToBuffer(e->e1, PREC_primary); | |
2858 | buf->writeByte('.'); | |
2859 | buf->writestring(e->td->toChars()); | |
2860 | } | |
2861 | ||
2862 | void visit(DotVarExp *e) | |
2863 | { | |
2864 | expToBuffer(e->e1, PREC_primary); | |
2865 | buf->writeByte('.'); | |
2866 | buf->writestring(e->var->toChars()); | |
2867 | } | |
2868 | ||
2869 | void visit(DotTemplateInstanceExp *e) | |
2870 | { | |
2871 | expToBuffer(e->e1, PREC_primary); | |
2872 | buf->writeByte('.'); | |
2873 | e->ti->accept(this); | |
2874 | } | |
2875 | ||
2876 | void visit(DelegateExp *e) | |
2877 | { | |
2878 | buf->writeByte('&'); | |
2879 | if (!e->func->isNested()) | |
2880 | { | |
2881 | expToBuffer(e->e1, PREC_primary); | |
2882 | buf->writeByte('.'); | |
2883 | } | |
2884 | buf->writestring(e->func->toChars()); | |
2885 | } | |
2886 | ||
2887 | void visit(DotTypeExp *e) | |
2888 | { | |
2889 | expToBuffer(e->e1, PREC_primary); | |
2890 | buf->writeByte('.'); | |
2891 | buf->writestring(e->sym->toChars()); | |
2892 | } | |
2893 | ||
2894 | void visit(CallExp *e) | |
2895 | { | |
2896 | if (e->e1->op == TOKtype) | |
2897 | { | |
2898 | /* Avoid parens around type to prevent forbidden cast syntax: | |
2899 | * (sometype)(arg1) | |
2900 | * This is ok since types in constructor calls | |
2901 | * can never depend on parens anyway | |
2902 | */ | |
2903 | e->e1->accept(this); | |
2904 | } | |
2905 | else | |
2906 | expToBuffer(e->e1, precedence[e->op]); | |
2907 | buf->writeByte('('); | |
2908 | argsToBuffer(e->arguments); | |
2909 | buf->writeByte(')'); | |
2910 | } | |
2911 | ||
2912 | void visit(PtrExp *e) | |
2913 | { | |
2914 | buf->writeByte('*'); | |
2915 | expToBuffer(e->e1, precedence[e->op]); | |
2916 | } | |
2917 | ||
2918 | void visit(DeleteExp *e) | |
2919 | { | |
2920 | buf->writestring("delete "); | |
2921 | expToBuffer(e->e1, precedence[e->op]); | |
2922 | } | |
2923 | ||
2924 | void visit(CastExp *e) | |
2925 | { | |
2926 | buf->writestring("cast("); | |
2927 | if (e->to) | |
2928 | typeToBuffer(e->to, NULL); | |
2929 | else | |
2930 | { | |
2931 | MODtoBuffer(buf, e->mod); | |
2932 | } | |
2933 | buf->writeByte(')'); | |
2934 | expToBuffer(e->e1, precedence[e->op]); | |
2935 | } | |
2936 | ||
2937 | void visit(VectorExp *e) | |
2938 | { | |
2939 | buf->writestring("cast("); | |
2940 | typeToBuffer(e->to, NULL); | |
2941 | buf->writeByte(')'); | |
2942 | expToBuffer(e->e1, precedence[e->op]); | |
2943 | } | |
2944 | ||
b9da0278 IB |
2945 | void visit(VectorArrayExp *e) |
2946 | { | |
2947 | expToBuffer(e->e1, PREC_primary); | |
2948 | buf->writestring(".array"); | |
2949 | } | |
2950 | ||
b4c522fa IB |
2951 | void visit(SliceExp *e) |
2952 | { | |
2953 | expToBuffer(e->e1, precedence[e->op]); | |
2954 | buf->writeByte('['); | |
2955 | if (e->upr || e->lwr) | |
2956 | { | |
2957 | if (e->lwr) | |
2958 | sizeToBuffer(e->lwr); | |
2959 | else | |
2960 | buf->writeByte('0'); | |
2961 | buf->writestring(".."); | |
2962 | if (e->upr) | |
2963 | sizeToBuffer(e->upr); | |
2964 | else | |
2965 | buf->writeByte('$'); | |
2966 | } | |
2967 | buf->writeByte(']'); | |
2968 | } | |
2969 | ||
2970 | void visit(ArrayLengthExp *e) | |
2971 | { | |
2972 | expToBuffer(e->e1, PREC_primary); | |
2973 | buf->writestring(".length"); | |
2974 | } | |
2975 | ||
2976 | void visit(IntervalExp *e) | |
2977 | { | |
2978 | expToBuffer(e->lwr, PREC_assign); | |
2979 | buf->writestring(".."); | |
2980 | expToBuffer(e->upr, PREC_assign); | |
2981 | } | |
2982 | ||
2983 | void visit(DelegatePtrExp *e) | |
2984 | { | |
2985 | expToBuffer(e->e1, PREC_primary); | |
2986 | buf->writestring(".ptr"); | |
2987 | } | |
2988 | ||
2989 | void visit(DelegateFuncptrExp *e) | |
2990 | { | |
2991 | expToBuffer(e->e1, PREC_primary); | |
2992 | buf->writestring(".funcptr"); | |
2993 | } | |
2994 | ||
2995 | void visit(ArrayExp *e) | |
2996 | { | |
2997 | expToBuffer(e->e1, PREC_primary); | |
2998 | buf->writeByte('['); | |
2999 | argsToBuffer(e->arguments); | |
3000 | buf->writeByte(']'); | |
3001 | } | |
3002 | ||
3003 | void visit(DotExp *e) | |
3004 | { | |
3005 | expToBuffer(e->e1, PREC_primary); | |
3006 | buf->writeByte('.'); | |
3007 | expToBuffer(e->e2, PREC_primary); | |
3008 | } | |
3009 | ||
3010 | void visit(IndexExp *e) | |
3011 | { | |
3012 | expToBuffer(e->e1, PREC_primary); | |
3013 | buf->writeByte('['); | |
3014 | sizeToBuffer(e->e2); | |
3015 | buf->writeByte(']'); | |
3016 | } | |
3017 | ||
3018 | void visit(PostExp *e) | |
3019 | { | |
3020 | expToBuffer(e->e1, precedence[e->op]); | |
3021 | buf->writestring(Token::toChars(e->op)); | |
3022 | } | |
3023 | ||
3024 | void visit(PreExp *e) | |
3025 | { | |
3026 | buf->writestring(Token::toChars(e->op)); | |
3027 | expToBuffer(e->e1, precedence[e->op]); | |
3028 | } | |
3029 | ||
3030 | void visit(RemoveExp *e) | |
3031 | { | |
3032 | expToBuffer(e->e1, PREC_primary); | |
3033 | buf->writestring(".remove("); | |
3034 | expToBuffer(e->e2, PREC_assign); | |
3035 | buf->writeByte(')'); | |
3036 | } | |
3037 | ||
3038 | void visit(CondExp *e) | |
3039 | { | |
3040 | expToBuffer(e->econd, PREC_oror); | |
3041 | buf->writestring(" ? "); | |
3042 | expToBuffer(e->e1, PREC_expr); | |
3043 | buf->writestring(" : "); | |
3044 | expToBuffer(e->e2, PREC_cond); | |
3045 | } | |
3046 | ||
3047 | void visit(DefaultInitExp *e) | |
3048 | { | |
3049 | buf->writestring(Token::toChars(e->subop)); | |
3050 | } | |
3051 | ||
3052 | void visit(ClassReferenceExp *e) | |
3053 | { | |
3054 | buf->writestring(e->value->toChars()); | |
3055 | } | |
3056 | ||
3057 | //////////////////////////////////////////////////////////////////////////// | |
3058 | ||
3059 | void visit(TemplateTypeParameter *tp) | |
3060 | { | |
3061 | buf->writestring(tp->ident->toChars()); | |
3062 | if (tp->specType) | |
3063 | { | |
3064 | buf->writestring(" : "); | |
3065 | typeToBuffer(tp->specType, NULL); | |
3066 | } | |
3067 | if (tp->defaultType) | |
3068 | { | |
3069 | buf->writestring(" = "); | |
3070 | typeToBuffer(tp->defaultType, NULL); | |
3071 | } | |
3072 | } | |
3073 | ||
3074 | void visit(TemplateThisParameter *tp) | |
3075 | { | |
3076 | buf->writestring("this "); | |
3077 | visit((TemplateTypeParameter *)tp); | |
3078 | } | |
3079 | ||
3080 | void visit(TemplateAliasParameter *tp) | |
3081 | { | |
3082 | buf->writestring("alias "); | |
3083 | if (tp->specType) | |
3084 | typeToBuffer(tp->specType, tp->ident); | |
3085 | else | |
3086 | buf->writestring(tp->ident->toChars()); | |
3087 | if (tp->specAlias) | |
3088 | { | |
3089 | buf->writestring(" : "); | |
3090 | objectToBuffer(tp->specAlias); | |
3091 | } | |
3092 | if (tp->defaultAlias) | |
3093 | { | |
3094 | buf->writestring(" = "); | |
3095 | objectToBuffer(tp->defaultAlias); | |
3096 | } | |
3097 | } | |
3098 | ||
3099 | void visit(TemplateValueParameter *tp) | |
3100 | { | |
3101 | typeToBuffer(tp->valType, tp->ident); | |
3102 | if (tp->specValue) | |
3103 | { | |
3104 | buf->writestring(" : "); | |
3105 | tp->specValue->accept(this); | |
3106 | } | |
3107 | if (tp->defaultValue) | |
3108 | { | |
3109 | buf->writestring(" = "); | |
3110 | tp->defaultValue->accept(this); | |
3111 | } | |
3112 | } | |
3113 | ||
3114 | void visit(TemplateTupleParameter *tp) | |
3115 | { | |
3116 | buf->writestring(tp->ident->toChars()); | |
3117 | buf->writestring("..."); | |
3118 | } | |
3119 | ||
3120 | //////////////////////////////////////////////////////////////////////////// | |
3121 | ||
3122 | void visit(DebugCondition *c) | |
3123 | { | |
3124 | if (c->ident) | |
3125 | buf->printf("debug (%s)", c->ident->toChars()); | |
3126 | else | |
3127 | buf->printf("debug (%u)", c->level); | |
3128 | } | |
3129 | ||
3130 | void visit(VersionCondition *c) | |
3131 | { | |
3132 | if (c->ident) | |
3133 | buf->printf("version (%s)", c->ident->toChars()); | |
3134 | else | |
3135 | buf->printf("version (%u)", c->level); | |
3136 | } | |
3137 | ||
3138 | void visit(StaticIfCondition *c) | |
3139 | { | |
3140 | buf->writestring("static if ("); | |
3141 | c->exp->accept(this); | |
3142 | buf->writeByte(')'); | |
3143 | } | |
3144 | ||
3145 | //////////////////////////////////////////////////////////////////////////// | |
3146 | ||
3147 | void visit(Parameter *p) | |
3148 | { | |
dddea6d4 IB |
3149 | if (p->userAttribDecl) |
3150 | { | |
3151 | buf->writestring("@"); | |
3152 | bool isAnonymous = p->userAttribDecl->atts->length > 0 | |
3153 | && (*p->userAttribDecl->atts)[0]->op != TOKcall; | |
3154 | if (isAnonymous) | |
3155 | buf->writestring("("); | |
3156 | argsToBuffer(p->userAttribDecl->atts); | |
3157 | if (isAnonymous) | |
3158 | buf->writestring(")"); | |
3159 | buf->writestring(" "); | |
3160 | } | |
b4c522fa IB |
3161 | if (p->storageClass & STCauto) |
3162 | buf->writestring("auto "); | |
3163 | ||
3164 | if (p->storageClass & STCreturn) | |
3165 | buf->writestring("return "); | |
3166 | ||
3167 | if (p->storageClass & STCout) | |
3168 | buf->writestring("out "); | |
3169 | else if (p->storageClass & STCref) | |
3170 | buf->writestring("ref "); | |
3171 | else if (p->storageClass & STCin) | |
3172 | buf->writestring("in "); | |
3173 | else if (p->storageClass & STClazy) | |
3174 | buf->writestring("lazy "); | |
3175 | else if (p->storageClass & STCalias) | |
3176 | buf->writestring("alias "); | |
3177 | ||
3178 | StorageClass stc = p->storageClass; | |
3179 | if (p->type && p->type->mod & MODshared) | |
3180 | stc &= ~STCshared; | |
3181 | ||
3182 | if (stcToBuffer(buf, stc & (STCconst | STCimmutable | STCwild | STCshared | STCscope | STCscopeinferred))) | |
3183 | buf->writeByte(' '); | |
3184 | ||
3185 | if (p->storageClass & STCalias) | |
3186 | { | |
3187 | if (p->ident) | |
3188 | buf->writestring(p->ident->toChars()); | |
3189 | } | |
3190 | else if (p->type->ty == Tident && | |
3191 | strlen(((TypeIdentifier *)p->type)->ident->toChars()) > 3 && | |
3192 | strncmp(((TypeIdentifier *)p->type)->ident->toChars(), "__T", 3) == 0) | |
3193 | { | |
3194 | // print parameter name, instead of undetermined type parameter | |
3195 | buf->writestring(p->ident->toChars()); | |
3196 | } | |
3197 | else | |
3198 | typeToBuffer(p->type, p->ident); | |
3199 | if (p->defaultArg) | |
3200 | { | |
3201 | buf->writestring(" = "); | |
3202 | p->defaultArg->accept(this); | |
3203 | } | |
3204 | } | |
3205 | ||
3206 | void parametersToBuffer(Parameters *parameters, int varargs) | |
3207 | { | |
3208 | buf->writeByte('('); | |
3209 | if (parameters) | |
3210 | { | |
3211 | size_t dim = Parameter::dim(parameters); | |
3212 | for (size_t i = 0; i < dim; i++) | |
3213 | { | |
3214 | if (i) | |
3215 | buf->writestring(", "); | |
3216 | Parameter *fparam = Parameter::getNth(parameters, i); | |
3217 | fparam->accept(this); | |
3218 | } | |
3219 | if (varargs) | |
3220 | { | |
2cbc99d1 | 3221 | if (parameters->length && varargs == 1) |
b4c522fa IB |
3222 | buf->writestring(", "); |
3223 | buf->writestring("..."); | |
3224 | } | |
3225 | } | |
3226 | buf->writeByte(')'); | |
3227 | } | |
3228 | ||
3229 | void visit(Module *m) | |
3230 | { | |
3231 | if (m->md) | |
3232 | { | |
3233 | if (m->userAttribDecl) | |
3234 | { | |
3235 | buf->writestring("@("); | |
3236 | argsToBuffer(m->userAttribDecl->atts); | |
3237 | buf->writeByte(')'); | |
3238 | buf->writenl(); | |
3239 | } | |
3240 | if (m->md->isdeprecated) | |
3241 | { | |
3242 | if (m->md->msg) | |
3243 | { | |
3244 | buf->writestring("deprecated("); | |
3245 | m->md->msg->accept(this); | |
3246 | buf->writestring(") "); | |
3247 | } | |
3248 | else | |
3249 | buf->writestring("deprecated "); | |
3250 | } | |
3251 | ||
3252 | buf->writestring("module "); | |
3253 | buf->writestring(m->md->toChars()); | |
3254 | buf->writeByte(';'); | |
3255 | buf->writenl(); | |
3256 | } | |
2cbc99d1 | 3257 | for (size_t i = 0; i < m->members->length; i++) |
b4c522fa IB |
3258 | { |
3259 | Dsymbol *s = (*m->members)[i]; | |
3260 | s->accept(this); | |
3261 | } | |
3262 | } | |
3263 | }; | |
3264 | ||
3265 | void toCBuffer(Statement *s, OutBuffer *buf, HdrGenState *hgs) | |
3266 | { | |
3267 | PrettyPrintVisitor v(buf, hgs); | |
3268 | s->accept(&v); | |
3269 | } | |
3270 | ||
3271 | void toCBuffer(Type *t, OutBuffer *buf, Identifier *ident, HdrGenState *hgs) | |
3272 | { | |
3273 | PrettyPrintVisitor v(buf, hgs); | |
3274 | v.typeToBuffer(t, ident); | |
3275 | } | |
3276 | ||
3277 | void toCBuffer(Dsymbol *s, OutBuffer *buf, HdrGenState *hgs) | |
3278 | { | |
3279 | PrettyPrintVisitor v(buf, hgs); | |
3280 | s->accept(&v); | |
3281 | } | |
3282 | ||
3283 | // used from TemplateInstance::toChars() and TemplateMixin::toChars() | |
3284 | void toCBufferInstance(TemplateInstance *ti, OutBuffer *buf, bool qualifyTypes) | |
3285 | { | |
3286 | HdrGenState hgs; | |
3287 | hgs.fullQual = qualifyTypes; | |
3288 | PrettyPrintVisitor v(buf, &hgs); | |
3289 | v.visit(ti); | |
3290 | } | |
3291 | ||
3292 | void toCBuffer(Initializer *iz, OutBuffer *buf, HdrGenState *hgs) | |
3293 | { | |
3294 | PrettyPrintVisitor v(buf, hgs); | |
3295 | iz->accept(&v); | |
3296 | } | |
3297 | ||
3298 | bool stcToBuffer(OutBuffer *buf, StorageClass stc) | |
3299 | { | |
3300 | bool result = false; | |
3301 | if ((stc & (STCreturn | STCscope)) == (STCreturn | STCscope)) | |
3302 | stc &= ~STCscope; | |
3303 | if (stc & STCscopeinferred) | |
3304 | stc &= ~(STCscope | STCscopeinferred); | |
3305 | while (stc) | |
3306 | { | |
3307 | const char *p = stcToChars(stc); | |
3308 | if (!p) | |
3309 | break; | |
3310 | if (!result) | |
3311 | result = true; | |
3312 | else | |
3313 | buf->writeByte(' '); | |
3314 | buf->writestring(p); | |
3315 | } | |
3316 | return result; | |
3317 | } | |
3318 | ||
3319 | /************************************************* | |
3320 | * Pick off one of the storage classes from stc, | |
3321 | * and return a pointer to a string representation of it. | |
3322 | * stc is reduced by the one picked. | |
3323 | */ | |
3324 | const char *stcToChars(StorageClass& stc) | |
3325 | { | |
3326 | struct SCstring | |
3327 | { | |
3328 | StorageClass stc; | |
3329 | TOK tok; | |
3330 | const char *id; | |
3331 | }; | |
3332 | ||
3333 | static SCstring table[] = | |
3334 | { | |
3335 | { STCauto, TOKauto, NULL }, | |
3336 | { STCscope, TOKscope, NULL }, | |
3337 | { STCstatic, TOKstatic, NULL }, | |
3338 | { STCextern, TOKextern, NULL }, | |
3339 | { STCconst, TOKconst, NULL }, | |
3340 | { STCfinal, TOKfinal, NULL }, | |
3341 | { STCabstract, TOKabstract, NULL }, | |
3342 | { STCsynchronized, TOKsynchronized, NULL }, | |
3343 | { STCdeprecated, TOKdeprecated, NULL }, | |
3344 | { STCoverride, TOKoverride, NULL }, | |
3345 | { STClazy, TOKlazy, NULL }, | |
3346 | { STCalias, TOKalias, NULL }, | |
3347 | { STCout, TOKout, NULL }, | |
3348 | { STCin, TOKin, NULL }, | |
3349 | { STCmanifest, TOKenum, NULL }, | |
3350 | { STCimmutable, TOKimmutable, NULL }, | |
3351 | { STCshared, TOKshared, NULL }, | |
3352 | { STCnothrow, TOKnothrow, NULL }, | |
3353 | { STCwild, TOKwild, NULL }, | |
3354 | { STCpure, TOKpure, NULL }, | |
3355 | { STCref, TOKref, NULL }, | |
3356 | { STCtls, TOKreserved, NULL }, | |
3357 | { STCgshared, TOKgshared, NULL }, | |
3358 | { STCnogc, TOKat, "@nogc" }, | |
3359 | { STCproperty, TOKat, "@property" }, | |
3360 | { STCsafe, TOKat, "@safe" }, | |
3361 | { STCtrusted, TOKat, "@trusted" }, | |
3362 | { STCsystem, TOKat, "@system" }, | |
3363 | { STCdisable, TOKat, "@disable" }, | |
3364 | { STCfuture, TOKat, "@__future" }, | |
5b74dd0a | 3365 | { STClocal, TOKat, "__local" }, |
b4c522fa IB |
3366 | { 0, TOKreserved, NULL } |
3367 | }; | |
3368 | ||
3369 | for (int i = 0; table[i].stc; i++) | |
3370 | { | |
3371 | StorageClass tbl = table[i].stc; | |
3372 | assert(tbl & STCStorageClass); | |
3373 | if (stc & tbl) | |
3374 | { | |
3375 | stc &= ~tbl; | |
3376 | if (tbl == STCtls) // TOKtls was removed | |
3377 | return "__thread"; | |
3378 | ||
3379 | TOK tok = table[i].tok; | |
3380 | if (tok == TOKat) | |
3381 | return table[i].id; | |
3382 | else | |
3383 | return Token::toChars(tok); | |
3384 | } | |
3385 | } | |
3386 | //printf("stc = %llx\n", stc); | |
3387 | return NULL; | |
3388 | } | |
3389 | ||
3390 | void trustToBuffer(OutBuffer *buf, TRUST trust) | |
3391 | { | |
3392 | const char *p = trustToChars(trust); | |
3393 | if (p) | |
3394 | buf->writestring(p); | |
3395 | } | |
3396 | ||
3397 | const char *trustToChars(TRUST trust) | |
3398 | { | |
3399 | switch (trust) | |
3400 | { | |
3401 | case TRUSTdefault: return NULL; | |
3402 | case TRUSTsystem: return "@system"; | |
3403 | case TRUSTtrusted: return "@trusted"; | |
3404 | case TRUSTsafe: return "@safe"; | |
3405 | default: assert(0); | |
3406 | } | |
3407 | return NULL; // never reached | |
3408 | } | |
3409 | ||
3410 | void linkageToBuffer(OutBuffer *buf, LINK linkage) | |
3411 | { | |
3412 | const char *p = linkageToChars(linkage); | |
3413 | if (p) | |
3414 | { | |
3415 | buf->writestring("extern ("); | |
3416 | buf->writestring(p); | |
3417 | buf->writeByte(')'); | |
3418 | } | |
3419 | } | |
3420 | ||
3421 | const char *linkageToChars(LINK linkage) | |
3422 | { | |
3423 | switch (linkage) | |
3424 | { | |
3425 | case LINKdefault: return NULL; | |
3426 | case LINKd: return "D"; | |
3427 | case LINKc: return "C"; | |
3428 | case LINKcpp: return "C++"; | |
3429 | case LINKwindows: return "Windows"; | |
b4c522fa IB |
3430 | case LINKobjc: return "Objective-C"; |
3431 | case LINKsystem: return "System"; | |
3432 | default: assert(0); | |
3433 | } | |
3434 | return NULL; // never reached | |
3435 | } | |
3436 | ||
3437 | void protectionToBuffer(OutBuffer *buf, Prot prot) | |
3438 | { | |
3439 | const char *p = protectionToChars(prot.kind); | |
3440 | if (p) | |
3441 | buf->writestring(p); | |
3442 | ||
0a2ee409 | 3443 | if (prot.kind == Prot::package_ && prot.pkg) |
b4c522fa IB |
3444 | { |
3445 | buf->writeByte('('); | |
3446 | buf->writestring(prot.pkg->toPrettyChars(true)); | |
3447 | buf->writeByte(')'); | |
3448 | } | |
3449 | } | |
3450 | ||
0a2ee409 | 3451 | const char *protectionToChars(Prot::Kind kind) |
b4c522fa IB |
3452 | { |
3453 | switch (kind) | |
3454 | { | |
0a2ee409 IB |
3455 | case Prot::undefined: return NULL; |
3456 | case Prot::none: return "none"; | |
3457 | case Prot::private_: return "private"; | |
3458 | case Prot::package_: return "package"; | |
3459 | case Prot::protected_: return "protected"; | |
3460 | case Prot::public_: return "public"; | |
3461 | case Prot::export_: return "export"; | |
b4c522fa IB |
3462 | default: assert(0); |
3463 | } | |
3464 | return NULL; // never reached | |
3465 | } | |
3466 | ||
3467 | // Print the full function signature with correct ident, attributes and template args | |
3468 | void functionToBufferFull(TypeFunction *tf, OutBuffer *buf, Identifier *ident, | |
3469 | HdrGenState* hgs, TemplateDeclaration *td) | |
3470 | { | |
3471 | //printf("TypeFunction::toCBuffer() this = %p\n", this); | |
3472 | PrettyPrintVisitor v(buf, hgs); | |
3473 | v.visitFuncIdentWithPrefix(tf, ident, td); | |
3474 | } | |
3475 | ||
3476 | // ident is inserted before the argument list and will be "function" or "delegate" for a type | |
3477 | void functionToBufferWithIdent(TypeFunction *tf, OutBuffer *buf, const char *ident) | |
3478 | { | |
3479 | HdrGenState hgs; | |
3480 | PrettyPrintVisitor v(buf, &hgs); | |
3481 | v.visitFuncIdentWithPostfix(tf, ident); | |
3482 | } | |
3483 | ||
3484 | void toCBuffer(Expression *e, OutBuffer *buf, HdrGenState *hgs) | |
3485 | { | |
3486 | PrettyPrintVisitor v(buf, hgs); | |
3487 | e->accept(&v); | |
3488 | } | |
3489 | ||
3490 | /************************************************** | |
3491 | * Write out argument types to buf. | |
3492 | */ | |
3493 | void argExpTypesToCBuffer(OutBuffer *buf, Expressions *arguments) | |
3494 | { | |
2cbc99d1 | 3495 | if (!arguments || !arguments->length) |
b4c522fa IB |
3496 | return; |
3497 | ||
3498 | HdrGenState hgs; | |
3499 | PrettyPrintVisitor v(buf, &hgs); | |
2cbc99d1 | 3500 | for (size_t i = 0; i < arguments->length; i++) |
b4c522fa IB |
3501 | { |
3502 | Expression *arg = (*arguments)[i]; | |
3503 | if (i) | |
3504 | buf->writestring(", "); | |
3505 | v.typeToBuffer(arg->type, NULL); | |
3506 | } | |
3507 | } | |
3508 | ||
3509 | void toCBuffer(TemplateParameter *tp, OutBuffer *buf, HdrGenState *hgs) | |
3510 | { | |
3511 | PrettyPrintVisitor v(buf, hgs); | |
3512 | tp->accept(&v); | |
3513 | } | |
3514 | ||
3515 | void arrayObjectsToBuffer(OutBuffer *buf, Objects *objects) | |
3516 | { | |
2cbc99d1 | 3517 | if (!objects || !objects->length) |
b4c522fa IB |
3518 | return; |
3519 | ||
3520 | HdrGenState hgs; | |
3521 | PrettyPrintVisitor v(buf, &hgs); | |
2cbc99d1 | 3522 | for (size_t i = 0; i < objects->length; i++) |
b4c522fa IB |
3523 | { |
3524 | RootObject *o = (*objects)[i]; | |
3525 | if (i) | |
3526 | buf->writestring(", "); | |
3527 | v.objectToBuffer(o); | |
3528 | } | |
3529 | } | |
3530 | ||
c3a2ba10 | 3531 | const char *parametersTypeToChars(ParameterList pl) |
b4c522fa IB |
3532 | { |
3533 | OutBuffer buf; | |
3534 | HdrGenState hgs; | |
3535 | PrettyPrintVisitor v(&buf, &hgs); | |
c3a2ba10 | 3536 | v.parametersToBuffer(pl.parameters, pl.varargs); |
fced594b | 3537 | return buf.extractChars(); |
b4c522fa | 3538 | } |