1 /// Author: Aziz Köksal 2 /// License: GPL3 3 /// $(Maturity average) 4 module dil.semantic.Symbols; 5 6 import dil.ast.Expression; 7 import dil.semantic.Symbol, 8 dil.semantic.SymbolTable, 9 dil.semantic.Types; 10 import dil.lexer.IdTable; 11 import dil.Enums, 12 dil.String; 13 import common; 14 15 /// Declaration symbol. 16 abstract class DeclarationSymbol : Symbol 17 { 18 Protection prot; /// The protection. 19 StorageClass stcs; /// The storage classes. 20 LinkageType linkage; /// The linkage type. 21 22 this(SYM sid, Identifier* name, SLoc loc) 23 { 24 super(sid, name, loc); 25 } 26 27 override cstring toMangle() 28 { 29 return toMangle(this, linkage); 30 } 31 32 static cstring toMangle(Symbol s, LinkageType linkage) 33 { 34 cstring toCppMangle(Symbol s){ /+TODO+/ return ""; } 35 36 cstring m; 37 if (!s.parent || s.parent.isModule()) 38 switch (linkage) 39 { 40 case LinkageType.D: 41 break; 42 case LinkageType.C, 43 LinkageType.Windows, 44 LinkageType.Pascal: 45 m = s.name.str; 46 break; 47 case LinkageType.Cpp: 48 version(D2)version(Windows) 49 goto case LinkageType.C; // D2 on Windows 50 51 m = toCppMangle(s); 52 break; 53 case LinkageType.None: 54 // TODO: issue forward declaration error? 55 goto case LinkageType.C; 56 default: assert(0); 57 } 58 if (!m) 59 m = "_D" ~ toMangle2(s); 60 return m; 61 } 62 63 static cstring toMangle2(Symbol s) 64 { // Recursive function. 65 cstring m; 66 Symbol s2 = s; 67 for (; s2; s2 = s2.parent) 68 if (s2.name is Ident.Empty) 69 m = "0" ~ m; 70 else if (s2 !is s && s2.isFunction()) 71 { 72 m = toMangle2(s2) ~ m; // Recursive call. 73 break; 74 } 75 else 76 { 77 auto id = s2.name.str; 78 m = itoa(id.length) ~ id ~ m; 79 } 80 81 auto fs = s.isFunction() ? s.to!(FunctionSymbol) : null; 82 83 if (fs /+&& (fs.needThis() || fs.isNested())+/) // FIXME: 84 m ~= 'M'; // Mangle char for member/nested functions. 85 if (auto t = cast(Type)s.getType()) 86 if (t.mangled) 87 m ~= t.mangled; 88 89 return m; 90 } 91 } 92 93 /// A symbol that has its own scope with a symbol table. 94 class ScopeSymbol : Symbol 95 { 96 SymbolTable symbolTable; /// The symbol table. 97 Symbol[] members; /// The member symbols (in lexical order.) 98 99 /// Constructs a ScopeSymbol object. 100 this(SYM sid, Identifier* name, SLoc loc) 101 { 102 super(sid, name, loc); 103 } 104 105 /// Constructs a ScopeSymbol object with the SYM.Scope ID. 106 this(Identifier* name = Ident.Empty, SLoc loc = SLoc.init) 107 { 108 super(SYM.Scope, name, loc); 109 } 110 111 /// Looks up name in the table. 112 Symbol lookup(Identifier* name) 113 { 114 return symbolTable.lookup(name); 115 } 116 117 /// Looks up a symbol in the table using its string hash. 118 Symbol lookup(hash_t hash) 119 { 120 return symbolTable.lookup(hash); 121 } 122 123 /// Inserts a symbol into the table. 124 void insert(Symbol s, Identifier* name) 125 { 126 symbolTable.insert(s, name); 127 members ~= s; 128 } 129 } 130 131 /// A module symbol. 132 class ModuleSymbol : ScopeSymbol 133 { 134 ModuleInfoSymbol varminfo; /// The ModuleInfo for this module. 135 136 this(Identifier* name = null, SLoc loc = SLoc.init) 137 { 138 super(SYM.Module, name, loc); 139 } 140 } 141 142 /// A package symbol. 143 class PackageSymbol : ScopeSymbol 144 { 145 this(Identifier* name = null, SLoc loc = SLoc.init) 146 { 147 super(SYM.Package, name, loc); 148 } 149 } 150 151 /// Aggregates have function and field members. 152 abstract class AggregateSymbol : ScopeSymbol 153 { 154 Type type; 155 FunctionSymbol[] funcs; 156 VariableSymbol[] fields; 157 AliasSymbol[] aliases; /// AliasThis symbols. 158 159 this(SYM sid, Identifier* name, SLoc loc) 160 { 161 super(sid, name, loc); 162 } 163 164 override: 165 void insert(Symbol s, Identifier* ident) 166 { 167 if (s.isVariable()) 168 // Append variable to fields. 169 fields ~= s.to!(VariableSymbol); 170 else if (s.isFunction()) 171 // Append function to funcs. 172 funcs ~= s.to!(FunctionSymbol); 173 super.insert(s, ident); 174 } 175 176 Type getType() 177 { 178 return type; 179 } 180 181 cstring toMangle() 182 { 183 return Symbol.toMangle(this); 184 } 185 } 186 187 /// A class symbol. 188 class ClassSymbol : AggregateSymbol 189 { 190 ClassSymbol base; /// The inherited base class. 191 InterfaceSymbol[] ifaces; /// The inherited interfaces. 192 193 TypeInfoSymbol vartinfo; /// The TypeInfo of this class. 194 195 this(Identifier* name, SLoc loc) 196 { 197 super(SYM.Class, name, loc); 198 this.type = new TypeClass(this); 199 } 200 } 201 202 /// Special classes, e.g.: Object, ClassInfo, ModuleInfo etc. 203 class SpecialClassSymbol : ClassSymbol 204 { 205 this(Identifier* name, SLoc loc) 206 { 207 super(name, loc); 208 } 209 210 /// Handle mangling differently for special classes. 211 override cstring toMangle() 212 { 213 auto parent_save = parent; 214 parent = null; 215 auto m = super.toMangle(); 216 parent = parent_save; 217 return m; 218 } 219 } 220 221 /// An interface symbol. 222 class InterfaceSymbol : ClassSymbol 223 { 224 this(Identifier* name, SLoc loc) 225 { 226 super(name, loc); 227 this.sid = SYM.Interface; 228 this.type = new TypeClass(this); 229 } 230 } 231 232 /// A struct symbol. 233 class StructSymbol : AggregateSymbol 234 { 235 bool isAnonymous; 236 this(Identifier* name, SLoc loc) 237 { 238 super(SYM.Struct, name, loc); 239 this.type = new TypeStruct(this); 240 this.isAnonymous = name is null; 241 } 242 } 243 244 /// A union symbol. 245 class UnionSymbol : StructSymbol 246 { 247 bool isAnonymous; 248 this(Identifier* name, SLoc loc) 249 { 250 super(name, loc); 251 this.sid = SYM.Union; 252 this.type = new TypeStruct(this); 253 this.isAnonymous = name is null; 254 } 255 } 256 257 /// An enum symbol. 258 class EnumSymbol : ScopeSymbol 259 { 260 TypeEnum type; 261 bool isAnonymous; 262 this(Identifier* name, SLoc loc) 263 { 264 super(SYM.Enum, name, loc); 265 this.type = new TypeEnum(this); 266 this.isAnonymous = name is null; 267 } 268 269 void setType(TypeEnum type) 270 { 271 this.type = type; 272 } 273 274 override Type getType() 275 { 276 return type; 277 } 278 } 279 280 /// A function symbol. 281 class FunctionSymbol : ScopeSymbol 282 { 283 Protection prot; /// The protection. 284 StorageClass stcs; /// The storage classes. 285 LinkageType linkage; /// The linkage type. 286 TypeFunction type; /// The type of this function. 287 ParametersSymbol params; /// The parameters of this function. 288 289 this(Identifier* name, SLoc loc) 290 { 291 super(SYM.Function, name, loc); 292 } 293 294 override Type getType() 295 { 296 return type; 297 } 298 299 cstring toText() 300 { // := ReturnType Name ParameterList 301 return type.retType.toString() ~ name.str ~ params.toString(); 302 } 303 304 override cstring toMangle() 305 { 306 if (isDMain()) 307 return "_Dmain"; 308 if (isWinMain() || isDllMain()) 309 return name.str; 310 return DeclarationSymbol.toMangle(this, linkage); 311 } 312 313 bool isDMain() 314 { 315 return name is Ident.main && linkage != LinkageType.C && !isMember(); 316 } 317 318 bool isWinMain() 319 { 320 return name is Ident.WinMain && linkage != LinkageType.C && !isMember(); 321 } 322 323 bool isDllMain() 324 { 325 return name is Ident.DllMain && linkage != LinkageType.C && !isMember(); 326 } 327 328 bool isMember() 329 { // TODO 330 return false; 331 } 332 } 333 334 /// The parameter symbol. 335 class ParameterSymbol : Symbol 336 { 337 StorageClass stcs; /// Storage classes. 338 VariadicStyle variadic; /// Variadic style. 339 Type ptype; /// The parameter's type. 340 Expression defValue; /// The default initialization value. 341 342 TypeParameter type; /// Type of this symbol. 343 344 this(Type ptype, Identifier* name, 345 StorageClass stcs, VariadicStyle variadic, SLoc loc) 346 { 347 super(SYM.Parameter, name, loc); 348 this.stcs = stcs; 349 this.variadic = variadic; 350 this.ptype = ptype; 351 this.type = new TypeParameter(ptype, stcs, variadic); 352 } 353 354 cstring toText() 355 { // := StorageClasses? ParamType? ParamName? (" = " DefaultValue)? "..."? 356 char[] s; 357 foreach (stc; EnumString.all(stcs)) 358 s ~= stc ~ " "; 359 if (type) 360 s ~= type.toString(); 361 if (name !is Ident.Empty) 362 s ~= name.str; 363 if (defValue) 364 s ~= " = " ~ defValue.toText(); 365 else if (variadic) 366 s ~= "..."; 367 assert(s.length, "empty parameter?"); 368 return s; 369 } 370 371 override cstring toMangle() 372 { 373 return type.toMangle(); 374 } 375 } 376 377 /// A list of ParameterSymbol objects. 378 class ParametersSymbol : Symbol 379 { 380 ParameterSymbol[] params; /// The parameters. 381 TypeParameters type; /// Type of this symbol. 382 383 this(ParameterSymbol[] params, SLoc loc = SLoc.init) 384 { 385 super(SYM.Parameters, Ident.Empty, loc); 386 this.params = params; 387 auto ptypes = new TypeParameter[params.length]; 388 foreach (i, p; params) 389 ptypes[i] = p.type; 390 this.type = new TypeParameters(ptypes); 391 } 392 393 /// Returns the variadic style of the last parameter. 394 VariadicStyle getVariadic() 395 { 396 return type.getVariadic(); 397 } 398 399 cstring toText() 400 { // := "(" ParameterList ")" 401 char[] s; 402 s ~= "("; 403 foreach (i, p; params) { 404 if (i) s ~= ", "; // Append comma if more than one param. 405 s ~= p.toString(); 406 } 407 s ~= ")"; 408 return s; 409 } 410 411 override cstring toMangle() 412 { 413 return type.toMangle(); 414 } 415 } 416 417 /// A variable symbol. 418 class VariableSymbol : Symbol 419 { 420 Protection prot; /// The protection. 421 StorageClass stcs; /// The storage classes. 422 LinkageType linkage; /// The linkage type. 423 424 Type type; /// The type of this variable. 425 Expression value; /// The value of this variable. 426 427 this(Identifier* name, 428 Protection prot, StorageClass stcs, LinkageType linkage, 429 SLoc loc) 430 { 431 super(SYM.Variable, name, loc); 432 433 this.prot = prot; 434 this.stcs = stcs; 435 this.linkage = linkage; 436 } 437 438 this(Identifier* name, SLoc loc) 439 { 440 this(name, Protection.None, StorageClass.None, LinkageType.None, loc); 441 } 442 443 override cstring toMangle() 444 { 445 return DeclarationSymbol.toMangle(this, linkage); 446 } 447 } 448 449 /// An enum member symbol. 450 class EnumMemberSymbol : VariableSymbol 451 { 452 this(Identifier* name, 453 Protection prot, StorageClass stcs, LinkageType linkage, 454 SLoc loc) 455 { 456 super(name, prot, stcs, linkage, loc); 457 this.sid = SYM.EnumMember; 458 } 459 } 460 461 /// A this-pointer symbol for member functions (or frame pointers.) 462 class ThisSymbol : VariableSymbol 463 { 464 this(Type type, SLoc loc) 465 { 466 super(Keyword.This, loc); 467 this.type = type; 468 } 469 } 470 471 /// A ClassInfo variable symbol. 472 class ClassInfoSymbol : VariableSymbol 473 { 474 ClassSymbol clas; /// The class to provide info for. 475 /// Constructs a ClassInfoSymbol object. 476 /// 477 /// Params: 478 /// clas = ClassInfo for this class. 479 /// classClassInfo = The global ClassInfo class from object.d. 480 this(ClassSymbol clas, ClassSymbol classClassInfo) 481 { 482 super(clas.name, clas.loc); 483 this.type = classClassInfo.type; 484 this.clas = clas; 485 this.stcs = StorageClass.Static; 486 } 487 488 // Something toSomething() // TODO: 489 // { return null; } 490 } 491 492 /// A ModuleInfo variable symbol. 493 class ModuleInfoSymbol : VariableSymbol 494 { 495 ModuleSymbol modul; /// The module to provide info for. 496 /// Constructs a ModuleInfoSymbol object. 497 /// 498 /// Params: 499 /// modul = ModuleInfo for this module. 500 /// classModuleInfo = The global ModuleInfo class from object.d. 501 this(ModuleSymbol modul, ClassSymbol classModuleInfo) 502 { 503 super(modul.name, modul.loc); 504 this.type = classModuleInfo.type; 505 this.modul = modul; 506 this.stcs = StorageClass.Static; 507 } 508 509 // Something toSomething() // TODO: 510 // { return null; } 511 } 512 513 /// A TypeInfo variable symbol. 514 class TypeInfoSymbol : VariableSymbol 515 { 516 Type titype; /// The type to provide info for. 517 /// Constructs a TypeInfo object. 518 /// 519 /// The variable is of type TypeInfo and its name is mangled. 520 /// E.g.: 521 /// --- 522 /// TypeInfo _D10TypeInfo_a6__initZ; // For type "char". 523 /// --- 524 /// Params: 525 /// titype = TypeInfo for this type. 526 /// name = The mangled name of this variable. 527 /// classTypeInfo = The global TypeInfo class from object.d. 528 this(Type titype, Identifier* name, ClassSymbol classTypeInfo) 529 { // FIXME: provide the node of TypeInfo for now. 530 // titype has no node; should every Type get one? 531 super(name, classTypeInfo.loc); 532 this.type = classTypeInfo.type; 533 this.titype = titype; 534 this.stcs = StorageClass.Static; 535 this.prot = Protection.Public; 536 this.linkage = LinkageType.C; 537 } 538 539 // Something toSomething() // TODO: 540 // { 541 // switch (titype.tid) 542 // { 543 // case TYP.Char: break; 544 // case TYP.Function: break; 545 // // etc. 546 // default: 547 // } 548 // return null; 549 // } 550 } 551 552 // TODO: let dil.semantic.Types.Type inherit from Symbol? 553 /// A type symbol. 554 class TypeSymbol : Symbol 555 { 556 Type type; /// Wrapper around this type. 557 558 this(Type type) 559 { 560 super(SYM.Type, null, SLoc.init); 561 this.type = type; 562 } 563 } 564 565 /// A tuple symbol. 566 class TupleSymbol : Symbol 567 { 568 TypeTuple type; /// The type of this tuple. 569 Symbol[] items; /// The items in this tuple. 570 571 this(Symbol[] items, Identifier* name, SLoc loc) 572 { 573 super(SYM.Tuple, name, loc); 574 } 575 576 /// Returns the type only when all elements are types, otherwise null. 577 override Type getType() 578 { 579 if (!type && hasOnlyTypes()) 580 type = makeTypeTuple(); 581 return type; 582 } 583 584 /// Returns true if all elements are types (also if the tuple is empty.) 585 bool hasOnlyTypes() 586 { 587 foreach (item; items) 588 if (!item.isType()) 589 return false; 590 return true; 591 } 592 593 /// Creates a TypeTuple instance from the items of this tuple. 594 TypeTuple makeTypeTuple() 595 in { assert(hasOnlyTypes()); } 596 body 597 { 598 auto types = new Type[items.length]; // Allocate exact amount of types. 599 foreach (i, item; items) 600 types[i] = item.to!(TypeSymbol).type; 601 return new TypeTuple(types); 602 } 603 604 override cstring toMangle() 605 { 606 return DeclarationSymbol.toMangle(this, LinkageType.D /+FIXME+/); 607 } 608 } 609 610 // class ExprTupleSymbol : TupleSymbol 611 // { 612 // // TODO: 613 // } 614 615 /// An alias symbol. 616 class AliasSymbol : Symbol 617 { 618 Type aliasType; 619 Symbol aliasSym; 620 621 this(Identifier* name, SLoc loc) 622 { 623 super(SYM.Alias, name, loc); 624 } 625 626 override cstring toMangle() 627 { 628 return DeclarationSymbol.toMangle(this, LinkageType.D /+FIXME+/); 629 } 630 } 631 632 /// A typedef symbol. 633 class TypedefSymbol : Symbol 634 { 635 this(Identifier* name, SLoc loc) 636 { 637 super(SYM.Typedef, name, loc); 638 } 639 640 override cstring toMangle() 641 { 642 return Symbol.toMangle(this); 643 } 644 } 645 646 /// A template symbol. 647 class TemplateSymbol : ScopeSymbol 648 { 649 AliasSymbol[] aliases; /// AliasThis symbols. 650 this(Identifier* name, SLoc loc) 651 { 652 super(SYM.Template, name, loc); 653 } 654 } 655 656 /// A template instance symbol. 657 class TemplInstanceSymbol : ScopeSymbol 658 { 659 // TemplArgSymbol[] tiArgs; 660 TemplateSymbol tplSymbol; 661 this(Identifier* name, SLoc loc) 662 { 663 super(SYM.TemplateInstance, name, loc); 664 } 665 666 override cstring toMangle() 667 { // := ParentMangle? NameMangleLength NameMangle 668 if (name is Ident.Empty) 669 {} // TODO: ? 670 cstring pm; // Parent mangle. 671 if (!tplSymbol) 672 {} // Error: undefined 673 else if (tplSymbol.parent) 674 { 675 pm = tplSymbol.parent.toMangle(); 676 if (pm.length >= 2 && pm[0..2] == "_D") 677 pm = pm[2..$]; // Skip the prefix. 678 } 679 cstring id = name.str; 680 return pm ~ itoa(id.length) ~ id; 681 } 682 } 683 684 /// A template mixin symbol. 685 class TemplMixinSymbol : TemplInstanceSymbol 686 { 687 this(Identifier* name, SLoc loc) 688 { 689 super(name, loc); 690 this.sid = SYM.TemplateMixin; 691 } 692 693 override cstring toMangle() 694 { 695 return Symbol.toMangle(this); 696 } 697 } 698 699 /// A list of symbols that share the same identifier. 700 /// 701 /// These can be functions, templates and aggregates with template parameter lists. 702 class OverloadSet : Symbol 703 { 704 Symbol[] symbols; 705 706 this(Identifier* name, SLoc loc) 707 { 708 super(SYM.OverloadSet, name, loc); 709 } 710 711 void add(Symbol s) 712 { 713 symbols ~= s; 714 } 715 }