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 }