1 /// Author: Aziz Köksal
2 /// License: GPL3
3 /// $(Maturity average)
4 module dil.translator.PyTreeEmitter;
5
6 import dil.ast.Visitor,
7 dil.ast.Node,
8 dil.ast.Declarations,
9 dil.ast.Statements,
10 dil.ast.Expressions,
11 dil.ast.Parameters,
12 dil.ast.Types;
13 import dil.semantic.Module;
14 import dil.lexer.Funcs;
15 import dil.Time,
16 dil.String;
17 import common;
18
19 /// Replaces \ with \\ and " with \".
20 cstring escapeDblQuotes(cstring text)
21 {
22 char[] result;
23 auto p = text.ptr;
24 auto end = p + text.length;
25 auto prev = p;
26 string esc;
27 for (; p < end; p++)
28 switch (*p)
29 {
30 case '"': esc = `\"`; goto case_common;
31 case '\\': esc = `\\`; goto case_common;
32 case_common:
33 if (prev < p) // Copy previous piece.
34 result ~= slice(prev, p);
35 result ~= esc;
36 prev = p + 1;
37 default:
38 }
39 if (prev == text.ptr)
40 return text; // Nothing to escape.
41 if (prev < end) // Copy last piece.
42 result ~= slice(prev, p);
43 return result;
44 }
45
46 /// Returns the number of characters if ws contains only ' ' chars,
47 /// otherwise returns ws in single quotes.
48 cstring quoteOrCountWhitespace(cstring ws)
49 {
50 foreach (c; ws)
51 if (c != ' ') return "'"~ws~"'";
52 return itoa(ws.length);
53 }
54
55 /// Enumeration of flags that indicate what's contained in a string.
56 enum Flags
57 {
58 None = 0, /// No special characters.
59 Backslash = 1, /// \
60 DblQuote = 2, /// "
61 SglQuote = 4, /// '
62 Newline = 8, /// \n, \r, \u2028, \u2029
63 SglAndDbl = DblQuote | SglQuote, /// " and '
64 }
65
66 /// Searches for backslashes, quotes and newlines in a string.
67 /// Returns: A set of flags.
68 Flags analyzeString(cstring str)
69 {
70 Flags flags;
71 foreach (c; str)
72 if (c == '\\') flags |= Flags.Backslash;
73 else if (c == '"') flags |= Flags.DblQuote;
74 else if (c == '\'') flags |= Flags.SglQuote;
75 else if (c == '\n' || c == '\r' || c == '\u2028' || c == '\u2029')
76 flags |= Flags.Newline;
77 return flags;
78 }
79
80 char[] writeTokenList(Token* first_token, ref uint[Token*] indexMap)
81 {
82 char[] result = "token_list = (\n".dup;
83 char[] line;
84 class Tuple
85 {
86 uint_t count;
87 cstring str;
88 TOK kind;
89 alias pos = count;
90 this(uint_t count, cstring str, TOK kind)
91 {
92 this.count = count;
93 this.str = str;
94 this.kind = kind;
95 }
96 override int opCmp(Object o)
97 {
98 return count > (cast(Tuple)cast(void*)o).count;
99 }
100 }
101 // Gather all identifiers, comments, strings and numbers in this map.
102 Tuple[hash_t] map;
103 for (auto token = first_token; token.kind; token++)
104 if (token.kind.In(TOK.Identifier, TOK.Comment, TOK.String, TOK.Character,
105 TOK.Int32, TOK.Int64, TOK.UInt32, TOK.UInt64,
106 TOK.Float32, TOK.Float64, TOK.Float80,
107 TOK.IFloat32, TOK.IFloat64, TOK.IFloat80))
108 {
109 auto hash = hashOf(token.text);
110 auto p = hash in map;
111 if (p) p.count += 1;
112 else map[hash] = new Tuple(1, token.text, token.kind);
113 }
114 // Create a sorted list. We want the strings that appear the most
115 // in the source text to be at the beginning of the list.
116 // That way less space is taken up by index numbers in the emitted text.
117 // NB.: First tests showed, that this only saves about 3% of characters.
118 auto list = map.values.sort;
119 result ~= "(";
120 // Print the sorted string list.
121 foreach (i, item; list)
122 { // By analyzing the string we can determine the optimal
123 // way to represent strings in the Python source code.
124 auto str = item.str;
125 Flags flags = analyzeString(str);
126 string quote = `"`; // Default to double quotemarks.
127
128 if (flags & Flags.Backslash ||
129 (flags & Flags.SglAndDbl) == Flags.SglAndDbl)
130 { // Use triple quotes for multiline strings.
131 quote = (flags & Flags.Newline) ? `"""` : `"`;
132 str = escapeDblQuotes(str);
133 }
134 else if (flags & Flags.Newline)
135 quote = (flags & Flags.DblQuote) ? "'''" : `"""`;
136 else if (flags & Flags.DblQuote)
137 quote = "'";
138 //else if (flags & Flags.SglQuote)
139 // quote = `"`;
140
141 line ~= quote;
142 line ~= str;
143 line ~= quote;
144 line ~= ',';
145
146 if (line.length > 100)
147 (result ~= line ~ "\n"), line = null;
148 item.pos = i; /// Update position.
149 }
150 if (line.length)
151 result ~= line;
152 if (result[$-1] == '\n')
153 result.length--;
154 result ~= "),\n[\n";
155 line = null;
156
157 // Print the list of all tokens, encoded with IDs and indices.
158 uint index;
159 for (auto token = first_token; token.kind; index++, token++)
160 {
161 indexMap[token] = index;
162 line ~= '(' ~ itoa(token.kind) ~ ',';
163 line ~= (token.ws) ? quoteOrCountWhitespace(token.wsChars) : `0`;
164 line ~= ',';
165 switch (token.kind)
166 {
167 case TOK.Identifier, TOK.Comment, TOK.String, TOK.Character,
168 TOK.Int32, TOK.Int64, TOK.UInt32, TOK.UInt64,
169 TOK.Float32, TOK.Float64, TOK.Float80,
170 TOK.IFloat32, TOK.IFloat64, TOK.IFloat80:
171 line ~= itoa(map[hashOf(token.text)].pos);
172 break;
173 case TOK.Shebang:
174 line ~= '"' ~ escapeDblQuotes(token.text) ~ '"';
175 break;
176 case TOK.HashLine:
177 // The text to be inserted into formatStr.
178 void printWS(cchar* start, cchar* end) {
179 line ~= '"' ~ start[0 .. end - start] ~ `",`;
180 }
181 auto num = token.hlval.lineNum;
182 line ~= `"#line"`;
183 if (num)
184 { // Print whitespace between #line and number.
185 printWS(token.start, num.start); // Prints "#line" as well.
186 line ~= '"' ~ num.text ~ '"'; // Print the number.
187 if (auto filespec = token.hlval.filespec)
188 { // Print whitespace between number and filespec.
189 printWS(num.end, filespec.start);
190 line ~= '"' ~ escapeDblQuotes(filespec.text) ~ '"';
191 }
192 }
193 break;
194 case TOK.Illegal:
195 line ~= '"' ~ escapeDblQuotes(token.text) ~ '"';
196 break;
197 default:
198 line = line[0..$-1];
199 }
200 line ~= "),";
201 if (line.length > 100)
202 (result ~= line ~ "\n"), line = null;
203 }
204 if (line.length)
205 result ~= line;
206 return result ~ "\n])\n";
207 }
208
209 /// Emits a D parse tree as Python code.
210 class PyTreeEmitter : Visitor2
211 {
212 char[] text; /// Contains the code.
213 char[] line; /// Line buffer.
214 Module modul; /// The module to be processed.
215 uint[Token*] index; /// Map tokens to index numbers.
216
217 /// Constructs a PyTreeEmitter object.
218 this(Module modul)
219 {
220 this.modul = modul;
221 }
222
223 /// Entry method.
224 char[] emit()
225 {
226 string d_version = "1.0";
227 version(D2)
228 d_version = "2.0";
229 text = Format("# -*- coding: utf-8 -*-\n"
230 "from __future__ import unicode_literals\n"
231 "import dil.token\n"
232 "from dil.module import Module\n"
233 "from dil.nodes import *\n\n"
234 "generated_by = 'dil'\n"
235 "format_version = '1.0'\n"
236 "d_version= '{}'\n"
237 "date = '{}'\n\n",
238 d_version, Time.now());
239
240 text ~= writeTokenList(modul.firstToken, index);
241 text ~= "t = tokens = dil.token.create_tokens(token_list)\n\n";
242 text ~= "def p(beg,end):\n"
243 " return (tokens[beg], tokens[beg+end])\n"
244 /+"def tl(*args):\n"
245 " return [tokens[i] for i in args]\n"
246 " #return map(tokens.__getitem__, args)\n"+/
247 "n = None\n\n"
248 /+"def N(id, *args):\n"+/
249 /+" return NodeTable[id](*args)\n\n"+/;
250 text ~= `module = Module(tokens=tokens, fqn="` ~ modul.getFQN() ~
251 `",ext="` ~ modul.fileExtension() ~ `",root=`"\n";
252
253 visitD(modul.root);
254 if (line.length)
255 text ~= line ~ "\n";
256 text ~= ")\n";
257 return text;
258 }
259
260
261 /// Returns the index number of a token as a string.
262 char[] indexOf(Token* token)
263 {
264 return "t["~itoa(index[token])~"]";
265 }
266
267 void write(cstring str)
268 {
269 line ~= str;
270 if (line.length > 100)
271 (this.text ~= line ~ "\n"), line = null;
272 }
273
274 /// Writes the list of nodes separated by commas.
275 void write(Node[] nodes)
276 {
277 write("(");
278 if (nodes.length)
279 {
280 visitN(nodes[0]);
281 foreach (n; nodes[1..$])
282 write(","), visitN(n);
283 if (nodes.length == 1)
284 write(","); // Trailing comma for single element tuples.
285 }
286 write(")");
287 }
288
289 void writeNodes(T)(T nodes)
290 {
291 write(cast(Node[])nodes);
292 }
293
294 void begin(Node n)
295 {
296 write("N"~itoa(n.kind)~"(");
297 }
298
299 void end(Node n, bool writeComma = true)
300 {
301 assert(n !is null && n.begin !is null && n.end !is null);
302 auto i1 = index[n.begin], i2 = index[n.end];
303 assert(i1 <= i2,
304 Format("ops, Parser or AST buggy? {}@{},i1={},i2={}",
305 NodeClassNames[n.kind],
306 n.begin.getRealLocation(modul.filePath()).str(), i1, i2));
307 write((writeComma ? ",":"") ~ "p("~itoa(i1)~","~itoa(i2-i1)~"))");
308 }
309
310 override
311 {
312 void visit(CompoundDecl d)
313 {
314 begin(d);
315 writeNodes(d.decls);
316 end(d);
317 }
318
319 void visit(IllegalDecl)
320 { assert(0); }
321
322 void visit(EmptyDecl d)
323 {
324 begin(d);
325 end(d, false);
326 }
327
328 void visit(ModuleDecl d)
329 {
330 begin(d);
331 d.type ? write(indexOf(d.type)) : write("n");
332 write(",");
333 write(indexOf(d.name)~",");
334 write("(");
335 foreach (tok; d.packages)
336 write(indexOf(tok)~",");
337 write(")");
338 end(d);
339 }
340
341 void visit(ImportDecl d)
342 {
343 begin(d);
344 write("(");
345 foreach (moduleFQN; d.moduleFQNs)
346 {
347 write("(");
348 foreach (tok; moduleFQN)
349 write(indexOf(tok)~",");
350 write("),");
351 }
352 write("),(");
353 foreach (tok; d.moduleAliases)
354 tok ? write(indexOf(tok)~",") : write("n,");
355 write("),(");
356 foreach (tok; d.bindNames)
357 write(indexOf(tok)~",");
358 write("),(");
359 foreach (tok; d.bindAliases)
360 tok ? write(indexOf(tok)~",") : write("n,");
361 write(")");
362 end(d);
363 }
364
365 void visit(AliasThisDecl d)
366 {
367 begin(d);
368 write(indexOf(d.name));
369 end(d);
370 }
371
372 void visit(AliasDecl d)
373 {
374 begin(d);
375 visitD(d.decl);
376 end(d);
377 }
378
379 void visit(TypedefDecl d)
380 {
381 begin(d);
382 visitD(d.decl);
383 end(d);
384 }
385
386 void visit(EnumDecl d)
387 {
388 begin(d);
389 write(indexOf(d.name));
390 write(",");
391 d.baseType ? visitT(d.baseType) : write("n");
392 write(",");
393 writeNodes(d.members);
394 end(d);
395 }
396
397 void visit(EnumMemberDecl d)
398 {
399 begin(d);
400 d.type ? visitT(d.type) : write("n");
401 write(",");
402 write(indexOf(d.name));
403 write(",");
404 d.value ? visitE(d.value) : write("n");
405 end(d);
406 }
407
408 void visit(ClassDecl d)
409 {
410 begin(d);
411 write(indexOf(d.name));
412 write(",");
413 writeNodes(d.bases);
414 write(",");
415 d.decls ? visitD(d.decls) : write("n");
416 end(d);
417 }
418
419 void visit(InterfaceDecl d)
420 {
421 begin(d);
422 write(indexOf(d.name));
423 write(",");
424 writeNodes(d.bases);
425 write(",");
426 d.decls ? visitD(d.decls) : write("n");
427 end(d);
428 }
429
430 void visit(StructDecl d)
431 {
432 begin(d);
433 write(indexOf(d.name));
434 write(",");
435 d.decls ? visitD(d.decls) : write("n");
436 end(d);
437 }
438
439 void visit(UnionDecl d)
440 {
441 begin(d);
442 write(indexOf(d.name));
443 write(",");
444 d.decls ? visitD(d.decls) : write("n");
445 end(d);
446 }
447
448 void visit(ConstructorDecl d)
449 {
450 begin(d);
451 visitN(d.params);
452 write(",");
453 visitS(d.funcBody);
454 end(d);
455 }
456
457 void visit(StaticCtorDecl d)
458 {
459 begin(d);
460 visitS(d.funcBody);
461 end(d);
462 }
463
464 void visit(DestructorDecl d)
465 {
466 begin(d);
467 visitS(d.funcBody);
468 end(d);
469 }
470
471 void visit(StaticDtorDecl d)
472 {
473 begin(d);
474 visitS(d.funcBody);
475 end(d);
476 }
477
478 void visit(FunctionDecl d)
479 {
480 begin(d);
481 d.returnType ? visitT(d.returnType) : write("n");
482 write(",");
483 write(indexOf(d.name));
484 write(",");
485 visitN(d.params);
486 write(",");
487 visitS(d.funcBody);
488 end(d);
489 }
490
491 void visit(VariablesDecl d)
492 {
493 begin(d);
494 // Type
495 if (d.type !is null)
496 visitT(d.type);
497 else
498 write("-1");
499 // Variable names.
500 write(",(");
501 foreach (name; d.names)
502 write(indexOf(name) ~ ",");
503 write("),(");
504 foreach (init; d.inits) {
505 if (init) visitE(init);
506 else write("-1");
507 write(",");
508 }
509 write(")");
510 end(d);
511 }
512
513 void visit(InvariantDecl d)
514 {
515 begin(d);
516 visitS(d.funcBody);
517 end(d);
518 }
519
520 void visit(UnittestDecl d)
521 {
522 begin(d);
523 visitS(d.funcBody);
524 end(d);
525 }
526
527 void visit(DebugDecl d)
528 {
529 begin(d);
530 d.spec ? write(indexOf(d.spec)) : write("n");
531 write(",");
532 d.cond ? write(indexOf(d.cond)) : write("n");
533 write(",");
534 d.decls ? visitD(d.decls) : write("n");
535 write(",");
536 d.elseDecls ? visitD(d.elseDecls) : write("n");
537 end(d);
538 }
539
540 void visit(VersionDecl d)
541 {
542 begin(d);
543 d.spec ? write(indexOf(d.spec)) : write("n");
544 write(",");
545 d.cond ? write(indexOf(d.cond)) : write("n");
546 write(",");
547 d.decls ? visitD(d.decls) : write("n");
548 write(",");
549 d.elseDecls ? visitD(d.elseDecls) : write("n");
550 end(d);
551 }
552
553 void visit(TemplateDecl d)
554 {
555 begin(d);
556 write(indexOf(d.name));
557 write(",");
558 visitN(d.tparams);
559 write(",");
560 d.constraint ? visitE(d.constraint) : write("n");
561 write(",");
562 visitD(d.decls);
563 end(d);
564 }
565
566 void visit(NewDecl d)
567 {
568 begin(d);
569 visitN(d.params);
570 write(",");
571 visitS(d.funcBody);
572 end(d);
573 }
574
575 void visit(DeleteDecl d)
576 {
577 begin(d);
578 visitN(d.params);
579 write(",");
580 visitS(d.funcBody);
581 end(d);
582 }
583
584 // Attributes:
585
586 void visit(ProtectionDecl d)
587 {
588 begin(d);
589 visitD(d.decls);
590 end(d);
591 }
592
593 void visit(StorageClassDecl d)
594 {
595 begin(d);
596 visitD(d.decls);
597 end(d);
598 }
599
600 void visit(LinkageDecl d)
601 {
602 begin(d);
603 visitD(d.decls);
604 end(d);
605 }
606
607 void visit(AlignDecl d)
608 {
609 begin(d);
610 d.sizetok ? write(indexOf(d.sizetok)) : write("n");
611 write(",");
612 visitD(d.decls);
613 end(d);
614 }
615
616 void visit(StaticAssertDecl d)
617 {
618 begin(d);
619 visitE(d.condition);
620 write(",");
621 d.message ? visitE(d.message) : write("n");
622 end(d);
623 }
624
625 void visit(StaticIfDecl d)
626 {
627 begin(d);
628 visitE(d.condition);
629 write(",");
630 visitD(d.ifDecls);
631 write(",");
632 d.elseDecls ? visitD(d.elseDecls) : write("n");
633 end(d);
634 }
635
636 void visit(MixinDecl d)
637 {
638 begin(d);
639 d.templateExpr ? visitE(d.templateExpr) : write("n");
640 write(",");
641 d.argument ? visitE(d.argument) : write("n");
642 write(",");
643 d.mixinIdent ? write(indexOf(d.mixinIdent)) : write("n");
644 end(d);
645 }
646
647 void visit(PragmaDecl d)
648 {
649 begin(d);
650 write(indexOf(d.name));
651 write(",");
652 writeNodes(d.args);
653 write(",");
654 visitD(d.decls);
655 end(d);
656 }
657
658 } // override
659
660 /+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
661 | Statements |
662 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+/
663
664 override
665 {
666
667 void visit(CompoundStmt s)
668 {
669 begin(s);
670 writeNodes(s.stmnts);
671 end(s);
672 }
673
674 void visit(IllegalStmt)
675 { assert(0, "interpreting invalid AST"); }
676
677 void visit(EmptyStmt s)
678 {
679 begin(s);
680 end(s, false);
681 }
682
683 void visit(FuncBodyStmt s)
684 {
685 begin(s);
686 s.funcBody ? visitS(s.funcBody) : write("n");
687 write(",");
688 s.inBody ? visitS(s.inBody) : write("n");
689 write(",");
690 s.outBody ? visitS(s.outBody) : write("n");
691 write(",");
692 s.outIdent ? write(indexOf(s.outIdent)) : write("n");
693 end(s);
694 }
695
696 void visit(ScopeStmt s)
697 {
698 begin(s);
699 visitS(s.stmnt);
700 end(s);
701 }
702
703 void visit(LabeledStmt s)
704 {
705 begin(s);
706 write(indexOf(s.label));
707 write(",");
708 visitS(s.stmnt);
709 end(s);
710 }
711
712 void visit(ExpressionStmt s)
713 {
714 begin(s);
715 visitE(s.expr);
716 end(s);
717 }
718
719 void visit(DeclarationStmt s)
720 {
721 begin(s);
722 visitD(s.decl);
723 end(s);
724 }
725
726 void visit(IfStmt s)
727 {
728 begin(s);
729 s.variable ? visitS(s.variable) : write("n");
730 write(",");
731 s.condition ? visitE(s.condition) : write("n");
732 write(",");
733 visitS(s.ifBody);
734 write(",");
735 s.elseBody ? visitS(s.elseBody) : write("n");
736 end(s);
737 }
738
739 void visit(WhileStmt s)
740 {
741 begin(s);
742 visitE(s.condition);
743 write(",");
744 visitS(s.whileBody);
745 end(s);
746 }
747
748 void visit(DoWhileStmt s)
749 {
750 begin(s);
751 visitS(s.doBody);
752 write(",");
753 visitE(s.condition);
754 end(s);
755 }
756
757 void visit(ForStmt s)
758 {
759 begin(s);
760 s.init ? visitS(s.init) : write("n");
761 write(",");
762 s.condition ? visitE(s.condition) : write("n");
763 write(",");
764 s.increment ? visitE(s.increment) : write("n");
765 write(",");
766 s.forBody ? visitS(s.forBody) : write("n");
767 end(s);
768 }
769
770 void visit(ForeachStmt s)
771 {
772 begin(s);
773 visitN(s.params);
774 write(",");
775 visitE(s.aggregate);
776 write(",");
777 visitS(s.forBody);
778 end(s);
779 }
780
781 void visit(SwitchStmt s)
782 {
783 begin(s);
784 visitE(s.condition);
785 write(",");
786 visitS(s.switchBody);
787 end(s);
788 }
789
790 void visit(CaseStmt s)
791 {
792 begin(s);
793 writeNodes(s.values);
794 write(",");
795 visitS(s.caseBody);
796 end(s);
797 }
798
799 void visit(DefaultStmt s)
800 {
801 begin(s);
802 visitS(s.defaultBody);
803 end(s);
804 }
805
806 void visit(ContinueStmt s)
807 {
808 begin(s);
809 s.label ? write(indexOf(s.label)) : write("n");
810 end(s);
811 }
812
813 void visit(BreakStmt s)
814 {
815 begin(s);
816 s.label ? write(indexOf(s.label)) : write("n");
817 end(s);
818 }
819
820 void visit(ReturnStmt s)
821 {
822 begin(s);
823 s.expr ? visitE(s.expr) : write("n");
824 end(s);
825 }
826
827 void visit(GotoStmt s)
828 {
829 begin(s);
830 s.ident ? write(indexOf(s.ident)) : write("n");
831 write(",");
832 s.expr ? visitE(s.expr) : write("n");
833 end(s);
834 }
835
836 void visit(WithStmt s)
837 {
838 begin(s);
839 visitE(s.expr);
840 write(",");
841 visitS(s.withBody);
842 end(s);
843 }
844
845 void visit(SynchronizedStmt s)
846 {
847 begin(s);
848 s.expr ? visitE(s.expr) : write("n");
849 write(",");
850 visitS(s.syncBody);
851 end(s);
852 }
853
854 void visit(TryStmt s)
855 {
856 begin(s);
857 visitS(s.tryBody);
858 write(",");
859 writeNodes(s.catchBodies);
860 write(",");
861 s.finallyBody ? visitS(s.finallyBody) : write("n");
862 end(s);
863 }
864
865 void visit(CatchStmt s)
866 {
867 begin(s);
868 s.param ? visitN(s.param) : write("n");
869 write(",");
870 visitS(s.catchBody);
871 end(s);
872 }
873
874 void visit(FinallyStmt s)
875 {
876 begin(s);
877 visitS(s.finallyBody);
878 end(s);
879 }
880
881 void visit(ScopeGuardStmt s)
882 {
883 begin(s);
884 write(indexOf(s.condition));
885 write(",");
886 visitS(s.scopeBody);
887 end(s);
888 }
889
890 void visit(ThrowStmt s)
891 {
892 begin(s);
893 visitE(s.expr);
894 end(s);
895 }
896
897 void visit(VolatileStmt s)
898 {
899 begin(s);
900 s.volatileBody ? visitS(s.volatileBody) : write("n");
901 end(s);
902 }
903
904 void visit(AsmBlockStmt s)
905 {
906 begin(s);
907 visitS(s.statements);
908 end(s);
909 }
910
911 void visit(AsmStmt s)
912 {
913 begin(s);
914 s.opcode ? write(indexOf(s.opcode)) : write("n");
915 write(",");
916 writeNodes(s.operands);
917 end(s);
918 }
919
920 void visit(AsmAlignStmt s)
921 {
922 begin(s);
923 write(indexOf(s.numtok));
924 end(s);
925 }
926
927 void visit(IllegalAsmStmt)
928 { assert(0, "invalid AST"); }
929
930 void visit(PragmaStmt s)
931 {
932 begin(s);
933 s.name ? write(indexOf(s.name)) : write("n");
934 write(",");
935 writeNodes(s.args);
936 write(",");
937 visitS(s.pragmaBody);
938 end(s);
939 }
940
941 void visit(MixinStmt s)
942 {
943 begin(s);
944 visitE(s.templateExpr);
945 write(",");
946 s.mixinIdent ? write(indexOf(s.mixinIdent)) : write("n");
947 end(s);
948 }
949
950 void visit(StaticIfStmt s)
951 {
952 begin(s);
953 visitE(s.condition);
954 write(",");
955 visitS(s.ifBody);
956 write(",");
957 s.elseBody ? visitS(s.elseBody) : write("n");
958 end(s);
959 }
960
961 void visit(StaticAssertStmt s)
962 {
963 begin(s);
964 visitE(s.condition);
965 write(",");
966 s.message ? visitE(s.message) : write("n");
967 end(s);
968 }
969
970 void visit(DebugStmt s)
971 {
972 begin(s);
973 visitS(s.mainBody);
974 write(",");
975 s.elseBody ? visitS(s.elseBody) : write("n");
976 end(s);
977 }
978
979 void visit(VersionStmt s)
980 {
981 begin(s);
982 visitS(s.mainBody);
983 write(",");
984 s.elseBody ? visitS(s.elseBody) : write("n");
985 end(s);
986 }
987
988 } // override
989
990 /+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
991 | Expressions |
992 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+/
993
994 enum binaryExpr = `
995 begin(e);
996 visitE(e.lhs);
997 write(",");
998 visitE(e.rhs);
999 write(",");
1000 write(indexOf(e.optok));
1001 end(e);`;
1002
1003 enum unaryExpr = `
1004 begin(e);
1005 visitE(e.una);
1006 end(e);`;
1007
1008 override
1009 {
1010 void visit(IllegalExpr)
1011 { assert(0, "interpreting invalid AST"); }
1012
1013 void visit(CondExpr e)
1014 {
1015 begin(e);
1016 visitE(e.condition);
1017 write(",");
1018 visitE(e.lhs);
1019 write(",");
1020 visitE(e.rhs);
1021 write(",");
1022 write(indexOf(e.optok));
1023 write(",");
1024 write(indexOf(e.ctok));
1025 end(e);
1026 }
1027
1028 void visit(CommaExpr e)
1029 {
1030 mixin(binaryExpr);
1031 }
1032
1033 void visit(OrOrExpr e)
1034 {
1035 mixin(binaryExpr);
1036 }
1037
1038 void visit(AndAndExpr e)
1039 {
1040 mixin(binaryExpr);
1041 }
1042
1043 void visit(OrExpr e)
1044 {
1045 mixin(binaryExpr);
1046 }
1047
1048 void visit(XorExpr e)
1049 {
1050 mixin(binaryExpr);
1051 }
1052
1053 void visit(AndExpr e)
1054 {
1055 mixin(binaryExpr);
1056 }
1057
1058 void visit(EqualExpr e)
1059 {
1060 mixin(binaryExpr);
1061 }
1062
1063 void visit(IdentityExpr e)
1064 {
1065 mixin(binaryExpr);
1066 }
1067
1068 void visit(RelExpr e)
1069 {
1070 mixin(binaryExpr);
1071 }
1072
1073 void visit(InExpr e)
1074 {
1075 mixin(binaryExpr);
1076 }
1077
1078 void visit(LShiftExpr e)
1079 {
1080 mixin(binaryExpr);
1081 }
1082
1083 void visit(RShiftExpr e)
1084 {
1085 mixin(binaryExpr);
1086 }
1087
1088 void visit(URShiftExpr e)
1089 {
1090 mixin(binaryExpr);
1091 }
1092
1093 void visit(PlusExpr e)
1094 {
1095 mixin(binaryExpr);
1096 }
1097
1098 void visit(MinusExpr e)
1099 {
1100 mixin(binaryExpr);
1101 }
1102
1103 void visit(CatExpr e)
1104 {
1105 mixin(binaryExpr);
1106 }
1107
1108 void visit(MulExpr e)
1109 {
1110 mixin(binaryExpr);
1111 }
1112
1113 void visit(DivExpr e)
1114 {
1115 mixin(binaryExpr);
1116 }
1117
1118 void visit(ModExpr e)
1119 {
1120 mixin(binaryExpr);
1121 }
1122
1123 void visit(RangeExpr e)
1124 {
1125 mixin(binaryExpr);
1126 }
1127
1128 void visit(AssignExpr e)
1129 {
1130 mixin(binaryExpr);
1131 }
1132
1133 void visit(LShiftAssignExpr e)
1134 {
1135 mixin(binaryExpr);
1136 }
1137
1138 void visit(RShiftAssignExpr e)
1139 {
1140 mixin(binaryExpr);
1141 }
1142
1143 void visit(URShiftAssignExpr e)
1144 {
1145 mixin(binaryExpr);
1146 }
1147
1148 void visit(OrAssignExpr e)
1149 {
1150 mixin(binaryExpr);
1151 }
1152
1153 void visit(AndAssignExpr e)
1154 {
1155 mixin(binaryExpr);
1156 }
1157
1158 void visit(PlusAssignExpr e)
1159 {
1160 mixin(binaryExpr);
1161 }
1162
1163 void visit(MinusAssignExpr e)
1164 {
1165 mixin(binaryExpr);
1166 }
1167
1168 void visit(DivAssignExpr e)
1169 {
1170 mixin(binaryExpr);
1171 }
1172
1173 void visit(MulAssignExpr e)
1174 {
1175 mixin(binaryExpr);
1176 }
1177
1178 void visit(ModAssignExpr e)
1179 {
1180 mixin(binaryExpr);
1181 }
1182
1183 void visit(XorAssignExpr e)
1184 {
1185 mixin(binaryExpr);
1186 }
1187
1188 void visit(CatAssignExpr e)
1189 {
1190 mixin(binaryExpr);
1191 }
1192
1193 void visit(AddressExpr e)
1194 {
1195 mixin(unaryExpr);
1196 }
1197
1198 void visit(PreIncrExpr e)
1199 {
1200 mixin(unaryExpr);
1201 }
1202
1203 void visit(PreDecrExpr e)
1204 {
1205 mixin(unaryExpr);
1206 }
1207
1208 void visit(PostIncrExpr e)
1209 {
1210 mixin(unaryExpr);
1211 }
1212
1213 void visit(PostDecrExpr e)
1214 {
1215 mixin(unaryExpr);
1216 }
1217
1218 void visit(DerefExpr e)
1219 {
1220 mixin(unaryExpr);
1221 }
1222
1223 void visit(SignExpr e)
1224 {
1225 mixin(unaryExpr);
1226 }
1227
1228 void visit(NotExpr e)
1229 {
1230 mixin(unaryExpr);
1231 }
1232
1233 void visit(CompExpr e)
1234 {
1235 mixin(unaryExpr);
1236 }
1237
1238 void visit(CallExpr e)
1239 {
1240 mixin(unaryExpr);
1241 }
1242
1243 void visit(NewExpr e)
1244 {
1245 begin(e);
1246 writeNodes(e.newArgs);
1247 write(",");
1248 visitT(e.type);
1249 write(",");
1250 writeNodes(e.ctorArgs);
1251 end(e);
1252 }
1253
1254 void visit(NewClassExpr e)
1255 {
1256 begin(e);
1257 writeNodes(e.newArgs);
1258 write(",");
1259 writeNodes(e.bases);
1260 write(",");
1261 writeNodes(e.ctorArgs);
1262 write(",");
1263 visitD(e.decls);
1264 end(e);
1265 }
1266
1267 void visit(DeleteExpr e)
1268 {
1269 mixin(unaryExpr);
1270 }
1271
1272 void visit(CastExpr e)
1273 {
1274 begin(e);
1275 version(D2)
1276 e.type ? visitT(e.type) : write("n");
1277 else
1278 visitT(e.type);
1279 write(",");
1280 visitE(e.una);
1281 end(e);
1282 }
1283
1284 void visit(IndexExpr e)
1285 {
1286 begin(e);
1287 visitE(e.una);
1288 write(",");
1289 writeNodes(e.args);
1290 end(e);
1291 }
1292
1293 void visit(SliceExpr e)
1294 {
1295 begin(e);
1296 visitE(e.una);
1297 write(",");
1298 e.range ? visitE(e.range) : write("n");
1299 end(e);
1300 }
1301
1302 void visit(ModuleScopeExpr e)
1303 {
1304 begin(e);
1305 end(e, false);
1306 }
1307
1308 void visit(IdentifierExpr e)
1309 {
1310 begin(e);
1311 write(indexOf(e.name));
1312 end(e);
1313 }
1314
1315 void visit(TmplInstanceExpr e)
1316 {
1317 begin(e);
1318 write(indexOf(e.name));
1319 write(",");
1320 e.targs ? visitN(e.targs) : write("n");
1321 end(e);
1322 }
1323
1324 void visit(SpecialTokenExpr e)
1325 {
1326 begin(e);
1327 write(indexOf(e.specialToken));
1328 end(e);
1329 }
1330
1331 void visit(ThisExpr e)
1332 {
1333 begin(e);
1334 end(e, false);
1335 }
1336
1337 void visit(SuperExpr e)
1338 {
1339 begin(e);
1340 end(e, false);
1341 }
1342
1343 void visit(NullExpr e)
1344 {
1345 begin(e);
1346 end(e, false);
1347 }
1348
1349 void visit(DollarExpr e)
1350 {
1351 begin(e);
1352 end(e, false);
1353 }
1354
1355 void visit(BoolExpr e)
1356 {
1357 begin(e);
1358 end(e, false);
1359 }
1360
1361 void visit(IntExpr e)
1362 {
1363 begin(e);
1364 end(e, false);
1365 }
1366
1367 void visit(FloatExpr e)
1368 {
1369 begin(e);
1370 end(e, false);
1371 }
1372
1373 void visit(ComplexExpr e)
1374 {
1375 begin(e);
1376 end(e, false);
1377 }
1378
1379 void visit(CharExpr e)
1380 {
1381 begin(e);
1382 end(e, false);
1383 }
1384
1385 void visit(StringExpr e)
1386 {
1387 begin(e);
1388 end(e, false);
1389 }
1390
1391 void visit(ArrayLiteralExpr e)
1392 {
1393 begin(e);
1394 writeNodes(e.values);
1395 end(e);
1396 }
1397
1398 void visit(AArrayLiteralExpr e)
1399 {
1400 begin(e);
1401 writeNodes(e.keys);
1402 write(",");
1403 writeNodes(e.values);
1404 end(e);
1405 }
1406
1407 void visit(AssertExpr e)
1408 {
1409 begin(e);
1410 visitE(e.expr);
1411 write(",");
1412 e.msg ? visitE(e.msg) : write("n");
1413 end(e);
1414 }
1415
1416 void visit(MixinExpr e)
1417 {
1418 begin(e);
1419 visitE(e.expr);
1420 end(e);
1421 }
1422
1423 void visit(ImportExpr e)
1424 {
1425 begin(e);
1426 visitE(e.expr);
1427 end(e);
1428 }
1429
1430 void visit(TypeofExpr e)
1431 {
1432 begin(e);
1433 visitT(e.type);
1434 end(e);
1435 }
1436
1437 void visit(TypeDotIdExpr e)
1438 {
1439 begin(e);
1440 visitT(e.type);
1441 end(e);
1442 }
1443
1444 void visit(TypeidExpr e)
1445 {
1446 begin(e);
1447 visitT(e.type);
1448 end(e);
1449 }
1450
1451 void visit(IsExpr e)
1452 {
1453 begin(e);
1454 visitT(e.type);
1455 write(",");
1456 e.specType ? visitT(e.specType) : write("n");
1457 write(",");
1458 e.tparams ? visitN(e.tparams) : write("n");
1459 end(e);
1460 }
1461
1462 void visit(ParenExpr e)
1463 {
1464 begin(e);
1465 visitE(e.next);
1466 end(e);
1467 }
1468
1469 void visit(FuncLiteralExpr e)
1470 {
1471 begin(e);
1472 e.returnType ? visitT(e.returnType) : write("n");
1473 write(",");
1474 e.params ? visitN(e.params) : write("n");
1475 write(",");
1476 visitS(e.funcBody);
1477 end(e);
1478 }
1479
1480 void visit(LambdaExpr e)
1481 {
1482 begin(e);
1483 visitN(e.params);
1484 write(",");
1485 visitE(e.expr);
1486 end(e);
1487 }
1488
1489 void visit(TraitsExpr e) // D2.0
1490 {
1491 begin(e);
1492 write(indexOf(e.name)~",");
1493 visitN(e.targs);
1494 end(e);
1495 }
1496
1497 void visit(VoidInitExpr e)
1498 {
1499 begin(e);
1500 end(e, false);
1501 }
1502
1503 void visit(ArrayInitExpr e)
1504 {
1505 begin(e);
1506 write("(");
1507 foreach (k; e.keys)
1508 (k ? visitE(k) : write("n")), write(",");
1509 write("),");
1510 writeNodes(e.values);
1511 end(e);
1512 }
1513
1514 void visit(StructInitExpr e)
1515 {
1516 begin(e);
1517 write("(");
1518 foreach (i; e.idents)
1519 (i ? write(indexOf(i)) : write("n")), write(",");
1520 write("),");
1521 writeNodes(e.values);
1522 end(e);
1523 }
1524
1525 void visit(AsmTypeExpr e)
1526 {
1527 mixin(unaryExpr);
1528 }
1529
1530 void visit(AsmOffsetExpr e)
1531 {
1532 mixin(unaryExpr);
1533 }
1534
1535 void visit(AsmSegExpr e)
1536 {
1537 mixin(unaryExpr);
1538 }
1539
1540 void visit(AsmPostBracketExpr e)
1541 {
1542 begin(e);
1543 visitE(e.una);
1544 write(",");
1545 visitE(e.index);
1546 end(e);
1547 }
1548
1549 void visit(AsmBracketExpr e)
1550 {
1551 begin(e);
1552 visitE(e.expr);
1553 end(e);
1554 }
1555
1556 void visit(AsmLocalSizeExpr e)
1557 {
1558 begin(e);
1559 end(e, false);
1560 }
1561
1562 void visit(AsmRegisterExpr e)
1563 {
1564 begin(e);
1565 e.number ? visitE(e.number) : write("n");
1566 end(e);
1567 }
1568 } // override
1569
1570 /+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1571 | Types |
1572 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+/
1573
1574 override
1575 {
1576 void visit(IllegalType)
1577 { assert(0, "interpreting invalid AST"); }
1578
1579 void visit(IntegralType t)
1580 {
1581 begin(t);
1582 write(indexOf(t.begin));
1583 end(t);
1584 }
1585
1586 void visit(ModuleScopeType t)
1587 {
1588 begin(t);
1589 end(t, false);
1590 }
1591
1592 void visit(IdentifierType t)
1593 {
1594 begin(t);
1595 t.next ? visitT(t.next) : write("n");
1596 write(",");
1597 write(indexOf(t.begin));
1598 end(t);
1599 }
1600
1601 void visit(TypeofType t)
1602 {
1603 begin(t);
1604 t.expr ? visitE(t.expr) : write("n");
1605 end(t);
1606 }
1607
1608 void visit(TmplInstanceType t)
1609 {
1610 begin(t);
1611 t.next ? visitT(t.next) : write("n");
1612 write(",");
1613 write(indexOf(t.begin));
1614 write(",");
1615 t.targs ? visitN(t.targs) : write("n");
1616 end(t);
1617 }
1618
1619 void visit(PointerType t)
1620 {
1621 begin(t);
1622 visitT(t.next);
1623 end(t);
1624 }
1625
1626 void visit(ArrayType t)
1627 {
1628 begin(t);
1629 visitT(t.next);
1630 write(",");
1631 t.assocType ? visitT(t.assocType) : write("n");
1632 write(",");
1633 t.index1 ? visitE(t.index1) : write("n");
1634 write(",");
1635 t.index2 ? visitE(t.index2) : write("n");
1636 end(t);
1637 }
1638
1639 void visit(FunctionType t)
1640 {
1641 begin(t);
1642 visitT(t.returnType);
1643 write(",");
1644 visitN(t.params);
1645 end(t);
1646 }
1647
1648 void visit(DelegateType t)
1649 {
1650 begin(t);
1651 visitT(t.returnType);
1652 write(",");
1653 visitN(t.params);
1654 end(t);
1655 }
1656
1657 void visit(BaseClassType t)
1658 {
1659 begin(t);
1660 // TODO: emit t.prot?
1661 visitT(t.next);
1662 end(t);
1663 }
1664
1665 void visit(ModifierType t) // D2.0
1666 {
1667 begin(t);
1668 write(indexOf(t.mod));
1669 t.next && visitT(t.next);
1670 end(t);
1671 }
1672 } // override
1673
1674 /+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1675 | Parameters |
1676 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+/
1677
1678 override
1679 {
1680 void visit(Parameter p)
1681 {
1682 begin(p);
1683 p.type ? visitT(p.type) : write("n");
1684 write(",");
1685 p.defValue ? visitE(p.defValue) : write("n");
1686 end(p);
1687 }
1688
1689 void visit(Parameters p)
1690 {
1691 begin(p);
1692 write(p.children);
1693 end(p);
1694 }
1695
1696 void visit(TemplateAliasParam p)
1697 {
1698 begin(p);
1699 p.spec ? visitN(p.spec) : write("n");
1700 write(",");
1701 p.def ? visitN(p.def) : write("n");
1702 end(p);
1703 }
1704
1705 void visit(TemplateTypeParam p)
1706 {
1707 begin(p);
1708 p.specType ? visitT(p.specType) : write("n");
1709 write(",");
1710 p.defType ? visitT(p.defType) : write("n");
1711 end(p);
1712 }
1713
1714 void visit(TemplateThisParam p) // D2.0
1715 {
1716 begin(p);
1717 p.specType ? visitT(p.specType) : write("n");
1718 write(",");
1719 p.defType ? visitT(p.defType) : write("n");
1720 end(p);
1721 }
1722
1723 void visit(TemplateValueParam p)
1724 {
1725 begin(p);
1726 p.valueType ? visitT(p.valueType) : write("n");
1727 write(",");
1728 p.specValue ? visitE(p.specValue) : write("n");
1729 write(",");
1730 p.defValue ? visitE(p.defValue) : write("n");
1731 end(p);
1732 }
1733
1734 void visit(TemplateTupleParam p)
1735 {
1736 begin(p);
1737 end(p, false);
1738 }
1739
1740 void visit(TemplateParameters p)
1741 {
1742 begin(p);
1743 write(p.children);
1744 end(p);
1745 }
1746
1747 void visit(TemplateArguments p)
1748 {
1749 begin(p);
1750 write(p.children);
1751 end(p);
1752 }
1753 } // override
1754 }