Wiki

root/cobra/trunk/Source/Boxes.cobra

Revision 2631, 66.8 KB (checked in by Charles.Esterbrook, 5 months ago)

JVM back-end progress.
credit:hopscc

  • Property svn:eol-style set to native
Line 
1use System.Reflection
2
3
4class Box
5    is abstract, partial
6    inherits Container<of IBoxMember>
7    implements IType, IParentSpace, INameSpaceMember, IBoxMember
8    """
9    The abstract base class for:
10        * Class
11        * Interface
12        * Struct
13    These are collectively known as "boxes".
14    Note that of all the types, only Boxes can be generic. Which makes them special.
15    """
16
17    # TODO: need to override greatestCommonDenominatorWith() to handle base interfaces
18
19    var _genericParams as List<of IType>  # as in generic parameters
20    var _genericDef as Box?
21    var _constructedTypes as Dictionary<of String, Box>?
22
23    var _baseClass as Class?
24    var _baseInterfaceProxies as List<of ITypeProxy>
25    var _baseInterfaces as List<of Interface>
26
27    var _overloads as List<of MemberOverload>
28    var _nextPrivateSerialNumber = 1001
29
30    var _attribs as AttributeList
31
32    var _invariants as List<of Expr>
33    var _testMethods as List<of TestMethod>
34
35    var _nativeType as NativeType?
36    var _needScanNativeType as bool
37    var _membersToUnNil as String?
38
39    cue init(token as IToken, idToken as IToken, name as String, paramList as List<of IType>, isNames as String*, attribs as AttributeList, baseInterfaceNodes as List<of ITypeProxy>, docString as String?)
40        base.init(token, name, isNames, docString)
41        _idToken = idToken
42        _attribs = attribs
43        _genericParams = paramList
44        for i in _genericParams.count
45            p = _genericParams[i]
46            if p inherits GenericParam
47                p.index = i
48                p.parentDefinition = this
49        _baseInterfaceProxies = baseInterfaceNodes
50        _baseInterfaces = List<of Interface>()
51        _overloads = List<of MemberOverload>()
52        _invariants = List<of Expr>()
53        _testMethods = List<of TestMethod>()
54
55    def _initNativeType(t as NativeType)
56        ensure .needScanNativeType
57        _nativeType = t
58        _needScanNativeType = true
59        assert .compiler
60        .backEnd.scanGenericArgs(this)  # convert any generic args from back-end form to Cobra data structures
61               
62    def addMinFields
63        base.addMinFields
64        .addField('didBindInh', .didBindInh)
65        .addField('isGeneric', .isGeneric)
66        .addField('isGenericDef', .isGenericDef)
67        .addField('needsConstruction', .needsConstruction)
68
69    def addRefFields
70        base.addRefFields
71        .addField('genericDef', _genericDef)
72        .addField('baseClass', _baseClass)
73        .addField('nativeType', .nativeType)
74
75    def addSubFields
76        base.addSubFields
77        .addField('genericParams', _genericParams)
78        .addField('baseInterfaces', _baseInterfaces)
79        .addField('baseInterfaceProxies', _baseInterfaceProxies)
80
81    def toTraceString as String
82        sb = StringBuilder('[.getType.name]([.name], [.serialNum], ')
83        if _genericParams.count
84            sb.append('genericParams=[CobraCore.toTechString(_genericParams)], ')
85        if not .didBindInh, sb.append('not ')
86        sb.append('didBindInh, ')
87        if not .didBindInt, sb.append('not ')
88        sb.append('didBindInt, ')
89        sb.append('nativeType=[.nativeType]')
90        sb.append(')')
91        return sb.toString
92
93    get attributes as AttributeList is override
94        return _attribs
95
96    def allBaseTypes as Box*
97        require .didBindInh
98        if .baseClass
99            yield .baseClass to !
100            for bt in .baseClass.allBaseTypes, yield bt
101        for bi in .baseInterfaces
102            yield bi
103            for bt in bi.allBaseTypes, yield bt
104       
105    def allMembers as IList<of IBoxMember>
106        imembers = List<of IBoxMember>()
107        members = List<of IBoxCodeMember>()
108        _allMembers(imembers, members)
109        _allExtensionMembers(imembers, members)
110        return imembers
111
112    def _allMembers(imembers as IList<of IBoxMember>, members as IList<of IBoxCodeMember>)
113        for imember in .declsInOrder
114            if imember inherits IBoxCodeMember
115                if not any for m in members get m.matchesSignature(imember)
116                    imembers.add(imember)
117                    members.add(imember)
118            else
119                imembers.add(imember)
120        for box in .allBaseTypes
121            box._allMembers(imembers, members)
122
123    def _allExtensionMembers(imembers as IList<of IBoxMember>, members as IList<of IBoxCodeMember>)
124        if .compiler and .compiler.nameSpaceStack.count
125            .prepIfNeeded
126            for ns in .compiler.nameSpaceStack
127                _allExtensionMembers(ns, imembers, members)
128            for box in .allBaseTypes
129                box._allExtensionMembers(imembers, members)
130            for ud in .compiler.nameSpaceStack.peek.useDirectives
131                _allExtensionMembers(ud.boundNameSpace, imembers, members)
132
133    def _allExtensionMembers(ns as NameSpace, imembers as IList<of IBoxMember>, members as IList<of IBoxCodeMember>)
134        for decl in ns.declsInOrder
135            if decl inherits Extension
136                ext = decl
137                ext.prepIfNeeded
138                if ext.extendedBox == this
139                    for imember in ext.declsInOrder
140                        if imember inherits IBoxCodeMember
141                            if not any for m in members get m.matchesSignature(imember)
142                                imembers.add(imember)
143                                members.add(imember)
144                        else
145                            imembers.add(imember)
146                else if .isGeneric and ext.isGeneric
147                    # see Extension.extensionMemberFor
148                    cto = .constructedTypeOf(ext.extendedBox.genericDef to !)
149                    if cto and .isDescendantOf(cto to !)
150                        for imember in ext.constructedTypeFor(cto.genericParams).declsInOrder
151                            if imember inherits IBoxCodeMember
152                                if not any for m in members get m.matchesSignature(imember)
153                                    imembers.add(imember)
154                                    members.add(imember)
155                            else
156                                imembers.add(imember)                               
157
158    get baseClass from var
159
160    get baseInterfaces from var
161
162    get baseInterfaceProxies from var
163
164    get canDeclNamesDifferOnlyByCase as bool is override
165        return .nativeType is not nil
166
167    get canHaveDetailedStackTrace as bool
168        """
169        Normally returns true, but will return false for some key run-time support classes that help *implement* the DST.
170        Otherwise, those classes could easily cause infinite recursion / stack overflow.
171        Examples include CobraFrame and SourceSite.
172
173        Note that returning true does not mean that the -dst option is turned on.
174        Returning true only means that this box *can* have code instrumentation for DST.
175        """
176        if .name in @['CobraFrame', 'SourceSite']
177            return false  # otherwise, stack overflow
178        for attribute in .attributes
179            if attribute.name == 'DetailedStackTraceAttribute'
180                return false
181        # probably don't need the following, because this method is only invoked against source code
182        if .nativeType
183            for attrib in .nativeType.customAttributes
184                if attrib inherits DetailedStackTraceAttribute
185                    if not attrib.flag
186                        trace attrib, this
187                        return false
188        if .baseClass
189            return .baseClass.canHaveDetailedStackTrace
190        else
191            return true
192
193    get canHaveStatements as bool
194        """
195        Returns true if the members of the box can contain statements.
196        Returns true by default.
197        Interfaces return false (in contrast to classes, structs, mixins and extensions).
198        """
199        return true
200
201    get constructedTypes as IDictionary<of String, Box>
202        """
203        The return value is a shallow copy to prevent outside modification of a generic's constructedTypes cache.
204        This property exists primarily for debugging/display.
205        """
206        return if(_constructedTypes, Dictionary<of String, Box>(_constructedTypes), Dictionary<of String, Box>())
207
208    get defaultAccessLevel as String is override
209        return 'public'
210
211    get idToken from var as IToken
212
213    get isFromBinaryLibrary as bool
214        """
215        Returns true if this box was read from a binary library such as a .NET assembly (.dll, .exe)
216        or Java binary (.class, .jar) as opposed to be source based. This is independent of
217        language. If the binary was originally written in Cobra, this still returns true.
218        """
219        ensure
220            .isSystemObjectClass implies result
221            result implies .nativeType or (.genericDef and .genericDef.nativeType)
222            not result implies .nativeType is nil
223        body
224            return _nativeType or (_genericDef and _genericDef._nativeType)
225
226    get isShared as bool is override
227        # When a box is declared inside another box (for example, nested classes), you can say: A.B
228        # DotExpr needs to know this, hence return true for .isShared
229        return true
230
231    get invariants from var
232        has Subnodes
233
234    get hasInvariants as bool
235        """
236        Returns true if the box has any invariant conditions whether directly or through inheritance.
237        """
238        if _invariants.count
239            return true
240        if _baseClass
241            return _baseClass.hasInvariants
242        else
243            return false
244
245    # TODO: cache
246    get isSystemObjectClass as bool is override
247        #return _baseClass is nil and .name == 'Object' and .parentNameSpace and .parentNameSpace.fullName == 'System'
248        return _nativeType and _nativeType.isSystemObjectClass
249
250    get isSystemTypeClass as bool is override
251        #return .name == 'Type' and .parentNameSpace and .parentNameSpace.fullName == 'System'
252        return _nativeType and _nativeType.isSystemTypeClass
253
254    pro membersToUnNil from var
255
256    get nativeType from var
257
258    get needScanNativeType from var
259   
260    get nestedBoxes as IEnumerable<of Box>
261        for decl in _declsInOrder
262            if decl inherits Box
263                yield decl
264
265    pro parentNameSpace as NameSpace?
266        get
267            return base.parentNameSpace
268        set
269            # a box needs to be tied to its local namespace, not the unified one
270            assert (value and .token.text <> '(empty)') implies not value.isUnified
271            base.parentNameSpace = value
272
273    get overloads from var
274
275    get nameWithGenericParams as String
276        if _genericParams.count
277            name = StringBuilder(.rootName+'<of ')
278            sep = ''
279            for gp in _genericParams
280                name.append(sep)
281                name.append(gp.name)
282                sep = ', '
283            name.append('>')
284            return name.toString
285        else
286            return .name
287
288    get rootName as String
289        ensure
290            '<' not in result
291            .name.startsWith(result)
292        body
293            name = .name
294            i = name.indexOf('<')
295            if i <> -1  # List<of>, Dictionary<of,>
296                name = name[0:i]
297            return name
298
299    get qualifiedRootName as String
300        require
301            .parentNameSpace
302        ensure
303            not result.startsWith('.')
304            not result.endsWith('.')
305            not .parentNameSpace.isRoot implies '.' in result
306        body
307            return _qualifiedPrefix + .rootName
308
309    get qualifiedName as String
310        return _qualifiedPrefix + .name
311
312    get _qualifiedPrefix as String
313        ensure
314            result.length implies result.endsWith('.')
315            ' ' not in result
316        body
317            nameSpaces = List<of NameSpace>()
318            ns = .parentNameSpace
319            while ns and not ns.isRoot
320                nameSpaces.add(ns to !)
321                assert ns is not ns.superNameSpace
322                ns = ns.superNameSpace
323            nameSpaces.reverse
324            prefix = (for ns in nameSpaces get ns.name).join('.')
325            if prefix.length
326                prefix += '.'
327            return prefix
328
329    get superType as IType? is override
330        or require true
331        if not .didBindInh, .bindInh
332        assert .didBindInh
333        return _baseClass
334
335    pro testMethods from var
336
337    get isExtern as bool
338        return 'extern' in _isNames
339
340    def constructedTypeOf(box as Box) as Box?
341        require
342            .didBindInh
343            box.isGenericDef
344        ensure
345            result implies result is this or result in .allBaseTypes
346        body
347            if .genericDef is box, return this
348            for bt in .allBaseTypes, if bt.genericDef is box, return bt
349            return nil
350
351    def isDescendantOfInterface(inter as Interface) as bool
352        require .didBindInh or .nativeType
353        _prepLibraryBox
354        if this == inter, return true
355        if _baseInterfaces.count == 0 and _baseInterfaceProxies.count, .bindInh
356        if .compiler, inter.bindInh
357        assert .serialNum <> inter.serialNum
358        assert _baseInterfaceProxies.count == 0 or _baseInterfaces.count == _baseInterfaceProxies.count
359        for bit in _baseInterfaces
360            if bit.isDescendantOfInterface(inter)
361                return true
362        return false
363
364    def allMembersForName(name as String) as Set<of IBoxMember>
365        """
366        Returns a set of all members with a given name, including inherited members,
367        with no duplicates and no guaranteed order.
368        """
369        return Set<of IBoxMember>(_allMembersForName(name))
370       
371    def _allMembersForName(name as String) as IBoxMember*
372        decl = .declForName(name)
373        if decl, yield decl
374        if .baseClass
375            for m in .baseClass._allMembersForName(name)
376                yield m
377        for inter in _baseInterfaces
378            for m in inter._allMembersForName(name)
379                yield m
380
381    def cobraSourceSignature as String
382        return .idString
383
384    def interfaceMemberForName(name as String) as IBoxMember?
385        m = .declForName(name)
386        if m, return m
387        for inter in _baseInterfaces
388            m = inter.interfaceMemberForName(name)
389            if m, break
390        return m
391
392    def makeNextPrivateSerialNumber as int
393        n = _nextPrivateSerialNumber
394        _nextPrivateSerialNumber += 1
395        return n
396
397    def mergedIntoPartialBox(newBox as Box)
398        require
399            newBox is not .parentBox
400            newBox.name == .parentBox.name
401        body
402            _parentBox = newBox
403
404    get canAccessMemberForName as bool is override
405        return .didBindInh or (.nativeType and (.compiler.isBindingInt or .compiler.isBindingImp))
406
407    def extensionMemberFor(box as Box, name as String) as IMember?
408        # in the future, in support of C# 3.0, it will be necessary to implement this
409        # to find the static extension methods like "static void Foo(this String s, ...)",
410        # or for Extensions to be instantiated when DLLs are scanned
411        return nil
412
413    def mangleName(name as String) as String
414        return name
415
416    def memberForName(name as String) as IMember? is override
417        if .compiler and .compiler.nodeStack.count and (.compiler.nodeStack.peek to Node).isBindingImp
418            return __memberForNameIncludingExtensions(name)
419        else
420            return __memberForName(name)
421
422    def __memberForName(name as String) as IMember?
423        .prepIfNeeded
424        return base.memberForName(name)
425   
426    def __memberForNameIncludingExtensions(name as String) as IMember?
427        m = __memberForName(name)
428        if m is nil and .compiler
429            # look for an extension member, but it has to be accessible according to namespaces
430            if .compiler.nameSpaceStack.count
431                # don't need to go through the whole namespace stack because the namespace will check its parent
432                m = .compiler.curNameSpace.extensionMemberFor(this, name)
433        return m
434
435    def suggestionsForBadMemberName(name as String) as List<of String>
436        suggs = base.suggestionsForBadMemberName(name)
437        if _baseClass
438            suggs.addRange(_baseClass.suggestionsForBadMemberName(name))
439        for bi in _baseInterfaces
440            suggs.addRange(bi.suggestionsForBadMemberName(name))
441
442        # eliminate duplicates
443        suggs = List<of String>(Set<of String>(suggs))
444       
445        # sort
446        suggs.sort(ref _compareMemberNames)
447
448        # okay to sort by alpha, but if a name differs only by case, put it up front
449        lowerName = name.toLower
450        for i in suggs.count
451            if suggs[i].toLower == lowerName
452                sugg = suggs[i]
453                suggs.removeAt(i)
454                suggs.insert(0, sugg)
455                break
456        return suggs
457
458    def _compareMemberNames(a as String, b as String) as int
459        ensure result in {-1, 0, +1}
460        # put '_foo' after 'foo'
461        if a.startsWith('_') and not b.startsWith('_')
462            diff = a[1:].compareTo(b)
463            return if(diff == 0, 1, diff)
464        if not a.startsWith('_') and b.startsWith('_')
465            diff = a.compareTo(b[1:])
466            return if(diff == 0, -1, diff)
467        return a.compareTo(b)
468   
469    def prepIfNeeded
470        if _nativeType, _prepLibraryBox
471        else, .completeMemberConstructionIfNeeded
472
473    def registerOverload(ol as MemberOverload)
474        require
475            ol.name.length
476            ol not in _overloads
477        body
478            _overloads.add(ol)
479            _declsByName[ol.name] = ol
480            _declsByNameCI[ol.name.toLower] = ol
481
482    def addDeclFromOverload(decl as IBoxMember, ol as MemberOverload)
483        require
484            ol in .overloads
485            decl.name == ol.name
486        body
487            _declsInOrder.add(decl)
488
489    def paramForName(name as String) as IType?
490        # linear search is okay here since generic arg count is usually 0, 1 or 2
491        for param in _genericParams, if name == param.name, return param
492        return nil
493
494    def symbolForName(name as String, haveThis as bool) as IMember?
495        return .symbolForName(name, haveThis, true)
496
497    def symbolForName(name as String, haveThis as bool, firstCall as bool) as IMember?
498        """
499        Unlike the inherited .declForName, this method follows the
500        inheritance chain and provides options for haveThis.
501       
502        TODO:
503        This method should be protected, but then this expression in the override in Extension:
504            .extendedBox._symbolForName(name, haveThis, firstCall)
505        Gives this error message in C#:
506            Cannot access protected member "Box._symbolForName(string, bool, bool)" via a qualifier of type "Box"; the qualifier must be of type "Extension" (or derived from it)
507        Is this a limitation of C# or CLR? Do Java, C++ and D have the same restruction?
508        """
509        if firstCall and name == _name
510            return this
511        p = .paramForName(name)
512        if p
513            if haveThis
514                .throwError('Cannot refer to a generic parameter ("[name]") through `this`.')
515            else
516                return p
517        x = .declForName(name) to IMember?
518        if x is nil and _baseClass
519            # try base class to look for nested types
520            x = _baseClass.symbolForName(name, haveThis, false)
521        if x is nil
522            x = .interfaceMemberForName(name)  # TODO: can this be guarded by haveThis? can interfaces have enum decls and sigs?
523        if x and not haveThis
524            if x.requiresThis, x = nil
525        if x is nil and firstCall
526            # TODO: can this be guarded by haveThis
527            # try parent box or namespace because they are in lexical scope
528            nameSpace = .parentNameSpace
529            if nameSpace is nil
530                # happens for nested boxes which currently means sig/delegate inside a class
531                # when classes can really be nested, or generic sigs are supported, we'll need some more work here
532                if .parentBox
533                    x = .parentBox.symbolForName(name, haveThis, firstCall)
534            else
535                if not .name.startsWith('ArrayType_')  # TODO: axe this guard when ArrayType.memberForName's TODO to read the Array library type is done
536                    if .didBindInt
537                        assert nameSpace
538                assert not nameSpace.isUnified
539                x = nameSpace.symbolForName(name)
540        return x
541
542    ## INamedNode
543
544    get typeForIdentifier as IType is override
545        assert .compiler
546        return .compiler.typeType
547
548    get typeForReceiver as IType is override
549        return this
550
551    ## IType
552
553    get innerType as IType? is override
554        .prepIfNeeded
555        if this is .compiler.stringType  # TODO: hacky. solution is to look at the specific type of .current property of enumerator. make a test case that shows that
556            return .compiler.charType
557# TODO: can a for loop go through an IEnumerator<of>?
558#       if .isConstructed and .genericDef is .compiler.enumeratorOfType
559#           return .genericParams[0]
560        getEnum as IMember?
561        if .declForName('getEnumerator') is nil
562            # Comes up for IList<of T> which has multiple 'getEnumerator' methods in ancestor interfaces
563            for member in .allMembersForName('getEnumerator')
564                if member inherits Method and member.parentBox.isGeneric
565                    getEnum = member
566                    break
567        if getEnum is nil
568            getEnum = .symbolForName('getEnumerator', true)
569        if getEnum
570            assert getEnum.didBindInt
571            # can have two getEnumerators -- one generic and the other not. favor the generic one
572            if getEnum inherits MemberOverload
573                for member in getEnum.members
574                    if member inherits Method
575                        if member.resultType <> .compiler.objectType
576                            # implementing IEnumerable<of T> which requires two `getEnumerator` members
577                            getEnum = member
578                            break
579            rt = getEnum.resultType
580            if rt.isDynamicOrPassThrough
581                return rt
582            rt = rt.nonNil  # nilable is not a concern; unwrap it
583            if rt inherits Box and (rt to Box).isGeneric
584                # don't take the first argument of the result type -- that won't work for a nested type in a generic class, like ValueCollection, which gets the generic params of its parents
585                rt = rt.memberForName('current').resultType
586                return rt
587            else
588                if rt.isDescendantOf(.compiler.dictEnumeratorType)
589                    return rt.memberForName('entry').resultType
590                if rt.isDescendantOf(.compiler.enumeratorType)
591                    rt = rt.memberForName('current').resultType
592                    if rt.nonNil.isSystemObjectClass
593                        # can we do better with indexer returnType? (e.g. MatchCollection)
594                        indexer = .symbolForName(r'[]', true)
595                        if indexer, rt = indexer.resultType
596                    return rt
597                else
598                    throw FallThroughException({'rt': rt, 'this': this, 'getEnum': getEnum})
599        return nil
600
601    def isEquatableTo(t as IType) as bool
602        r = base.isEquatableTo(t)
603        if not r and t inherits CharType and this is .compiler.stringType  # TODO: hacky? could this be determined by looking for a static == operator overload?
604            r = true
605        if not r and ('dynamic' in .name or 'dynamic' in t.name)  # TODO: hacky
606            r = true
607        if not r and t inherits ArrayType and (t to ArrayType).isEquatableTo(this)  # TODO: hacky
608            r = true
609        return r
610
611    def isComparableTo(t as IType) as bool
612        r = base.isComparableTo(t)
613        if not r and t inherits CharType and this is .compiler.stringType  # TODO: hacky? could this be determined by looking for a static == operator overload?
614            r = true
615        if not r and ('dynamic' in .name or 'dynamic' in t.name)  # TODO: hacky
616            r = true
617        return r
618
619    ## Binding
620    def _scanNativeType
621        #print '_scanNativeType ', .name
622        assert .compiler
623        .backEnd.scanNativeType(this)  # Convert library (native) info to Cobra data structures
624       
625    def _stackPush
626        base._stackPush
627        if .compiler, .compiler.boxStack.push(this)
628   
629    def _stackPop
630        base._stackPop
631        if .compiler, .compiler.boxStack.pop
632   
633    def bindInh
634        base.bindInh
635        # nested types
636        if .didBindInh and not .isBindingInh
637            for decl in .declsInOrder, if decl implements IType, decl.bindInh
638       
639    def _bindInh
640        base._bindInh
641        if _needScanNativeType, _scanNativeType
642        _checkModifiers
643        _bindBase
644        # structs, classes and interfaces can all have 0 or more interfaces they inherit/implement
645        if _baseInterfaceProxies.count <> _baseInterfaces.count  # otherwise, already done
646            assert _baseInterfaces.count == 0
647            for interfaceProxy in _baseInterfaceProxies
648                try
649                    baseWhat = interfaceProxy.realType
650                    if baseWhat inherits Interface
651                        _baseInterfaces.add(baseWhat)
652                    else
653                        _badInterfaceError(baseWhat)
654                catch ne as NodeException
655                    hadBaseInterfaceError = ne to ?
656                    .compiler.recordError(ne)
657        _checkForInheritanceCycles(this, Stack<of Box>())
658        if _baseClass, _baseClass.bindInh
659        for interf in _baseInterfaces, interf.bindInh
660
661        # .bindInh on the .nestedBoxes causes problems. ticket:127
662        # for box in .nestedBoxes, box.bindInh
663
664        # trace this, hadBaseInterfaceError, .baseInterfaceProxies, .baseInterfaces
665        assert hadBaseInterfaceError or .baseInterfaceProxies.count == 0 or .baseInterfaceProxies.count == .baseInterfaces.count, [.baseInterfaceProxies.count, .baseInterfaces.count]
666
667    def _checkModifiers
668        if 'readonly' in .isNames
669            .recordError('The keyword "readonly" does not apply to [Utils.pluralize(.englishName)].')
670
671    def _checkForInheritanceCycles(originalBox as Box, bases as Stack<of Box>)
672        if this in bases
673            names = for aBase in List<of Box>(Stack<of Box>(bases))[1:] get aBase.name
674            .throwError('Cyclical inheritance for "[.name]" with ancestor types [names.join(", ")] and back to [.name].')
675        else
676            bases.push(this)
677            if .baseClass, .baseClass._checkForInheritanceCycles(originalBox, bases)
678            for bi in .baseInterfaces, bi._checkForInheritanceCycles(originalBox, bases)
679            bases.pop
680
681    def bindInt as INode
682        if not .didBindInt and not .isBindingInt
683            # because DLL boxes get bindInh and bindInt on demand, check this:
684            if _genericDef
685                assert _genericDef is not this
686                if not _genericDef.didBindInt and not _genericDef.isBindingInt
687                    _genericDef.bindInt
688                assert _genericDef.didBindInt or _genericDef.isBindingInt
689            if .nativeType
690                _prepLibraryBox
691            else if not .didBindInh
692                .bindInh
693            if _genericDef
694                assert _genericDef is not this
695                assert _genericDef.didBindInt or _genericDef.isBindingInt
696        return base.bindInt
697
698    def _bindInt
699        # Note that .bindInt (not this method, _bindInt) already ensures that if this box is constructed, its generic def binds int *first*.
700        # Therefore, everthing below has already happened for a constructed box's generic def.
701        base._bindInt
702        if .isSystemObjectClass
703            assert .compiler
704            .backEnd.prepSystemObjectClass(this) # add any improvements to root Object
705        errorCount = .compiler.errors.count
706        if _needScanNativeType, _scanNativeType
707        if _baseClass
708            _baseClass.bindInt
709        for interf in _baseInterfaces
710            interf.bindInt
711        for param in _genericParams
712            param.bindInt
713        if not .isConstructed  # because constructed boxes are already taken care of by way of their generic type def
714            .unNilReturnTypes(this)
715        for attrib in _attribs
716            try
717                attrib.bindInt
718            catch ne as NodeException
719                .compiler.recordError(ne)
720        for invari in _invariants
721            invari.bindInt
722        _makeInitializers
723        hasError = false
724        for decl in List<of IBoxMember>(_declsInOrder)
725            assert not decl is this
726            .compiler.boxMemberStack.push(decl)
727            try
728                if decl inherits BoxMember
729                    if decl.parentBox is not this  # TODO: when does this happen
730                        continue
731                decl.bindInt
732            catch ne as NodeException
733                .compiler.recordError(ne)
734                hasError = true
735            finally
736                .compiler.boxMemberStack.pop
737        if not hasError
738            _finishOverloads
739            for tm in _testMethods
740                .compiler.boxMemberStack.push(tm)
741                try,     tm.bindInt
742                finally, .compiler.boxMemberStack.pop
743            if _constructedTypes
744                if .compiler.errors.count <= errorCount  # completing construction on constructed types leads to chaos if this generic def had errors during bind interface
745                    for ct in _constructedTypes.values.toList
746                        assert ct is not this
747                        ct.completeMemberConstructionIfNeeded
748                        ct.bindInt
749
750    def _bindBase
751        # invoked by _bindInt
752        _baseClass = .compiler.objectClass
753
754    def _badInterfaceError(type as IType)
755        .throwError('Cannot inherit "[type.name]" which is a [type.englishName].')
756
757    def _makeInitializers
758        pass
759
760    def _finishOverloads
761        # this method is broken out so Class can override and deal with inheritance and overloads
762        for ol in _overloads
763            try
764                ol.bindInt
765            catch ne as NodeException
766                .compiler.recordError(ne)
767
768    def _computeMatchingBaseMembers
769        base._computeMatchingBaseMembers
770        for decl in .declsInOrder
771            decl.computeMatchingBaseMembers
772
773    def _bindImp
774        base._bindImp
775        assert .didBindInt
776        for attrib in _attribs
777            try
778                attrib.bindImp
779            catch ne as NodeException
780                .compiler.recordError(ne)
781        for i in _invariants.count
782            invari = _invariants[i].bindImp
783            if invari.type is not .compiler.boolType
784                _invariants[i] = TruthExpr(invari).bindAll to Expr
785        # TODO: should be able to remove the following
786        for invari in _invariants
787            invari.bindImp
788        for decl in List<of IBoxMember>(_declsInOrder)
789            assert not decl is this
790            .compiler.boxMemberStack.push(decl)
791            try
792                if decl inherits BoxMember
793                    if decl.parentBox is not this
794                        continue
795                decl.bindImp
796            catch ne as NodeException
797                .compiler.recordError(ne)
798            finally
799                .compiler.boxMemberStack.pop
800        for ol in _overloads
801            try
802                ol.bindImp
803            catch ne as NodeException
804                .compiler.recordError(ne)
805        for tm in _testMethods
806            .compiler.boxMemberStack.push(tm)
807            try,     tm.bindImp
808            finally, .compiler.boxMemberStack.pop
809
810    def _prepLibraryBox
811        ensure .didBindInh
812        if _nativeType and not _didPrep
813            __prepLibraryBox
814           
815    var _didPrep as bool
816
817    def __prepLibraryBox
818        """
819        DLL types get bindInh & bindInt only on demand. (Otherwise reading system DLLs slows things down.)
820        """
821        require .nativeType
822        ensure .didBindInh
823        if _didPrep, return
824        _didPrep = true
825        if not .didBindInh
826            .bindInh
827            assert .didBindInh
828        if not .didBindInt and not .compiler.isBindingInh
829            .bindInt
830            assert .didBindInt
831
832    var _didUnNilReturnTypes as bool
833
834    get didUnNilReturnTypes as bool
835        if .isConstructed
836            return .genericDef.didUnNilReturnTypes
837        else
838            return _didUnNilReturnTypes
839
840    def unNilReturnTypes(box as Box)
841        if .compiler.isBindingInh
842            # because the .membersToUnNil properties won't even be set until the compiler starts .bindInt
843            return
844        if _didUnNilReturnTypes
845            return
846        _didUnNilReturnTypes = true
847        _unNilReturnTypes(box)
848
849    def _unNilReturnTypes(box as Box)
850        assert not _needScanNativeType
851        if box.membersToUnNil
852            for name in box.membersToUnNil.split
853                m = .declForName(name)  # using .memberForName here is unnecessary and could/would cause an infinite loop
854                if m
855                    m.unNilReturnType
856        # follow inheritance to look at ancestors' .membersToUnNil
857        if box.baseClass
858            _unNilReturnTypes(box.baseClass to !)
859        for interf in box.baseInterfaces
860            _unNilReturnTypes(interf)
861
862    ## Generics
863
864    def isAssignableTo(type as IType) as bool
865        .prepIfNeeded
866        r = base.isAssignableTo(type)
867        if not r
868            type = type.nonNil
869            if type inherits PrimitiveType
870                if type.systemAliasType == this
871                    return true  # example: this is Int32 and type is int
872            if type inherits Box
873                if (.isGeneric and type.isGeneric and .genericDef is type.genericDef) or (.isGenericDef and type.isGeneric and this is type.genericDef)
874                    # CC?: r = all for i, gp in .genericParams.numbered get gp.isAssignableTo(type.genericParams[i])
875                    # CC?: r = for i, gp in .genericParams.numbered get all gp.isAssignableTo(type.genericParams[i])
876                    i = 0
877                    r = true
878                    for gp in .genericParams  # CC: for i, gp in .genericParams.numbered
879                        if not gp.isAssignableTo(type.genericParams[i])
880                            r = false
881                            break
882                        i += 1
883                else if type.isGenericDef and .isGeneric and type is .genericDef
884                    r = type.isAssignableTo(this)
885        if not r
886            if type inherits StreamType
887                r = .isAssignableTo(type.box to !)
888        return r
889
890    get isConstructed as bool
891        return _genericDef is not nil
892
893    def isDirectConstructionOf(box as Box) as bool
894        """
895        Returns true if this type was directly constructed from the given box.
896        """
897        require
898            .didBindInh
899            box.isGenericDef
900        body
901            return .genericDef is box
902
903    def isIndirectConstructionOf(box as Box) as bool
904        """
905        Returns true if this type or any of its ancestor types
906        is a construction of the given generic type def.
907        """
908        require
909            .didBindInh
910            box.isGenericDef
911        body
912            return .constructedTypeOf(box) is not nil
913
914    get isGenericDef as bool
915        """
916        Returns true if this type is a definition of a generic type, and
917        therefore capable of making subsequent generic types via the
918        `constructedTypeFor` method. A generic type will have generic
919        parameters which are all GenericParam (as opposed to other types
920        such as `int` or a given class).
921        """
922        # TODO: make this more efficient, maybe by computing in the initializer
923        if _genericDef
924            return false
925        else if _genericParams.count
926            for param in _genericParams
927                if not param inherits GenericParam
928                    return false
929            return true
930        else
931            return false
932
933    get isGeneric as bool
934        """
935        Returns true if this type is a generic type which includes
936        generic type defs and open-or-closed constructed types. Note
937        that arrays of generic types and pointers to generic types will
938        return false.
939        """
940        return _genericParams.count > 0
941
942    get genericParams as List<of IType>
943        """
944        Return the list of generic params for this generic type. This
945        property requires that .isGenericDef is true.
946        """
947        require .isGeneric
948        return _genericParams
949
950    get genericDef as Box?
951        """
952        Returns the generic type definition for a constructed type (or nil if this type is not constructed).
953        """
954        return _genericDef
955
956    def extendedMethodGenericParams(genericParams as IList<of IType>) as IList<of IType>
957        """
958        This is a hook for Extension and Method which have to deal with extensions on generic classes.
959        """
960        ensure
961            old genericParams == genericParams
962            result.count >= genericParams.count
963        body
964            return genericParams
965
966    def constructedTypeFor(typeArgs as List<of IType>) as Box
967        require
968            .isGenericDef
969            .containsGenericParameters
970            typeArgs.count == .genericParams.count
971        ensure
972            result is not this and result.genericDef is this
973            result.genericParams == typeArgs
974            not result.isGenericDef
975        body
976            _prepLibraryBox
977
978            # the cache of constructed types has to come from the root generic type def or you end up with duplicate
979            # constructed types which is not only wasteful, but causes problems with inheritance tests
980            if .genericDef, return .genericDef.constructedTypeFor(typeArgs)
981
982            if _constructedTypes is nil, _constructedTypes = Dictionary<of String, Box>()
983           
984            key = TypeUtil.keyForTypeArgs(typeArgs)
985
986            if _constructedTypes.containsKey(key), return _constructedTypes[key]
987
988            assert not .isBindingInh
989
990            if not .didBindInh
991                assert not .didBindInt
992                .bindInh
993                assert not .didBindInt
994                if .nativeType
995                    _prepLibraryBox
996                    assert not .didBindInt or not .compiler.isBindingInh
997
998            assert _baseInterfaceProxies.count == _baseInterfaces.count
999
1000            t = .memberwiseClone to Box
1001            assert t is not this
1002            _constructedTypes[key] = t
1003            argNames = (for type in typeArgs get type.name).join(',')
1004            t._name = '[.rootName]<of [argNames]>'
1005            t._genericDef = this
1006            t._nativeType = nil  # The constructed type is really sourced from the generic def. Don't foster confusion with a reference to the original generic def's clr type (if there is one).
1007            t.cloneCollections
1008
1009            # set the contructed type args immediately or its ancestors will get the original generic args during _bindInt:
1010            for i in typeArgs.count
1011                t._genericParams[i] = typeArgs[i]
1012            assert t._constructedTypes is nil or t._constructedTypes.count == 0
1013
1014            if .didBindInt, t._completeConstruction(typeArgs)
1015            else, t._needsConstruction(typeArgs)
1016            assert t._constructedTypes is nil or t._constructedTypes.count == 0
1017
1018            return t
1019
1020    var _needs_typeArgs as List<of IType>?
1021        """
1022        When non-nil, this box is constructed from a generic *and* requires completion of its construction of members.
1023        """
1024
1025    def completeMemberConstructionIfNeeded
1026        if _needs_typeArgs
1027            assert not .isGenericDef
1028            if not .didBindInt and not .isBindingInt
1029                .bindInt  # this is required when inheriting from a constructed type such as "class Foo inherits List<of int>". Since "bind inheritance" happens prior to "bind interface", the base type will have been partially constructed without ever binding int.
1030            # TODO: compiler gives false warning for next line. see http://cobra-language.com/trac/cobra/ticket/41
1031            if _needs_typeArgs  # .no-warnings.
1032                typeArgs = _needs_typeArgs
1033                _needs_typeArgs = nil
1034                _completeConstruction(typeArgs)
1035
1036    get needsConstruction as bool
1037        return _needs_typeArgs is not nil
1038
1039    def _needsConstruction(typeArgs as List<of IType>)
1040        require
1041            .genericParams.count == typeArgs.count
1042        body
1043            _needs_typeArgs = typeArgs
1044
1045    def _completeConstruction(typeArgs as List<of IType>)
1046        """
1047        When this method is called, this instance is a constructed type, but its members (such as methods and properties) are still those of its generic type def.
1048        This method creates new members that are like the generic ones, but with the constructed type arguments substituted in.
1049        `.foo(item as T)` becomes `.foo(item as int)`
1050        """
1051        require
1052            .isConstructed
1053            .genericParams.count == typeArgs.count
1054            .didBindInt or .isBindingInt
1055            not .isGenericDef
1056            .genericDef
1057            .genericDef.didBindInt or .genericDef.isBindingInt
1058        body
1059            _genericDef.unNilReturnTypes(_genericDef to !)
1060            gpToType = TypeUtil.dictionaryOf(_genericDef.genericParams, typeArgs)
1061
1062            if _baseClass, _baseClass = _baseClass.secondaryConstructedTypeFor(this, gpToType) to Class
1063
1064            assert _baseInterfaceProxies.count == 0 or _baseInterfaceProxies.count == _baseInterfaces.count
1065            for i in _baseInterfaces.count
1066                _baseInterfaces[i] = _baseInterfaces[i].secondaryConstructedTypeFor(this, gpToType) to Interface
1067
1068            # construct the declarations
1069            _overloads = List<of MemberOverload>()
1070            newDecls = List<of IBoxMember>()
1071            # hmmm, is it really necessary to do the nested boxes before the other members?
1072            for decl in _declsInOrder
1073                if decl inherits Box
1074                    nd = decl.constructedTypeFor(typeArgs) to IBoxMember
1075                    newDecls.add(nd)
1076            for decl in _declsInOrder
1077                if decl inherits BoxMember
1078                    #if not decl.didBindInt # hops: fix for crash with generics and java before changeset 2576
1079                    #   print 'dbg: ', decl.name
1080                    #   decl.bindInt
1081                    nd = decl.constructedFor(this, gpToType)
1082                    assert nd <> decl
1083                    newDecls.add(nd)
1084                else if not decl inherits Box
1085                    newDecls.add(nd)
1086            _declsInOrder = List<of IBoxMember>()
1087            _declsByName = Dictionary<of String, IBoxMember>()
1088            _declsByNameCI = Dictionary<of String, IBoxMember>()
1089            for decl in newDecls
1090                if _declsByName.containsKey(decl.name)
1091                    overload = nil to MemberOverload?
1092                    other = _declsByName[decl.name]
1093                    if other inherits MemberOverload
1094                        overload = other
1095                    else if other implements IOverloadable
1096                        overload = MemberOverload(other)
1097                        .registerOverload(overload to !)
1098                    else
1099                        throw FallThroughException(other)
1100                    overload.addMember(decl to IOverloadable)
1101                else
1102                    _declsInOrder.add(decl)
1103                    _declsByName[decl.name] = decl
1104                    _declsByNameCI[decl.name.toLower] = decl
1105            # TODO: can this next statement can be axed since there is a separate "bind inheritance" phase?
1106            _finishOverloads
1107
1108    def secondaryConstructedTypeFor(box as Box, gpToType as Dictionary<of GenericParam, IType>) as IType is override
1109        if _genericParams.count == 0
1110            return this
1111        typeArgs = List<of IType>()
1112        params = .genericParams
1113        for param in params
1114            if param inherits GenericParam
1115                # doesn't work:
1116                # typeArgs.add(gpToType[param])
1117                found as GenericParam?
1118                for key as dynamic in gpToType.keys
1119                    if key.name == param.name
1120                        found = key
1121                # The generic param may not be found because, for example, it's declared for a
1122                # generic method and what's being constructed is the containing type; hence the
1123                # method's additional generic parameters are still generic.
1124                # see Tests/240-generics/400-generic-methods
1125                if found, typeArgs.add(gpToType[found])
1126                else, typeArgs.add(param)
1127            else
1128                typeArgs.add(param.secondaryConstructedTypeFor(box, gpToType))
1129        if .isGenericDef
1130            return .constructedTypeFor(typeArgs)
1131        else
1132            assert .genericDef.isGenericDef  # if this ever fails, we may just need to follow .genericDef back iteratively until we get to the real generic type def
1133            return .genericDef.constructedTypeFor(typeArgs)
1134
1135    def cloneCollections
1136        base.cloneCollections
1137        _genericParams = List<of IType>(_genericParams)  # TODO: Can I just say _genericParams.clone? Do I need the cast?
1138        _constructedTypes = nil
1139        _baseInterfaceProxies = List<of ITypeProxy>(_baseInterfaceProxies)
1140        _baseInterfaces = List<of Interface>(_baseInterfaces)
1141        # _overloads = List<of MemberOverload>(_overloads)  # these will be recreated
1142
1143    def typeForGenericParam(gp as GenericParam) as IType # TODO: is this needed for NilableType?
1144        """
1145        Returns the specific type arg that corresponds to the given generic
1146        parameter. Used to match the generic params in method, properties, etc. against
1147        the actual types in a constructed type.
1148        """
1149        require
1150            .isGeneric
1151            .genericParams.count
1152        body
1153            # TODO: When does this get called? Investigate this.
1154            return .genericParams[gp.index]
1155
1156    get containsGenericParameters as bool
1157        for param in _genericParams
1158            if param inherits GenericParam
1159                return true
1160            if param inherits Box  # CC: and <next if condition>
1161                if param.containsGenericParameters
1162                    return true
1163        return false
1164
1165
1166class ClassOrStruct inherits Box is abstract, partial
1167    """
1168    The abstract base class for Class and Struct.
1169    """
1170   
1171    var _addsProxies as List<of ITypeProxy>
1172
1173    cue init(token as IToken, idToken as IToken, name as String, paramList as List<of IType>, isNames as String*, attribs as AttributeList, implementsNodes as List<of ITypeProxy>, addsProxies as List<of ITypeProxy>, docString as String?)
1174        base.init(token, idToken, name, paramList, isNames, attribs, implementsNodes, docString)
1175        _addsProxies = addsProxies
1176
1177    def _bindInh
1178        # mixins act as interfaces (and more)
1179        for proxy in _addsProxies
1180            _baseInterfaceProxies.add(proxy)
1181        base._bindInh
1182
1183    def _bindInt
1184        # inject mixins
1185        for interf in _baseInterfaces
1186            if interf inherits Mixin
1187                interf.injectInto(this)
1188        base._bindInt
1189
1190    def _bindImp
1191        base._bindImp
1192        _checkForSuspiciousDefInit
1193
1194    def _checkForSuspiciousDefInit
1195        """
1196        If a class or struct has no explicit initializers and has a 'def init' and
1197        it is not an override, then give a warning.
1198        """
1199        if .isFromBinaryLibrary, return
1200        # have an explicit initializer?
1201        found = false
1202        for decl in .declsInOrder
1203            if decl inherits Initializer and not (decl to Node).isImplicit
1204                found = true
1205                break
1206        if found, return
1207        # have a non-overriding 'def init'?
1208        found = false
1209        for decl in .declsInOrder
1210            if decl inherits Method
1211                if decl.name == 'init' and not decl.isOverride
1212                    found = true
1213                    break
1214        if found
1215            .compiler.warning(decl to ISyntaxNode, 'Did you mean "cue init"?')
1216
1217
1218class Class
1219    is partial
1220    inherits ClassOrStruct
1221
1222    var _baseNode as ITypeProxy?
1223    var _subclasses = List<of Class>()
1224
1225    cue init(token as IToken, idToken as IToken, name as String, paramList as List<of IType>, isNames as String*, attribs as AttributeList, baseNode as ITypeProxy?, implementsNodes as List<of ITypeProxy>, addsProxies as List<of ITypeProxy>, docString as String?)
1226        base.init(token, idToken, name, paramList, isNames, attribs, implementsNodes, addsProxies, docString)
1227        _baseNode = baseNode
1228
1229    cue init(name as String, paramList as List<of IType>)
1230        """ public skeleton class - init with given name and paramlist -  no baseclass, attributes, interfaces or mixins."""
1231        .init(Token.empty, Token.empty, name, paramList, ['public'], AttributeList(), nil, List<of ITypeProxy>(), List<of ITypeProxy>(), '')
1232           
1233    cue init(nativeType as NativeType, backend as BackEnd)
1234        # TODO: fix native
1235        base.init(TokenFix.empty, TokenFix.empty, backend.cobraNameForNativeBoxName(nativeType.name), List<of IType>(), List<of String>(), AttributeList(), List<of ITypeProxy>(), List<of ITypeProxy>(), nil)
1236        if nativeType.baseType
1237            _baseNode = backend.nativeTypeProxy(nativeType.baseType to !)
1238        # to-do: keep the following? error? assertion
1239#       else if nativeType.name <> 'Object'
1240#           print 'No baseType for [nativeType.name]'
1241        _initNativeType(nativeType)
1242       
1243    def addRefFields
1244        base.addRefFields
1245        .addField('baseNode', _baseNode)
1246
1247    get isCallable as bool is override
1248        return true
1249
1250    def isDescendantOf(type as IType) as bool is override
1251        or require .nativeType
1252        _prepLibraryBox
1253        if this == type, return true
1254        if not .baseClass and _baseNode, .bindInh
1255        if .compiler, type.bindInh
1256        if type inherits Interface
1257            if .isDescendantOfInterface(type)
1258                return true
1259        baseClass = .baseClass
1260        assert baseClass is not this  # check for direct cycles
1261        if baseClass, return baseClass.isDescendantOf(type)
1262        return false
1263
1264    get isReference as bool is override
1265        return true
1266
1267    get subclasses from var
1268   
1269    pro baseNode from var
1270
1271    def declForName(name as String) as IBoxMember? is override
1272        """
1273        Handle get/set parts like "someProp.get" or "[].set"
1274        `computeMatchingBaseMember` in Members.cobra is at least one that returns this.
1275        """
1276        m = base.declForName(name)
1277        if m is nil and '.' in name
1278            isProperty = true
1279            if name.endsWith('.get'), part = 'g'
1280            else if name.endsWith('.set'), part = 's'
1281            else, isProperty = false  # example: 'System.Collections.IList.IsFixedSize'
1282            if isProperty
1283                pd = .memberForName(name[:-4])
1284                if pd inherits ProperDexer
1285                    branch part
1286                        on 'g', m = pd.getPart
1287                        on 's', m = pd.setPart
1288                    # TODO: cache the above back into the _decls
1289                # TODO: ? else, throw FallThroughException(...)
1290        return m
1291
1292    var _hackCheck = false
1293
1294    def memberForName(name as String) as IMember?
1295        # the next assertion fails for Tests\600-misc\404-implement-IEnumerable
1296        # could not fix. I'm confused. Something to do with generics. So bail on generics:
1297        # asserting .didBindInt is difficult because .memberForName gets invoked during bindInt
1298        # if not .isGeneric
1299        #   assert .didBindInt  # TODO: is this legit? if so, push up to Container
1300        # TODO: assert .didBindInh
1301
1302        if not _hackCheck
1303            _hackCheck = true
1304            if _nativeType and .name == 'String' and .parentNameSpace and .parentNameSpace.name == 'System' and name <> 'repeat'
1305                # Address the problem where `s.split(sep, 2)` binds to the wrong .split and therefore generates the wrong code.
1306                # The real fix is deeper and won't be done just now. to-do
1307                .memberForName('repeat')
1308
1309        m = base.memberForName(name)
1310        if m is nil and _baseClass, m = _baseClass.memberForName(name)
1311        if m is nil, m = .interfaceMemberForName(name)
1312        return m
1313
1314    def _bindBase is override
1315        if _baseNode
1316            possible = _baseNode.realType
1317            baseName = if(_baseNode inherits AbstractTypeIdentifier, (_baseNode to AbstractTypeIdentifier).name, nil)  # CC: if-inherits should work for expressions too
1318            if possible inherits Class
1319                _baseClass = possible
1320            else if possible inherits Interface
1321                assert baseName
1322                .throwError('The base "[baseName]" is an interface. Try "implements" instead of "inherits".')
1323            else if possible inherits Struct
1324                assert baseName
1325                .throwError('The base "[baseName]" is a struct. Classes cannot inherit from structs.')
1326            else
1327                assert baseName
1328                .throwError('The base class "[baseName]" is not actually a class, it is a "[possible.englishName]".')
1329        else
1330            t = .compiler.objectType to Class
1331            if this is not t  # don't want Object to inherit Object
1332                _baseClass = t
1333        if _baseClass
1334            _baseClass._subclasses.add(this)
1335
1336    def _bindInt
1337        # Note that the _baseClass is not told to bindInt. That would fail for classes in other namespaces and it's unnecessary
1338        base._bindInt
1339        if .isDescendantOf(.compiler.attributeType) and not .name.endsWith('Attribute')
1340            .compiler.warning(this, 'When attributes are declared, they should be suffixed with "Attribute".')
1341
1342    def _badInterfaceError(type as IType) is override
1343        msg = 'Cannot implement "[type.name]" which is a [type.englishName].'
1344        if type inherits Class, msg += ' Use "inherits" instead.'
1345        .throwError(msg)
1346
1347    def _makeInitializers
1348        base._makeInitializers
1349
1350        for decl in .declsInOrder, if decl inherits Initializer, return
1351
1352        if .compiler.options.boolValue('legacy-one-default-initializer')
1353            init = Initializer(.token, Token.empty, this, List<of Param>(), ['public'], AttributeList(), '', isImplicit=true)
1354            init.addStmt(DotExpr(.token.copy('DOT', '.'), 'DOT', BaseLit(.token.copy('BASE', 'base')), MemberExpr(.token.copy('ID', 'init'))))
1355            .addDecl(init)
1356        else
1357            # provide every initializer from the base class
1358            count = 0
1359            firstInit as Initializer?
1360            .baseClass.prepIfNeeded
1361            isFromBinaryLibrary = .baseClass.isFromBinaryLibrary
1362            inits = List<of Initializer>()
1363            for decl in .baseClass.declsInOrder
1364                if decl inherits Initializer
1365                    if decl.isPrivate, continue
1366                    if isFromBinaryLibrary and not decl.isPublic and not decl.isProtected, continue
1367                    if decl.isPublic or decl.isProtected
1368                        init = Initializer(.token, Token.empty, this, decl.params.clone, decl.isNames, decl.attributes, '', isImplicit=true)
1369                        inits.add(init)
1370                        if decl.params.count == 0
1371                            dotRight = MemberExpr(.token.copy('ID', 'init')) to Expr
1372                        else
1373                            args = for param in decl.params get IdentifierExpr(.token.copy('ID', param.name), param.name) to Expr
1374                            dotRight = CallExpr(.token.copy('ID', 'init'), 'init', args, true)
1375                        init.addStmt(DotExpr(.token.copy('DOT', '.'), 'DOT', BaseLit(.token.copy('BASE', 'base')), dotRight))
1376                        if count == 0
1377                            .addDecl(init)
1378                            firstInit = init
1379                        else if count == 1
1380                            overload = MemberOverload(firstInit)
1381                            .registerOverload(overload)
1382                            overload.addMember(init)
1383                        else
1384                            overload.addMember(init)
1385                        count += 1
1386            # System.Attribute's initializer is protected, making it awkward if a subclass does not define one. Therefore:
1387            if inits.count == 1 and inits[0].params.count == 0 and not inits[0].isPublic
1388                inits[0].changeToPublic
1389            # System.Collections.ObjectModel.KeyedCollection<of TKey, TValue> is also awkward as all of its initializers are protected
1390            else if inits.count > 1
1391                hasPublic = false
1392                for init in inits
1393                    if init.isPublic
1394                        hasPublic = true
1395                        break
1396                if not hasPublic
1397                    for init in inits
1398                        if init.params.count == 0
1399                            init.changeToPublic
1400                            break
1401
1402    get isSystemObjectClass as bool is override
1403        return _nativeType and _nativeType.isSystemObjectClass
1404
1405    get isSystemTypeClass as bool is override
1406        return _nativeType and _nativeType.isSystemTypeClass
1407
1408    def _finishOverloads
1409        # deal with inheritance and overloads
1410        assert _baseClass or .isSystemObjectClass
1411        if _baseClass
1412            #assert _baseClass.didBindInt
1413            for decl in List<of IBoxMember>(_declsInOrder)
1414                if decl inherits Method and not decl inherits Initializer  # TODO: I don't think this captures Indexers. Make a test case if needed, write: if decl.canBeOverloaded or if decl inherits ICanBeOverloaded
1415                    other = _baseClass.memberForName(decl.name)
1416                    if other
1417                        if decl inherits MemberOverload
1418                            overload = decl
1419                        else if decl implements IOverloadable
1420                            overload = MemberOverload(decl)
1421                            .registerOverload(overload)
1422                        else
1423                            throw FallThroughException(decl)
1424                        if other inherits MemberOverload
1425                            for member in other.members
1426                                overload.addInheritedMemberIfNoMatch(member)
1427                        else if other inherits IOverloadable
1428                            overload.addInheritedMemberIfNoMatch(other)
1429                        else
1430                            decl.recordError('Cannot declare a [decl.englishName] named "[decl.name]" because the base member "[decl.name]" is a [other.englishName].')
1431        base._finishOverloads
1432
1433    get englishName as String is override
1434        return 'class'
1435
1436
1437class Mixin
1438    is partial
1439    inherits Interface
1440
1441    # Hilarious! The implementation of Mixin would benefit from having mixins in the language
1442    # because we need them for class, struct and mixin, but not for interfaces. Awesome!  :-)
1443   
1444    cue init(token as IToken, idToken as IToken, name as String, paramList as List<of IType>, isNames as String*, attribs as AttributeList, baseNode as ITypeProxy?, implementsNodes as List<of ITypeProxy>, addsProxies as List<of ITypeProxy>, docString as String?)
1445        base.init(token, idToken, name, paramList, isNames, attribs, implementsNodes, docString)
1446        # there are restrictions on mixins which may be relaxed in the future
1447        assert baseNode is nil
1448        assert implementsNodes.count == 0
1449        assert addsProxies.count == 0
1450        _addsProxies = addsProxies
1451
1452    var _canHaveStatements = true
1453   
1454    get canHaveStatements as bool is override
1455        return _canHaveStatements
1456
1457    var _addsProxies as List<of ITypeProxy>
1458   
1459    def _bindInt
1460        # mixins act as interfaces (and more)
1461        for proxy in _addsProxies
1462            _baseInterfaceProxies.add(proxy)
1463        base._bindInt
1464
1465    def injectInto(box as Box)
1466        for member in .declsInOrder  # TODO: deal with inheritance if mixins are allowed to have mixins added to them
1467            # TODO: deal with overloads
1468            if member inherits Method
1469                method = Method(member.token, member.idToken, box, member.name, member.genericParams, member.params, member.resultType, nil/#implementsTypeNode#/, member.isNames, member.attributes, member.docString)
1470                # TODO: contracts? tests?
1471                for stmt in member.statements
1472                    method.addStmt(stmt.clone)
1473                box.addDecl(method)
1474            else if member inherits Property
1475                prop = Property(member.token, member.idToken, box, member.name, member.returnType, member.isNames, member.attributes, member.docString)
1476                if member.getPart
1477                    getPart = prop.makeGetPart(member.getPart.token)
1478                    for stmt in member.getPart.statements
1479                        getPart.addStmt(stmt.clone)
1480                if member.setPart
1481                    setPart = prop.makeSetPart(member.setPart.token)
1482                    for stmt in member.setPart.statements
1483                        setPart.addStmt(stmt.clone)
1484                box.addDecl(prop)
1485            else if member inherits BoxField
1486                box.addDecl(member)
1487            else
1488                # TODO: warning?
1489                pass
1490
1491
1492class Interface
1493    is partial
1494    inherits Box
1495
1496    cue init(token as IToken, idToken as IToken, name as String, paramList as List<of IType>, isNames as String*, attribs as AttributeList, baseNodes as List<of ITypeProxy>, docString as String?)
1497        base.init(token, idToken, name, paramList, isNames, attribs, baseNodes, docString)
1498       
1499    cue init(nativeType as NativeType, backend as BackEnd)
1500        base.init(TokenFix.empty, TokenFix.empty, backend.cobraNameForNativeBoxName(nativeType.name), List<of IType>(), List<of String>(), AttributeList(), List<of ITypeProxy>(), nil)
1501        _initNativeType(nativeType)
1502
1503    get canHaveStatements as bool is override
1504        return false
1505
1506    get englishName as String is override
1507        return 'interface'
1508
1509    get isReference as bool is override
1510        return true
1511
1512    def isDescendantOf(type as IType) as bool is override
1513        or require .nativeType
1514        _prepLibraryBox
1515        if this == type, return true
1516        if type inherits Interface
1517            if .isDescendantOfInterface(type)
1518                return true
1519        if .superType is type or .superType.isDescendantOf(type), return true
1520        return false
1521
1522    def memberForName(name as String) as IMember?
1523        m = base.memberForName(name)
1524        if m is nil
1525            m = .interfaceMemberForName(name)
1526            if m is nil and _baseClass
1527                m = _baseClass.memberForName(name)
1528        return m
1529
1530
1531class Struct
1532    is partial
1533    inherits ClassOrStruct
1534
1535    cue init(token as IToken, idToken as IToken, name as String, paramList as List<of IType>, isNames as String*, attribs as AttributeList, baseName as String?, interfaceNodes as List<of ITypeProxy>, addsProxies as List<of ITypeProxy>, docString as String?)
1536        base.init(token, idToken, name, paramList, isNames, attribs, interfaceNodes, addsProxies, docString)
1537
1538    cue init(nativeType as NativeType,  backend as BackEnd)
1539        base.init(TokenFix.empty, TokenFix.empty, backend.cobraNameForNativeBoxName(nativeType.name), List<of IType>(), List<of String>(), AttributeList(), List<of ITypeProxy>(), List<of ITypeProxy>(), nil)
1540        _initNativeType(nativeType)
1541
1542    get englishName as String is override
1543        return 'struct'
1544
1545    def isDescendantOf(type as IType) as bool is override
1546        # TODO: hmmm, almost duplicated from Class
1547        or require .nativeType
1548        _prepLibraryBox
1549        if this == type, return true
1550        if not .baseClass /# TODO? and _baseNode #/, .bindInh
1551        if .compiler, type.bindInh
1552        if type inherits Interface
1553            if .isDescendantOfInterface(type)
1554                return true
1555        baseClass = .baseClass
1556        # assert baseClass is not this, this  # check for direct cycles
1557        if baseClass, return baseClass.isDescendantOf(type)
1558        return false
1559
1560    get isCallable as bool is override
1561        return true
1562
1563    get isReference as bool is override
1564        return false
1565
1566    def memberForName(name as String) as IMember?
1567        m = base.memberForName(name)
1568        if m is nil and _baseClass
1569            m = _baseClass.memberForName(name)
1570        return m
1571
1572    def _makeInitializers
1573        base._makeInitializers
1574        if .isFromBinaryLibrary, return
1575        # Check for explicit parameterless inits which are disallowed in structs
1576        hasParameterlessInit = false
1577        for decl in .declsInOrder
1578            if decl inherits Initializer
1579                if not decl.hasParams
1580                    decl.recordError('Structs cannot contain explicit parameterless initializers. A default one is provided.')
1581                    hasParameterlessInit = true
1582        # Create the implicit parameterless init
1583        if hasParameterlessInit, return
1584        init = Initializer(.token, .token, this, List<of Param>(), ['public'], AttributeList(), 'Default struct initializer.', isImplicit = true)
1585        other = .declForName('cue.init')
1586        overload = nil to MemberOverload?
1587        if other inherits MemberOverload
1588            overload = other
1589        else if other
1590            overload = MemberOverload(other to IOverloadable)
1591            .registerOverload(overload to !)
1592        else
1593            .addDecl(init)
1594        if overload, overload.addMember(init)
1595
1596
1597class MethodSig inherits Class is partial
1598    """
1599    Example Cobra source:
1600        sig ComputeSomething(a is int, b as int) as int
1601
1602    .NET calls these delegates and describes them as type-safe method signatures.
1603    The "sig" keyword fits nicely with other declaration keywords like "var" "def" and "get".
1604    And "sig" is a more platform neutral term should we have other non-CLI backends.
1605   
1606    MethodSigs are only created when parsing. When reading from a DLL, delegates are merely
1607    subclasses of Delegate or MulticastDelegate.
1608   
1609    Note that MethodSig is a subclass of Class and therefore both a Box and an IType. Also, it will
1610    return true for .isDescendantOf(.compiler.delegateType).
1611   
1612    Reference: Pro C# 2008, Chapter 11
1613    """
1614
1615    var _params as List<of Param>
1616    var _returnTypeProxy as ITypeProxy
1617    var _returnType as IType?
1618
1619    cue init(token as IToken, idToken as IToken, parent as IParentSpace?, name as String, params as List<of Param>, returnTypeProxy as ITypeProxy, isNames as String*, attribs as AttributeList, docString as String)
1620        base.init(token, idToken, name, List<of IType>(), isNames, attribs, LibraryTypeProxy('System.MulticastDelegate'), List<of ITypeProxy>(), List<of ITypeProxy>(), docString)
1621        _initParent(parent)
1622        _params = params
1623        _returnTypeProxy = returnTypeProxy
1624 
1625    get params from var
1626   
1627    get returnTypeProxy from var
1628   
1629    get returnType from var
1630   
1631    get resultType as IType? is override
1632        return .returnType
1633
1634    def _bindInh
1635        base._bindInh
1636        assert _baseClass
1637        assert _baseClass.qualifiedName == 'System.MulticastDelegate'
1638        assert .parentBox or .parentNameSpace
1639
1640    def _bindInt
1641        returnType as ITypeProxy = .returnType ? .returnTypeProxy
1642        .addDecl(_makeMethod('invoke', .params.clone, returnType))
1643        # dynamic type vari length param in list as placeholder for multiple params
1644        params = [Param('vParam', VariTypeIdentifier(.token, TypeIdentifier(.token, DynamicType())))]
1645        .addDecl(_makeMethod('beginInvoke', params, TypeIdentifier(.token.copy('ID', 'IAsyncResult')) to ITypeProxy))
1646        .addDecl(_makeMethod('endInvoke',   params, returnType ))
1647        base._bindInt
1648        for param in .params
1649            param.bindInt
1650        if not _returnType
1651            _returnType = _returnTypeProxy.realType
1652
1653    def _makeInitializers is override
1654        pass
1655
1656    def _makeMethod(name as String, params as IList<of Param>, returnTypeProxy as ITypeProxy) as Method
1657        m = Method(.token, .token, this, name, params, returnTypeProxy, nil, .isNames, AttributeList(), '')
1658        # method body just to avoid a Cobra warning during .bindImp
1659        m.statements.add(ThrowStmt(.token, PostCallExpr(.token, IdentifierExpr(.token, 'Exception'), List<of Expr>()))) 
1660        return m
1661       
1662class GenericParam inherits CobraType is partial
1663    """
1664    A generic parameter *is* a type.
1665    """
1666
1667    var _name as String
1668    var _constraints as List<of GenericConstraint>
1669    var _index as int
1670    var _objectClass as Class?
1671    var _nativeType as NativeType?
1672
1673    cue init(name as String)
1674        require name.length
1675        base.init
1676        _name = name
1677        _constraints = List<of GenericConstraint>()
1678
1679    cue init(genArgType as NativeType)
1680        .init(genArgType.name)
1681        _nativeType = genArgType
1682        # TODO: scan Constraints
1683   
1684    get constraints from var
1685
1686    get englishName as String is override
1687        return 'generic parameter'
1688
1689    get idString as String is override
1690        return '[.getType.name]([.serialNum], "[.name]")'
1691
1692    pro index from var
1693
1694    get isReference as bool is override
1695        # Well, it's hard to say if a GenericParam is a reference or value type, but CompareExpr() influences us to say "true".
1696        # TODO: if there are constraints on the generic param, examine them to determine answer
1697        return true
1698
1699    get isUninitializedForLocalVars as bool is override
1700        return false  # TODO: could use a more sophisticated implementation
1701
1702    get name as String is override
1703        return _name
1704
1705    get nativeType from var
1706
1707    pro parentDefinition from var as NamedNode?
1708        """
1709        The definition that directly contains this generic parameter.
1710        For example, if non-nil, then `gp in .parentDefinition.genericParams` will be true.
1711        GenericParams are created in other circumstances such as being passed into a constructed type, in which case .parentDefinition will be nil.
1712        Note that .parentDefinition is always a Box or a Method.  # TODO: require/ensure that?
1713        """
1714
1715    def addMinFields
1716        base.addMinFields
1717        .addField('name', _name)
1718
1719    def addSubFields
1720        base.addSubFields
1721        .addField('constraints', _constraints)
1722        .addField('index', _index)
1723
1724    def declForName(name as String) as IMember? is override
1725        for constraint in _constraints
1726            decl = constraint.declForName(name)
1727            if decl
1728                return decl
1729        return _objectClass.declForName(name)
1730
1731    def memberForName(name as String) as IMember? is override
1732        for constraint in _constraints
1733            member = constraint.memberForName(name)
1734            if member
1735                return member
1736        return _objectClass.memberForName(name)
1737
1738    def isDescendantOf(type as IType) as bool is override
1739        if this == type, return true
1740        if type is .compiler.objectType, return true
1741        if type.superType is nil, return true  # the root type
1742        for constraint in _constraints
1743            if constraint.isDescendantOf(type)
1744                return true
1745        return false
1746
1747    def secondaryConstructedTypeFor(box as Box, gpToType as Dictionary<of GenericParam, IType>) as IType is override
1748        if gpToType.containsKey(this)
1749            return gpToType[this]
1750        for key in gpToType.keys
1751            if key.name == .name
1752                return gpToType[key]
1753        # a generic method in a generic class requires the next statement
1754        # see Tests/240-generics/400-generic-methods/102-generic-method-in-generic-class.cobra
1755        return this
1756
1757    def _bindInt
1758        base._bindInt
1759        _objectClass = .compiler.objectClass
1760        for constraint in _constraints
1761            constraint.bindInt
1762
1763
1764class GenericConstraint
1765    inherits SyntaxNode
1766
1767    cue init(token as IToken)
1768        base.init(token)
1769
1770    def isDescendantOf(type as IType) as bool
1771        return false
1772
1773    def declForName(name as String) as IBoxMember?
1774        """
1775        Returns nil by default.
1776        """
1777        return nil
1778
1779    def memberForName(name as String) as IMember?
1780        """
1781        Returns nil by default.
1782        """
1783        return nil
1784
1785    def _bindInt
1786        base._bindInt
1787
1788
1789class GenericClassConstraint
1790    is partial
1791    inherits GenericConstraint
1792    """
1793    Represents the generic constraint class
1794    """
1795
1796    cue init(token as IToken)
1797        base.init(token)
1798
1799
1800class GenericStructConstraint
1801    is partial
1802    inherits GenericConstraint
1803    """
1804    Represents the generic constraint class
1805    """
1806
1807    cue init(token as IToken)
1808        base.init(token)
1809
1810
1811class GenericCallableConstraint
1812    is partial
1813    inherits GenericConstraint
1814    """
1815    Represents the generic constraint callable
1816    """
1817
1818    cue init(token as IToken)
1819        base.init(token)
1820
1821
1822class GenericTypeConstraint
1823    is partial
1824    inherits GenericConstraint
1825    """
1826    Represents the generic constraint of a particular type.
1827    """
1828
1829    var _representedType as IType?
1830    var _typeNode as ITypeProxy
1831
1832    cue init(typeNode as ITypeProxy)
1833        base.init((typeNode to ISyntaxNode).token)  # CC: could be potential for making arg a compound interface ISyntaxNode+ITypeProxy from the 'Speculative' list
1834        _typeNode = typeNode
1835
1836    def isDescendantOf(type as IType) as bool is override
1837        assert _representedType
1838        return _representedType.isDescendantOf(type)
1839
1840# TODO?
1841#   def declForName(name as String) as IBoxMember? is override
1842#       assert _representedType
1843#       return _representedType.declForName(name)
1844
1845    def memberForName(name as String) as IMember? is override
1846        assert _representedType
1847        return _representedType.memberForName(name)
1848
1849    def _bindInt
1850        base._bindInt
1851        if _representedType is nil
1852            _representedType = _typeNode.realType
1853            assert _representedType
1854        if not _representedType inherits Class and not _representedType inherits Interface
1855            .throwError('A generic type constraint must be a class or an interface. "[_representedType.name]" is not.')
1856
1857
1858class Extension inherits Box is partial
1859    """
1860    Example:
1861        extend String       
1862            get doubleLength as int
1863                return .length * 2
1864    """
1865
1866    var _extendedBoxProxy as ITypeProxy?
1867    var _extendedBox as Box?
1868
1869    cue init(token as IToken, idToken as IToken, extendedBoxProxy as ITypeProxy, isNames as String*, docString as String?)
1870        base.init(token, idToken, '(unnamed extension)', List<of IType>(), isNames, AttributeList(), List<of ITypeProxy>(), docString)
1871        _name = '(unnamed extension [.serialNum])'
1872        _extendedBoxProxy = extendedBoxProxy
1873
1874    cue init(nativeType as NativeType,  backend as BackEnd)
1875        # this only for Cobra specific extensions. Example: class Extend_String_FileName
1876        base.init(TokenFix.empty, TokenFix.empty, backend.cobraNameForNativeBoxName(nativeType.name), List<of IType>(), List<of String>(), AttributeList(), List<of ITypeProxy>(), nil)
1877        _initNativeType(nativeType)
1878        # the real extended type is not this type, but the type of the first argument of any method
1879        nativeType = backend.determineExtnNativeType(this, nativeType)
1880        _extendedBoxProxy = backend.nativeTypeProxy(nativeType)
1881        (.compiler.curModule to AssemblyModule).addMustBindInh(this)
1882
1883    get extendedBox from var
1884
1885    get isReference as bool is override
1886        return _extendedBox.isReference
1887
1888    get englishName as String is override
1889        return if(_extendedBox, _extendedBox.englishName+' ', '') + 'extension'
1890
1891    def addDecl(decl as IBoxMember) is override
1892        base.addDecl(decl)
1893
1894    def extensionMemberFor(box as Box, name as String) as IMember? is override
1895        # TODO: this method is called too frequently, probably due to _finishOverloads, but may also be other sources. there's no bug, but it may be a performance drag
1896        if not .declForName(name), return nil
1897        assert .didBindInh
1898        .prepIfNeeded
1899        assert _extendedBox
1900        if _extendedBox
1901            if box.isDescendantOf(_extendedBox)
1902                return .declForName(name)
1903            else if box.isGeneric and .isGeneric
1904                # example:
1905                # this == Extension(6376, "IEnumerable<of T>.extension.6376")
1906                # box  == Class(13618, "KeyCollection<of String,int>")
1907                # name == 'toList'
1908                # cto  == Interface(13543, "IEnumerable<of String>")
1909                cto = box.constructedTypeOf(_extendedBox.genericDef to !)
1910                if cto
1911                    if box.isDescendantOf(cto) and .declForName(name)
1912                        return .constructedTypeFor(cto.genericParams).declForName(name)
1913            else if .isGeneric
1914                # Example:
1915                # this == Extension of IEnumerable<of T>
1916                # box == X implements IEnumerable<of int>
1917                # name == 'toList'
1918                # The IEnumerable<of T> has .genericDef IEnumerable<>
1919                # The X's IEnumerable<of int> has .genericDef IEnumerable<>
1920                # Note that X and the Extension are not directly connected.
1921                # Only by tracing up to the generic def IEnumerable<> do they "connect".
1922                # see cobra/Tests/420-extensions/400-extend-generics/220-extend-ancestor-interface.cobra
1923                constructed = box.constructedTypeOf(_extendedBox.genericDef to !)
1924                if constructed, return .extensionMemberFor(constructed, name)
1925        return nil
1926
1927    def memberForName(name as String) as IMember?
1928        result = base.memberForName(name)
1929        if result is nil, result = .extendedBox.memberForName(name)
1930        return result
1931
1932    def symbolForName(name as String, haveThis as bool, firstCall as bool) as IMember?
1933        result = base.symbolForName(name, haveThis, firstCall)
1934        if result is nil and .extendedBox  # may be nil during .bindInh phase
1935            result = .extendedBox.symbolForName(name, haveThis, firstCall)
1936        return result
1937
1938    def _bindInh
1939        base._bindInh
1940
1941        if _extendedBox is nil
1942            if _extendedBoxProxy inherits GenericTypeIdentifier
1943                # this will error on the generic params unless we set them up to be found
1944                for tn in _extendedBoxProxy.typeNodes
1945                    if tn inherits TypeIdentifier
1946                        _genericParams.add(GenericParam(tn.name))
1947                    else
1948                        .throwError('Invalid generic param "[tn]".')
1949
1950            realType = _extendedBoxProxy.realType
1951            if realType inherits Box
1952                _extendedBox = realType
1953                if _extendedBox.genericDef
1954                    _genericParams = List<of IType>(_extendedBox.genericParams)
1955            else
1956                .throwError('Cannot extend a [realType.name]. You can extend classes, structs and interfaces.')
1957               
1958        _name = '[_extendedBox.name].extension.[.serialNum]'
1959
1960        # shouldn't need or use inherited types
1961        _baseClass = nil
1962        _baseInterfaceProxies = List<of ITypeProxy>()
1963        _baseInterfaces = List<of Interface>()
1964       
1965        if not _extendedBox.didBindInh, _extendedBox.bindInh
1966   
1967    def bindInt as INode
1968        extendedBox = .extendedBox
1969        assert extendedBox.didBindInh
1970        if not extendedBox.didBindInt and not extendedBox.isBindingInh, extendedBox.bindInt
1971        assert extendedBox.didBindInt
1972        return base.bindInt
1973   
1974    def _bindInt
1975        extendedBox = .extendedBox
1976        assert extendedBox.didBindInh and extendedBox.didBindInt
1977        base._bindInt
1978        sharpName = .sharpRef   # TODO: how to generalize this beyond CLR? idea: change .sharedMethodBacking to refer to a method instead of being a String
1979        for decl in .declsInOrder
1980            if decl inherits AbstractMethod
1981                if decl inherits Initializer
1982                    decl.recordError('Extensions can only contain methods, not initializers.')
1983                else
1984                    decl.sharedMethodBacking = '[sharpName].[decl.name.capitalized]'
1985                    decl.changeToNonVirtual
1986                    decl.bindInt
1987                    # handle overloads
1988                    other = extendedBox.declForName(decl.name)
1989                    if other
1990                        newOverload = nil to MemberOverload?
1991                        if other inherits MemberOverload
1992                            overload = other
1993                        else if other inherits AbstractMethod
1994                            newOverload = overload = MemberOverload(other)
1995                            extendedBox.registerOverload(overload)
1996                        else
1997                            throw FallThroughException([this, decl])
1998                        decl.overloadGroup = nil  # Could be in a group from the extension itself. And .addMember below doesn't like that.
1999                        overload.addMember(decl)
2000                        if newOverload, newOverload.bindInt  # an overload that never .bindInt will get cranky later
2001            else
2002                decl.recordError('Extensions can only contain methods.')
2003
2004    def _bindImp
2005        base._bindImp
2006        for decl in .declsInOrder
2007            decl.bindImp
Note: See TracBrowser for help on using the browser.