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 module vdc.ast.type; 10 11 import vdc.util; 12 import vdc.lexer; 13 import vdc.semantic; 14 import vdc.interpret; 15 16 import vdc.ast.node; 17 import vdc.ast.expr; 18 import vdc.ast.misc; 19 import vdc.ast.aggr; 20 import vdc.ast.tmpl; 21 import vdc.ast.stmt; 22 import vdc.ast.decl; 23 import vdc.ast.writer; 24 25 import stdext.util; 26 import std.conv; 27 28 class BuiltinPropertyBase : Symbol 29 { 30 string ident; 31 } 32 33 class BuiltinProperty(T) : BuiltinPropertyBase 34 { 35 Value value; 36 37 this(string id, T val) 38 { 39 ident = id; 40 value = Value.create(val); 41 } 42 43 override void toD(CodeWriter writer) 44 { 45 _assert(false); 46 } 47 48 override Type calcType() 49 { 50 return value.getType(); 51 } 52 override Value interpret(Context sc) 53 { 54 return value; 55 } 56 } 57 58 Symbol newBuiltinProperty(T)(Scope sc, string id, T val) 59 { 60 auto bp = new BuiltinProperty!T(id, val); 61 sc.addSymbol(id, bp); 62 return bp; 63 } 64 65 class BuiltinType(T) : Node 66 { 67 } 68 69 Scope[int] builtInScopes; 70 alias AssociativeArray!(int, Scope) _wa1; // fully instantiate type info 71 72 Scope getBuiltinBasicTypeScope(int tokid) 73 { 74 if(auto ps = tokid in builtInScopes) 75 return *ps; 76 77 Scope sc = new Scope; 78 79 foreach(tok; BasicTypeTokens) 80 { 81 if (tokid == tok) 82 { 83 alias Token2BasicType!(tok) BT; 84 85 newBuiltinProperty(sc, "init", BT.init); 86 newBuiltinProperty(sc, "sizeof", BT.sizeof); 87 newBuiltinProperty(sc, "mangleof", BT.mangleof); 88 newBuiltinProperty(sc, "alignof", BT.alignof); 89 newBuiltinProperty(sc, "stringof", BT.stringof); 90 static if(__traits(compiles, BT.min)) 91 newBuiltinProperty(sc, "min", BT.min); 92 static if(__traits(compiles, BT.max)) 93 newBuiltinProperty(sc, "max", BT.max); 94 static if(__traits(compiles, BT.nan)) 95 newBuiltinProperty(sc, "nan", BT.nan); 96 } 97 } 98 builtInScopes[tokid] = sc; 99 return sc; 100 } 101 102 class Type : Node 103 { 104 // semantic data 105 TypeInfo typeinfo; 106 107 mixin ForwardCtor!(); 108 109 abstract bool propertyNeedsParens() const; 110 111 override Type clone() 112 { 113 Type n = static_cast!Type(super.clone()); 114 return n; 115 } 116 117 enum ConversionFlags 118 { 119 kAllowBaseClass = 1 << 0, 120 kAllowConstConversion = 1 << 1, 121 kAllowBaseTypeConversion = 1 << 2, 122 123 // flags to clear on indirection 124 kIndirectionClear = kAllowBaseClass | kAllowBaseTypeConversion, 125 kImpliciteConversion = kAllowBaseClass | kAllowConstConversion | kAllowBaseTypeConversion, 126 } 127 128 bool convertableFrom(Type from, ConversionFlags flags) 129 { 130 if(from == this) 131 return true; 132 return false; 133 } 134 final bool convertableFromImplicite(Type from) 135 { 136 return convertableFrom(from, ConversionFlags.kImpliciteConversion); 137 } 138 139 Type commonType(Type other) 140 { 141 if(convertableFromImplicite(other)) 142 return this; 143 if(other.convertableFromImplicite(this)) 144 return other; 145 return semanticErrorType(this, " has no common type with ", other); 146 } 147 148 override void _semantic(Scope sc) 149 { 150 if(!typeinfo) 151 typeSemantic(sc); 152 } 153 154 void typeSemantic(Scope sc) 155 { 156 super._semantic(sc); 157 } 158 159 override Type calcType() 160 { 161 return this; 162 } 163 164 override Value interpret(Context sc) 165 { 166 return new TypeValue(this); 167 } 168 169 Value getProperty(Value sv, string ident, bool virtualCall) 170 { 171 return null; 172 } 173 174 Value getProperty(Value sv, Declarator decl, bool virtualCall) 175 { 176 return null; 177 } 178 179 final Value interpretProperty(Context ctx, string prop) 180 { 181 if(Value v = _interpretProperty(ctx, prop)) 182 return v; 183 return semanticErrorValue("cannot calculate property ", prop, " of type ", this); 184 } 185 Value _interpretProperty(Context ctx, string prop) 186 { 187 return null; 188 } 189 190 Value createValue(Context ctx, Value initValue) 191 { 192 return semanticErrorValue("cannot create value of type ", this); 193 } 194 195 Type opIndex(int v) 196 { 197 return semanticErrorType("cannot index a ", this); 198 } 199 200 Type opSlice(int b, int e) 201 { 202 return semanticErrorType("cannot slice a ", this); 203 } 204 205 Type opCall(Type args) 206 { 207 return semanticErrorType("cannot call a ", this); 208 } 209 210 ////////////////////////////////////////////////////////////// 211 Type unqualified() 212 { 213 return this; 214 } 215 } 216 217 class ErrorType : Type 218 { 219 mixin ForwardCtor!(); 220 221 override bool propertyNeedsParens() const { return false; } 222 override void toD(CodeWriter writer) { writer("_errortype_"); } 223 224 override Scope getScope() 225 { 226 if(!scop) 227 scop = new Scope(); 228 return scop; 229 } 230 } 231 232 // moved out of BasicType due to BUG9672 233 Type createBasicType(int tokid) 234 { 235 BasicType type = new BasicType; 236 type.id = tokid; 237 return type; 238 } 239 240 //BasicType only created for standard types associated with tokens 241 class BasicType : Type 242 { 243 mixin ForwardCtor!(); 244 245 override bool propertyNeedsParens() const { return false; } 246 247 static Type getSizeType() 248 { 249 return getType(TOK_uint); // TOK_ulong if compiling for 64-bit 250 } 251 252 static Type getType(int tokid) 253 { 254 static Type[] cachedTypes; 255 if(tokid >= cachedTypes.length) 256 cachedTypes.length = tokid + 1; 257 if(!cachedTypes[tokid]) 258 cachedTypes[tokid] = createBasicType(tokid); 259 return cachedTypes[tokid]; 260 } 261 262 static TypeInfo getTypeInfo(int id) 263 { 264 // TODO: convert foreach to table access for faster lookup 265 foreach(tok; BasicTypeTokens) 266 { 267 if (id == tok) 268 return typeid(Token2BasicType!(tok)); 269 } 270 return null; 271 } 272 273 static size_t getSizeof(int id) 274 { 275 // TODO: convert foreach to table access for faster lookup 276 foreach(tok; BasicTypeTokens) 277 { 278 if (id == tok) 279 return Token2BasicType!(tok).sizeof; 280 } 281 _assert(false); 282 return int.sizeof; 283 } 284 285 static string getMangleof(int id) 286 { 287 // TODO: convert foreach to table access for faster lookup 288 foreach(tok; BasicTypeTokens) 289 { 290 if (id == tok) 291 return Token2BasicType!(tok).mangleof; 292 } 293 _assert(false); 294 return null; 295 } 296 297 static size_t getAlignof(int id) 298 { 299 // TODO: convert foreach to table access for faster lookup 300 foreach(tok; BasicTypeTokens) 301 { 302 if (id == tok) 303 return Token2BasicType!(tok).alignof; 304 } 305 _assert(false); 306 return int.alignof; 307 } 308 309 static string getStringof(int id) 310 { 311 // TODO: convert foreach to table access for faster lookup 312 foreach(tok; BasicTypeTokens) 313 { 314 if (id == tok) 315 return Token2BasicType!(tok).stringof; 316 } 317 _assert(false); 318 return null; 319 } 320 321 static Value getMin(int id) 322 { 323 // TODO: convert foreach to table access for faster lookup 324 foreach(tok; BasicTypeTokens) 325 { 326 static if(__traits(compiles, Token2BasicType!(tok).min)) 327 if (id == tok) 328 return Value.create(Token2BasicType!(tok).min); 329 } 330 return .semanticErrorValue(tokenString(id), " has no min property"); 331 } 332 333 static Value getMax(int id) 334 { 335 // TODO: convert foreach to table access for faster lookup 336 foreach(tok; BasicTypeTokens) 337 { 338 static if(__traits(compiles, Token2BasicType!(tok).max)) 339 if (id == tok) 340 return Value.create(Token2BasicType!(tok).max); 341 } 342 return .semanticErrorValue(tokenString(id), " has no max property"); 343 } 344 345 override Value createValue(Context ctx, Value initValue) 346 { 347 // TODO: convert foreach to table access for faster lookup 348 foreach(tok; BasicTypeTokens) 349 { 350 if (id == tok) 351 { 352 if(initValue) 353 return createInitValue!(Token2ValueType!(tok))(ctx, initValue); 354 return Value.create(Token2BasicType!(tok).init); 355 } 356 } 357 return semanticErrorValue("cannot create value of type ", this); 358 } 359 360 override void typeSemantic(Scope sc) 361 { 362 _assert(id != TOK_auto); 363 typeinfo = getTypeInfo(id); 364 } 365 366 override Scope getScope() 367 { 368 if(!scop) 369 scop = getBuiltinBasicTypeScope(id); 370 return scop; 371 } 372 373 enum Category { kInteger, kFloat, kComplex, kVoid } 374 375 static int categoryLevel(int id) 376 { 377 switch(id) 378 { 379 case TOK_bool: return 0; 380 case TOK_byte: return 1; 381 case TOK_ubyte: return 1; 382 case TOK_short: return 2; 383 case TOK_ushort: return 2; 384 case TOK_int: return 4; 385 case TOK_uint: return 4; 386 case TOK_long: return 8; 387 case TOK_ulong: return 8; 388 case TOK_char: return 1; 389 case TOK_wchar: return 2; 390 case TOK_dchar: return 4; 391 case TOK_float: return 10; // assume al floats convertable, ignore lost accuracy 392 case TOK_double: return 10; 393 case TOK_real: return 10; 394 case TOK_ifloat: return 10; 395 case TOK_idouble: return 10; 396 case TOK_ireal: return 10; 397 case TOK_cfloat: return 16; 398 case TOK_cdouble: return 16; 399 case TOK_creal: return 16; 400 default: assert(false); 401 } 402 } 403 404 static Category category(int id) 405 { 406 switch(id) 407 { 408 case TOK_bool: return Category.kInteger; 409 case TOK_byte: return Category.kInteger; 410 case TOK_ubyte: return Category.kInteger; 411 case TOK_short: return Category.kInteger; 412 case TOK_ushort: return Category.kInteger; 413 case TOK_int: return Category.kInteger; 414 case TOK_uint: return Category.kInteger; 415 case TOK_long: return Category.kInteger; 416 case TOK_ulong: return Category.kInteger; 417 case TOK_char: return Category.kInteger; 418 case TOK_wchar: return Category.kInteger; 419 case TOK_dchar: return Category.kInteger; 420 case TOK_float: return Category.kFloat; 421 case TOK_double: return Category.kFloat; 422 case TOK_real: return Category.kFloat; 423 case TOK_ifloat: return Category.kFloat; 424 case TOK_idouble: return Category.kFloat; 425 case TOK_ireal: return Category.kFloat; 426 case TOK_cfloat: return Category.kComplex; 427 case TOK_cdouble: return Category.kComplex; 428 case TOK_creal: return Category.kComplex; 429 case TOK_void: return Category.kVoid; 430 default: break; 431 } 432 _assert(false); 433 return Category.kVoid; 434 } 435 436 override Value _interpretProperty(Context ctx, string prop) 437 { 438 switch(prop) 439 { 440 // all types 441 case "init": 442 return createValue(nullContext, null); 443 case "sizeof": 444 return Value.create(getSizeof(id)); 445 case "alignof": 446 return Value.create(getAlignof(id)); 447 case "mangleof": 448 return Value.create(getMangleof(id)); 449 case "stringof": 450 return Value.create(getStringof(id)); 451 452 // integer types 453 case "min": 454 return getMin(id); 455 case "max": 456 return getMax(id); 457 458 // floating point types 459 case "infinity": 460 case "nan": 461 case "dig": 462 case "epsilon": 463 case "mant_dig": 464 case "max_10_exp": 465 case "max_exp": 466 case "min_10_exp": 467 case "min_exp": 468 case "min_normal": 469 case "re": 470 case "im": 471 default: 472 return super._interpretProperty(ctx, prop); 473 } 474 } 475 476 override bool convertableFrom(Type from, ConversionFlags flags) 477 { 478 if(super.convertableFrom(from, flags)) 479 return true; 480 481 auto bt = cast(BasicType) from; 482 if(!bt) 483 return false; 484 if(id == bt.id) 485 return true; 486 487 Category cat = category(id); 488 Category fcat = category(bt.id); 489 490 if(flags & ConversionFlags.kAllowBaseTypeConversion) 491 return cat == fcat; 492 if(flags & ConversionFlags.kImpliciteConversion) 493 { 494 if(cat == Category.kVoid || fcat != Category.kVoid) 495 return cat == fcat; 496 return (categoryLevel(id) >= categoryLevel(bt.id)); 497 } 498 return false; 499 } 500 501 override void toD(CodeWriter writer) 502 { 503 _assert(id != TOK_auto); 504 writer(id); 505 } 506 } 507 508 class NullType : Type 509 { 510 override bool propertyNeedsParens() const { return false; } 511 512 override void toD(CodeWriter writer) 513 { 514 writer("Null"); 515 } 516 } 517 518 //AutoType: 519 // auto added implicitely if there is no other type specified 520 class AutoType : Type 521 { 522 mixin ForwardCtor!(); 523 524 override bool propertyNeedsParens() const { return false; } 525 526 override void toD(CodeWriter writer) 527 { 528 if(id != TOK_auto) // only implicitely added? 529 writer(id); 530 } 531 532 override Value createValue(Context ctx, Value initValue) 533 { 534 if(!initValue) 535 return semanticErrorValue("no initializer in auto declaration"); 536 return initValue; 537 } 538 539 override Type calcType() 540 { 541 Expression expr; 542 543 if(auto decl = cast(Decl) parent) 544 { 545 Declarators decls = decl.getDeclarators(); 546 if(auto declinit = cast(DeclaratorInitializer) decls.getMember(0)) 547 expr = declinit.getInitializer(); 548 } 549 if(expr) 550 return expr.calcType(); 551 return semanticErrorType("no initializer in auto declaration"); 552 } 553 554 override bool convertableFrom(Type from, ConversionFlags flags) 555 { 556 return calcType().convertableFrom(from, flags); 557 } 558 } 559 560 class VectorType : Type 561 { 562 mixin ForwardCtor!(); 563 564 override bool propertyNeedsParens() const { return true; } 565 566 override void toD(CodeWriter writer) 567 { 568 writer("__vector(", getMember(0), ")"); 569 } 570 } 571 572 //ModifiedType: 573 // [Type] 574 class ModifiedType : Type 575 { 576 mixin ForwardCtor!(); 577 578 override bool propertyNeedsParens() const { return true; } 579 580 Type getType() { return getMember!Type(0); } // ignoring modifiers 581 582 override Type unqualified() 583 { 584 return getType(); 585 } 586 587 override void typeSemantic(Scope sc) 588 { 589 TypeInfo_Const ti; 590 switch(id) 591 { 592 case TOK_const: ti = new TypeInfo_Const; break; 593 case TOK_immutable: ti = new TypeInfo_Invariant; break; 594 case TOK_inout: ti = new TypeInfo_Inout; break; 595 case TOK_shared: ti = new TypeInfo_Shared; break; 596 default: _assert(false); 597 } 598 599 auto type = getType(); 600 type.semantic(sc); 601 ti.base = type.typeinfo; 602 603 typeinfo = ti; 604 } 605 606 override bool convertableFrom(Type from, ConversionFlags flags) 607 { 608 if(super.convertableFrom(from, flags)) 609 return true; 610 611 Type nextThis = getType(); 612 auto modfrom = cast(ModifiedType) from; 613 if(modfrom) 614 { 615 Type nextFrom = modfrom.getType(); 616 if(id == modfrom.id) 617 if(nextThis.convertableFrom(nextFrom, flags)) 618 return true; 619 620 if(flags & ConversionFlags.kAllowConstConversion) 621 if(id == TOK_const && modfrom.id == TOK_immutable) 622 if(nextThis.convertableFrom(nextFrom, flags)) 623 return true; 624 } 625 if(flags & ConversionFlags.kAllowConstConversion) 626 if(id == TOK_const) 627 if(nextThis.convertableFrom(from, flags)) 628 return true; 629 return false; 630 } 631 632 override Value createValue(Context ctx, Value initValue) 633 { 634 return getType().createValue(ctx, initValue); // TODO: ignores modifier 635 } 636 637 override void toD(CodeWriter writer) 638 { 639 writer(id, "(", getMember(0), ")"); 640 } 641 } 642 643 //IdentifierType: 644 // [IdentifierList] 645 class IdentifierType : Type 646 { 647 mixin ForwardCtor!(); 648 649 override bool propertyNeedsParens() const { return false; } 650 651 //Node resolved; 652 Type type; 653 654 IdentifierList getIdentifierList() { return getMember!IdentifierList(0); } 655 656 override void toD(CodeWriter writer) 657 { 658 writer(getMember(0)); 659 } 660 661 override bool convertableFrom(Type from, ConversionFlags flags) 662 { 663 return calcType().convertableFrom(from, flags); 664 } 665 666 override Type calcType() 667 { 668 if(type) 669 return type; 670 671 auto idlist = getIdentifierList(); 672 type = idlist.calcType(); 673 return type; 674 } 675 676 override Value interpret(Context sc) 677 { 678 // might also be called inside an alias, actually resolving to a value 679 return new TypeValue(this); 680 } 681 } 682 683 684 //Typeof: 685 // [Expression/Type_opt IdentifierList_opt] 686 class Typeof : Type 687 { 688 mixin ForwardCtor!(); 689 690 override bool propertyNeedsParens() const { return false; } 691 692 bool isReturn() { return id == TOK_return; } 693 694 IdentifierList getIdentifierList() { return getMember!IdentifierList(1); } 695 696 override void toD(CodeWriter writer) 697 { 698 if(isReturn()) 699 writer("typeof(return)"); 700 else 701 writer("typeof(", getMember(0), ")"); 702 if(auto identifierList = getIdentifierList()) 703 writer(".", identifierList); 704 } 705 706 override Value interpret(Context sc) 707 { 708 if(isReturn()) 709 { 710 return semanticErrorValue("typeof(return) not implemented"); 711 } 712 Node n = getMember(0); 713 Type t = n.calcType(); 714 return new TypeValue(t); 715 } 716 } 717 718 // base class for types that have an indirection, i.e. pointer and arrays 719 class TypeIndirection : Type 720 { 721 mixin ForwardCtor!(); 722 723 override TypeIndirection clone() 724 { 725 auto n = static_cast!TypeIndirection(super.clone()); 726 if(members.length == 0) 727 n.setNextType(_next); 728 return n; 729 } 730 731 Type _next; 732 733 override bool propertyNeedsParens() const { return true; } 734 735 //Type getType() { return getMember!Type(0); } 736 737 void setNextType(Type t) 738 { 739 _next = t.calcType(); 740 } 741 742 Type getNextType() 743 { 744 if(_next) 745 return _next; 746 _next = getMember!Type(0).calcType(); 747 return _next; 748 } 749 750 override bool convertableFrom(Type from, ConversionFlags flags) 751 { 752 if(super.convertableFrom(from, flags)) 753 return true; 754 755 Type nextThis = getNextType(); 756 if (typeid(this) != typeid(from)) 757 return false; 758 auto ifrom = static_cast!TypeIndirection(from); 759 _assert(ifrom !is null); 760 761 // could allow A* -> const(B*) if class A derives from B 762 // even better -> head_const(B*) 763 return nextThis.convertableFrom(ifrom.getNextType(), flags & ~ConversionFlags.kIndirectionClear); 764 } 765 766 override Type opIndex(int v) 767 { 768 //_assert(false); 769 return getNextType(); 770 } 771 772 override Type opSlice(int b, int e) 773 { 774 _assert(false); 775 return this; 776 } 777 778 } 779 780 //TypePointer: 781 // [Type] 782 class TypePointer : TypeIndirection 783 { 784 mixin ForwardCtor!(); 785 786 override void typeSemantic(Scope sc) 787 { 788 auto type = getNextType(); 789 //type.semantic(sc); 790 auto typeinfo_ptr = new TypeInfo_Pointer; 791 typeinfo_ptr.m_next = type.typeinfo; 792 typeinfo = typeinfo_ptr; 793 } 794 795 override Value createValue(Context ctx, Value initValue) 796 { 797 auto v = PointerValue._create(this, null); 798 if(initValue) 799 v.opBin(ctx, TOK_assign, initValue); 800 return v; 801 } 802 803 bool convertableTo(TypePointer t) 804 { 805 auto type = getNextType(); 806 auto otype = t.getNextType(); 807 return otype.compare(type); 808 } 809 810 override void toD(CodeWriter writer) 811 { 812 if(auto m = getMember(0)) 813 writer(m, "*"); 814 else if(_next) 815 writer(_next, "*"); 816 else 817 writer("_missingtype_*"); 818 } 819 } 820 821 class LengthProperty : Symbol 822 { 823 Type type; 824 825 override Type calcType() 826 { 827 if(!type) 828 type = createBasicType(TOK_uint); 829 return type; 830 } 831 832 override Value interpret(Context sc) 833 { 834 if(auto ac = cast(AggrContext)sc) 835 { 836 if(auto dav = cast(DynArrayValue) ac.instance) 837 return new SetLengthValue(dav); 838 return semanticErrorValue("cannot calulate length of ", ac.instance); 839 } 840 return semanticErrorValue("no context to length of ", sc); 841 } 842 843 override void toD(CodeWriter writer) 844 { 845 writer("length"); 846 } 847 } 848 849 class PtrProperty : Symbol 850 { 851 Type type; 852 853 this(Type t) 854 { 855 auto tp = new TypePointer(TOK_mul, t.span); 856 tp.setNextType(t); 857 type = tp; 858 } 859 860 override Type calcType() 861 { 862 return type; 863 } 864 865 override Value interpret(Context sc) 866 { 867 if(auto ac = cast(AggrContext)sc) 868 { 869 if(auto dav = cast(DynArrayValue) ac.instance) 870 { 871 if(dav.first) 872 return dav.first.opRefPointer(); 873 else 874 return type.createValue(sc, null); 875 } 876 return semanticErrorValue("cannot calculate ptr of ", ac.instance); 877 } 878 return semanticErrorValue("no context to ptr of ", sc); 879 } 880 881 override void toD(CodeWriter writer) 882 { 883 writer("ptr"); 884 } 885 } 886 887 //TypeDynamicArray: 888 // [Type] 889 class TypeDynamicArray : TypeIndirection 890 { 891 mixin ForwardCtor!(); 892 893 static Scope cachedScope; 894 895 override void typeSemantic(Scope sc) 896 { 897 auto type = getNextType(); 898 //type.semantic(sc); 899 auto typeinfo_arr = new TypeInfo_Array; 900 typeinfo_arr.value = type.typeinfo; 901 typeinfo = typeinfo_arr; 902 } 903 904 override bool convertableFrom(Type from, ConversionFlags flags) 905 { 906 if(super.convertableFrom(from, flags)) 907 return true; 908 909 if (typeid(from) is typeid(TypeStaticArray)) 910 { 911 Type nextThis = getNextType(); 912 auto arrfrom = static_cast!TypeStaticArray(from); 913 assert(arrfrom); 914 915 // should allow A[] -> const(B[]) if class A derives from B 916 // even better -> head_const(B[]) 917 if(nextThis.convertableFrom(arrfrom.getNextType(), flags & ~ConversionFlags.kIndirectionClear)) 918 return true; 919 } 920 return false; 921 } 922 923 override void toD(CodeWriter writer) 924 { 925 writer(getMember(0), "[]"); 926 } 927 928 override Scope getScope() 929 { 930 if(!scop) 931 { 932 Scope sc = parent ? parent.getScope() : null; 933 scop = sc ? sc.pushClone() : new Scope; 934 scop.addSymbol("length", new LengthProperty); 935 scop.addSymbol("ptr", new PtrProperty(getNextType())); 936 } 937 return scop; 938 } 939 940 override Value createValue(Context ctx, Value initValue) 941 { 942 version(none) 943 if(auto mtype = cast(ModifiedType) getType()) 944 if(mtype.id == TOK_immutable) 945 if(auto btype = cast(BasicType) mtype.getType()) 946 if(btype.id == TOK_char) 947 return createInitValue!StringValue(ctx, initValue); 948 949 auto val = new DynArrayValue(this); 950 if(initValue) 951 val.opBin(ctx, TOK_assign, initValue); 952 return val; 953 } 954 955 override Type opSlice(int b, int e) 956 { 957 return this; 958 /+ 959 auto da = new TypeStaticArray; 960 da.setNextType(getNextType()); //addMember(nextType().clone()); 961 return da; 962 +/ 963 } 964 965 /+ Value deepCopy(Context sc, Value initValue) 966 { 967 auto val = new DynArrayValue(this); 968 if(int dim = initValue ? initValue.interpretProperty(sc, "length").toInt() : 0) 969 { 970 auto type = getType(); 971 Value[] values; 972 values.length = dim; 973 IntValue idxval = new IntValue; 974 for(int i = 0; i < dim; i++) 975 { 976 *(idxval.pval) = i; 977 Value v = initValue ? initValue.opIndex(idxval) : null; 978 values[i] = type.createValue(sc, v); 979 } 980 val.values = values; 981 } 982 return val; 983 } 984 +/ 985 } 986 987 //SuffixDynamicArray: 988 // [] 989 class SuffixDynamicArray : Node 990 { 991 mixin ForwardCtor!(); 992 993 override void toD(CodeWriter writer) 994 { 995 writer("[]"); 996 } 997 } 998 999 // can be both static or assoc, which one is correct cannot be decided by the parser in general 1000 //SuffixArray: 1001 // [Expression|Type] 1002 class SuffixArray : Node 1003 { 1004 mixin ForwardCtor!(); 1005 1006 Expression getDimension() { return getMember!Expression(0); } 1007 Type getKeyType() { return getMember!Type(0); } 1008 1009 override void toD(CodeWriter writer) 1010 { 1011 writer("[", getMember(0), "]"); 1012 } 1013 } 1014 1015 //TypeStaticArray: 1016 // [Type Expression] 1017 class TypeStaticArray : TypeIndirection 1018 { 1019 mixin ForwardCtor!(); 1020 1021 override TypeStaticArray clone() 1022 { 1023 auto n = static_cast!TypeStaticArray(super.clone()); 1024 n.dimExpr = dimExpr; 1025 return n; 1026 } 1027 1028 Expression getDimension() { return dimExpr ? dimExpr : getMember!Expression(1); } 1029 1030 Expression dimExpr; 1031 1032 override void typeSemantic(Scope sc) 1033 { 1034 auto type = getNextType(); 1035 //type.semantic(sc); 1036 auto typeinfo_arr = new TypeInfo_StaticArray; 1037 typeinfo_arr.value = type.typeinfo; 1038 1039 Context ctx = new Context(nullContext); 1040 ctx.scop = sc; 1041 typeinfo_arr.len = getDimension().interpret(ctx).toInt(); 1042 typeinfo = typeinfo_arr; 1043 } 1044 1045 override Scope getScope() 1046 { 1047 if(!scop) 1048 { 1049 enterScope(parent.getScope()); 1050 Context ctx = new Context(nullContext); 1051 ctx.scop = scop; 1052 size_t len = getDimension().interpret(ctx).toInt(); 1053 newBuiltinProperty(scop, "length", len); 1054 } 1055 return scop; 1056 } 1057 1058 /+ 1059 override Scope getScope() 1060 { 1061 if(!scop) 1062 { 1063 scop = createTypeScope(); 1064 //scop.addSymbol("length", new BuiltinProperty!uint(BasicType.getType(TOK_uint), 0)); 1065 scop.parent = super.getScope(); 1066 } 1067 return scop; 1068 } 1069 +/ 1070 1071 override void toD(CodeWriter writer) 1072 { 1073 writer(getMember(0), "[", getMember(1), "]"); 1074 } 1075 1076 override Value createValue(Context ctx, Value initValue) 1077 { 1078 int dim = getDimension().interpret(ctx).toInt(); 1079 auto val = new StaticArrayValue(this); 1080 val.setLength(ctx, dim); 1081 if(initValue) 1082 val.opBin(ctx, TOK_assign, initValue); 1083 1084 return val; 1085 } 1086 1087 override Type opSlice(int b, int e) 1088 { 1089 auto da = new TypeDynamicArray; 1090 da.setNextType(getNextType()); //addMember(nextType().clone()); 1091 return da; 1092 //return this; 1093 } 1094 1095 } 1096 1097 //TypeAssocArray: 1098 // [Type Type] 1099 class TypeAssocArray : TypeIndirection 1100 { 1101 mixin ForwardCtor!(); 1102 1103 override TypeAssocArray clone() 1104 { 1105 auto n = static_cast!TypeAssocArray(super.clone()); 1106 n.keyType = keyType; 1107 return n; 1108 } 1109 1110 Type getKeyType() { return keyType ? keyType : getMember!Type(1); } 1111 1112 Type keyType; 1113 1114 override void typeSemantic(Scope sc) 1115 { 1116 auto vtype = getNextType(); 1117 //vtype.semantic(sc); 1118 auto ktype = getKeyType(); 1119 //ktype.semantic(sc); 1120 1121 auto typeinfo_arr = new TypeInfo_AssociativeArray; 1122 typeinfo_arr.value = vtype.typeinfo; 1123 typeinfo_arr.key = ktype.typeinfo; 1124 typeinfo = typeinfo_arr; 1125 } 1126 1127 override bool convertableFrom(Type from, ConversionFlags flags) 1128 { 1129 if(super.convertableFrom(from, flags)) 1130 { 1131 auto aafrom = static_cast!TypeAssocArray(from); // verified in super.convertableFrom 1132 if(getKeyType().convertableFrom(aafrom.getKeyType(), flags & ~ConversionFlags.kIndirectionClear)) 1133 return true; 1134 } 1135 return false; 1136 } 1137 1138 override void toD(CodeWriter writer) 1139 { 1140 writer(getMember(0), "[", getMember(1), "]"); 1141 } 1142 } 1143 1144 //TypeArraySlice: 1145 // [Type Expression Expression] 1146 class TypeArraySlice : Type 1147 { 1148 mixin ForwardCtor!(); 1149 1150 override bool propertyNeedsParens() const { return true; } 1151 1152 Type getType() { return getMember!Type(0); } 1153 Expression getLower() { return getMember!Expression(1); } 1154 Expression getUpper() { return getMember!Expression(2); } 1155 1156 override void typeSemantic(Scope sc) 1157 { 1158 auto rtype = getType(); 1159 if(auto tpl = cast(TypeInfo_Tuple) rtype.typeinfo) 1160 { 1161 Context ctx = new Context(nullContext); 1162 ctx.scop = sc; 1163 int lo = getLower().interpret(ctx).toInt(); 1164 int up = getUpper().interpret(ctx).toInt(); 1165 if(lo > up || lo < 0 || up > tpl.elements.length) 1166 { 1167 semanticError("tuple slice out of bounds"); 1168 typeinfo = tpl; 1169 } 1170 else 1171 { 1172 auto ntpl = new TypeInfo_Tuple; 1173 ntpl.elements = tpl.elements[lo..up]; 1174 typeinfo = ntpl; 1175 } 1176 } 1177 else 1178 { 1179 semanticError("type is not a tuple"); 1180 typeinfo = rtype.typeinfo; 1181 } 1182 } 1183 1184 override void toD(CodeWriter writer) 1185 { 1186 writer(getMember(0), "[", getLower(), " .. ", getUpper(), "]"); 1187 } 1188 } 1189 1190 //TypeFunction: 1191 // [Type ParameterList] 1192 class TypeFunction : Type 1193 { 1194 mixin ForwardCtor!(); 1195 1196 override TypeFunction clone() 1197 { 1198 auto n = static_cast!TypeFunction(super.clone()); 1199 n.paramList = paramList; 1200 n.returnType = returnType; 1201 n.funcDecl = funcDecl; 1202 return n; 1203 } 1204 1205 override bool propertyNeedsParens() const { return true; } 1206 1207 Type getReturnType() { return returnType ? returnType : getMember!Type(0); } // overwritten in TypeFunctionLiteral/TypeDelegateLiteral 1208 ParameterList getParameters() { return paramList ? paramList : getMember!ParameterList(1); } 1209 1210 ParameterList paramList; 1211 Type returnType; 1212 1213 Declarator funcDecl; // the actual function pointer 1214 1215 override void typeSemantic(Scope sc) 1216 { 1217 auto ti_fn = new TypeInfo_FunctionX; 1218 1219 auto rtype = getReturnType(); 1220 rtype.semantic(sc); 1221 auto params = getParameters(); 1222 params.semantic(sc); 1223 1224 ti_fn.next = rtype.typeinfo; 1225 ti_fn.parameters = new TypeInfo_Tuple; 1226 for(size_t p = 0; p < params.members.length; p++) 1227 ti_fn.parameters.elements ~= params.getParameter(p).getParameterDeclarator().getType().typeinfo; 1228 ti_fn.attributes = combineAttributes(attr, params.attr); 1229 typeinfo = ti_fn; 1230 } 1231 1232 override Value createValue(Context ctx, Value initValue) 1233 { 1234 auto fv = new FunctionValue; 1235 if(FunctionValue ifv = cast(FunctionValue) initValue) 1236 { 1237 // TODO: verfy types 1238 fv.functype = ifv.functype; 1239 } 1240 else if(initValue) 1241 return semanticErrorValue("cannot assign ", initValue, " to ", this); 1242 else 1243 fv.functype = this; 1244 return fv; 1245 } 1246 1247 override Type opCall(Type args) 1248 { 1249 return getReturnType().calcType(); 1250 } 1251 1252 override void toD(CodeWriter writer) 1253 { 1254 writer(getReturnType(), " function", getParameters()); 1255 writer.writeAttributesAndAnnotations(attr, annotation, true); 1256 } 1257 } 1258 1259 //TypeDelegate: 1260 // [Type ParameterList] 1261 class TypeDelegate : TypeFunction 1262 { 1263 mixin ForwardCtor!(); 1264 1265 override void typeSemantic(Scope sc) 1266 { 1267 auto ti_dg = new TypeInfo_DelegateX; 1268 1269 auto rtype = getReturnType(); 1270 rtype.semantic(sc); 1271 auto params = getParameters(); 1272 params.semantic(sc); 1273 1274 ti_dg.next = rtype.typeinfo; 1275 ti_dg.parameters = new TypeInfo_Tuple; 1276 for(size_t p = 0; p < params.members.length; p++) 1277 ti_dg.parameters.elements ~= params.getParameter(p).getParameterDeclarator().getType().typeinfo; 1278 ti_dg.attributes = combineAttributes(attr, params.attr); 1279 // no context information when defining the type, only with an instance 1280 typeinfo = ti_dg; 1281 } 1282 1283 override Value createValue(Context ctx, Value initValue) 1284 { 1285 auto fv = new DelegateValue; 1286 if(DelegateValue ifv = cast(DelegateValue) initValue) 1287 { 1288 // TODO: verfy types 1289 fv.functype = ifv.functype; 1290 fv.context = ifv.context; 1291 } 1292 else if(initValue) 1293 return semanticErrorValue("cannot assign ", initValue, " to ", this); 1294 else 1295 { 1296 fv.functype = this; 1297 fv.context = ctx; 1298 } 1299 return fv; 1300 } 1301 1302 override void toD(CodeWriter writer) 1303 { 1304 writer(getReturnType(), " delegate", getParameters()); 1305 writer.writeAttributesAndAnnotations(attr, annotation, true); 1306 } 1307 } 1308 1309 class TypeInfo_FunctionX : TypeInfo_Function 1310 { 1311 TypeInfo_Tuple parameters; 1312 int attributes; 1313 } 1314 1315 class TypeInfo_DelegateX : TypeInfo_Delegate 1316 { 1317 TypeInfo_Tuple parameters; 1318 int attributes; 1319 TypeInfo context; 1320 } 1321 1322 class TypeString : TypeDynamicArray 1323 { 1324 mixin ForwardCtor!(); 1325 1326 version(none) 1327 override Value createValue(Context ctx, Value initValue) 1328 { 1329 return createInitValue!StringValue(ctx, initValue); 1330 } 1331 1332 } 1333 1334 TypeDynamicArray createTypeString(C)() 1335 { 1336 TextSpan span; 1337 return createTypeString!C(span); 1338 } 1339 1340 TypeDynamicArray createTypeString(C)(ref const(TextSpan) span) 1341 { 1342 auto arr = new TypeString(span); 1343 1344 BasicType ct = new BasicType(BasicType2Token!C(), span); 1345 ModifiedType mt = new ModifiedType(TOK_immutable, span); 1346 mt.addMember(ct); 1347 arr.addMember(mt); 1348 return arr; 1349 } 1350 1351 TypeDynamicArray getTypeString(C)() 1352 { 1353 static TypeDynamicArray cachedTypedString; 1354 if(!cachedTypedString) 1355 { 1356 TextSpan span; 1357 cachedTypedString = createTypeString!C(span); 1358 } 1359 return cachedTypedString; 1360 }