1 module d.ir.symbol; 2 3 import d.ir.dscope; 4 import d.ir.expression; 5 import d.ir.type; 6 7 import d.common.node; 8 9 import source.context; 10 import source.name; 11 12 public import d.common.qualifier; 13 14 enum Step { 15 Parsed, 16 Populated, 17 Signed, 18 Processed, 19 } 20 21 enum InTemplate { 22 No, 23 Yes, 24 } 25 26 class Symbol : Node { 27 Name name; 28 Name mangle; 29 30 import std.bitmanip; 31 mixin(bitfields!( 32 Step, "step", 2, 33 Linkage, "linkage", 3, 34 Visibility, "visibility", 3, 35 InTemplate, "inTemplate", 1, 36 bool, "hasThis", 1, 37 bool, "hasContext", 1, 38 bool, "isPoisoned", 1, 39 bool, "isAbstract", 1, 40 bool, "isProperty", 1, 41 uint, "__derived", 18, 42 )); 43 44 this(Location location, Name name) { 45 super(location); 46 47 this.name = name; 48 } 49 50 string toString(const Context c) const { 51 return name.toString(c); 52 } 53 54 protected: 55 @property derived() const { 56 return __derived; 57 } 58 59 @property derived(uint val) { 60 return __derived = val; 61 } 62 } 63 64 /** 65 * Symbol that introduce a scope. 66 * NB: Symbols that introduce non standard scope may not extend this. 67 */ 68 abstract class ScopeSymbol : Symbol, Scope { 69 mixin ScopeImpl; 70 71 this(Location location, Scope parentScope, Name name) { 72 super(location, name); 73 fillParentScope(parentScope); 74 } 75 } 76 77 /** 78 * Symbol that represent a value once resolved. 79 */ 80 abstract class ValueSymbol : Symbol { 81 this(Location location, Name name) { 82 super(location, name); 83 } 84 } 85 86 /** 87 * Package 88 */ 89 class Package : Symbol, Scope { 90 mixin ScopeImpl!(ScopeType.Module); 91 92 Package parent; 93 94 this(Location location, Name name, Package parent) { 95 super(location, name); 96 97 this.parent = parent; 98 } 99 } 100 101 /** 102 * Function 103 */ 104 class Function : ValueSymbol, Scope { 105 mixin ScopeImpl; 106 FunctionType type; 107 108 Variable[] params; 109 uint[Variable] closure; 110 111 import d.ir.instruction; 112 Body fbody; 113 114 this( 115 Location location, 116 Scope parentScope, 117 FunctionType type, 118 Name name, 119 Variable[] params, 120 ) { 121 super(location, name); 122 fillParentScope(parentScope); 123 124 this.type = type; 125 this.params = params; 126 } 127 128 @property intrinsicID() const { 129 if (hasThis) { 130 return Intrinsic.None; 131 } 132 133 return cast(Intrinsic) __derived; 134 } 135 136 @property intrinsicID(Intrinsic id) in { 137 assert(!hasThis, "Method can't be intrinsic"); 138 assert(intrinsicID == Intrinsic.None, "This is already an intrinsic"); 139 } do { 140 __derived = id; 141 return intrinsicID; 142 } 143 144 void dump(const Context c) const { 145 import std.algorithm, std.range; 146 auto params = params 147 .map!(p => p.name.toString(c)) 148 .join(", "); 149 150 auto retStr = (step >= Step.Signed) 151 ? type.returnType.toString(c) 152 : "__untyped"; 153 154 import std.stdio; 155 write(retStr, ' ', name.toString(c), '(', params, ") {"); 156 fbody.dump(c); 157 writeln("}\n"); 158 } 159 } 160 161 /** 162 * Entry for template parameters 163 */ 164 class TemplateParameter : Symbol { 165 this(Location location, Name name, uint index) { 166 super(location, name); 167 168 this.derived = index; 169 } 170 171 final: 172 @property index() const { 173 return derived; 174 } 175 } 176 177 /** 178 * Superclass for struct, class and interface. 179 */ 180 abstract class Aggregate : ScopeSymbol { 181 Name[] aliasThis; 182 Symbol[] members; 183 184 this(Location location, Scope parentScope, Name name, Symbol[] members) { 185 super(location, parentScope, name); 186 187 this.members = members; 188 } 189 } 190 191 final: 192 /** 193 * Module 194 */ 195 class Module : Package { 196 Symbol[] members; 197 Function[] tests; 198 199 this(Location location, Name name, Package parent) { 200 super(location, name, parent); 201 dmodule = this; 202 } 203 } 204 205 /** 206 * Placeholder in symbol tables for templates and functions. 207 */ 208 class OverloadSet : Symbol { 209 Symbol[] set; 210 211 this(Location location, Name name, Symbol[] set) { 212 super(location, name); 213 this.mangle = name; 214 this.set = set; 215 } 216 217 OverloadSet clone() { 218 auto os = new OverloadSet(location, name, set); 219 os.mangle = mangle; 220 return os; 221 } 222 223 @property isResolved() const { 224 return !!__derived; 225 } 226 227 @property isResolved(bool resolved) { 228 __derived = resolved; 229 return resolved; 230 } 231 } 232 233 /** 234 * Variable 235 */ 236 class Variable : ValueSymbol { 237 Expression value; 238 ParamType paramType; 239 240 this( 241 Location location, 242 ParamType paramType, 243 Name name, 244 Expression value = null, 245 ) { 246 super(location, name); 247 248 this.paramType = paramType; 249 this.value = value; 250 } 251 252 this(Location location, Type type, Name name, Expression value = null) { 253 super(location, name); 254 255 this.type = type; 256 this.value = value; 257 } 258 259 @property 260 inout(Type) type() inout { 261 return paramType.getType(); 262 } 263 264 @property 265 Type type(Type t) { 266 paramType = t.getParamType(ParamKind.Regular); 267 return t; 268 } 269 270 @property 271 bool isRef() const { 272 return paramType.isRef; 273 } 274 275 @property 276 bool isFinal() const { 277 return paramType.isFinal; 278 } 279 280 @property storage() const { 281 return cast(Storage) (__derived & 0x03); 282 } 283 284 @property storage(Storage storage) { 285 __derived = storage; 286 return storage; 287 } 288 289 override 290 string toString(const Context c) const { 291 return type.toString(c) ~ " " ~ name.toString(c) 292 ~ " = " ~ value.toString(c) ~ ";"; 293 } 294 } 295 296 /** 297 * Field 298 * Simply a Variable with a field index. 299 */ 300 class Field : ValueSymbol { 301 CompileTimeExpression value; 302 Type type; 303 304 this( 305 Location location, 306 uint index, 307 Type type, 308 Name name, 309 CompileTimeExpression value = null, 310 ) { 311 super(location, name); 312 313 this.value = value; 314 this.type = type; 315 this.derived = index; 316 317 // Always true for fields. 318 this.hasThis = true; 319 } 320 321 @property index() const { 322 return derived; 323 } 324 } 325 326 /** 327 * Template 328 */ 329 class Template : ScopeSymbol { 330 TemplateInstance[string] instances; 331 Type[] ifti; 332 333 TemplateParameter[] parameters; 334 335 import d.ast.declaration : Declaration; 336 Declaration[] members; 337 338 this( 339 Location location, 340 Scope parentScope, 341 Name name, 342 TemplateParameter[] parameters, 343 Declaration[] members, 344 ) { 345 super(location, parentScope, name); 346 347 this.parameters = parameters; 348 this.members = members; 349 } 350 351 @property storage() const { 352 return cast(Storage) (__derived & 0x03); 353 } 354 355 @property storage(Storage storage) { 356 __derived = storage; 357 return storage; 358 } 359 } 360 361 /** 362 * Template type parameter 363 */ 364 class TypeTemplateParameter : TemplateParameter { 365 Type specialization; 366 Type defaultValue; 367 368 this( 369 Location location, 370 Name name, 371 uint index, 372 Type specialization, 373 Type defaultValue, 374 ) { 375 super(location, name, index); 376 377 this.specialization = specialization; 378 this.defaultValue = defaultValue; 379 } 380 381 override string toString(const Context c) const { 382 return name.toString(c) 383 ~ " : " ~ specialization.toString(c) 384 ~ " = " ~ defaultValue.toString(c); 385 } 386 } 387 388 /** 389 * Template value parameter 390 */ 391 class ValueTemplateParameter : TemplateParameter { 392 Type type; 393 Expression defaultValue; 394 395 this( 396 Location location, 397 Name name, 398 uint index, 399 Type type, 400 Expression defaultValue, 401 ) { 402 super(location, name, index); 403 404 this.type = type; 405 this.defaultValue = defaultValue; 406 } 407 } 408 409 /** 410 * Template alias parameter 411 */ 412 class AliasTemplateParameter : TemplateParameter { 413 this(Location location, Name name, uint index) { 414 super(location, name, index); 415 } 416 } 417 418 /** 419 * Template typed alias parameter 420 */ 421 class TypedAliasTemplateParameter : TemplateParameter { 422 Type type; 423 424 this(Location location, Name name, uint index, Type type) { 425 super(location, name, index); 426 427 this.type = type; 428 } 429 } 430 431 /** 432 * Template instance 433 */ 434 class TemplateInstance : Symbol, Scope { 435 mixin ScopeImpl!(ScopeType.WithParent, Template); 436 437 TemplateArgument[] args; 438 Symbol[] members; 439 440 this(Location location, Template tpl, TemplateArgument[] args) { 441 super(location, tpl.name); 442 fillParentScope(tpl); 443 444 this.args = args; 445 } 446 447 Template getTemplate() { 448 return getParentScope(); 449 } 450 451 @property storage() const { 452 return cast(Storage) (__derived & 0x03); 453 } 454 455 @property storage(Storage storage) { 456 __derived = storage; 457 return storage; 458 } 459 } 460 461 alias TemplateArgument = Type.UnionType!(typeof(null), Symbol, CompileTimeExpression); 462 463 auto apply(alias undefinedHandler, alias handler)(TemplateArgument a) { 464 alias Tag = typeof(a.tag); 465 final switch(a.tag) with(Tag) { 466 case Undefined : 467 return undefinedHandler(); 468 469 case Symbol : 470 return handler(a.get!Symbol); 471 472 case CompileTimeExpression : 473 return handler(a.get!CompileTimeExpression); 474 475 case Type : 476 return handler(a.get!Type); 477 } 478 } 479 480 unittest { 481 TemplateArgument.init.apply!(() {}, (i) { assert(0); })(); 482 } 483 484 /** 485 * Alias of symbols 486 */ 487 class SymbolAlias : Symbol { 488 Symbol symbol; 489 490 this(Location location, Name name, Symbol symbol) { 491 super(location, name); 492 493 this.symbol = symbol; 494 } 495 /+ 496 invariant() { 497 if (step >= Step.Signed) { 498 assert(symbol && hasContext == symbol.hasContext); 499 } 500 } 501 +/ 502 } 503 504 /** 505 * Alias of types 506 */ 507 class TypeAlias : Symbol { 508 Type type; 509 510 this(Location location, Name name, Type type) { 511 super(location, name); 512 513 this.type = type; 514 } 515 } 516 517 /** 518 * Alias of values 519 */ 520 class ValueAlias : ValueSymbol { 521 CompileTimeExpression value; 522 523 this(Location location, Name name, CompileTimeExpression value) { 524 super(location, name); 525 526 this.value = value; 527 } 528 } 529 530 /** 531 * Struct 532 */ 533 class Struct : Aggregate { 534 this(Location location, Scope parentScope, Name name, Symbol[] members) { 535 super(location, parentScope, name, members); 536 } 537 538 // XXX: std.bitmanip should really offer the possibility to create bitfield 539 // out of unused bits of existing bitfields. 540 @property hasIndirection() const in { 541 assert( 542 step >= Step.Signed, 543 "Struct need to be signed to use hasIndirection" 544 ); 545 } do { 546 return !!(derived & 0x01); 547 } 548 549 @property hasIndirection(bool hasIndirection) { 550 if (hasIndirection) { 551 derived = derived | 0x01; 552 } else { 553 derived = derived & ~0x01; 554 } 555 556 return hasIndirection; 557 } 558 559 @property isPod() const in { 560 assert( 561 step >= Step.Signed, 562 "Struct need to be signed to use isPod", 563 ); 564 } do { 565 return !!(derived & 0x02); 566 } 567 568 @property isPod(bool isPod) { 569 if (isPod) { 570 derived = derived | 0x02; 571 } else { 572 derived = derived & ~0x02; 573 } 574 575 return isPod; 576 } 577 578 @property isSmall() const in { 579 assert( 580 step >= Step.Signed, 581 "Struct need to be signed to use isSmall", 582 ); 583 } do { 584 return !!(derived & 0x04); 585 } 586 587 @property isSmall(bool isSmall) { 588 if (isSmall) { 589 derived = derived | 0x04; 590 } else { 591 derived = derived & ~0x04; 592 } 593 594 return isSmall; 595 } 596 } 597 598 /** 599 * Union 600 */ 601 class Union : Aggregate { 602 this(Location location, Scope parentScope, Name name, Symbol[] members) { 603 super(location, parentScope, name, members); 604 } 605 606 @property hasIndirection() const in { 607 assert( 608 step >= Step.Signed, 609 "Union need to be signed to use hasIndirection" 610 ); 611 } do { 612 return !!derived; 613 } 614 615 @property hasIndirection(bool hasIndirection) { 616 derived = hasIndirection; 617 return hasIndirection; 618 } 619 } 620 621 /** 622 * Class 623 */ 624 class Class : Aggregate { 625 Class base; 626 Interface[] interfaces; 627 628 this(Location location, Scope parentScope, Name name, Symbol[] members) { 629 super(location, parentScope, name, members); 630 631 this.name = name; 632 } 633 } 634 635 /** 636 * Interface 637 */ 638 class Interface : Aggregate { 639 Interface[] bases; 640 641 this( 642 Location location, 643 Scope parentScope, 644 Name name, 645 Interface[] bases, 646 Symbol[] members, 647 ) { 648 super(location, parentScope, name, members); 649 this.bases = bases; 650 } 651 } 652 653 /** 654 * Enum 655 */ 656 class Enum : ScopeSymbol { 657 Type type; 658 Variable[] entries; 659 660 this( 661 Location location, 662 Scope parentScope, 663 Name name, 664 Type type, 665 Variable[] entries, 666 ) { 667 super(location, parentScope, name); 668 669 this.type = type; 670 this.entries = entries; 671 } 672 } 673 674 /** 675 * Virtual method 676 * Simply a function declaration with its index in the vtable. 677 */ 678 class Method : Function { 679 uint index; 680 681 this( 682 Location location, 683 Scope parentScope, 684 uint index, 685 FunctionType type, 686 Name name, 687 Variable[] params, 688 ) { 689 super(location, parentScope, type, name, params); 690 691 this.index = index; 692 } 693 }