1 /// Author: Aziz Köksal 2 /// License: GPL3 3 /// $(Maturity high) 4 module dil.ast.Statements; 5 6 public import dil.ast.Statement; 7 import dil.ast.Node, 8 dil.ast.Expression, 9 dil.ast.Declaration, 10 dil.ast.Type, 11 dil.ast.Parameters, 12 dil.ast.NodeCopier, 13 dil.ast.Meta; 14 import dil.lexer.IdTable; 15 import common; 16 17 class CompoundStmt : Statement 18 { 19 this() 20 { 21 mixin(set_kind); 22 } 23 24 this(Statement[] stmnts) 25 { 26 this(); 27 addChildren(stmnts); 28 } 29 30 void opCatAssign(Statement s) 31 { 32 addChild(s); 33 } 34 35 Statement[] stmnts() @property 36 { 37 return cast(Statement[])this.children; 38 } 39 40 void stmnts(Statement[] stmnts) @property 41 { 42 this.children = cast(Node[])stmnts; 43 } 44 45 mixin(memberInfo("stmnts")); 46 47 mixin methods; 48 } 49 50 class IllegalStmt : Statement 51 { 52 mixin(memberInfo()); 53 this() 54 { 55 mixin(set_kind); 56 } 57 mixin methods; 58 } 59 60 class EmptyStmt : Statement 61 { 62 mixin(memberInfo()); 63 this() 64 { 65 mixin(set_kind); 66 } 67 mixin methods; 68 } 69 70 class FuncBodyStmt : Statement 71 { 72 Statement funcBody, inBody, outBody; 73 Token* outIdent; /// $(BNF "out" ("(" Identifier ")")?) 74 mixin(memberInfo("funcBody?", "inBody?", "outBody?", "outIdent?")); 75 this(Statement funcBody, Statement inBody, Statement outBody, 76 Token* outIdent) 77 { 78 mixin(set_kind); 79 addOptChild(funcBody); 80 addOptChild(inBody); 81 addOptChild(outBody); 82 this.funcBody = funcBody; 83 this.inBody = inBody; 84 this.outBody = outBody; 85 this.outIdent = outIdent; 86 } 87 88 bool isEmpty() 89 { 90 return funcBody is null; 91 } 92 93 mixin methods; 94 } 95 96 class ScopeStmt : Statement 97 { 98 Statement stmnt; 99 mixin(memberInfo("stmnt")); 100 this(Statement s) 101 { 102 mixin(set_kind); 103 addChild(s); 104 this.stmnt = s; 105 } 106 mixin methods; 107 } 108 109 class LabeledStmt : Statement 110 { 111 Token* label; 112 Statement stmnt; 113 mixin(memberInfo("label", "stmnt")); 114 this(Token* label, Statement s) 115 { 116 mixin(set_kind); 117 addChild(s); 118 this.label = label; 119 this.stmnt = s; 120 } 121 mixin methods; 122 } 123 124 class ExpressionStmt : Statement 125 { 126 Expression expr; 127 mixin(memberInfo("expr")); 128 this(Expression e) 129 { 130 mixin(set_kind); 131 addChild(e); 132 this.expr = e; 133 } 134 mixin methods; 135 } 136 137 class DeclarationStmt : Statement 138 { 139 Declaration decl; 140 mixin(memberInfo("decl")); 141 this(Declaration decl) 142 { 143 mixin(set_kind); 144 addChild(decl); 145 this.decl = decl; 146 } 147 mixin methods; 148 } 149 150 class IfStmt : Statement 151 { 152 Declaration variable; // VariablesDecl 153 Expression condition; 154 Statement ifBody; 155 Statement elseBody; 156 mixin(memberInfo("variable?", "condition?", "ifBody", "elseBody?")); 157 this(Declaration variable, Expression condition, Statement ifBody, 158 Statement elseBody) 159 { 160 mixin(set_kind); 161 if (variable) { 162 addChild(variable); 163 assert(variable.kind == NodeKind.VariablesDecl); 164 } 165 else 166 addChild(condition); 167 addChild(ifBody); 168 addOptChild(elseBody); 169 170 this.variable = variable; 171 this.condition = condition; 172 this.ifBody = ifBody; 173 this.elseBody = elseBody; 174 } 175 mixin methods; 176 } 177 178 class WhileStmt : Statement 179 { 180 Expression condition; 181 Statement whileBody; 182 mixin(memberInfo("condition", "whileBody")); 183 this(Expression condition, Statement whileBody) 184 { 185 mixin(set_kind); 186 addChild(condition); 187 addChild(whileBody); 188 189 this.condition = condition; 190 this.whileBody = whileBody; 191 } 192 mixin methods; 193 } 194 195 class DoWhileStmt : Statement 196 { 197 Statement doBody; 198 Expression condition; 199 mixin(memberInfo("condition", "doBody")); 200 this(Expression condition, Statement doBody) 201 { 202 mixin(set_kind); 203 addChild(doBody); 204 addChild(condition); 205 206 this.condition = condition; 207 this.doBody = doBody; 208 } 209 mixin methods; 210 } 211 212 class ForStmt : Statement 213 { 214 Statement init; 215 Expression condition, increment; 216 Statement forBody; 217 218 mixin(memberInfo("init?", "condition?", "increment?", "forBody")); 219 this(Statement init, Expression condition, Expression increment, Statement forBody) 220 { 221 mixin(set_kind); 222 addOptChild(init); 223 addOptChild(condition); 224 addOptChild(increment); 225 addChild(forBody); 226 227 this.init = init; 228 this.condition = condition; 229 this.increment = increment; 230 this.forBody = forBody; 231 } 232 mixin methods; 233 } 234 235 class ForeachStmt : Statement 236 { 237 TOK tok; 238 Parameters params; 239 Expression aggregate; 240 Statement forBody; 241 242 mixin(memberInfo("tok", "params", "aggregate", "forBody")); 243 this(TOK tok, Parameters params, Expression aggregate, Statement forBody) 244 { 245 mixin(set_kind); 246 addChildren([cast(Node)params, aggregate, forBody]); 247 248 this.tok = tok; 249 this.params = params; 250 this.aggregate = aggregate; 251 this.forBody = forBody; 252 } 253 254 /// Returns true if this is a foreach_reverse statement. 255 bool isReverse() 256 { 257 return tok == TOK.ForeachReverse; 258 } 259 260 /// Returns true if the aggregate is a RangeExpr. 261 bool hasRange() 262 { 263 return aggregate.kind == NodeKind.RangeExpr; 264 } 265 266 mixin methods; 267 } 268 269 class SwitchStmt : Statement 270 { 271 Expression condition; 272 Statement switchBody; 273 bool isFinal; 274 275 mixin(memberInfo("condition", "switchBody", "isFinal")); 276 this(Expression condition, Statement switchBody, bool isFinal = false) 277 { 278 mixin(set_kind); 279 addChild(condition); 280 addChild(switchBody); 281 282 this.condition = condition; 283 this.switchBody = switchBody; 284 this.isFinal = isFinal; 285 } 286 mixin methods; 287 } 288 289 class CaseStmt : Statement 290 { 291 Expression[] values; 292 Statement caseBody; 293 294 mixin(memberInfo("values", "caseBody")); 295 this(Expression[] values, Statement caseBody) 296 { 297 mixin(set_kind); 298 addChildren(values); 299 addChild(caseBody); 300 301 this.values = values; 302 this.caseBody = caseBody; 303 } 304 mixin methods; 305 } 306 307 // D2 308 class CaseRangeStmt : Statement 309 { 310 Expression left, right; 311 Statement caseBody; 312 313 mixin(memberInfo("left", "right", "caseBody")); 314 this(Expression left, Expression right, Statement caseBody) 315 { 316 mixin(set_kind); 317 addChild(left); 318 addChild(right); 319 addChild(caseBody); 320 321 this.left = left; 322 this.right = right; 323 this.caseBody = caseBody; 324 } 325 mixin methods; 326 } 327 328 class DefaultStmt : Statement 329 { 330 Statement defaultBody; 331 mixin(memberInfo("defaultBody")); 332 this(Statement defaultBody) 333 { 334 mixin(set_kind); 335 addChild(defaultBody); 336 337 this.defaultBody = defaultBody; 338 } 339 mixin methods; 340 } 341 342 class ContinueStmt : Statement 343 { 344 Token* label; 345 mixin(memberInfo("label?")); 346 this(Token* label) 347 { 348 mixin(set_kind); 349 this.label = label; 350 } 351 mixin methods; 352 } 353 354 class BreakStmt : Statement 355 { 356 Token* label; 357 mixin(memberInfo("label?")); 358 this(Token* label) 359 { 360 mixin(set_kind); 361 this.label = label; 362 } 363 mixin methods; 364 } 365 366 class ReturnStmt : Statement 367 { 368 Expression expr; 369 mixin(memberInfo("expr?")); 370 this(Expression e) 371 { 372 mixin(set_kind); 373 addOptChild(e); 374 this.expr = e; 375 } 376 mixin methods; 377 } 378 379 class GotoStmt : Statement 380 { 381 Token* ident; /// The label id, case or default. 382 Expression expr; 383 mixin(memberInfo("ident", "expr?")); 384 this(Token* ident, Expression expr) 385 { 386 mixin(set_kind); 387 addOptChild(expr); 388 this.ident = ident; 389 this.expr = expr; 390 } 391 392 bool isGotoLabel() @property 393 { 394 return ident.kind == TOK.Identifier; 395 } 396 397 bool isGotoCase() @property 398 { 399 return ident.kind == TOK.Goto; 400 } 401 402 bool isGotoDefault() @property 403 { 404 return ident.kind == TOK.Default; 405 } 406 407 mixin methods; 408 } 409 410 class WithStmt : Statement 411 { 412 Expression expr; 413 Statement withBody; 414 mixin(memberInfo("expr", "withBody")); 415 this(Expression e, Statement withBody) 416 { 417 mixin(set_kind); 418 addChild(e); 419 addChild(withBody); 420 421 this.expr = e; 422 this.withBody = withBody; 423 } 424 mixin methods; 425 } 426 427 class SynchronizedStmt : Statement 428 { 429 Expression expr; 430 Statement syncBody; 431 mixin(memberInfo("expr?", "syncBody")); 432 this(Expression e, Statement syncBody) 433 { 434 mixin(set_kind); 435 addOptChild(e); 436 addChild(syncBody); 437 438 this.expr = e; 439 this.syncBody = syncBody; 440 } 441 mixin methods; 442 } 443 444 class TryStmt : Statement 445 { 446 Statement tryBody; 447 CatchStmt[] catchBodies; 448 FinallyStmt finallyBody; 449 mixin(memberInfo("tryBody", "catchBodies", "finallyBody?")); 450 this(Statement tryBody, CatchStmt[] catchBodies, FinallyStmt finallyBody) 451 { 452 mixin(set_kind); 453 addChild(tryBody); 454 addOptChildren(catchBodies); 455 addOptChild(finallyBody); 456 457 this.tryBody = tryBody; 458 this.catchBodies = catchBodies; 459 this.finallyBody = finallyBody; 460 } 461 mixin methods; 462 } 463 464 class CatchStmt : Statement 465 { 466 Parameter param; 467 Statement catchBody; 468 mixin(memberInfo("param?", "catchBody")); 469 this(Parameter param, Statement catchBody) 470 { 471 mixin(set_kind); 472 addOptChild(param); 473 addChild(catchBody); 474 this.param = param; 475 this.catchBody = catchBody; 476 } 477 mixin methods; 478 } 479 480 class FinallyStmt : Statement 481 { 482 Statement finallyBody; 483 mixin(memberInfo("finallyBody")); 484 this(Statement finallyBody) 485 { 486 mixin(set_kind); 487 addChild(finallyBody); 488 this.finallyBody = finallyBody; 489 } 490 mixin methods; 491 } 492 493 class ScopeGuardStmt : Statement 494 { 495 Token* condition; 496 Statement scopeBody; 497 mixin(memberInfo("condition", "scopeBody")); 498 this(Token* condition, Statement scopeBody) 499 { 500 mixin(set_kind); 501 addChild(scopeBody); 502 this.condition = condition; 503 this.scopeBody = scopeBody; 504 } 505 mixin methods; 506 } 507 508 class ThrowStmt : Statement 509 { 510 Expression expr; 511 mixin(memberInfo("expr")); 512 this(Expression e) 513 { 514 mixin(set_kind); 515 addChild(e); 516 this.expr = e; 517 } 518 mixin methods; 519 } 520 521 class VolatileStmt : Statement 522 { 523 Statement volatileBody; 524 mixin(memberInfo("volatileBody?")); 525 this(Statement volatileBody) 526 { 527 mixin(set_kind); 528 addOptChild(volatileBody); 529 this.volatileBody = volatileBody; 530 } 531 mixin methods; 532 } 533 534 class AsmBlockStmt : Statement 535 { 536 CompoundStmt statements; 537 mixin(memberInfo("statements")); 538 this(CompoundStmt statements) 539 { 540 mixin(set_kind); 541 addChild(statements); 542 this.statements = statements; 543 } 544 mixin methods; 545 } 546 547 class AsmStmt : Statement 548 { 549 Token* opcode; 550 Expression[] operands; 551 mixin(memberInfo("opcode", "operands")); 552 this(Token* opcode, Expression[] operands) 553 { 554 mixin(set_kind); 555 addOptChildren(operands); 556 this.opcode = opcode; 557 this.operands = operands; 558 } 559 mixin methods; 560 } 561 562 class AsmAlignStmt : Statement 563 { 564 int number; 565 Token* numtok; 566 mixin(memberInfo("numtok")); 567 this(Token* numtok) 568 { 569 mixin(set_kind); 570 this.numtok = numtok; 571 this.number = numtok.int_; 572 } 573 mixin methods; 574 } 575 576 class IllegalAsmStmt : Statement 577 { 578 mixin(memberInfo()); 579 this() 580 { 581 mixin(set_kind); 582 } 583 mixin methods; 584 } 585 586 class PragmaStmt : Statement 587 { 588 Token* name; 589 Expression[] args; 590 Statement pragmaBody; 591 mixin(memberInfo("name", "args", "pragmaBody")); 592 this(Token* name, Expression[] args, Statement pragmaBody) 593 { 594 mixin(set_kind); 595 addOptChildren(args); 596 addChild(pragmaBody); 597 598 this.name = name; 599 this.args = args; 600 this.pragmaBody = pragmaBody; 601 } 602 mixin methods; 603 } 604 605 class MixinStmt : Statement 606 { 607 Expression templateExpr; 608 Token* mixinIdent; 609 mixin(memberInfo("templateExpr", "mixinIdent")); 610 this(Expression templateExpr, Token* mixinIdent) 611 { 612 mixin(set_kind); 613 addChild(templateExpr); 614 this.templateExpr = templateExpr; 615 this.mixinIdent = mixinIdent; 616 } 617 mixin methods; 618 } 619 620 class StaticIfStmt : Statement 621 { 622 Expression condition; 623 Statement ifBody, elseBody; 624 mixin(memberInfo("condition", "ifBody", "elseBody?")); 625 this(Expression condition, Statement ifBody, Statement elseBody) 626 { 627 mixin(set_kind); 628 addChild(condition); 629 addChild(ifBody); 630 addOptChild(elseBody); 631 this.condition = condition; 632 this.ifBody = ifBody; 633 this.elseBody = elseBody; 634 } 635 mixin methods; 636 } 637 638 class StaticAssertStmt : Statement 639 { 640 Expression condition, message; 641 mixin(memberInfo("condition", "message?")); 642 this(Expression condition, Expression message) 643 { 644 mixin(set_kind); 645 addChild(condition); 646 addOptChild(message); 647 this.condition = condition; 648 this.message = message; 649 } 650 mixin methods; 651 } 652 653 abstract class ConditionalCompilationStmt : Statement 654 { 655 Token* cond; 656 Statement mainBody, elseBody; 657 this(Token* cond, Statement mainBody, Statement elseBody) 658 { 659 addChild(mainBody); 660 addOptChild(elseBody); 661 this.cond = cond; 662 this.mainBody = mainBody; 663 this.elseBody = elseBody; 664 } 665 } 666 667 class DebugStmt : ConditionalCompilationStmt 668 { 669 mixin(memberInfo("cond?", "mainBody", "elseBody?")); 670 this(Token* cond, Statement debugBody, Statement elseBody) 671 { 672 super(cond, debugBody, elseBody); 673 mixin(set_kind); 674 } 675 mixin methods; 676 } 677 678 class VersionStmt : ConditionalCompilationStmt 679 { 680 mixin(memberInfo("cond", "mainBody", "elseBody?")); 681 this(Token* cond, Statement versionBody, Statement elseBody) 682 { 683 super(cond, versionBody, elseBody); 684 mixin(set_kind); 685 } 686 mixin methods; 687 }