1 /// Author: Aziz Köksal 2 /// License: GPL3 3 /// $(Maturity low) 4 /// Description: This module is here for testing 5 /// a different algorithm to do semantic analysis 6 /// compared to SemanticPass1 and SemanticPass2! 7 module dil.semantic.Passes; 8 9 import dil.ast.DefaultVisitor, 10 dil.ast.Node, 11 dil.ast.Declarations, 12 dil.ast.Expressions, 13 dil.ast.Statements, 14 dil.ast.Types, 15 dil.ast.Parameters; 16 import dil.lexer.IdTable; 17 import dil.parser.Parser; 18 import dil.semantic.Symbol, 19 dil.semantic.Symbols, 20 dil.semantic.Types, 21 dil.semantic.Scope, 22 dil.semantic.Module, 23 dil.semantic.Analysis; 24 import dil.code.Interpreter; 25 import dil.i18n.Messages; 26 import dil.Compilation, 27 dil.SourceText, 28 dil.Diagnostics, 29 dil.Enums; 30 import common; 31 32 /// Some handy aliases. 33 private alias D = Declaration; 34 private alias E = Expression; /// ditto 35 private alias S = Statement; /// ditto 36 private alias T = TypeNode; /// ditto 37 private alias P = Parameter; /// ditto 38 private alias N = Node; /// ditto 39 40 /// A Scope class with added semantic information. 41 /// (May be merged together with class Scope in the future.) 42 class SemanticScope 43 { 44 Scope scop; /// The current basic scope. 45 Module modul; /// The module to be semantically checked. 46 47 /// Constructs a SemanticScope object. 48 /// Params: 49 /// modul = The module to be processed. 50 this(Module modul) 51 { 52 this.modul = modul; 53 this.scop = new Scope(null, modul); 54 } 55 56 /// Returns the ScopeSymbol of this scope (class/function/etc.) 57 ScopeSymbol symbol() @property 58 { 59 return scop.symbol; 60 } 61 62 /// Returns true if this is the module scope. 63 bool isModuleScope() @property 64 { 65 return scop.symbol.isModule(); 66 } 67 68 void enter(ScopeSymbol s) 69 { 70 scop = scop.enter(s); 71 } 72 73 void exit() 74 { 75 scop = scop.exit(); 76 } 77 78 /// Inserts a symbol into the current scope. 79 void insert(Symbol symbol) 80 { 81 insert(symbol, symbol.name); 82 } 83 84 /// Inserts a symbol into the current scope. 85 void insert(Symbol symbol, Identifier* name) 86 { 87 auto symX = scop.symbol.lookup(name); 88 if (symX) 89 reportSymbolConflict(symbol, symX, name); 90 else 91 scop.symbol.insert(symbol, name); 92 // Set the current scope symbol as the parent. 93 symbol.parent = scop.symbol; 94 } 95 96 /// Inserts a symbol into scopeSym. 97 void insert(Symbol symbol, ScopeSymbol scopeSym) 98 { 99 auto symX = scopeSym.lookup(symbol.name); 100 if (symX) 101 reportSymbolConflict(symbol, symX, symbol.name); 102 else 103 scopeSym.insert(symbol, symbol.name); 104 // Set the current scope symbol as the parent. 105 symbol.parent = scopeSym; 106 } 107 108 /// Inserts a symbol, overloading on the name, into the current scope. 109 void insertOverload(Symbol sym) 110 { 111 auto name = sym.name; 112 auto sym2 = scop.symbol.lookup(name); 113 if (sym2) 114 { 115 if (sym2.isOverloadSet) 116 sym2.to!(OverloadSet).add(sym); 117 else 118 reportSymbolConflict(sym, sym2, name); 119 } 120 else 121 // Create a new overload set. 122 scop.symbol.insert(new OverloadSet(name, sym.loc), name); 123 // Set the current scope symbol as the parent. 124 sym.parent = scop.symbol; 125 } 126 127 /// Reports an error: new symbol s1 conflicts with existing symbol s2. 128 void reportSymbolConflict(Symbol s1, Symbol s2, Identifier* name) 129 { 130 auto loc = s2.loc.t.getErrorLocation(modul.filePath()); 131 error(modul, s1.loc.t, MID.DeclConflictsWithDecl, name.str, loc.repr()); 132 } 133 134 /// Error messages are reported for undefined identifiers if true. 135 bool reportUndefinedIds; 136 /// Incremented when an undefined identifier was found. 137 uint undefinedIdsCount; 138 /// The symbol that must be ignored and skipped during a symbol search. 139 Symbol ignoreSymbol; 140 /// The current scope symbol to use for looking up identifiers. 141 /// 142 /// E.g.: 143 /// --- 144 /// / // * "object" is looked up in the current scope. 145 /// / // * idScope is set if "object" is a ScopeSymbol. 146 /// / // * "method" will be looked up in idScope. 147 /// object.method(); 148 /// / // * "dil" is looked up in the current scope 149 /// / // * idScope is set if "dil" is a ScopeSymbol. 150 /// / // * "ast" will be looked up in idScope. 151 /// / // * idScope is set if "ast" is a ScopeSymbol. 152 /// / // * etc. 153 /// dil.ast.Node.Node node; 154 /// --- 155 ScopeSymbol idScope; 156 157 /// The root of the Identifier tree. 158 Node rootIdNode; 159 160 /// This object is assigned to idScope when a symbol lookup 161 /// returned no valid symbol. 162 static ScopeSymbol emptyIdScope; 163 static this() 164 { 165 emptyIdScope = new ScopeSymbol(); 166 } 167 168 // Sets a new idScope symbol. 169 void setIdScope(Symbol symbol) 170 { 171 if (symbol) { 172 if (auto scopSymbol = cast(ScopeSymbol)symbol) 173 idScope = scopSymbol; 174 } 175 else 176 idScope = emptyIdScope; 177 } 178 179 /// Searches for a symbol. 180 Symbol search(Token* idTok) 181 { 182 assert(idTok.kind == TOK.Identifier); 183 auto id = idTok.ident; 184 Symbol symbol; 185 186 if (idScope is null) 187 // Search in the table of another symbol. 188 symbol = ignoreSymbol ? 189 scop.search(id, ignoreSymbol) : 190 scop.search(id); 191 else 192 // Search: symbol.id 193 symbol = idScope.lookup(id); 194 195 if (!symbol) 196 { 197 if (reportUndefinedIds) 198 error(modul, idTok, MID.UndefinedIdentifier, id.str); 199 undefinedIdsCount++; 200 } 201 202 return symbol; 203 } 204 } 205 206 /// Common interface for semantic passes. 207 interface SemanticPass 208 { 209 void run(); 210 void run(SemanticScope scop, Node node); 211 } 212 213 /// The first pass only declares symbols and handles imports. 214 class FirstSemanticPass : DefaultVisitor2, SemanticPass 215 { 216 Module modul; /// The module to be analyzed. 217 SemanticScope scop; /// Which scope to use for this pass. 218 ImportDecl[] imports; /// Modules to be imported. 219 // Attributes: 220 LinkageType linkageType; /// Current linkage type. 221 Protection protection; /// Current protection attribute. 222 StorageClass storageClass; /// Current storage classes. 223 uint alignSize; /// Current align size. 224 225 226 /// Constructs a SemanticPass object. 227 /// Params: 228 /// modul = The module to be processed. 229 this(Module modul) 230 { 231 this.alignSize = modul.cc.structAlign; 232 this.modul = modul; 233 } 234 235 /// Runs the semantic pass on the module. 236 override void run() 237 { 238 modul.semanticPass = 1; 239 run(new SemanticScope(modul), modul.root); 240 } 241 242 override void run(SemanticScope scop, Node node) 243 { 244 this.scop = scop; 245 visitN(node); 246 } 247 248 /// Looks for special classes and stores them in a table. 249 /// May modify d.symbol and assign a SpecialClassSymbol to it. 250 void lookForSpecialClasses(ClassDecl d) 251 { 252 if (!scop.isModuleScope) 253 return; // Only consider top-level classes. 254 modul.cc.tables.classes.lookForSpecialClasses(modul, d, 255 (name, format, ...) => error(modul, _arguments, _argptr, format, name)); 256 } 257 258 /// Appends the AliasSymbol to a list of the current ScopeSymbol. 259 /// Reports an error if it doesn't support "alias this". 260 void insertAliasThis(AliasSymbol s) 261 { 262 if (auto as = cast(AggregateSymbol)scop.symbol) 263 as.aliases ~= s; 264 else if (auto ts = cast(TemplateSymbol)scop.symbol) 265 ts.aliases ~= s; 266 else 267 error(modul, s.loc.t, "‘alias this’ works only in classes/structs"); 268 } 269 270 /// Forwards to SemanticScope. 271 void enterScope(ScopeSymbol s) 272 { 273 scop.enter(s); 274 } 275 /// ditto 276 void exitScope() 277 { 278 scop.exit(); 279 } 280 /// ditto 281 void insert(Symbol s) 282 { 283 scop.insert(s); 284 } 285 /// ditto 286 void insert(Symbol s, Identifier* name) 287 { 288 scop.insert(s, name); 289 } 290 /// ditto 291 void insert(Symbol s, ScopeSymbol ss) 292 { 293 scop.insert(s, ss); 294 } 295 /// ditto 296 void insertOverload(Symbol s) 297 { 298 scop.insertOverload(s); 299 } 300 301 /+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 302 | Declarations | 303 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+/ 304 305 override 306 { 307 //alias visit = super.visit; 308 309 void visit(CompoundDecl d) 310 { 311 foreach (decl; d.decls) 312 visitD(decl); 313 } 314 315 void visit(IllegalDecl) 316 { assert(0, "semantic pass on invalid AST"); } 317 318 // void visit(EmptyDecl ed) 319 // {} 320 321 // void visit(ModuleDecl) 322 // {} 323 324 void visit(ImportDecl d) 325 { 326 imports ~= d; 327 } 328 329 void visit(AliasDecl d) 330 { 331 auto vd = d.vardecl.to!(VariablesDecl); 332 d.symbols = new AliasSymbol[vd.names.length]; 333 // Insert alias symbols in this declaration into the symbol table. 334 foreach (i, name; vd.names) 335 insert(d.symbols[i] = new AliasSymbol(name.ident, SLoc(name, d))); 336 } 337 338 void visit(AliasesDecl d) 339 { 340 d.symbols = new AliasSymbol[d.idents.length]; 341 // Insert alias symbols in this declaration into the symbol table. 342 foreach (i, name; d.idents) 343 { 344 auto s = d.symbols[i] = new AliasSymbol(name.ident, SLoc(name, d)); 345 if (name.ident is Keyword.This) 346 insertAliasThis(s); 347 else 348 insert(s); 349 } 350 } 351 352 void visit(AliasThisDecl d) 353 { 354 insertAliasThis(d.symbol = new AliasSymbol(d.name.ident, SLoc(d.name, d))); 355 } 356 357 void visit(TypedefDecl d) 358 { 359 auto vd = d.vardecl.to!(VariablesDecl); 360 d.symbols = new TypedefSymbol[vd.names.length]; 361 // Insert typedef symbols in this declaration into the symbol table. 362 foreach (i, name; vd.names) 363 insert(d.symbols[i] = new TypedefSymbol(name.ident, SLoc(name, d))); 364 } 365 366 void visit(EnumDecl d) 367 { 368 if (d.symbol) 369 return; 370 // Create the symbol. 371 d.symbol = new EnumSymbol(d.nameId, SLoc(d.name ? d.name : d.begin, d)); 372 bool isAnonymous = d.symbol.isAnonymous; 373 if (isAnonymous) 374 d.symbol.name = modul.cc.tables.idents.genAnonEnumID(); 375 insert(d.symbol); 376 // Visit members. 377 auto parentScopeSymbol = scop.symbol; 378 auto enumSymbol = d.symbol; 379 enterScope(d.symbol); 380 // Declare members. 381 foreach (member; d.members) 382 { 383 visitD(member); 384 if (isAnonymous) // Also insert into parent scope if enum is anonymous. 385 insert(member.symbol, parentScopeSymbol); 386 member.symbol.type = enumSymbol.type; // Assign TypeEnum. 387 } 388 exitScope(); 389 } 390 391 void visit(EnumMemberDecl d) 392 { 393 d.symbol = new EnumMemberSymbol( 394 d.name.ident, protection, storageClass, linkageType, SLoc(d.name, d)); 395 insert(d.symbol); 396 } 397 398 void visit(ClassDecl d) 399 { 400 if (d.symbol) 401 return; 402 // Create the symbol. 403 d.symbol = new ClassSymbol(d.nameId, SLoc(d.name, d)); 404 lookForSpecialClasses(d); 405 // Insert into current scope. 406 insert(d.symbol); 407 enterScope(d.symbol); 408 // Continue semantic analysis. 409 d.decls && visitD(d.decls); 410 exitScope(); 411 } 412 413 void visit(InterfaceDecl d) 414 { 415 if (d.symbol) 416 return; 417 // Create the symbol. 418 d.symbol = new InterfaceSymbol(d.nameId, SLoc(d.name, d)); 419 // Insert into current scope. 420 insert(d.symbol); 421 enterScope(d.symbol); 422 // Continue semantic analysis. 423 d.decls && visitD(d.decls); 424 exitScope(); 425 } 426 427 void visit(StructDecl d) 428 { 429 auto s = d.symbol; 430 if (s) 431 return; 432 // Create the symbol. 433 auto loc = SLoc(d.name ? d.name : d.begin, d); 434 s = d.symbol = new StructSymbol(d.nameId, loc); 435 if (s.isAnonymous) 436 s.name = modul.cc.tables.idents.genAnonStructID(); 437 // Insert into current scope. 438 insert(s); 439 enterScope(s); 440 // Continue semantic analysis. 441 d.decls && visitD(d.decls); 442 exitScope(); 443 if (s.isAnonymous) 444 // Insert members into parent scope as well. 445 foreach (member; s.members) 446 insert(member); 447 } 448 449 void visit(UnionDecl d) 450 { 451 auto s = d.symbol; 452 if (s) 453 return; 454 // Create the symbol. 455 auto loc = SLoc(d.name ? d.name : d.begin, d); 456 s = d.symbol = new UnionSymbol(d.nameId, loc); 457 if (s.isAnonymous) 458 s.name = modul.cc.tables.idents.genAnonUnionID(); 459 // Insert into current scope. 460 insert(s); 461 enterScope(s); 462 // Continue semantic analysis. 463 d.decls && visitD(d.decls); 464 exitScope(); 465 if (s.isAnonymous) 466 // Insert members into parent scope as well. 467 foreach (member; s.members) 468 insert(member); 469 } 470 471 void visit(ConstructorDecl d) 472 { 473 auto func = new FunctionSymbol(Ident.Ctor, SLoc(d.begin, d)); 474 insertOverload(func); 475 enterScope(func); 476 visitN(d.funcBody); 477 exitScope(); 478 } 479 480 void visit(StaticCtorDecl d) 481 { 482 auto func = new FunctionSymbol(Ident.Ctor, SLoc(d.begin, d)); 483 func.type = Types.Void_0Args_DFunc; 484 insertOverload(func); 485 enterScope(func); 486 visitN(d.funcBody); 487 exitScope(); 488 } 489 490 void visit(DestructorDecl d) 491 { 492 auto func = new FunctionSymbol(Ident.Dtor, SLoc(d.begin, d)); 493 func.type = Types.Void_0Args_DFunc; 494 insertOverload(func); 495 enterScope(func); 496 visitN(d.funcBody); 497 exitScope(); 498 } 499 500 void visit(StaticDtorDecl d) 501 { 502 auto func = new FunctionSymbol(Ident.Dtor, SLoc(d.begin, d)); 503 func.type = Types.Void_0Args_DFunc; 504 insertOverload(func); 505 enterScope(func); 506 visitN(d.funcBody); 507 exitScope(); 508 } 509 510 void visit(FunctionDecl d) 511 { 512 auto func = new FunctionSymbol(d.name.ident, SLoc(d.name, d)); 513 insertOverload(func); 514 enterScope(func); 515 visitN(d.funcBody); 516 exitScope(); 517 } 518 519 void visit(VariablesDecl vd) 520 { // Error if we are in an interface. 521 if (scop.symbol.isInterface && 522 !(vd.isStatic || vd.isConst || vd.isManifest)) 523 return error(modul, vd, MID.InterfaceCantHaveVariables); 524 // Insert variable symbols in this declaration into the symbol table. 525 vd.variables = new VariableSymbol[vd.names.length]; 526 foreach (i, name; vd.names) 527 { 528 auto variable = new VariableSymbol(name.ident, protection, storageClass, 529 linkageType, SLoc(name, vd)); 530 variable.value = vd.inits[i]; 531 vd.variables[i] = variable; 532 insert(variable); 533 } 534 } 535 536 void visit(InvariantDecl d) 537 { 538 auto func = new FunctionSymbol(Ident.InvariantFn, SLoc(d.begin, d)); 539 insert(func); 540 enterScope(func); 541 visitN(d.funcBody); 542 exitScope(); 543 } 544 545 void visit(UnittestDecl d) 546 { 547 if (!modul.cc.unittestBuild) 548 return; 549 // TODO: generate anonymous unittest id? 550 auto func = new FunctionSymbol(Ident.UnittestFn, SLoc(d.begin, d)); 551 func.type = Types.Void_0Args_DFunc; 552 insertOverload(func); 553 enterScope(func); 554 visitN(d.funcBody); 555 exitScope(); 556 } 557 558 void visit(DebugDecl d) 559 { 560 if (d.isSpecification) 561 { // debug = Id | Int 562 if (!scop.isModuleScope) 563 error(modul, d, MID.DebugSpecModuleLevel, d.spec.text); 564 else if (d.spec.kind == TOK.Identifier) 565 modul.cc.addDebugId(d.spec.ident.str); 566 else 567 modul.cc.debugLevel = d.spec.uint_; 568 } 569 else 570 { // debug ( Condition ) 571 if (debugBranchChoice(d.cond, modul.cc)) 572 d.compiledDecls = d.decls; 573 else 574 d.compiledDecls = d.elseDecls; 575 d.compiledDecls && visitD(d.compiledDecls); 576 } 577 } 578 579 void visit(VersionDecl d) 580 { 581 if (d.isSpecification) 582 { // version = Id | Int 583 if (!scop.isModuleScope) 584 error(modul, d, MID.VersionSpecModuleLevel, d.spec.text); 585 else if (d.spec.kind == TOK.Identifier) 586 modul.cc.addVersionId(d.spec.ident.str); 587 else 588 modul.cc.versionLevel = d.spec.uint_; 589 } 590 else 591 { // version ( Condition ) 592 if (versionBranchChoice(d.cond, modul.cc)) 593 d.compiledDecls = d.decls; 594 else 595 d.compiledDecls = d.elseDecls; 596 d.compiledDecls && visitD(d.compiledDecls); 597 } 598 } 599 600 void visit(TemplateDecl d) 601 { 602 if (d.symbol) 603 return; 604 // Create the symbol. 605 d.symbol = new TemplateSymbol(d.nameId, SLoc(d.name, d)); 606 // Insert into current scope. 607 insertOverload(d.symbol); 608 enterScope(d.symbol); 609 // Declare template parameters. 610 visitN(d.tparams); 611 // Continue with the declarations inside. 612 d.decls && visitD(d.decls); 613 exitScope(); 614 } 615 616 void visit(NewDecl d) 617 { 618 auto func = new FunctionSymbol(Ident.NewFn, SLoc(d.begin, d)); 619 insert(func); 620 enterScope(func); 621 visitN(d.funcBody); 622 exitScope(); 623 } 624 625 void visit(DeleteDecl d) 626 { 627 auto func = new FunctionSymbol(Ident.DeleteFn, SLoc(d.begin, d)); 628 insert(func); 629 enterScope(func); 630 visitN(d.funcBody); 631 exitScope(); 632 } 633 634 // Attributes: 635 636 void visit(ProtectionDecl d) 637 { 638 auto saved = protection; // Save. 639 protection = d.prot; // Set. 640 visitD(d.decls); 641 protection = saved; // Restore. 642 } 643 644 void visit(StorageClassDecl d) 645 { 646 auto saved = storageClass; // Save. 647 storageClass = d.stc; // Set. 648 visitD(d.decls); 649 storageClass = saved; // Restore. 650 } 651 652 void visit(LinkageDecl d) 653 { 654 auto saved = linkageType; // Save. 655 linkageType = d.linkageType; // Set. 656 visitD(d.decls); 657 linkageType = saved; // Restore. 658 } 659 660 void visit(AlignDecl d) 661 { 662 auto saved = alignSize; // Save. 663 alignSize = d.size; // Set. 664 visitD(d.decls); 665 alignSize = saved; // Restore. 666 } 667 } // override 668 } 669 670 671 /// The second pass resolves variable types, base classes, 672 /// evaluates static ifs/asserts etc. 673 class SecondSemanticPass : DefaultVisitor, SemanticPass 674 { 675 Module modul; 676 SemanticScope scop; 677 Interpreter ip; /// Used to evaluate expressions. 678 679 this(Module modul) 680 { 681 this.modul = modul; 682 this.ip = new Interpreter(modul.cc.diag); 683 } 684 685 /// Runs the semantic pass on the module. 686 override void run() 687 { 688 modul.semanticPass = 2; 689 run(new SemanticScope(modul), modul.root); 690 } 691 692 override void run(SemanticScope scop, Node node) 693 { 694 this.scop = scop; 695 visitN(node); 696 } 697 698 Symbol search(Token* idTok) 699 { 700 return scop.search(idTok); 701 } 702 703 override 704 { 705 D visit(CompoundDecl d) 706 { 707 foreach (decl; d.decls) 708 visitD(decl); 709 return d; 710 } 711 712 D visit(AliasDecl d) 713 { 714 return d; 715 } 716 717 D visit(TypedefDecl d) 718 { 719 return d; 720 } 721 722 D visit(EnumDecl d) 723 { 724 return d; 725 } 726 727 D visit(EnumMemberDecl d) 728 { 729 return d; 730 } 731 732 D visit(ClassDecl d) 733 { 734 return d; 735 } 736 737 D visit(InterfaceDecl d) 738 { 739 return d; 740 } 741 742 D visit(StructDecl d) 743 { 744 return d; 745 } 746 747 D visit(UnionDecl d) 748 { 749 return d; 750 } 751 752 D visit(ConstructorDecl d) 753 { 754 return d; 755 } 756 757 D visit(StaticCtorDecl d) 758 { 759 return d; 760 } 761 762 D visit(DestructorDecl d) 763 { 764 return d; 765 } 766 767 D visit(StaticDtorDecl d) 768 { 769 return d; 770 } 771 772 D visit(FunctionDecl d) 773 { 774 return d; 775 } 776 777 D visit(VariablesDecl d) 778 { 779 return d; 780 } 781 782 D visit(InvariantDecl d) 783 { 784 return d; 785 } 786 787 D visit(UnittestDecl d) 788 { 789 return d; 790 } 791 792 D visit(TemplateDecl d) 793 { 794 return d; 795 } 796 797 D visit(NewDecl d) 798 { 799 return d; 800 } 801 802 D visit(DeleteDecl d) 803 { 804 return d; 805 } 806 807 D visit(StaticAssertDecl d) 808 { 809 d.condition = visitE(d.condition); 810 if (d.condition.isChecked()) 811 { 812 auto r = ip.eval(d.condition); 813 if (r !is Interpreter.NAR && ip.EM.isBool(r) == 0) 814 { 815 cstring errorMsg = "static assert is false"; 816 if (d.message) 817 { 818 d.message = visitE(d.message); 819 r = ip.eval(d.message); 820 auto se = r.Is!(StringExpr); 821 if (se) // TODO: allow non-string expressions? 822 errorMsg = se.getString(); 823 } 824 error(modul, d, errorMsg); 825 } 826 } 827 return d; 828 } 829 830 D visit(StaticIfDecl d) 831 { 832 // Eval condition 833 return d; 834 } 835 836 D visit(MixinDecl d) 837 { 838 // Eval d.argument 839 return d; 840 } 841 842 D visit(PragmaDecl d) 843 { 844 if (d.name.ident is Ident.msg) 845 { // Write arguments to standard output. 846 foreach (arg; d.args) 847 { 848 cstring msg; 849 arg = visitE(arg); 850 auto r = ip.eval(arg); 851 if (auto se = r.Is!(StringExpr)) 852 msg = se.getString(); 853 else 854 msg = "FIXME: can't print AST yet"; // = astPrinter.print(r) 855 Stdout(msg); 856 } 857 } 858 else 859 { 860 pragmaSemantic(scop.scop, d.begin, d.name.ident, d.args); 861 visitD(d.decls); 862 } 863 return d; 864 } 865 } // override 866 867 /+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 868 | Statements | 869 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+/ 870 871 /// The current surrounding, breakable statement. 872 S breakableStmt; 873 874 S setBS(S s) 875 { 876 auto old = breakableStmt; 877 breakableStmt = s; 878 return old; 879 } 880 881 void restoreBS(S s) 882 { 883 breakableStmt = s; 884 } 885 886 override 887 { 888 S visit(CompoundStmt s) 889 { 890 foreach (stmnt; s.stmnts) 891 visitS(stmnt); 892 return s; 893 } 894 895 S visit(IllegalStmt) 896 { assert(0, "semantic pass on invalid AST"); return null; } 897 898 S visit(EmptyStmt s) 899 { 900 return s; 901 } 902 903 S visit(FuncBodyStmt s) 904 { 905 return s; 906 } 907 908 S visit(ScopeStmt s) 909 { 910 // enterScope(); 911 visitS(s.stmnt); 912 // exitScope(); 913 return s; 914 } 915 916 S visit(LabeledStmt s) 917 { 918 return s; 919 } 920 921 S visit(ExpressionStmt s) 922 { 923 return s; 924 } 925 926 S visit(DeclarationStmt s) 927 { 928 return s; 929 } 930 931 S visit(IfStmt s) 932 { 933 return s; 934 } 935 936 S visit(WhileStmt s) 937 { 938 auto saved = setBS(s); 939 // TODO: 940 restoreBS(saved); 941 return s; 942 } 943 944 S visit(DoWhileStmt s) 945 { 946 auto saved = setBS(s); 947 // TODO: 948 restoreBS(saved); 949 return s; 950 } 951 952 S visit(ForStmt s) 953 { 954 auto saved = setBS(s); 955 // TODO: 956 restoreBS(saved); 957 return s; 958 } 959 960 S visit(ForeachStmt s) 961 { 962 auto saved = setBS(s); 963 // TODO: 964 // find overload opApply or opApplyReverse. 965 restoreBS(saved); 966 return s; 967 } 968 969 S visit(SwitchStmt s) 970 { 971 auto saved = setBS(s); 972 // TODO: 973 restoreBS(saved); 974 return s; 975 } 976 977 S visit(CaseStmt s) 978 { 979 auto saved = setBS(s); 980 // TODO: 981 restoreBS(saved); 982 return s; 983 } 984 985 S visit(DefaultStmt s) 986 { 987 auto saved = setBS(s); 988 // TODO: 989 restoreBS(saved); 990 return s; 991 } 992 993 S visit(ContinueStmt s) 994 { 995 return s; 996 } 997 998 S visit(BreakStmt s) 999 { 1000 return s; 1001 } 1002 1003 S visit(ReturnStmt s) 1004 { 1005 return s; 1006 } 1007 1008 S visit(GotoStmt s) 1009 { 1010 return s; 1011 } 1012 1013 S visit(WithStmt s) 1014 { 1015 return s; 1016 } 1017 1018 S visit(SynchronizedStmt s) 1019 { 1020 return s; 1021 } 1022 1023 S visit(TryStmt s) 1024 { 1025 return s; 1026 } 1027 1028 S visit(CatchStmt s) 1029 { 1030 return s; 1031 } 1032 1033 S visit(FinallyStmt s) 1034 { 1035 return s; 1036 } 1037 1038 S visit(ScopeGuardStmt s) 1039 { 1040 return s; 1041 } 1042 1043 S visit(ThrowStmt s) 1044 { 1045 return s; 1046 } 1047 1048 S visit(VolatileStmt s) 1049 { 1050 return s; 1051 } 1052 1053 S visit(AsmBlockStmt s) 1054 { 1055 foreach (stmnt; s.statements.stmnts) 1056 visitS(stmnt); 1057 return s; 1058 } 1059 1060 S visit(AsmStmt s) 1061 { 1062 return s; 1063 } 1064 1065 S visit(AsmAlignStmt s) 1066 { 1067 return s; 1068 } 1069 1070 S visit(IllegalAsmStmt) 1071 { assert(0, "semantic pass on invalid AST"); return null; } 1072 1073 S visit(PragmaStmt s) 1074 { 1075 return s; 1076 } 1077 1078 S visit(MixinStmt s) 1079 { 1080 return s; 1081 } 1082 1083 S visit(StaticIfStmt s) 1084 { 1085 return s; 1086 } 1087 1088 S visit(StaticAssertStmt s) 1089 { 1090 return s; 1091 } 1092 1093 S visit(DebugStmt s) 1094 { 1095 return s; 1096 } 1097 1098 S visit(VersionStmt s) 1099 { 1100 return s; 1101 } 1102 } // override 1103 1104 /+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1105 | Expressions | 1106 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+/ 1107 1108 /// Determines whether to issue an error when a symbol couldn't be found. 1109 bool errorOnUndefinedSymbol; 1110 //bool errorOnUnknownSymbol; 1111 1112 /// Reports an error if the type of e is not bool. 1113 void errorIfBool(Expression e) 1114 { 1115 assert(e.type !is null); 1116 if (e.type.isBaseBool()) 1117 error(modul, e, "the operation is undefined for type bool"); 1118 } 1119 1120 /// Reports an error if e has no boolean result. 1121 void errorIfNonBool(Expression e) 1122 { 1123 assert(e.type !is null); 1124 switch (e.kind) 1125 { 1126 case NodeKind.DeleteExpr: 1127 error(modul, e, "the delete operator has no boolean result"); 1128 break; 1129 case NodeKind.AssignExpr: 1130 error(modul, e, "the assignment operator '=' has no boolean result"); 1131 break; 1132 case NodeKind.CondExpr: 1133 auto cond = e.to!(CondExpr); 1134 errorIfNonBool(cond.lhs); 1135 errorIfNonBool(cond.rhs); 1136 break; 1137 default: 1138 if (!e.type.isBaseScalar()) // Only scalar types can be bool. 1139 error(modul, e, "expression has no boolean result"); 1140 } 1141 } 1142 1143 /// Returns a call expression if 'e' overrides 1144 /// an operatorwith the name 'id'. 1145 /// Params: 1146 /// e = The binary expression to be checked. 1147 /// id = The name of the overload function. 1148 Expression findOverload(UnaryExpr e, Identifier* id) 1149 { 1150 // TODO: 1151 // check e for struct or class 1152 // search for function named id 1153 // return call expression: e.opXYZ() 1154 return null; 1155 } 1156 1157 /// Returns a call expression if 'e' overrides 1158 /// an operator with the name 'id' or 'id_r'. 1159 /// Params: 1160 /// e = The binary expression to be checked. 1161 /// id = The name of the overload function. 1162 /// id_r = The name of the reverse overload function. 1163 Expression findOverload(BinaryExpr e, Identifier* id, Identifier* id_r) 1164 { 1165 // TODO: 1166 return null; 1167 } 1168 1169 /// Visit the operands of a binary operator. 1170 void visitBinary(BinaryExpr e) 1171 { 1172 e.lhs = visitE(e.lhs); 1173 e.rhs = visitE(e.rhs); 1174 } 1175 1176 override 1177 { 1178 E visit(IllegalExpr) 1179 { assert(0, "semantic pass on invalid AST"); return null; } 1180 1181 E visit(CondExpr e) 1182 { 1183 return e; 1184 } 1185 1186 E visit(CommaExpr e) 1187 { 1188 if (!e.isChecked) 1189 { 1190 e.lhs = visitE(e.lhs); 1191 e.rhs = visitE(e.rhs); 1192 e.type = e.rhs.type; // Take the type of the right hand side. 1193 } 1194 return e; 1195 } 1196 1197 E visit(OrOrExpr e) 1198 { 1199 if (!e.isChecked) 1200 { 1201 e.lhs = visitE(e.lhs); 1202 errorIfNonBool(e.lhs); // Left operand must be bool. 1203 e.rhs = visitE(e.rhs); 1204 if (e.rhs.type is Types.Void) 1205 e.type = Types.Void; // According to spec. 1206 else 1207 (e.type = Types.Bool), // Otherwise type is bool and 1208 errorIfNonBool(e.rhs); // right operand must be bool. 1209 } 1210 return e; 1211 } 1212 1213 E visit(AndAndExpr e) 1214 { 1215 if (!e.isChecked) 1216 { 1217 e.lhs = visitE(e.lhs); 1218 errorIfNonBool(e.lhs); // Left operand must be bool. 1219 e.rhs = visitE(e.rhs); 1220 if (e.rhs.type is Types.Void) 1221 e.type = Types.Void; // According to spec. 1222 else 1223 (e.type = Types.Bool), // Otherwise type is bool and 1224 errorIfNonBool(e.rhs); // right operand must be bool. 1225 } 1226 return e; 1227 } 1228 1229 E visit(OrExpr e) 1230 { 1231 if (auto o = findOverload(e, Ident.opOr, Ident.opOr_r)) 1232 return o; 1233 return e; 1234 } 1235 1236 E visit(XorExpr e) 1237 { 1238 if (auto o = findOverload(e, Ident.opXor, Ident.opXor_r)) 1239 return o; 1240 return e; 1241 } 1242 1243 E visit(AndExpr e) 1244 { 1245 if (auto o = findOverload(e, Ident.opAnd, Ident.opAnd_r)) 1246 return o; 1247 return e; 1248 } 1249 1250 E visit(EqualExpr e) 1251 { 1252 visitBinary(e); 1253 if (auto o = findOverload(e, Ident.opEquals, null)) 1254 return o; 1255 // TODO: 1256 e.type = Types.Bool; 1257 return e; 1258 } 1259 1260 E visit(IdentityExpr e) 1261 { 1262 return e; 1263 } 1264 1265 E visit(RelExpr e) 1266 { 1267 visitBinary(e); 1268 if (auto o = findOverload(e, Ident.opCmp, null)) 1269 return o; 1270 // TODO: check for more errors? 1271 if (e.lhs.type.isBaseComplex() || e.rhs.type.isBaseComplex()) 1272 { 1273 auto whichOp = e.lhs.type.isBaseComplex() ? e.lhs.begin : e.rhs.begin; 1274 error(modul, whichOp, 1275 "the operator '{}' is undefined for complex numbers", e.optok.text); 1276 } 1277 e.type = Types.Bool; 1278 return e; 1279 } 1280 1281 E visit(InExpr e) 1282 { 1283 visitBinary(e); 1284 if (auto o = findOverload(e, Ident.opIn, Ident.opIn_r)) 1285 return o; 1286 if (!e.rhs.type.baseType().isAArray()) 1287 { 1288 error(modul, e.rhs, 1289 "right operand of 'in' operator must be an associative array"); 1290 // Don't use Types.Error. Cascading error msgs are irritating. 1291 e.type = e.rhs.type; 1292 } 1293 else 1294 // Result type is pointer to element type of AA. 1295 e.type = e.rhs.type.next.ptrTo(); 1296 return e; 1297 } 1298 1299 E visit(LShiftExpr e) 1300 { 1301 if (auto o = findOverload(e, Ident.opShl, Ident.opShl_r)) 1302 return o; 1303 return e; 1304 } 1305 1306 E visit(RShiftExpr e) 1307 { 1308 if (auto o = findOverload(e, Ident.opShr, Ident.opShr_r)) 1309 return o; 1310 return e; 1311 } 1312 1313 E visit(URShiftExpr e) 1314 { 1315 if (auto o = findOverload(e, Ident.opUShr, Ident.opUShr_r)) 1316 return o; 1317 return e; 1318 } 1319 1320 E visit(PlusExpr e) 1321 { 1322 if (auto o = findOverload(e, Ident.opAdd, Ident.opAdd_r)) 1323 return o; 1324 return e; 1325 } 1326 1327 E visit(MinusExpr e) 1328 { 1329 if (auto o = findOverload(e, Ident.opSub, Ident.opSub_r)) 1330 return o; 1331 return e; 1332 } 1333 1334 E visit(CatExpr e) 1335 { 1336 visitBinary(e); 1337 if (auto o = findOverload(e, Ident.opCat, Ident.opCat_r)) 1338 return o; 1339 // Need to check the base types if they are arrays. 1340 // This will allow for concatenating typedef types: 1341 // typedef Handle[] Handles; Handles hlist; hlist ~ element; 1342 auto tl = e.lhs.type.baseType(), 1343 tr = e.rhs.type.baseType(); 1344 if (tl.isDorSArray() || tr.isDorSArray()) 1345 { 1346 // TODO: 1347 // e.type = ; 1348 } 1349 else 1350 { 1351 error(modul, e.optok, 1352 "concatenation operator '~' is undefined for: {} ~ {}", e.lhs, e.rhs); 1353 e.type = e.lhs.type; // Use Types.Error if e.lhs.type is not a good idea. 1354 } 1355 return e; 1356 } 1357 1358 E visit(MulExpr e) 1359 { 1360 if (auto o = findOverload(e, Ident.opMul, Ident.opMul_r)) 1361 return o; 1362 return e; 1363 } 1364 1365 E visit(DivExpr e) 1366 { 1367 if (auto o = findOverload(e, Ident.opDiv, Ident.opDiv_r)) 1368 return o; 1369 return e; 1370 } 1371 1372 E visit(ModExpr e) 1373 { 1374 if (auto o = findOverload(e, Ident.opMod, Ident.opMod_r)) 1375 return o; 1376 return e; 1377 } 1378 1379 E visit(AssignExpr e) 1380 { 1381 if (auto o = findOverload(e, Ident.opAssign, null)) 1382 return o; 1383 // TODO: also check for opIndexAssign and opSliceAssign. 1384 return e; 1385 } 1386 1387 E visit(LShiftAssignExpr e) 1388 { 1389 if (auto o = findOverload(e, Ident.opShlAssign, null)) 1390 return o; 1391 return e; 1392 } 1393 1394 E visit(RShiftAssignExpr e) 1395 { 1396 if (auto o = findOverload(e, Ident.opShrAssign, null)) 1397 return o; 1398 return e; 1399 } 1400 1401 E visit(URShiftAssignExpr e) 1402 { 1403 if (auto o = findOverload(e, Ident.opUShrAssign, null)) 1404 return o; 1405 return e; 1406 } 1407 1408 E visit(OrAssignExpr e) 1409 { 1410 if (auto o = findOverload(e, Ident.opOrAssign, null)) 1411 return o; 1412 return e; 1413 } 1414 1415 E visit(AndAssignExpr e) 1416 { 1417 if (auto o = findOverload(e, Ident.opAndAssign, null)) 1418 return o; 1419 return e; 1420 } 1421 1422 E visit(PlusAssignExpr e) 1423 { 1424 if (auto o = findOverload(e, Ident.opAddAssign, null)) 1425 return o; 1426 return e; 1427 } 1428 1429 E visit(MinusAssignExpr e) 1430 { 1431 if (auto o = findOverload(e, Ident.opSubAssign, null)) 1432 return o; 1433 return e; 1434 } 1435 1436 E visit(DivAssignExpr e) 1437 { 1438 auto o = findOverload(e, Ident.opDivAssign, null); 1439 if (o) 1440 return o; 1441 return e; 1442 } 1443 1444 E visit(MulAssignExpr e) 1445 { 1446 auto o = findOverload(e, Ident.opMulAssign, null); 1447 if (o) 1448 return o; 1449 return e; 1450 } 1451 1452 E visit(ModAssignExpr e) 1453 { 1454 auto o = findOverload(e, Ident.opModAssign, null); 1455 if (o) 1456 return o; 1457 return e; 1458 } 1459 1460 E visit(XorAssignExpr e) 1461 { 1462 auto o = findOverload(e, Ident.opXorAssign, null); 1463 if (o) 1464 return o; 1465 return e; 1466 } 1467 1468 E visit(CatAssignExpr e) 1469 { 1470 auto o = findOverload(e, Ident.opCatAssign, null); 1471 if (o) 1472 return o; 1473 return e; 1474 } 1475 1476 E visit(AddressExpr e) 1477 { 1478 if (e.isChecked) 1479 return e; 1480 e.una = visitE(e.una); 1481 e.type = e.una.type.ptrTo(); 1482 return e; 1483 } 1484 1485 E visit(PreIncrExpr e) 1486 { 1487 if (e.isChecked) 1488 return e; 1489 // TODO: rewrite to e+=1 1490 e.una = visitE(e.una); 1491 e.type = e.una.type; 1492 errorIfBool(e.una); 1493 return e; 1494 } 1495 1496 E visit(PreDecrExpr e) 1497 { 1498 if (e.isChecked) 1499 return e; 1500 // TODO: rewrite to e-=1 1501 e.una = visitE(e.una); 1502 e.type = e.una.type; 1503 errorIfBool(e.una); 1504 return e; 1505 } 1506 1507 E visit(PostIncrExpr e) 1508 { 1509 if (e.isChecked) 1510 return e; 1511 if (auto o = findOverload(e, Ident.opPostInc)) 1512 return o; 1513 e.una = visitE(e.una); 1514 e.type = e.una.type; 1515 errorIfBool(e.una); 1516 return e; 1517 } 1518 1519 E visit(PostDecrExpr e) 1520 { 1521 if (e.isChecked) 1522 return e; 1523 if (auto o = findOverload(e, Ident.opPostDec)) 1524 return o; 1525 e.una = visitE(e.una); 1526 e.type = e.una.type; 1527 errorIfBool(e.una); 1528 return e; 1529 } 1530 1531 E visit(DerefExpr e) 1532 { 1533 if (e.isChecked) 1534 return e; 1535 version(D2) 1536 if (auto o = findOverload(e, Ident.opStar)) 1537 return o; 1538 e.una = visitE(e.una); 1539 e.type = e.una.type.next; 1540 if (!e.una.type.isPointer) 1541 { 1542 error(modul, e.una, 1543 "dereference operator '*x' not defined for expression of type '{}'", 1544 e.una.type.toString()); 1545 e.type = Types.Error; 1546 } 1547 // TODO: 1548 // if (e.una.type.isVoid) 1549 // error(); 1550 return e; 1551 } 1552 1553 E visit(SignExpr e) 1554 { 1555 if (e.isChecked) 1556 return e; 1557 if (auto o = findOverload(e, e.isNeg ? Ident.opNeg : Ident.opPos)) 1558 return o; 1559 e.una = visitE(e.una); 1560 e.type = e.una.type; 1561 errorIfBool(e.una); 1562 return e; 1563 } 1564 1565 E visit(NotExpr e) 1566 { 1567 if (e.isChecked) 1568 return e; 1569 e.una = visitE(e.una); 1570 e.type = Types.Bool; 1571 errorIfNonBool(e.una); 1572 return e; 1573 } 1574 1575 E visit(CompExpr e) 1576 { 1577 if (e.isChecked) 1578 return e; 1579 if (auto o = findOverload(e, Ident.opCom)) 1580 return o; 1581 e.una = visitE(e.una); 1582 e.type = e.una.type; 1583 if (e.type.isBaseFloating() || e.type.isBaseBool()) 1584 { 1585 error(modul, e, "the operator '~x' is undefined for the type '{}'", 1586 e.type.toString()); 1587 e.type = Types.Error; 1588 } 1589 return e; 1590 } 1591 1592 E visit(CallExpr e) 1593 { 1594 if (auto o = findOverload(e, Ident.opCall)) 1595 return o; 1596 return e; 1597 } 1598 1599 E visit(NewExpr e) 1600 { 1601 return e; 1602 } 1603 1604 E visit(NewClassExpr e) 1605 { 1606 return e; 1607 } 1608 1609 E visit(DeleteExpr e) 1610 { 1611 return e; 1612 } 1613 1614 E visit(CastExpr e) 1615 { 1616 if (auto o = findOverload(e, Ident.opCast)) 1617 return o; 1618 return e; 1619 } 1620 1621 E visit(IndexExpr e) 1622 { 1623 if (auto o = findOverload(e, Ident.opIndex)) 1624 return o; 1625 return e; 1626 } 1627 1628 E visit(SliceExpr e) 1629 { 1630 if (auto o = findOverload(e, Ident.opSlice)) 1631 return o; 1632 return e; 1633 } 1634 1635 E visit(ModuleScopeExpr e) 1636 { 1637 return e; 1638 } 1639 1640 E visit(IdentifierExpr e) 1641 { 1642 if (e.isChecked) 1643 return e; 1644 debug(sema) Stdout.formatln("", e); 1645 e.symbol = search(e.name); 1646 return e; 1647 } 1648 1649 E visit(TmplInstanceExpr e) 1650 { 1651 if (e.isChecked) 1652 return e; 1653 debug(sema) Stdout.formatln("", e); 1654 e.symbol = search(e.name); 1655 return e; 1656 } 1657 1658 E visit(SpecialTokenExpr e) 1659 { 1660 if (e.isChecked) 1661 return e.value; 1662 switch (e.specialToken.ident.idKind) 1663 { 1664 case IDK.LINE, IDK.VERSION: 1665 e.value = new IntExpr(e.specialToken.uint_, Types.UInt32); 1666 break; 1667 case IDK.FILE, IDK.DATE, IDK.TIME, IDK.TIMESTAMP, IDK.VENDOR: 1668 e.value = new StringExpr(e.specialToken.strval.str); 1669 break; 1670 default: 1671 assert(0); 1672 } 1673 e.type = e.value.type; 1674 return e.value; 1675 } 1676 1677 E visit(ThisExpr e) 1678 { 1679 return e; 1680 } 1681 1682 E visit(SuperExpr e) 1683 { 1684 return e; 1685 } 1686 1687 E visit(NullExpr e) 1688 { 1689 if (!e.isChecked) 1690 e.type = Types.Void_ptr; 1691 return e; 1692 } 1693 1694 E visit(DollarExpr e) 1695 { 1696 if (e.isChecked) 1697 return e; 1698 e.type = modul.cc.tables.types.Size_t; 1699 // if (!inArraySubscript) 1700 // error("$ can only be in an array subscript."); 1701 return e; 1702 } 1703 1704 E visit(BoolExpr e) 1705 { 1706 assert(e.isChecked); 1707 return e.value; 1708 } 1709 1710 E visit(IntExpr e) 1711 { 1712 if (e.isChecked) 1713 return e; 1714 1715 if (e.number & 0x8000_0000_0000_0000) 1716 e.type = Types.UInt64; // 0xFFFF_FFFF_FFFF_FFFF 1717 else if (e.number & 0xFFFF_FFFF_0000_0000) 1718 e.type = Types.Int64; // 0x7FFF_FFFF_FFFF_FFFF 1719 else if (e.number & 0x8000_0000) 1720 e.type = Types.UInt32; // 0xFFFF_FFFF 1721 else 1722 e.type = Types.Int32; // 0x7FFF_FFFF 1723 return e; 1724 } 1725 1726 E visit(FloatExpr e) 1727 { 1728 if (!e.isChecked) 1729 e.type = Types.Float64; 1730 return e; 1731 } 1732 1733 E visit(ComplexExpr e) 1734 { 1735 if (!e.isChecked) 1736 e.type = Types.CFloat64; 1737 return e; 1738 } 1739 1740 E visit(CharExpr e) 1741 { 1742 assert(e.isChecked); 1743 return e.value; 1744 } 1745 1746 E visit(StringExpr e) 1747 { 1748 assert(e.isChecked); 1749 return e; 1750 } 1751 1752 E visit(ArrayLiteralExpr e) 1753 { 1754 return e; 1755 } 1756 1757 E visit(AArrayLiteralExpr e) 1758 { 1759 return e; 1760 } 1761 1762 E visit(AssertExpr e) 1763 { 1764 return e; 1765 } 1766 1767 E visit(MixinExpr e) 1768 { 1769 return e; 1770 } 1771 1772 E visit(ImportExpr e) 1773 { 1774 return e; 1775 } 1776 1777 E visit(TypeofExpr e) 1778 { 1779 return e; 1780 } 1781 1782 E visit(TypeDotIdExpr e) 1783 { 1784 return e; 1785 } 1786 1787 E visit(TypeidExpr e) 1788 { 1789 return e; 1790 } 1791 1792 E visit(IsExpr e) 1793 { 1794 return e; 1795 } 1796 1797 E visit(ParenExpr e) 1798 { 1799 if (!e.isChecked) 1800 { 1801 e.next = visitE(e.next); 1802 e.type = e.next.type; 1803 } 1804 return e; 1805 } 1806 1807 E visit(FuncLiteralExpr e) 1808 { 1809 return e; 1810 } 1811 1812 E visit(LambdaExpr e) 1813 { 1814 return e; 1815 } 1816 1817 E visit(TraitsExpr e) // D2.0 1818 { 1819 return e; 1820 } 1821 1822 E visit(VoidInitExpr e) 1823 { 1824 return e; 1825 } 1826 1827 E visit(ArrayInitExpr e) 1828 { 1829 return e; 1830 } 1831 1832 E visit(StructInitExpr e) 1833 { 1834 return e; 1835 } 1836 1837 E visit(AsmTypeExpr e) 1838 { 1839 return e; 1840 } 1841 1842 E visit(AsmOffsetExpr e) 1843 { 1844 return e; 1845 } 1846 1847 E visit(AsmSegExpr e) 1848 { 1849 return e; 1850 } 1851 1852 E visit(AsmPostBracketExpr e) 1853 { 1854 return e; 1855 } 1856 1857 E visit(AsmBracketExpr e) 1858 { 1859 return e; 1860 } 1861 1862 E visit(AsmLocalSizeExpr e) 1863 { 1864 return e; 1865 } 1866 1867 E visit(AsmRegisterExpr e) 1868 { 1869 return e; 1870 } 1871 } // override 1872 1873 /+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1874 | Types | 1875 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+/ 1876 1877 override 1878 { 1879 T visit(IllegalType) 1880 { assert(0, "semantic pass on invalid AST"); return null; } 1881 1882 T visit(IntegralType t) 1883 { 1884 t.type = Types.fromTOK(t.tok); 1885 return t; 1886 } 1887 1888 T visit(ModuleScopeType t) 1889 { 1890 return t; 1891 } 1892 1893 T visit(IdentifierType t) 1894 { 1895 //auto idToken = t.begin; 1896 //auto symbol = search(idToken); 1897 // TODO: save symbol or its type in t. 1898 return t; 1899 } 1900 1901 T visit(TypeofType t) 1902 { 1903 t.expr = visitE(t.expr); 1904 t.type = t.expr.type; 1905 return t; 1906 } 1907 1908 T visit(TmplInstanceType t) 1909 { 1910 auto idToken = t.begin; 1911 auto symbol = search(idToken); 1912 // TODO: save symbol or its type in t. 1913 return t; 1914 } 1915 1916 T visit(PointerType t) 1917 { 1918 t.type = visitT(t.next).type.ptrTo(); 1919 return t; 1920 } 1921 1922 T visit(ArrayType t) 1923 { 1924 auto baseType = visitT(t.next).type; 1925 if (t.isAssociative) 1926 t.type = baseType.arrayOf(visitT(t.assocType).type); 1927 else if (t.isDynamic) 1928 t.type = baseType.arrayOf(); 1929 else if (t.isStatic) 1930 {} 1931 else 1932 assert(t.isSlice); 1933 return t; 1934 } 1935 1936 T visit(FunctionType t) 1937 { 1938 return t; 1939 } 1940 1941 T visit(DelegateType t) 1942 { 1943 return t; 1944 } 1945 1946 T visit(BaseClassType t) 1947 { 1948 return t; 1949 } 1950 1951 T visit(ModifierType t) // D2.0 1952 { 1953 return t; 1954 } 1955 } // override 1956 1957 /+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1958 | Parameters | 1959 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+/ 1960 1961 override 1962 { 1963 N visit(Parameter p) 1964 { 1965 return p; 1966 } 1967 1968 N visit(Parameters p) 1969 { 1970 return p; 1971 } 1972 1973 N visit(TemplateAliasParam p) 1974 { 1975 return p; 1976 } 1977 1978 N visit(TemplateTypeParam p) 1979 { 1980 return p; 1981 } 1982 1983 N visit(TemplateThisParam p) // D2.0 1984 { 1985 return p; 1986 } 1987 1988 N visit(TemplateValueParam p) 1989 { 1990 return p; 1991 } 1992 1993 N visit(TemplateTupleParam p) 1994 { 1995 return p; 1996 } 1997 1998 N visit(TemplateParameters p) 1999 { 2000 return p; 2001 } 2002 2003 N visit(TemplateArguments p) 2004 { 2005 return p; 2006 } 2007 } // override 2008 } 2009 2010 /// Creates an error report. 2011 void error(Module m, Token* token, cstring formatMsg, ...) 2012 { 2013 error(m, _arguments, _argptr, formatMsg, token); 2014 } 2015 2016 /// ditto 2017 void error(Module m, Node n, cstring formatMsg, ...) 2018 { 2019 error(m, _arguments, _argptr, formatMsg, n.begin); 2020 } 2021 2022 /// ditto 2023 void error(Module m, Token* token, MID mid, ...) 2024 { 2025 error(m, _arguments, _argptr, m.cc.diag.msg(mid), token); 2026 } 2027 2028 /// ditto 2029 void error(Module m, Node n, MID mid, ...) 2030 { 2031 error(m, _arguments, _argptr, m.cc.diag.msg(mid), n.begin); 2032 } 2033 2034 /// ditto 2035 void error(Module m, TypeInfo[] _arguments, va_list _argptr, 2036 cstring msg, Token* token) 2037 { 2038 auto loc = token.getErrorLocation(m.filePath()); 2039 msg = m.cc.diag.format(_arguments, _argptr, msg); 2040 m.cc.diag ~= new SemanticError(loc, msg); 2041 }