d: Merge dmd. druntime e770945277, phobos 6d6e0b9b9
[official-gcc.git] / gcc / d / dmd / hdrgen.d
blob030153c91da2ad436a5bc93599f90876151d7287
1 /**
2 * Generate $(LINK2 https://dlang.org/dmd-windows.html#interface-files, D interface files).
4 * Also used to convert AST nodes to D code in general, e.g. for error messages or `printf` debugging.
6 * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved
7 * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright)
8 * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
9 * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/hdrgen.d, _hdrgen.d)
10 * Documentation: https://dlang.org/phobos/dmd_hdrgen.html
11 * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/hdrgen.d
14 module dmd.hdrgen;
16 import core.stdc.ctype;
17 import core.stdc.stdio;
18 import core.stdc.string;
19 import dmd.aggregate;
20 import dmd.aliasthis;
21 import dmd.arraytypes;
22 import dmd.astenums;
23 import dmd.attrib;
24 import dmd.cond;
25 import dmd.ctfeexpr;
26 import dmd.dclass;
27 import dmd.declaration;
28 import dmd.denum;
29 import dmd.dimport;
30 import dmd.dmodule;
31 import dmd.doc;
32 import dmd.dstruct;
33 import dmd.dsymbol;
34 import dmd.dtemplate;
35 import dmd.dversion;
36 import dmd.expression;
37 import dmd.func;
38 import dmd.id;
39 import dmd.identifier;
40 import dmd.init;
41 import dmd.mtype;
42 import dmd.nspace;
43 import dmd.optimize;
44 import dmd.parse;
45 import dmd.root.complex;
46 import dmd.root.ctfloat;
47 import dmd.common.outbuffer;
48 import dmd.rootobject;
49 import dmd.root.string;
50 import dmd.statement;
51 import dmd.staticassert;
52 import dmd.tokens;
53 import dmd.visitor;
55 struct HdrGenState
57 bool hdrgen; /// true if generating header file
58 bool ddoc; /// true if generating Ddoc file
59 bool fullDump; /// true if generating a full AST dump file
60 bool importcHdr; /// true if generating a .di file from an ImportC file
61 bool doFuncBodies; /// include function bodies in output
62 bool vcg_ast; /// write out codegen-ast
63 bool skipConstraints; // skip constraints when doing templates
65 bool fullQual; /// fully qualify types when printing
66 int tpltMember;
67 int autoMember;
68 int forStmtInit;
69 int insideFuncBody;
70 int insideAggregate;
72 bool declstring; // set while declaring alias for string,wstring or dstring
73 EnumDeclaration inEnumDecl;
76 enum TEST_EMIT_ALL = 0;
78 /****************************************
79 * Generate a header (.di) file for Module m.
80 * Params:
81 * m = Module to generate header for
82 * doFuncBodies = generate function definitions rather than just declarations
83 * buf = buffer to write the data to
85 extern (C++) void genhdrfile(Module m, bool doFuncBodies, ref OutBuffer buf)
87 buf.doindent = 1;
88 buf.printf("// D import file generated from '%s'", m.srcfile.toChars());
89 buf.writenl();
90 HdrGenState hgs;
91 hgs.hdrgen = true;
92 hgs.importcHdr = (m.filetype == FileType.c);
93 hgs.doFuncBodies = doFuncBodies;
94 toCBuffer(m, buf, hgs);
97 /***************************************
98 * Turn a Statement into a string suitable for printf.
99 * Leaks memory.
100 * Params:
101 * s = Statement to convert
102 * Returns:
103 * 0-terminated string
105 public extern (C++) const(char)* toChars(const Statement s)
107 HdrGenState hgs;
108 OutBuffer buf;
109 toCBuffer(s, buf, hgs);
110 buf.writeByte(0);
111 return buf.extractSlice().ptr;
114 public extern (C++) const(char)* toChars(const Expression e)
116 HdrGenState hgs;
117 OutBuffer buf;
118 toCBuffer(e, buf, hgs);
119 return buf.extractChars();
122 public extern (C++) const(char)* toChars(const Initializer i)
124 OutBuffer buf;
125 HdrGenState hgs;
126 toCBuffer(i, buf, hgs);
127 return buf.extractChars();
130 public extern (C++) const(char)* toChars(const Type t)
132 OutBuffer buf;
133 buf.reserve(16);
134 HdrGenState hgs;
135 hgs.fullQual = (t.ty == Tclass && !t.mod);
137 toCBuffer(t, buf, null, hgs);
138 return buf.extractChars();
141 public const(char)[] toString(const Initializer i)
143 OutBuffer buf;
144 HdrGenState hgs;
145 toCBuffer(i, buf, hgs);
146 return buf.extractSlice();
150 * Dumps the full contents of module `m` to `buf`.
151 * Params:
152 * buf = buffer to write to.
153 * vcg_ast = write out codegen ast
154 * m = module to visit all members of.
156 extern (C++) void moduleToBuffer(ref OutBuffer buf, bool vcg_ast, Module m)
158 HdrGenState hgs;
159 hgs.fullDump = true;
160 hgs.vcg_ast = vcg_ast;
161 toCBuffer(m, buf, hgs);
164 void moduleToBuffer2(Module m, ref OutBuffer buf, ref HdrGenState hgs)
166 if (m.md)
168 if (m.userAttribDecl)
170 buf.writestring("@(");
171 argsToBuffer(m.userAttribDecl.atts, buf, hgs);
172 buf.writeByte(')');
173 buf.writenl();
175 if (m.md.isdeprecated)
177 if (m.md.msg)
179 buf.writestring("deprecated(");
180 m.md.msg.expressionToBuffer(buf, hgs);
181 buf.writestring(") ");
183 else
184 buf.writestring("deprecated ");
186 buf.writestring("module ");
187 buf.writestring(m.md.toChars());
188 buf.writeByte(';');
189 buf.writenl();
192 foreach (s; *m.members)
194 s.dsymbolToBuffer(buf, hgs);
198 private void statementToBuffer(Statement s, ref OutBuffer buf, ref HdrGenState hgs)
200 void visitDefaultCase(Statement s)
202 printf("Statement::toCBuffer() %d\n", s.stmt);
203 assert(0, "unrecognized statement in statementToBuffer()");
206 void visitError(ErrorStatement s)
208 buf.writestring("__error__");
209 buf.writenl();
212 void visitExp(ExpStatement s)
214 if (s.exp && s.exp.op == EXP.declaration &&
215 (cast(DeclarationExp)s.exp).declaration)
217 // bypass visit(DeclarationExp)
218 (cast(DeclarationExp)s.exp).declaration.dsymbolToBuffer(buf, hgs);
219 return;
221 if (s.exp)
222 s.exp.expressionToBuffer(buf, hgs);
223 buf.writeByte(';');
224 if (!hgs.forStmtInit)
225 buf.writenl();
228 void visitDtorExp(DtorExpStatement s)
230 visitExp(s);
233 void visitMixin(MixinStatement s)
235 buf.writestring("mixin(");
236 argsToBuffer(s.exps, buf, hgs, null);
237 buf.writestring(");");
238 if (!hgs.forStmtInit)
239 buf.writenl();
242 void visitCompound(CompoundStatement s)
244 foreach (sx; *s.statements)
246 if (sx)
247 sx.statementToBuffer(buf, hgs);
251 void visitCompoundAsm(CompoundAsmStatement s)
253 visitCompound(s);
256 void visitCompoundDeclaration(CompoundDeclarationStatement s)
258 bool anywritten = false;
259 foreach (sx; *s.statements)
261 auto ds = sx ? sx.isExpStatement() : null;
262 if (ds && ds.exp.isDeclarationExp())
264 auto d = ds.exp.isDeclarationExp().declaration;
265 if (auto v = d.isVarDeclaration())
267 visitVarDecl(v, anywritten, buf, hgs);
269 else
270 d.dsymbolToBuffer(buf, hgs);
271 anywritten = true;
274 buf.writeByte(';');
275 if (!hgs.forStmtInit)
276 buf.writenl();
279 void visitUnrolledLoop(UnrolledLoopStatement s)
281 buf.writestring("/*unrolled*/ {");
282 buf.writenl();
283 buf.level++;
284 foreach (sx; *s.statements)
286 if (sx)
287 sx.statementToBuffer(buf, hgs);
289 buf.level--;
290 buf.writeByte('}');
291 buf.writenl();
294 void visitScope(ScopeStatement s)
296 buf.writeByte('{');
297 buf.writenl();
298 buf.level++;
299 if (s.statement)
300 s.statement.statementToBuffer(buf, hgs);
301 buf.level--;
302 buf.writeByte('}');
303 buf.writenl();
306 void visitWhile(WhileStatement s)
308 buf.writestring("while (");
309 if (auto p = s.param)
311 // Print condition assignment
312 StorageClass stc = p.storageClass;
313 if (!p.type && !stc)
314 stc = STC.auto_;
315 if (stcToBuffer(buf, stc))
316 buf.writeByte(' ');
317 if (p.type)
318 typeToBuffer(p.type, p.ident, buf, hgs);
319 else
320 buf.writestring(p.ident.toString());
321 buf.writestring(" = ");
323 s.condition.expressionToBuffer(buf, hgs);
324 buf.writeByte(')');
325 buf.writenl();
326 if (s._body)
327 s._body.statementToBuffer(buf, hgs);
330 void visitDo(DoStatement s)
332 buf.writestring("do");
333 buf.writenl();
334 if (s._body)
335 s._body.statementToBuffer(buf, hgs);
336 buf.writestring("while (");
337 s.condition.expressionToBuffer(buf, hgs);
338 buf.writestring(");");
339 buf.writenl();
342 void visitFor(ForStatement s)
344 buf.writestring("for (");
345 if (s._init)
347 hgs.forStmtInit++;
348 s._init.statementToBuffer(buf, hgs);
349 hgs.forStmtInit--;
351 else
352 buf.writeByte(';');
353 if (s.condition)
355 buf.writeByte(' ');
356 s.condition.expressionToBuffer(buf, hgs);
358 buf.writeByte(';');
359 if (s.increment)
361 buf.writeByte(' ');
362 s.increment.expressionToBuffer(buf, hgs);
364 buf.writeByte(')');
365 buf.writenl();
366 buf.writeByte('{');
367 buf.writenl();
368 buf.level++;
369 if (s._body)
370 s._body.statementToBuffer(buf, hgs);
371 buf.level--;
372 buf.writeByte('}');
373 buf.writenl();
376 void foreachWithoutBody(ForeachStatement s)
378 buf.writestring(Token.toString(s.op));
379 buf.writestring(" (");
380 foreach (i, p; *s.parameters)
382 if (i)
383 buf.writestring(", ");
384 if (stcToBuffer(buf, p.storageClass))
385 buf.writeByte(' ');
386 if (p.type)
387 typeToBuffer(p.type, p.ident, buf, hgs);
388 else
389 buf.writestring(p.ident.toString());
391 buf.writestring("; ");
392 s.aggr.expressionToBuffer(buf, hgs);
393 buf.writeByte(')');
394 buf.writenl();
397 void visitForeach(ForeachStatement s)
399 foreachWithoutBody(s);
400 buf.writeByte('{');
401 buf.writenl();
402 buf.level++;
403 if (s._body)
404 s._body.statementToBuffer(buf, hgs);
405 buf.level--;
406 buf.writeByte('}');
407 buf.writenl();
410 void foreachRangeWithoutBody(ForeachRangeStatement s)
412 buf.writestring(Token.toString(s.op));
413 buf.writestring(" (");
414 if (s.prm.type)
415 typeToBuffer(s.prm.type, s.prm.ident, buf, hgs);
416 else
417 buf.writestring(s.prm.ident.toString());
418 buf.writestring("; ");
419 s.lwr.expressionToBuffer(buf, hgs);
420 buf.writestring(" .. ");
421 s.upr.expressionToBuffer(buf, hgs);
422 buf.writeByte(')');
423 buf.writenl();
426 void visitForeachRange(ForeachRangeStatement s)
428 foreachRangeWithoutBody(s);
429 buf.writeByte('{');
430 buf.writenl();
431 buf.level++;
432 if (s._body)
433 s._body.statementToBuffer(buf, hgs);
434 buf.level--;
435 buf.writeByte('}');
436 buf.writenl();
439 void visitStaticForeach(StaticForeachStatement s)
441 buf.writestring("static ");
442 if (s.sfe.aggrfe)
444 visitForeach(s.sfe.aggrfe);
446 else
448 assert(s.sfe.rangefe);
449 visitForeachRange(s.sfe.rangefe);
453 void visitForwarding(ForwardingStatement s)
455 s.statement.statementToBuffer(buf, hgs);
458 void visitIf(IfStatement s)
460 buf.writestring("if (");
461 if (Parameter p = s.prm)
463 StorageClass stc = p.storageClass;
464 if (!p.type && !stc)
465 stc = STC.auto_;
466 if (stcToBuffer(buf, stc))
467 buf.writeByte(' ');
468 if (p.type)
469 typeToBuffer(p.type, p.ident, buf, hgs);
470 else
471 buf.writestring(p.ident.toString());
472 buf.writestring(" = ");
474 s.condition.expressionToBuffer(buf, hgs);
475 buf.writeByte(')');
476 buf.writenl();
477 if (s.ifbody.isScopeStatement())
479 s.ifbody.statementToBuffer(buf, hgs);
481 else
483 buf.level++;
484 s.ifbody.statementToBuffer(buf, hgs);
485 buf.level--;
487 if (s.elsebody)
489 buf.writestring("else");
490 if (!s.elsebody.isIfStatement())
492 buf.writenl();
494 else
496 buf.writeByte(' ');
498 if (s.elsebody.isScopeStatement() || s.elsebody.isIfStatement())
500 s.elsebody.statementToBuffer(buf, hgs);
502 else
504 buf.level++;
505 s.elsebody.statementToBuffer(buf, hgs);
506 buf.level--;
511 void visitConditional(ConditionalStatement s)
513 s.condition.conditionToBuffer(buf, hgs);
514 buf.writenl();
515 buf.writeByte('{');
516 buf.writenl();
517 buf.level++;
518 if (s.ifbody)
519 s.ifbody.statementToBuffer(buf, hgs);
520 buf.level--;
521 buf.writeByte('}');
522 buf.writenl();
523 if (s.elsebody)
525 buf.writestring("else");
526 buf.writenl();
527 buf.writeByte('{');
528 buf.level++;
529 buf.writenl();
530 s.elsebody.statementToBuffer(buf, hgs);
531 buf.level--;
532 buf.writeByte('}');
534 buf.writenl();
537 void visitPragma(PragmaStatement s)
539 buf.writestring("pragma (");
540 buf.writestring(s.ident.toString());
541 if (s.args && s.args.length)
543 buf.writestring(", ");
544 argsToBuffer(s.args, buf, hgs);
546 buf.writeByte(')');
547 if (s._body)
549 buf.writenl();
550 buf.writeByte('{');
551 buf.writenl();
552 buf.level++;
553 s._body.statementToBuffer(buf, hgs);
554 buf.level--;
555 buf.writeByte('}');
556 buf.writenl();
558 else
560 buf.writeByte(';');
561 buf.writenl();
565 void visitStaticAssert(StaticAssertStatement s)
567 s.sa.dsymbolToBuffer(buf, hgs);
570 void visitSwitch(SwitchStatement s)
572 buf.writestring(s.isFinal ? "final switch (" : "switch (");
573 if (auto p = s.param)
575 // Print condition assignment
576 StorageClass stc = p.storageClass;
577 if (!p.type && !stc)
578 stc = STC.auto_;
579 if (stcToBuffer(buf, stc))
580 buf.writeByte(' ');
581 if (p.type)
582 typeToBuffer(p.type, p.ident, buf, hgs);
583 else
584 buf.writestring(p.ident.toString());
585 buf.writestring(" = ");
587 s.condition.expressionToBuffer(buf, hgs);
588 buf.writeByte(')');
589 buf.writenl();
590 if (s._body)
592 if (!s._body.isScopeStatement())
594 buf.writeByte('{');
595 buf.writenl();
596 buf.level++;
597 s._body.statementToBuffer(buf, hgs);
598 buf.level--;
599 buf.writeByte('}');
600 buf.writenl();
602 else
604 s._body.statementToBuffer(buf, hgs);
609 void visitCase(CaseStatement s)
611 buf.writestring("case ");
612 s.exp.expressionToBuffer(buf, hgs);
613 buf.writeByte(':');
614 buf.writenl();
615 s.statement.statementToBuffer(buf, hgs);
618 void visitCaseRange(CaseRangeStatement s)
620 buf.writestring("case ");
621 s.first.expressionToBuffer(buf, hgs);
622 buf.writestring(": .. case ");
623 s.last.expressionToBuffer(buf, hgs);
624 buf.writeByte(':');
625 buf.writenl();
626 s.statement.statementToBuffer(buf, hgs);
629 void visitDefault(DefaultStatement s)
631 buf.writestring("default:");
632 buf.writenl();
633 s.statement.statementToBuffer(buf, hgs);
636 void visitGotoDefault(GotoDefaultStatement s)
638 buf.writestring("goto default;");
639 buf.writenl();
642 void visitGotoCase(GotoCaseStatement s)
644 buf.writestring("goto case");
645 if (s.exp)
647 buf.writeByte(' ');
648 s.exp.expressionToBuffer(buf, hgs);
650 buf.writeByte(';');
651 buf.writenl();
654 void visitSwitchError(SwitchErrorStatement s)
656 buf.writestring("SwitchErrorStatement::toCBuffer()");
657 buf.writenl();
660 void visitReturn(ReturnStatement s)
662 buf.writestring("return ");
663 if (s.exp)
664 s.exp.expressionToBuffer(buf, hgs);
665 buf.writeByte(';');
666 buf.writenl();
669 void visitBreak(BreakStatement s)
671 buf.writestring("break");
672 if (s.ident)
674 buf.writeByte(' ');
675 buf.writestring(s.ident.toString());
677 buf.writeByte(';');
678 buf.writenl();
681 void visitContinue(ContinueStatement s)
683 buf.writestring("continue");
684 if (s.ident)
686 buf.writeByte(' ');
687 buf.writestring(s.ident.toString());
689 buf.writeByte(';');
690 buf.writenl();
693 void visitSynchronized(SynchronizedStatement s)
695 buf.writestring("synchronized");
696 if (s.exp)
698 buf.writeByte('(');
699 s.exp.expressionToBuffer(buf, hgs);
700 buf.writeByte(')');
702 if (s._body)
704 buf.writeByte(' ');
705 s._body.statementToBuffer(buf, hgs);
709 void visitWith(WithStatement s)
711 buf.writestring("with (");
712 s.exp.expressionToBuffer(buf, hgs);
713 buf.writestring(")");
714 buf.writenl();
715 if (s._body)
716 s._body.statementToBuffer(buf, hgs);
719 void visitTryCatch(TryCatchStatement s)
721 buf.writestring("try");
722 buf.writenl();
723 if (s._body)
725 if (s._body.isScopeStatement())
727 s._body.statementToBuffer(buf, hgs);
729 else
731 buf.level++;
732 s._body.statementToBuffer(buf, hgs);
733 buf.level--;
736 foreach (c; *s.catches)
738 buf.writestring("catch");
739 if (c.type)
741 buf.writeByte('(');
742 typeToBuffer(c.type, c.ident, buf, hgs);
743 buf.writeByte(')');
745 buf.writenl();
746 buf.writeByte('{');
747 buf.writenl();
748 buf.level++;
749 if (c.handler)
750 c.handler.statementToBuffer(buf, hgs);
751 buf.level--;
752 buf.writeByte('}');
753 buf.writenl();
757 void visitTryFinally(TryFinallyStatement s)
759 buf.writestring("try");
760 buf.writenl();
761 buf.writeByte('{');
762 buf.writenl();
763 buf.level++;
764 s._body.statementToBuffer(buf, hgs);
765 buf.level--;
766 buf.writeByte('}');
767 buf.writenl();
768 buf.writestring("finally");
769 buf.writenl();
770 if (s.finalbody.isScopeStatement())
772 s.finalbody.statementToBuffer(buf, hgs);
774 else
776 buf.level++;
777 s.finalbody.statementToBuffer(buf, hgs);
778 buf.level--;
782 void visitScopeGuard(ScopeGuardStatement s)
784 buf.writestring(Token.toString(s.tok));
785 buf.writeByte(' ');
786 if (s.statement)
787 s.statement.statementToBuffer(buf, hgs);
790 void visitThrow(ThrowStatement s)
792 buf.writestring("throw ");
793 s.exp.expressionToBuffer(buf, hgs);
794 buf.writeByte(';');
795 buf.writenl();
798 void visitDebug(DebugStatement s)
800 if (s.statement)
802 s.statement.statementToBuffer(buf, hgs);
806 void visitGoto(GotoStatement s)
808 buf.writestring("goto ");
809 buf.writestring(s.ident.toString());
810 buf.writeByte(';');
811 buf.writenl();
814 void visitLabel(LabelStatement s)
816 buf.writestring(s.ident.toString());
817 buf.writeByte(':');
818 buf.writenl();
819 if (s.statement)
820 s.statement.statementToBuffer(buf, hgs);
823 void visitAsm(AsmStatement s)
825 buf.writestring("asm { ");
826 Token* t = s.tokens;
827 buf.level++;
828 while (t)
830 buf.writestring(t.toString());
831 if (t.next &&
832 t.value != TOK.min &&
833 t.value != TOK.comma && t.next.value != TOK.comma &&
834 t.value != TOK.leftBracket && t.next.value != TOK.leftBracket &&
835 t.next.value != TOK.rightBracket &&
836 t.value != TOK.leftParenthesis && t.next.value != TOK.leftParenthesis &&
837 t.next.value != TOK.rightParenthesis &&
838 t.value != TOK.dot && t.next.value != TOK.dot)
840 buf.writeByte(' ');
842 t = t.next;
844 buf.level--;
845 buf.writestring("; }");
846 buf.writenl();
849 void visitInlineAsm(InlineAsmStatement s)
851 visitAsm(s);
854 void visitGccAsm(GccAsmStatement s)
856 visitAsm(s);
859 void visitImport(ImportStatement s)
861 foreach (imp; *s.imports)
863 imp.dsymbolToBuffer(buf, hgs);
867 mixin VisitStatement!void visit;
868 visit.VisitStatement(s);
871 private void dsymbolToBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs)
873 toCBuffer(s, buf, hgs);
876 void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs)
878 void visitDsymbol(Dsymbol s)
880 buf.writestring(s.toChars());
883 void visitStaticAssert(StaticAssert s)
885 buf.writestring(s.kind());
886 buf.writeByte('(');
887 s.exp.expressionToBuffer(buf, hgs);
888 if (s.msgs)
890 foreach (m; (*s.msgs)[])
892 buf.writestring(", ");
893 m.expressionToBuffer(buf, hgs);
896 buf.writestring(");");
897 buf.writenl();
900 void visitDebugSymbol(DebugSymbol s)
902 buf.writestring("debug = ");
903 if (s.ident)
904 buf.writestring(s.ident.toString());
905 else
906 buf.print(s.level);
907 buf.writeByte(';');
908 buf.writenl();
911 void visitVersionSymbol(VersionSymbol s)
913 buf.writestring("version = ");
914 if (s.ident)
915 buf.writestring(s.ident.toString());
916 else
917 buf.print(s.level);
918 buf.writeByte(';');
919 buf.writenl();
922 void visitEnumMember(EnumMember em)
924 if (em.type)
925 typeToBuffer(em.type, em.ident, buf, hgs);
926 else
927 buf.writestring(em.ident.toString());
928 if (em.value)
930 buf.writestring(" = ");
931 em.value.expressionToBuffer(buf, hgs);
935 void visitImport(Import imp)
937 if (hgs.hdrgen && imp.id == Id.object)
938 return; // object is imported by default
939 if (imp.isstatic)
940 buf.writestring("static ");
941 buf.writestring("import ");
942 if (imp.aliasId)
944 buf.printf("%s = ", imp.aliasId.toChars());
946 foreach (const pid; imp.packages)
948 buf.write(pid.toString());
949 buf.writeByte('.');
951 buf.writestring(imp.id.toString());
952 if (imp.names.length)
954 buf.writestring(" : ");
955 foreach (const i, const name; imp.names)
957 if (i)
958 buf.writestring(", ");
959 const _alias = imp.aliases[i];
960 if (_alias)
961 buf.printf("%s = %s", _alias.toChars(), name.toChars());
962 else
963 buf.writestring(name.toChars());
966 buf.writeByte(';');
967 buf.writenl();
970 void visitAliasThis(AliasThis d)
972 buf.writestring("alias ");
973 buf.writestring(d.ident.toString());
974 buf.writestring(" this;\n");
977 void visitAttribDeclaration(AttribDeclaration d)
979 bool hasSTC;
980 if (auto stcd = d.isStorageClassDeclaration)
982 hasSTC = stcToBuffer(buf, stcd.stc);
985 if (!d.decl)
987 buf.writeByte(';');
988 buf.writenl();
989 return;
991 if (d.decl.length == 0 || (hgs.hdrgen && d.decl.length == 1 && (*d.decl)[0].isUnitTestDeclaration()))
993 // hack for https://issues.dlang.org/show_bug.cgi?id=8081
994 if (hasSTC) buf.writeByte(' ');
995 buf.writestring("{}");
997 else if (d.decl.length == 1)
999 if (hasSTC) buf.writeByte(' ');
1000 toCBuffer((*d.decl)[0], buf, hgs);
1001 return;
1003 else
1005 buf.writenl();
1006 buf.writeByte('{');
1007 buf.writenl();
1008 buf.level++;
1009 foreach (de; *d.decl)
1010 toCBuffer(de, buf, hgs);
1011 buf.level--;
1012 buf.writeByte('}');
1014 buf.writenl();
1017 void visitStorageClassDeclaration(StorageClassDeclaration d)
1019 visitAttribDeclaration(d);
1022 void visitDeprecatedDeclaration(DeprecatedDeclaration d)
1024 buf.writestring("deprecated(");
1025 d.msg.expressionToBuffer(buf, hgs);
1026 buf.writestring(") ");
1027 visitAttribDeclaration(d);
1030 void visitLinkDeclaration(LinkDeclaration d)
1032 buf.writestring("extern (");
1033 buf.writestring(linkageToString(d.linkage));
1034 buf.writestring(") ");
1035 visitAttribDeclaration(d);
1038 void visitCPPMangleDeclaration(CPPMangleDeclaration d)
1040 string s;
1041 final switch (d.cppmangle)
1043 case CPPMANGLE.asClass:
1044 s = "class";
1045 break;
1046 case CPPMANGLE.asStruct:
1047 s = "struct";
1048 break;
1049 case CPPMANGLE.def:
1050 break;
1052 buf.writestring("extern (C++, ");
1053 buf.writestring(s);
1054 buf.writestring(") ");
1055 visitAttribDeclaration(d);
1058 void visitVisibilityDeclaration(VisibilityDeclaration d)
1060 visibilityToBuffer(buf, d.visibility);
1061 AttribDeclaration ad = cast(AttribDeclaration)d;
1062 if (ad.decl.length <= 1)
1063 buf.writeByte(' ');
1064 if (ad.decl.length == 1 && (*ad.decl)[0].isVisibilityDeclaration)
1065 visitAttribDeclaration((*ad.decl)[0].isVisibilityDeclaration);
1066 else
1067 visitAttribDeclaration(d);
1070 void visitAlignDeclaration(AlignDeclaration d)
1072 if (d.exps)
1074 foreach (i, exp; (*d.exps)[])
1076 if (i)
1077 buf.writeByte(' ');
1078 buf.writestring("align (");
1079 toCBuffer(exp, buf, hgs);
1080 buf.writeByte(')');
1082 if (d.decl && d.decl.length < 2)
1083 buf.writeByte(' ');
1085 else
1086 buf.writestring("align ");
1088 visitAttribDeclaration(d.isAttribDeclaration());
1091 void visitAnonDeclaration(AnonDeclaration d)
1093 buf.writestring(d.isunion ? "union" : "struct");
1094 buf.writenl();
1095 buf.writestring("{");
1096 buf.writenl();
1097 buf.level++;
1098 if (d.decl)
1100 foreach (de; *d.decl)
1101 toCBuffer(de, buf, hgs);
1103 buf.level--;
1104 buf.writestring("}");
1105 buf.writenl();
1108 void visitPragmaDeclaration(PragmaDeclaration d)
1110 buf.writestring("pragma (");
1111 buf.writestring(d.ident.toString());
1112 if (d.args && d.args.length)
1114 buf.writestring(", ");
1115 argsToBuffer(d.args, buf, hgs);
1118 buf.writeByte(')');
1120 // https://issues.dlang.org/show_bug.cgi?id=14690
1121 // Unconditionally perform a full output dump
1122 // for `pragma(inline)` declarations.
1123 const saved = hgs.doFuncBodies;
1124 if (d.ident == Id.Pinline)
1125 hgs.doFuncBodies = true;
1127 visitAttribDeclaration(d);
1128 hgs.doFuncBodies = saved;
1131 void visitConditionalDeclaration(ConditionalDeclaration d)
1133 d.condition.conditionToBuffer(buf, hgs);
1134 if (d.decl || d.elsedecl)
1136 buf.writenl();
1137 buf.writeByte('{');
1138 buf.writenl();
1139 buf.level++;
1140 if (d.decl)
1142 foreach (de; *d.decl)
1143 toCBuffer(de, buf, hgs);
1145 buf.level--;
1146 buf.writeByte('}');
1147 if (d.elsedecl)
1149 buf.writenl();
1150 buf.writestring("else");
1151 buf.writenl();
1152 buf.writeByte('{');
1153 buf.writenl();
1154 buf.level++;
1155 foreach (de; *d.elsedecl)
1156 toCBuffer(de, buf, hgs);
1157 buf.level--;
1158 buf.writeByte('}');
1161 else
1162 buf.writeByte(':');
1163 buf.writenl();
1166 void visitStaticForeachDeclaration(StaticForeachDeclaration s)
1168 void foreachWithoutBody(ForeachStatement s)
1170 buf.writestring(Token.toString(s.op));
1171 buf.writestring(" (");
1172 foreach (i, p; *s.parameters)
1174 if (i)
1175 buf.writestring(", ");
1176 if (stcToBuffer(buf, p.storageClass))
1177 buf.writeByte(' ');
1178 if (p.type)
1179 typeToBuffer(p.type, p.ident, buf, hgs);
1180 else
1181 buf.writestring(p.ident.toString());
1183 buf.writestring("; ");
1184 s.aggr.expressionToBuffer(buf, hgs);
1185 buf.writeByte(')');
1186 buf.writenl();
1189 void foreachRangeWithoutBody(ForeachRangeStatement s)
1191 /* s.op ( prm ; lwr .. upr )
1193 buf.writestring(Token.toString(s.op));
1194 buf.writestring(" (");
1195 if (s.prm.type)
1196 typeToBuffer(s.prm.type, s.prm.ident, buf, hgs);
1197 else
1198 buf.writestring(s.prm.ident.toString());
1199 buf.writestring("; ");
1200 s.lwr.expressionToBuffer(buf, hgs);
1201 buf.writestring(" .. ");
1202 s.upr.expressionToBuffer(buf, hgs);
1203 buf.writeByte(')');
1204 buf.writenl();
1207 buf.writestring("static ");
1208 if (s.sfe.aggrfe)
1210 foreachWithoutBody(s.sfe.aggrfe);
1212 else
1214 assert(s.sfe.rangefe);
1215 foreachRangeWithoutBody(s.sfe.rangefe);
1217 buf.writeByte('{');
1218 buf.writenl();
1219 buf.level++;
1220 visitAttribDeclaration(s);
1221 buf.level--;
1222 buf.writeByte('}');
1223 buf.writenl();
1227 void visitMixinDeclaration(MixinDeclaration d)
1229 buf.writestring("mixin(");
1230 argsToBuffer(d.exps, buf, hgs, null);
1231 buf.writestring(");");
1232 buf.writenl();
1235 void visitUserAttributeDeclaration(UserAttributeDeclaration d)
1237 buf.writestring("@(");
1238 argsToBuffer(d.atts, buf, hgs);
1239 buf.writeByte(')');
1240 visitAttribDeclaration(d);
1243 void visitTemplateConstraint(Expression constraint)
1245 if (!constraint)
1246 return;
1247 buf.writestring(" if (");
1248 constraint.expressionToBuffer(buf, hgs);
1249 buf.writeByte(')');
1252 /// Returns: whether `do` is needed to write the function body
1253 bool contractsToBuffer(FuncDeclaration f)
1255 bool requireDo = false;
1256 // in{}
1257 if (f.frequires)
1259 foreach (frequire; *f.frequires)
1261 buf.writestring("in");
1262 if (auto es = frequire.isExpStatement())
1264 assert(es.exp && es.exp.op == EXP.assert_);
1265 buf.writestring(" (");
1266 (cast(AssertExp)es.exp).e1.expressionToBuffer(buf, hgs);
1267 buf.writeByte(')');
1268 buf.writenl();
1269 requireDo = false;
1271 else
1273 buf.writenl();
1274 frequire.statementToBuffer(buf, hgs);
1275 requireDo = true;
1279 // out{}
1280 if (f.fensures)
1282 foreach (fensure; *f.fensures)
1284 buf.writestring("out");
1285 if (auto es = fensure.ensure.isExpStatement())
1287 assert(es.exp && es.exp.op == EXP.assert_);
1288 buf.writestring(" (");
1289 if (fensure.id)
1291 buf.writestring(fensure.id.toString());
1293 buf.writestring("; ");
1294 (cast(AssertExp)es.exp).e1.expressionToBuffer(buf, hgs);
1295 buf.writeByte(')');
1296 buf.writenl();
1297 requireDo = false;
1299 else
1301 if (fensure.id)
1303 buf.writeByte('(');
1304 buf.writestring(fensure.id.toString());
1305 buf.writeByte(')');
1307 buf.writenl();
1308 fensure.ensure.statementToBuffer(buf, hgs);
1309 requireDo = true;
1313 return requireDo;
1316 void bodyToBuffer(FuncDeclaration f)
1318 if (!f.fbody || (hgs.hdrgen && hgs.doFuncBodies == false && !hgs.autoMember && !hgs.tpltMember && !hgs.insideFuncBody))
1320 if (!f.fbody && (f.fensures || f.frequires))
1322 buf.writenl();
1323 contractsToBuffer(f);
1325 buf.writeByte(';');
1326 buf.writenl();
1327 return;
1330 // there is no way to know if a function is nested
1331 // or not after parsing. We need scope information
1332 // for that, which is avaible during semantic
1333 // analysis. To overcome that, a simple mechanism
1334 // is implemented: everytime we print a function
1335 // body (templated or not) we increment a counter.
1336 // We decredement the counter when we stop
1337 // printing the function body.
1338 ++hgs.insideFuncBody;
1339 scope(exit) { --hgs.insideFuncBody; }
1341 const savetlpt = hgs.tpltMember;
1342 const saveauto = hgs.autoMember;
1343 hgs.tpltMember = 0;
1344 hgs.autoMember = 0;
1345 buf.writenl();
1346 bool requireDo = contractsToBuffer(f);
1348 if (requireDo)
1350 buf.writestring("do");
1351 buf.writenl();
1353 buf.writeByte('{');
1354 buf.writenl();
1355 buf.level++;
1356 f.fbody.statementToBuffer(buf, hgs);
1357 buf.level--;
1358 buf.writeByte('}');
1359 buf.writenl();
1360 hgs.tpltMember = savetlpt;
1361 hgs.autoMember = saveauto;
1364 void visitBaseClasses(ClassDeclaration d)
1366 if (!d || !d.baseclasses.length)
1367 return;
1368 if (!d.isAnonymous())
1369 buf.writestring(" : ");
1370 foreach (i, b; *d.baseclasses)
1372 if (i)
1373 buf.writestring(", ");
1374 typeToBuffer(b.type, null, buf, hgs);
1378 bool visitEponymousMember(TemplateDeclaration d)
1380 if (!d.members || d.members.length != 1)
1381 return false;
1382 Dsymbol onemember = (*d.members)[0];
1383 if (onemember.ident != d.ident)
1384 return false;
1385 if (FuncDeclaration fd = onemember.isFuncDeclaration())
1387 assert(fd.type);
1388 if (stcToBuffer(buf, fd.storage_class))
1389 buf.writeByte(' ');
1390 functionToBufferFull(cast(TypeFunction)fd.type, buf, d.ident, hgs, d);
1391 visitTemplateConstraint(d.constraint);
1392 hgs.tpltMember++;
1393 bodyToBuffer(fd);
1394 hgs.tpltMember--;
1395 return true;
1397 if (AggregateDeclaration ad = onemember.isAggregateDeclaration())
1399 buf.writestring(ad.kind());
1400 buf.writeByte(' ');
1401 buf.writestring(ad.ident.toString());
1402 buf.writeByte('(');
1403 visitTemplateParameters(hgs.ddoc ? d.origParameters : d.parameters, buf, hgs);
1404 buf.writeByte(')');
1405 visitTemplateConstraint(d.constraint);
1406 visitBaseClasses(ad.isClassDeclaration());
1407 hgs.tpltMember++;
1408 if (ad.members)
1410 buf.writenl();
1411 buf.writeByte('{');
1412 buf.writenl();
1413 buf.level++;
1414 foreach (s; *ad.members)
1415 toCBuffer(s, buf, hgs);
1416 buf.level--;
1417 buf.writeByte('}');
1419 else
1420 buf.writeByte(';');
1421 buf.writenl();
1422 hgs.tpltMember--;
1423 return true;
1425 if (VarDeclaration vd = onemember.isVarDeclaration())
1427 if (d.constraint)
1428 return false;
1429 if (stcToBuffer(buf, vd.storage_class))
1430 buf.writeByte(' ');
1431 if (vd.type)
1432 typeToBuffer(vd.type, vd.ident, buf, hgs);
1433 else
1434 buf.writestring(vd.ident.toString());
1435 buf.writeByte('(');
1436 visitTemplateParameters(hgs.ddoc ? d.origParameters : d.parameters, buf, hgs);
1437 buf.writeByte(')');
1438 if (vd._init)
1440 buf.writestring(" = ");
1441 ExpInitializer ie = vd._init.isExpInitializer();
1442 if (ie && (ie.exp.op == EXP.construct || ie.exp.op == EXP.blit))
1443 (cast(AssignExp)ie.exp).e2.expressionToBuffer(buf, hgs);
1444 else
1445 vd._init.initializerToBuffer(buf, hgs);
1447 buf.writeByte(';');
1448 buf.writenl();
1449 return true;
1451 return false;
1454 void visitTemplateDeclaration(TemplateDeclaration d)
1456 version (none)
1458 // Should handle template functions for doc generation
1459 if (onemember && onemember.isFuncDeclaration())
1460 buf.writestring("foo ");
1462 if ((hgs.hdrgen || hgs.fullDump) && visitEponymousMember(d))
1463 return;
1464 if (hgs.ddoc)
1465 buf.writestring(d.kind());
1466 else
1467 buf.writestring("template");
1468 buf.writeByte(' ');
1469 buf.writestring(d.ident.toString());
1470 buf.writeByte('(');
1471 visitTemplateParameters(hgs.ddoc ? d.origParameters : d.parameters, buf, hgs);
1472 buf.writeByte(')');
1473 visitTemplateConstraint(d.constraint);
1474 if (hgs.hdrgen || hgs.fullDump)
1476 hgs.tpltMember++;
1477 buf.writenl();
1478 buf.writeByte('{');
1479 buf.writenl();
1480 buf.level++;
1481 foreach (s; *d.members)
1482 toCBuffer(s, buf, hgs);
1483 buf.level--;
1484 buf.writeByte('}');
1485 buf.writenl();
1486 hgs.tpltMember--;
1490 void visitTemplateInstance(TemplateInstance ti)
1492 buf.writestring(ti.name.toChars());
1493 tiargsToBuffer(ti, buf, hgs);
1495 if (hgs.fullDump)
1497 buf.writenl();
1498 dumpTemplateInstance(ti, buf, hgs);
1502 void visitTemplateMixin(TemplateMixin tm)
1504 buf.writestring("mixin ");
1505 typeToBuffer(tm.tqual, null, buf, hgs);
1506 tiargsToBuffer(tm, buf, hgs);
1507 if (tm.ident && memcmp(tm.ident.toString().ptr, cast(const(char)*) "__mixin", 7) != 0)
1509 buf.writeByte(' ');
1510 buf.writestring(tm.ident.toString());
1512 buf.writeByte(';');
1513 buf.writenl();
1514 if (hgs.fullDump)
1515 dumpTemplateInstance(tm, buf, hgs);
1518 void visitEnumDeclaration(EnumDeclaration d)
1520 auto oldInEnumDecl = hgs.inEnumDecl;
1521 scope(exit) hgs.inEnumDecl = oldInEnumDecl;
1522 hgs.inEnumDecl = d;
1523 buf.writestring("enum ");
1524 if (d.ident)
1526 buf.writestring(d.ident.toString());
1528 if (d.memtype)
1530 buf.writestring(" : ");
1531 typeToBuffer(d.memtype, null, buf, hgs);
1533 if (!d.members)
1535 buf.writeByte(';');
1536 buf.writenl();
1537 return;
1539 buf.writenl();
1540 buf.writeByte('{');
1541 buf.writenl();
1542 buf.level++;
1543 foreach (em; *d.members)
1545 if (!em)
1546 continue;
1547 toCBuffer(em, buf, hgs);
1548 buf.writeByte(',');
1549 buf.writenl();
1551 buf.level--;
1552 buf.writeByte('}');
1553 buf.writenl();
1555 if (!hgs.importcHdr)
1556 return;
1558 /* C enums get their members inserted into the symbol table of the enum declaration.
1559 * This is accomplished in addEnumMembersToSymtab().
1560 * But when generating D code from ImportC code, D rulez are followed.
1561 * Accomplish this by generating an alias declaration for each member
1563 foreach (em; *d.members)
1565 if (!em)
1566 continue;
1567 buf.writestring("alias ");
1568 buf.writestring(em.ident.toString);
1569 buf.writestring(" = ");
1570 buf.writestring(d.ident.toString);
1571 buf.writeByte('.');
1572 buf.writestring(em.ident.toString);
1573 buf.writeByte(';');
1574 buf.writenl();
1578 void visitNspace(Nspace d)
1580 buf.writestring("extern (C++, ");
1581 buf.writestring(d.ident.toString());
1582 buf.writeByte(')');
1583 buf.writenl();
1584 buf.writeByte('{');
1585 buf.writenl();
1586 buf.level++;
1587 foreach (s; *d.members)
1588 toCBuffer(s, buf, hgs);
1589 buf.level--;
1590 buf.writeByte('}');
1591 buf.writenl();
1594 void visitStructDeclaration(StructDeclaration d)
1596 //printf("visitStructDeclaration() %s\n", d.ident.toChars());
1597 buf.writestring(d.kind());
1598 buf.writeByte(' ');
1599 if (!d.isAnonymous())
1600 buf.writestring(d.toChars());
1601 if (!d.members)
1603 buf.writeByte(';');
1604 buf.writenl();
1605 return;
1607 buf.writenl();
1608 buf.writeByte('{');
1609 buf.writenl();
1610 buf.level++;
1611 hgs.insideAggregate++;
1612 foreach (s; *d.members)
1613 toCBuffer(s, buf, hgs);
1614 hgs.insideAggregate--;
1615 buf.level--;
1616 buf.writeByte('}');
1617 buf.writenl();
1620 void visitClassDeclaration(ClassDeclaration d)
1622 if (!d.isAnonymous())
1624 buf.writestring(d.kind());
1625 buf.writeByte(' ');
1626 buf.writestring(d.ident.toString());
1628 visitBaseClasses(d);
1629 if (d.members)
1631 buf.writenl();
1632 buf.writeByte('{');
1633 buf.writenl();
1634 buf.level++;
1635 hgs.insideAggregate++;
1636 foreach (s; *d.members)
1637 toCBuffer(s, buf, hgs);
1638 hgs.insideAggregate--;
1639 buf.level--;
1640 buf.writeByte('}');
1642 else
1643 buf.writeByte(';');
1644 buf.writenl();
1647 void visitAliasDeclaration(AliasDeclaration d)
1649 if (d.storage_class & STC.local)
1650 return;
1651 if (d.adFlags & d.hidden)
1652 return;
1653 buf.writestring("alias ");
1654 if (d.aliassym)
1656 buf.writestring(d.ident.toString());
1657 buf.writestring(" = ");
1658 if (stcToBuffer(buf, d.storage_class))
1659 buf.writeByte(' ');
1661 https://issues.dlang.org/show_bug.cgi?id=23223
1662 https://issues.dlang.org/show_bug.cgi?id=23222
1663 This special case (initially just for modules) avoids some segfaults
1664 and nicer -vcg-ast output.
1666 if (d.aliassym.isModule())
1668 buf.writestring(d.aliassym.ident.toString());
1670 else
1672 toCBuffer(d.aliassym, buf, hgs);
1675 else if (d.type.ty == Tfunction)
1677 if (stcToBuffer(buf, d.storage_class))
1678 buf.writeByte(' ');
1679 typeToBuffer(d.type, d.ident, buf, hgs);
1681 else if (d.ident)
1683 hgs.declstring = (d.ident == Id.string || d.ident == Id.wstring || d.ident == Id.dstring);
1684 buf.writestring(d.ident.toString());
1685 buf.writestring(" = ");
1686 if (stcToBuffer(buf, d.storage_class))
1687 buf.writeByte(' ');
1688 typeToBuffer(d.type, null, buf, hgs);
1689 hgs.declstring = false;
1691 buf.writeByte(';');
1692 buf.writenl();
1695 void visitAliasAssign(AliasAssign d)
1697 buf.writestring(d.ident.toString());
1698 buf.writestring(" = ");
1699 if (d.aliassym)
1700 toCBuffer(d.aliassym, buf, hgs);
1701 else // d.type
1702 typeToBuffer(d.type, null, buf, hgs);
1703 buf.writeByte(';');
1704 buf.writenl();
1707 void visitVarDeclaration(VarDeclaration d)
1709 if (d.storage_class & STC.local)
1710 return;
1711 visitVarDecl(d, false, buf, hgs);
1712 buf.writeByte(';');
1713 buf.writenl();
1716 void visitFuncDeclaration(FuncDeclaration f)
1718 //printf("FuncDeclaration::toCBuffer() '%s'\n", f.toChars());
1719 if (stcToBuffer(buf, f.storage_class))
1720 buf.writeByte(' ');
1721 auto tf = f.type.isTypeFunction();
1722 typeToBuffer(tf, f.ident, buf, hgs);
1724 if (hgs.hdrgen)
1726 // if the return type is missing (e.g. ref functions or auto)
1727 // https://issues.dlang.org/show_bug.cgi?id=20090
1728 // constructors are an exception: they don't have an explicit return
1729 // type but we still don't output the body.
1730 if ((!f.isCtorDeclaration() && !tf.next) || f.storage_class & STC.auto_)
1732 hgs.autoMember++;
1733 bodyToBuffer(f);
1734 hgs.autoMember--;
1736 else if (hgs.tpltMember == 0 && hgs.doFuncBodies == false && !hgs.insideFuncBody)
1738 if (!f.fbody)
1740 // this can happen on interfaces / abstract functions, see `allowsContractWithoutBody`
1741 if (f.fensures || f.frequires)
1742 buf.writenl();
1743 contractsToBuffer(f);
1745 buf.writeByte(';');
1746 buf.writenl();
1748 else
1749 bodyToBuffer(f);
1751 else
1752 bodyToBuffer(f);
1755 void visitFuncLiteralDeclaration(FuncLiteralDeclaration f)
1757 if (f.type.ty == Terror)
1759 buf.writestring("__error");
1760 return;
1762 if (f.tok != TOK.reserved)
1764 buf.writestring(f.kind());
1765 buf.writeByte(' ');
1767 TypeFunction tf = cast(TypeFunction)f.type;
1769 if (!f.inferRetType && tf.next)
1770 typeToBuffer(tf.next, null, buf, hgs);
1771 parametersToBuffer(tf.parameterList, buf, hgs);
1773 // https://issues.dlang.org/show_bug.cgi?id=20074
1774 void printAttribute(string str)
1776 buf.writeByte(' ');
1777 buf.writestring(str);
1779 tf.attributesApply(&printAttribute);
1782 CompoundStatement cs = f.fbody.isCompoundStatement();
1783 Statement s1;
1784 if (f.semanticRun >= PASS.semantic3done && cs)
1786 s1 = (*cs.statements)[cs.statements.length - 1];
1788 else
1789 s1 = !cs ? f.fbody : null;
1790 ReturnStatement rs = s1 ? s1.endsWithReturnStatement() : null;
1791 if (rs && rs.exp)
1793 buf.writestring(" => ");
1794 rs.exp.expressionToBuffer(buf, hgs);
1796 else
1798 hgs.tpltMember++;
1799 bodyToBuffer(f);
1800 hgs.tpltMember--;
1804 void visitPostBlitDeclaration(PostBlitDeclaration d)
1806 if (stcToBuffer(buf, d.storage_class))
1807 buf.writeByte(' ');
1808 buf.writestring("this(this)");
1809 bodyToBuffer(d);
1812 void visitDtorDeclaration(DtorDeclaration d)
1814 if (stcToBuffer(buf, d.storage_class))
1815 buf.writeByte(' ');
1816 buf.writestring("~this()");
1817 bodyToBuffer(d);
1820 void visitStaticCtorDeclaration(StaticCtorDeclaration d)
1822 if (stcToBuffer(buf, d.storage_class & ~STC.static_))
1823 buf.writeByte(' ');
1824 if (d.isSharedStaticCtorDeclaration())
1825 buf.writestring("shared ");
1826 buf.writestring("static this()");
1827 if (hgs.hdrgen && !hgs.tpltMember)
1829 buf.writeByte(';');
1830 buf.writenl();
1832 else
1833 bodyToBuffer(d);
1836 void visitStaticDtorDeclaration(StaticDtorDeclaration d)
1838 if (stcToBuffer(buf, d.storage_class & ~STC.static_))
1839 buf.writeByte(' ');
1840 if (d.isSharedStaticDtorDeclaration())
1841 buf.writestring("shared ");
1842 buf.writestring("static ~this()");
1843 if (hgs.hdrgen && !hgs.tpltMember)
1845 buf.writeByte(';');
1846 buf.writenl();
1848 else
1849 bodyToBuffer(d);
1852 void visitInvariantDeclaration(InvariantDeclaration d)
1854 if (hgs.hdrgen)
1855 return;
1856 if (stcToBuffer(buf, d.storage_class))
1857 buf.writeByte(' ');
1858 buf.writestring("invariant");
1859 if(auto es = d.fbody.isExpStatement())
1861 assert(es.exp && es.exp.op == EXP.assert_);
1862 buf.writestring(" (");
1863 (cast(AssertExp)es.exp).e1.expressionToBuffer(buf, hgs);
1864 buf.writestring(");");
1865 buf.writenl();
1867 else
1869 bodyToBuffer(d);
1873 void visitUnitTestDeclaration(UnitTestDeclaration d)
1875 if (hgs.hdrgen)
1876 return;
1877 if (stcToBuffer(buf, d.storage_class))
1878 buf.writeByte(' ');
1879 buf.writestring("unittest");
1880 bodyToBuffer(d);
1883 void visitBitFieldDeclaration(BitFieldDeclaration d)
1885 if (stcToBuffer(buf, d.storage_class))
1886 buf.writeByte(' ');
1887 Identifier id = d.isAnonymous() ? null : d.ident;
1888 typeToBuffer(d.type, id, buf, hgs);
1889 buf.writestring(" : ");
1890 d.width.expressionToBuffer(buf, hgs);
1891 buf.writeByte(';');
1892 buf.writenl();
1895 void visitNewDeclaration(NewDeclaration d)
1897 if (stcToBuffer(buf, d.storage_class & ~STC.static_))
1898 buf.writeByte(' ');
1899 buf.writestring("new();");
1902 void visitModule(Module m)
1904 moduleToBuffer2(m, buf, hgs);
1907 extern (C++)
1908 final class DsymbolPrettyPrintVisitor : Visitor
1910 alias visit = Visitor.visit;
1912 public:
1913 override:
1914 void visit(Dsymbol s) { visitDsymbol(s); }
1915 void visit(StaticAssert s) { visitStaticAssert(s); }
1916 void visit(DebugSymbol s) { visitDebugSymbol(s); }
1917 void visit(VersionSymbol s) { visitVersionSymbol(s); }
1918 void visit(EnumMember em) { visitEnumMember(em); }
1919 void visit(Import imp) { visitImport(imp); }
1920 void visit(AliasThis d) { visitAliasThis(d); }
1921 void visit(AttribDeclaration d) { visitAttribDeclaration(d); }
1922 void visit(StorageClassDeclaration d) { visitStorageClassDeclaration(d); }
1923 void visit(DeprecatedDeclaration d) { visitDeprecatedDeclaration(d); }
1924 void visit(LinkDeclaration d) { visitLinkDeclaration(d); }
1925 void visit(CPPMangleDeclaration d) { visitCPPMangleDeclaration(d); }
1926 void visit(VisibilityDeclaration d) { visitVisibilityDeclaration(d); }
1927 void visit(AlignDeclaration d) { visitAlignDeclaration(d); }
1928 void visit(AnonDeclaration d) { visitAnonDeclaration(d); }
1929 void visit(PragmaDeclaration d) { visitPragmaDeclaration(d); }
1930 void visit(ConditionalDeclaration d) { visitConditionalDeclaration(d); }
1931 void visit(StaticForeachDeclaration s) { visitStaticForeachDeclaration(s); }
1932 void visit(MixinDeclaration d) { visitMixinDeclaration(d); }
1933 void visit(UserAttributeDeclaration d) { visitUserAttributeDeclaration(d); }
1934 void visit(TemplateDeclaration d) { visitTemplateDeclaration(d); }
1935 void visit(TemplateInstance ti) { visitTemplateInstance(ti); }
1936 void visit(TemplateMixin tm) { visitTemplateMixin(tm); }
1937 void visit(EnumDeclaration d) { visitEnumDeclaration(d); }
1938 void visit(Nspace d) { visitNspace(d); }
1939 void visit(StructDeclaration d) { visitStructDeclaration(d); }
1940 void visit(ClassDeclaration d) { visitClassDeclaration(d); }
1941 void visit(AliasDeclaration d) { visitAliasDeclaration(d); }
1942 void visit(AliasAssign d) { visitAliasAssign(d); }
1943 void visit(VarDeclaration d) { visitVarDeclaration(d); }
1944 void visit(FuncDeclaration f) { visitFuncDeclaration(f); }
1945 void visit(FuncLiteralDeclaration f) { visitFuncLiteralDeclaration(f); }
1946 void visit(PostBlitDeclaration d) { visitPostBlitDeclaration(d); }
1947 void visit(DtorDeclaration d) { visitDtorDeclaration(d); }
1948 void visit(StaticCtorDeclaration d) { visitStaticCtorDeclaration(d); }
1949 void visit(StaticDtorDeclaration d) { visitStaticDtorDeclaration(d); }
1950 void visit(InvariantDeclaration d) { visitInvariantDeclaration(d); }
1951 void visit(UnitTestDeclaration d) { visitUnitTestDeclaration(d); }
1952 void visit(BitFieldDeclaration d) { visitBitFieldDeclaration(d); }
1953 void visit(NewDeclaration d) { visitNewDeclaration(d); }
1954 void visit(Module m) { visitModule(m); }
1957 scope v = new DsymbolPrettyPrintVisitor();
1958 s.accept(v);
1961 // Note: this function is not actually `const`, because iterating the
1962 // function parameter list may run dsymbolsemantic on enum types
1963 public
1964 void toCharsMaybeConstraints(const TemplateDeclaration td, ref OutBuffer buf, ref HdrGenState hgs)
1966 buf.writestring(td.ident == Id.ctor ? "this" : td.ident.toString());
1967 buf.writeByte('(');
1968 foreach (i, const tp; *td.parameters)
1970 if (i)
1971 buf.writestring(", ");
1972 toCBuffer(tp, buf, hgs);
1974 buf.writeByte(')');
1976 if (td.onemember)
1978 if (const fd = td.onemember.isFuncDeclaration())
1980 if (TypeFunction tf = cast(TypeFunction)fd.type.isTypeFunction())
1982 // !! Casted away const
1983 buf.writestring(parametersTypeToChars(tf.parameterList));
1984 if (tf.mod)
1986 buf.writeByte(' ');
1987 buf.MODtoBuffer(tf.mod);
1993 if (!hgs.skipConstraints &&
1994 td.constraint)
1996 buf.writestring(" if (");
1997 toCBuffer(td.constraint, buf, hgs);
1998 buf.writeByte(')');
2003 /*****************************************
2004 * Pretty-print a template parameter list to a buffer.
2006 private void visitTemplateParameters(TemplateParameters* parameters, ref OutBuffer buf, ref HdrGenState hgs)
2008 if (!parameters)
2009 return;
2010 foreach (i, p; *parameters)
2012 if (i)
2013 buf.writestring(", ");
2014 toCBuffer(p, buf, hgs);
2019 /*******************************************
2020 * Pretty-print a VarDeclaration to buf.
2022 private void visitVarDecl(VarDeclaration v, bool anywritten, ref OutBuffer buf, ref HdrGenState hgs)
2024 const bool isextern = hgs.hdrgen &&
2025 !hgs.insideFuncBody &&
2026 !hgs.tpltMember &&
2027 !hgs.insideAggregate &&
2028 !(v.storage_class & STC.manifest);
2030 void vinit(VarDeclaration v)
2032 auto ie = v._init.isExpInitializer();
2033 if (ie && (ie.exp.op == EXP.construct || ie.exp.op == EXP.blit))
2034 (cast(AssignExp)ie.exp).e2.expressionToBuffer(buf, hgs);
2035 else
2036 v._init.initializerToBuffer(buf, hgs);
2039 const commentIt = hgs.importcHdr && isSpecialCName(v.ident);
2040 if (commentIt)
2041 buf.writestring("/+");
2043 if (anywritten)
2045 buf.writestring(", ");
2046 buf.writestring(v.ident.toString());
2048 else
2050 const bool useTypeof = isextern && v._init && !v.type;
2051 auto stc = v.storage_class;
2052 if (isextern)
2053 stc |= STC.extern_;
2054 if (useTypeof)
2055 stc &= ~STC.auto_;
2056 if (stcToBuffer(buf, stc))
2057 buf.writeByte(' ');
2058 if (v.type)
2059 typeToBuffer(v.type, v.ident, buf, hgs);
2060 else if (useTypeof)
2062 buf.writestring("typeof(");
2063 vinit(v);
2064 buf.writestring(") ");
2065 buf.writestring(v.ident.toString());
2067 else
2068 buf.writestring(v.ident.toString());
2070 if (v._init && !isextern)
2072 buf.writestring(" = ");
2073 vinit(v);
2075 if (commentIt)
2076 buf.writestring("+/");
2079 /*************************************
2080 * The names __DATE__, __TIME__,__EOF__, __VENDOR__, __TIMESTAMP__, __VERSION__
2081 * are special to the D lexer and cannot be used as D source variable names.
2082 * Params:
2083 * id = name to check
2084 * Returns:
2085 * true if special C name
2087 private bool isSpecialCName(Identifier id)
2089 auto s = id.toString();
2090 if (s.length >= 7 && s[0] == '_' && s[1] == '_' &&
2091 (id == Id.DATE ||
2092 id == Id.TIME ||
2093 id == Id.EOFX ||
2094 id == Id.VENDOR ||
2095 id == Id.TIMESTAMP ||
2096 id == Id.VERSIONX))
2097 return true;
2098 return false;
2101 /*********************************************
2102 * Print expression to buffer.
2104 private void expressionPrettyPrint(Expression e, ref OutBuffer buf, ref HdrGenState hgs)
2106 void visit(Expression e)
2108 buf.writestring(EXPtoString(e.op));
2111 void visitInteger(IntegerExp e)
2113 const ulong v = e.toInteger();
2114 if (e.type)
2116 Type t = e.type;
2118 switch (t.ty)
2120 case Tenum:
2122 TypeEnum te = cast(TypeEnum)t;
2123 auto sym = te.sym;
2124 if (sym && sym.members && (!hgs.inEnumDecl || hgs.inEnumDecl != sym))
2126 foreach (em; *sym.members)
2128 if ((cast(EnumMember)em).value.toInteger == v)
2130 const id = em.ident.toString();
2131 buf.printf("%s.%.*s", sym.toChars(), cast(int)id.length, id.ptr);
2132 return ;
2137 buf.printf("cast(%s)", te.sym.toChars());
2138 t = te.sym.memtype;
2139 goto L1;
2141 case Tchar:
2142 case Twchar:
2143 case Tdchar:
2145 const o = buf.length;
2146 writeSingleCharLiteral(buf, cast(dchar) v);
2147 if (hgs.ddoc)
2148 escapeDdocString(buf, o);
2149 break;
2151 case Tint8:
2152 buf.writestring("cast(byte)");
2153 goto L2;
2154 case Tint16:
2155 buf.writestring("cast(short)");
2156 goto L2;
2157 case Tint32:
2159 buf.printf("%d", cast(int)v);
2160 break;
2161 case Tuns8:
2162 buf.writestring("cast(ubyte)");
2163 goto case Tuns32;
2164 case Tuns16:
2165 buf.writestring("cast(ushort)");
2166 goto case Tuns32;
2167 case Tuns32:
2168 buf.printf("%uu", cast(uint)v);
2169 break;
2170 case Tint64:
2171 if (v == long.min)
2173 // https://issues.dlang.org/show_bug.cgi?id=23173
2174 // This is a special case because - is not part of the
2175 // integer literal and 9223372036854775808L overflows a long
2176 buf.writestring("cast(long)-9223372036854775808");
2178 else
2180 buf.printf("%lldL", v);
2182 break;
2183 case Tuns64:
2184 buf.printf("%lluLU", v);
2185 break;
2186 case Tbool:
2187 buf.writestring(v ? "true" : "false");
2188 break;
2189 case Tpointer:
2190 buf.writestring("cast(");
2192 HdrGenState hgs2; // should re-examine need for new hgs
2193 hgs2.fullQual = (t.ty == Tclass && !t.mod);
2194 toCBuffer(t, buf, null, hgs2);
2196 buf.writestring(")cast(size_t)");
2197 goto case Tuns64;
2199 case Tvoid:
2200 buf.writestring("cast(void)0");
2201 break;
2203 default:
2204 /* This can happen if errors, such as
2205 * the type is painted on like in fromConstInitializer().
2206 * Just ignore
2208 break;
2211 else if (v & 0x8000000000000000L)
2212 buf.printf("0x%llx", v);
2213 else
2214 buf.print(v);
2217 void visitError(ErrorExp e)
2219 buf.writestring("__error");
2222 void visitVoidInit(VoidInitExp e)
2224 buf.writestring("void");
2227 void floatToBuffer(Type type, real_t value)
2229 .floatToBuffer(type, value, buf, hgs.hdrgen);
2232 void visitReal(RealExp e)
2234 floatToBuffer(e.type, e.value);
2237 void visitComplex(ComplexExp e)
2239 /* Print as:
2240 * (re+imi)
2242 buf.writeByte('(');
2243 floatToBuffer(e.type, creall(e.value));
2244 buf.writeByte('+');
2245 floatToBuffer(e.type, cimagl(e.value));
2246 buf.writestring("i)");
2249 void visitIdentifier(IdentifierExp e)
2251 if (hgs.hdrgen || hgs.ddoc)
2252 buf.writestring(e.ident.toHChars2());
2253 else
2254 buf.writestring(e.ident.toString());
2257 void visitDsymbol(DsymbolExp e)
2259 buf.writestring(e.s.toChars());
2262 void visitThis(ThisExp e)
2264 buf.writestring("this");
2267 void visitSuper(SuperExp e)
2269 buf.writestring("super");
2272 void visitNull(NullExp e)
2274 buf.writestring("null");
2277 void visitString(StringExp e)
2279 if (e.hexString || e.sz == 8)
2281 buf.writeByte('x');
2282 buf.writeByte('"');
2283 buf.writeHexString(e.peekData, true);
2284 buf.writeByte('"');
2285 if (e.postfix)
2286 buf.writeByte(e.postfix);
2287 return;
2289 buf.writeByte('"');
2290 const o = buf.length;
2291 foreach (i; 0 .. e.len)
2293 writeCharLiteral(buf, e.getCodeUnit(i));
2295 if (hgs.ddoc)
2296 escapeDdocString(buf, o);
2297 buf.writeByte('"');
2298 if (e.postfix)
2299 buf.writeByte(e.postfix);
2302 void visitInterpolation(InterpExp e)
2304 buf.writeByte('i');
2305 buf.writeByte('"');
2306 const o = buf.length;
2308 foreach (idx, str; e.interpolatedSet.parts)
2310 if (idx % 2 == 0)
2312 foreach(ch; str)
2313 writeCharLiteral(buf, ch);
2315 else
2317 buf.writeByte('$');
2318 buf.writeByte('(');
2319 foreach(ch; str)
2320 buf.writeByte(ch);
2321 buf.writeByte(')');
2325 if (hgs.ddoc)
2326 escapeDdocString(buf, o);
2327 buf.writeByte('"');
2328 if (e.postfix)
2329 buf.writeByte(e.postfix);
2333 void visitArrayLiteral(ArrayLiteralExp e)
2335 buf.writeByte('[');
2336 argsToBuffer(e.elements, buf, hgs, e.basis);
2337 buf.writeByte(']');
2340 void visitAssocArrayLiteral(AssocArrayLiteralExp e)
2342 buf.writeByte('[');
2343 foreach (i, key; *e.keys)
2345 if (i)
2346 buf.writestring(", ");
2347 expToBuffer(key, PREC.assign, buf, hgs);
2348 buf.writeByte(':');
2349 auto value = (*e.values)[i];
2350 expToBuffer(value, PREC.assign, buf, hgs);
2352 buf.writeByte(']');
2355 void visitStructLiteral(StructLiteralExp e)
2357 buf.writestring(e.sd.toChars());
2358 buf.writeByte('(');
2359 // CTFE can generate struct literals that contain an AddrExp pointing
2360 // to themselves, need to avoid infinite recursion:
2361 // struct S { this(int){ this.s = &this; } S* s; }
2362 // const foo = new S(0);
2363 if (e.stageflags & stageToCBuffer)
2364 buf.writestring("<recursion>");
2365 else
2367 const old = e.stageflags;
2368 e.stageflags |= stageToCBuffer;
2369 argsToBuffer(e.elements, buf, hgs);
2370 e.stageflags = old;
2372 buf.writeByte(')');
2375 void visitCompoundLiteral(CompoundLiteralExp e)
2377 buf.writeByte('(');
2378 typeToBuffer(e.type, null, buf, hgs);
2379 buf.writeByte(')');
2380 e.initializer.initializerToBuffer(buf, hgs);
2383 void visitType(TypeExp e)
2385 typeToBuffer(e.type, null, buf, hgs);
2388 void visitScope(ScopeExp e)
2390 if (e.sds.isTemplateInstance())
2392 e.sds.dsymbolToBuffer(buf, hgs);
2394 else if (hgs.ddoc)
2396 // fixes bug 6491
2397 if (auto m = e.sds.isModule())
2398 buf.writestring(m.md.toChars());
2399 else
2400 buf.writestring(e.sds.toChars());
2402 else
2404 buf.writestring(e.sds.kind());
2405 buf.writeByte(' ');
2406 buf.writestring(e.sds.toChars());
2410 void visitTemplate(TemplateExp e)
2412 buf.writestring(e.td.toChars());
2415 void visitNew(NewExp e)
2417 if (e.thisexp)
2419 expToBuffer(e.thisexp, PREC.primary, buf, hgs);
2420 buf.writeByte('.');
2422 buf.writestring("new ");
2423 typeToBuffer(e.newtype, null, buf, hgs);
2424 if (e.arguments && e.arguments.length)
2426 buf.writeByte('(');
2427 argsToBuffer(e.arguments, buf, hgs, null, e.names);
2428 buf.writeByte(')');
2432 void visitNewAnonClass(NewAnonClassExp e)
2434 if (e.thisexp)
2436 expToBuffer(e.thisexp, PREC.primary, buf, hgs);
2437 buf.writeByte('.');
2439 buf.writestring("new");
2440 buf.writestring(" class ");
2441 if (e.arguments && e.arguments.length)
2443 buf.writeByte('(');
2444 argsToBuffer(e.arguments, buf, hgs);
2445 buf.writeByte(')');
2447 if (e.cd)
2448 e.cd.dsymbolToBuffer(buf, hgs);
2451 void visitSymOff(SymOffExp e)
2453 if (e.offset)
2454 buf.printf("(& %s%+lld)", e.var.toChars(), e.offset);
2455 else if (e.var.isTypeInfoDeclaration())
2456 buf.writestring(e.var.toChars());
2457 else
2458 buf.printf("& %s", e.var.toChars());
2461 void visitVar(VarExp e)
2463 buf.writestring(e.var.toChars());
2466 void visitOver(OverExp e)
2468 buf.writestring(e.vars.ident.toString());
2471 void visitTuple(TupleExp e)
2473 if (e.e0)
2475 buf.writeByte('(');
2476 e.e0.expressionPrettyPrint(buf, hgs);
2477 buf.writestring(", AliasSeq!(");
2478 argsToBuffer(e.exps, buf, hgs);
2479 buf.writestring("))");
2481 else
2483 buf.writestring("AliasSeq!(");
2484 argsToBuffer(e.exps, buf, hgs);
2485 buf.writeByte(')');
2489 void visitFunc(FuncExp e)
2491 e.fd.dsymbolToBuffer(buf, hgs);
2492 //buf.writestring(e.fd.toChars());
2495 void visitDeclaration(DeclarationExp e)
2497 /* Normal dmd execution won't reach here - regular variable declarations
2498 * are handled in visit(ExpStatement), so here would be used only when
2499 * we'll directly call Expression.toChars() for debugging.
2501 if (e.declaration)
2503 if (auto var = e.declaration.isVarDeclaration())
2505 // For debugging use:
2506 // - Avoid printing newline.
2507 // - Intentionally use the format (Type var;)
2508 // which isn't correct as regular D code.
2509 buf.writeByte('(');
2511 visitVarDecl(var, false, buf, hgs);
2513 buf.writeByte(';');
2514 buf.writeByte(')');
2516 else e.declaration.dsymbolToBuffer(buf, hgs);
2520 void visitTypeid(TypeidExp e)
2522 buf.writestring("typeid(");
2523 objectToBuffer(e.obj, buf, hgs);
2524 buf.writeByte(')');
2527 void visitTraits(TraitsExp e)
2529 buf.writestring("__traits(");
2530 if (e.ident)
2531 buf.writestring(e.ident.toString());
2532 if (e.args)
2534 foreach (arg; *e.args)
2536 buf.writestring(", ");
2537 objectToBuffer(arg, buf, hgs);
2540 buf.writeByte(')');
2543 void visitHalt(HaltExp e)
2545 buf.writestring("halt");
2548 void visitIs(IsExp e)
2550 buf.writestring("is(");
2551 typeToBuffer(e.targ, e.id, buf, hgs);
2552 if (e.tok2 != TOK.reserved)
2554 buf.writeByte(' ');
2555 buf.writestring(Token.toString(e.tok));
2556 buf.writeByte(' ');
2557 buf.writestring(Token.toString(e.tok2));
2559 else if (e.tspec)
2561 if (e.tok == TOK.colon)
2562 buf.writestring(" : ");
2563 else
2564 buf.writestring(" == ");
2565 typeToBuffer(e.tspec, null, buf, hgs);
2567 if (e.parameters && e.parameters.length)
2569 buf.writestring(", ");
2570 visitTemplateParameters(e.parameters, buf, hgs);
2572 buf.writeByte(')');
2575 void visitUna(UnaExp e)
2577 buf.writestring(EXPtoString(e.op));
2578 expToBuffer(e.e1, precedence[e.op], buf, hgs);
2581 void visitLoweredAssignExp(LoweredAssignExp e)
2583 if (hgs.vcg_ast)
2585 expressionToBuffer(e.lowering, buf, hgs);
2586 return;
2589 visit(cast(BinExp)e);
2591 void visitBin(BinExp e)
2593 expToBuffer(e.e1, precedence[e.op], buf, hgs);
2594 buf.writeByte(' ');
2595 buf.writestring(EXPtoString(e.op));
2596 buf.writeByte(' ');
2597 expToBuffer(e.e2, cast(PREC)(precedence[e.op] + 1), buf, hgs);
2600 void visitComma(CommaExp e)
2602 // CommaExp is generated by the compiler so it shouldn't
2603 // appear in error messages or header files.
2604 // For now, this treats the case where the compiler
2605 // generates CommaExp for temporaries by calling
2606 // the `sideeffect.copyToTemp` function.
2607 auto ve = e.e2.isVarExp();
2609 // not a CommaExp introduced for temporaries, go on
2610 // the old path
2611 if (!ve || !(ve.var.storage_class & STC.temp))
2613 visitBin(cast(BinExp)e);
2614 return;
2617 // CommaExp that contain temporaries inserted via
2618 // `copyToTemp` are usually of the form
2619 // ((T __temp = exp), __tmp).
2620 // Asserts are here to easily spot
2621 // missing cases where CommaExp
2622 // are used for other constructs
2623 auto vd = ve.var.isVarDeclaration();
2624 assert(vd && vd._init);
2626 if (auto ei = vd._init.isExpInitializer())
2628 Expression commaExtract;
2629 auto exp = ei.exp;
2630 if (auto ce = exp.isConstructExp())
2631 commaExtract = ce.e2;
2632 else if (auto se = exp.isStructLiteralExp())
2633 commaExtract = se;
2635 if (commaExtract)
2637 expToBuffer(commaExtract, precedence[exp.op], buf, hgs);
2638 return;
2642 // not one of the known cases, go on the old path
2643 visitBin(cast(BinExp)e);
2644 return;
2647 void visitMixin(MixinExp e)
2649 buf.writestring("mixin(");
2650 argsToBuffer(e.exps, buf, hgs, null);
2651 buf.writeByte(')');
2654 void visitImport(ImportExp e)
2656 buf.writestring("import(");
2657 expToBuffer(e.e1, PREC.assign, buf, hgs);
2658 buf.writeByte(')');
2661 void visitAssert(AssertExp e)
2663 buf.writestring("assert(");
2664 expToBuffer(e.e1, PREC.assign, buf, hgs);
2665 if (e.msg)
2667 buf.writestring(", ");
2668 expToBuffer(e.msg, PREC.assign, buf, hgs);
2670 buf.writeByte(')');
2673 void visitThrow(ThrowExp e)
2675 buf.writestring("throw ");
2676 expToBuffer(e.e1, PREC.unary, buf, hgs);
2679 void visitDotId(DotIdExp e)
2681 expToBuffer(e.e1, PREC.primary, buf, hgs);
2682 if (e.arrow)
2683 buf.writestring("->");
2684 else
2685 buf.writeByte('.');
2686 buf.writestring(e.ident.toString());
2689 void visitDotTemplate(DotTemplateExp e)
2691 expToBuffer(e.e1, PREC.primary, buf, hgs);
2692 buf.writeByte('.');
2693 buf.writestring(e.td.toChars());
2696 void visitDotVar(DotVarExp e)
2698 expToBuffer(e.e1, PREC.primary, buf, hgs);
2699 buf.writeByte('.');
2700 buf.writestring(e.var.toChars());
2703 void visitDotTemplateInstance(DotTemplateInstanceExp e)
2705 expToBuffer(e.e1, PREC.primary, buf, hgs);
2706 buf.writeByte('.');
2707 e.ti.dsymbolToBuffer(buf, hgs);
2710 void visitDelegate(DelegateExp e)
2712 buf.writeByte('&');
2713 if (!e.func.isNested() || e.func.needThis())
2715 expToBuffer(e.e1, PREC.primary, buf, hgs);
2716 buf.writeByte('.');
2718 buf.writestring(e.func.toChars());
2721 void visitDotType(DotTypeExp e)
2723 expToBuffer(e.e1, PREC.primary, buf, hgs);
2724 buf.writeByte('.');
2725 buf.writestring(e.sym.toChars());
2728 void visitCall(CallExp e)
2730 if (e.e1.op == EXP.type)
2732 /* Avoid parens around type to prevent forbidden cast syntax:
2733 * (sometype)(arg1)
2734 * This is ok since types in constructor calls
2735 * can never depend on parens anyway
2737 e.e1.expressionPrettyPrint(buf, hgs);
2739 else
2740 expToBuffer(e.e1, precedence[e.op], buf, hgs);
2741 buf.writeByte('(');
2742 argsToBuffer(e.arguments, buf, hgs, null, e.names);
2743 buf.writeByte(')');
2746 void visitPtr(PtrExp e)
2748 buf.writeByte('*');
2749 expToBuffer(e.e1, precedence[e.op], buf, hgs);
2752 void visitDelete(DeleteExp e)
2754 buf.writestring("delete ");
2755 expToBuffer(e.e1, precedence[e.op], buf, hgs);
2758 void visitCast(CastExp e)
2760 buf.writestring("cast(");
2761 if (e.to)
2762 typeToBuffer(e.to, null, buf, hgs);
2763 else
2765 MODtoBuffer(buf, e.mod);
2767 buf.writeByte(')');
2768 expToBuffer(e.e1, precedence[e.op], buf, hgs);
2771 void visitVector(VectorExp e)
2773 buf.writestring("cast(");
2774 typeToBuffer(e.to, null, buf, hgs);
2775 buf.writeByte(')');
2776 expToBuffer(e.e1, precedence[e.op], buf, hgs);
2779 void visitVectorArray(VectorArrayExp e)
2781 expToBuffer(e.e1, PREC.primary, buf, hgs);
2782 buf.writestring(".array");
2785 void visitSlice(SliceExp e)
2787 expToBuffer(e.e1, precedence[e.op], buf, hgs);
2788 buf.writeByte('[');
2789 if (e.upr || e.lwr)
2791 if (e.lwr)
2792 sizeToBuffer(e.lwr, buf, hgs);
2793 else
2794 buf.writeByte('0');
2795 buf.writestring("..");
2796 if (e.upr)
2797 sizeToBuffer(e.upr, buf, hgs);
2798 else
2799 buf.writeByte('$');
2801 buf.writeByte(']');
2804 void visitArrayLength(ArrayLengthExp e)
2806 expToBuffer(e.e1, PREC.primary, buf, hgs);
2807 buf.writestring(".length");
2810 void visitInterval(IntervalExp e)
2812 expToBuffer(e.lwr, PREC.assign, buf, hgs);
2813 buf.writestring("..");
2814 expToBuffer(e.upr, PREC.assign, buf, hgs);
2817 void visitDelegatePtr(DelegatePtrExp e)
2819 expToBuffer(e.e1, PREC.primary, buf, hgs);
2820 buf.writestring(".ptr");
2823 void visitDelegateFuncptr(DelegateFuncptrExp e)
2825 expToBuffer(e.e1, PREC.primary, buf, hgs);
2826 buf.writestring(".funcptr");
2829 void visitArray(ArrayExp e)
2831 expToBuffer(e.e1, PREC.primary, buf, hgs);
2832 buf.writeByte('[');
2833 argsToBuffer(e.arguments, buf, hgs);
2834 buf.writeByte(']');
2837 void visitDot(DotExp e)
2839 expToBuffer(e.e1, PREC.primary, buf, hgs);
2840 buf.writeByte('.');
2841 expToBuffer(e.e2, PREC.primary, buf, hgs);
2844 void visitIndex(IndexExp e)
2846 expToBuffer(e.e1, PREC.primary, buf, hgs);
2847 buf.writeByte('[');
2848 sizeToBuffer(e.e2, buf, hgs);
2849 buf.writeByte(']');
2852 void visitPost(PostExp e)
2854 expToBuffer(e.e1, precedence[e.op], buf, hgs);
2855 buf.writestring(EXPtoString(e.op));
2858 void visitPre(PreExp e)
2860 buf.writestring(EXPtoString(e.op));
2861 expToBuffer(e.e1, precedence[e.op], buf, hgs);
2864 void visitRemove(RemoveExp e)
2866 expToBuffer(e.e1, PREC.primary, buf, hgs);
2867 buf.writestring(".remove(");
2868 expToBuffer(e.e2, PREC.assign, buf, hgs);
2869 buf.writeByte(')');
2872 void visitCond(CondExp e)
2874 expToBuffer(e.econd, PREC.oror, buf, hgs);
2875 buf.writestring(" ? ");
2876 expToBuffer(e.e1, PREC.expr, buf, hgs);
2877 buf.writestring(" : ");
2878 expToBuffer(e.e2, PREC.cond, buf, hgs);
2881 void visitDefaultInit(DefaultInitExp e)
2883 buf.writestring(EXPtoString(e.op));
2886 void visitClassReference(ClassReferenceExp e)
2888 buf.writestring(e.value.toChars());
2891 switch (e.op)
2893 default:
2894 if (auto be = e.isBinExp())
2895 return visitBin(be);
2896 else if (auto ue = e.isUnaExp())
2897 return visitUna(ue);
2898 else if (auto de = e.isDefaultInitExp())
2899 return visitDefaultInit(e.isDefaultInitExp());
2900 return visit(e);
2902 case EXP.int64: return visitInteger(e.isIntegerExp());
2903 case EXP.error: return visitError(e.isErrorExp());
2904 case EXP.void_: return visitVoidInit(e.isVoidInitExp());
2905 case EXP.float64: return visitReal(e.isRealExp());
2906 case EXP.complex80: return visitComplex(e.isComplexExp());
2907 case EXP.identifier: return visitIdentifier(e.isIdentifierExp());
2908 case EXP.dSymbol: return visitDsymbol(e.isDsymbolExp());
2909 case EXP.this_: return visitThis(e.isThisExp());
2910 case EXP.super_: return visitSuper(e.isSuperExp());
2911 case EXP.null_: return visitNull(e.isNullExp());
2912 case EXP.string_: return visitString(e.isStringExp());
2913 case EXP.interpolated: return visitInterpolation(e.isInterpExp());
2914 case EXP.arrayLiteral: return visitArrayLiteral(e.isArrayLiteralExp());
2915 case EXP.assocArrayLiteral: return visitAssocArrayLiteral(e.isAssocArrayLiteralExp());
2916 case EXP.structLiteral: return visitStructLiteral(e.isStructLiteralExp());
2917 case EXP.compoundLiteral: return visitCompoundLiteral(e.isCompoundLiteralExp());
2918 case EXP.type: return visitType(e.isTypeExp());
2919 case EXP.scope_: return visitScope(e.isScopeExp());
2920 case EXP.template_: return visitTemplate(e.isTemplateExp());
2921 case EXP.new_: return visitNew(e.isNewExp());
2922 case EXP.newAnonymousClass: return visitNewAnonClass(e.isNewAnonClassExp());
2923 case EXP.symbolOffset: return visitSymOff(e.isSymOffExp());
2924 case EXP.variable: return visitVar(e.isVarExp());
2925 case EXP.overloadSet: return visitOver(e.isOverExp());
2926 case EXP.tuple: return visitTuple(e.isTupleExp());
2927 case EXP.function_: return visitFunc(e.isFuncExp());
2928 case EXP.declaration: return visitDeclaration(e.isDeclarationExp());
2929 case EXP.typeid_: return visitTypeid(e.isTypeidExp());
2930 case EXP.traits: return visitTraits(e.isTraitsExp());
2931 case EXP.halt: return visitHalt(e.isHaltExp());
2932 case EXP.is_: return visitIs(e.isExp());
2933 case EXP.comma: return visitComma(e.isCommaExp());
2934 case EXP.mixin_: return visitMixin(e.isMixinExp());
2935 case EXP.import_: return visitImport(e.isImportExp());
2936 case EXP.assert_: return visitAssert(e.isAssertExp());
2937 case EXP.throw_: return visitThrow(e.isThrowExp());
2938 case EXP.dotIdentifier: return visitDotId(e.isDotIdExp());
2939 case EXP.dotTemplateDeclaration: return visitDotTemplate(e.isDotTemplateExp());
2940 case EXP.dotVariable: return visitDotVar(e.isDotVarExp());
2941 case EXP.dotTemplateInstance: return visitDotTemplateInstance(e.isDotTemplateInstanceExp());
2942 case EXP.delegate_: return visitDelegate(e.isDelegateExp());
2943 case EXP.dotType: return visitDotType(e.isDotTypeExp());
2944 case EXP.call: return visitCall(e.isCallExp());
2945 case EXP.star: return visitPtr(e.isPtrExp());
2946 case EXP.delete_: return visitDelete(e.isDeleteExp());
2947 case EXP.cast_: return visitCast(e.isCastExp());
2948 case EXP.vector: return visitVector(e.isVectorExp());
2949 case EXP.vectorArray: return visitVectorArray(e.isVectorArrayExp());
2950 case EXP.slice: return visitSlice(e.isSliceExp());
2951 case EXP.arrayLength: return visitArrayLength(e.isArrayLengthExp());
2952 case EXP.interval: return visitInterval(e.isIntervalExp());
2953 case EXP.delegatePointer: return visitDelegatePtr(e.isDelegatePtrExp());
2954 case EXP.delegateFunctionPointer: return visitDelegateFuncptr(e.isDelegateFuncptrExp());
2955 case EXP.array: return visitArray(e.isArrayExp());
2956 case EXP.dot: return visitDot(e.isDotExp());
2957 case EXP.index: return visitIndex(e.isIndexExp());
2958 case EXP.minusMinus:
2959 case EXP.plusPlus: return visitPost(e.isPostExp());
2960 case EXP.preMinusMinus:
2961 case EXP.prePlusPlus: return visitPre(e.isPreExp());
2962 case EXP.remove: return visitRemove(e.isRemoveExp());
2963 case EXP.question: return visitCond(e.isCondExp());
2964 case EXP.classReference: return visitClassReference(e.isClassReferenceExp());
2965 case EXP.loweredAssignExp: return visitLoweredAssignExp(e.isLoweredAssignExp());
2970 * Formats `value` as a literal of type `type` into `buf`.
2972 * Params:
2973 * type = literal type (e.g. Tfloat)
2974 * value = value to print
2975 * buf = target buffer
2976 * allowHex = whether hex floating point literals may be used
2977 * for greater accuracy
2979 void floatToBuffer(Type type, const real_t value, ref OutBuffer buf, const bool allowHex)
2981 /** sizeof(value)*3 is because each byte of mantissa is max
2982 of 256 (3 characters). The string will be "-M.MMMMe-4932".
2983 (ie, 8 chars more than mantissa). Plus one for trailing \0.
2984 Plus one for rounding. */
2985 const(size_t) BUFFER_LEN = value.sizeof * 3 + 8 + 1 + 1;
2986 char[BUFFER_LEN] buffer = void;
2987 CTFloat.sprint(buffer.ptr, BUFFER_LEN, 'g', value);
2988 assert(strlen(buffer.ptr) < BUFFER_LEN);
2989 if (allowHex)
2991 bool isOutOfRange;
2992 real_t r = CTFloat.parse(buffer.ptr, isOutOfRange);
2993 //assert(!isOutOfRange); // test/compilable/test22725.c asserts here
2994 if (r != value) // if exact duplication
2995 CTFloat.sprint(buffer.ptr, BUFFER_LEN, 'a', value);
2997 buf.writestring(buffer.ptr);
2998 if (buffer.ptr[strlen(buffer.ptr) - 1] == '.')
2999 buf.remove(buf.length() - 1, 1);
3001 if (type)
3003 Type t = type.toBasetype();
3004 switch (t.ty)
3006 case Tfloat32:
3007 case Timaginary32:
3008 case Tcomplex32:
3009 buf.writeByte('F');
3010 break;
3011 case Tfloat80:
3012 case Timaginary80:
3013 case Tcomplex80:
3014 buf.writeByte('L');
3015 break;
3016 default:
3017 break;
3019 if (t.isimaginary())
3020 buf.writeByte('i');
3024 void toCBuffer(const TemplateParameter tp, ref OutBuffer buf, ref HdrGenState hgs)
3026 scope v = new TemplateParameterPrettyPrintVisitor(&buf, &hgs);
3027 (cast() tp).accept(v);
3030 private extern (C++) final class TemplateParameterPrettyPrintVisitor : Visitor
3032 alias visit = Visitor.visit;
3033 public:
3034 OutBuffer* buf;
3035 HdrGenState* hgs;
3037 extern (D) this(OutBuffer* buf, HdrGenState* hgs) scope @safe
3039 this.buf = buf;
3040 this.hgs = hgs;
3043 override void visit(TemplateTypeParameter tp)
3045 buf.writestring(tp.ident.toString());
3046 if (tp.specType)
3048 buf.writestring(" : ");
3049 typeToBuffer(tp.specType, null, *buf, *hgs);
3051 if (tp.defaultType)
3053 buf.writestring(" = ");
3054 typeToBuffer(tp.defaultType, null, *buf, *hgs);
3058 override void visit(TemplateThisParameter tp)
3060 buf.writestring("this ");
3061 visit(cast(TemplateTypeParameter)tp);
3064 override void visit(TemplateAliasParameter tp)
3066 buf.writestring("alias ");
3067 if (tp.specType)
3068 typeToBuffer(tp.specType, tp.ident, *buf, *hgs);
3069 else
3070 buf.writestring(tp.ident.toString());
3071 if (tp.specAlias)
3073 buf.writestring(" : ");
3074 objectToBuffer(tp.specAlias, *buf, *hgs);
3076 if (tp.defaultAlias)
3078 buf.writestring(" = ");
3079 objectToBuffer(tp.defaultAlias, *buf, *hgs);
3083 override void visit(TemplateValueParameter tp)
3085 typeToBuffer(tp.valType, tp.ident, *buf, *hgs);
3086 if (tp.specValue)
3088 buf.writestring(" : ");
3089 tp.specValue.expressionToBuffer(*buf, *hgs);
3091 if (tp.defaultValue)
3093 buf.writestring(" = ");
3094 tp.defaultValue.expressionToBuffer(*buf, *hgs);
3098 override void visit(TemplateTupleParameter tp)
3100 buf.writestring(tp.ident.toString());
3101 buf.writestring("...");
3105 private void conditionToBuffer(Condition c, ref OutBuffer buf, ref HdrGenState hgs)
3107 scope v = new ConditionPrettyPrintVisitor(&buf, &hgs);
3108 c.accept(v);
3111 private extern (C++) final class ConditionPrettyPrintVisitor : Visitor
3113 alias visit = Visitor.visit;
3114 public:
3115 OutBuffer* buf;
3116 HdrGenState* hgs;
3118 extern (D) this(OutBuffer* buf, HdrGenState* hgs) scope @safe
3120 this.buf = buf;
3121 this.hgs = hgs;
3124 override void visit(DebugCondition c)
3126 buf.writestring("debug (");
3127 if (c.ident)
3128 buf.writestring(c.ident.toString());
3129 else
3130 buf.print(c.level);
3131 buf.writeByte(')');
3134 override void visit(VersionCondition c)
3136 buf.writestring("version (");
3137 if (c.ident)
3138 buf.writestring(c.ident.toString());
3139 else
3140 buf.print(c.level);
3141 buf.writeByte(')');
3144 override void visit(StaticIfCondition c)
3146 buf.writestring("static if (");
3147 c.exp.expressionToBuffer(*buf, *hgs);
3148 buf.writeByte(')');
3152 void toCBuffer(const Statement s, ref OutBuffer buf, ref HdrGenState hgs)
3154 (cast()s).statementToBuffer(buf, hgs);
3157 void toCBuffer(const Type t, ref OutBuffer buf, const Identifier ident, ref HdrGenState hgs)
3159 typeToBuffer(cast() t, ident, buf, hgs);
3162 // used from TemplateInstance::toChars() and TemplateMixin::toChars()
3163 void toCBufferInstance(const TemplateInstance ti, ref OutBuffer buf, bool qualifyTypes = false)
3165 HdrGenState hgs;
3166 hgs.fullQual = qualifyTypes;
3168 buf.writestring(ti.name.toChars());
3169 tiargsToBuffer(cast() ti, buf, hgs);
3172 void toCBuffer(const Initializer iz, ref OutBuffer buf, ref HdrGenState hgs)
3174 initializerToBuffer(cast() iz, buf, hgs);
3177 bool stcToBuffer(ref OutBuffer buf, StorageClass stc) @safe
3179 //printf("stc: %llx\n", stc);
3180 bool result = false;
3182 if (stc & STC.scopeinferred)
3184 //buf.writestring("scope-inferred ");
3185 stc &= ~(STC.scope_ | STC.scopeinferred);
3187 if (stc & STC.returninferred)
3189 //buf.writestring((stc & STC.returnScope) ? "return-scope-inferred " : "return-ref-inferred ");
3190 stc &= ~(STC.return_ | STC.returninferred);
3193 /* Put scope ref return into a standard order
3195 string rrs;
3196 const isout = (stc & STC.out_) != 0;
3197 //printf("bsr = %d %llx\n", buildScopeRef(stc), stc);
3198 final switch (buildScopeRef(stc))
3200 case ScopeRef.None:
3201 case ScopeRef.Scope:
3202 case ScopeRef.Ref:
3203 case ScopeRef.Return:
3204 break;
3206 case ScopeRef.ReturnScope: rrs = "return scope"; goto L1;
3207 case ScopeRef.ReturnRef: rrs = isout ? "return out" : "return ref"; goto L1;
3208 case ScopeRef.RefScope: rrs = isout ? "out scope" : "ref scope"; goto L1;
3209 case ScopeRef.ReturnRef_Scope: rrs = isout ? "return out scope" : "return ref scope"; goto L1;
3210 case ScopeRef.Ref_ReturnScope: rrs = isout ? "out return scope" : "ref return scope"; goto L1;
3212 buf.writestring(rrs);
3213 result = true;
3214 stc &= ~(STC.out_ | STC.scope_ | STC.ref_ | STC.return_);
3215 break;
3218 while (stc)
3220 const s = stcToString(stc);
3221 if (!s.length)
3222 break;
3223 if (result)
3224 buf.writeByte(' ');
3225 result = true;
3226 buf.writestring(s);
3229 return result;
3232 /*************************************************
3233 * Pick off one of the storage classes from stc,
3234 * and return a string representation of it.
3235 * stc is reduced by the one picked.
3237 string stcToString(ref StorageClass stc) @safe
3239 static struct SCstring
3241 StorageClass stc;
3242 string id;
3245 // Note: The identifier needs to be `\0` terminated
3246 // as some code assumes it (e.g. when printing error messages)
3247 static immutable SCstring[] table =
3249 SCstring(STC.auto_, Token.toString(TOK.auto_)),
3250 SCstring(STC.scope_, Token.toString(TOK.scope_)),
3251 SCstring(STC.static_, Token.toString(TOK.static_)),
3252 SCstring(STC.extern_, Token.toString(TOK.extern_)),
3253 SCstring(STC.const_, Token.toString(TOK.const_)),
3254 SCstring(STC.final_, Token.toString(TOK.final_)),
3255 SCstring(STC.abstract_, Token.toString(TOK.abstract_)),
3256 SCstring(STC.synchronized_, Token.toString(TOK.synchronized_)),
3257 SCstring(STC.deprecated_, Token.toString(TOK.deprecated_)),
3258 SCstring(STC.override_, Token.toString(TOK.override_)),
3259 SCstring(STC.lazy_, Token.toString(TOK.lazy_)),
3260 SCstring(STC.alias_, Token.toString(TOK.alias_)),
3261 SCstring(STC.out_, Token.toString(TOK.out_)),
3262 SCstring(STC.in_, Token.toString(TOK.in_)),
3263 SCstring(STC.manifest, Token.toString(TOK.enum_)),
3264 SCstring(STC.immutable_, Token.toString(TOK.immutable_)),
3265 SCstring(STC.shared_, Token.toString(TOK.shared_)),
3266 SCstring(STC.nothrow_, Token.toString(TOK.nothrow_)),
3267 SCstring(STC.wild, Token.toString(TOK.inout_)),
3268 SCstring(STC.pure_, Token.toString(TOK.pure_)),
3269 SCstring(STC.ref_, Token.toString(TOK.ref_)),
3270 SCstring(STC.return_, Token.toString(TOK.return_)),
3271 SCstring(STC.gshared, Token.toString(TOK.gshared)),
3272 SCstring(STC.nogc, "@nogc"),
3273 SCstring(STC.live, "@live"),
3274 SCstring(STC.property, "@property"),
3275 SCstring(STC.safe, "@safe"),
3276 SCstring(STC.trusted, "@trusted"),
3277 SCstring(STC.system, "@system"),
3278 SCstring(STC.disable, "@disable"),
3279 SCstring(STC.future, "@__future"),
3280 SCstring(STC.local, "__local"),
3282 foreach (ref entry; table)
3284 const StorageClass tbl = entry.stc;
3285 assert(tbl & STC.visibleStorageClasses);
3286 if (stc & tbl)
3288 stc &= ~tbl;
3289 return entry.id;
3292 //printf("stc = %llx\n", stc);
3293 return null;
3296 private void linkageToBuffer(ref OutBuffer buf, LINK linkage) @safe
3298 const s = linkageToString(linkage);
3299 if (s.length)
3301 buf.writestring("extern (");
3302 buf.writestring(s);
3303 buf.writeByte(')');
3307 const(char)* linkageToChars(LINK linkage)
3309 /// Works because we return a literal
3310 return linkageToString(linkage).ptr;
3313 string linkageToString(LINK linkage) pure nothrow @safe
3315 with (LINK)
3317 immutable string[7] a = [
3318 default_ : null,
3319 d : "D",
3320 c : "C",
3321 cpp : "C++",
3322 windows : "Windows",
3323 objc : "Objective-C",
3324 system : "System" ];
3325 return a[linkage];
3329 void visibilityToBuffer(ref OutBuffer buf, Visibility vis)
3331 buf.writestring(visibilityToString(vis.kind));
3332 if (vis.kind == Visibility.Kind.package_ && vis.pkg)
3334 buf.writeByte('(');
3335 buf.writestring(vis.pkg.toPrettyChars(true));
3336 buf.writeByte(')');
3341 * Returns:
3342 * a human readable representation of `kind`
3344 const(char)* visibilityToChars(Visibility.Kind kind)
3346 // Null terminated because we return a literal
3347 return visibilityToString(kind).ptr;
3350 /// Ditto
3351 extern (D) string visibilityToString(Visibility.Kind kind) nothrow pure @safe
3353 with (Visibility.Kind)
3355 immutable string[7] a = [
3356 none : "none",
3357 private_ : "private",
3358 package_ : "package",
3359 protected_ : "protected",
3360 public_ : "public",
3361 export_ : "export" ];
3362 return a[kind];
3366 // Print the full function signature with correct ident, attributes and template args
3367 void functionToBufferFull(TypeFunction tf, ref OutBuffer buf, const Identifier ident, ref HdrGenState hgs, TemplateDeclaration td)
3369 //printf("TypeFunction::toCBuffer() this = %p\n", this);
3370 visitFuncIdentWithPrefix(tf, ident, td, buf, hgs);
3373 // ident is inserted before the argument list and will be "function" or "delegate" for a type
3374 void functionToBufferWithIdent(TypeFunction tf, ref OutBuffer buf, const(char)* ident, bool isStatic)
3376 HdrGenState hgs;
3377 visitFuncIdentWithPostfix(tf, ident.toDString(), buf, hgs, isStatic);
3380 void toCBuffer(const Expression e, ref OutBuffer buf, ref HdrGenState hgs)
3382 expressionPrettyPrint(cast()e, buf, hgs);
3385 /**************************************************
3386 * Write out argument types to buf.
3388 void argExpTypesToCBuffer(ref OutBuffer buf, Expressions* arguments)
3390 if (!arguments || !arguments.length)
3391 return;
3392 HdrGenState hgs;
3393 foreach (i, arg; *arguments)
3395 if (i)
3396 buf.writestring(", ");
3397 typeToBuffer(arg.type, null, buf, hgs);
3401 void arrayObjectsToBuffer(ref OutBuffer buf, Objects* objects)
3403 if (!objects || !objects.length)
3404 return;
3405 HdrGenState hgs;
3406 foreach (i, o; *objects)
3408 if (i)
3409 buf.writestring(", ");
3410 objectToBuffer(o, buf, hgs);
3414 /*************************************************************
3415 * Pretty print function parameters.
3416 * Params:
3417 * pl = parameter list to print
3418 * Returns: Null-terminated string representing parameters.
3420 extern (C++) const(char)* parametersTypeToChars(ParameterList pl)
3422 OutBuffer buf;
3423 HdrGenState hgs;
3424 parametersToBuffer(pl, buf, hgs);
3425 return buf.extractChars();
3428 /*************************************************************
3429 * Pretty print function parameter.
3430 * Params:
3431 * parameter = parameter to print.
3432 * tf = TypeFunction which holds parameter.
3433 * fullQual = whether to fully qualify types.
3434 * Returns: Null-terminated string representing parameters.
3436 const(char)* parameterToChars(Parameter parameter, TypeFunction tf, bool fullQual)
3438 OutBuffer buf;
3439 HdrGenState hgs;
3440 hgs.fullQual = fullQual;
3442 parameterToBuffer(parameter, buf, hgs);
3444 if (tf.parameterList.varargs == VarArg.typesafe && parameter == tf.parameterList[tf.parameterList.parameters.length - 1])
3446 buf.writestring("...");
3448 return buf.extractChars();
3452 /*************************************************
3453 * Write ParameterList to buffer.
3454 * Params:
3455 * pl = parameter list to serialize
3456 * buf = buffer to write it to
3457 * hgs = context
3460 private void parametersToBuffer(ParameterList pl, ref OutBuffer buf, ref HdrGenState hgs)
3462 buf.writeByte('(');
3463 foreach (i; 0 .. pl.length)
3465 if (i)
3466 buf.writestring(", ");
3467 pl[i].parameterToBuffer(buf, hgs);
3469 final switch (pl.varargs)
3471 case VarArg.none:
3472 case VarArg.KRvariadic:
3473 break;
3475 case VarArg.variadic:
3476 if (pl.length)
3477 buf.writestring(", ");
3479 if (stcToBuffer(buf, pl.stc))
3480 buf.writeByte(' ');
3481 goto case VarArg.typesafe;
3483 case VarArg.typesafe:
3484 buf.writestring("...");
3485 break;
3487 buf.writeByte(')');
3491 /***********************************************************
3492 * Write parameter `p` to buffer `buf`.
3493 * Params:
3494 * p = parameter to serialize
3495 * buf = buffer to write it to
3496 * hgs = context
3498 private void parameterToBuffer(Parameter p, ref OutBuffer buf, ref HdrGenState hgs)
3500 if (p.userAttribDecl)
3502 buf.writeByte('@');
3504 bool isAnonymous = p.userAttribDecl.atts.length > 0 && !(*p.userAttribDecl.atts)[0].isCallExp();
3505 if (isAnonymous)
3506 buf.writeByte('(');
3508 argsToBuffer(p.userAttribDecl.atts, buf, hgs);
3510 if (isAnonymous)
3511 buf.writeByte(')');
3512 buf.writeByte(' ');
3514 if (p.storageClass & STC.auto_)
3515 buf.writestring("auto ");
3517 StorageClass stc = p.storageClass;
3518 if (p.storageClass & STC.in_)
3520 buf.writestring("in ");
3521 if ((p.storageClass & (STC.constscoperef | STC.ref_)) == (STC.constscoperef | STC.ref_))
3522 stc &= ~STC.ref_;
3524 else if (p.storageClass & STC.lazy_)
3525 buf.writestring("lazy ");
3526 else if (p.storageClass & STC.alias_)
3527 buf.writestring("alias ");
3529 if (p.type && p.type.mod & MODFlags.shared_)
3530 stc &= ~STC.shared_;
3532 if (stcToBuffer(buf, stc & (STC.const_ | STC.immutable_ | STC.wild | STC.shared_ |
3533 STC.return_ | STC.returninferred | STC.scope_ | STC.scopeinferred | STC.out_ | STC.ref_ | STC.returnScope)))
3534 buf.writeByte(' ');
3536 const(char)[] s;
3537 if (p.storageClass & STC.alias_)
3539 if (p.ident)
3540 buf.writestring(p.ident.toString());
3542 else if (p.type.isTypeIdentifier() &&
3543 (s = p.type.isTypeIdentifier().ident.toString()).length > 3 &&
3544 s[0..3] == "__T")
3546 // print parameter name, instead of undetermined type parameter
3547 buf.writestring(p.ident.toString());
3549 else
3551 typeToBuffer(p.type, p.ident, buf, hgs, (stc & STC.in_) ? MODFlags.const_ : 0);
3554 if (p.defaultArg)
3556 buf.writestring(" = ");
3557 p.defaultArg.expToBuffer(PREC.assign, buf, hgs);
3562 /**************************************************
3563 * Write out argument list to buf.
3564 * Params:
3565 * expressions = argument list
3566 * buf = buffer to write to
3567 * hgs = context
3568 * basis = replace `null`s in argument list with this expression (for sparse array literals)
3569 * names = if non-null, use these as the names for the arguments
3571 private void argsToBuffer(Expressions* expressions, ref OutBuffer buf, ref HdrGenState hgs, Expression basis = null, Identifiers* names = null)
3573 if (!expressions || !expressions.length)
3574 return;
3575 version (all)
3577 foreach (i, el; *expressions)
3579 if (i)
3580 buf.writestring(", ");
3582 if (names && i < names.length && (*names)[i])
3584 buf.writestring((*names)[i].toString());
3585 buf.writestring(": ");
3587 if (!el)
3588 el = basis;
3589 if (el)
3590 expToBuffer(el, PREC.assign, buf, hgs);
3593 else
3595 // Sparse style formatting, for debug use only
3596 // [0..length: basis, 1: e1, 5: e5]
3597 if (basis)
3599 buf.writestring("0..");
3600 buf.print(expressions.length);
3601 buf.writestring(": ");
3602 expToBuffer(basis, PREC.assign, buf, hgs);
3604 foreach (i, el; *expressions)
3606 if (el)
3608 if (basis)
3610 buf.writestring(", ");
3611 buf.print(i);
3612 buf.writestring(": ");
3614 else if (i)
3615 buf.writestring(", ");
3616 expToBuffer(el, PREC.assign, buf, hgs);
3622 private void sizeToBuffer(Expression e, ref OutBuffer buf, ref HdrGenState hgs)
3624 if (e.type == Type.tsize_t)
3626 Expression ex = (e.op == EXP.cast_ ? (cast(CastExp)e).e1 : e);
3627 ex = ex.optimize(WANTvalue);
3628 const ulong uval = ex.op == EXP.int64 ? ex.toInteger() : cast(ulong)-1;
3629 if (cast(long)uval >= 0)
3631 if (uval <= 0xFFFFU)
3633 buf.print(uval);
3634 return;
3636 if (uval <= 0x7FFF_FFFF_FFFF_FFFFUL)
3638 buf.writestring("cast(size_t)");
3639 buf.print(uval);
3640 return;
3644 expToBuffer(e, PREC.assign, buf, hgs);
3647 private void expressionToBuffer(Expression e, ref OutBuffer buf, ref HdrGenState hgs)
3649 expressionPrettyPrint(e, buf, hgs);
3652 /**************************************************
3653 * Write expression out to buf, but wrap it
3654 * in ( ) if its precedence is less than pr.
3656 private void expToBuffer(Expression e, PREC pr, ref OutBuffer buf, ref HdrGenState hgs)
3658 debug
3660 if (precedence[e.op] == PREC.zero)
3661 printf("precedence not defined for token '%s'\n", EXPtoString(e.op).ptr);
3663 if (e.op == 0xFF)
3665 buf.writestring("<FF>");
3666 return;
3668 assert(precedence[e.op] != PREC.zero);
3669 assert(pr != PREC.zero);
3670 /* Despite precedence, we don't allow a<b<c expressions.
3671 * They must be parenthesized.
3673 if (precedence[e.op] < pr || (pr == PREC.rel && precedence[e.op] == pr)
3674 || (pr >= PREC.or && pr <= PREC.and && precedence[e.op] == PREC.rel))
3676 buf.writeByte('(');
3677 e.expressionToBuffer(buf, hgs);
3678 buf.writeByte(')');
3680 else
3682 e.expressionToBuffer(buf, hgs);
3687 /**************************************************
3688 * An entry point to pretty-print type.
3690 private void typeToBuffer(Type t, const Identifier ident, ref OutBuffer buf, ref HdrGenState hgs,
3691 ubyte modMask = 0)
3693 if (auto tf = t.isTypeFunction())
3695 visitFuncIdentWithPrefix(tf, ident, null, buf, hgs);
3696 return;
3698 visitWithMask(t, modMask, buf, hgs);
3699 if (ident)
3701 buf.writeByte(' ');
3702 buf.writestring(ident.toString());
3706 private void visitWithMask(Type t, ubyte modMask, ref OutBuffer buf, ref HdrGenState hgs)
3708 // Tuples and functions don't use the type constructor syntax
3709 if (modMask == t.mod || t.ty == Tfunction || t.ty == Ttuple)
3711 typeToBufferx(t, buf, hgs);
3713 else
3715 ubyte m = t.mod & ~(t.mod & modMask);
3716 if (m & MODFlags.shared_)
3718 MODtoBuffer(buf, MODFlags.shared_);
3719 buf.writeByte('(');
3721 if (m & MODFlags.wild)
3723 MODtoBuffer(buf, MODFlags.wild);
3724 buf.writeByte('(');
3726 if (m & (MODFlags.const_ | MODFlags.immutable_))
3728 MODtoBuffer(buf, m & (MODFlags.const_ | MODFlags.immutable_));
3729 buf.writeByte('(');
3731 typeToBufferx(t, buf, hgs);
3732 if (m & (MODFlags.const_ | MODFlags.immutable_))
3733 buf.writeByte(')');
3734 if (m & MODFlags.wild)
3735 buf.writeByte(')');
3736 if (m & MODFlags.shared_)
3737 buf.writeByte(')');
3742 private void dumpTemplateInstance(TemplateInstance ti, ref OutBuffer buf, ref HdrGenState hgs)
3744 buf.writeByte('{');
3745 buf.writenl();
3746 buf.level++;
3748 if (ti.aliasdecl)
3750 ti.aliasdecl.dsymbolToBuffer(buf, hgs);
3751 buf.writenl();
3753 else if (ti.members)
3755 foreach(m;*ti.members)
3756 m.dsymbolToBuffer(buf, hgs);
3759 buf.level--;
3760 buf.writeByte('}');
3761 buf.writenl();
3765 private void tiargsToBuffer(TemplateInstance ti, ref OutBuffer buf, ref HdrGenState hgs)
3767 buf.writeByte('!');
3768 if (ti.nest)
3770 buf.writestring("(...)");
3771 return;
3773 if (!ti.tiargs)
3775 buf.writestring("()");
3776 return;
3778 if (ti.tiargs.length == 1)
3780 RootObject oarg = (*ti.tiargs)[0];
3781 if (Type t = isType(oarg))
3783 if (t.equals(Type.tstring) || t.equals(Type.twstring) || t.equals(Type.tdstring) || t.mod == 0 && (t.isTypeBasic() || t.ty == Tident && (cast(TypeIdentifier)t).idents.length == 0))
3785 HdrGenState hgs2; // re-examine need for new hgs
3786 hgs2.fullQual = (t.ty == Tclass && !t.mod);
3787 toCBuffer(t, buf, null, hgs2);
3788 return;
3791 else if (Expression e = isExpression(oarg))
3793 if (e.op == EXP.int64 || e.op == EXP.float64 || e.op == EXP.null_ || e.op == EXP.string_ || e.op == EXP.this_)
3795 toCBuffer(e, buf, hgs);
3796 return;
3800 buf.writeByte('(');
3801 ti.nestUp();
3802 foreach (i, arg; *ti.tiargs)
3804 if (i)
3805 buf.writestring(", ");
3806 objectToBuffer(arg, buf, hgs);
3808 ti.nestDown();
3809 buf.writeByte(')');
3812 /****************************************
3813 * This makes a 'pretty' version of the template arguments.
3814 * It's analogous to genIdent() which makes a mangled version.
3816 private void objectToBuffer(RootObject oarg, ref OutBuffer buf, ref HdrGenState hgs)
3818 //printf("objectToBuffer()\n");
3819 /* The logic of this should match what genIdent() does. The _dynamic_cast()
3820 * function relies on all the pretty strings to be unique for different classes
3821 * See https://issues.dlang.org/show_bug.cgi?id=7375
3822 * Perhaps it would be better to demangle what genIdent() does.
3824 if (auto t = isType(oarg))
3826 //printf("\tt: %s ty = %d\n", t.toChars(), t.ty);
3827 typeToBuffer(t, null, buf, hgs);
3829 else if (auto e = isExpression(oarg))
3831 if (e.op == EXP.variable)
3832 e = e.optimize(WANTvalue); // added to fix https://issues.dlang.org/show_bug.cgi?id=7375
3833 expToBuffer(e, PREC.assign, buf, hgs);
3835 else if (Dsymbol s = isDsymbol(oarg))
3837 if (s.ident)
3838 buf.writestring(s.ident.toString());
3839 else
3840 buf.writestring(s.toChars());
3842 else if (auto v = isTuple(oarg))
3844 auto args = &v.objects;
3845 foreach (i, arg; *args)
3847 if (i)
3848 buf.writestring(", ");
3849 objectToBuffer(arg, buf, hgs);
3852 else if (auto p = isParameter(oarg))
3854 parameterToBuffer(p, buf, hgs);
3856 else if (!oarg)
3858 buf.writestring("NULL");
3860 else
3862 debug
3864 printf("bad Object = %p\n", oarg);
3866 assert(0);
3871 private void visitFuncIdentWithPostfix(TypeFunction t, const char[] ident, ref OutBuffer buf, ref HdrGenState hgs, bool isStatic)
3873 if (t.inuse)
3875 t.inuse = 2; // flag error to caller
3876 return;
3878 t.inuse++;
3879 if (t.linkage > LINK.d && hgs.ddoc != 1 && !hgs.hdrgen)
3881 linkageToBuffer(buf, t.linkage);
3882 buf.writeByte(' ');
3884 if (t.linkage == LINK.objc && isStatic)
3885 buf.write("static ");
3886 if (t.next)
3888 typeToBuffer(t.next, null, buf, hgs);
3889 if (ident)
3890 buf.writeByte(' ');
3892 else if (hgs.ddoc)
3893 buf.writestring("auto ");
3894 if (ident)
3895 buf.writestring(ident);
3896 parametersToBuffer(t.parameterList, buf, hgs);
3897 /* Use postfix style for attributes
3899 if (t.mod)
3901 buf.writeByte(' ');
3902 MODtoBuffer(buf, t.mod);
3905 void dg(string str)
3907 buf.writeByte(' ');
3908 buf.writestring(str);
3910 t.attributesApply(&dg);
3912 t.inuse--;
3915 private void visitFuncIdentWithPrefix(TypeFunction t, const Identifier ident, TemplateDeclaration td,
3916 ref OutBuffer buf, ref HdrGenState hgs)
3918 if (t.inuse)
3920 t.inuse = 2; // flag error to caller
3921 return;
3923 t.inuse++;
3925 /* Use 'storage class' (prefix) style for attributes
3927 if (t.mod)
3929 MODtoBuffer(buf, t.mod);
3930 buf.writeByte(' ');
3933 void ignoreReturn(string str)
3935 if (str != "return")
3937 // don't write 'ref' for ctors
3938 if ((ident == Id.ctor) && str == "ref")
3939 return;
3940 buf.writestring(str);
3941 buf.writeByte(' ');
3944 t.attributesApply(&ignoreReturn);
3946 if (t.linkage > LINK.d && hgs.ddoc != 1 && !hgs.hdrgen)
3948 linkageToBuffer(buf, t.linkage);
3949 buf.writeByte(' ');
3951 if (ident && ident.toHChars2() != ident.toChars())
3953 // Don't print return type for ctor, dtor, unittest, etc
3955 else if (t.next)
3957 typeToBuffer(t.next, null, buf, hgs);
3958 if (ident)
3959 buf.writeByte(' ');
3961 else if (hgs.ddoc)
3962 buf.writestring("auto ");
3963 if (ident)
3964 buf.writestring(ident.toHChars2());
3965 if (td)
3967 buf.writeByte('(');
3968 foreach (i, p; *td.origParameters)
3970 if (i)
3971 buf.writestring(", ");
3972 toCBuffer(p, buf, hgs);
3974 buf.writeByte(')');
3976 parametersToBuffer(t.parameterList, buf, hgs);
3977 if (t.isreturn)
3979 buf.writestring(" return");
3981 t.inuse--;
3985 private void initializerToBuffer(Initializer inx, ref OutBuffer buf, ref HdrGenState hgs)
3987 void visitError(ErrorInitializer iz)
3989 buf.writestring("__error__");
3992 void visitVoid(VoidInitializer iz)
3994 buf.writestring("void");
3997 void visitDefault(DefaultInitializer iz)
3999 buf.writestring("{ }");
4002 void visitStruct(StructInitializer si)
4004 //printf("StructInitializer::toCBuffer()\n");
4005 buf.writeByte('{');
4006 foreach (i, const id; si.field)
4008 if (i)
4009 buf.writestring(", ");
4010 if (id)
4012 buf.writestring(id.toString());
4013 buf.writeByte(':');
4015 if (auto iz = si.value[i])
4016 initializerToBuffer(iz, buf, hgs);
4018 buf.writeByte('}');
4021 void visitArray(ArrayInitializer ai)
4023 buf.writeByte('[');
4024 foreach (i, ex; ai.index)
4026 if (i)
4027 buf.writestring(", ");
4028 if (ex)
4030 ex.expressionToBuffer(buf, hgs);
4031 buf.writeByte(':');
4033 if (auto iz = ai.value[i])
4034 initializerToBuffer(iz, buf, hgs);
4036 buf.writeByte(']');
4039 void visitExp(ExpInitializer ei)
4041 ei.exp.expressionToBuffer(buf, hgs);
4044 void visitC(CInitializer ci)
4046 buf.writeByte('{');
4047 foreach (i, ref DesigInit di; ci.initializerList)
4049 if (i)
4050 buf.writestring(", ");
4051 if (di.designatorList)
4053 foreach (ref Designator d; (*di.designatorList)[])
4055 if (d.exp)
4057 buf.writeByte('[');
4058 toCBuffer(d.exp, buf, hgs);
4059 buf.writeByte(']');
4061 else
4063 buf.writeByte('.');
4064 buf.writestring(d.ident.toString());
4067 buf.writeByte('=');
4069 initializerToBuffer(di.initializer, buf, hgs);
4071 buf.writeByte('}');
4074 mixin VisitInitializer!void visit;
4075 visit.VisitInitializer(inx);
4079 private void typeToBufferx(Type t, ref OutBuffer buf, ref HdrGenState hgs)
4081 void visitType(Type t)
4083 printf("t = %p, ty = %d\n", t, t.ty);
4084 assert(0);
4087 void visitError(TypeError t)
4089 buf.writestring("_error_");
4092 void visitBasic(TypeBasic t)
4094 //printf("TypeBasic::toCBuffer2(t.mod = %d)\n", t.mod);
4095 buf.writestring(t.dstring);
4098 void visitTraits(TypeTraits t)
4100 //printf("TypeBasic::toCBuffer2(t.mod = %d)\n", t.mod);
4101 t.exp.expressionToBuffer(buf, hgs);
4104 void visitVector(TypeVector t)
4106 //printf("TypeVector::toCBuffer2(t.mod = %d)\n", t.mod);
4107 buf.writestring("__vector(");
4108 visitWithMask(t.basetype, t.mod, buf, hgs);
4109 buf.writestring(")");
4112 void visitSArray(TypeSArray t)
4114 visitWithMask(t.next, t.mod, buf, hgs);
4115 buf.writeByte('[');
4116 sizeToBuffer(t.dim, buf, hgs);
4117 buf.writeByte(']');
4120 void visitDArray(TypeDArray t)
4122 Type ut = t.castMod(0);
4123 if (hgs.declstring)
4124 goto L1;
4125 if (ut.equals(Type.tstring))
4126 buf.writestring("string");
4127 else if (ut.equals(Type.twstring))
4128 buf.writestring("wstring");
4129 else if (ut.equals(Type.tdstring))
4130 buf.writestring("dstring");
4131 else
4134 visitWithMask(t.next, t.mod, buf, hgs);
4135 buf.writestring("[]");
4139 void visitAArray(TypeAArray t)
4141 visitWithMask(t.next, t.mod, buf, hgs);
4142 buf.writeByte('[');
4143 visitWithMask(t.index, 0, buf, hgs);
4144 buf.writeByte(']');
4147 void visitPointer(TypePointer t)
4149 //printf("TypePointer::toCBuffer2() next = %d\n", t.next.ty);
4150 if (t.next.ty == Tfunction)
4151 visitFuncIdentWithPostfix(cast(TypeFunction)t.next, "function", buf, hgs, false);
4152 else
4154 visitWithMask(t.next, t.mod, buf, hgs);
4155 buf.writeByte('*');
4159 void visitReference(TypeReference t)
4161 visitWithMask(t.next, t.mod, buf, hgs);
4162 buf.writeByte('&');
4165 void visitFunction(TypeFunction t)
4167 //printf("TypeFunction::toCBuffer2() t = %p, ref = %d\n", t, t.isref);
4168 visitFuncIdentWithPostfix(t, null, buf, hgs, false);
4171 void visitDelegate(TypeDelegate t)
4173 visitFuncIdentWithPostfix(cast(TypeFunction)t.next, "delegate", buf, hgs, false);
4176 void visitTypeQualifiedHelper(TypeQualified t)
4178 foreach (id; t.idents)
4180 switch (id.dyncast()) with (DYNCAST)
4182 case dsymbol:
4183 buf.writeByte('.');
4184 TemplateInstance ti = cast(TemplateInstance)id;
4185 ti.dsymbolToBuffer(buf, hgs);
4186 break;
4187 case expression:
4188 buf.writeByte('[');
4189 (cast(Expression)id).expressionToBuffer(buf, hgs);
4190 buf.writeByte(']');
4191 break;
4192 case type:
4193 buf.writeByte('[');
4194 typeToBufferx(cast(Type)id, buf, hgs);
4195 buf.writeByte(']');
4196 break;
4197 default:
4198 buf.writeByte('.');
4199 buf.writestring(id.toString());
4204 void visitIdentifier(TypeIdentifier t)
4206 //printf("visitTypeIdentifier() %s\n", t.ident.toChars());
4207 buf.writestring(t.ident.toString());
4208 visitTypeQualifiedHelper(t);
4211 void visitInstance(TypeInstance t)
4213 t.tempinst.dsymbolToBuffer(buf, hgs);
4214 visitTypeQualifiedHelper(t);
4217 void visitTypeof(TypeTypeof t)
4219 buf.writestring("typeof(");
4220 t.exp.expressionToBuffer(buf, hgs);
4221 buf.writeByte(')');
4222 visitTypeQualifiedHelper(t);
4225 void visitReturn(TypeReturn t)
4227 buf.writestring("typeof(return)");
4228 visitTypeQualifiedHelper(t);
4231 void visitEnum(TypeEnum t)
4233 //printf("visitEnum: %s\n", t.sym.toChars());
4234 buf.writestring(hgs.fullQual ? t.sym.toPrettyChars() : t.sym.toChars());
4237 void visitStruct(TypeStruct t)
4239 //printf("visitTypeStruct() %s\n", t.sym.toChars());
4241 // https://issues.dlang.org/show_bug.cgi?id=13776
4242 // Don't use ti.toAlias() to avoid forward reference error
4243 // while printing messages.
4244 TemplateInstance ti = t.sym.parent ? t.sym.parent.isTemplateInstance() : null;
4245 if (ti && ti.aliasdecl == t.sym)
4246 buf.writestring(hgs.fullQual ? ti.toPrettyChars() : ti.toChars());
4247 else
4248 buf.writestring(hgs.fullQual ? t.sym.toPrettyChars() : t.sym.toChars());
4251 void visitClass(TypeClass t)
4253 // https://issues.dlang.org/show_bug.cgi?id=13776
4254 // Don't use ti.toAlias() to avoid forward reference error
4255 // while printing messages.
4256 TemplateInstance ti = t.sym.parent ? t.sym.parent.isTemplateInstance() : null;
4257 if (ti && ti.aliasdecl == t.sym)
4258 buf.writestring(hgs.fullQual ? ti.toPrettyChars() : ti.toChars());
4259 else
4260 buf.writestring(hgs.fullQual ? t.sym.toPrettyChars() : t.sym.toChars());
4263 void visitTag(TypeTag t)
4265 if (t.mod & MODFlags.const_)
4266 buf.writestring("const ");
4267 if (hgs.importcHdr && t.id)
4269 buf.writestring(t.id.toString());
4270 return;
4272 buf.writestring(Token.toString(t.tok));
4273 buf.writeByte(' ');
4274 if (t.id)
4275 buf.writestring(t.id.toString());
4276 if (t.tok == TOK.enum_ && t.base && t.base.ty != TY.Tint32)
4278 buf.writestring(" : ");
4279 visitWithMask(t.base, t.mod, buf, hgs);
4283 void visitTuple(TypeTuple t)
4285 parametersToBuffer(ParameterList(t.arguments, VarArg.none), buf, hgs);
4288 void visitSlice(TypeSlice t)
4290 visitWithMask(t.next, t.mod, buf, hgs);
4291 buf.writeByte('[');
4292 sizeToBuffer(t.lwr, buf, hgs);
4293 buf.writestring(" .. ");
4294 sizeToBuffer(t.upr, buf, hgs);
4295 buf.writeByte(']');
4298 void visitNull(TypeNull t)
4300 buf.writestring("typeof(null)");
4303 void visitMixin(TypeMixin t)
4305 buf.writestring("mixin(");
4306 argsToBuffer(t.exps, buf, hgs, null);
4307 buf.writeByte(')');
4310 void visitNoreturn(TypeNoreturn t)
4312 buf.writestring("noreturn");
4316 switch (t.ty)
4318 default: return t.isTypeBasic() ?
4319 visitBasic(cast(TypeBasic)t) :
4320 visitType(t);
4322 case Terror: return visitError(cast(TypeError)t);
4323 case Ttraits: return visitTraits(cast(TypeTraits)t);
4324 case Tvector: return visitVector(cast(TypeVector)t);
4325 case Tsarray: return visitSArray(cast(TypeSArray)t);
4326 case Tarray: return visitDArray(cast(TypeDArray)t);
4327 case Taarray: return visitAArray(cast(TypeAArray)t);
4328 case Tpointer: return visitPointer(cast(TypePointer)t);
4329 case Treference: return visitReference(cast(TypeReference)t);
4330 case Tfunction: return visitFunction(cast(TypeFunction)t);
4331 case Tdelegate: return visitDelegate(cast(TypeDelegate)t);
4332 case Tident: return visitIdentifier(cast(TypeIdentifier)t);
4333 case Tinstance: return visitInstance(cast(TypeInstance)t);
4334 case Ttypeof: return visitTypeof(cast(TypeTypeof)t);
4335 case Treturn: return visitReturn(cast(TypeReturn)t);
4336 case Tenum: return visitEnum(cast(TypeEnum)t);
4337 case Tstruct: return visitStruct(cast(TypeStruct)t);
4338 case Tclass: return visitClass(cast(TypeClass)t);
4339 case Ttuple: return visitTuple (cast(TypeTuple)t);
4340 case Tslice: return visitSlice(cast(TypeSlice)t);
4341 case Tnull: return visitNull(cast(TypeNull)t);
4342 case Tmixin: return visitMixin(cast(TypeMixin)t);
4343 case Tnoreturn: return visitNoreturn(cast(TypeNoreturn)t);
4344 case Ttag: return visitTag(cast(TypeTag)t);
4348 /****************************************
4349 * Convert EXP to char*.
4352 string EXPtoString(EXP op)
4354 static immutable char*[EXP.max + 1] strings =
4356 EXP.type : "type",
4357 EXP.error : "error",
4358 EXP.objcClassReference : "class",
4360 EXP.mixin_ : "mixin",
4362 EXP.import_ : "import",
4363 EXP.dotVariable : "dotvar",
4364 EXP.scope_ : "scope",
4365 EXP.identifier : "identifier",
4366 EXP.this_ : "this",
4367 EXP.super_ : "super",
4368 EXP.int64 : "long",
4369 EXP.float64 : "double",
4370 EXP.complex80 : "creal",
4371 EXP.null_ : "null",
4372 EXP.string_ : "string",
4373 EXP.arrayLiteral : "arrayliteral",
4374 EXP.assocArrayLiteral : "assocarrayliteral",
4375 EXP.classReference : "classreference",
4376 EXP.file : "__FILE__",
4377 EXP.fileFullPath : "__FILE_FULL_PATH__",
4378 EXP.line : "__LINE__",
4379 EXP.moduleString : "__MODULE__",
4380 EXP.functionString : "__FUNCTION__",
4381 EXP.prettyFunction : "__PRETTY_FUNCTION__",
4382 EXP.typeid_ : "typeid",
4383 EXP.is_ : "is",
4384 EXP.assert_ : "assert",
4385 EXP.halt : "halt",
4386 EXP.template_ : "template",
4387 EXP.dSymbol : "symbol",
4388 EXP.function_ : "function",
4389 EXP.variable : "var",
4390 EXP.symbolOffset : "symoff",
4391 EXP.structLiteral : "structLiteral",
4392 EXP.compoundLiteral : "compoundliteral",
4393 EXP.arrayLength : "arraylength",
4394 EXP.delegatePointer : "delegateptr",
4395 EXP.delegateFunctionPointer : "delegatefuncptr",
4396 EXP.remove : "remove",
4397 EXP.tuple : "sequence",
4398 EXP.traits : "__traits",
4399 EXP.overloadSet : "__overloadset",
4400 EXP.void_ : "void",
4401 EXP.vectorArray : "vectorarray",
4402 EXP._Generic : "_Generic",
4404 // post
4405 EXP.dotTemplateInstance : "dotti",
4406 EXP.dotIdentifier : "dotid",
4407 EXP.dotTemplateDeclaration : "dottd",
4408 EXP.dot : ".",
4409 EXP.dotType : "dottype",
4410 EXP.plusPlus : "++",
4411 EXP.minusMinus : "--",
4412 EXP.prePlusPlus : "++",
4413 EXP.preMinusMinus : "--",
4414 EXP.call : "call",
4415 EXP.slice : "..",
4416 EXP.array : "[]",
4417 EXP.index : "[i]",
4419 EXP.delegate_ : "delegate",
4420 EXP.address : "&",
4421 EXP.star : "*",
4422 EXP.negate : "-",
4423 EXP.uadd : "+",
4424 EXP.not : "!",
4425 EXP.tilde : "~",
4426 EXP.delete_ : "delete",
4427 EXP.new_ : "new",
4428 EXP.newAnonymousClass : "newanonclass",
4429 EXP.cast_ : "cast",
4431 EXP.vector : "__vector",
4432 EXP.pow : "^^",
4434 EXP.mul : "*",
4435 EXP.div : "/",
4436 EXP.mod : "%",
4438 EXP.add : "+",
4439 EXP.min : "-",
4440 EXP.concatenate : "~",
4442 EXP.leftShift : "<<",
4443 EXP.rightShift : ">>",
4444 EXP.unsignedRightShift : ">>>",
4446 EXP.lessThan : "<",
4447 EXP.lessOrEqual : "<=",
4448 EXP.greaterThan : ">",
4449 EXP.greaterOrEqual : ">=",
4450 EXP.in_ : "in",
4452 EXP.equal : "==",
4453 EXP.notEqual : "!=",
4454 EXP.identity : "is",
4455 EXP.notIdentity : "!is",
4457 EXP.and : "&",
4458 EXP.xor : "^",
4459 EXP.or : "|",
4461 EXP.andAnd : "&&",
4462 EXP.orOr : "||",
4464 EXP.question : "?",
4466 EXP.assign : "=",
4467 EXP.construct : "=",
4468 EXP.blit : "=",
4469 EXP.addAssign : "+=",
4470 EXP.minAssign : "-=",
4471 EXP.concatenateAssign : "~=",
4472 EXP.concatenateElemAssign : "~=",
4473 EXP.concatenateDcharAssign : "~=",
4474 EXP.mulAssign : "*=",
4475 EXP.divAssign : "/=",
4476 EXP.modAssign : "%=",
4477 EXP.powAssign : "^^=",
4478 EXP.leftShiftAssign : "<<=",
4479 EXP.rightShiftAssign : ">>=",
4480 EXP.unsignedRightShiftAssign : ">>>=",
4481 EXP.andAssign : "&=",
4482 EXP.orAssign : "|=",
4483 EXP.xorAssign : "^=",
4485 EXP.comma : ",",
4486 EXP.declaration : "declaration",
4488 EXP.interval : "interval",
4489 EXP.loweredAssignExp : "="
4491 const p = strings[op];
4492 if (!p)
4494 printf("error: EXP %d has no string\n", op);
4495 return "XXXXX";
4496 //assert(0);
4498 assert(p);
4499 return p[0 .. strlen(p)];