1 // This file is part of Visual D 2 // 3 // Visual D integrates the D programming language into Visual Studio 4 // Copyright (c) 2010-2011 by Rainer Schuetze, All Rights Reserved 5 // 6 // Distributed under the Boost Software License, Version 1.0. 7 // See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt 8 // 9 // interpret: return null to indicate that execution should continue 10 // return special values for program flow control 11 // return normal values for returning values 12 // 13 module vdc.ast.stmt; 14 15 import vdc.util; 16 import vdc.lexer; 17 import vdc.ast.node; 18 import vdc.ast.expr; 19 import vdc.ast.decl; 20 import vdc.ast.type; 21 import vdc.ast.writer; 22 import vdc.semantic; 23 import vdc.interpret; 24 25 import vdc.parser.engine; 26 27 import stdext.util; 28 29 import std.conv; 30 31 //Statement: 32 // [Statement...] 33 class Statement : Node 34 { 35 mixin ForwardCtor!(); 36 37 override Value interpret(Context sc) 38 { 39 foreach(m; members) 40 { 41 Value v = m.interpret(sc); 42 if(v) 43 return v; 44 } 45 return null; 46 } 47 } 48 49 class EmptyStatement : Statement 50 { 51 mixin ForwardCtor!(); 52 53 override void toD(CodeWriter writer) 54 { 55 writer(";"); 56 writer.nl; 57 } 58 } 59 60 version(obsolete) 61 { 62 //ScopeStatement: 63 // ; 64 // NonEmptyStatement 65 // ScopeBlockStatement 66 // 67 //ScopeBlockStatement: 68 // BlockStatement 69 class ScopeStatement : Statement 70 { 71 mixin ForwardCtor!(); 72 } 73 74 //ScopeNonEmptyStatement: 75 // NonEmptyStatement 76 // BlockStatement 77 class ScopeNonEmptyStatement : Statement 78 { 79 mixin ForwardCtor!(); 80 } 81 82 //NoScopeNonEmptyStatement: 83 // NonEmptyStatement 84 // BlockStatement 85 class NoScopeNonEmptyStatement : ScopeNonEmptyStatement 86 { 87 mixin ForwardCtor!(); 88 } 89 90 //NoScopeStatement: 91 // ; 92 // NonEmptyStatement 93 // BlockStatement 94 class NoScopeStatement : ScopeStatement 95 { 96 mixin ForwardCtor!(); 97 } 98 99 //NonEmptyStatement: 100 // LabeledStatement 101 // ExpressionStatement 102 // DeclarationStatement 103 // IfStatement 104 // WhileStatement 105 // DoStatement 106 // ForStatement 107 // ForeachStatement 108 // SwitchStatement 109 // FinalSwitchStatement 110 // CaseStatement 111 // CaseRangeStatement 112 // DefaultStatement 113 // ContinueStatement 114 // BreakStatement 115 // ReturnStatement 116 // GotoStatement 117 // WithStatement 118 // SynchronizedStatement 119 // VolatileStatement 120 // TryStatement 121 // ScopeGuardStatement 122 // ThrowStatement 123 // AsmStatement 124 // PragmaStatement 125 // MixinStatement 126 // ForeachRangeStatement 127 // ConditionalStatement 128 // StaticAssert 129 // TemplateMixin 130 class NonEmptyStatement : Statement 131 { 132 mixin ForwardCtor!(); 133 } 134 } // version(obsolete) 135 136 //LabeledStatement: 137 // Identifier : NoScopeStatement 138 class LabeledStatement : Statement 139 { 140 string ident; 141 142 Statement getStatement() { return getMember!Statement(0); } 143 144 this() {} // default constructor needed for clone() 145 146 this(Token tok) 147 { 148 super(tok); 149 ident = tok.txt; 150 } 151 152 override LabeledStatement clone() 153 { 154 LabeledStatement n = static_cast!LabeledStatement(super.clone()); 155 n.ident = ident; 156 return n; 157 } 158 override bool compare(const(Node) n) const 159 { 160 if(!super.compare(n)) 161 return false; 162 163 auto tn = static_cast!(typeof(this))(n); 164 return tn.ident == ident; 165 } 166 167 override void toD(CodeWriter writer) 168 { 169 { 170 CodeIndenter indent = CodeIndenter(writer, -1); 171 writer.writeIdentifier(ident); 172 writer(":"); 173 writer.nl; 174 } 175 writer(getStatement()); 176 } 177 } 178 179 //BlockStatement: 180 // { } 181 // { StatementList } 182 // 183 //StatementList: 184 // Statement 185 // Statement StatementList 186 class BlockStatement : Statement 187 { 188 mixin ForwardCtor!(); 189 190 override void toD(CodeWriter writer) 191 { 192 writer("{"); 193 writer.nl; 194 { 195 CodeIndenter indent = CodeIndenter(writer); 196 foreach(m; members) 197 writer(m); 198 } 199 writer("}"); 200 writer.nl; 201 } 202 203 override bool createsScope() const { return true; } 204 205 override void _semantic(Scope sc) 206 { 207 // TODO: TemplateParameterList, Constraint 208 if(members.length > 0) 209 { 210 sc = enterScope(sc); 211 super._semantic(sc); 212 sc = sc.pop(); 213 } 214 } 215 216 } 217 218 //ExpressionStatement: 219 // [Expression] 220 class ExpressionStatement : Statement 221 { 222 mixin ForwardCtor!(); 223 224 override void toD(CodeWriter writer) 225 { 226 writer(getMember(0), ";"); 227 writer.nl; 228 } 229 230 override Value interpret(Context sc) 231 { 232 getMember(0).interpret(sc); 233 return null; 234 } 235 } 236 237 //DeclarationStatement: 238 // [Decl] 239 class DeclarationStatement : Statement 240 { 241 mixin ForwardCtor!(); 242 243 override void toD(CodeWriter writer) 244 { 245 writer(getMember(0)); 246 } 247 248 override Node[] expandNonScopeBlock(Scope sc, Node[] athis) 249 { 250 Node n = getMember(0); 251 Node[1] nthis = [ n ]; 252 Node[] nm = n.expandNonScopeBlock(sc, nthis); 253 if(nm.length == 1 && nm[0] == n) 254 return athis; 255 256 Node[] decls; 257 foreach(m; nm) 258 { 259 auto decl = new DeclarationStatement(id, span); 260 decl.addMember(m); 261 decls ~= decl; 262 } 263 return decls; 264 } 265 266 override void addSymbols(Scope sc) 267 { 268 addMemberSymbols(sc); 269 } 270 271 override void _semantic(Scope sc) 272 { 273 auto decl = getMember(0); 274 decl.addSymbols(sc); // symbols might already be referenced in an initializer 275 super._semantic(sc); 276 if(decl.attr & Attr_Static) 277 { 278 Context ctx = new Context(nullContext); 279 ctx.scop = sc; 280 initValues(ctx, false); 281 } 282 } 283 284 override Value interpret(Context sc) 285 { 286 auto decl = getMember(0); 287 if(!(decl.attr & Attr_Static)) 288 initValues(sc, true); 289 return null; 290 } 291 292 void initValues(Context sc, bool reinit) 293 { 294 auto decl = cast(Decl)getMember(0); 295 if(!decl) 296 return; // classes, enums, etc 297 //if(decl.getFunctionBody()) 298 // return; // nothing to do for local functions 299 300 auto decls = decl.getDeclarators(); 301 for(int n = 0; n < decls.members.length; n++) 302 { 303 auto d = decls.getDeclarator(n); 304 if(reinit) 305 { 306 d.value = null; 307 d.interpretReinit(sc); 308 } 309 else 310 d.interpret(sc); 311 } 312 } 313 } 314 315 //ImportStatement: 316 // [ImportDeclaration] 317 class ImportStatement : Statement 318 { 319 mixin ForwardCtor!(); 320 321 override void toD(CodeWriter writer) 322 { 323 getMember(0).toD(writer); 324 } 325 326 override Value interpret(Context sc) 327 { 328 return null; 329 } 330 } 331 332 //IfStatement: 333 // if ( IfCondition ) ThenStatement 334 // if ( IfCondition ) ThenStatement else ElseStatement 335 // 336 //IfCondition: 337 // Expression 338 // auto Identifier = Expression 339 // Declarator = Expression 340 // 341 //ThenStatement: 342 // ScopeNonEmptyStatement 343 // 344 //ElseStatement: 345 // ScopeNonEmptyStatement 346 class IfStatement : Statement 347 { 348 mixin ForwardCtor!(); 349 350 override void toD(CodeWriter writer) 351 { 352 writer("if(", getMember(0), ")"); 353 writer.nl; 354 { 355 CodeIndenter indent = CodeIndenter(writer); 356 writer(getMember(1)); 357 } 358 if(members.length > 2) 359 { 360 writer("else"); 361 writer.nl; 362 { 363 CodeIndenter indent = CodeIndenter(writer); 364 writer(getMember(2)); 365 } 366 } 367 } 368 369 override bool createsScope() const { return true; } 370 371 override Value interpret(Context sc) 372 { 373 Value cond = getMember(0).interpret(sc); 374 if(cond.toBool()) 375 { 376 if(Value v = getMember(1).interpret(sc)) 377 return v; 378 } 379 else if(members.length > 2) 380 { 381 if(Value v = getMember(2).interpret(sc)) 382 return v; 383 } 384 return null; 385 } 386 } 387 388 //WhileStatement: 389 // while ( Expression ) ScopeNonEmptyStatement 390 class WhileStatement : Statement 391 { 392 mixin ForwardCtor!(); 393 394 override bool createsScope() const { return true; } 395 396 override void toD(CodeWriter writer) 397 { 398 writer("while(", getMember(0), ")"); 399 writer.nl; 400 { 401 CodeIndenter indent = CodeIndenter(writer); 402 writer(getMember(1)); 403 } 404 } 405 406 override Value interpret(Context sc) 407 { 408 while(getMember(0).interpret(sc).toBool()) 409 { 410 if(Value v = getMember(1).interpret(sc)) 411 { 412 if(auto bv = cast(BreakValue)v) 413 { 414 if(!bv.label) 415 break; 416 if(auto ls = cast(LabeledStatement)parent) 417 if(ls.ident == bv.label) 418 break; 419 } 420 else if(auto cv = cast(ContinueValue)v) 421 { 422 if(!cv.label) 423 continue; 424 if(auto ls = cast(LabeledStatement)parent) 425 if(ls.ident == cv.label) 426 continue; 427 } 428 return v; 429 } 430 } 431 return null; 432 } 433 } 434 435 //DoStatement: 436 // do ScopeNonEmptyStatement while ( Expression ) 437 class DoStatement : Statement 438 { 439 mixin ForwardCtor!(); 440 441 override bool createsScope() const { return true; } 442 443 override void toD(CodeWriter writer) 444 { 445 writer("do"); 446 writer.nl; 447 { 448 CodeIndenter indent = CodeIndenter(writer); 449 writer(getMember(0)); 450 } 451 writer("while(", getMember(1), ")"); 452 writer.nl; 453 } 454 455 override Value interpret(Context sc) 456 { 457 do 458 { 459 if(Value v = getMember(0).interpret(sc)) 460 { 461 if(auto bv = cast(BreakValue)v) 462 { 463 if(!bv.label) 464 break; 465 if(auto ls = cast(LabeledStatement)parent) 466 if(ls.ident == bv.label) 467 break; 468 } 469 else if(auto cv = cast(ContinueValue)v) 470 { 471 if(!cv.label) 472 continue; 473 if(auto ls = cast(LabeledStatement)parent) 474 if(ls.ident == cv.label) 475 continue; 476 } 477 return v; 478 } 479 } 480 while(getMember(1).interpret(sc).toBool()); 481 return null; 482 } 483 } 484 485 //ForStatement: 486 // for ( Initialize Test ; Increment ) ScopeNonEmptyStatement 487 //Initialize: 488 // ; 489 // NoScopeNonEmptyStatement 490 // 491 //Test: 492 // Expression_opt 493 // 494 //Increment: 495 // Expression_opt 496 // 497 class ForStatement : Statement 498 { 499 mixin ForwardCtor!(); 500 501 override bool createsScope() const { return true; } 502 503 override void toD(CodeWriter writer) 504 { 505 writer("for(", getMember(0), getMember(1), "; ", getMember(2), ")"); 506 writer.nl; 507 { 508 CodeIndenter indent = CodeIndenter(writer); 509 writer(getMember(3)); 510 } 511 } 512 513 override Value interpret(Context sc) 514 { 515 for(getMember(0).interpret(sc); getMember(1).interpret(sc).toBool(); 516 getMember(2).interpret(sc)) 517 { 518 if(Value v = getMember(3).interpret(sc)) 519 { 520 if(auto bv = cast(BreakValue)v) 521 { 522 if(!bv.label) 523 break; 524 if(auto ls = cast(LabeledStatement)parent) 525 if(ls.ident == bv.label) 526 break; 527 } 528 else if(auto cv = cast(ContinueValue)v) 529 { 530 if(!cv.label) 531 continue; 532 if(auto ls = cast(LabeledStatement)parent) 533 if(ls.ident == cv.label) 534 continue; 535 } 536 return v; 537 } 538 } 539 return null; 540 } 541 } 542 543 //ForeachStatement: 544 // Foreach ( ForeachTypeList ; Aggregate ) NoScopeNonEmptyStatement 545 // 546 //Foreach: 547 // foreach 548 // foreach_reverse 549 // 550 //ForeachTypeList: 551 // ForeachType 552 // ForeachType , ForeachTypeList 553 // 554 //ForeachType: 555 // ref Type Identifier 556 // Type Identifier 557 // ref Identifier 558 // Identifier 559 // 560 //Aggregate: 561 // Expression 562 // 563 //ForeachRangeStatement: 564 // Foreach ( ForeachType ; LwrExpression .. UprExpression ) ScopeNonEmptyStatement 565 // 566 //LwrExpression: 567 // Expression 568 // 569 //UprExpression: 570 // Expression 571 class ForeachStatement : Statement 572 { 573 mixin ForwardCtor!(); 574 575 override bool createsScope() const { return true; } 576 577 Expression getAggregate() { return getMember!Expression(1); } 578 Expression getLwrExpression() { return getMember!Expression(1); } 579 Expression getUprExpression() { return getMember!Expression(2); } 580 581 final bool isRangeForeach() const { return members.length > 3; } 582 583 override void toD(CodeWriter writer) 584 { 585 writer(id, "(", getMember(0), "; "); 586 if(members.length == 3) 587 writer(getMember(1)); 588 else 589 writer(getMember(1), " .. ", getMember(2)); 590 591 writer(")"); 592 writer.nl; 593 { 594 CodeIndenter indent = CodeIndenter(writer); 595 writer(getMember(members.length - 1)); 596 } 597 } 598 599 override Value interpret(Context sc) 600 { 601 return semanticErrorValue(this, " not implemented."); 602 } 603 } 604 605 class ForeachTypeList : Node 606 { 607 mixin ForwardCtor!(); 608 609 override void toD(CodeWriter writer) 610 { 611 writer.writeArray(members); 612 } 613 614 override void addSymbols(Scope sc) 615 { 616 addMemberSymbols(sc); 617 } 618 } 619 620 class ForeachType : Node 621 { 622 mixin ForwardCtor!(); 623 624 bool isRef; 625 Type type; 626 627 Type getType() { return members.length == 2 ? getMember!Type(0) : null; } 628 Identifier getIdentifier() { return getMember!Identifier(members.length - 1); } 629 630 override ForeachType clone() 631 { 632 ForeachType n = static_cast!ForeachType(super.clone()); 633 n.isRef = isRef; 634 return n; 635 } 636 override bool compare(const(Node) n) const 637 { 638 if(!super.compare(n)) 639 return false; 640 641 auto tn = static_cast!(typeof(this))(n); 642 return tn.isRef == isRef; 643 } 644 645 override void toD(CodeWriter writer) 646 { 647 if(isRef) 648 writer("ref "); 649 writer.writeArray(members, " "); 650 } 651 652 override void addSymbols(Scope sc) 653 { 654 string ident = getIdentifier().ident; 655 sc.addSymbol(ident, this); 656 } 657 658 override Type calcType() 659 { 660 if(type) 661 return type; 662 663 if(auto t = getType()) 664 type = t.calcType(); 665 666 else if(ForeachStatement stmt = parent ? cast(ForeachStatement) parent.parent : null) 667 { 668 if(stmt.isRangeForeach()) 669 type = stmt.getLwrExpression().calcType(); 670 else 671 { 672 Expression expr = stmt.getAggregate(); 673 Type et = expr.calcType(); 674 if(auto ti = cast(TypeIndirection) et) 675 { 676 type = ti.getNextType(); 677 } 678 } 679 } 680 if(!type) 681 type = semanticErrorType("cannot infer type of foreach variable ", getIdentifier().ident); 682 return type; 683 } 684 } 685 686 //SwitchStatement: 687 // switch ( Expression ) ScopeNonEmptyStatement 688 class SwitchStatement : Statement 689 { 690 mixin ForwardCtor!(); 691 692 bool isFinal; 693 694 override bool createsScope() const { return true; } 695 696 override SwitchStatement clone() 697 { 698 SwitchStatement n = static_cast!SwitchStatement(super.clone()); 699 n.isFinal = isFinal; 700 return n; 701 } 702 override bool compare(const(Node) n) const 703 { 704 if(!super.compare(n)) 705 return false; 706 707 auto tn = static_cast!(typeof(this))(n); 708 return tn.isFinal == isFinal; 709 } 710 711 override void toD(CodeWriter writer) 712 { 713 if(isFinal) 714 writer("final "); 715 writer("switch(", getMember(0), ")"); 716 writer.nl; 717 { 718 CodeIndenter indent = CodeIndenter(writer); 719 writer(getMember(1)); 720 } 721 } 722 723 override Value interpret(Context sc) 724 { 725 return semanticErrorValue(this, " not implemented."); 726 } 727 } 728 729 //FinalSwitchStatement: 730 // final switch ( Expression ) ScopeNonEmptyStatement 731 // 732 class FinalSwitchStatement : Statement 733 { 734 mixin ForwardCtor!(); 735 736 override Value interpret(Context sc) 737 { 738 return semanticErrorValue(this, " not implemented."); 739 } 740 } 741 742 //CaseStatement: 743 // case ArgumentList : Statement 744 // 745 //CaseRangeStatement: 746 // case FirstExp : .. case LastExp : Statement 747 // 748 //FirstExp: 749 // AssignExpression 750 // 751 //LastExp: 752 // AssignExpression 753 class CaseStatement : Statement 754 { 755 mixin ForwardCtor!(); 756 757 override void toD(CodeWriter writer) 758 { 759 { 760 CodeIndenter indent = CodeIndenter(writer, -1); 761 writer("case ", getMember(0)); 762 if(id == TOK_slice) 763 { 764 writer(": .. case ", getMember(1)); 765 } 766 else 767 { 768 writer.writeArray(members[1..$], ", ", true); 769 } 770 writer(":"); 771 } 772 writer.nl(); 773 } 774 775 override Value interpret(Context sc) 776 { 777 return semanticErrorValue(this, " not implemented."); 778 } 779 } 780 781 //DefaultStatement: 782 // default : Statement 783 class DefaultStatement : Statement 784 { 785 mixin ForwardCtor!(); 786 787 override void toD(CodeWriter writer) 788 { 789 { 790 CodeIndenter indent = CodeIndenter(writer, -1); 791 writer("default:"); 792 } 793 writer.nl(); 794 } 795 796 override Value interpret(Context sc) 797 { 798 return semanticErrorValue(this, " not implemented."); 799 } 800 } 801 802 //ContinueStatement: 803 // continue ; 804 // continue Identifier ; 805 class ContinueStatement : Statement 806 { 807 mixin ForwardCtor!(); 808 809 string ident; 810 811 override ContinueStatement clone() 812 { 813 ContinueStatement n = static_cast!ContinueStatement(super.clone()); 814 n.ident = ident; 815 return n; 816 } 817 override bool compare(const(Node) n) const 818 { 819 if(!super.compare(n)) 820 return false; 821 822 auto tn = static_cast!(typeof(this))(n); 823 return tn.ident == ident; 824 } 825 826 override void toD(CodeWriter writer) 827 { 828 writer("continue"); 829 if(ident.length) 830 { 831 writer(" "); 832 writer.writeIdentifier(ident); 833 } 834 writer(";"); 835 writer.nl; 836 } 837 838 override Value interpret(Context sc) 839 { 840 return new ContinueValue(ident); 841 } 842 } 843 844 //BreakStatement: 845 // break ; 846 // break Identifier ; 847 class BreakStatement : Statement 848 { 849 mixin ForwardCtor!(); 850 851 string ident; 852 853 override BreakStatement clone() 854 { 855 BreakStatement n = static_cast!BreakStatement(super.clone()); 856 n.ident = ident; 857 return n; 858 } 859 override bool compare(const(Node) n) const 860 { 861 if(!super.compare(n)) 862 return false; 863 864 auto tn = static_cast!(typeof(this))(n); 865 return tn.ident == ident; 866 } 867 868 override void toD(CodeWriter writer) 869 { 870 writer("break"); 871 if(ident.length) 872 { 873 writer(" "); 874 writer.writeIdentifier(ident); 875 } 876 writer(";"); 877 writer.nl; 878 } 879 880 override Value interpret(Context sc) 881 { 882 return new BreakValue(ident); 883 } 884 } 885 886 887 //ReturnStatement: 888 // return ; 889 // return Expression ; 890 class ReturnStatement : Statement 891 { 892 mixin ForwardCtor!(); 893 894 override void toD(CodeWriter writer) 895 { 896 writer("return ", getMember(0), ";"); 897 writer.nl; 898 } 899 900 override Value interpret(Context sc) 901 { 902 return getMember(0).interpret(sc); 903 } 904 } 905 906 907 //GotoStatement: 908 // goto Identifier ; 909 // goto default ; 910 // goto case ; 911 // goto case Expression ; 912 class GotoStatement : Statement 913 { 914 mixin ForwardCtor!(); 915 916 string ident; 917 918 override GotoStatement clone() 919 { 920 GotoStatement n = static_cast!GotoStatement(super.clone()); 921 n.ident = ident; 922 return n; 923 } 924 override bool compare(const(Node) n) const 925 { 926 if(!super.compare(n)) 927 return false; 928 929 auto tn = static_cast!(typeof(this))(n); 930 return tn.ident == ident; 931 } 932 933 override void toD(CodeWriter writer) 934 { 935 if(id == TOK_Identifier) 936 { 937 writer("goto "); 938 writer.writeIdentifier(ident); 939 writer(";"); 940 } 941 else if(id == TOK_default) 942 writer("goto default;"); 943 else 944 { 945 if(members.length > 0) 946 writer("goto case ", getMember(0), ";"); 947 else 948 writer("goto case;"); 949 } 950 writer.nl; 951 } 952 953 override Value interpret(Context sc) 954 { 955 return semanticErrorValue(this, " not implemented."); 956 } 957 } 958 959 //WithStatement: 960 // with ( Expression ) ScopeNonEmptyStatement 961 // with ( Symbol ) ScopeNonEmptyStatement 962 // with ( TemplateInstance ) ScopeNonEmptyStatement 963 class WithStatement : Statement 964 { 965 mixin ForwardCtor!(); 966 967 override bool createsScope() const { return true; } 968 969 override void toD(CodeWriter writer) 970 { 971 writer("with(", getMember(0), ")"); 972 writer.nl; 973 { 974 CodeIndenter indent = CodeIndenter(writer); 975 writer(getMember(1)); 976 } 977 } 978 979 override Value interpret(Context sc) 980 { 981 return semanticErrorValue(this, " not implemented."); 982 } 983 } 984 985 //SynchronizedStatement: 986 // [Expression_opt ScopeNonEmptyStatement] 987 class SynchronizedStatement : Statement 988 { 989 mixin ForwardCtor!(); 990 991 override bool createsScope() const { return true; } 992 993 override void toD(CodeWriter writer) 994 { 995 if(members.length > 1) 996 writer("synchronized(", getMember(0), ") "); 997 else 998 writer("synchronized "); 999 1000 writer.nl; 1001 { 1002 CodeIndenter indent = CodeIndenter(writer); 1003 writer(getMember(members.length - 1)); 1004 } 1005 } 1006 1007 override Value interpret(Context sc) 1008 { 1009 // no need to synhronize, interpreter is single-threaded 1010 return getMember(members.length - 1).interpret(sc); 1011 } 1012 } 1013 1014 //VolatileStatement: 1015 // [ScopeNonEmptyStatement] 1016 class VolatileStatement : Statement 1017 { 1018 mixin ForwardCtor!(); 1019 1020 override bool createsScope() const { return true; } 1021 1022 override void toD(CodeWriter writer) 1023 { 1024 writer("volatile "); 1025 writer.nl; 1026 { 1027 CodeIndenter indent = CodeIndenter(writer); 1028 writer(getMember(members.length - 1)); 1029 } 1030 } 1031 1032 override Value interpret(Context sc) 1033 { 1034 // no need to synhronize, interpreter is single-threaded 1035 return super.interpret(sc); 1036 } 1037 } 1038 1039 1040 //TryStatement: 1041 // try ScopeNonEmptyStatement Catches 1042 // try ScopeNonEmptyStatement Catches FinallyStatement 1043 // try ScopeNonEmptyStatement FinallyStatement 1044 // 1045 //Catches: 1046 // LastCatch 1047 // Catch 1048 // Catch Catches 1049 // 1050 //LastCatch: 1051 // catch NoScopeNonEmptyStatement 1052 // 1053 //Catch: 1054 // catch ( CatchParameter ) NoScopeNonEmptyStatement 1055 // 1056 //CatchParameter: 1057 // BasicType Identifier 1058 // 1059 //FinallyStatement: 1060 // finally NoScopeNonEmptyStatement 1061 class TryStatement : Statement 1062 { 1063 mixin ForwardCtor!(); 1064 1065 override bool createsScope() const { return true; } 1066 1067 override void toD(CodeWriter writer) 1068 { 1069 writer("try"); 1070 writer.nl(); 1071 { 1072 CodeIndenter indent = CodeIndenter(writer); 1073 writer(getMember(0)); 1074 } 1075 foreach(m; members[1..$]) 1076 writer(m); 1077 } 1078 1079 override Value interpret(Context sc) 1080 { 1081 return semanticErrorValue(this, " not implemented."); 1082 } 1083 } 1084 1085 class Catch : Node 1086 { 1087 mixin ForwardCtor!(); 1088 1089 override bool createsScope() const { return true; } 1090 1091 override void toD(CodeWriter writer) 1092 { 1093 if(members.length > 2) 1094 writer("catch(", getMember(0), " ", getMember(1), ")"); 1095 else if(members.length > 1) 1096 writer("catch(", getMember(0), ")"); 1097 else 1098 writer("catch"); 1099 writer.nl(); 1100 { 1101 CodeIndenter indent = CodeIndenter(writer); 1102 writer(getMember(members.length - 1)); 1103 } 1104 } 1105 } 1106 1107 class FinallyStatement : Catch 1108 { 1109 mixin ForwardCtor!(); 1110 1111 override bool createsScope() const { return true; } 1112 1113 override void toD(CodeWriter writer) 1114 { 1115 writer("finally"); 1116 writer.nl(); 1117 { 1118 CodeIndenter indent = CodeIndenter(writer); 1119 writer(getMember(0)); 1120 } 1121 } 1122 } 1123 1124 1125 //ThrowStatement: 1126 // throw Expression ; 1127 class ThrowStatement : Statement 1128 { 1129 mixin ForwardCtor!(); 1130 1131 override void toD(CodeWriter writer) 1132 { 1133 writer("throw ", getMember(0), ";"); 1134 writer.nl; 1135 } 1136 1137 override Value interpret(Context sc) 1138 { 1139 return semanticErrorValue(this, " not implemented."); 1140 } 1141 } 1142 1143 //ScopeGuardStatement: 1144 // scope ( "exit" ) ScopeNonEmptyStatement 1145 // scope ( "success" ) ScopeNonEmptyStatement 1146 // scope ( "failure" ) ScopeNonEmptyStatement 1147 class ScopeGuardStatement : Statement 1148 { 1149 mixin ForwardCtor!(); 1150 1151 override bool createsScope() const { return true; } 1152 1153 override void toD(CodeWriter writer) 1154 { 1155 writer("scope(", getMember(0), ")"); 1156 writer.nl; 1157 { 1158 CodeIndenter indent = CodeIndenter(writer); 1159 writer(getMember(1)); 1160 } 1161 } 1162 1163 override Value interpret(Context sc) 1164 { 1165 return semanticErrorValue(this, " not implemented."); 1166 } 1167 } 1168 1169 //AsmStatement: 1170 // asm { } 1171 // asm { AsmInstructionList } 1172 // 1173 //AsmInstructionList: 1174 // AsmInstruction ; 1175 // AsmInstruction ; AsmInstructionList 1176 class AsmStatement : Statement 1177 { 1178 mixin ForwardCtor!(); 1179 1180 override void toD(CodeWriter writer) 1181 { 1182 writer("asm {"); 1183 writer.nl; 1184 { 1185 CodeIndenter indent = CodeIndenter(writer); 1186 writer(getMember(0)); 1187 } 1188 writer("}"); 1189 writer.nl; 1190 } 1191 1192 override Value interpret(Context sc) 1193 { 1194 return semanticErrorValue(this, " cannot be interpreted."); 1195 } 1196 } 1197 1198 class AsmInstructionList : Node 1199 { 1200 mixin ForwardCtor!(); 1201 1202 override void toD(CodeWriter writer) 1203 { 1204 foreach(m; members) 1205 { 1206 writer(m, ";"); 1207 writer.nl(); 1208 } 1209 } 1210 } 1211 1212 //PragmaStatement: 1213 // Pragma NoScopeStatement 1214 class PragmaStatement : Statement 1215 { 1216 mixin ForwardCtor!(); 1217 1218 override void toD(CodeWriter writer) 1219 { 1220 writer(getMember(0), " ", getMember(1)); 1221 } 1222 1223 override Value interpret(Context sc) 1224 { 1225 getMember(0).interpret(sc); 1226 return getMember(1).interpret(sc); 1227 } 1228 } 1229 1230 //MixinStatement: 1231 // [ AssignExpression ] 1232 class MixinStatement : Statement 1233 { 1234 mixin ForwardCtor!(); 1235 1236 override void toD(CodeWriter writer) 1237 { 1238 writer("mixin(", getMember(0), ");"); 1239 writer.nl; 1240 } 1241 1242 override void _semantic(Scope sc) 1243 { 1244 Context ctx = new Context(nullContext); 1245 ctx.scop = sc; 1246 Value v = getMember(0).interpretCatch(ctx); 1247 string s = v.toMixin(); 1248 Parser parser = new Parser; 1249 if(auto prj = sc.getProject()) 1250 parser.saveErrors = prj.saveErrors; 1251 Node[] n = parser.parseStatements(s, span); 1252 parent.replaceMember(this, n); 1253 } 1254 1255 override Value interpret(Context sc) 1256 { 1257 return semanticErrorValue(this, " semantic not run"); 1258 } 1259 }