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 }