d: Merge upstream dmd, druntime 4c18eed967, phobos d945686a4.
[official-gcc.git] / gcc / d / dmd / hdrgen.d
blob056e486e927ad9ed68f512da5f554c28bb2795a7
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-2023 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.globals;
39 import dmd.id;
40 import dmd.identifier;
41 import dmd.init;
42 import dmd.mtype;
43 import dmd.nspace;
44 import dmd.parse;
45 import dmd.root.complex;
46 import dmd.root.ctfloat;
47 import dmd.common.outbuffer;
48 import dmd.root.rootobject;
49 import dmd.root.string;
50 import dmd.statement;
51 import dmd.staticassert;
52 import dmd.target;
53 import dmd.tokens;
54 import dmd.visitor;
56 struct HdrGenState
58 bool hdrgen; /// true if generating header file
59 bool ddoc; /// true if generating Ddoc file
60 bool fullDump; /// true if generating a full AST dump file
62 bool fullQual; /// fully qualify types when printing
63 int tpltMember;
64 int autoMember;
65 int forStmtInit;
66 int insideFuncBody;
67 int insideAggregate;
69 bool declstring; // set while declaring alias for string,wstring or dstring
70 EnumDeclaration inEnumDecl;
73 enum TEST_EMIT_ALL = 0;
75 /****************************************
76 * Generate a header (.di) file for Module m.
77 * Params:
78 * m = Module to generate header for
79 * buf = buffer to write the data to
81 extern (C++) void genhdrfile(Module m, ref OutBuffer buf)
83 buf.doindent = 1;
84 buf.printf("// D import file generated from '%s'", m.srcfile.toChars());
85 buf.writenl();
86 HdrGenState hgs;
87 hgs.hdrgen = true;
88 toCBuffer(m, buf, hgs);
91 /***************************************
92 * Turn a Statement into a string suitable for printf.
93 * Leaks memory.
94 * Params:
95 * s = Statement to convert
96 * Returns:
97 * 0-terminated string
99 public extern (C++) const(char)* toChars(const Statement s)
101 HdrGenState hgs;
102 OutBuffer buf;
103 toCBuffer(s, buf, hgs);
104 buf.writeByte(0);
105 return buf.extractSlice().ptr;
108 public extern (C++) const(char)* toChars(const Initializer i)
110 OutBuffer buf;
111 HdrGenState hgs;
112 toCBuffer(i, buf, hgs);
113 return buf.extractChars();
116 public const(char)[] toString(const Initializer i)
118 OutBuffer buf;
119 HdrGenState hgs;
120 toCBuffer(i, buf, hgs);
121 return buf.extractSlice();
125 * Dumps the full contents of module `m` to `buf`.
126 * Params:
127 * buf = buffer to write to.
128 * m = module to visit all members of.
130 extern (C++) void moduleToBuffer(ref OutBuffer buf, Module m)
132 HdrGenState hgs;
133 hgs.fullDump = true;
134 toCBuffer(m, buf, hgs);
137 void moduleToBuffer2(Module m, ref OutBuffer buf, HdrGenState* hgs)
139 if (m.md)
141 if (m.userAttribDecl)
143 buf.writestring("@(");
144 argsToBuffer(m.userAttribDecl.atts, buf, hgs);
145 buf.writeByte(')');
146 buf.writenl();
148 if (m.md.isdeprecated)
150 if (m.md.msg)
152 buf.writestring("deprecated(");
153 m.md.msg.expressionToBuffer(buf, hgs);
154 buf.writestring(") ");
156 else
157 buf.writestring("deprecated ");
159 buf.writestring("module ");
160 buf.writestring(m.md.toChars());
161 buf.writeByte(';');
162 buf.writenl();
165 foreach (s; *m.members)
167 s.dsymbolToBuffer(buf, hgs);
171 private void statementToBuffer(Statement s, ref OutBuffer buf, HdrGenState* hgs)
173 void visitDefaultCase(Statement s)
175 printf("Statement::toCBuffer() %d\n", s.stmt);
176 assert(0, "unrecognized statement in statementToBuffer()");
179 void visitError(ErrorStatement s)
181 buf.writestring("__error__");
182 buf.writenl();
185 void visitExp(ExpStatement s)
187 if (s.exp && s.exp.op == EXP.declaration &&
188 (cast(DeclarationExp)s.exp).declaration)
190 // bypass visit(DeclarationExp)
191 (cast(DeclarationExp)s.exp).declaration.dsymbolToBuffer(buf, hgs);
192 return;
194 if (s.exp)
195 s.exp.expressionToBuffer(buf, hgs);
196 buf.writeByte(';');
197 if (!hgs.forStmtInit)
198 buf.writenl();
201 void visitDtorExp(DtorExpStatement s)
203 visitExp(s);
206 void visitMixin(MixinStatement s)
208 buf.writestring("mixin(");
209 argsToBuffer(s.exps, buf, hgs, null);
210 buf.writestring(");");
211 if (!hgs.forStmtInit)
212 buf.writenl();
215 void visitCompound(CompoundStatement s)
217 foreach (sx; *s.statements)
219 if (sx)
220 sx.statementToBuffer(buf, hgs);
224 void visitCompoundAsm(CompoundAsmStatement s)
226 visitCompound(s);
229 void visitCompoundDeclaration(CompoundDeclarationStatement s)
231 bool anywritten = false;
232 foreach (sx; *s.statements)
234 auto ds = sx ? sx.isExpStatement() : null;
235 if (ds && ds.exp.isDeclarationExp())
237 auto d = ds.exp.isDeclarationExp().declaration;
238 if (auto v = d.isVarDeclaration())
240 visitVarDecl(v, anywritten, buf, *hgs);
242 else
243 d.dsymbolToBuffer(buf, hgs);
244 anywritten = true;
247 buf.writeByte(';');
248 if (!hgs.forStmtInit)
249 buf.writenl();
252 void visitUnrolledLoop(UnrolledLoopStatement s)
254 buf.writestring("/*unrolled*/ {");
255 buf.writenl();
256 buf.level++;
257 foreach (sx; *s.statements)
259 if (sx)
260 sx.statementToBuffer(buf, hgs);
262 buf.level--;
263 buf.writeByte('}');
264 buf.writenl();
267 void visitScope(ScopeStatement s)
269 buf.writeByte('{');
270 buf.writenl();
271 buf.level++;
272 if (s.statement)
273 s.statement.statementToBuffer(buf, hgs);
274 buf.level--;
275 buf.writeByte('}');
276 buf.writenl();
279 void visitWhile(WhileStatement s)
281 buf.writestring("while (");
282 if (auto p = s.param)
284 // Print condition assignment
285 StorageClass stc = p.storageClass;
286 if (!p.type && !stc)
287 stc = STC.auto_;
288 if (stcToBuffer(buf, stc))
289 buf.writeByte(' ');
290 if (p.type)
291 typeToBuffer(p.type, p.ident, buf, hgs);
292 else
293 buf.writestring(p.ident.toString());
294 buf.writestring(" = ");
296 s.condition.expressionToBuffer(buf, hgs);
297 buf.writeByte(')');
298 buf.writenl();
299 if (s._body)
300 s._body.statementToBuffer(buf, hgs);
303 void visitDo(DoStatement s)
305 buf.writestring("do");
306 buf.writenl();
307 if (s._body)
308 s._body.statementToBuffer(buf, hgs);
309 buf.writestring("while (");
310 s.condition.expressionToBuffer(buf, hgs);
311 buf.writestring(");");
312 buf.writenl();
315 void visitFor(ForStatement s)
317 buf.writestring("for (");
318 if (s._init)
320 hgs.forStmtInit++;
321 s._init.statementToBuffer(buf, hgs);
322 hgs.forStmtInit--;
324 else
325 buf.writeByte(';');
326 if (s.condition)
328 buf.writeByte(' ');
329 s.condition.expressionToBuffer(buf, hgs);
331 buf.writeByte(';');
332 if (s.increment)
334 buf.writeByte(' ');
335 s.increment.expressionToBuffer(buf, hgs);
337 buf.writeByte(')');
338 buf.writenl();
339 buf.writeByte('{');
340 buf.writenl();
341 buf.level++;
342 if (s._body)
343 s._body.statementToBuffer(buf, hgs);
344 buf.level--;
345 buf.writeByte('}');
346 buf.writenl();
349 void foreachWithoutBody(ForeachStatement s)
351 buf.writestring(Token.toString(s.op));
352 buf.writestring(" (");
353 foreach (i, p; *s.parameters)
355 if (i)
356 buf.writestring(", ");
357 if (stcToBuffer(buf, p.storageClass))
358 buf.writeByte(' ');
359 if (p.type)
360 typeToBuffer(p.type, p.ident, buf, hgs);
361 else
362 buf.writestring(p.ident.toString());
364 buf.writestring("; ");
365 s.aggr.expressionToBuffer(buf, hgs);
366 buf.writeByte(')');
367 buf.writenl();
370 void visitForeach(ForeachStatement s)
372 foreachWithoutBody(s);
373 buf.writeByte('{');
374 buf.writenl();
375 buf.level++;
376 if (s._body)
377 s._body.statementToBuffer(buf, hgs);
378 buf.level--;
379 buf.writeByte('}');
380 buf.writenl();
383 void foreachRangeWithoutBody(ForeachRangeStatement s)
385 buf.writestring(Token.toString(s.op));
386 buf.writestring(" (");
387 if (s.prm.type)
388 typeToBuffer(s.prm.type, s.prm.ident, buf, hgs);
389 else
390 buf.writestring(s.prm.ident.toString());
391 buf.writestring("; ");
392 s.lwr.expressionToBuffer(buf, hgs);
393 buf.writestring(" .. ");
394 s.upr.expressionToBuffer(buf, hgs);
395 buf.writeByte(')');
396 buf.writenl();
399 void visitForeachRange(ForeachRangeStatement s)
401 foreachRangeWithoutBody(s);
402 buf.writeByte('{');
403 buf.writenl();
404 buf.level++;
405 if (s._body)
406 s._body.statementToBuffer(buf, hgs);
407 buf.level--;
408 buf.writeByte('}');
409 buf.writenl();
412 void visitStaticForeach(StaticForeachStatement s)
414 buf.writestring("static ");
415 if (s.sfe.aggrfe)
417 visitForeach(s.sfe.aggrfe);
419 else
421 assert(s.sfe.rangefe);
422 visitForeachRange(s.sfe.rangefe);
426 void visitForwarding(ForwardingStatement s)
428 s.statement.statementToBuffer(buf, hgs);
431 void visitIf(IfStatement s)
433 buf.writestring("if (");
434 if (Parameter p = s.prm)
436 StorageClass stc = p.storageClass;
437 if (!p.type && !stc)
438 stc = STC.auto_;
439 if (stcToBuffer(buf, stc))
440 buf.writeByte(' ');
441 if (p.type)
442 typeToBuffer(p.type, p.ident, buf, hgs);
443 else
444 buf.writestring(p.ident.toString());
445 buf.writestring(" = ");
447 s.condition.expressionToBuffer(buf, hgs);
448 buf.writeByte(')');
449 buf.writenl();
450 if (s.ifbody.isScopeStatement())
452 s.ifbody.statementToBuffer(buf, hgs);
454 else
456 buf.level++;
457 s.ifbody.statementToBuffer(buf, hgs);
458 buf.level--;
460 if (s.elsebody)
462 buf.writestring("else");
463 if (!s.elsebody.isIfStatement())
465 buf.writenl();
467 else
469 buf.writeByte(' ');
471 if (s.elsebody.isScopeStatement() || s.elsebody.isIfStatement())
473 s.elsebody.statementToBuffer(buf, hgs);
475 else
477 buf.level++;
478 s.elsebody.statementToBuffer(buf, hgs);
479 buf.level--;
484 void visitConditional(ConditionalStatement s)
486 s.condition.conditionToBuffer(buf, hgs);
487 buf.writenl();
488 buf.writeByte('{');
489 buf.writenl();
490 buf.level++;
491 if (s.ifbody)
492 s.ifbody.statementToBuffer(buf, hgs);
493 buf.level--;
494 buf.writeByte('}');
495 buf.writenl();
496 if (s.elsebody)
498 buf.writestring("else");
499 buf.writenl();
500 buf.writeByte('{');
501 buf.level++;
502 buf.writenl();
503 s.elsebody.statementToBuffer(buf, hgs);
504 buf.level--;
505 buf.writeByte('}');
507 buf.writenl();
510 void visitPragma(PragmaStatement s)
512 buf.writestring("pragma (");
513 buf.writestring(s.ident.toString());
514 if (s.args && s.args.length)
516 buf.writestring(", ");
517 argsToBuffer(s.args, buf, hgs);
519 buf.writeByte(')');
520 if (s._body)
522 buf.writenl();
523 buf.writeByte('{');
524 buf.writenl();
525 buf.level++;
526 s._body.statementToBuffer(buf, hgs);
527 buf.level--;
528 buf.writeByte('}');
529 buf.writenl();
531 else
533 buf.writeByte(';');
534 buf.writenl();
538 void visitStaticAssert(StaticAssertStatement s)
540 s.sa.dsymbolToBuffer(buf, hgs);
543 void visitSwitch(SwitchStatement s)
545 buf.writestring(s.isFinal ? "final switch (" : "switch (");
546 if (auto p = s.param)
548 // Print condition assignment
549 StorageClass stc = p.storageClass;
550 if (!p.type && !stc)
551 stc = STC.auto_;
552 if (stcToBuffer(buf, stc))
553 buf.writeByte(' ');
554 if (p.type)
555 typeToBuffer(p.type, p.ident, buf, hgs);
556 else
557 buf.writestring(p.ident.toString());
558 buf.writestring(" = ");
560 s.condition.expressionToBuffer(buf, hgs);
561 buf.writeByte(')');
562 buf.writenl();
563 if (s._body)
565 if (!s._body.isScopeStatement())
567 buf.writeByte('{');
568 buf.writenl();
569 buf.level++;
570 s._body.statementToBuffer(buf, hgs);
571 buf.level--;
572 buf.writeByte('}');
573 buf.writenl();
575 else
577 s._body.statementToBuffer(buf, hgs);
582 void visitCase(CaseStatement s)
584 buf.writestring("case ");
585 s.exp.expressionToBuffer(buf, hgs);
586 buf.writeByte(':');
587 buf.writenl();
588 s.statement.statementToBuffer(buf, hgs);
591 void visitCaseRange(CaseRangeStatement s)
593 buf.writestring("case ");
594 s.first.expressionToBuffer(buf, hgs);
595 buf.writestring(": .. case ");
596 s.last.expressionToBuffer(buf, hgs);
597 buf.writeByte(':');
598 buf.writenl();
599 s.statement.statementToBuffer(buf, hgs);
602 void visitDefault(DefaultStatement s)
604 buf.writestring("default:");
605 buf.writenl();
606 s.statement.statementToBuffer(buf, hgs);
609 void visitGotoDefault(GotoDefaultStatement s)
611 buf.writestring("goto default;");
612 buf.writenl();
615 void visitGotoCase(GotoCaseStatement s)
617 buf.writestring("goto case");
618 if (s.exp)
620 buf.writeByte(' ');
621 s.exp.expressionToBuffer(buf, hgs);
623 buf.writeByte(';');
624 buf.writenl();
627 void visitSwitchError(SwitchErrorStatement s)
629 buf.writestring("SwitchErrorStatement::toCBuffer()");
630 buf.writenl();
633 void visitReturn(ReturnStatement s)
635 buf.writestring("return ");
636 if (s.exp)
637 s.exp.expressionToBuffer(buf, hgs);
638 buf.writeByte(';');
639 buf.writenl();
642 void visitBreak(BreakStatement s)
644 buf.writestring("break");
645 if (s.ident)
647 buf.writeByte(' ');
648 buf.writestring(s.ident.toString());
650 buf.writeByte(';');
651 buf.writenl();
654 void visitContinue(ContinueStatement s)
656 buf.writestring("continue");
657 if (s.ident)
659 buf.writeByte(' ');
660 buf.writestring(s.ident.toString());
662 buf.writeByte(';');
663 buf.writenl();
666 void visitSynchronized(SynchronizedStatement s)
668 buf.writestring("synchronized");
669 if (s.exp)
671 buf.writeByte('(');
672 s.exp.expressionToBuffer(buf, hgs);
673 buf.writeByte(')');
675 if (s._body)
677 buf.writeByte(' ');
678 s._body.statementToBuffer(buf, hgs);
682 void visitWith(WithStatement s)
684 buf.writestring("with (");
685 s.exp.expressionToBuffer(buf, hgs);
686 buf.writestring(")");
687 buf.writenl();
688 if (s._body)
689 s._body.statementToBuffer(buf, hgs);
692 void visitTryCatch(TryCatchStatement s)
694 buf.writestring("try");
695 buf.writenl();
696 if (s._body)
698 if (s._body.isScopeStatement())
700 s._body.statementToBuffer(buf, hgs);
702 else
704 buf.level++;
705 s._body.statementToBuffer(buf, hgs);
706 buf.level--;
709 foreach (c; *s.catches)
711 buf.writestring("catch");
712 if (c.type)
714 buf.writeByte('(');
715 typeToBuffer(c.type, c.ident, buf, hgs);
716 buf.writeByte(')');
718 buf.writenl();
719 buf.writeByte('{');
720 buf.writenl();
721 buf.level++;
722 if (c.handler)
723 c.handler.statementToBuffer(buf, hgs);
724 buf.level--;
725 buf.writeByte('}');
726 buf.writenl();
730 void visitTryFinally(TryFinallyStatement s)
732 buf.writestring("try");
733 buf.writenl();
734 buf.writeByte('{');
735 buf.writenl();
736 buf.level++;
737 s._body.statementToBuffer(buf, hgs);
738 buf.level--;
739 buf.writeByte('}');
740 buf.writenl();
741 buf.writestring("finally");
742 buf.writenl();
743 if (s.finalbody.isScopeStatement())
745 s.finalbody.statementToBuffer(buf, hgs);
747 else
749 buf.level++;
750 s.finalbody.statementToBuffer(buf, hgs);
751 buf.level--;
755 void visitScopeGuard(ScopeGuardStatement s)
757 buf.writestring(Token.toString(s.tok));
758 buf.writeByte(' ');
759 if (s.statement)
760 s.statement.statementToBuffer(buf, hgs);
763 void visitThrow(ThrowStatement s)
765 buf.writestring("throw ");
766 s.exp.expressionToBuffer(buf, hgs);
767 buf.writeByte(';');
768 buf.writenl();
771 void visitDebug(DebugStatement s)
773 if (s.statement)
775 s.statement.statementToBuffer(buf, hgs);
779 void visitGoto(GotoStatement s)
781 buf.writestring("goto ");
782 buf.writestring(s.ident.toString());
783 buf.writeByte(';');
784 buf.writenl();
787 void visitLabel(LabelStatement s)
789 buf.writestring(s.ident.toString());
790 buf.writeByte(':');
791 buf.writenl();
792 if (s.statement)
793 s.statement.statementToBuffer(buf, hgs);
796 void visitAsm(AsmStatement s)
798 buf.writestring("asm { ");
799 Token* t = s.tokens;
800 buf.level++;
801 while (t)
803 buf.writestring(t.toChars());
804 if (t.next &&
805 t.value != TOK.min &&
806 t.value != TOK.comma && t.next.value != TOK.comma &&
807 t.value != TOK.leftBracket && t.next.value != TOK.leftBracket &&
808 t.next.value != TOK.rightBracket &&
809 t.value != TOK.leftParenthesis && t.next.value != TOK.leftParenthesis &&
810 t.next.value != TOK.rightParenthesis &&
811 t.value != TOK.dot && t.next.value != TOK.dot)
813 buf.writeByte(' ');
815 t = t.next;
817 buf.level--;
818 buf.writestring("; }");
819 buf.writenl();
822 void visitInlineAsm(InlineAsmStatement s)
824 visitAsm(s);
827 void visitGccAsm(GccAsmStatement s)
829 visitAsm(s);
832 void visitImport(ImportStatement s)
834 foreach (imp; *s.imports)
836 imp.dsymbolToBuffer(buf, hgs);
840 mixin VisitStatement!void visit;
841 visit.VisitStatement(s);
844 private void dsymbolToBuffer(Dsymbol s, ref OutBuffer buf, HdrGenState* hgs)
846 toCBuffer(s, buf, *hgs);
849 void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs)
851 void visitDsymbol(Dsymbol s)
853 buf.writestring(s.toChars());
856 void visitStaticAssert(StaticAssert s)
858 buf.writestring(s.kind());
859 buf.writeByte('(');
860 s.exp.expressionToBuffer(buf, &hgs);
861 if (s.msgs)
863 foreach (m; (*s.msgs)[])
865 buf.writestring(", ");
866 m.expressionToBuffer(buf, &hgs);
869 buf.writestring(");");
870 buf.writenl();
873 void visitDebugSymbol(DebugSymbol s)
875 buf.writestring("debug = ");
876 if (s.ident)
877 buf.writestring(s.ident.toString());
878 else
879 buf.print(s.level);
880 buf.writeByte(';');
881 buf.writenl();
884 void visitVersionSymbol(VersionSymbol s)
886 buf.writestring("version = ");
887 if (s.ident)
888 buf.writestring(s.ident.toString());
889 else
890 buf.print(s.level);
891 buf.writeByte(';');
892 buf.writenl();
895 void visitEnumMember(EnumMember em)
897 if (em.type)
898 typeToBuffer(em.type, em.ident, buf, &hgs);
899 else
900 buf.writestring(em.ident.toString());
901 if (em.value)
903 buf.writestring(" = ");
904 em.value.expressionToBuffer(buf, &hgs);
908 void visitImport(Import imp)
910 if (hgs.hdrgen && imp.id == Id.object)
911 return; // object is imported by default
912 if (imp.isstatic)
913 buf.writestring("static ");
914 buf.writestring("import ");
915 if (imp.aliasId)
917 buf.printf("%s = ", imp.aliasId.toChars());
919 foreach (const pid; imp.packages)
921 buf.printf("%s.", pid.toChars());
923 buf.writestring(imp.id.toString());
924 if (imp.names.length)
926 buf.writestring(" : ");
927 foreach (const i, const name; imp.names)
929 if (i)
930 buf.writestring(", ");
931 const _alias = imp.aliases[i];
932 if (_alias)
933 buf.printf("%s = %s", _alias.toChars(), name.toChars());
934 else
935 buf.writestring(name.toChars());
938 buf.writeByte(';');
939 buf.writenl();
942 void visitAliasThis(AliasThis d)
944 buf.writestring("alias ");
945 buf.writestring(d.ident.toString());
946 buf.writestring(" this;\n");
949 void visitAttribDeclaration(AttribDeclaration d)
951 bool hasSTC;
952 if (auto stcd = d.isStorageClassDeclaration)
954 hasSTC = stcToBuffer(buf, stcd.stc);
957 if (!d.decl)
959 buf.writeByte(';');
960 buf.writenl();
961 return;
963 if (d.decl.length == 0 || (hgs.hdrgen && d.decl.length == 1 && (*d.decl)[0].isUnitTestDeclaration()))
965 // hack for https://issues.dlang.org/show_bug.cgi?id=8081
966 if (hasSTC) buf.writeByte(' ');
967 buf.writestring("{}");
969 else if (d.decl.length == 1)
971 if (hasSTC) buf.writeByte(' ');
972 toCBuffer((*d.decl)[0], buf, hgs);
973 return;
975 else
977 buf.writenl();
978 buf.writeByte('{');
979 buf.writenl();
980 buf.level++;
981 foreach (de; *d.decl)
982 toCBuffer(de, buf, hgs);
983 buf.level--;
984 buf.writeByte('}');
986 buf.writenl();
989 void visitStorageClassDeclaration(StorageClassDeclaration d)
991 visitAttribDeclaration(d);
994 void visitDeprecatedDeclaration(DeprecatedDeclaration d)
996 buf.writestring("deprecated(");
997 d.msg.expressionToBuffer(buf, &hgs);
998 buf.writestring(") ");
999 visitAttribDeclaration(d);
1002 void visitLinkDeclaration(LinkDeclaration d)
1004 buf.writestring("extern (");
1005 buf.writestring(linkageToString(d.linkage));
1006 buf.writestring(") ");
1007 visitAttribDeclaration(d);
1010 void visitCPPMangleDeclaration(CPPMangleDeclaration d)
1012 string s;
1013 final switch (d.cppmangle)
1015 case CPPMANGLE.asClass:
1016 s = "class";
1017 break;
1018 case CPPMANGLE.asStruct:
1019 s = "struct";
1020 break;
1021 case CPPMANGLE.def:
1022 break;
1024 buf.writestring("extern (C++, ");
1025 buf.writestring(s);
1026 buf.writestring(") ");
1027 visitAttribDeclaration(d);
1030 void visitVisibilityDeclaration(VisibilityDeclaration d)
1032 visibilityToBuffer(buf, d.visibility);
1033 AttribDeclaration ad = cast(AttribDeclaration)d;
1034 if (ad.decl.length <= 1)
1035 buf.writeByte(' ');
1036 if (ad.decl.length == 1 && (*ad.decl)[0].isVisibilityDeclaration)
1037 visitAttribDeclaration((*ad.decl)[0].isVisibilityDeclaration);
1038 else
1039 visitAttribDeclaration(d);
1042 void visitAlignDeclaration(AlignDeclaration d)
1044 if (d.exps)
1046 foreach (i, exp; (*d.exps)[])
1048 if (i)
1049 buf.writeByte(' ');
1050 buf.printf("align (%s)", exp.toChars());
1052 if (d.decl && d.decl.length < 2)
1053 buf.writeByte(' ');
1055 else
1056 buf.writestring("align ");
1058 visitAttribDeclaration(d.isAttribDeclaration());
1061 void visitAnonDeclaration(AnonDeclaration d)
1063 buf.writestring(d.isunion ? "union" : "struct");
1064 buf.writenl();
1065 buf.writestring("{");
1066 buf.writenl();
1067 buf.level++;
1068 if (d.decl)
1070 foreach (de; *d.decl)
1071 toCBuffer(de, buf, hgs);
1073 buf.level--;
1074 buf.writestring("}");
1075 buf.writenl();
1078 void visitPragmaDeclaration(PragmaDeclaration d)
1080 buf.writestring("pragma (");
1081 buf.writestring(d.ident.toString());
1082 if (d.args && d.args.length)
1084 buf.writestring(", ");
1085 argsToBuffer(d.args, buf, &hgs);
1088 buf.writeByte(')');
1090 // https://issues.dlang.org/show_bug.cgi?id=14690
1091 // Unconditionally perform a full output dump
1092 // for `pragma(inline)` declarations.
1093 bool savedFullDump = global.params.dihdr.fullOutput;
1094 if (d.ident == Id.Pinline)
1095 global.params.dihdr.fullOutput = true;
1097 visitAttribDeclaration(d);
1098 global.params.dihdr.fullOutput = savedFullDump;
1101 void visitConditionalDeclaration(ConditionalDeclaration d)
1103 d.condition.conditionToBuffer(buf, &hgs);
1104 if (d.decl || d.elsedecl)
1106 buf.writenl();
1107 buf.writeByte('{');
1108 buf.writenl();
1109 buf.level++;
1110 if (d.decl)
1112 foreach (de; *d.decl)
1113 toCBuffer(de, buf, hgs);
1115 buf.level--;
1116 buf.writeByte('}');
1117 if (d.elsedecl)
1119 buf.writenl();
1120 buf.writestring("else");
1121 buf.writenl();
1122 buf.writeByte('{');
1123 buf.writenl();
1124 buf.level++;
1125 foreach (de; *d.elsedecl)
1126 toCBuffer(de, buf, hgs);
1127 buf.level--;
1128 buf.writeByte('}');
1131 else
1132 buf.writeByte(':');
1133 buf.writenl();
1136 void visitStaticForeachDeclaration(StaticForeachDeclaration s)
1138 void foreachWithoutBody(ForeachStatement s)
1140 buf.writestring(Token.toString(s.op));
1141 buf.writestring(" (");
1142 foreach (i, p; *s.parameters)
1144 if (i)
1145 buf.writestring(", ");
1146 if (stcToBuffer(buf, p.storageClass))
1147 buf.writeByte(' ');
1148 if (p.type)
1149 typeToBuffer(p.type, p.ident, buf, &hgs);
1150 else
1151 buf.writestring(p.ident.toString());
1153 buf.writestring("; ");
1154 s.aggr.expressionToBuffer(buf, &hgs);
1155 buf.writeByte(')');
1156 buf.writenl();
1159 void foreachRangeWithoutBody(ForeachRangeStatement s)
1161 /* s.op ( prm ; lwr .. upr )
1163 buf.writestring(Token.toString(s.op));
1164 buf.writestring(" (");
1165 if (s.prm.type)
1166 typeToBuffer(s.prm.type, s.prm.ident, buf, &hgs);
1167 else
1168 buf.writestring(s.prm.ident.toString());
1169 buf.writestring("; ");
1170 s.lwr.expressionToBuffer(buf, &hgs);
1171 buf.writestring(" .. ");
1172 s.upr.expressionToBuffer(buf, &hgs);
1173 buf.writeByte(')');
1174 buf.writenl();
1177 buf.writestring("static ");
1178 if (s.sfe.aggrfe)
1180 foreachWithoutBody(s.sfe.aggrfe);
1182 else
1184 assert(s.sfe.rangefe);
1185 foreachRangeWithoutBody(s.sfe.rangefe);
1187 buf.writeByte('{');
1188 buf.writenl();
1189 buf.level++;
1190 visitAttribDeclaration(s);
1191 buf.level--;
1192 buf.writeByte('}');
1193 buf.writenl();
1197 void visitMixinDeclaration(MixinDeclaration d)
1199 buf.writestring("mixin(");
1200 argsToBuffer(d.exps, buf, &hgs, null);
1201 buf.writestring(");");
1202 buf.writenl();
1205 void visitUserAttributeDeclaration(UserAttributeDeclaration d)
1207 buf.writestring("@(");
1208 argsToBuffer(d.atts, buf, &hgs);
1209 buf.writeByte(')');
1210 visitAttribDeclaration(d);
1213 void visitTemplateConstraint(Expression constraint)
1215 if (!constraint)
1216 return;
1217 buf.writestring(" if (");
1218 constraint.expressionToBuffer(buf, &hgs);
1219 buf.writeByte(')');
1222 /// Returns: whether `do` is needed to write the function body
1223 bool contractsToBuffer(FuncDeclaration f)
1225 bool requireDo = false;
1226 // in{}
1227 if (f.frequires)
1229 foreach (frequire; *f.frequires)
1231 buf.writestring("in");
1232 if (auto es = frequire.isExpStatement())
1234 assert(es.exp && es.exp.op == EXP.assert_);
1235 buf.writestring(" (");
1236 (cast(AssertExp)es.exp).e1.expressionToBuffer(buf, &hgs);
1237 buf.writeByte(')');
1238 buf.writenl();
1239 requireDo = false;
1241 else
1243 buf.writenl();
1244 frequire.statementToBuffer(buf, &hgs);
1245 requireDo = true;
1249 // out{}
1250 if (f.fensures)
1252 foreach (fensure; *f.fensures)
1254 buf.writestring("out");
1255 if (auto es = fensure.ensure.isExpStatement())
1257 assert(es.exp && es.exp.op == EXP.assert_);
1258 buf.writestring(" (");
1259 if (fensure.id)
1261 buf.writestring(fensure.id.toString());
1263 buf.writestring("; ");
1264 (cast(AssertExp)es.exp).e1.expressionToBuffer(buf, &hgs);
1265 buf.writeByte(')');
1266 buf.writenl();
1267 requireDo = false;
1269 else
1271 if (fensure.id)
1273 buf.writeByte('(');
1274 buf.writestring(fensure.id.toString());
1275 buf.writeByte(')');
1277 buf.writenl();
1278 fensure.ensure.statementToBuffer(buf, &hgs);
1279 requireDo = true;
1283 return requireDo;
1286 void bodyToBuffer(FuncDeclaration f)
1288 if (!f.fbody || (hgs.hdrgen && global.params.dihdr.fullOutput == false && !hgs.autoMember && !hgs.tpltMember && !hgs.insideFuncBody))
1290 if (!f.fbody && (f.fensures || f.frequires))
1292 buf.writenl();
1293 contractsToBuffer(f);
1295 buf.writeByte(';');
1296 buf.writenl();
1297 return;
1300 // there is no way to know if a function is nested
1301 // or not after parsing. We need scope information
1302 // for that, which is avaible during semantic
1303 // analysis. To overcome that, a simple mechanism
1304 // is implemented: everytime we print a function
1305 // body (templated or not) we increment a counter.
1306 // We decredement the counter when we stop
1307 // printing the function body.
1308 ++hgs.insideFuncBody;
1309 scope(exit) { --hgs.insideFuncBody; }
1311 const savetlpt = hgs.tpltMember;
1312 const saveauto = hgs.autoMember;
1313 hgs.tpltMember = 0;
1314 hgs.autoMember = 0;
1315 buf.writenl();
1316 bool requireDo = contractsToBuffer(f);
1318 if (requireDo)
1320 buf.writestring("do");
1321 buf.writenl();
1323 buf.writeByte('{');
1324 buf.writenl();
1325 buf.level++;
1326 f.fbody.statementToBuffer(buf, &hgs);
1327 buf.level--;
1328 buf.writeByte('}');
1329 buf.writenl();
1330 hgs.tpltMember = savetlpt;
1331 hgs.autoMember = saveauto;
1334 void visitBaseClasses(ClassDeclaration d)
1336 if (!d || !d.baseclasses.length)
1337 return;
1338 if (!d.isAnonymous())
1339 buf.writestring(" : ");
1340 foreach (i, b; *d.baseclasses)
1342 if (i)
1343 buf.writestring(", ");
1344 typeToBuffer(b.type, null, buf, &hgs);
1348 bool visitEponymousMember(TemplateDeclaration d)
1350 if (!d.members || d.members.length != 1)
1351 return false;
1352 Dsymbol onemember = (*d.members)[0];
1353 if (onemember.ident != d.ident)
1354 return false;
1355 if (FuncDeclaration fd = onemember.isFuncDeclaration())
1357 assert(fd.type);
1358 if (stcToBuffer(buf, fd.storage_class))
1359 buf.writeByte(' ');
1360 functionToBufferFull(cast(TypeFunction)fd.type, buf, d.ident, &hgs, d);
1361 visitTemplateConstraint(d.constraint);
1362 hgs.tpltMember++;
1363 bodyToBuffer(fd);
1364 hgs.tpltMember--;
1365 return true;
1367 if (AggregateDeclaration ad = onemember.isAggregateDeclaration())
1369 buf.writestring(ad.kind());
1370 buf.writeByte(' ');
1371 buf.writestring(ad.ident.toString());
1372 buf.writeByte('(');
1373 visitTemplateParameters(hgs.ddoc ? d.origParameters : d.parameters, buf, hgs);
1374 buf.writeByte(')');
1375 visitTemplateConstraint(d.constraint);
1376 visitBaseClasses(ad.isClassDeclaration());
1377 hgs.tpltMember++;
1378 if (ad.members)
1380 buf.writenl();
1381 buf.writeByte('{');
1382 buf.writenl();
1383 buf.level++;
1384 foreach (s; *ad.members)
1385 toCBuffer(s, buf, hgs);
1386 buf.level--;
1387 buf.writeByte('}');
1389 else
1390 buf.writeByte(';');
1391 buf.writenl();
1392 hgs.tpltMember--;
1393 return true;
1395 if (VarDeclaration vd = onemember.isVarDeclaration())
1397 if (d.constraint)
1398 return false;
1399 if (stcToBuffer(buf, vd.storage_class))
1400 buf.writeByte(' ');
1401 if (vd.type)
1402 typeToBuffer(vd.type, vd.ident, buf, &hgs);
1403 else
1404 buf.writestring(vd.ident.toString());
1405 buf.writeByte('(');
1406 visitTemplateParameters(hgs.ddoc ? d.origParameters : d.parameters, buf, hgs);
1407 buf.writeByte(')');
1408 if (vd._init)
1410 buf.writestring(" = ");
1411 ExpInitializer ie = vd._init.isExpInitializer();
1412 if (ie && (ie.exp.op == EXP.construct || ie.exp.op == EXP.blit))
1413 (cast(AssignExp)ie.exp).e2.expressionToBuffer(buf, &hgs);
1414 else
1415 vd._init.initializerToBuffer(buf, &hgs);
1417 buf.writeByte(';');
1418 buf.writenl();
1419 return true;
1421 return false;
1424 void visitTemplateDeclaration(TemplateDeclaration d)
1426 version (none)
1428 // Should handle template functions for doc generation
1429 if (onemember && onemember.isFuncDeclaration())
1430 buf.writestring("foo ");
1432 if ((hgs.hdrgen || hgs.fullDump) && visitEponymousMember(d))
1433 return;
1434 if (hgs.ddoc)
1435 buf.writestring(d.kind());
1436 else
1437 buf.writestring("template");
1438 buf.writeByte(' ');
1439 buf.writestring(d.ident.toString());
1440 buf.writeByte('(');
1441 visitTemplateParameters(hgs.ddoc ? d.origParameters : d.parameters, buf, hgs);
1442 buf.writeByte(')');
1443 visitTemplateConstraint(d.constraint);
1444 if (hgs.hdrgen || hgs.fullDump)
1446 hgs.tpltMember++;
1447 buf.writenl();
1448 buf.writeByte('{');
1449 buf.writenl();
1450 buf.level++;
1451 foreach (s; *d.members)
1452 toCBuffer(s, buf, hgs);
1453 buf.level--;
1454 buf.writeByte('}');
1455 buf.writenl();
1456 hgs.tpltMember--;
1460 void visitTemplateInstance(TemplateInstance ti)
1462 buf.writestring(ti.name.toChars());
1463 tiargsToBuffer(ti, buf, &hgs);
1465 if (hgs.fullDump)
1467 buf.writenl();
1468 dumpTemplateInstance(ti, buf, &hgs);
1472 void visitTemplateMixin(TemplateMixin tm)
1474 buf.writestring("mixin ");
1475 typeToBuffer(tm.tqual, null, buf, &hgs);
1476 tiargsToBuffer(tm, buf, &hgs);
1477 if (tm.ident && memcmp(tm.ident.toChars(), cast(const(char)*)"__mixin", 7) != 0)
1479 buf.writeByte(' ');
1480 buf.writestring(tm.ident.toString());
1482 buf.writeByte(';');
1483 buf.writenl();
1484 if (hgs.fullDump)
1485 dumpTemplateInstance(tm, buf, &hgs);
1488 void visitEnumDeclaration(EnumDeclaration d)
1490 auto oldInEnumDecl = hgs.inEnumDecl;
1491 scope(exit) hgs.inEnumDecl = oldInEnumDecl;
1492 hgs.inEnumDecl = d;
1493 buf.writestring("enum ");
1494 if (d.ident)
1496 buf.writestring(d.ident.toString());
1498 if (d.memtype)
1500 buf.writestring(" : ");
1501 typeToBuffer(d.memtype, null, buf, &hgs);
1503 if (!d.members)
1505 buf.writeByte(';');
1506 buf.writenl();
1507 return;
1509 buf.writenl();
1510 buf.writeByte('{');
1511 buf.writenl();
1512 buf.level++;
1513 foreach (em; *d.members)
1515 if (!em)
1516 continue;
1517 toCBuffer(em, buf, hgs);
1518 buf.writeByte(',');
1519 buf.writenl();
1521 buf.level--;
1522 buf.writeByte('}');
1523 buf.writenl();
1526 void visitNspace(Nspace d)
1528 buf.writestring("extern (C++, ");
1529 buf.writestring(d.ident.toString());
1530 buf.writeByte(')');
1531 buf.writenl();
1532 buf.writeByte('{');
1533 buf.writenl();
1534 buf.level++;
1535 foreach (s; *d.members)
1536 toCBuffer(s, buf, hgs);
1537 buf.level--;
1538 buf.writeByte('}');
1539 buf.writenl();
1542 void visitStructDeclaration(StructDeclaration d)
1544 buf.writestring(d.kind());
1545 buf.writeByte(' ');
1546 if (!d.isAnonymous())
1547 buf.writestring(d.toChars());
1548 if (!d.members)
1550 buf.writeByte(';');
1551 buf.writenl();
1552 return;
1554 buf.writenl();
1555 buf.writeByte('{');
1556 buf.writenl();
1557 buf.level++;
1558 hgs.insideAggregate++;
1559 foreach (s; *d.members)
1560 toCBuffer(s, buf, hgs);
1561 hgs.insideAggregate--;
1562 buf.level--;
1563 buf.writeByte('}');
1564 buf.writenl();
1567 void visitClassDeclaration(ClassDeclaration d)
1569 if (!d.isAnonymous())
1571 buf.writestring(d.kind());
1572 buf.writeByte(' ');
1573 buf.writestring(d.ident.toString());
1575 visitBaseClasses(d);
1576 if (d.members)
1578 buf.writenl();
1579 buf.writeByte('{');
1580 buf.writenl();
1581 buf.level++;
1582 hgs.insideAggregate++;
1583 foreach (s; *d.members)
1584 toCBuffer(s, buf, hgs);
1585 hgs.insideAggregate--;
1586 buf.level--;
1587 buf.writeByte('}');
1589 else
1590 buf.writeByte(';');
1591 buf.writenl();
1594 void visitAliasDeclaration(AliasDeclaration d)
1596 if (d.storage_class & STC.local)
1597 return;
1598 buf.writestring("alias ");
1599 if (d.aliassym)
1601 buf.writestring(d.ident.toString());
1602 buf.writestring(" = ");
1603 if (stcToBuffer(buf, d.storage_class))
1604 buf.writeByte(' ');
1606 https://issues.dlang.org/show_bug.cgi?id=23223
1607 https://issues.dlang.org/show_bug.cgi?id=23222
1608 This special case (initially just for modules) avoids some segfaults
1609 and nicer -vcg-ast output.
1611 if (d.aliassym.isModule())
1613 buf.writestring(d.aliassym.ident.toString());
1615 else
1617 toCBuffer(d.aliassym, buf, hgs);
1620 else if (d.type.ty == Tfunction)
1622 if (stcToBuffer(buf, d.storage_class))
1623 buf.writeByte(' ');
1624 typeToBuffer(d.type, d.ident, buf, &hgs);
1626 else if (d.ident)
1628 hgs.declstring = (d.ident == Id.string || d.ident == Id.wstring || d.ident == Id.dstring);
1629 buf.writestring(d.ident.toString());
1630 buf.writestring(" = ");
1631 if (stcToBuffer(buf, d.storage_class))
1632 buf.writeByte(' ');
1633 typeToBuffer(d.type, null, buf, &hgs);
1634 hgs.declstring = false;
1636 buf.writeByte(';');
1637 buf.writenl();
1640 void visitAliasAssign(AliasAssign d)
1642 buf.writestring(d.ident.toString());
1643 buf.writestring(" = ");
1644 if (d.aliassym)
1645 toCBuffer(d.aliassym, buf, hgs);
1646 else // d.type
1647 typeToBuffer(d.type, null, buf, &hgs);
1648 buf.writeByte(';');
1649 buf.writenl();
1652 void visitVarDeclaration(VarDeclaration d)
1654 if (d.storage_class & STC.local)
1655 return;
1656 visitVarDecl(d, false, buf, hgs);
1657 buf.writeByte(';');
1658 buf.writenl();
1661 void visitFuncDeclaration(FuncDeclaration f)
1663 //printf("FuncDeclaration::toCBuffer() '%s'\n", f.toChars());
1664 if (stcToBuffer(buf, f.storage_class))
1665 buf.writeByte(' ');
1666 auto tf = cast(TypeFunction)f.type;
1667 typeToBuffer(tf, f.ident, buf, &hgs);
1669 if (hgs.hdrgen)
1671 // if the return type is missing (e.g. ref functions or auto)
1672 // https://issues.dlang.org/show_bug.cgi?id=20090
1673 // constructors are an exception: they don't have an explicit return
1674 // type but we still don't output the body.
1675 if ((!f.isCtorDeclaration() && !tf.next) || f.storage_class & STC.auto_)
1677 hgs.autoMember++;
1678 bodyToBuffer(f);
1679 hgs.autoMember--;
1681 else if (hgs.tpltMember == 0 && global.params.dihdr.fullOutput == false && !hgs.insideFuncBody)
1683 if (!f.fbody)
1685 // this can happen on interfaces / abstract functions, see `allowsContractWithoutBody`
1686 if (f.fensures || f.frequires)
1687 buf.writenl();
1688 contractsToBuffer(f);
1690 buf.writeByte(';');
1691 buf.writenl();
1693 else
1694 bodyToBuffer(f);
1696 else
1697 bodyToBuffer(f);
1700 void visitFuncLiteralDeclaration(FuncLiteralDeclaration f)
1702 if (f.type.ty == Terror)
1704 buf.writestring("__error");
1705 return;
1707 if (f.tok != TOK.reserved)
1709 buf.writestring(f.kind());
1710 buf.writeByte(' ');
1712 TypeFunction tf = cast(TypeFunction)f.type;
1714 if (!f.inferRetType && tf.next)
1715 typeToBuffer(tf.next, null, buf, &hgs);
1716 parametersToBuffer(tf.parameterList, buf, &hgs);
1718 // https://issues.dlang.org/show_bug.cgi?id=20074
1719 void printAttribute(string str)
1721 buf.writeByte(' ');
1722 buf.writestring(str);
1724 tf.attributesApply(&printAttribute);
1727 CompoundStatement cs = f.fbody.isCompoundStatement();
1728 Statement s1;
1729 if (f.semanticRun >= PASS.semantic3done && cs)
1731 s1 = (*cs.statements)[cs.statements.length - 1];
1733 else
1734 s1 = !cs ? f.fbody : null;
1735 ReturnStatement rs = s1 ? s1.endsWithReturnStatement() : null;
1736 if (rs && rs.exp)
1738 buf.writestring(" => ");
1739 rs.exp.expressionToBuffer(buf, &hgs);
1741 else
1743 hgs.tpltMember++;
1744 bodyToBuffer(f);
1745 hgs.tpltMember--;
1749 void visitPostBlitDeclaration(PostBlitDeclaration d)
1751 if (stcToBuffer(buf, d.storage_class))
1752 buf.writeByte(' ');
1753 buf.writestring("this(this)");
1754 bodyToBuffer(d);
1757 void visitDtorDeclaration(DtorDeclaration d)
1759 if (stcToBuffer(buf, d.storage_class))
1760 buf.writeByte(' ');
1761 buf.writestring("~this()");
1762 bodyToBuffer(d);
1765 void visitStaticCtorDeclaration(StaticCtorDeclaration d)
1767 if (stcToBuffer(buf, d.storage_class & ~STC.static_))
1768 buf.writeByte(' ');
1769 if (d.isSharedStaticCtorDeclaration())
1770 buf.writestring("shared ");
1771 buf.writestring("static this()");
1772 if (hgs.hdrgen && !hgs.tpltMember)
1774 buf.writeByte(';');
1775 buf.writenl();
1777 else
1778 bodyToBuffer(d);
1781 void visitStaticDtorDeclaration(StaticDtorDeclaration d)
1783 if (stcToBuffer(buf, d.storage_class & ~STC.static_))
1784 buf.writeByte(' ');
1785 if (d.isSharedStaticDtorDeclaration())
1786 buf.writestring("shared ");
1787 buf.writestring("static ~this()");
1788 if (hgs.hdrgen && !hgs.tpltMember)
1790 buf.writeByte(';');
1791 buf.writenl();
1793 else
1794 bodyToBuffer(d);
1797 void visitInvariantDeclaration(InvariantDeclaration d)
1799 if (hgs.hdrgen)
1800 return;
1801 if (stcToBuffer(buf, d.storage_class))
1802 buf.writeByte(' ');
1803 buf.writestring("invariant");
1804 if(auto es = d.fbody.isExpStatement())
1806 assert(es.exp && es.exp.op == EXP.assert_);
1807 buf.writestring(" (");
1808 (cast(AssertExp)es.exp).e1.expressionToBuffer(buf, &hgs);
1809 buf.writestring(");");
1810 buf.writenl();
1812 else
1814 bodyToBuffer(d);
1818 void visitUnitTestDeclaration(UnitTestDeclaration d)
1820 if (hgs.hdrgen)
1821 return;
1822 if (stcToBuffer(buf, d.storage_class))
1823 buf.writeByte(' ');
1824 buf.writestring("unittest");
1825 bodyToBuffer(d);
1828 void visitBitFieldDeclaration(BitFieldDeclaration d)
1830 if (stcToBuffer(buf, d.storage_class))
1831 buf.writeByte(' ');
1832 Identifier id = d.isAnonymous() ? null : d.ident;
1833 typeToBuffer(d.type, id, buf, &hgs);
1834 buf.writestring(" : ");
1835 d.width.expressionToBuffer(buf, &hgs);
1836 buf.writeByte(';');
1837 buf.writenl();
1840 void visitNewDeclaration(NewDeclaration d)
1842 if (stcToBuffer(buf, d.storage_class & ~STC.static_))
1843 buf.writeByte(' ');
1844 buf.writestring("new();");
1847 void visitModule(Module m)
1849 moduleToBuffer2(m, buf, &hgs);
1852 extern (C++)
1853 final class DsymbolPrettyPrintVisitor : Visitor
1855 alias visit = Visitor.visit;
1857 public:
1858 override:
1859 void visit(Dsymbol s) { visitDsymbol(s); }
1860 void visit(StaticAssert s) { visitStaticAssert(s); }
1861 void visit(DebugSymbol s) { visitDebugSymbol(s); }
1862 void visit(VersionSymbol s) { visitVersionSymbol(s); }
1863 void visit(EnumMember em) { visitEnumMember(em); }
1864 void visit(Import imp) { visitImport(imp); }
1865 void visit(AliasThis d) { visitAliasThis(d); }
1866 void visit(AttribDeclaration d) { visitAttribDeclaration(d); }
1867 void visit(StorageClassDeclaration d) { visitStorageClassDeclaration(d); }
1868 void visit(DeprecatedDeclaration d) { visitDeprecatedDeclaration(d); }
1869 void visit(LinkDeclaration d) { visitLinkDeclaration(d); }
1870 void visit(CPPMangleDeclaration d) { visitCPPMangleDeclaration(d); }
1871 void visit(VisibilityDeclaration d) { visitVisibilityDeclaration(d); }
1872 void visit(AlignDeclaration d) { visitAlignDeclaration(d); }
1873 void visit(AnonDeclaration d) { visitAnonDeclaration(d); }
1874 void visit(PragmaDeclaration d) { visitPragmaDeclaration(d); }
1875 void visit(ConditionalDeclaration d) { visitConditionalDeclaration(d); }
1876 void visit(StaticForeachDeclaration s) { visitStaticForeachDeclaration(s); }
1877 void visit(MixinDeclaration d) { visitMixinDeclaration(d); }
1878 void visit(UserAttributeDeclaration d) { visitUserAttributeDeclaration(d); }
1879 void visit(TemplateDeclaration d) { visitTemplateDeclaration(d); }
1880 void visit(TemplateInstance ti) { visitTemplateInstance(ti); }
1881 void visit(TemplateMixin tm) { visitTemplateMixin(tm); }
1882 void visit(EnumDeclaration d) { visitEnumDeclaration(d); }
1883 void visit(Nspace d) { visitNspace(d); }
1884 void visit(StructDeclaration d) { visitStructDeclaration(d); }
1885 void visit(ClassDeclaration d) { visitClassDeclaration(d); }
1886 void visit(AliasDeclaration d) { visitAliasDeclaration(d); }
1887 void visit(AliasAssign d) { visitAliasAssign(d); }
1888 void visit(VarDeclaration d) { visitVarDeclaration(d); }
1889 void visit(FuncDeclaration f) { visitFuncDeclaration(f); }
1890 void visit(FuncLiteralDeclaration f) { visitFuncLiteralDeclaration(f); }
1891 void visit(PostBlitDeclaration d) { visitPostBlitDeclaration(d); }
1892 void visit(DtorDeclaration d) { visitDtorDeclaration(d); }
1893 void visit(StaticCtorDeclaration d) { visitStaticCtorDeclaration(d); }
1894 void visit(StaticDtorDeclaration d) { visitStaticDtorDeclaration(d); }
1895 void visit(InvariantDeclaration d) { visitInvariantDeclaration(d); }
1896 void visit(UnitTestDeclaration d) { visitUnitTestDeclaration(d); }
1897 void visit(BitFieldDeclaration d) { visitBitFieldDeclaration(d); }
1898 void visit(NewDeclaration d) { visitNewDeclaration(d); }
1899 void visit(Module m) { visitModule(m); }
1902 scope v = new DsymbolPrettyPrintVisitor();
1903 s.accept(v);
1907 /*****************************************
1908 * Pretty-print a template parameter list to a buffer.
1910 private void visitTemplateParameters(TemplateParameters* parameters, ref OutBuffer buf, ref HdrGenState hgs)
1912 if (!parameters)
1913 return;
1914 foreach (i, p; *parameters)
1916 if (i)
1917 buf.writestring(", ");
1918 p.templateParameterToBuffer(buf, &hgs);
1923 /*******************************************
1924 * Pretty-print a VarDeclaration to buf.
1926 private void visitVarDecl(VarDeclaration v, bool anywritten, ref OutBuffer buf, ref HdrGenState hgs)
1928 const bool isextern = hgs.hdrgen &&
1929 !hgs.insideFuncBody &&
1930 !hgs.tpltMember &&
1931 !hgs.insideAggregate &&
1932 !(v.storage_class & STC.manifest);
1934 void vinit(VarDeclaration v)
1936 auto ie = v._init.isExpInitializer();
1937 if (ie && (ie.exp.op == EXP.construct || ie.exp.op == EXP.blit))
1938 (cast(AssignExp)ie.exp).e2.expressionToBuffer(buf, &hgs);
1939 else
1940 v._init.initializerToBuffer(buf, &hgs);
1943 if (anywritten)
1945 buf.writestring(", ");
1946 buf.writestring(v.ident.toString());
1948 else
1950 const bool useTypeof = isextern && v._init && !v.type;
1951 auto stc = v.storage_class;
1952 if (isextern)
1953 stc |= STC.extern_;
1954 if (useTypeof)
1955 stc &= ~STC.auto_;
1956 if (stcToBuffer(buf, stc))
1957 buf.writeByte(' ');
1958 if (v.type)
1959 typeToBuffer(v.type, v.ident, buf, &hgs);
1960 else if (useTypeof)
1962 buf.writestring("typeof(");
1963 vinit(v);
1964 buf.writestring(") ");
1965 buf.writestring(v.ident.toString());
1967 else
1968 buf.writestring(v.ident.toString());
1970 if (v._init && !isextern)
1972 buf.writestring(" = ");
1973 vinit(v);
1978 /*********************************************
1979 * Print expression to buffer.
1981 private void expressionPrettyPrint(Expression e, ref OutBuffer buf, HdrGenState* hgs)
1983 void visit(Expression e)
1985 buf.writestring(EXPtoString(e.op));
1988 void visitInteger(IntegerExp e)
1990 const dinteger_t v = e.toInteger();
1991 if (e.type)
1993 Type t = e.type;
1995 switch (t.ty)
1997 case Tenum:
1999 TypeEnum te = cast(TypeEnum)t;
2000 auto sym = te.sym;
2001 if (sym && sym.members && (!hgs.inEnumDecl || hgs.inEnumDecl != sym))
2003 foreach (em; *sym.members)
2005 if ((cast(EnumMember)em).value.toInteger == v)
2007 buf.printf("%s.%s", sym.toChars(), em.ident.toChars());
2008 return ;
2013 buf.printf("cast(%s)", te.sym.toChars());
2014 t = te.sym.memtype;
2015 goto L1;
2017 case Tchar:
2018 case Twchar:
2019 case Tdchar:
2021 const o = buf.length;
2022 writeSingleCharLiteral(buf, cast(dchar) v);
2023 if (hgs.ddoc)
2024 escapeDdocString(buf, o);
2025 break;
2027 case Tint8:
2028 buf.writestring("cast(byte)");
2029 goto L2;
2030 case Tint16:
2031 buf.writestring("cast(short)");
2032 goto L2;
2033 case Tint32:
2035 buf.printf("%d", cast(int)v);
2036 break;
2037 case Tuns8:
2038 buf.writestring("cast(ubyte)");
2039 goto case Tuns32;
2040 case Tuns16:
2041 buf.writestring("cast(ushort)");
2042 goto case Tuns32;
2043 case Tuns32:
2044 buf.printf("%uu", cast(uint)v);
2045 break;
2046 case Tint64:
2047 if (v == long.min)
2049 // https://issues.dlang.org/show_bug.cgi?id=23173
2050 // This is a special case because - is not part of the
2051 // integer literal and 9223372036854775808L overflows a long
2052 buf.writestring("cast(long)-9223372036854775808");
2054 else
2056 buf.printf("%lldL", v);
2058 break;
2059 case Tuns64:
2060 buf.printf("%lluLU", v);
2061 break;
2062 case Tbool:
2063 buf.writestring(v ? "true" : "false");
2064 break;
2065 case Tpointer:
2066 buf.writestring("cast(");
2067 buf.writestring(t.toChars());
2068 buf.writeByte(')');
2069 if (target.ptrsize == 8)
2070 goto case Tuns64;
2071 else if (target.ptrsize == 4 ||
2072 target.ptrsize == 2)
2073 goto case Tuns32;
2074 else
2075 assert(0);
2077 case Tvoid:
2078 buf.writestring("cast(void)0");
2079 break;
2081 default:
2082 /* This can happen if errors, such as
2083 * the type is painted on like in fromConstInitializer().
2085 if (!global.errors)
2087 assert(0);
2089 break;
2092 else if (v & 0x8000000000000000L)
2093 buf.printf("0x%llx", v);
2094 else
2095 buf.print(v);
2098 void visitError(ErrorExp e)
2100 buf.writestring("__error");
2103 void visitVoidInit(VoidInitExp e)
2105 buf.writestring("void");
2108 void floatToBuffer(Type type, real_t value)
2110 .floatToBuffer(type, value, buf, hgs.hdrgen);
2113 void visitReal(RealExp e)
2115 floatToBuffer(e.type, e.value);
2118 void visitComplex(ComplexExp e)
2120 /* Print as:
2121 * (re+imi)
2123 buf.writeByte('(');
2124 floatToBuffer(e.type, creall(e.value));
2125 buf.writeByte('+');
2126 floatToBuffer(e.type, cimagl(e.value));
2127 buf.writestring("i)");
2130 void visitIdentifier(IdentifierExp e)
2132 if (hgs.hdrgen || hgs.ddoc)
2133 buf.writestring(e.ident.toHChars2());
2134 else
2135 buf.writestring(e.ident.toString());
2138 void visitDsymbol(DsymbolExp e)
2140 buf.writestring(e.s.toChars());
2143 void visitThis(ThisExp e)
2145 buf.writestring("this");
2148 void visitSuper(SuperExp e)
2150 buf.writestring("super");
2153 void visitNull(NullExp e)
2155 buf.writestring("null");
2158 void visitString(StringExp e)
2160 buf.writeByte('"');
2161 const o = buf.length;
2162 foreach (i; 0 .. e.len)
2164 writeCharLiteral(buf, e.getCodeUnit(i));
2166 if (hgs.ddoc)
2167 escapeDdocString(buf, o);
2168 buf.writeByte('"');
2169 if (e.postfix)
2170 buf.writeByte(e.postfix);
2173 void visitArrayLiteral(ArrayLiteralExp e)
2175 buf.writeByte('[');
2176 argsToBuffer(e.elements, buf, hgs, e.basis);
2177 buf.writeByte(']');
2180 void visitAssocArrayLiteral(AssocArrayLiteralExp e)
2182 buf.writeByte('[');
2183 foreach (i, key; *e.keys)
2185 if (i)
2186 buf.writestring(", ");
2187 expToBuffer(key, PREC.assign, buf, hgs);
2188 buf.writeByte(':');
2189 auto value = (*e.values)[i];
2190 expToBuffer(value, PREC.assign, buf, hgs);
2192 buf.writeByte(']');
2195 void visitStructLiteral(StructLiteralExp e)
2197 buf.writestring(e.sd.toChars());
2198 buf.writeByte('(');
2199 // CTFE can generate struct literals that contain an AddrExp pointing
2200 // to themselves, need to avoid infinite recursion:
2201 // struct S { this(int){ this.s = &this; } S* s; }
2202 // const foo = new S(0);
2203 if (e.stageflags & stageToCBuffer)
2204 buf.writestring("<recursion>");
2205 else
2207 const old = e.stageflags;
2208 e.stageflags |= stageToCBuffer;
2209 argsToBuffer(e.elements, buf, hgs);
2210 e.stageflags = old;
2212 buf.writeByte(')');
2215 void visitCompoundLiteral(CompoundLiteralExp e)
2217 buf.writeByte('(');
2218 typeToBuffer(e.type, null, buf, hgs);
2219 buf.writeByte(')');
2220 e.initializer.initializerToBuffer(buf, hgs);
2223 void visitType(TypeExp e)
2225 typeToBuffer(e.type, null, buf, hgs);
2228 void visitScope(ScopeExp e)
2230 if (e.sds.isTemplateInstance())
2232 e.sds.dsymbolToBuffer(buf, hgs);
2234 else if (hgs !is null && hgs.ddoc)
2236 // fixes bug 6491
2237 if (auto m = e.sds.isModule())
2238 buf.writestring(m.md.toChars());
2239 else
2240 buf.writestring(e.sds.toChars());
2242 else
2244 buf.writestring(e.sds.kind());
2245 buf.writeByte(' ');
2246 buf.writestring(e.sds.toChars());
2250 void visitTemplate(TemplateExp e)
2252 buf.writestring(e.td.toChars());
2255 void visitNew(NewExp e)
2257 if (e.thisexp)
2259 expToBuffer(e.thisexp, PREC.primary, buf, hgs);
2260 buf.writeByte('.');
2262 buf.writestring("new ");
2263 typeToBuffer(e.newtype, null, buf, hgs);
2264 if (e.arguments && e.arguments.length)
2266 buf.writeByte('(');
2267 argsToBuffer(e.arguments, buf, hgs, null, e.names);
2268 buf.writeByte(')');
2272 void visitNewAnonClass(NewAnonClassExp e)
2274 if (e.thisexp)
2276 expToBuffer(e.thisexp, PREC.primary, buf, hgs);
2277 buf.writeByte('.');
2279 buf.writestring("new");
2280 buf.writestring(" class ");
2281 if (e.arguments && e.arguments.length)
2283 buf.writeByte('(');
2284 argsToBuffer(e.arguments, buf, hgs);
2285 buf.writeByte(')');
2287 if (e.cd)
2288 e.cd.dsymbolToBuffer(buf, hgs);
2291 void visitSymOff(SymOffExp e)
2293 if (e.offset)
2294 buf.printf("(& %s%+lld)", e.var.toChars(), e.offset);
2295 else if (e.var.isTypeInfoDeclaration())
2296 buf.writestring(e.var.toChars());
2297 else
2298 buf.printf("& %s", e.var.toChars());
2301 void visitVar(VarExp e)
2303 buf.writestring(e.var.toChars());
2306 void visitOver(OverExp e)
2308 buf.writestring(e.vars.ident.toString());
2311 void visitTuple(TupleExp e)
2313 if (e.e0)
2315 buf.writeByte('(');
2316 e.e0.expressionPrettyPrint(buf, hgs);
2317 buf.writestring(", AliasSeq!(");
2318 argsToBuffer(e.exps, buf, hgs);
2319 buf.writestring("))");
2321 else
2323 buf.writestring("AliasSeq!(");
2324 argsToBuffer(e.exps, buf, hgs);
2325 buf.writeByte(')');
2329 void visitFunc(FuncExp e)
2331 e.fd.dsymbolToBuffer(buf, hgs);
2332 //buf.writestring(e.fd.toChars());
2335 void visitDeclaration(DeclarationExp e)
2337 /* Normal dmd execution won't reach here - regular variable declarations
2338 * are handled in visit(ExpStatement), so here would be used only when
2339 * we'll directly call Expression.toChars() for debugging.
2341 if (e.declaration)
2343 if (auto var = e.declaration.isVarDeclaration())
2345 // For debugging use:
2346 // - Avoid printing newline.
2347 // - Intentionally use the format (Type var;)
2348 // which isn't correct as regular D code.
2349 buf.writeByte('(');
2351 visitVarDecl(var, false, buf, *hgs);
2353 buf.writeByte(';');
2354 buf.writeByte(')');
2356 else e.declaration.dsymbolToBuffer(buf, hgs);
2360 void visitTypeid(TypeidExp e)
2362 buf.writestring("typeid(");
2363 objectToBuffer(e.obj, buf, hgs);
2364 buf.writeByte(')');
2367 void visitTraits(TraitsExp e)
2369 buf.writestring("__traits(");
2370 if (e.ident)
2371 buf.writestring(e.ident.toString());
2372 if (e.args)
2374 foreach (arg; *e.args)
2376 buf.writestring(", ");
2377 objectToBuffer(arg, buf, hgs);
2380 buf.writeByte(')');
2383 void visitHalt(HaltExp e)
2385 buf.writestring("halt");
2388 void visitIs(IsExp e)
2390 buf.writestring("is(");
2391 typeToBuffer(e.targ, e.id, buf, hgs);
2392 if (e.tok2 != TOK.reserved)
2394 buf.printf(" %s %s", Token.toChars(e.tok), Token.toChars(e.tok2));
2396 else if (e.tspec)
2398 if (e.tok == TOK.colon)
2399 buf.writestring(" : ");
2400 else
2401 buf.writestring(" == ");
2402 typeToBuffer(e.tspec, null, buf, hgs);
2404 if (e.parameters && e.parameters.length)
2406 buf.writestring(", ");
2407 visitTemplateParameters(e.parameters, buf, *hgs);
2409 buf.writeByte(')');
2412 void visitUna(UnaExp e)
2414 buf.writestring(EXPtoString(e.op));
2415 expToBuffer(e.e1, precedence[e.op], buf, hgs);
2418 void visitLoweredAssignExp(LoweredAssignExp e)
2420 if (global.params.vcg_ast)
2422 expressionToBuffer(e.lowering, buf, hgs);
2423 return;
2426 visit(cast(BinExp)e);
2428 void visitBin(BinExp e)
2430 expToBuffer(e.e1, precedence[e.op], buf, hgs);
2431 buf.writeByte(' ');
2432 buf.writestring(EXPtoString(e.op));
2433 buf.writeByte(' ');
2434 expToBuffer(e.e2, cast(PREC)(precedence[e.op] + 1), buf, hgs);
2437 void visitComma(CommaExp e)
2439 // CommaExp is generated by the compiler so it shouldn't
2440 // appear in error messages or header files.
2441 // For now, this treats the case where the compiler
2442 // generates CommaExp for temporaries by calling
2443 // the `sideeffect.copyToTemp` function.
2444 auto ve = e.e2.isVarExp();
2446 // not a CommaExp introduced for temporaries, go on
2447 // the old path
2448 if (!ve || !(ve.var.storage_class & STC.temp))
2450 visitBin(cast(BinExp)e);
2451 return;
2454 // CommaExp that contain temporaries inserted via
2455 // `copyToTemp` are usually of the form
2456 // ((T __temp = exp), __tmp).
2457 // Asserts are here to easily spot
2458 // missing cases where CommaExp
2459 // are used for other constructs
2460 auto vd = ve.var.isVarDeclaration();
2461 assert(vd && vd._init);
2463 if (auto ei = vd._init.isExpInitializer())
2465 Expression commaExtract;
2466 auto exp = ei.exp;
2467 if (auto ce = exp.isConstructExp())
2468 commaExtract = ce.e2;
2469 else if (auto se = exp.isStructLiteralExp())
2470 commaExtract = se;
2472 if (commaExtract)
2474 expToBuffer(commaExtract, precedence[exp.op], buf, hgs);
2475 return;
2479 // not one of the known cases, go on the old path
2480 visitBin(cast(BinExp)e);
2481 return;
2484 void visitMixin(MixinExp e)
2486 buf.writestring("mixin(");
2487 argsToBuffer(e.exps, buf, hgs, null);
2488 buf.writeByte(')');
2491 void visitImport(ImportExp e)
2493 buf.writestring("import(");
2494 expToBuffer(e.e1, PREC.assign, buf, hgs);
2495 buf.writeByte(')');
2498 void visitAssert(AssertExp e)
2500 buf.writestring("assert(");
2501 expToBuffer(e.e1, PREC.assign, buf, hgs);
2502 if (e.msg)
2504 buf.writestring(", ");
2505 expToBuffer(e.msg, PREC.assign, buf, hgs);
2507 buf.writeByte(')');
2510 void visitThrow(ThrowExp e)
2512 buf.writestring("throw ");
2513 expToBuffer(e.e1, PREC.unary, buf, hgs);
2516 void visitDotId(DotIdExp e)
2518 expToBuffer(e.e1, PREC.primary, buf, hgs);
2519 if (e.arrow)
2520 buf.writestring("->");
2521 else
2522 buf.writeByte('.');
2523 buf.writestring(e.ident.toString());
2526 void visitDotTemplate(DotTemplateExp e)
2528 expToBuffer(e.e1, PREC.primary, buf, hgs);
2529 buf.writeByte('.');
2530 buf.writestring(e.td.toChars());
2533 void visitDotVar(DotVarExp e)
2535 expToBuffer(e.e1, PREC.primary, buf, hgs);
2536 buf.writeByte('.');
2537 buf.writestring(e.var.toChars());
2540 void visitDotTemplateInstance(DotTemplateInstanceExp e)
2542 expToBuffer(e.e1, PREC.primary, buf, hgs);
2543 buf.writeByte('.');
2544 e.ti.dsymbolToBuffer(buf, hgs);
2547 void visitDelegate(DelegateExp e)
2549 buf.writeByte('&');
2550 if (!e.func.isNested() || e.func.needThis())
2552 expToBuffer(e.e1, PREC.primary, buf, hgs);
2553 buf.writeByte('.');
2555 buf.writestring(e.func.toChars());
2558 void visitDotType(DotTypeExp e)
2560 expToBuffer(e.e1, PREC.primary, buf, hgs);
2561 buf.writeByte('.');
2562 buf.writestring(e.sym.toChars());
2565 void visitCall(CallExp e)
2567 if (e.e1.op == EXP.type)
2569 /* Avoid parens around type to prevent forbidden cast syntax:
2570 * (sometype)(arg1)
2571 * This is ok since types in constructor calls
2572 * can never depend on parens anyway
2574 e.e1.expressionPrettyPrint(buf, hgs);
2576 else
2577 expToBuffer(e.e1, precedence[e.op], buf, hgs);
2578 buf.writeByte('(');
2579 argsToBuffer(e.arguments, buf, hgs, null, e.names);
2580 buf.writeByte(')');
2583 void visitPtr(PtrExp e)
2585 buf.writeByte('*');
2586 expToBuffer(e.e1, precedence[e.op], buf, hgs);
2589 void visitDelete(DeleteExp e)
2591 buf.writestring("delete ");
2592 expToBuffer(e.e1, precedence[e.op], buf, hgs);
2595 void visitCast(CastExp e)
2597 buf.writestring("cast(");
2598 if (e.to)
2599 typeToBuffer(e.to, null, buf, hgs);
2600 else
2602 MODtoBuffer(buf, e.mod);
2604 buf.writeByte(')');
2605 expToBuffer(e.e1, precedence[e.op], buf, hgs);
2608 void visitVector(VectorExp e)
2610 buf.writestring("cast(");
2611 typeToBuffer(e.to, null, buf, hgs);
2612 buf.writeByte(')');
2613 expToBuffer(e.e1, precedence[e.op], buf, hgs);
2616 void visitVectorArray(VectorArrayExp e)
2618 expToBuffer(e.e1, PREC.primary, buf, hgs);
2619 buf.writestring(".array");
2622 void visitSlice(SliceExp e)
2624 expToBuffer(e.e1, precedence[e.op], buf, hgs);
2625 buf.writeByte('[');
2626 if (e.upr || e.lwr)
2628 if (e.lwr)
2629 sizeToBuffer(e.lwr, buf, hgs);
2630 else
2631 buf.writeByte('0');
2632 buf.writestring("..");
2633 if (e.upr)
2634 sizeToBuffer(e.upr, buf, hgs);
2635 else
2636 buf.writeByte('$');
2638 buf.writeByte(']');
2641 void visitArrayLength(ArrayLengthExp e)
2643 expToBuffer(e.e1, PREC.primary, buf, hgs);
2644 buf.writestring(".length");
2647 void visitInterval(IntervalExp e)
2649 expToBuffer(e.lwr, PREC.assign, buf, hgs);
2650 buf.writestring("..");
2651 expToBuffer(e.upr, PREC.assign, buf, hgs);
2654 void visitDelegatePtr(DelegatePtrExp e)
2656 expToBuffer(e.e1, PREC.primary, buf, hgs);
2657 buf.writestring(".ptr");
2660 void visitDelegateFuncptr(DelegateFuncptrExp e)
2662 expToBuffer(e.e1, PREC.primary, buf, hgs);
2663 buf.writestring(".funcptr");
2666 void visitArray(ArrayExp e)
2668 expToBuffer(e.e1, PREC.primary, buf, hgs);
2669 buf.writeByte('[');
2670 argsToBuffer(e.arguments, buf, hgs);
2671 buf.writeByte(']');
2674 void visitDot(DotExp e)
2676 expToBuffer(e.e1, PREC.primary, buf, hgs);
2677 buf.writeByte('.');
2678 expToBuffer(e.e2, PREC.primary, buf, hgs);
2681 void visitIndex(IndexExp e)
2683 expToBuffer(e.e1, PREC.primary, buf, hgs);
2684 buf.writeByte('[');
2685 sizeToBuffer(e.e2, buf, hgs);
2686 buf.writeByte(']');
2689 void visitPost(PostExp e)
2691 expToBuffer(e.e1, precedence[e.op], buf, hgs);
2692 buf.writestring(EXPtoString(e.op));
2695 void visitPre(PreExp e)
2697 buf.writestring(EXPtoString(e.op));
2698 expToBuffer(e.e1, precedence[e.op], buf, hgs);
2701 void visitRemove(RemoveExp e)
2703 expToBuffer(e.e1, PREC.primary, buf, hgs);
2704 buf.writestring(".remove(");
2705 expToBuffer(e.e2, PREC.assign, buf, hgs);
2706 buf.writeByte(')');
2709 void visitCond(CondExp e)
2711 expToBuffer(e.econd, PREC.oror, buf, hgs);
2712 buf.writestring(" ? ");
2713 expToBuffer(e.e1, PREC.expr, buf, hgs);
2714 buf.writestring(" : ");
2715 expToBuffer(e.e2, PREC.cond, buf, hgs);
2718 void visitDefaultInit(DefaultInitExp e)
2720 buf.writestring(EXPtoString(e.op));
2723 void visitClassReference(ClassReferenceExp e)
2725 buf.writestring(e.value.toChars());
2728 switch (e.op)
2730 default:
2731 if (auto be = e.isBinExp())
2732 return visitBin(be);
2733 else if (auto ue = e.isUnaExp())
2734 return visitUna(ue);
2735 else if (auto de = e.isDefaultInitExp())
2736 return visitDefaultInit(e.isDefaultInitExp());
2737 return visit(e);
2739 case EXP.int64: return visitInteger(e.isIntegerExp());
2740 case EXP.error: return visitError(e.isErrorExp());
2741 case EXP.void_: return visitVoidInit(e.isVoidInitExp());
2742 case EXP.float64: return visitReal(e.isRealExp());
2743 case EXP.complex80: return visitComplex(e.isComplexExp());
2744 case EXP.identifier: return visitIdentifier(e.isIdentifierExp());
2745 case EXP.dSymbol: return visitDsymbol(e.isDsymbolExp());
2746 case EXP.this_: return visitThis(e.isThisExp());
2747 case EXP.super_: return visitSuper(e.isSuperExp());
2748 case EXP.null_: return visitNull(e.isNullExp());
2749 case EXP.string_: return visitString(e.isStringExp());
2750 case EXP.arrayLiteral: return visitArrayLiteral(e.isArrayLiteralExp());
2751 case EXP.assocArrayLiteral: return visitAssocArrayLiteral(e.isAssocArrayLiteralExp());
2752 case EXP.structLiteral: return visitStructLiteral(e.isStructLiteralExp());
2753 case EXP.compoundLiteral: return visitCompoundLiteral(e.isCompoundLiteralExp());
2754 case EXP.type: return visitType(e.isTypeExp());
2755 case EXP.scope_: return visitScope(e.isScopeExp());
2756 case EXP.template_: return visitTemplate(e.isTemplateExp());
2757 case EXP.new_: return visitNew(e.isNewExp());
2758 case EXP.newAnonymousClass: return visitNewAnonClass(e.isNewAnonClassExp());
2759 case EXP.symbolOffset: return visitSymOff(e.isSymOffExp());
2760 case EXP.variable: return visitVar(e.isVarExp());
2761 case EXP.overloadSet: return visitOver(e.isOverExp());
2762 case EXP.tuple: return visitTuple(e.isTupleExp());
2763 case EXP.function_: return visitFunc(e.isFuncExp());
2764 case EXP.declaration: return visitDeclaration(e.isDeclarationExp());
2765 case EXP.typeid_: return visitTypeid(e.isTypeidExp());
2766 case EXP.traits: return visitTraits(e.isTraitsExp());
2767 case EXP.halt: return visitHalt(e.isHaltExp());
2768 case EXP.is_: return visitIs(e.isExp());
2769 case EXP.comma: return visitComma(e.isCommaExp());
2770 case EXP.mixin_: return visitMixin(e.isMixinExp());
2771 case EXP.import_: return visitImport(e.isImportExp());
2772 case EXP.assert_: return visitAssert(e.isAssertExp());
2773 case EXP.throw_: return visitThrow(e.isThrowExp());
2774 case EXP.dotIdentifier: return visitDotId(e.isDotIdExp());
2775 case EXP.dotTemplateDeclaration: return visitDotTemplate(e.isDotTemplateExp());
2776 case EXP.dotVariable: return visitDotVar(e.isDotVarExp());
2777 case EXP.dotTemplateInstance: return visitDotTemplateInstance(e.isDotTemplateInstanceExp());
2778 case EXP.delegate_: return visitDelegate(e.isDelegateExp());
2779 case EXP.dotType: return visitDotType(e.isDotTypeExp());
2780 case EXP.call: return visitCall(e.isCallExp());
2781 case EXP.star: return visitPtr(e.isPtrExp());
2782 case EXP.delete_: return visitDelete(e.isDeleteExp());
2783 case EXP.cast_: return visitCast(e.isCastExp());
2784 case EXP.vector: return visitVector(e.isVectorExp());
2785 case EXP.vectorArray: return visitVectorArray(e.isVectorArrayExp());
2786 case EXP.slice: return visitSlice(e.isSliceExp());
2787 case EXP.arrayLength: return visitArrayLength(e.isArrayLengthExp());
2788 case EXP.interval: return visitInterval(e.isIntervalExp());
2789 case EXP.delegatePointer: return visitDelegatePtr(e.isDelegatePtrExp());
2790 case EXP.delegateFunctionPointer: return visitDelegateFuncptr(e.isDelegateFuncptrExp());
2791 case EXP.array: return visitArray(e.isArrayExp());
2792 case EXP.dot: return visitDot(e.isDotExp());
2793 case EXP.index: return visitIndex(e.isIndexExp());
2794 case EXP.minusMinus:
2795 case EXP.plusPlus: return visitPost(e.isPostExp());
2796 case EXP.preMinusMinus:
2797 case EXP.prePlusPlus: return visitPre(e.isPreExp());
2798 case EXP.remove: return visitRemove(e.isRemoveExp());
2799 case EXP.question: return visitCond(e.isCondExp());
2800 case EXP.classReference: return visitClassReference(e.isClassReferenceExp());
2801 case EXP.loweredAssignExp: return visitLoweredAssignExp(e.isLoweredAssignExp());
2806 * Formats `value` as a literal of type `type` into `buf`.
2808 * Params:
2809 * type = literal type (e.g. Tfloat)
2810 * value = value to print
2811 * buf = target buffer
2812 * allowHex = whether hex floating point literals may be used
2813 * for greater accuracy
2815 void floatToBuffer(Type type, const real_t value, ref OutBuffer buf, const bool allowHex)
2817 /** sizeof(value)*3 is because each byte of mantissa is max
2818 of 256 (3 characters). The string will be "-M.MMMMe-4932".
2819 (ie, 8 chars more than mantissa). Plus one for trailing \0.
2820 Plus one for rounding. */
2821 const(size_t) BUFFER_LEN = value.sizeof * 3 + 8 + 1 + 1;
2822 char[BUFFER_LEN] buffer = void;
2823 CTFloat.sprint(buffer.ptr, BUFFER_LEN, 'g', value);
2824 assert(strlen(buffer.ptr) < BUFFER_LEN);
2825 if (allowHex)
2827 bool isOutOfRange;
2828 real_t r = CTFloat.parse(buffer.ptr, isOutOfRange);
2829 //assert(!isOutOfRange); // test/compilable/test22725.c asserts here
2830 if (r != value) // if exact duplication
2831 CTFloat.sprint(buffer.ptr, BUFFER_LEN, 'a', value);
2833 buf.writestring(buffer.ptr);
2834 if (buffer.ptr[strlen(buffer.ptr) - 1] == '.')
2835 buf.remove(buf.length() - 1, 1);
2837 if (type)
2839 Type t = type.toBasetype();
2840 switch (t.ty)
2842 case Tfloat32:
2843 case Timaginary32:
2844 case Tcomplex32:
2845 buf.writeByte('F');
2846 break;
2847 case Tfloat80:
2848 case Timaginary80:
2849 case Tcomplex80:
2850 buf.writeByte('L');
2851 break;
2852 default:
2853 break;
2855 if (t.isimaginary())
2856 buf.writeByte('i');
2860 private void templateParameterToBuffer(TemplateParameter tp, ref OutBuffer buf, HdrGenState* hgs)
2862 scope v = new TemplateParameterPrettyPrintVisitor(&buf, hgs);
2863 tp.accept(v);
2866 private extern (C++) final class TemplateParameterPrettyPrintVisitor : Visitor
2868 alias visit = Visitor.visit;
2869 public:
2870 OutBuffer* buf;
2871 HdrGenState* hgs;
2873 extern (D) this(OutBuffer* buf, HdrGenState* hgs) scope @safe
2875 this.buf = buf;
2876 this.hgs = hgs;
2879 override void visit(TemplateTypeParameter tp)
2881 buf.writestring(tp.ident.toString());
2882 if (tp.specType)
2884 buf.writestring(" : ");
2885 typeToBuffer(tp.specType, null, *buf, hgs);
2887 if (tp.defaultType)
2889 buf.writestring(" = ");
2890 typeToBuffer(tp.defaultType, null, *buf, hgs);
2894 override void visit(TemplateThisParameter tp)
2896 buf.writestring("this ");
2897 visit(cast(TemplateTypeParameter)tp);
2900 override void visit(TemplateAliasParameter tp)
2902 buf.writestring("alias ");
2903 if (tp.specType)
2904 typeToBuffer(tp.specType, tp.ident, *buf, hgs);
2905 else
2906 buf.writestring(tp.ident.toString());
2907 if (tp.specAlias)
2909 buf.writestring(" : ");
2910 objectToBuffer(tp.specAlias, *buf, hgs);
2912 if (tp.defaultAlias)
2914 buf.writestring(" = ");
2915 objectToBuffer(tp.defaultAlias, *buf, hgs);
2919 override void visit(TemplateValueParameter tp)
2921 typeToBuffer(tp.valType, tp.ident, *buf, hgs);
2922 if (tp.specValue)
2924 buf.writestring(" : ");
2925 tp.specValue.expressionToBuffer(*buf, hgs);
2927 if (tp.defaultValue)
2929 buf.writestring(" = ");
2930 tp.defaultValue.expressionToBuffer(*buf, hgs);
2934 override void visit(TemplateTupleParameter tp)
2936 buf.writestring(tp.ident.toString());
2937 buf.writestring("...");
2941 private void conditionToBuffer(Condition c, ref OutBuffer buf, HdrGenState* hgs)
2943 scope v = new ConditionPrettyPrintVisitor(&buf, hgs);
2944 c.accept(v);
2947 private extern (C++) final class ConditionPrettyPrintVisitor : Visitor
2949 alias visit = Visitor.visit;
2950 public:
2951 OutBuffer* buf;
2952 HdrGenState* hgs;
2954 extern (D) this(OutBuffer* buf, HdrGenState* hgs) scope @safe
2956 this.buf = buf;
2957 this.hgs = hgs;
2960 override void visit(DebugCondition c)
2962 buf.writestring("debug (");
2963 if (c.ident)
2964 buf.writestring(c.ident.toString());
2965 else
2966 buf.print(c.level);
2967 buf.writeByte(')');
2970 override void visit(VersionCondition c)
2972 buf.writestring("version (");
2973 if (c.ident)
2974 buf.writestring(c.ident.toString());
2975 else
2976 buf.print(c.level);
2977 buf.writeByte(')');
2980 override void visit(StaticIfCondition c)
2982 buf.writestring("static if (");
2983 c.exp.expressionToBuffer(*buf, hgs);
2984 buf.writeByte(')');
2988 void toCBuffer(const Statement s, ref OutBuffer buf, ref HdrGenState hgs)
2990 (cast()s).statementToBuffer(buf, &hgs);
2993 void toCBuffer(const Type t, ref OutBuffer buf, const Identifier ident, ref HdrGenState hgs)
2995 typeToBuffer(cast() t, ident, buf, &hgs);
2998 // used from TemplateInstance::toChars() and TemplateMixin::toChars()
2999 void toCBufferInstance(const TemplateInstance ti, ref OutBuffer buf, bool qualifyTypes = false)
3001 HdrGenState hgs;
3002 hgs.fullQual = qualifyTypes;
3004 buf.writestring(ti.name.toChars());
3005 tiargsToBuffer(cast() ti, buf, &hgs);
3008 void toCBuffer(const Initializer iz, ref OutBuffer buf, ref HdrGenState hgs)
3010 initializerToBuffer(cast() iz, buf, &hgs);
3013 bool stcToBuffer(ref OutBuffer buf, StorageClass stc) @safe
3015 //printf("stc: %llx\n", stc);
3016 bool result = false;
3018 if (stc & STC.scopeinferred)
3020 //buf.writestring("scope-inferred ");
3021 stc &= ~(STC.scope_ | STC.scopeinferred);
3023 if (stc & STC.returninferred)
3025 //buf.writestring((stc & STC.returnScope) ? "return-scope-inferred " : "return-ref-inferred ");
3026 stc &= ~(STC.return_ | STC.returninferred);
3029 /* Put scope ref return into a standard order
3031 string rrs;
3032 const isout = (stc & STC.out_) != 0;
3033 //printf("bsr = %d %llx\n", buildScopeRef(stc), stc);
3034 final switch (buildScopeRef(stc))
3036 case ScopeRef.None:
3037 case ScopeRef.Scope:
3038 case ScopeRef.Ref:
3039 case ScopeRef.Return:
3040 break;
3042 case ScopeRef.ReturnScope: rrs = "return scope"; goto L1;
3043 case ScopeRef.ReturnRef: rrs = isout ? "return out" : "return ref"; goto L1;
3044 case ScopeRef.RefScope: rrs = isout ? "out scope" : "ref scope"; goto L1;
3045 case ScopeRef.ReturnRef_Scope: rrs = isout ? "return out scope" : "return ref scope"; goto L1;
3046 case ScopeRef.Ref_ReturnScope: rrs = isout ? "out return scope" : "ref return scope"; goto L1;
3048 buf.writestring(rrs);
3049 result = true;
3050 stc &= ~(STC.out_ | STC.scope_ | STC.ref_ | STC.return_);
3051 break;
3054 while (stc)
3056 const s = stcToString(stc);
3057 if (!s.length)
3058 break;
3059 if (result)
3060 buf.writeByte(' ');
3061 result = true;
3062 buf.writestring(s);
3065 return result;
3068 /*************************************************
3069 * Pick off one of the storage classes from stc,
3070 * and return a string representation of it.
3071 * stc is reduced by the one picked.
3073 string stcToString(ref StorageClass stc) @safe
3075 static struct SCstring
3077 StorageClass stc;
3078 string id;
3081 // Note: The identifier needs to be `\0` terminated
3082 // as some code assumes it (e.g. when printing error messages)
3083 static immutable SCstring[] table =
3085 SCstring(STC.auto_, Token.toString(TOK.auto_)),
3086 SCstring(STC.scope_, Token.toString(TOK.scope_)),
3087 SCstring(STC.static_, Token.toString(TOK.static_)),
3088 SCstring(STC.extern_, Token.toString(TOK.extern_)),
3089 SCstring(STC.const_, Token.toString(TOK.const_)),
3090 SCstring(STC.final_, Token.toString(TOK.final_)),
3091 SCstring(STC.abstract_, Token.toString(TOK.abstract_)),
3092 SCstring(STC.synchronized_, Token.toString(TOK.synchronized_)),
3093 SCstring(STC.deprecated_, Token.toString(TOK.deprecated_)),
3094 SCstring(STC.override_, Token.toString(TOK.override_)),
3095 SCstring(STC.lazy_, Token.toString(TOK.lazy_)),
3096 SCstring(STC.alias_, Token.toString(TOK.alias_)),
3097 SCstring(STC.out_, Token.toString(TOK.out_)),
3098 SCstring(STC.in_, Token.toString(TOK.in_)),
3099 SCstring(STC.manifest, Token.toString(TOK.enum_)),
3100 SCstring(STC.immutable_, Token.toString(TOK.immutable_)),
3101 SCstring(STC.shared_, Token.toString(TOK.shared_)),
3102 SCstring(STC.nothrow_, Token.toString(TOK.nothrow_)),
3103 SCstring(STC.wild, Token.toString(TOK.inout_)),
3104 SCstring(STC.pure_, Token.toString(TOK.pure_)),
3105 SCstring(STC.ref_, Token.toString(TOK.ref_)),
3106 SCstring(STC.return_, Token.toString(TOK.return_)),
3107 SCstring(STC.gshared, Token.toString(TOK.gshared)),
3108 SCstring(STC.nogc, "@nogc"),
3109 SCstring(STC.live, "@live"),
3110 SCstring(STC.property, "@property"),
3111 SCstring(STC.safe, "@safe"),
3112 SCstring(STC.trusted, "@trusted"),
3113 SCstring(STC.system, "@system"),
3114 SCstring(STC.disable, "@disable"),
3115 SCstring(STC.future, "@__future"),
3116 SCstring(STC.local, "__local"),
3118 foreach (ref entry; table)
3120 const StorageClass tbl = entry.stc;
3121 assert(tbl & STC.visibleStorageClasses);
3122 if (stc & tbl)
3124 stc &= ~tbl;
3125 return entry.id;
3128 //printf("stc = %llx\n", stc);
3129 return null;
3132 private void linkageToBuffer(ref OutBuffer buf, LINK linkage) @safe
3134 const s = linkageToString(linkage);
3135 if (s.length)
3137 buf.writestring("extern (");
3138 buf.writestring(s);
3139 buf.writeByte(')');
3143 const(char)* linkageToChars(LINK linkage)
3145 /// Works because we return a literal
3146 return linkageToString(linkage).ptr;
3149 string linkageToString(LINK linkage) pure nothrow @safe
3151 with (LINK)
3153 immutable string[7] a = [
3154 default_ : null,
3155 d : "D",
3156 c : "C",
3157 cpp : "C++",
3158 windows : "Windows",
3159 objc : "Objective-C",
3160 system : "System" ];
3161 return a[linkage];
3165 void visibilityToBuffer(ref OutBuffer buf, Visibility vis)
3167 buf.writestring(visibilityToString(vis.kind));
3168 if (vis.kind == Visibility.Kind.package_ && vis.pkg)
3170 buf.writeByte('(');
3171 buf.writestring(vis.pkg.toPrettyChars(true));
3172 buf.writeByte(')');
3177 * Returns:
3178 * a human readable representation of `kind`
3180 const(char)* visibilityToChars(Visibility.Kind kind)
3182 // Null terminated because we return a literal
3183 return visibilityToString(kind).ptr;
3186 /// Ditto
3187 extern (D) string visibilityToString(Visibility.Kind kind) nothrow pure @safe
3189 with (Visibility.Kind)
3191 immutable string[7] a = [
3192 none : "none",
3193 private_ : "private",
3194 package_ : "package",
3195 protected_ : "protected",
3196 public_ : "public",
3197 export_ : "export" ];
3198 return a[kind];
3202 // Print the full function signature with correct ident, attributes and template args
3203 void functionToBufferFull(TypeFunction tf, ref OutBuffer buf, const Identifier ident, HdrGenState* hgs, TemplateDeclaration td)
3205 //printf("TypeFunction::toCBuffer() this = %p\n", this);
3206 visitFuncIdentWithPrefix(tf, ident, td, buf, hgs);
3209 // ident is inserted before the argument list and will be "function" or "delegate" for a type
3210 void functionToBufferWithIdent(TypeFunction tf, ref OutBuffer buf, const(char)* ident, bool isStatic)
3212 HdrGenState hgs;
3213 visitFuncIdentWithPostfix(tf, ident.toDString(), buf, &hgs, isStatic);
3216 void toCBuffer(const Expression e, ref OutBuffer buf, ref HdrGenState hgs)
3218 expressionPrettyPrint(cast()e, buf, &hgs);
3221 /**************************************************
3222 * Write out argument types to buf.
3224 void argExpTypesToCBuffer(ref OutBuffer buf, Expressions* arguments)
3226 if (!arguments || !arguments.length)
3227 return;
3228 HdrGenState hgs;
3229 foreach (i, arg; *arguments)
3231 if (i)
3232 buf.writestring(", ");
3233 typeToBuffer(arg.type, null, buf, &hgs);
3237 void toCBuffer(const TemplateParameter tp, ref OutBuffer buf, ref HdrGenState hgs)
3239 scope v = new TemplateParameterPrettyPrintVisitor(&buf, &hgs);
3240 (cast() tp).accept(v);
3243 void arrayObjectsToBuffer(ref OutBuffer buf, Objects* objects)
3245 if (!objects || !objects.length)
3246 return;
3247 HdrGenState hgs;
3248 foreach (i, o; *objects)
3250 if (i)
3251 buf.writestring(", ");
3252 objectToBuffer(o, buf, &hgs);
3256 /*************************************************************
3257 * Pretty print function parameters.
3258 * Params:
3259 * pl = parameter list to print
3260 * Returns: Null-terminated string representing parameters.
3262 extern (C++) const(char)* parametersTypeToChars(ParameterList pl)
3264 OutBuffer buf;
3265 HdrGenState hgs;
3266 parametersToBuffer(pl, buf, &hgs);
3267 return buf.extractChars();
3270 /*************************************************************
3271 * Pretty print function parameter.
3272 * Params:
3273 * parameter = parameter to print.
3274 * tf = TypeFunction which holds parameter.
3275 * fullQual = whether to fully qualify types.
3276 * Returns: Null-terminated string representing parameters.
3278 const(char)* parameterToChars(Parameter parameter, TypeFunction tf, bool fullQual)
3280 OutBuffer buf;
3281 HdrGenState hgs;
3282 hgs.fullQual = fullQual;
3284 parameterToBuffer(parameter, buf, &hgs);
3286 if (tf.parameterList.varargs == VarArg.typesafe && parameter == tf.parameterList[tf.parameterList.parameters.length - 1])
3288 buf.writestring("...");
3290 return buf.extractChars();
3294 /*************************************************
3295 * Write ParameterList to buffer.
3296 * Params:
3297 * pl = parameter list to serialize
3298 * buf = buffer to write it to
3299 * hgs = context
3302 private void parametersToBuffer(ParameterList pl, ref OutBuffer buf, HdrGenState* hgs)
3304 buf.writeByte('(');
3305 foreach (i; 0 .. pl.length)
3307 if (i)
3308 buf.writestring(", ");
3309 pl[i].parameterToBuffer(buf, hgs);
3311 final switch (pl.varargs)
3313 case VarArg.none:
3314 case VarArg.KRvariadic:
3315 break;
3317 case VarArg.variadic:
3318 if (pl.length)
3319 buf.writestring(", ");
3321 if (stcToBuffer(buf, pl.stc))
3322 buf.writeByte(' ');
3323 goto case VarArg.typesafe;
3325 case VarArg.typesafe:
3326 buf.writestring("...");
3327 break;
3329 buf.writeByte(')');
3333 /***********************************************************
3334 * Write parameter `p` to buffer `buf`.
3335 * Params:
3336 * p = parameter to serialize
3337 * buf = buffer to write it to
3338 * hgs = context
3340 private void parameterToBuffer(Parameter p, ref OutBuffer buf, HdrGenState* hgs)
3342 if (p.userAttribDecl)
3344 buf.writeByte('@');
3346 bool isAnonymous = p.userAttribDecl.atts.length > 0 && !(*p.userAttribDecl.atts)[0].isCallExp();
3347 if (isAnonymous)
3348 buf.writeByte('(');
3350 argsToBuffer(p.userAttribDecl.atts, buf, hgs);
3352 if (isAnonymous)
3353 buf.writeByte(')');
3354 buf.writeByte(' ');
3356 if (p.storageClass & STC.auto_)
3357 buf.writestring("auto ");
3359 StorageClass stc = p.storageClass;
3360 if (p.storageClass & STC.in_)
3362 buf.writestring("in ");
3363 if (global.params.previewIn && p.storageClass & STC.ref_)
3364 stc &= ~STC.ref_;
3366 else if (p.storageClass & STC.lazy_)
3367 buf.writestring("lazy ");
3368 else if (p.storageClass & STC.alias_)
3369 buf.writestring("alias ");
3371 if (p.type && p.type.mod & MODFlags.shared_)
3372 stc &= ~STC.shared_;
3374 if (stcToBuffer(buf, stc & (STC.const_ | STC.immutable_ | STC.wild | STC.shared_ |
3375 STC.return_ | STC.returninferred | STC.scope_ | STC.scopeinferred | STC.out_ | STC.ref_ | STC.returnScope)))
3376 buf.writeByte(' ');
3378 if (p.storageClass & STC.alias_)
3380 if (p.ident)
3381 buf.writestring(p.ident.toString());
3383 else if (p.type.ty == Tident &&
3384 (cast(TypeIdentifier)p.type).ident.toString().length > 3 &&
3385 strncmp((cast(TypeIdentifier)p.type).ident.toChars(), "__T", 3) == 0)
3387 // print parameter name, instead of undetermined type parameter
3388 buf.writestring(p.ident.toString());
3390 else
3392 typeToBuffer(p.type, p.ident, buf, hgs, (stc & STC.in_) ? MODFlags.const_ : 0);
3395 if (p.defaultArg)
3397 buf.writestring(" = ");
3398 p.defaultArg.expToBuffer(PREC.assign, buf, hgs);
3403 /**************************************************
3404 * Write out argument list to buf.
3405 * Params:
3406 * expressions = argument list
3407 * buf = buffer to write to
3408 * hgs = context
3409 * basis = replace `null`s in argument list with this expression (for sparse array literals)
3410 * names = if non-null, use these as the names for the arguments
3412 private void argsToBuffer(Expressions* expressions, ref OutBuffer buf, HdrGenState* hgs, Expression basis = null, Identifiers* names = null)
3414 if (!expressions || !expressions.length)
3415 return;
3416 version (all)
3418 foreach (i, el; *expressions)
3420 if (i)
3421 buf.writestring(", ");
3423 if (names && i < names.length && (*names)[i])
3425 buf.writestring((*names)[i].toString());
3426 buf.writestring(": ");
3428 if (!el)
3429 el = basis;
3430 if (el)
3431 expToBuffer(el, PREC.assign, buf, hgs);
3434 else
3436 // Sparse style formatting, for debug use only
3437 // [0..length: basis, 1: e1, 5: e5]
3438 if (basis)
3440 buf.writestring("0..");
3441 buf.print(expressions.length);
3442 buf.writestring(": ");
3443 expToBuffer(basis, PREC.assign, buf, hgs);
3445 foreach (i, el; *expressions)
3447 if (el)
3449 if (basis)
3451 buf.writestring(", ");
3452 buf.print(i);
3453 buf.writestring(": ");
3455 else if (i)
3456 buf.writestring(", ");
3457 expToBuffer(el, PREC.assign, buf, hgs);
3463 private void sizeToBuffer(Expression e, ref OutBuffer buf, HdrGenState* hgs)
3465 if (e.type == Type.tsize_t)
3467 Expression ex = (e.op == EXP.cast_ ? (cast(CastExp)e).e1 : e);
3468 ex = ex.optimize(WANTvalue);
3469 const dinteger_t uval = ex.op == EXP.int64 ? ex.toInteger() : cast(dinteger_t)-1;
3470 if (cast(sinteger_t)uval >= 0)
3472 dinteger_t sizemax = void;
3473 if (target.ptrsize == 8)
3474 sizemax = 0xFFFFFFFFFFFFFFFFUL;
3475 else if (target.ptrsize == 4)
3476 sizemax = 0xFFFFFFFFU;
3477 else if (target.ptrsize == 2)
3478 sizemax = 0xFFFFU;
3479 else
3480 assert(0);
3481 if (uval <= sizemax && uval <= 0x7FFFFFFFFFFFFFFFUL)
3483 buf.print(uval);
3484 return;
3488 expToBuffer(e, PREC.assign, buf, hgs);
3491 private void expressionToBuffer(Expression e, ref OutBuffer buf, HdrGenState* hgs)
3493 expressionPrettyPrint(e, buf, hgs);
3496 /**************************************************
3497 * Write expression out to buf, but wrap it
3498 * in ( ) if its precedence is less than pr.
3500 private void expToBuffer(Expression e, PREC pr, ref OutBuffer buf, HdrGenState* hgs)
3502 debug
3504 if (precedence[e.op] == PREC.zero)
3505 printf("precedence not defined for token '%s'\n", EXPtoString(e.op).ptr);
3507 if (e.op == 0xFF)
3509 buf.writestring("<FF>");
3510 return;
3512 assert(precedence[e.op] != PREC.zero);
3513 assert(pr != PREC.zero);
3514 /* Despite precedence, we don't allow a<b<c expressions.
3515 * They must be parenthesized.
3517 if (precedence[e.op] < pr || (pr == PREC.rel && precedence[e.op] == pr)
3518 || (pr >= PREC.or && pr <= PREC.and && precedence[e.op] == PREC.rel))
3520 buf.writeByte('(');
3521 e.expressionToBuffer(buf, hgs);
3522 buf.writeByte(')');
3524 else
3526 e.expressionToBuffer(buf, hgs);
3531 /**************************************************
3532 * An entry point to pretty-print type.
3534 private void typeToBuffer(Type t, const Identifier ident, ref OutBuffer buf, HdrGenState* hgs,
3535 ubyte modMask = 0)
3537 if (auto tf = t.isTypeFunction())
3539 visitFuncIdentWithPrefix(tf, ident, null, buf, hgs);
3540 return;
3542 visitWithMask(t, modMask, buf, hgs);
3543 if (ident)
3545 buf.writeByte(' ');
3546 buf.writestring(ident.toString());
3550 private void visitWithMask(Type t, ubyte modMask, ref OutBuffer buf, HdrGenState* hgs)
3552 // Tuples and functions don't use the type constructor syntax
3553 if (modMask == t.mod || t.ty == Tfunction || t.ty == Ttuple)
3555 typeToBufferx(t, buf, hgs);
3557 else
3559 ubyte m = t.mod & ~(t.mod & modMask);
3560 if (m & MODFlags.shared_)
3562 MODtoBuffer(buf, MODFlags.shared_);
3563 buf.writeByte('(');
3565 if (m & MODFlags.wild)
3567 MODtoBuffer(buf, MODFlags.wild);
3568 buf.writeByte('(');
3570 if (m & (MODFlags.const_ | MODFlags.immutable_))
3572 MODtoBuffer(buf, m & (MODFlags.const_ | MODFlags.immutable_));
3573 buf.writeByte('(');
3575 typeToBufferx(t, buf, hgs);
3576 if (m & (MODFlags.const_ | MODFlags.immutable_))
3577 buf.writeByte(')');
3578 if (m & MODFlags.wild)
3579 buf.writeByte(')');
3580 if (m & MODFlags.shared_)
3581 buf.writeByte(')');
3586 private void dumpTemplateInstance(TemplateInstance ti, ref OutBuffer buf, HdrGenState* hgs)
3588 buf.writeByte('{');
3589 buf.writenl();
3590 buf.level++;
3592 if (ti.aliasdecl)
3594 ti.aliasdecl.dsymbolToBuffer(buf, hgs);
3595 buf.writenl();
3597 else if (ti.members)
3599 foreach(m;*ti.members)
3600 m.dsymbolToBuffer(buf, hgs);
3603 buf.level--;
3604 buf.writeByte('}');
3605 buf.writenl();
3609 private void tiargsToBuffer(TemplateInstance ti, ref OutBuffer buf, HdrGenState* hgs)
3611 buf.writeByte('!');
3612 if (ti.nest)
3614 buf.writestring("(...)");
3615 return;
3617 if (!ti.tiargs)
3619 buf.writestring("()");
3620 return;
3622 if (ti.tiargs.length == 1)
3624 RootObject oarg = (*ti.tiargs)[0];
3625 if (Type t = isType(oarg))
3627 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))
3629 buf.writestring(t.toChars());
3630 return;
3633 else if (Expression e = isExpression(oarg))
3635 if (e.op == EXP.int64 || e.op == EXP.float64 || e.op == EXP.null_ || e.op == EXP.string_ || e.op == EXP.this_)
3637 buf.writestring(e.toChars());
3638 return;
3642 buf.writeByte('(');
3643 ti.nestUp();
3644 foreach (i, arg; *ti.tiargs)
3646 if (i)
3647 buf.writestring(", ");
3648 objectToBuffer(arg, buf, hgs);
3650 ti.nestDown();
3651 buf.writeByte(')');
3654 /****************************************
3655 * This makes a 'pretty' version of the template arguments.
3656 * It's analogous to genIdent() which makes a mangled version.
3658 private void objectToBuffer(RootObject oarg, ref OutBuffer buf, HdrGenState* hgs)
3660 //printf("objectToBuffer()\n");
3661 /* The logic of this should match what genIdent() does. The _dynamic_cast()
3662 * function relies on all the pretty strings to be unique for different classes
3663 * See https://issues.dlang.org/show_bug.cgi?id=7375
3664 * Perhaps it would be better to demangle what genIdent() does.
3666 if (auto t = isType(oarg))
3668 //printf("\tt: %s ty = %d\n", t.toChars(), t.ty);
3669 typeToBuffer(t, null, buf, hgs);
3671 else if (auto e = isExpression(oarg))
3673 if (e.op == EXP.variable)
3674 e = e.optimize(WANTvalue); // added to fix https://issues.dlang.org/show_bug.cgi?id=7375
3675 expToBuffer(e, PREC.assign, buf, hgs);
3677 else if (Dsymbol s = isDsymbol(oarg))
3679 const p = s.ident ? s.ident.toChars() : s.toChars();
3680 buf.writestring(p);
3682 else if (auto v = isTuple(oarg))
3684 auto args = &v.objects;
3685 foreach (i, arg; *args)
3687 if (i)
3688 buf.writestring(", ");
3689 objectToBuffer(arg, buf, hgs);
3692 else if (auto p = isParameter(oarg))
3694 parameterToBuffer(p, buf, hgs);
3696 else if (!oarg)
3698 buf.writestring("NULL");
3700 else
3702 debug
3704 printf("bad Object = %p\n", oarg);
3706 assert(0);
3711 private void visitFuncIdentWithPostfix(TypeFunction t, const char[] ident, ref OutBuffer buf, HdrGenState* hgs, bool isStatic)
3713 if (t.inuse)
3715 t.inuse = 2; // flag error to caller
3716 return;
3718 t.inuse++;
3719 if (t.linkage > LINK.d && hgs.ddoc != 1 && !hgs.hdrgen)
3721 linkageToBuffer(buf, t.linkage);
3722 buf.writeByte(' ');
3724 if (t.linkage == LINK.objc && isStatic)
3725 buf.write("static ");
3726 if (t.next)
3728 typeToBuffer(t.next, null, buf, hgs);
3729 if (ident)
3730 buf.writeByte(' ');
3732 else if (hgs.ddoc)
3733 buf.writestring("auto ");
3734 if (ident)
3735 buf.writestring(ident);
3736 parametersToBuffer(t.parameterList, buf, hgs);
3737 /* Use postfix style for attributes
3739 if (t.mod)
3741 buf.writeByte(' ');
3742 MODtoBuffer(buf, t.mod);
3745 void dg(string str)
3747 buf.writeByte(' ');
3748 buf.writestring(str);
3750 t.attributesApply(&dg);
3752 t.inuse--;
3755 private void visitFuncIdentWithPrefix(TypeFunction t, const Identifier ident, TemplateDeclaration td,
3756 ref OutBuffer buf, HdrGenState* hgs)
3758 if (t.inuse)
3760 t.inuse = 2; // flag error to caller
3761 return;
3763 t.inuse++;
3765 /* Use 'storage class' (prefix) style for attributes
3767 if (t.mod)
3769 MODtoBuffer(buf, t.mod);
3770 buf.writeByte(' ');
3773 void ignoreReturn(string str)
3775 if (str != "return")
3777 // don't write 'ref' for ctors
3778 if ((ident == Id.ctor) && str == "ref")
3779 return;
3780 buf.writestring(str);
3781 buf.writeByte(' ');
3784 t.attributesApply(&ignoreReturn);
3786 if (t.linkage > LINK.d && hgs.ddoc != 1 && !hgs.hdrgen)
3788 linkageToBuffer(buf, t.linkage);
3789 buf.writeByte(' ');
3791 if (ident && ident.toHChars2() != ident.toChars())
3793 // Don't print return type for ctor, dtor, unittest, etc
3795 else if (t.next)
3797 typeToBuffer(t.next, null, buf, hgs);
3798 if (ident)
3799 buf.writeByte(' ');
3801 else if (hgs.ddoc)
3802 buf.writestring("auto ");
3803 if (ident)
3804 buf.writestring(ident.toHChars2());
3805 if (td)
3807 buf.writeByte('(');
3808 foreach (i, p; *td.origParameters)
3810 if (i)
3811 buf.writestring(", ");
3812 p.templateParameterToBuffer(buf, hgs);
3814 buf.writeByte(')');
3816 parametersToBuffer(t.parameterList, buf, hgs);
3817 if (t.isreturn)
3819 buf.writestring(" return");
3821 t.inuse--;
3825 private void initializerToBuffer(Initializer inx, ref OutBuffer buf, HdrGenState* hgs)
3827 void visitError(ErrorInitializer iz)
3829 buf.writestring("__error__");
3832 void visitVoid(VoidInitializer iz)
3834 buf.writestring("void");
3837 void visitStruct(StructInitializer si)
3839 //printf("StructInitializer::toCBuffer()\n");
3840 buf.writeByte('{');
3841 foreach (i, const id; si.field)
3843 if (i)
3844 buf.writestring(", ");
3845 if (id)
3847 buf.writestring(id.toString());
3848 buf.writeByte(':');
3850 if (auto iz = si.value[i])
3851 initializerToBuffer(iz, buf, hgs);
3853 buf.writeByte('}');
3856 void visitArray(ArrayInitializer ai)
3858 buf.writeByte('[');
3859 foreach (i, ex; ai.index)
3861 if (i)
3862 buf.writestring(", ");
3863 if (ex)
3865 ex.expressionToBuffer(buf, hgs);
3866 buf.writeByte(':');
3868 if (auto iz = ai.value[i])
3869 initializerToBuffer(iz, buf, hgs);
3871 buf.writeByte(']');
3874 void visitExp(ExpInitializer ei)
3876 ei.exp.expressionToBuffer(buf, hgs);
3879 void visitC(CInitializer ci)
3881 buf.writeByte('{');
3882 foreach (i, ref DesigInit di; ci.initializerList)
3884 if (i)
3885 buf.writestring(", ");
3886 if (di.designatorList)
3888 foreach (ref Designator d; (*di.designatorList)[])
3890 if (d.exp)
3892 buf.writeByte('[');
3893 toCBuffer(d.exp, buf, *hgs);
3894 buf.writeByte(']');
3896 else
3898 buf.writeByte('.');
3899 buf.writestring(d.ident.toString());
3902 buf.writeByte('=');
3904 initializerToBuffer(di.initializer, buf, hgs);
3906 buf.writeByte('}');
3909 mixin VisitInitializer!void visit;
3910 visit.VisitInitializer(inx);
3914 private void typeToBufferx(Type t, ref OutBuffer buf, HdrGenState* hgs)
3916 void visitType(Type t)
3918 printf("t = %p, ty = %d\n", t, t.ty);
3919 assert(0);
3922 void visitError(TypeError t)
3924 buf.writestring("_error_");
3927 void visitBasic(TypeBasic t)
3929 //printf("TypeBasic::toCBuffer2(t.mod = %d)\n", t.mod);
3930 buf.writestring(t.dstring);
3933 void visitTraits(TypeTraits t)
3935 //printf("TypeBasic::toCBuffer2(t.mod = %d)\n", t.mod);
3936 t.exp.expressionToBuffer(buf, hgs);
3939 void visitVector(TypeVector t)
3941 //printf("TypeVector::toCBuffer2(t.mod = %d)\n", t.mod);
3942 buf.writestring("__vector(");
3943 visitWithMask(t.basetype, t.mod, buf, hgs);
3944 buf.writestring(")");
3947 void visitSArray(TypeSArray t)
3949 visitWithMask(t.next, t.mod, buf, hgs);
3950 buf.writeByte('[');
3951 sizeToBuffer(t.dim, buf, hgs);
3952 buf.writeByte(']');
3955 void visitDArray(TypeDArray t)
3957 Type ut = t.castMod(0);
3958 if (hgs.declstring)
3959 goto L1;
3960 if (ut.equals(Type.tstring))
3961 buf.writestring("string");
3962 else if (ut.equals(Type.twstring))
3963 buf.writestring("wstring");
3964 else if (ut.equals(Type.tdstring))
3965 buf.writestring("dstring");
3966 else
3969 visitWithMask(t.next, t.mod, buf, hgs);
3970 buf.writestring("[]");
3974 void visitAArray(TypeAArray t)
3976 visitWithMask(t.next, t.mod, buf, hgs);
3977 buf.writeByte('[');
3978 visitWithMask(t.index, 0, buf, hgs);
3979 buf.writeByte(']');
3982 void visitPointer(TypePointer t)
3984 //printf("TypePointer::toCBuffer2() next = %d\n", t.next.ty);
3985 if (t.next.ty == Tfunction)
3986 visitFuncIdentWithPostfix(cast(TypeFunction)t.next, "function", buf, hgs, false);
3987 else
3989 visitWithMask(t.next, t.mod, buf, hgs);
3990 buf.writeByte('*');
3994 void visitReference(TypeReference t)
3996 visitWithMask(t.next, t.mod, buf, hgs);
3997 buf.writeByte('&');
4000 void visitFunction(TypeFunction t)
4002 //printf("TypeFunction::toCBuffer2() t = %p, ref = %d\n", t, t.isref);
4003 visitFuncIdentWithPostfix(t, null, buf, hgs, false);
4006 void visitDelegate(TypeDelegate t)
4008 visitFuncIdentWithPostfix(cast(TypeFunction)t.next, "delegate", buf, hgs, false);
4011 void visitTypeQualifiedHelper(TypeQualified t)
4013 foreach (id; t.idents)
4015 switch (id.dyncast()) with (DYNCAST)
4017 case dsymbol:
4018 buf.writeByte('.');
4019 TemplateInstance ti = cast(TemplateInstance)id;
4020 ti.dsymbolToBuffer(buf, hgs);
4021 break;
4022 case expression:
4023 buf.writeByte('[');
4024 (cast(Expression)id).expressionToBuffer(buf, hgs);
4025 buf.writeByte(']');
4026 break;
4027 case type:
4028 buf.writeByte('[');
4029 typeToBufferx(cast(Type)id, buf, hgs);
4030 buf.writeByte(']');
4031 break;
4032 default:
4033 buf.writeByte('.');
4034 buf.writestring(id.toString());
4039 void visitIdentifier(TypeIdentifier t)
4041 buf.writestring(t.ident.toString());
4042 visitTypeQualifiedHelper(t);
4045 void visitInstance(TypeInstance t)
4047 t.tempinst.dsymbolToBuffer(buf, hgs);
4048 visitTypeQualifiedHelper(t);
4051 void visitTypeof(TypeTypeof t)
4053 buf.writestring("typeof(");
4054 t.exp.expressionToBuffer(buf, hgs);
4055 buf.writeByte(')');
4056 visitTypeQualifiedHelper(t);
4059 void visitReturn(TypeReturn t)
4061 buf.writestring("typeof(return)");
4062 visitTypeQualifiedHelper(t);
4065 void visitEnum(TypeEnum t)
4067 buf.writestring(hgs.fullQual ? t.sym.toPrettyChars() : t.sym.toChars());
4070 void visitStruct(TypeStruct t)
4072 // https://issues.dlang.org/show_bug.cgi?id=13776
4073 // Don't use ti.toAlias() to avoid forward reference error
4074 // while printing messages.
4075 TemplateInstance ti = t.sym.parent ? t.sym.parent.isTemplateInstance() : null;
4076 if (ti && ti.aliasdecl == t.sym)
4077 buf.writestring(hgs.fullQual ? ti.toPrettyChars() : ti.toChars());
4078 else
4079 buf.writestring(hgs.fullQual ? t.sym.toPrettyChars() : t.sym.toChars());
4082 void visitClass(TypeClass t)
4084 // https://issues.dlang.org/show_bug.cgi?id=13776
4085 // Don't use ti.toAlias() to avoid forward reference error
4086 // while printing messages.
4087 TemplateInstance ti = t.sym.parent ? t.sym.parent.isTemplateInstance() : null;
4088 if (ti && ti.aliasdecl == t.sym)
4089 buf.writestring(hgs.fullQual ? ti.toPrettyChars() : ti.toChars());
4090 else
4091 buf.writestring(hgs.fullQual ? t.sym.toPrettyChars() : t.sym.toChars());
4094 void visitTag(TypeTag t)
4096 if (t.mod & MODFlags.const_)
4097 buf.writestring("const ");
4098 buf.writestring(Token.toChars(t.tok));
4099 buf.writeByte(' ');
4100 if (t.id)
4101 buf.writestring(t.id.toChars());
4102 if (t.tok == TOK.enum_ && t.base && t.base.ty != TY.Tint32)
4104 buf.writestring(" : ");
4105 visitWithMask(t.base, t.mod, buf, hgs);
4109 void visitTuple(TypeTuple t)
4111 parametersToBuffer(ParameterList(t.arguments, VarArg.none), buf, hgs);
4114 void visitSlice(TypeSlice t)
4116 visitWithMask(t.next, t.mod, buf, hgs);
4117 buf.writeByte('[');
4118 sizeToBuffer(t.lwr, buf, hgs);
4119 buf.writestring(" .. ");
4120 sizeToBuffer(t.upr, buf, hgs);
4121 buf.writeByte(']');
4124 void visitNull(TypeNull t)
4126 buf.writestring("typeof(null)");
4129 void visitMixin(TypeMixin t)
4131 buf.writestring("mixin(");
4132 argsToBuffer(t.exps, buf, hgs, null);
4133 buf.writeByte(')');
4136 void visitNoreturn(TypeNoreturn t)
4138 buf.writestring("noreturn");
4142 switch (t.ty)
4144 default: return t.isTypeBasic() ?
4145 visitBasic(cast(TypeBasic)t) :
4146 visitType(t);
4148 case Terror: return visitError(cast(TypeError)t);
4149 case Ttraits: return visitTraits(cast(TypeTraits)t);
4150 case Tvector: return visitVector(cast(TypeVector)t);
4151 case Tsarray: return visitSArray(cast(TypeSArray)t);
4152 case Tarray: return visitDArray(cast(TypeDArray)t);
4153 case Taarray: return visitAArray(cast(TypeAArray)t);
4154 case Tpointer: return visitPointer(cast(TypePointer)t);
4155 case Treference: return visitReference(cast(TypeReference)t);
4156 case Tfunction: return visitFunction(cast(TypeFunction)t);
4157 case Tdelegate: return visitDelegate(cast(TypeDelegate)t);
4158 case Tident: return visitIdentifier(cast(TypeIdentifier)t);
4159 case Tinstance: return visitInstance(cast(TypeInstance)t);
4160 case Ttypeof: return visitTypeof(cast(TypeTypeof)t);
4161 case Treturn: return visitReturn(cast(TypeReturn)t);
4162 case Tenum: return visitEnum(cast(TypeEnum)t);
4163 case Tstruct: return visitStruct(cast(TypeStruct)t);
4164 case Tclass: return visitClass(cast(TypeClass)t);
4165 case Ttuple: return visitTuple (cast(TypeTuple)t);
4166 case Tslice: return visitSlice(cast(TypeSlice)t);
4167 case Tnull: return visitNull(cast(TypeNull)t);
4168 case Tmixin: return visitMixin(cast(TypeMixin)t);
4169 case Tnoreturn: return visitNoreturn(cast(TypeNoreturn)t);
4170 case Ttag: return visitTag(cast(TypeTag)t);
4174 /****************************************
4175 * Convert EXP to char*.
4178 string EXPtoString(EXP op)
4180 static immutable char*[EXP.max + 1] strings =
4182 EXP.type : "type",
4183 EXP.error : "error",
4184 EXP.objcClassReference : "class",
4186 EXP.mixin_ : "mixin",
4188 EXP.import_ : "import",
4189 EXP.dotVariable : "dotvar",
4190 EXP.scope_ : "scope",
4191 EXP.identifier : "identifier",
4192 EXP.this_ : "this",
4193 EXP.super_ : "super",
4194 EXP.int64 : "long",
4195 EXP.float64 : "double",
4196 EXP.complex80 : "creal",
4197 EXP.null_ : "null",
4198 EXP.string_ : "string",
4199 EXP.arrayLiteral : "arrayliteral",
4200 EXP.assocArrayLiteral : "assocarrayliteral",
4201 EXP.classReference : "classreference",
4202 EXP.file : "__FILE__",
4203 EXP.fileFullPath : "__FILE_FULL_PATH__",
4204 EXP.line : "__LINE__",
4205 EXP.moduleString : "__MODULE__",
4206 EXP.functionString : "__FUNCTION__",
4207 EXP.prettyFunction : "__PRETTY_FUNCTION__",
4208 EXP.typeid_ : "typeid",
4209 EXP.is_ : "is",
4210 EXP.assert_ : "assert",
4211 EXP.halt : "halt",
4212 EXP.template_ : "template",
4213 EXP.dSymbol : "symbol",
4214 EXP.function_ : "function",
4215 EXP.variable : "var",
4216 EXP.symbolOffset : "symoff",
4217 EXP.structLiteral : "structLiteral",
4218 EXP.compoundLiteral : "compoundliteral",
4219 EXP.arrayLength : "arraylength",
4220 EXP.delegatePointer : "delegateptr",
4221 EXP.delegateFunctionPointer : "delegatefuncptr",
4222 EXP.remove : "remove",
4223 EXP.tuple : "sequence",
4224 EXP.traits : "__traits",
4225 EXP.overloadSet : "__overloadset",
4226 EXP.void_ : "void",
4227 EXP.vectorArray : "vectorarray",
4228 EXP._Generic : "_Generic",
4230 // post
4231 EXP.dotTemplateInstance : "dotti",
4232 EXP.dotIdentifier : "dotid",
4233 EXP.dotTemplateDeclaration : "dottd",
4234 EXP.dot : ".",
4235 EXP.dotType : "dottype",
4236 EXP.plusPlus : "++",
4237 EXP.minusMinus : "--",
4238 EXP.prePlusPlus : "++",
4239 EXP.preMinusMinus : "--",
4240 EXP.call : "call",
4241 EXP.slice : "..",
4242 EXP.array : "[]",
4243 EXP.index : "[i]",
4245 EXP.delegate_ : "delegate",
4246 EXP.address : "&",
4247 EXP.star : "*",
4248 EXP.negate : "-",
4249 EXP.uadd : "+",
4250 EXP.not : "!",
4251 EXP.tilde : "~",
4252 EXP.delete_ : "delete",
4253 EXP.new_ : "new",
4254 EXP.newAnonymousClass : "newanonclass",
4255 EXP.cast_ : "cast",
4257 EXP.vector : "__vector",
4258 EXP.pow : "^^",
4260 EXP.mul : "*",
4261 EXP.div : "/",
4262 EXP.mod : "%",
4264 EXP.add : "+",
4265 EXP.min : "-",
4266 EXP.concatenate : "~",
4268 EXP.leftShift : "<<",
4269 EXP.rightShift : ">>",
4270 EXP.unsignedRightShift : ">>>",
4272 EXP.lessThan : "<",
4273 EXP.lessOrEqual : "<=",
4274 EXP.greaterThan : ">",
4275 EXP.greaterOrEqual : ">=",
4276 EXP.in_ : "in",
4278 EXP.equal : "==",
4279 EXP.notEqual : "!=",
4280 EXP.identity : "is",
4281 EXP.notIdentity : "!is",
4283 EXP.and : "&",
4284 EXP.xor : "^",
4285 EXP.or : "|",
4287 EXP.andAnd : "&&",
4288 EXP.orOr : "||",
4290 EXP.question : "?",
4292 EXP.assign : "=",
4293 EXP.construct : "=",
4294 EXP.blit : "=",
4295 EXP.addAssign : "+=",
4296 EXP.minAssign : "-=",
4297 EXP.concatenateAssign : "~=",
4298 EXP.concatenateElemAssign : "~=",
4299 EXP.concatenateDcharAssign : "~=",
4300 EXP.mulAssign : "*=",
4301 EXP.divAssign : "/=",
4302 EXP.modAssign : "%=",
4303 EXP.powAssign : "^^=",
4304 EXP.leftShiftAssign : "<<=",
4305 EXP.rightShiftAssign : ">>=",
4306 EXP.unsignedRightShiftAssign : ">>>=",
4307 EXP.andAssign : "&=",
4308 EXP.orAssign : "|=",
4309 EXP.xorAssign : "^=",
4311 EXP.comma : ",",
4312 EXP.declaration : "declaration",
4314 EXP.interval : "interval",
4315 EXP.loweredAssignExp : "="
4317 const p = strings[op];
4318 if (!p)
4320 printf("error: EXP %d has no string\n", op);
4321 return "XXXXX";
4322 //assert(0);
4324 assert(p);
4325 return p[0 .. strlen(p)];