Wiki

root/cobra/trunk/Source/Types.cobra

Revision 2636, 50.6 KB (checked in by Charles.Esterbrook, 7 weeks ago)

JVM back-end progress.
credit:hopscc

  • Property svn:eol-style set to native
Line 
1use System.Reflection
2
3class NativeType is abstract
4    """
5    The abstract base class for a boxed native type of the platform being compiled to.
6
7    For generalizing the native types of a platform such as a CLR struct or a JVM class.
8   
9    This does *not* represent a Cobra IType descendant.
10    It just represents a "boxed" native type.
11   
12    This abstract class facilitates multiple backends for Cobra.
13   
14    Cobra code that is not platform specific should refer to NativeType rather than
15    CLR's System.Type or JVM's Class.
16   
17    TODO: Since this is being used to "box" native types, another approach could be to make this class an interface and use structs.
18    However, I'm not sure if the use of an interface for arguments and return types wouldn't just eliminate any struct pass-by-value efficiency anyway.
19    """
20
21    get name as String is abstract
22        """
23        Return the name of the type, sans namespace or package.
24        """
25
26    get fullName as String is abstract
27        """
28        Return the full name of the type including the namespace/package which may be empty if this type is in the global namespace.
29        TODO: ensure result.endsWith(.name)
30        """
31
32    get isValueType as bool is abstract
33        """
34        Return true if this is a value type such as a bool, int, float or struct.
35        """
36
37    get baseType as NativeType? is abstract
38        """
39        Return the native base type that this native type inherits from, if any.
40        Actually, native types should return the root Object class with the exception of the Object class.
41        TODO: Add contract to enforce above statement
42        """
43
44    get isSystemObjectClass as bool is abstract
45        """
46        Return true if this is the Native Type Object for the root Object of the class hierarchy.
47            e.g. like System.Object in .Net, java.lang.Object in java
48        """
49
50    get isSystemTypeClass as bool is abstract
51        """
52        Return true if this is the Native Type Object for a System Type.
53            e.g. like System.Type in .Net, java.lang.class in java
54        """
55               
56    def customAttributes as IList<of dynamic> is abstract
57        """
58        Return a list of custom attributes attached to this type.
59        """
60
61    def equals(other as Object?) as bool is override
62        throw Exception('Subclasses must override .equals')
63
64    def getHashCode as int is override
65        throw Exception('Subclasses must override .getHashCode')
66           
67class NullNativeType inherits NativeType
68    """
69    Valid but empty nativeType for Tests
70    """
71    var _full = ''
72    var _name = ''
73   
74    cue init(qualName as String)
75        base.init
76        _full = qualName
77        l = qualName.split('.')
78        _name = l[l.length-1]   # l.last or l[-1:][0]
79       
80    get name as String is override
81        return _name
82   
83    get fullName as String is override
84        return _full
85
86    get isValueType as bool is override
87        return false
88       
89    get baseType as NativeType? is override
90        return this # wrong either way - cant get ObjectType and isnt Object root so cant return nil
91   
92    def customAttributes as IList<of dynamic> is override
93        return List<of dynamic>() 
94
95    def equals(other as Object?) as bool is override
96        return false
97
98    def getHashCode as int is override
99        return 999666
100   
101    get isSystemObjectClass as bool is override 
102        return false   
103       
104    get isSystemTypeClass as bool is override
105        return false   
106
107interface ITypeProvider
108    """
109    A type provider can provide essential types and serve as a place to centralise the provision of these
110    types. They are "uniqued" in order to avoid type duplication.
111
112    The Cobra types themselves rely on having a type provider available to implement some of their methods.
113
114    The main type provider is in the Compiler.
115    There is also a BasicTypeProvider that is useful in setting up tests.
116    """
117
118    def typeForName(name as String) as IType
119
120    def typeOrNilForName(name as String) as IType?
121
122    def arrayType(type as IType) as ArrayType
123
124    get boolType as BoolType
125
126    get charType as CharType
127
128    get decimalType as DecimalType
129
130    def floatType as FloatType
131
132    def floatType(size as int) as FloatType
133
134    def intType as IntType
135
136    def uintType as IntType
137
138    def intType(signed as bool, size as int) as IntType
139        require size in @[8, 16, 32, 64]
140
141    get dynamicType as DynamicType
142
143    get nilType as NilType
144
145    get numberType as AbstractNumberType
146
147    get objectType as IType
148
149    get passThroughType as PassThroughType
150
151    get typeType as IType
152
153    get unspecifiedType as UnspecifiedType
154
155    get voidType as VoidType
156
157    def nilableType(t as IType) as NilableType
158
159    def variType(type as IType) as VariType
160
161    def libraryType(qualifiedName as String) as IType
162
163    def nativeType(qualifiedName as String) as NativeType
164
165    def defaultType as IType
166
167       
168#   TODO: rename to TypeProvider, change to a "mix-in" and have the Compiler class inherit it
169class BasicTypeProvider
170    implements ITypeProvider
171    """
172    This is the base and also can be used as a test TypeProvider
173    """
174
175    var _anyFloatType       as AnyFloatType?
176    var _anyIntType         as AnyIntType?
177    var _arrayTypes         as Dictionary<of IType, ArrayType>?
178    var _boolType           as BoolType?
179    var _charType           as CharType?
180    var _decimalType        as DecimalType?
181    var _dynamicType        as DynamicType?
182    var _floatTypes         =  Dictionary<of int, FloatType>()
183    var _intTypes           =  Dictionary<of int, IntType>()
184    var _nilType            as NilType?
185    var _numberType         as AbstractNumberType?
186    var _passThroughType    as PassThroughType?
187    var _unspecifiedType    as UnspecifiedType?
188    var _voidType           as VoidType?
189    var _nilableTypes       as Dictionary<of IType, NilableType>?
190    var _variTypes          as Dictionary<of IType, VariType>?
191    var _defaultType        as IType?
192
193    def typeForName(name as String) as IType
194        assert false, 'TODO'
195        return .intType
196
197    def typeOrNilForName(name as String) as IType?
198        assert false, 'TODO'
199        return nil
200
201    get anyFloatType as AnyFloatType
202        if _anyFloatType is nil
203            _anyFloatType = AnyFloatType()
204        return _anyFloatType to !
205
206    get anyIntType as AnyIntType
207        if _anyIntType is nil
208            _anyIntType = AnyIntType()
209        return _anyIntType to !
210
211    def arrayType(type as IType) as ArrayType
212        if _arrayTypes is nil, _arrayTypes = Dictionary<of IType, ArrayType>()
213        if _arrayTypes.containsKey(type)
214            return _arrayTypes[type]
215        else
216            _arrayTypes[type] = at = ArrayType(type)
217            at.bindInh
218            at.bindInt
219            return at
220
221    get boolType as BoolType
222        if _boolType is nil
223            _boolType = BoolType()
224        return _boolType to !
225
226    get charType as CharType
227        if _charType is nil
228            _charType = CharType()
229        return _charType to !
230
231    get decimalType as DecimalType
232        if _decimalType is nil
233            _decimalType = DecimalType()
234        return _decimalType to !
235
236    get dynamicType as DynamicType
237        if _dynamicType is nil
238            _dynamicType = DynamicType()
239        return _dynamicType to !
240
241    def floatType as FloatType
242        return .floatType(64)
243   
244    def floatType(size as int) as FloatType
245        require size in [32, 64]
246        type as FloatType?
247        if _floatTypes.tryGetValue(size, out type)
248            return type to !
249        else
250            type = _floatTypes[size] = FloatType(size, .anyFloatType)
251            return type to !
252
253    def intType as IntType
254        return .intType(true, 32)
255
256    def uintType as IntType
257        return .intType(false, 32)
258
259    def intType(signed as bool, size as int) as IntType
260        require size in [8, 16, 32, 64] # CC: inherit from interface
261        key = if(signed, -1, +1) * size
262        type as IntType?
263        if _intTypes.tryGetValue(key, out type)
264            return type to !
265        else
266            type = _intTypes[key] = IntType(signed, size, .anyIntType)
267            return type to !
268       
269    get nilType as NilType
270        if _nilType is nil
271            _nilType = NilType()
272        return _nilType to !
273
274    get numberType as AbstractNumberType
275        return .decimalType
276
277    get objectType as IType
278        return .libraryType('System.Object')
279
280    get passThroughType as PassThroughType
281        if _passThroughType is nil
282            _passThroughType = PassThroughType()
283        return _passThroughType to !
284
285    get typeType as IType
286        return .libraryType('System.Type')
287
288    get unspecifiedType as UnspecifiedType
289        if _unspecifiedType is nil
290            _unspecifiedType = UnspecifiedType()
291        return _unspecifiedType to !
292
293    get voidType as VoidType
294        if _voidType is nil
295            _voidType = VoidType()
296        return _voidType to !
297
298    def nilableType(type as IType) as NilableType
299        if type inherits NilableType, return type
300        if _nilableTypes is nil
301            _nilableTypes = Dictionary<of IType, NilableType>()
302        if _nilableTypes.containsKey(type)
303            return _nilableTypes[type]
304        else
305            _nilableTypes[type] = nt = NilableType(type)
306            nt.bindInh
307            nt.bindInt
308            return nt
309
310    def variType(type as IType) as VariType
311        if _variTypes is nil
312            _variTypes = Dictionary<of IType, VariType>()
313        else if _variTypes.containsKey(type)
314            return _variTypes[type]
315        _variTypes[type] = vt = VariType(type)
316        return vt
317
318    def defaultType as IType
319        if _defaultType is nil
320            _defaultType = .nilableType(.dynamicType)
321        return _defaultType to !
322
323    def libraryType(qualifiedName as String) as IType
324        return BasicLibraryType(.nativeType(qualifiedName))
325
326    def nativeType(qualifiedName as String) as NativeType
327        return NullNativeType(qualifiedName)
328        #return ClrNativeType(sharp'System.Type.GetType(qualifiedName)' to System.Type)
329       
330
331class BasicLibraryType
332    is partial
333    implements IType
334    """
335    These objects are created by BasicTypeProvider and only for testing purposes.
336    The real library types used by the compiler are instances of Class, Interface, Struct, etc.
337    See BasicTypeProvider.libraryType and Compiler.libraryType.
338    """
339
340    shared
341       
342        def systemObjectType as BasicLibraryType
343            #nativeType = .compiler.ObjectNativeType
344            nativeType = ClrNativeType(sharp'typeof(System.Object)')
345            return BasicLibraryType(nativeType)
346
347    var _nativeType as NativeType
348
349    cue init(nativeType as NativeType)
350        base.init
351        _nativeType = nativeType
352
353    get idString as String
354        return .toString
355
356    def toString as String is override
357        return '[.getType.name]([.nativeType])'
358
359    def equals(other as Object?) as bool is override
360        if other
361            if other inherits BasicLibraryType
362                return .nativeType == other.nativeType
363            else
364                return false
365        else
366            return false
367
368    def getHashCode as int is override
369        return _nativeType.getHashCode
370
371    get nativeType from var
372
373    ## IType Properties
374
375    get innerType as IType?
376        return nil
377
378    get realType as IType
379        return this
380
381    get superType as IType?
382        return if(.isSystemObjectClass, nil, .systemObjectType)
383
384    ## IType isFoo
385
386    get isDynamic as bool
387        return false
388
389    get isSystemObjectClass as bool
390        return _nativeType.name == 'Object'
391
392    get isSystemTypeClass as bool
393        return _nativeType.name == 'Type'
394
395    def isAssignableTo(t as IType) as bool
396        return this == t or t.isSystemObjectClass
397
398    def isComparableTo(t as IType) as bool
399        return this == t
400
401    def isEquatableTo(t as IType) as bool
402        return this == t
403
404    def isDescendantOf(t as IType) as bool
405        return this == t or t.isSystemObjectClass
406
407    get isReference as bool
408        return not _nativeType.isValueType
409
410    get isUninitializedForLocalVars as bool
411        return .isReference
412
413    def isStrictDescendantOf(t as IType) as bool
414        return this is not t and t.isSystemObjectClass
415
416    get nonNil as IType
417        return this
418
419    ## Methods
420
421    def greatestCommonDenominatorWith(type as IType) as IType
422        if type == this
423            return this
424        else
425            return .systemObjectType
426
427    def memberForName(name as String) as IMember?
428        return nil
429
430    def suggestionsForBadMemberName(name as String) as List<of String>
431        return List<of String>()
432
433    def secondaryConstructedTypeFor(box as Box, gpToType as Dictionary<of GenericParam, IType>) as IType
434        return this
435
436    ## INode
437
438    def bindAll as INode
439        .bindInh
440        .bindInt
441        return .bindImp
442
443    def bindInh
444        _didBindInh = true
445
446    var _didBindInh as bool
447    get didBindInh from var
448
449    def bindInt as INode
450        _didBindInt = true
451        return this
452
453    var _didBindInt as bool
454    get didBindInt from var
455
456    def computeMatchingBaseMembers
457        pass
458   
459    def bindImp as dynamic
460        _didBindImp = true
461        return this
462
463    var _didBindImp as bool
464    get didBindImp from var
465
466    var _addOnValues as Dictionary<of String, Object>?
467   
468    get addOnValues as Dictionary<of String, Object>
469        if _addOnValues is nil
470            _addOnValues = Dictionary<of String, Object>()
471        return _addOnValues to !
472
473    get hasError as bool
474        return false
475
476    get serialNum as int
477        return 1
478
479    pro superNode as INode?
480        get
481            return nil
482        set
483            pass
484
485    def toTechString as String
486        return .toString
487
488    def throwError(msg as String)
489        throw NodeException(this, msg)
490
491    def recordError(msg as String)
492        pass
493
494    def writeDeepString
495        .writeDeepString(IndentedWriter(CobraCore.printDestination))
496
497    def writeDeepString(iw as IndentedWriter)
498        pass
499
500    get idSring as String
501        return '[.getType.name]()'
502
503    get deepString as String
504        return .toString
505
506    get minimalString as String
507        return .toString
508   
509    get shallowString as String
510        return .toString
511
512    def replaceChild(find as INode, replace as INode) as bool
513        throw NotImplementedException('[.getType.name].replaceChild')
514
515    pro transformedFrom as INode?
516        get
517            return nil
518        set
519            throw NotImplementedException('[.getType.name].replaceChild')
520
521    ## INamedNode
522   
523    get name as String
524        return .nativeType.name
525
526    get typeForIdentifier as IType
527        return this # well should really be System.Type TODO: what?
528
529    get typeForReceiver as IType
530        return this
531
532    get isMethod as bool
533        return false
534
535    pro isUsed as bool
536        get
537            return false
538        set
539            pass
540
541    ## IMember
542
543    get attributes as AttributeList
544        return AttributeList()
545
546    get englishName as String
547        return 'library type'
548
549    get isCallable as bool
550        return true
551
552    get isShared as bool
553        return true
554
555    pro parentNameSpace as NameSpace?
556        get
557            return nil
558        set
559            pass
560
561    get requiresThis as bool
562        return false
563
564    get resultType as IType
565        return this
566
567    def unNilReturnType
568        pass
569
570       
571
572interface IType
573    is partial
574    inherits ITypeProxy, IMember
575
576    def isAssignableTo(type as IType) as bool
577
578    def isDescendantOf(type as IType) as bool
579
580    def isStrictDescendantOf(type as IType) as bool
581
582    get isDynamic as bool
583        """
584        Returns true if the type is a dynamic type.
585        You cannot use `t inherits DynamicType` because a NilableType gives false for that even though it may be dynamic.
586        """
587
588    get isReference as bool
589        """
590        Returns true if the type is a reference type, such as a class, interface or nilable type.
591        And as opposed to value type such as a struct, int, etc.).
592        """
593
594    get isSystemObjectClass as bool
595        """
596        Return true if this type represents/is System.Object.
597        """
598
599    get isSystemTypeClass as bool
600        """
601        Return true if this type represents/is System.Type.
602        """
603
604    get isUninitializedForLocalVars as bool
605        """
606        Return true if a local var of this type is uninitialized without an explicit assignment.
607        The default implementation is typically: return .isReference
608        because non-nil reference types need an initial value.
609        """
610
611    def isComparableTo(t as IType) as bool
612        """
613        Returns true if this type can be compared to the given type via comparison operators such as `>`, `<=`, etc.
614        """
615
616    def isEquatableTo(t as IType) as bool
617        """
618        Returns true if this type can be compared to the given type via `is`, `is not`, `==` and `<>`.
619        """
620
621    get nonNil as IType
622        """
623        Returns the non-nil version of the receiver.
624        This is normally just the receiver itself, except in the case of NilableType.
625        """
626
627    def secondaryConstructedTypeFor(box as Box, gpToType as Dictionary<of GenericParam, IType>) as IType
628        """
629        Makes a new generic type, if needed, using the given map from generic params to types.
630        Returns this type if no generic construction is necessary.
631        This method is invoked during the type construction for return types, parameter types, etc.
632        """
633
634    def greatestCommonDenominatorWith(type as IType) as IType
635        """
636        Return the most specific type that is compatible with both this type and the arg.
637        The worst case scenarious are Object and Object? since all types are compatible
638        with Object. Used for at least if() expressions, list literals and dictionary
639        literals.
640        """
641
642    get innerType as IType?
643        """
644        Used by the enumerable for statement to infer the type of the control variable.
645        Examples:
646            List<of int> --> int
647            List<of dynamic> --> dynamic
648            ArrayList --> Object
649            String --> char
650            Object --> nil
651        """
652
653    get superType as IType?
654        """
655        Returns the super type of this type.
656        If an implementor has multiple super types (interfaces do), then this method should
657        return nil and other methods such as isDescendantOf() and memberForName() must be
658        sure to take the multiple super types into consideration.
659        """
660
661    def memberForName(name as String) as IMember?
662        """
663        Used for `foo.bar` where this type is the type of `foo`.
664        Should return members that are inherited (if any).
665        """
666
667    def suggestionsForBadMemberName(name as String) as List<of String>
668        """
669        When .memberForName returns nil for the given name, provide suggestions of names that actually exist.
670        """
671
672
673class CobraType
674    is abstract, partial
675    inherits Node
676    implements IType, ITypeProxy
677    """
678    This is the parent type of all other types.
679    It exists for organizational purposes.
680    No actual expression is ever directly assigned this type.
681    If you are looking for "dynamic", see DynamicType.
682    If you are looking for "object", see ObjectType.
683    If you are looking for the type of types, that would be typeProvider.typeType which is a cover for typeProvider.libraryType('System.Type').
684    TODO: Could CobraType be a subclass of NamedNode instead?
685    """
686
687    var _parentNameSpace as NameSpace?
688    var _superType as IType?
689    var _isUsed as bool
690
691    cue init
692        .init(nil)
693
694    cue init(superType as IType?)
695        base.init
696        _superType = superType
697
698    get attributes as AttributeList
699        return AttributeList()
700       
701    get englishName as String is abstract
702
703    get name as String
704        return .getType.toString
705
706    pro parentNameSpace from var
707
708    get isCallable as bool
709        return true
710
711    get isDynamic as bool
712        return false
713
714    get isMethod as bool
715        return false
716
717    get isReference as bool is abstract
718
719    get isShared as bool
720        return true
721
722    get isSystemObjectClass as bool
723        return false
724
725    get isSystemTypeClass as bool
726        return false
727
728    get isUninitializedForLocalVars as bool
729        return .isReference
730
731    def isComparableTo(t as IType) as bool
732        t = t.nonNil
733        compareTo = .memberForName('compareTo')
734        if compareTo and compareTo.isMethod and compareTo.resultType is .compiler.intType and t.isDescendantOf(this)
735            # TODO: check that the compareTo can take a `t` as an argument
736            return true
737        if t.isDynamicOrPassThrough
738            return true
739        return false
740
741    def isEquatableTo(t as IType) as bool
742        t = t.nonNil
743        if this == t, return true
744        if .isAssignableTo(t) or t.isAssignableTo(this), return true
745        return false
746
747    get nonNil as IType
748        ensure not result inherits NilableType
749        return this
750
751    get requiresThis as bool
752        return false
753
754    get resultType as IType?
755        return this
756
757    get typeForIdentifier as IType
758        return .compiler.typeType
759
760    get typeForReceiver as IType
761        return this
762
763    get innerType as IType?
764        return nil
765
766    get realType as IType
767        return this
768
769    get superType from var
770
771    def secondaryConstructedTypeFor(box as Box, gpToType as Dictionary<of GenericParam, IType>) as IType
772        return this
773
774    def greatestCommonDenominatorWith(type as IType) as IType
775        if this == type
776            return this
777        if type inherits NilableType
778            return type.greatestCommonDenominatorWith(this)
779        if type inherits NilType
780            return .typeProvider.nilableType(this)
781        if .isDescendantOf(type)
782            return type
783        if type.isDescendantOf(this)
784            return this
785        if type inherits DynamicType
786            return type
787        # TODO: following is a guess -- haven't really thought about following both superTypes at the same time or if there is even any point
788        if .superType and type.superType
789            return .superType.greatestCommonDenominatorWith(type.superType to !)
790        else
791            return .typeProvider.objectType
792
793    def isAssignableTo(type as IType) as bool
794        require
795            .typeProvider
796        body
797            if this == type, return true
798            if type is .typeProvider.passThroughType, return true
799            if type is .typeProvider.dynamicType, return true
800            if type is .typeProvider.objectType, return true
801            if type inherits NilableType
802                return .isAssignableTo(type.theWrappedType to passthrough) # CC: bug with if-inherits changes the parameter type
803            return .isDescendantOf(type)
804
805    def isDescendantOf(type as IType) as bool
806        """
807        Returns true if this type is a subtype (direct or indirect) of type.
808        """
809        if this == type, return true
810        if not .didBindInh, .bindInh
811        curType = this to IType?
812        counter = 0
813        while true
814            if curType == type, return true
815            curType = curType.superType
816            if curType is nil, break
817            counter += 1
818            assert counter < 1000
819        return false
820
821    def isStrictDescendantOf(type as IType) as bool
822        if type == this
823            return false
824        else
825            return .isDescendantOf(type)
826
827    pro isUsed from var
828
829    def declForName(name as String) as IMember?
830        """
831        Returns nil by default.
832        """
833        return nil
834
835    def memberForName(name as String) as IMember?
836        """
837        Returns a named member of System.Object by default.
838        """
839        assert .didBindInh and .didBindInt  # don't `require` because subclass overrides may check and fix before invoking base
840        objectClass = .compiler.objectType
841        return objectClass.memberForName(name)
842
843    def suggestionsForBadMemberName(name as String) as List<of String>
844        suggs = List<of String>()
845        if _superType
846            suggs.addRange(_superType.suggestionsForBadMemberName(name))
847        return suggs
848
849    def equals(obj as Object?) as bool is override
850        if obj is nil
851            return false
852        if obj inherits CobraType
853            return .serialNum.equals(obj.serialNum)
854        else
855            return false
856
857    def getHashCode as int is override
858        return .serialNum.getHashCode
859
860    def unNilReturnType
861        # ack! apparently CobraType inherits IMember
862        pass
863
864
865class ValueType
866    is abstract
867    inherits CobraType
868
869    cue init
870        .init(nil)
871
872    cue init(superType as IType?)
873        base.init(superType)
874
875    get englishName as String is override
876        return 'primitive type'
877
878    get isReference as bool is override
879        return false
880
881    def equals(obj as Object?) as bool is override
882        if obj is nil, return false
883        if not obj inherits CobraType, return false
884        if .getType is obj.getType, return true
885        return false
886
887    def getHashCode as int is override
888        return .getType.getHashCode
889
890
891class PrimitiveType
892    is abstract
893    inherits ValueType
894    """
895    The base class of BoolType, CharType, etc.
896    Used in part for classification purposes (`t inherits PrimitiveType`).
897    """
898
899    var _systemAliasProxy as ITypeProxy?
900        """
901        Subclasses set this to a LibraryTypeProxy instead of a backendTypeProxy because, for example, the
902        ClrTypeProxy for the clr type System.Boolean would return a Cobra BoolType instance! Then
903        the primitive type would have a self reference when what it really wanted was the Struct
904        instance for System.Boolean.
905        """
906
907    var _systemAliasType as IType?
908
909    var _nativeType as NativeType?
910
911    cue init
912        .init(nil)
913
914    cue init(superType as IType?)
915        base.init(superType)
916
917    get box from var as Box?
918        # Holds the methods and properties that this primitive type supports.
919
920    get nativeType from var
921
922    get systemAliasProxy from var
923
924    get systemAliasType from var
925
926    def _bindInh
927        base._bindInh
928        if _superType is nil
929            _superType = .compiler.objectType
930        if not _systemAliasType and _systemAliasProxy
931            _systemAliasType = _systemAliasProxy.realType
932            _systemAliasType.bindInh
933        if .compiler  # will be nil during unit tests
934            baseNode = .compiler.objectTypeProxy
935            _box = Class(Token.empty, Token.empty, '[.getType.name]_[.serialNum]', List<of IType>(), List<of String>(), AttributeList(), baseNode, List<of ITypeProxy>(), List<of ITypeProxy>(), nil)
936            if _systemAliasType inherits Box
937                for bip in _systemAliasType.baseInterfaceProxies
938                    _box.baseInterfaceProxies.add(bip)
939            _box.bindInh
940
941    def _bindInt
942        base._bindInt
943        if _systemAliasType, _systemAliasType.bindInt
944        if .compiler and _nativeType
945            .compiler.installNativeMethods(_box to !, _nativeType to !) # BackEnd
946        _box.bindInt
947
948    def memberForName(name as String) as IMember?
949        member = base.memberForName(name)
950        if member is nil, member = _box.memberForName(name)
951        return member
952
953    def isAssignableTo(type as IType) as bool
954        return this == type _
955            or _systemAliasType == type _
956            or (_box and _box.isAssignableTo(type)) _
957            or base.isAssignableTo(type)
958
959    def isComparableTo(type as IType) as bool
960        return this == type _
961            or _systemAliasType == type _
962            or (_box and _box.isComparableTo(type)) _
963            or base.isComparableTo(type)
964
965# TODO?
966#   def isEquatableTo(t as IType) as bool
967
968
969class BoolType
970    is partial
971    inherits PrimitiveType
972
973    cue init
974        base.init
975        _nativeType = .typeProvider.nativeType('bool')
976        _systemAliasProxy = LibraryTypeProxy('bool')
977
978    get name as String is override
979        return 'bool'
980
981
982class CharType inherits PrimitiveType is partial
983
984    cue init
985        base.init
986        _nativeType = .typeProvider.nativeType('char')
987        _systemAliasProxy = LibraryTypeProxy('char')
988
989    get name as String is override
990        return 'char'
991
992    def isComparableTo(t as IType) as bool
993        return base.isComparableTo(t) or t is .compiler.stringType
994
995    def isEquatableTo(t as IType) as bool
996        return base.isEquatableTo(t) or t is .compiler.stringType
997
998
999class DecimalType inherits AbstractNumberType
1000
1001    cue init
1002        base.init
1003        _nativeType = .typeProvider.nativeType('decimal')
1004        _systemAliasProxy = LibraryTypeProxy('decimal')
1005
1006    get name as String is override
1007        return 'decimal'
1008
1009    def isComparableTo(t as IType) as bool
1010        return base.isComparableTo(t) or t inherits IntType
1011
1012
1013class DynamicType
1014    is partial
1015    inherits CobraType
1016
1017    get englishName as String is override
1018        return 'basic type'
1019
1020    get name as String is override
1021        return 'dynamic'
1022
1023    def isAssignableTo(type as IType) as bool is override
1024        return true
1025
1026    def isComparableTo(type as IType) as bool is override
1027        return true
1028
1029    def isEquatableTo(type as IType) as bool is override
1030        return true
1031
1032    get isDynamic as bool is override
1033        return true
1034
1035    get isReference as bool is override
1036        return true
1037
1038    get innerType as IType? is override
1039        return this
1040
1041    def greatestCommonDenominatorWith(type as IType) as IType is override
1042        if this == type
1043            return this
1044        if type inherits NilableType or type inherits NilType
1045            return .typeProvider.nilableType(this)
1046        return this
1047
1048
1049class AnyFloatType
1050    inherits AbstractNumberType
1051   
1052    cue init
1053        .init(nil)
1054   
1055    cue init(superType as IType?)
1056        base.init(superType)
1057
1058
1059class FloatType
1060    is partial
1061    inherits AnyFloatType
1062
1063    test
1064        saveTP = if(Node.hasTypeProvider, Node.typeProvider, nil)
1065        Node.typeProvider = BasicTypeProvider()
1066        try
1067            anyFloat = AnyFloatType()
1068
1069            f32 = FloatType(32, anyFloat)
1070            assert f32.name == 'float32'
1071            assert f32.size == 32
1072           
1073            f64 = FloatType(64, anyFloat)
1074            assert f64.name == 'float'
1075            assert f64.size == 64
1076
1077            assert f64.isEquatableTo(f32)
1078            assert f32.isEquatableTo(f64)
1079            assert f32.isAssignableTo(f64)
1080            assert not f64.isAssignableTo(f32)
1081
1082            f32b = FloatType(32, anyFloat)
1083            assert f32 == f32b
1084            assert f32 <> f64
1085        finally
1086            Node.typeProvider = saveTP
1087
1088    var _size as int
1089
1090    cue init(size as int, superType as IType?)
1091        require
1092            size in [32, 64]
1093            superType implies superType inherits AnyFloatType
1094        body
1095            base.init(superType)
1096            _size = size
1097            branch size
1098                on 32, tag = 'single'
1099                on 64, tag = 'double'
1100                else, throw FallThroughException(size)
1101            _nativeType = .typeProvider.nativeType(tag)
1102            _systemAliasProxy = LibraryTypeProxy(tag)
1103
1104    def addMinFields
1105        base.addMinFields
1106        .addField('size', .size)
1107
1108    def equals(other as Object?) as bool is override
1109        if other is this
1110            return true
1111        else if other
1112            if other inherits FloatType
1113                return .size == other.size
1114            else
1115                return false
1116        else
1117            return false
1118
1119    def getHashCode as int is override
1120        return .size.getHashCode
1121
1122    get isDefaultFloatType as bool
1123        return _size == 64
1124
1125    get isDefaultSize as bool
1126        return _size == 64
1127
1128    get name as String is override
1129        if .isDefaultFloatType
1130            return 'float'
1131        else
1132            return 'float[.size]'
1133
1134    get size from var
1135
1136    def isAssignableTo(type as IType) as bool
1137        if type == this  # common case
1138            return true
1139        if type inherits FloatType
1140            if .size <= type.size
1141                return true
1142        return base.isAssignableTo(type)
1143
1144    def isComparableTo(t as IType) as bool
1145        return base.isComparableTo(t) or t inherits IntType or t inherits FloatType
1146
1147    def greatestCommonDenominatorWith(type as IType) as IType is override
1148        if type inherits FloatType
1149            maxSize = if(type.size > .size, type.size, .size)
1150            return .compiler.floatType(maxSize)
1151        else
1152            return base.greatestCommonDenominatorWith(type)
1153
1154
1155class AnyIntType
1156    inherits AbstractNumberType
1157   
1158    cue init
1159        .init(nil)
1160
1161    cue init(superType as IType?)
1162        base.init(superType)
1163
1164
1165class IntType
1166    is partial
1167    inherits AnyIntType
1168
1169    test
1170        saveTP = if(Node.hasTypeProvider, Node.typeProvider, nil)
1171        Node.typeProvider = BasicTypeProvider()
1172        try
1173            anyInt = AnyIntType()
1174
1175            snt16 = IntType(true, 16, anyInt)
1176            assert snt16.name == 'int16'
1177            assert snt16.isSigned == true
1178            assert snt16.size == 16
1179
1180            snt64 = IntType(true, 64, anyInt)
1181
1182            assert snt64.isEquatableTo(snt16)
1183            assert snt16.isEquatableTo(snt64)
1184            assert snt16.isAssignableTo(snt64)
1185            assert not snt64.isAssignableTo(snt16)
1186           
1187            snt16b = IntType(true, 16, anyInt)
1188            assert snt16 == snt16b
1189            assert snt16 <> snt64
1190        finally
1191            Node.typeProvider = saveTP
1192
1193    var _signed as bool
1194    var _size as int
1195
1196    cue init(signed as bool, size as int, superType as IType?)
1197        require
1198            size in @[8, 16, 32, 64]
1199            superType implies superType inherits AnyIntType
1200        body
1201            base.init(superType)
1202            _signed = signed
1203            _size = size
1204            if signed
1205                branch size
1206                    on  8, tag = 'sbyte'
1207                    on 16, tag = 'int16'
1208                    on 32, tag = 'int32'
1209                    on 64, tag = 'int64'
1210                    else, throw FallThroughException(size)
1211            else
1212                branch size
1213                    on  8, tag = 'byte'
1214                    on 16, tag = 'uint16'
1215                    on 32, tag = 'uint32'
1216                    on 64, tag = 'uint64'
1217                    else, throw FallThroughException(size)
1218            _nativeType = .typeProvider.nativeType(tag)
1219            _systemAliasProxy = LibraryTypeProxy(tag)
1220
1221    def addMinFields
1222        base.addMinFields
1223        .addField('isSigned', .isSigned)
1224        .addField('size', .size)
1225
1226    def equals(other as Object?) as bool is override
1227        if other is this
1228            return true
1229        else if other
1230            if other inherits IntType
1231                return .isSigned == other.isSigned and .size == other.size
1232            else
1233                return false
1234        else
1235            return false
1236
1237    def getHashCode as int is override
1238        code = if(.isSigned, -1, 1) * .size
1239        return code.getHashCode
1240
1241    get isDefaultIntType as bool
1242        return _signed and _size == 32
1243
1244    get isDefaultSize as bool
1245        return _size == 32
1246
1247    get isSigned as bool
1248        return _signed
1249   
1250    get isUnsigned as bool
1251        return not _signed
1252
1253    get name as String is override
1254        if .isDefaultIntType
1255            return 'int'
1256        prefix = if(.isSigned, '', 'u')
1257        if .isDefaultSize
1258            return '[prefix]int'
1259        else
1260            return '[prefix]int[.size]'
1261
1262    get size from var
1263
1264    def isAssignableTo(type as IType) as bool
1265        if type == this  # common case
1266            return true
1267        if type is .typeProvider.decimalType
1268            return true
1269        if type inherits AnyFloatType
1270            return true
1271        if type inherits IntType
1272            if .isSigned == type.isSigned and .size == type.size
1273                return true
1274            if .size < type.size
1275                return true
1276        return base.isAssignableTo(type)
1277
1278    def isComparableTo(t as IType) as bool
1279        return base.isComparableTo(t) or t inherits IntType or t inherits DecimalType or t inherits FloatType
1280
1281    def greatestCommonDenominatorWith(type as IType) as IType is override
1282        if type inherits IntType
1283            # TODO: same size different signs
1284            maxSize = if(type.size > .size, type.size, .size)
1285            return .compiler.intType(.isSigned, maxSize)
1286        else
1287            return base.greatestCommonDenominatorWith(type)
1288
1289
1290class NilableType inherits WrappedType is partial
1291    """
1292    Rather than instantiating this type directly, use:
1293   
1294        .typeProvider.nilableType(t)
1295
1296    Or if the code block already belongs to a type provider:
1297   
1298        .nilableType(t)
1299       
1300    Note that NilableType will not wrap another NilableType. Also, .typeProvider.nilableType(t)
1301    silently handles this so in practice you don't have to guard against it.
1302    """
1303
1304    cue init(t as IType)
1305        require not t inherits NilableType
1306        base.init(t)
1307
1308    get englishName as String is override
1309        return 'nilable ' + _wrappedType.englishName
1310
1311    get name as String is override
1312        return _wrappedType.name + '?'
1313
1314    get isDynamic as bool is override
1315        return _wrappedType.isDynamic
1316
1317    get isReference as bool is override
1318        # Keep in mind that Nullable<T> is a struct so when T is also a struct, the effect is a value type.
1319        # When T is a reference type then the Nullable<T> struct is holding a reference.
1320        return _wrappedType.isReference
1321
1322    get isUninitializedForLocalVars as bool is override
1323        return false  # because nil is fine for the default value
1324
1325    # TODO: I think the following is appropriate, but come up with a test case for it first.
1326    #get innerType
1327    #   return .wrappedType.innerType
1328
1329    def isAssignableTo(type as IType) as bool is override
1330        if _wrappedType.isDynamic, return true
1331        if type inherits PassThroughType, return true
1332        if type inherits NilableType, return _wrappedType.isAssignableTo(type.nonNil)
1333        return false
1334
1335    def isComparableTo(b as IType) as bool is override
1336        if b inherits NilType
1337            return true
1338        else
1339            return _wrappedType.isComparableTo(b)
1340
1341    def isDescendantOf(type as IType) as bool
1342        return base.isDescendantOf(type) and _wrappedType.isDescendantOf(type)
1343        # to-do: answer hops question: shouldnt the above conjunction be an 'or' ??
1344
1345    def isEquatableTo(b as IType) as bool is override
1346        if b inherits NilType
1347            return true
1348        else
1349            return _wrappedType.isEquatableTo(b)
1350
1351    get nonNil as IType is override
1352        return _wrappedType
1353
1354    def memberForName(name as String) as IMember? is override
1355        _bindBasics
1356        return _wrappedType.memberForName(name)
1357
1358    def greatestCommonDenominatorWith(type as IType) as IType is override
1359        if this == type
1360            return this
1361        if type inherits NilType
1362            return this
1363        if type inherits NilableType
1364            if _wrappedType == type.nonNil
1365                return this
1366            else
1367                return .typeProvider.nilableType(_wrappedType.greatestCommonDenominatorWith(type.nonNil))
1368        return .typeProvider.nilableType(_wrappedType.greatestCommonDenominatorWith(type))
1369
1370    def secondaryConstructedTypeFor(box as Box, gpToType as Dictionary<of GenericParam, IType>) as IType is override
1371        wt = _wrappedType.secondaryConstructedTypeFor(box, gpToType)
1372        if not wt inherits NilableType
1373            thisType = .getType
1374            return thisType(wt)
1375        else
1376            return wt
1377
1378    def suggestionsForBadMemberName(name as String) as List<of String> is override
1379        return _wrappedType.suggestionsForBadMemberName(name)
1380
1381    get suffix as String is override
1382        return '?'
1383
1384
1385class NilType
1386    is partial
1387    inherits CobraType
1388
1389    get englishName as String is override
1390        return 'nil type'
1391
1392    get name as String is override
1393        return 'nil'
1394
1395    get isReference as bool is override
1396        return true
1397
1398    def isAssignableTo(type as IType) as bool is override
1399        if this == type, return true
1400        if type is .compiler.passThroughType, return true
1401        if type inherits NilableType, return true
1402        return false
1403
1404    def isEquatableTo(t as IType) as bool
1405        return base.isEquatableTo(t) or t inherits NilableType
1406
1407    def greatestCommonDenominatorWith(type as IType) as IType is override
1408        if this == type
1409            return this
1410        if type inherits NilableType
1411            return type
1412        else
1413            return .typeProvider.nilableType(type)
1414
1415# TODO:
1416#   def checkBinaryOp(self, op, right, compiler):
1417#       RootType.checkBinaryOp(self, op, right, compiler)
1418#       if op=='TO':
1419#           from Expressions import TypeExpr
1420#           type = right.realType
1421#           assert types, right
1422#           assert not inherits(type, NilType)
1423#           if not inherits(type, NilableType) and type is not tpassthrough:
1424#               .throwError('Cannot cast nil to a non-nil type.')
1425
1426
1427class AbstractNumberType
1428    is abstract, partial
1429    inherits PrimitiveType
1430    """
1431    The base class for int, float and decimal.
1432    This is *not* the type `number` which is an alias for one of the fractional
1433    types such as `decimal` or `float`.
1434    """
1435
1436    cue init
1437        base.init
1438
1439    cue init(superType as IType?)
1440        base.init(superType)
1441
1442
1443class PassThroughType
1444    is partial
1445    inherits CobraType
1446    """
1447    This is a temporary helper type used while Cobra is still deficient in type checking mostly
1448    due to its inability to look up methods, properties, etc.
1449
1450    Originally it overrode .isDescendantOf to always return true, but this mislead the C#
1451    body generation. The override was removed and now you have to check for it explicitly.
1452    """
1453
1454    cue init
1455        base.init
1456
1457    get englishName as String is override
1458        return 'basic type'
1459
1460    get isReference as bool is override
1461        return true
1462
1463    get name as String is override
1464        return 'passthrough'
1465
1466    get innerType as IType? is override
1467        return this
1468
1469    def isAssignableTo(type as IType) as bool is override
1470        return true
1471
1472    def isComparableTo(type as IType) as bool is override
1473        return true
1474
1475
1476class StreamType inherits WrappedType is partial
1477    """
1478    - Streams are portable between backends, whereas .NET's IEnumerable<of> and JVM's Iterable<of> are not.
1479    - Streams are two-way compatible with IEnumerable/Iterable:
1480        - Streams can be used whereever a compatible IEnumerable/Iterable is expected.
1481        - An IEnumerable/Iterable can be used whereever a compatible stream type is expected.
1482        - The term "compatible" means the same inner type: int* is compatible with IEnumerable<of int>/Iterable<of int>, but not IEnumerable<of String>/Iterable<of String>
1483    - However, compatibility does not mean that you can use the methods of IEnumerable or Iterable, since these vary between platforms.
1484    - Streams are an abstract type, so you cannot create them directly with a call on the type such as `int*()`. Instead, use a concrete class such as `List<of>` or `yield` results out of a method.
1485    - Streams are defaulted to be empty rather than nil.
1486    """
1487
1488    var _box as Box?
1489
1490    cue init(t as IType)
1491        base.init(t)
1492
1493    get englishName as String is override
1494        return 'stream of ' + _wrappedType.englishName
1495
1496    get box from var
1497
1498    get name as String is override
1499        return _wrappedType.name + '*'
1500
1501    get isReference as bool is override
1502        return true
1503
1504    get isUninitializedForLocalVars as bool is override
1505        return false  # because streams get initialized to EmptyStream<of T> for convenience
1506
1507    get innerType as IType? is override
1508        return .theWrappedType
1509
1510    get suffix as String is override
1511        return '*'
1512
1513    def isAssignableTo(type as IType) as bool is override
1514        return base.isAssignableTo(type)
1515
1516    def isComparableTo(b as IType) as bool is override
1517        return base.isComparableTo(b)
1518
1519    def isDescendantOf(type as IType) as bool
1520        return base.isDescendantOf(type) or .box.isDescendantOf(type)
1521
1522    def isEquatableTo(b as IType) as bool is override
1523        return base.isEquatableTo(b)
1524
1525    def memberForName(name as String) as IMember? is override
1526        m = base.memberForName(name)
1527        if m is nil and _box and .compiler and .compiler.nodeStack.count and (.compiler.nodeStack.peek to Node).isBindingImp
1528            # look for an extension member, but it has to be accessible according to namespaces
1529            if .compiler.nameSpaceStack.count
1530                # don't need to go through the whole namespace stack because the namespace will check its parent
1531                m = .compiler.curNameSpace.extensionMemberFor(_box to !, name)
1532        return m
1533
1534    def suggestionsForBadMemberName(name as String) as List<of String> is override
1535        # Need to include extension members somehow
1536        return List<of String>()
1537
1538    def greatestCommonDenominatorWith(type as IType) as IType is override
1539        return base.greatestCommonDenominatorWith(type)
1540
1541    def _bindInh
1542        base._bindInh
1543        if .compiler  # will be nil during unit tests
1544            _box = .compiler.enumerableOfType.constructedTypeFor([.theWrappedType])
1545            _box.bindInh
1546            _superType = _box
1547
1548
1549class VoidType
1550    is partial
1551    inherits CobraType
1552    """
1553    This type is used only for methods that don't declare a return type and therefore cannot return
1554    anything.
1555    """
1556
1557    cue init
1558        base.init
1559
1560    get englishName as String is override
1561        return 'void type'
1562
1563    get isReference as bool is override
1564        return false
1565
1566    get name as String is override
1567        return 'void'
1568
1569
1570##
1571## Wrapped Types
1572##
1573
1574class WrappedType inherits CobraType is abstract, partial
1575
1576    var _wrappedType as IType
1577    var _hashCode as int?
1578
1579    cue init(wrappedType as IType)
1580        base.init
1581        assert not wrappedType inherits NameSpace  # TODO: remove this when NameSpace is no longer an IType
1582        _wrappedType = wrappedType
1583
1584    get idString as String is override
1585        try, name = .name
1586        catch exc as Exception, name = '([exc])'
1587        try, wrapped = _wrappedType.idString
1588        catch exc as Exception, wrapped = '([exc])'
1589        return '[.typeOf.name]([.serialNum], "[name]", [wrapped])'
1590
1591    def addRefFields is override
1592        base.addRefFields
1593        .addField('wrappedType', _wrappedType)
1594
1595    def equals(obj as Object?) as bool is override
1596        if this is obj, return true
1597        if obj is nil, return false
1598        if .getType is not obj.getType, return false
1599        # at this point, not the identical object, but the class of obj is the same as ours
1600        if obj inherits WrappedType
1601            return _wrappedType.equals(obj._wrappedType)
1602        else
1603            throw FallThroughException([this, obj])
1604
1605    def getHashCode as int is override
1606        if _hashCode is nil
1607            _hashCode = _wrappedType.getHashCode   # TODO: should be combined with something else so no collision with the actual wrapped type.
1608        return _hashCode to !
1609
1610    # CC: this should work, but C# don't dig it. maybe for that reason we can't do it even when generating IL since we want C# to feel comfortable with Cobra based libraries
1611    #get wrappedType from _wrappedType
1612
1613    get theWrappedType as IType
1614        return _wrappedType
1615
1616    get innerType as IType? is override
1617        return _wrappedType.innerType  # TODO: 2008-11-22, I think this should just be _wrappedType; 2010-03-07: or abstract and make subclasses specify
1618
1619    get suffix as String is abstract
1620
1621    def memberForName(name as String) as IMember? is override
1622        _bindBasics
1623        return base.memberForName(name)
1624
1625    def secondaryConstructedTypeFor(box as Box, gpToType as Dictionary<of GenericParam, IType>) as IType is override
1626        thisType = .getType
1627        return thisType(_wrappedType.secondaryConstructedTypeFor(box, gpToType))
1628
1629    def _bindBasics
1630        .bindInh
1631        .bindInt
1632
1633
1634class ArrayType inherits WrappedType is partial
1635    """
1636    Represents an array.
1637
1638    Only single dimension arrays have been tested and are officially supported. These are common in
1639    the BCL as return types and sometimes as parameters. Multi-dim and jagged arrays are not popular.
1640    Also, most projects can get by just fine with nested List<of>s.
1641
1642    Rather than instantiating this type directly, use:
1643   
1644        .typeProvider.arrayType(t)
1645
1646    Or if the code block already belongs to a type provider:
1647   
1648        .arrayType(t)
1649       
1650    TODO: Get this related to System.Array.
1651    """
1652
1653    test
1654        saveTP = if(Node.hasTypeProvider, Node.typeProvider, nil)
1655        Node.typeProvider = BasicTypeProvider()
1656        try
1657            a1 = ArrayType(BoolType())
1658            a2 = ArrayType(BoolType())
1659            assert a1 is not a2
1660            assert a1 == a2
1661        finally
1662            Node.typeProvider = saveTP
1663
1664    var _ilistOf as Interface?
1665   
1666    cue init(wrappedType as IType)
1667        base.init(wrappedType)
1668
1669    get englishName as String is override
1670        return 'array of ' + .theWrappedType.name
1671
1672    get innerType as IType? is override
1673        return _wrappedType
1674
1675    get isReference as bool is override
1676        return true
1677
1678    get box from var as Box?
1679
1680    get name as String is override
1681        return _wrappedType.name + r'[]'
1682
1683    get suffix as String is override
1684        return r'[]'
1685
1686    def isAssignableTo(type as IType) as bool is override
1687        if base.isAssignableTo(type), return true
1688        if type inherits ArrayType
1689            if _wrappedType == type.theWrappedType, return true
1690            # covariance with arrays
1691            if _wrappedType.isAssignableTo(type.theWrappedType), return true
1692        if type inherits StreamType
1693            if .isAssignableTo(type.box to !), return true
1694            # covariance with streams
1695            if _wrappedType.isAssignableTo(type.innerType to !), return true
1696        if _box.isAssignableTo(type), return true
1697        return false
1698
1699    def isDescendantOf(type as IType) as bool
1700        return base.isDescendantOf(type) or .box.isDescendantOf(type)
1701
1702    def isEquatableTo(t as IType) as bool
1703        assert .didBindInh
1704        return base.isEquatableTo(t) or t.isDescendantOf(_ilistOf to !) or _ilistOf.isDescendantOf(t)
1705
1706    def memberForName(name as String) as IMember? is override
1707        m = base.memberForName(name)
1708        if m is nil, m = .box.memberForName(name)
1709        # TODO: dup'ed from StreamType:
1710        if m is nil and _box and .compiler and .compiler.nodeStack.count and (.compiler.nodeStack.peek to Node).isBindingImp
1711            # look for an extension member, but it has to be accessible according to namespaces
1712            if .compiler.nameSpaceStack.count
1713                # don't need to go through the whole namespace stack because the namespace will check its parent
1714                m = .compiler.curNameSpace.extensionMemberFor(_box to !, name)
1715        return m
1716
1717    def secondaryConstructedTypeFor(box as Box, gpToType as Dictionary<of GenericParam, IType>) as IType is override
1718        at = ArrayType(_wrappedType.secondaryConstructedTypeFor(box, gpToType))
1719        at.bindInh
1720        at.bindInt
1721        return at
1722
1723    def suggestionsForBadMemberName(name as String) as List<of String> is override
1724        return .box.suggestionsForBadMemberName(name)
1725
1726    def _bindInh
1727        base._bindInh
1728        if .compiler  # will be nil during unit tests
1729            #iclone = .compiler.libraryType('ICloneable')
1730
1731            #icoll = (.compiler.libraryType('System.Collections.Generic.ICollection<of>') to Box).constructedTypeFor([.theWrappedType])
1732            #icoll = (.compiler.libraryType('ICollection<of>') to Box).constructedTypeFor([.theWrappedType])
1733            icoll = .compiler.collectionOfType.constructedTypeFor([.theWrappedType])
1734            ienum = .compiler.enumerableOfType.constructedTypeFor([.theWrappedType])
1735            _ilistOf = .compiler.ilistOfType.constructedTypeFor([.theWrappedType]) to Interface
1736            interfaces = [icoll to ITypeProxy, ienum]  # TODO:, _ilistOf]  -- problems with cobra -ert:yes hello and extension method String.split
1737            iclone = .compiler.libraryType('ICloneable')
1738            interfaces.insert(0, iclone to ITypeProxy)
1739            _box = Class(Token.empty, Token.empty, '[.getType.name]_[.serialNum]', List<of IType>(), List<of String>(), AttributeList(), nil, interfaces, List<of ITypeProxy>(), nil)
1740            # TODO: make members based on System.Array
1741            indexer = Indexer(Token.empty, Token.empty, _box, r'[]', [Param(Token('', 1, 1, 1, 'ID', 'index', nil), .compiler.intType)], _wrappedType, List<of String>(), AttributeList(), '')
1742            _box.addDecl(indexer)
1743            lengthProp = Property(Token.empty, Token.empty, _box, 'length', .compiler.intType, List<of String>(), AttributeList(), '')
1744            _box.addDecl(lengthProp)
1745            _box.bindInh
1746            _superType = _box
1747
1748    def _bindInt
1749        base._bindInt
1750        _box.bindInt
1751   
1752    def _bindImp
1753        base._bindImp
1754        _box.bindImp
1755
1756
1757class VariType inherits ArrayType is partial
1758    """
1759    Represents the type for variable number of arguments:
1760        def sumInts(nums as vari int)
1761    Not valid for non-parameters such as locals and class fields.
1762    """
1763
1764    cue init(wrappedType as IType)
1765        base.init(wrappedType)
1766
1767    get englishName as String is override
1768        return 'variable args type'
1769
1770    get innerType as IType? is override
1771        return _wrappedType
1772
1773    get name as String is override
1774        return 'vari ' + _wrappedType.name
1775
1776    def _bindInh
1777        base._bindInh
1778
1779    def _bindInt
1780        base._bindInt
1781
1782    def secondaryConstructedTypeFor(box as Box, gpToType as Dictionary<of GenericParam, IType>) as IType is override
1783        at = VariType(_wrappedType.secondaryConstructedTypeFor(box, gpToType))
1784        at.bindInh
1785        at.bindInt
1786        return at
1787
1788
1789class UnspecifiedType
1790    is partial
1791    inherits CobraType
1792    """
1793    This is for the compiler's internal use.
1794    See CobraParser.localVarDecl and the methods that use it.
1795    """
1796
1797    get englishName as String is override
1798        return 'unspecified'
1799
1800    get isReference as bool is override
1801        return true
1802
1803
1804extend IType
1805
1806    def isDynamicOrPassThrough as bool
1807        return this inherits DynamicType or this inherits PassThroughType
1808
1809    def isNilableAndDescendantOf(otherType as IType) as bool
1810        return this inherits NilableType and .nonNil.isDescendantOf(otherType)
1811
1812    def isEnumerable as bool
1813        if this inherits NilableType, return .nonNil.isEnumerable
1814        tp = Node.getCompiler  # 'tp' for 'type provider'
1815        if .isDescendantOf(tp.enumerableType), return true
1816        enumerableOfType = tp.enumerableOfType
1817        if .isDescendantOf(enumerableOfType), return true
1818        type = this
1819        if type inherits Box
1820            return type.constructedTypeOf(enumerableOfType) is not nil
1821        if .isSequenceLike, return true
1822        return false
1823       
1824    def isSequenceLike as bool
1825        """
1826        Returns true if the receiver is like a sequence, such as being an actual array, list, string, or a nilable version thereof.
1827        The dynamic type will also return true because at compile-time, dynamic is considered to be like everything.
1828        Requires Node.getCompiler
1829        """
1830        type = this
1831        if type inherits NilableType
1832            return type.nonNil.isSequenceLike
1833        # TODO: check for ISliceable which would have a .getSlice
1834        tp = Node.getCompiler  # 'tp' for 'type provider'
1835        if type.isDescendantOf(tp.stringType)
1836            return true
1837        # if type.isDescendantOf(tp.arrayType)
1838        if type inherits ArrayType
1839            return true
1840        if type.isDescendantOf(tp.ilistType)
1841            return true
1842        genericList = tp.listOfType
1843        if type.isDescendantOf(genericList)
1844            return true
1845        if type inherits Box
1846            if type.genericDef is genericList
1847                return true
1848        genericIList = tp.ilistOfType
1849        if type.isDescendantOf(genericIList)
1850            return true
1851        if type inherits Box
1852            if type.genericDef is genericIList
1853                return true
1854        if type.isDynamic
1855            return true
1856        return false
1857
1858    def isDictionaryLike as bool
1859        """
1860        Returns true if the receiver is like a dictionary, such as being an actual dictionary type or a nilable version thereof.
1861        The dynamic type will also return true because at compile-time, dynamic is considered to be like everything.
1862        Requires Node.getCompiler
1863        """
1864        type = this
1865        if type inherits NilableType
1866            return type.nonNil.isDictionaryLike
1867        tp = Node.getCompiler  # 'tp' for 'type provider' # TODO? expand ITypeProvider to cover idictionaryType, dictionaryOfType, idictionaryOfType
1868        if type.isDescendantOf(tp.idictionaryType)
1869            return true
1870        genericDict = tp.dictionaryOfType
1871        if type.isDescendantOf(genericDict)
1872            return true
1873        if type inherits Box
1874            if type.genericDef is genericDict
1875                return true
1876        genericIDict = tp.idictionaryOfType
1877        if type.isDescendantOf(genericIDict)
1878            return true
1879        if type inherits Box
1880            if type.genericDef is genericIDict
1881                return true
1882        if type.isDynamic
1883            return true
1884        return false
1885
1886
1887class TypeUtil
1888    """
1889    If the utility involves primarily one instance of IType, or an instance of IType is the logical
1890    "receiver" of a message, then add the utility method to "extend IType" above.
1891    """
1892   
1893    shared
1894
1895        def dictionaryOf(genericParams as List<of IType>, typeArgs as IList<of IType>) as Dictionary<of GenericParam, IType>
1896            """
1897            Create a dictionary from the generic params to their effective type.
1898            Each type arg must be a GenericParam.
1899            Used by generic boxes and generic methods.
1900            """
1901            require
1902                typeArgs.count > 0
1903            ensure
1904                result.count == typeArgs.count
1905            body
1906                gpToType = Dictionary<of GenericParam, IType>()
1907                for i in typeArgs.count
1908                    if (p = genericParams[i]) inherits GenericParam
1909                        gpToType[p] = typeArgs[i]
1910                    else
1911                        throw FallThroughException(p)
1912                return gpToType
1913
1914        def keyForTypeArgs(typeArgs as IList<of IType>) as String
1915            """
1916            Returns a string that uniquely names the given type arguments.
1917            Can be used as key in a dictionary-based cache.
1918            Typically used in generics for caching the constructions of the generic (whether box or method).
1919            """
1920            require
1921                typeArgs.count > 0
1922            ensure
1923                result <> ''
1924            body
1925                # old key computation is incorrect: key = Utils.join(',', for type in typeArgs get type.name)
1926                # it doesn't distinguish two different types with the same name (such as a generic param T which may be passed in via a subclass or generic method)
1927                sb = StringBuilder()
1928                for type in typeArgs
1929                    # note: wrapped types like NilableType are not kept unique by the compiler, so we cannot use their serial number down below
1930                    if type inherits WrappedType
1931                        suffix = type.suffix
1932                        type = type.theWrappedType
1933                    else
1934                        suffix = ''
1935                    if sb.length, sb.append(',')
1936                    sb.append('[type.serialNum]-[type.name][suffix]')  # the serial num is necessary. the name is just a convenience when debugging
1937                return sb.toString
Note: See TracBrowser for help on using the browser.