1 /// Author: Aziz Köksal
2 /// License: GPL3
3 /// $(Maturity average)
4 module dil.semantic.Types;
5 
6 import dil.semantic.Symbol,
7        dil.semantic.TypesEnum;
8 import dil.lexer.Identifier,
9        dil.lexer.IdTable,
10        dil.lexer.TokensEnum;
11 import dil.Enums,
12        dil.String;
13 import common;
14 
15 /// The base type for all type structures.
16 abstract class Type/* : Symbol*/
17 {
18   Type next;     /// The next type in the type structure.
19   TYP tid;       /// The ID of the type.
20   Symbol symbol; /// Not null if this type has a symbol.
21   cstring mangled; /// The mangled identifier of the type.
22 
23   this(){}
24 
25   /// Constructs a Type object.
26   /// Params:
27   ///   next = The type's next type.
28   ///   tid = The type's ID.
29   this(Type next, TYP tid)
30   {
31 //     this.sid = SYM.Type;
32 
33     this.next = next;
34     this.tid = tid;
35   }
36 
37   /// Casts the type to Class.
38   Class to(Class)()
39   {
40     static if (Class.stringof == "TypeBasic")
41       assert(this.isBasic());
42     else // [4..$] is there for slicing off "Type" from the class name.
43       assert(this.tid == mixin("TYP." ~ Class.stringof[4..$]));
44     return cast(Class)cast(void*)this;
45   }
46 
47   /// Returns the mangled TypeInfo identifier for this type.
48   /// Params:
49   ///   idtable = Inserts the returned id into this table.
50   final Identifier* mangledTypeInfoIdent(IdTable idtable)
51   {
52     auto m = toMangle();
53     m = "_D" ~ itoa(m.length+9) ~ "TypeInfo_" ~ m ~ "6__initZ";
54     return idtable.lookup(m);
55   }
56 
57   /// Returns the base type if this is an enum or typedef, or itself otherwise.
58   Type baseType()
59   {
60     auto t = this;
61     for (; t.hasBaseType(); t = t.next)
62       assert(t !is null);
63     return t;
64   }
65 
66   /// Returns true if this type has a base type (enum or typedef.)
67   final bool hasBaseType()
68   {
69     return tid == TYP.Enum || tid == TYP.Typedef;
70   }
71 
72   alias opEquals = super.opEquals;
73 
74   /// Returns true if this type equals the other one.
75   bool opEquals(Type other)
76   {
77     if (this.next is null && other.next is null)
78       return this.tid == other.tid;
79     // TODO:
80     return false;
81   }
82 
83   /// Returns a pointer type to this type.
84   TypePointer ptrTo()
85   {
86     return new TypePointer(this);
87   }
88 
89   /// Returns a dynamic array type using this type as its base.
90   TypeDArray arrayOf()
91   {
92     return new TypeDArray(this);
93   }
94 
95   /// Returns an associative array type using this type as its base.
96   /// Params:
97   ///   key = The key type.
98   TypeAArray arrayOf(Type key)
99   {
100     return new TypeAArray(this, key);
101   }
102 
103   /// Returns a static array type using this type as its base.
104   /// Params:
105   ///   size = The number of elements in the array.
106   TypeSArray arrayOf(size_t size)
107   {
108     return new TypeSArray(this, size);
109   }
110 
111   /// Returns the byte size of this type.
112   /// Returns 0 if it could not be determined.
113   /// Params:
114   ///   tti = Contains target-dependent info.
115   size_t sizeOf(TargetTInfo tti = null)
116   {
117     return MITable.getSize(this);
118   }
119 
120   /// Returns the align size of this type.
121   /// Returns 0 if it could not be determined.
122   /// Params:
123   ///   tti = Contains target-dependent info.
124   size_t alignSizeOf(TargetTInfo tti = null)
125   {
126     return MITable.getAlignSize(this);
127   }
128 
129   /// Returns the flags of this type.
130   TypeFlags flagsOf()
131   {
132     return MITable.getFlags(this);
133   }
134 
135   /// Returns true if this type has a boolean value.
136   final bool hasBoolVal()
137   {
138     return flagsOf().isBoolVal();
139   }
140 
141   /// Returns true if this type is initialized with zero(s).
142   final bool isZeroInit()
143   {
144     return flagsOf().isZeroInit();
145   }
146 
147   /// Returns true if this type has a symbol.
148   final bool hasSymbol()
149   {
150     return symbol !is null;
151   }
152 
153   /// Returns the type as a human-readable string.
154   abstract cstring toText();
155 
156   /// Returns true if error type.
157   final bool isError()
158   {
159     return tid == TYP.Error;
160   }
161 
162   /// Returns true if dynamic array type.
163   final bool isDArray()
164   {
165     return tid == TYP.DArray;
166   }
167 
168   /// Returns true if static array type.
169   final bool isSArray()
170   {
171     return tid == TYP.SArray;
172   }
173 
174   /// Returns true if associative array type.
175   final bool isAArray()
176   {
177     return tid == TYP.AArray;
178   }
179 
180   /// Returns true if parameter type.
181   final bool isParameter()
182   {
183     return tid == TYP.Parameter;
184   }
185 
186   /// Returns true if parameters type.
187   final bool isParameters()
188   {
189     return tid == TYP.Parameters;
190   }
191 
192   /// Returns true if enum type.
193   final bool isEnum()
194   {
195     return tid == TYP.Enum;
196   }
197 
198   /// Returns true if struct type.
199   final bool isStruct()
200   {
201     return tid == TYP.Struct;
202   }
203 
204   /// Returns true if class type.
205   final bool isClass()
206   {
207     return tid == TYP.Struct;
208   }
209 
210   /// Returns true if typedef type.
211   final bool isTypedef()
212   {
213     return tid == TYP.Typedef;
214   }
215 
216   /// Returns true if function type.
217   final bool isFunction()
218   {
219     return tid == TYP.Function;
220   }
221 
222   /// Returns true if Delegate type.
223   final bool isDelegate()
224   {
225     return tid == TYP.Delegate;
226   }
227 
228   /// Returns true if pointer type.
229   final bool isPointer()
230   {
231     return tid == TYP.Pointer;
232   }
233 
234   /// Returns true if reference type.
235   final bool isReference()
236   {
237     return tid == TYP.Reference;
238   }
239 
240   /// Returns true if identifier type.
241   final bool isIdentifier()
242   {
243     return tid == TYP.Identifier;
244   }
245 
246   /// Returns true if template instance type.
247   final bool isTInstance()
248   {
249     return tid == TYP.TInstance;
250   }
251 
252   /// Returns true if tuple type.
253   final bool isTuple()
254   {
255     return tid == TYP.Tuple;
256   }
257 
258   /// Returns true if const type. D2.
259   final bool isConst()
260   {
261     return tid == TYP.Const;
262   }
263 
264   /// Returns true if immutable type. D2.
265   final bool isImmutable()
266   {
267     return tid == TYP.Immutable;
268   }
269 
270   /// Returns true if dynamic or static array type.
271   final bool isDorSArray()
272   {
273     return tid == TYP.DArray || tid == TYP.SArray;
274   }
275 
276   /// Returns true if bool type.
277   final bool isBool()
278   {
279     return tid == TYP.Bool;
280   }
281 
282   /// Like isBool(). Also checks base types of typedef/enum.
283   final bool isBaseBool()
284   {
285     if (hasBaseType())
286       return next.isBool(); // Check base type.
287     return isBool();
288   }
289 
290   /// Returns true if the type is signed.
291   final bool isSigned()
292   {
293     return MITable.getFlags(this).isSigned();
294   }
295 
296   /// Returns true if the type is unsigned.
297   final bool isUnsigned()
298   {
299     return MITable.getFlags(this).isUnsigned();
300   }
301 
302   /// Returns true if this is a basic type.
303   final bool isBasic()
304   {
305     return MITable.getFlags(this).isBasic();
306   }
307 
308   /// Returns true if this type is an integral number type.
309   final bool isIntegral()
310   {
311     return MITable.getFlags(this).isIntegral();
312   }
313 
314   /// Returns true if this type is a floating point number type.
315   final bool isFloating()
316   {
317     return MITable.getFlags(this).isFloating();
318   }
319 
320   /// Like isFloating(). Also checks base types of typedef/enum.
321   final bool isBaseFloating()
322   {
323     if (tid == TYP.Enum)
324       return false; // Base type of enum can't be floating.
325     if (tid == TYP.Typedef)
326       return next.isBaseFloating();
327     return isFloating();
328   }
329 
330   /// Returns true if this type is a real number type.
331   final bool isReal()
332   {
333     return MITable.getFlags(this).isReal();
334   }
335 
336   /// Like isReal(). Also checks base types of typedef/enum.
337   final bool isBaseReal()
338   {
339     if (tid == TYP.Enum)
340       return false; // Base type of enum can't be real.
341     if (tid == TYP.Typedef)
342       return next.isBaseReal();
343     return isReal();
344   }
345 
346   /// Returns true if this type is an imaginary number type.
347   final bool isImaginary()
348   {
349     return MITable.getFlags(this).isImaginary();
350   }
351 
352   /// Like isImaginary(). Also checks base types of typedef/enum.
353   final bool isBaseImaginary()
354   {
355     if (tid == TYP.Enum)
356       return false; // Base type of enum can't be imaginary.
357     if (tid == TYP.Typedef)
358       return next.isBaseImaginary();
359     return isImaginary();
360   }
361 
362   /// Returns true if this type is a complex number type.
363   final bool isComplex()
364   {
365     return MITable.getFlags(this).isComplex();
366   }
367 
368   /// Like isComplex(). Also checks base types of typedef/enum.
369   final bool isBaseComplex()
370   {
371     if (tid == TYP.Enum)
372       return false; // Base type of enum can't be complex.
373     if (tid == TYP.Typedef)
374       return next.isBaseComplex();
375     return isComplex();
376   }
377 
378   /// Returns true for scalar types.
379   final bool isScalar()
380   {
381     return MITable.getFlags(this).isScalar();
382   }
383 
384   /// Like isScalar(). Also checks base types of typedef/enum.
385   final bool isBaseScalar()
386   {
387     if (tid == TYP.Enum)
388       return true; // Base type of enum can only be scalar.
389     if (tid == TYP.Typedef)
390       return next.isScalar(); // Check base type.
391     return isScalar();
392   }
393 
394   /// Returns the mangle character for this type.
395   final char mangleChar()
396   {
397     return MITable.mangleChar(this);
398   }
399 
400   /// Returns the mangled name of this type.
401   cstring toMangle()
402   {
403     if (mangled.length)
404       return mangled;
405     char[] m;
406     m ~= mangleChar();
407     if (next)
408       m ~= next.toMangle();
409     return m;
410   }
411 }
412 
413 /// The error type.
414 class TypeError : Type
415 {
416   this()
417   {
418     super(null, TYP.Error);
419   }
420 
421 override:
422   cstring toText()
423   {
424     return "{TypeError}";
425   }
426 
427   cstring toMangle()
428   {
429     return "{TypeError}";
430   }
431 }
432 
433 /// All basic types. E.g.: int, char, real etc.
434 class TypeBasic : Type
435 {
436   Identifier* ident; /// Keyword identifier.
437 
438   this(Identifier* ident, TYP typ)
439   {
440     super(null, typ);
441     this.ident = ident;
442   }
443 
444 override:
445   size_t alignSizeOf(TargetTInfo tti)
446   { // TODO:
447     return 0;
448   }
449 
450   cstring toText()
451   {
452     return ident.str;
453   }
454 }
455 
456 /// Dynamic array type.
457 class TypeDArray : Type
458 {
459   this(Type next)
460   {
461     super(next, TYP.DArray);
462   }
463 
464 override:
465   size_t sizeOf(TargetTInfo tti)
466   {
467     return tti.ptrSize * 2;
468   }
469 
470   size_t alignSizeOf(TargetTInfo tti)
471   {
472     return tti.ptrSize;
473   }
474 
475   cstring toText()
476   {
477     return next.toText() ~ "[]";
478   }
479 }
480 
481 /// Associative array type.
482 class TypeAArray : Type
483 {
484   Type keyType;
485   this(Type next, Type keyType)
486   {
487     super(next, TYP.AArray);
488     this.keyType = keyType;
489   }
490 
491 override:
492   size_t sizeOf(TargetTInfo tti)
493   {
494     return tti.ptrSize * 2;
495   }
496 
497   cstring toText()
498   {
499     return next.toText() ~ "[" ~ keyType.toText() ~ "]";
500   }
501 
502   cstring toMangle()
503   {
504     if (mangled.length)
505       return mangled;
506     return mangleChar() ~ keyType.toMangle() ~ next.toMangle();
507   }
508 }
509 
510 /// Static array type.
511 class TypeSArray : Type
512 {
513   size_t dimension;
514   this(Type next, size_t dimension)
515   {
516     super(next, TYP.SArray);
517     this.dimension = dimension;
518   }
519 
520 override:
521   size_t sizeOf(TargetTInfo tti)
522   {
523     return tti.ptrSize * 2;
524   }
525 
526   size_t alignSizeOf(TargetTInfo tti)
527   {
528     return next.alignSizeOf(tti);
529   }
530 
531   TypeFlags flagsOf()
532   { // TODO:
533     auto tf = next.flagsOf();
534     //if (symbol.isZeroInit())
535       //tf |= TypeFlags.ZeroInit;
536     return tf;
537   }
538 
539   cstring toText()
540   {
541     return next.toText() ~ "[" ~ itoa(dimension) ~ "]";
542   }
543 
544   cstring toMangle()
545   {
546     if (mangled.length)
547       return mangled;
548     return mangleChar() ~ itoa(dimension) ~ next.toMangle();
549   }
550 }
551 
552 /// Pointer type.
553 class TypePointer : Type
554 {
555   this(Type next)
556   {
557     super(next, TYP.Pointer);
558   }
559 
560 override:
561   size_t sizeOf(TargetTInfo tti)
562   {
563     return tti.ptrSize;
564   }
565 
566   cstring toText()
567   {
568     return next.toText() ~ "*";
569   }
570 }
571 
572 /// Reference type.
573 class TypeReference : Type
574 {
575   this(Type next)
576   {
577     super(next, TYP.Reference);
578   }
579 
580 override:
581   size_t sizeOf(TargetTInfo tti)
582   {
583     return tti.ptrSize;
584   }
585 
586   cstring toText()
587   { // FIXME: this is probably wrong.
588     return next.toText() ~ "&";
589   }
590 }
591 
592 /// Enum type.
593 class TypeEnum : Type
594 {
595   this(Symbol symbol)
596   {
597     // FIXME: pass int as the base type for the time being.
598     // Use Types.DontKnowYet instead?
599     super(Types.Int32, TYP.Enum);
600     this.symbol = symbol;
601   }
602 
603   /// Setter for the base type.
604   void baseType(Type type)
605   {
606     next = type;
607   }
608 
609 override:
610   size_t sizeOf(TargetTInfo tti)
611   { // TODO:
612     return 0;
613   }
614 
615   size_t alignSizeOf(TargetTInfo tti)
616   {
617     return next.sizeOf(tti);
618   }
619 
620   TypeFlags flagsOf()
621   { // TODO:
622     auto tf = next.flagsOf();
623     //if (symbol.isZeroInit())
624       //tf |= TypeFlags.ZeroInit;
625     return tf;
626   }
627 
628   cstring toText()
629   {
630     return symbol.name.str;
631   }
632 
633   cstring toMangle()
634   {
635     if (mangled.length)
636       return mangled;
637     return mangleChar() ~ symbol.toMangle();
638   }
639 }
640 
641 /// Struct type.
642 class TypeStruct : Type
643 {
644   this(Symbol symbol)
645   {
646     super(null, TYP.Struct);
647     this.symbol = symbol;
648   }
649 
650 override:
651   size_t sizeOf(TargetTInfo tti)
652   { // TODO:
653     return 0;
654   }
655 
656   size_t alignSizeOf(TargetTInfo tti)
657   { // TODO:
658     return 0;
659   }
660 
661   cstring toText()
662   {
663     return symbol.name.str;
664   }
665 
666   cstring toMangle()
667   {
668     if (mangled.length)
669       return mangled;
670     return mangleChar() ~ symbol.toMangle();
671   }
672 }
673 
674 /// Class type.
675 class TypeClass : Type
676 {
677   this(Symbol symbol)
678   {
679     super(null, TYP.Class);
680     this.symbol = symbol;
681   }
682 
683 override:
684   size_t sizeOf(TargetTInfo tti)
685   {
686     return tti.ptrSize;
687   }
688 
689   cstring toText()
690   {
691     return symbol.name.str;
692   }
693 
694   cstring toMangle()
695   {
696     if (mangled.length)
697       return mangled;
698     return mangleChar() ~ symbol.toMangle();
699   }
700 }
701 
702 /// Typedef type.
703 class TypeTypedef : Type
704 {
705   this(Type next)
706   {
707     super(next, TYP.Typedef);
708   }
709 
710 override:
711   size_t sizeOf(TargetTInfo tti)
712   {
713     return next.sizeOf(tti);
714   }
715 
716   size_t alignSizeOf(TargetTInfo tti)
717   {
718     return next.alignSizeOf(tti);
719   }
720 
721   TypeFlags flagsOf()
722   { // TODO:
723     auto tf = next.flagsOf();
724     //if (symbol.isZeroInit())
725       //tf |= TypeFlags.ZeroInit;
726     return tf;
727   }
728 
729   cstring toText()
730   {
731     return next.toText();
732   }
733 
734   cstring toMangle()
735   {
736     if (mangled.length)
737       return mangled;
738     return mangleChar() ~ symbol.toMangle();
739   }
740 }
741 
742 /// Parameter type.
743 class TypeParameter : Type
744 {
745   alias type = next; /// Parameter's type.
746   StorageClass stcs; /// Storage classes.
747   VariadicStyle variadic; /// Variadic style.
748   // TODO: add these?
749   // They have no relevance for mangling,
750   // because they don't affect the function signature,
751   // and they will be null after a Type.merge().
752   // Identifier* name;
753   // Node defValue;
754 
755   this(Type type, StorageClass stcs, VariadicStyle variadic=VariadicStyle.None)
756   {
757     super(type, TYP.Parameter);
758     this.stcs = stcs;
759     this.variadic = variadic;
760   }
761 
762   /// NB: the parameter's name and the optional default value are not printed.
763 override:
764   cstring toText()
765   { // := StorageClasses? ParamType? "..."?
766     char[] s;
767     // TODO: exclude STC.In?
768     foreach (stc; EnumString.all(stcs/+ & ~StorageClass.In+/))
769       s ~= stc ~ " ";
770     if (type)
771       s ~= type.toText();
772     else if (variadic)
773       s ~= "...";
774     assert(s.length, "empty parameter?");
775     return s;
776   }
777 
778   cstring toMangle()
779   { // := StorageClassMangleChar TypeMangle
780     if (mangled.length)
781       return mangled;
782     // 1. Mangle storage class.
783     char[] m;
784     char mc = 0;
785     // TODO: D2 can have more than one stc. What to do?
786     if (stcs & StorageClass.Out)
787       mc = 'J';
788     //else if (stcs & StorageClass.In)
789       //mc = 0;
790     else if (stcs & StorageClass.Ref)
791       mc = 'K';
792     else if (stcs & StorageClass.Lazy)
793       mc = 'L';
794     if (mc)
795       m ~= mc;
796     // 2. Mangle parameter type.
797     if (type)
798       m ~= type.toMangle();
799     else
800       assert(variadic == VariadicStyle.C);
801     return m;
802   }
803 }
804 
805 /// A list of TypeParameter objects.
806 class TypeParameters : Type
807 {
808   TypeParameter[] params; /// The parameters.
809 
810   this(TypeParameter[] params)
811   {
812     super(null, TYP.Parameters);
813     this.params = params;
814   }
815 
816   /// Returns the variadic style of the last parameter.
817   VariadicStyle getVariadic()
818   {
819     return params.length ? params[$-1].variadic : VariadicStyle.None;
820   }
821 
822 override:
823   cstring toText()
824   { // := "(" ParameterList ")"
825     char[] s;
826     s ~= "(";
827     foreach (i, p; params) {
828       if (i) s ~= ", "; // Append comma if more than one param.
829       s ~= p.toText();
830     }
831     s ~= ")";
832     return s;
833   }
834 
835   cstring toMangle()
836   {
837     if (mangled.length)
838       return mangled;
839     char[] m;
840     foreach (p; params)
841       m ~= p.toMangle();
842     return m;
843   }
844 }
845 
846 /// A function type.
847 class TypeFunction : Type
848 {
849   alias retType = next;
850   TypeParameters params; /// The parameter list.
851   StorageClass stcs; /// The storage classes.
852   LinkageType linkage; /// The linkage type.
853   VariadicStyle variadic; /// Variadic style.
854 
855   this(Type retType, TypeParameters params, StorageClass stcs, LinkageType linkage)
856   {
857     super(retType, TYP.Function);
858     this.params = params;
859     this.stcs = stcs;
860     this.linkage = linkage;
861     this.variadic = params.getVariadic();
862   }
863 
864   override cstring toText()
865   { // := ReturnType ParameterList
866     return retType.toText() ~ params.toText();
867   }
868 
869   override cstring toMangle()
870   { // := MangleChar LinkageChar ParamsMangle ReturnChar ReturnTypeMangle
871     if (mangled.length)
872       return mangled;
873     char[] m;
874     char mc = void;
875     version(D2)
876     m ~= modsToMangle();
877     switch (linkage)
878     {
879     case LinkageType.C:       mc = 'U'; break;
880     case LinkageType.D:       mc = 'F'; break;
881     case LinkageType.Cpp:     mc = 'R'; break;
882     case LinkageType.Windows: mc = 'W'; break;
883     case LinkageType.Pascal:  mc = 'V'; break;
884     default: assert(0);
885     }
886     m ~= mc;
887     version(D2)
888     m ~= attrsToMangle();
889     m ~= params.toMangle();
890     mc = cast(char)('Z' - variadic);
891     assert(mc == 'X' || mc == 'Y' || mc == 'Z');
892     m ~= mc; // Marks end of parameter list.
893     m ~= retType.toMangle();
894     return m;
895   }
896 
897   version(D2)
898   {
899   /// Mangles the modifiers of this function.
900   cstring modsToMangle()
901   out(m) { assert(m in ["O"[]:1, "Ox":1, "ONg":1, "x":1, "y":1, "Ng":1]); }
902   body
903   {
904     char[] m;
905     if (stcs & StorageClass.Shared)
906       m ~= "O";
907     if (stcs & StorageClass.Const)
908       m ~= "x";
909     if (stcs & StorageClass.Immutable)
910       m ~= "y";
911     if (stcs & StorageClass.Inout)
912       m ~= "Ng";
913     return m;
914   }
915 
916   /// Mangles the attributes of this function.
917   cstring attrsToMangle()
918   {
919     char[] m;
920     if (stcs & StorageClass.Pure)
921       m ~= "Na";
922     if (stcs & StorageClass.Nothrow)
923       m ~= "Nb";
924     if (stcs & StorageClass.Ref)
925       m ~= "Nc";
926     if (stcs & StorageClass.Property)
927       m ~= "Nd";
928     if (stcs & StorageClass.Trusted)
929       m ~= "Ne";
930     if (stcs & StorageClass.Safe)
931       m ~= "Nf";
932     return m;
933   }
934   } // version(D2)
935 }
936 
937 /// Pointer to function type.
938 class TypeFuncPtr : Type
939 {
940   this(TypeFunction func)
941   {
942     super(func, TYP.FuncPtr);
943   }
944 
945   TypeFunction funcType()
946   {
947     return next.to!(TypeFunction);
948   }
949 
950 override:
951   size_t sizeOf(TargetTInfo tti)
952   {
953     return tti.ptrSize;
954   }
955 
956   cstring toText()
957   {
958     auto f = funcType();
959     return f.retType.toText() ~ " function" ~ f.params.toText();
960   }
961 
962   cstring toMangle()
963   {
964     return mangleChar() ~ next.toMangle();
965   }
966 }
967 
968 /// Delegate type.
969 class TypeDelegate : Type
970 {
971   this(TypeFunction func)
972   {
973     super(func, TYP.Delegate);
974   }
975 
976   TypeFunction funcType()
977   {
978     return next.to!(TypeFunction);
979   }
980 
981 override:
982   size_t sizeOf(TargetTInfo tti)
983   {
984     return tti.ptrSize * 2;
985   }
986 
987   size_t alignSizeOf(TargetTInfo tti)
988   {
989     return tti.ptrSize;
990   }
991 
992   cstring toText()
993   {
994     auto f = funcType();
995     return f.retType.toText() ~ " delegate" ~ f.params.toText();
996   }
997 
998   cstring toMangle()
999   {
1000     return mangleChar() ~ next.toMangle();
1001   }
1002 }
1003 
1004 /// Identifier type.
1005 class TypeIdentifier : Type
1006 {
1007   Identifier* ident;
1008   this(Identifier* ident)
1009   {
1010     super(null, TYP.Identifier);
1011   }
1012 
1013 override:
1014   size_t sizeOf(TargetTInfo tti)
1015   { // TODO:
1016     return 0;
1017   }
1018 
1019   cstring toText()
1020   {
1021     return ident.str;
1022   }
1023 
1024   cstring toMangle()
1025   { // := MangleChar IDLength ID
1026     if (mangled.length)
1027       return mangled;
1028     auto id = ident.str;
1029     return mangleChar() ~ itoa(id.length) ~ id;
1030   }
1031 }
1032 
1033 /// Template instantiation type.
1034 class TypeTemplInstance : Type
1035 {
1036   this()
1037   {
1038     super(null, TYP.TInstance);
1039   }
1040 
1041 override:
1042   size_t sizeOf(TargetTInfo tti)
1043   { // TODO:
1044     return 0;
1045   }
1046 
1047   cstring toText()
1048   { // TODO:
1049     return "tpl!()";
1050   }
1051 }
1052 
1053 /// Template tuple type.
1054 class TypeTuple : Type
1055 {
1056   Type[] types; /// The types inside this tuple.
1057 
1058   this(Type[] types)
1059   {
1060     super(null, TYP.Tuple);
1061     this.types = types;
1062   }
1063 
1064 override:
1065   size_t sizeOf(TargetTInfo tti)
1066   { // TODO:
1067     return 0;
1068   }
1069 
1070   cstring toText()
1071   { // := "(" TypeList ")"
1072     char[] s;
1073     s ~= "(";
1074     foreach (i, t; types) {
1075       if (i) s ~= ", "; // Append comma if more than one type.
1076       s ~= t.toText();
1077     }
1078     s ~= ")";
1079     return s;
1080   }
1081 
1082   cstring toMangle()
1083   { // := MangleChar TypesMangleLength TypesMangle
1084     if (mangled.length)
1085       return mangled;
1086     char[] tm;
1087     foreach (t; types)
1088       tm ~= t.toMangle();
1089     return mangleChar() ~ itoa(tm.length) ~ tm;
1090   }
1091 }
1092 
1093 /// Constant type. D2.0
1094 class TypeConst : Type
1095 {
1096   this(Type next)
1097   {
1098     super(next, TYP.Const);
1099   }
1100 
1101 override:
1102   size_t sizeOf(TargetTInfo tti)
1103   {
1104     return next.sizeOf(tti);
1105   }
1106 
1107   cstring toText()
1108   {
1109     return "const(" ~ next.toText() ~ ")";
1110   }
1111 }
1112 
1113 /// Immutable type. D2.0
1114 class TypeImmutable : Type
1115 {
1116   this(Type next)
1117   {
1118     super(next, TYP.Immutable);
1119   }
1120 
1121 override:
1122   size_t sizeOf(TargetTInfo tti)
1123   {
1124     return next.sizeOf(tti);
1125   }
1126 
1127   cstring toText()
1128   {
1129     return "immutable(" ~ next.toText() ~ ")";
1130   }
1131 }
1132 
1133 /// Maps mangled type identifiers to Type objects.
1134 class TypeTable
1135 {
1136   Type[hash_t] table; /// The table data structure.
1137 
1138   /// Looks up a type by its mangled id.
1139   /// Returns: the symbol if there, otherwise null.
1140   Type lookup(cstring mangled)
1141   {
1142     assert(mangled.length);
1143     return lookup(hashOf(mangled));
1144   }
1145 
1146   /// Looks up a type by the hash of its mangled id.
1147   Type lookup(hash_t hash)
1148   {
1149     auto ptype = hash in table;
1150     return ptype ? *ptype : null;
1151   }
1152 
1153   /// Inserts a type into the table.
1154   void insert(Type type)
1155   {
1156     assert(type.mangled.length);
1157     insert(type, hashOf(type.mangled));
1158   }
1159 
1160   /// Inserts a type into the table by its hash.
1161   void insert(Type type, hash_t hash)
1162   {
1163     assert(type.mangled.length && hash == hashOf(type.mangled));
1164     table[hash] = type;
1165   }
1166 
1167   /// Returns the unique version of a type
1168   /// by looking up its mangled name.
1169   /// The subtypes in the type chain are visited as well.
1170   /// The type is inserted into the table if not present.
1171   Type unique(Type t)
1172   {
1173     if (t.next) // Follow the type chain.
1174       t.next = unique(t.next);
1175     return unique2(t);
1176   }
1177 
1178   /// Same as unique(Type) but doesn't follow the type chain.
1179   Type unique2(Type t)
1180   { // Get the mangled string and look it up.
1181     if (!t.mangled.length)
1182       t.mangled = t.toMangle();
1183     auto m_hash = hashOf(t.mangled); // Only calculate once.
1184     if (auto t_intable = lookup(m_hash))
1185       t = t_intable; // Found.
1186     else // Insert new type.
1187       insert(t, m_hash);
1188     return t;
1189   }
1190 
1191   // TODO: change bool[string] to a different structure if necessary.
1192   /// Initializes the table and
1193   /// takes the target machine's properties into account.
1194   void init(bool[cstring] args)
1195   {
1196     synchronized Types.init();
1197 
1198     if("is64" in args) // Generate code for 64bit?
1199     {
1200       Size_t = Types.UInt64;
1201       Ptrdiff_t = Types.Int64;
1202     }
1203     else
1204     {
1205       Size_t = Types.UInt32;
1206       Ptrdiff_t = Types.Int32;
1207     }
1208     PtrSize = Ptrdiff_t.sizeOf();
1209 
1210     tti = new TargetTInfo;
1211     tti.ptrSize = PtrSize;
1212     tti.is64 = !!("is64" in args);
1213   }
1214 
1215   TargetTInfo tti; /// An instance used to calculate type sizes.
1216 
1217   TypeBasic Size_t; /// The size type.
1218   TypeBasic Ptrdiff_t; /// The pointer difference type.
1219 
1220   size_t PtrSize; /// The size of a pointer (dependent on the architecture.)
1221 
1222   /// Returns the byte size of t.
1223   size_t sizeOf(Type t)
1224   {
1225     return t.sizeOf(tti);
1226   }
1227 
1228   /// Returns the align size of t.
1229   size_t alignOf(Type t)
1230   {
1231     return t.alignSizeOf(tti);
1232   }
1233 }
1234 
1235 /// Represents a value related to a Type.
1236 union Value
1237 {
1238   void*  pvoid;
1239   bool   bool_;
1240   dchar  dchar_;
1241   long   long_;
1242   ulong  ulong_;
1243   int    int_;
1244   uint   uint_;
1245   float  float_;
1246   double double_;
1247   real   real_;
1248   creal  creal_;
1249 }
1250 
1251 /// A list of flags for types.
1252 struct TypeFlags
1253 {
1254   /// The actual flags.
1255   immutable enum
1256   {
1257     None      = 0,      /// No flags are set.
1258     ZeroInit  = 1 << 0, /// All bytes of the type can be initialized to 0.
1259     Signed    = 1 << 1, /// Signed type.
1260     Unsigned  = 1 << 2, /// Unsigned type.
1261     Integral  = 1 << 3, /// Integral type.
1262     Floating  = 1 << 4, /// Floating point type.
1263     Real      = 1 << 5, /// Real part of a complex number.
1264     Imaginary = 1 << 6, /// Imaginary part of a complex number.
1265     Complex   = 1 << 7, /// Complex number type.
1266     Pointer   = 1 << 8, /// Pointer or function pointer type.
1267     BoolVal   = 1 << 9, /// Non-scalar type can be in a boolean expression.
1268     Basic     = Integral | Floating, /// Basic type.
1269     Scalar    = Basic | Pointer, /// Scalar type.
1270   }
1271   alias Flags = typeof(None); /// Alias to enum member.
1272 
1273   Flags flags; /// Holds a set of flags.
1274 
1275   /// Returns true if any bit from fs is set in flags.
1276   bool has(Flags fs){ return (flags & fs) != 0; }
1277   /// Returns true if all bits from fs are set in flags.
1278   bool hasAll(Flags fs){ return (flags & fs) == fs; }
1279   /// Returns true if zero init.
1280   bool isZeroInit() { return has(ZeroInit); }
1281   /// Returns true if signed.
1282   bool isSigned() { return has(Signed); }
1283   /// Returns true if unsigned.
1284   bool isUnsigned() { return has(Unsigned); }
1285   /// Returns true if integral.
1286   bool isIntegral() { return has(Integral); }
1287   /// Returns true if floating.
1288   bool isFloating() { return has(Floating); }
1289   /// Returns true if real.
1290   bool isReal() { return has(Real); }
1291   /// Returns true if imaginary.
1292   bool isImaginary() { return has(Imaginary); }
1293   /// Returns true if complex.
1294   bool isComplex() { return has(Complex); }
1295   /// Returns true if pointer.
1296   bool isPointer() { return has(Pointer); }
1297   /// Returns true if boolean value.
1298   bool isBoolVal() { return has(BoolVal | Scalar); }
1299   /// Returns true if basic.
1300   bool isBasic() { return has(Basic); }
1301   /// Returns true if scalar.
1302   bool isScalar() { return has(Scalar); }
1303 
1304   TypeFlags opOrAssign(TypeFlags tf)
1305   {
1306     flags |= tf.flags;
1307     return this;
1308   }
1309 
1310   TypeFlags opOr(TypeFlags tf)
1311   {
1312     return this |= tf;
1313   }
1314 
1315   TypeFlags opAndAssign(TypeFlags tf)
1316   {
1317     flags &= tf.flags;
1318     return this;
1319   }
1320 
1321   TypeFlags opAnd(TypeFlags tf)
1322   {
1323     return this &= tf;
1324   }
1325 }
1326 
1327 /// Target information for types.
1328 class TargetTInfo
1329 {
1330   size_t ptrSize; /// The size of a pointer.
1331   bool is64; /// Is it a 64bit CPU?
1332   bool isLE; /// Is it little-endian or big-endian?
1333 }
1334 
1335 /// Information related to a Type.
1336 struct TypeMetaInfo
1337 {
1338   char mangle; /// Mangle character of the type.
1339   ushort size; /// Byte size of the type.
1340   ushort alignsize; /// Align size of the type.
1341   const Value* defaultInit; /// Default initialization value.
1342   TypeFlags.Flags flags; /// The flags of the type.
1343 }
1344 
1345 /// Namespace for the meta info table.
1346 struct MITable
1347 {
1348 static:
1349   const ushort SIZE_NOT_AVAILABLE = 0; /// Size not available.
1350   const ushort ALIGN_NOT_AVAILABLE = 0; /// Align not available.
1351   const Value VZERO   = {int_:0}; /// Value 0.
1352   const Value VNULL   = {pvoid:null}; /// Value null.
1353   const Value V0xFF   = {dchar_:0xFF}; /// Value 0xFF.
1354   const Value V0xFFFF = {dchar_:0xFFFF}; /// Value 0xFFFF.
1355   const Value VFALSE  = {bool_:false}; /// Value false.
1356   const Value VNAN    = {float_:float.nan}; /// Value NAN.
1357   const Value VCNAN   = {creal_:creal.nan}; /// Value complex NAN.
1358   private
1359   {
1360   alias SNA = SIZE_NOT_AVAILABLE;
1361   alias ANA = ALIGN_NOT_AVAILABLE;
1362   const ushort PS = 0/+1?+/; // Used for documentation purposes below.
1363   alias TF = TypeFlags;    /// Shortcuts.
1364   const Z = TF.ZeroInit;
1365   const U = TF.Unsigned;;   /// ditto
1366   const S = TF.Signed;;     /// ditto
1367   const I = TF.Integral;;   /// ditto
1368   const F = TF.Floating;;   /// ditto
1369   const Re = TF.Real;;      /// ditto
1370   const Im = TF.Imaginary;; /// ditto
1371   const Cx = TF.Complex;;   /// ditto
1372   const P = TF.Pointer;;    /// ditto
1373   const BV = TF.BoolVal;;   /// ditto
1374   }
1375   /// The meta info table.
1376   private const TypeMetaInfo table[] = [
1377     {'?', SNA, ANA}, // Error
1378 
1379     {'a', 1, ANA, &V0xFF, I|U},    // Char
1380     {'u', 2, ANA, &V0xFFFF, I|U},  // WChar
1381     {'w', 4, ANA, &V0xFFFF, I|U},  // DChar
1382     {'b', 1, ANA, &VFALSE, I|U|Z}, // Bool
1383     {'g', 1, ANA, &VZERO, I|S|Z},  // Int8
1384     {'h', 1, ANA, &VZERO, I|U|Z},  // UInt8
1385     {'s', 2, ANA, &VZERO, I|S|Z},  // Int16
1386     {'t', 2, ANA, &VZERO, I|U|Z},  // UInt16
1387     {'i', 4, ANA, &VZERO, I|S|Z},  // Int32
1388     {'k', 4, ANA, &VZERO, I|U|Z},  // UInt32
1389     {'l', 8, ANA, &VZERO, I|S|Z},  // Int64
1390     {'m', 8, ANA, &VZERO, I|U|Z},  // UInt64
1391     {'?', 16, ANA, &VZERO, I|S|Z}, // Int128
1392     {'?', 16, ANA, &VZERO, I|U|Z}, // UInt128
1393     {'f', 4, ANA, &VNAN, F|Re},    // Float32
1394     {'d', 8, ANA, &VNAN, F|Re},    // Float64
1395     {'e', 10, ANA, &VNAN, F|Re},   // Float80
1396     {'o', 4, ANA, &VNAN, F|Im},    // IFloat32
1397     {'p', 8, ANA, &VNAN, F|Im},    // IFloat64
1398     {'j', 10, ANA, &VNAN, F|Im},   // IFloat80
1399     {'q', 8, ANA, &VCNAN, F|Cx},   // CFloat32
1400     {'r', 16, ANA, &VCNAN, F|Cx},  // CFloat64
1401     {'c', 20, ANA, &VCNAN, F|Cx},  // CFloat80
1402     {'v', 1, 1},                   // Void
1403 
1404     {'n', SNA, ANA}, // None
1405 
1406     {'?', SNA, ANA}, // Parameter
1407     {'?', SNA, ANA}, // Parameters
1408 
1409     {'A', PS*2, ANA, &VNULL, Z|BV}, // Dynamic array
1410     {'G', PS*2, ANA}, // Static array
1411     {'H', PS*2, ANA, &VNULL, Z|BV}, // Associative array
1412 
1413     {'E', SNA, ANA}, // Enum
1414     {'S', SNA, ANA}, // Struct
1415     {'C', PS, ANA, &VNULL, Z|BV}, // Class
1416     {'T', SNA, ANA}, // Typedef
1417     {'F', SNA, ANA}, // Function
1418     {'P', PS, ANA, &VNULL, Z|BV|P}, // FuncPtr
1419     {'D', PS*2, ANA, &VNULL, Z|BV}, // Delegate
1420     {'P', PS, ANA, &VNULL, Z|BV|P}, // Pointer
1421     {'R', PS, ANA, &VNULL, Z}, // Reference
1422     {'I', SNA, ANA}, // Identifier
1423     {'?', SNA, ANA}, // Template instance
1424     {'B', SNA, ANA}, // Tuple
1425     {'x', SNA, ANA}, // Const, D2
1426     {'y', SNA, ANA}, // Immutable, D2
1427   ];
1428   static assert(table.length == TYP.max+1);
1429 
1430   /// Returns the byte size of a type.
1431   size_t getSize(Type type)
1432   {
1433     return table[type.tid].size;
1434   }
1435 
1436   /// Returns the align size of a type.
1437   size_t getAlignSize(Type type)
1438   {
1439     return table[type.tid].size;
1440   }
1441 
1442   /// Returns the flags of a type.
1443   TypeFlags getFlags(Type type)
1444   {
1445     TypeFlags tf = {MITable.table[type.tid].flags};
1446     return tf;
1447   }
1448 
1449   /// Returns the mangle character of a type.
1450   char mangleChar(Type type)
1451   {
1452     return table[type.tid].mangle;
1453   }
1454 }
1455 
1456 /// Namespace for a set of predefined types.
1457 struct Types
1458 {
1459 static:
1460   /// Predefined basic types.
1461   TypeBasic XChar,    Char,     WChar, DChar,  Bool,
1462             Int8,     UInt8,    Int16, UInt16,
1463             Int32,    UInt32,   Int64, UInt64,
1464             Int128,   UInt128,
1465             Float32,  Float64,  Float80,
1466             IFloat32, IFloat64, IFloat80,
1467             CFloat32, CFloat64, CFloat80, Void;
1468 
1469   TypePointer Void_ptr; /// The void pointer type.
1470   TypeError Error; /// The error type.
1471   TypeError Undefined; /// The undefined type.
1472   TypeError DontKnowYet; /// The symbol is undefined but might be resolved.
1473 
1474   TypeFunction Void_0Args_DFunc; /// Type: extern(D) void X()
1475 
1476   // A table mapping the kind of a token to its corresponding semantic Type.
1477   TypeBasic[TOK] TOK2Type;
1478 
1479   /// Returns the corresponding Type instance for tok,
1480   /// or null if it does not apply.
1481   Type fromTOK(TOK tok)
1482   {
1483     auto ptype = tok in TOK2Type;
1484     return ptype ? *ptype : null;
1485   }
1486 
1487   /// Creates a list of statements for creating and initializing types.
1488   /// ---
1489   /// Int8 = new TypeBasic(Keyword.Byte, TYP.Int8);
1490   /// ---
1491   char[] createTypes(string[2][] typeNames)
1492   {
1493     char[] result;
1494     foreach (n; typeNames)
1495       result ~= n[0]~" = new TypeBasic(Keyword."~n[1]~", TYP."~n[0]~");";
1496     return result;
1497   }
1498 
1499   /// Initializes global, predefined types.
1500   /// NB: Not thread-safe.
1501   auto init = &init_;
1502   /// ditto
1503   void init_()
1504   {
1505     init = {}; // Disable with empty function after first call.
1506 
1507     mixin(createTypes([ // Pass tuples: (TypeName, KeywordName)
1508       ["Char", "Char"], ["WChar", "Wchar"], ["DChar", "Dchar"],
1509       ["Bool", "Bool"],
1510       ["Int8", "Byte"], ["UInt8", "Ubyte"],
1511       ["Int16", "Short"], ["UInt16", "Ushort"],
1512       ["Int32", "Int"], ["UInt32", "Uint"],
1513       ["Int64", "Long"], ["UInt64", "Ulong"],
1514       ["Int128", "Cent"], ["UInt128", "Ucent"],
1515       ["Float32", "Float"], ["Float64", "Double"], ["Float80", "Real"],
1516       ["IFloat32", "Ifloat"], ["IFloat64", "Idouble"], ["IFloat80", "Ireal"],
1517       ["CFloat32", "Cfloat"], ["CFloat64", "Cdouble"],
1518       ["CFloat80", "Creal"], ["Void", "Void"]
1519     ]));
1520 
1521     /// Polysemous character type.
1522     XChar = new TypeBasic(Char.ident, Char.tid);
1523 
1524     TOK2Type = [
1525       // Number literal TOKs:
1526       TOK.Int32 : Types.Int32, TOK.UInt32 : Types.UInt32,
1527       TOK.Int64 : Types.Int64, TOK.UInt64 : Types.UInt64,
1528       TOK.Float32 : Types.Float32, TOK.Float64 : Types.Float64,
1529       TOK.Float80 : Types.Float80, TOK.IFloat32 : Types.IFloat32,
1530       TOK.IFloat64 : Types.IFloat64, TOK.IFloat80 : Types.IFloat80,
1531       // Keyword TOKs:
1532       TOK.Char : Types.Char, TOK.Wchar : Types.WChar, TOK.Dchar : Types.DChar,
1533       TOK.Bool : Types.Bool,
1534       TOK.Byte : Types.Int8, TOK.Ubyte : Types.UInt8,
1535       TOK.Short : Types.Int16, TOK.Ushort : Types.UInt16,
1536       TOK.Int : Types.Int32, TOK.Uint : Types.UInt32,
1537       TOK.Long : Types.Int64, TOK.Ulong : Types.UInt64,
1538       TOK.Cent : Types.Int128, TOK.Ucent : Types.UInt128,
1539       TOK.Float : Types.Float32, TOK.Double : Types.Float64,
1540       TOK.Real : Types.Float80,
1541       TOK.Ifloat : Types.IFloat32, TOK.Idouble : Types.IFloat64,
1542       TOK.Ireal : Types.IFloat80,
1543       TOK.Cfloat : Types.CFloat32, TOK.Cdouble : Types.CFloat64,
1544       TOK.Creal : Types.CFloat80, TOK.Void : Types.Void
1545     ];
1546 
1547     Void_ptr = Void.ptrTo();
1548     Error = new TypeError();
1549     Undefined = new TypeError();
1550     DontKnowYet = new TypeError();
1551 
1552     // A function type that's frequently used.
1553     auto params = new TypeParameters(null);
1554     Void_0Args_DFunc = new TypeFunction(Types.Void, params,
1555       StorageClass.None, LinkageType.D);
1556   }
1557 }