Changeset 1573

Show
Ignore:
Timestamp:
08/12/08 21:13:54 (3 months ago)
Author:
Chuck.Esterbrook
Message:

Added partial classes.
ticket:10

Location:
cobra/trunk
Files:
7 added
8 modified

Legend:

Unmodified
Added
Removed
  • cobra/trunk/Developer/IntermediateReleaseNotes.text

    r1572 r1573  
    11Post 0.8 
     2 
     3* Added partial classes, a la C# and VB. This enables class (and struct) declarations to be split across files. This can be useful for organizing generated code or even manually written code based on purpose. ticket:10 
     4.code 
     5        # file Foo.cobra 
     6        class Foo 
     7                is partial 
     8                 
     9                var _name as String 
     10                 
     11                pro name from var 
     12         
     13        # file Foo.gen.cobra 
     14        class Foo 
     15                is partial 
     16                 
     17                def generatedMethod 
     18                        pass 
     19 
    220 
    321* Added new comment markers /# ... #/ which can be used for block comments and inline comments. Block comments must start at the beginning of a line and can be used to comment out multiple lines of source. They can be nested. Inline comments also start with /# and end with #/, but within the same line. They can be used to comment out a portion of a line. Regular end of line comments are still available and still the norm. 
  • cobra/trunk/Source/Attributes.cobra

    r1553 r1573  
    9494                return 'assembly' 
    9595 
     96        get isNames as List<of String> 
     97                return List<of String>() 
     98 
    9699        get typeForIdentifier as IType? is override 
    97100                assert false 
  • cobra/trunk/Source/Boxes.cobra

    r1560 r1573  
    281281                _nextPrivateSerialNumber += 1 
    282282                return n 
     283 
     284        def mergedIntoPartialBox(newBox as Box) 
     285                require 
     286                        newBox is not .parentBox 
     287                        newBox.name == .parentBox.name 
     288                body 
     289                        _parentBox = newBox 
    283290 
    284291        get canAccessMemberForName as bool is override 
     
    568575                                try 
    569576                                        if decl inherits BoxMember 
    570                                                 if decl.box is not this 
     577                                                if decl.box is not this  # TODO: when does this happen 
    571578                                                        continue 
    572579                                        decl.bindInt 
  • cobra/trunk/Source/CobraParser.cobra

    r1569 r1573  
    526526                                        .throwError('Expecting use, assembly, namespace, class, interface or enum, but got [tok].[sugg]') 
    527527                                if what 
    528                                         _nameSpaceAddDecl(_module.topNameSpace, what) 
    529                                 if what inherits Box 
    530                                         assert what.parentNameSpace 
     528                                        what = _nameSpaceAddDecl(_module.topNameSpace, what) 
     529                                        if what inherits Box 
     530                                                assert what.parentNameSpace 
    531531                finally 
    532532                        _nameSpaceStack.pop 
     
    691691                """ 
    692692                if _validIsNames is nil 
    693                         _validIsNames = ['fake', 'shared', 'virtual', 'nonvirtual', 'override', 'new', 'public', 'protected', 'private', 'internal', 'abstract'] 
     693                        _validIsNames = ['fake', 'shared', 'virtual', 'nonvirtual', 'override', 'new', 'public', 'protected', 'private', 'internal', 'abstract', 'partial'] 
    694694                names = List<of String>(_isNamesStack) 
    695695                if .optional('IS') is nil 
     
    10281028                return firstNameSpace to ! 
    10291029 
    1030         def _nameSpaceAddDecl(ns as NameSpace, decl as INameSpaceMember) 
    1031                 if ns.declForName(decl.name) 
    1032                         .throwError((decl to dynamic).token to IToken, 'The namespace "[ns.fullName]" already contains a declaration named "[decl.name]".')  # TODO: give an "error" for the location  
    1033                 if ns.unifiedNameSpace.declForName(decl.name) 
    1034                         .throwError((decl to dynamic).token to IToken, 'The namespace "[ns.fullName]" already contains a declaration named "[decl.name]" in another file.')  # TODO: give an "error" for the location  
     1030        def _nameSpaceAddDecl(ns as NameSpace, decl as INameSpaceMember) as INameSpaceMember 
     1031                """ 
     1032                Adds the decl to the given namespace or throws an error for duplicate declarations. 
     1033                Also, handles `partial` classes and structs. 
     1034                Returns the same declaration, or in the case of `partial`, the original declaration. 
     1035                """ 
     1036                # TODO: complain if inheritance or is-names are different. at least for inheritance, that needs to be done post-parsing 
     1037                checkForDups = true 
     1038                if 'partial' in decl.isNames 
     1039                        if decl inherits Box 
     1040                                if not (decl inherits Class or decl inherits Struct) 
     1041                                        .throwError(decl.token, '[Utils.capped(decl.englishName)] cannot be "partial".') 
     1042                                checkForDups = false 
     1043                                otherDecl = ns.unifiedNameSpace.declForName(decl.name) 
     1044                                if otherDecl 
     1045                                        if otherDecl.getType is not decl.getType 
     1046                                                .throwError(decl.token, 'The other partial declaration is a "[otherDecl.englishName]", not a "[decl.englishName]".') 
     1047                                        if 'partial' not in otherDecl.isNames 
     1048                                                .throwError(decl.token, 'The other declaration is not marked "partial".') 
     1049                                        otherBox = otherDecl to Box  # will always work because of above checks 
     1050                                        for memberDecl in decl.declsInOrder 
     1051                                                overload = _overloadIfNeeded(otherBox, memberDecl.name) 
     1052                                                if overload 
     1053                                                        overload.addMember(memberDecl to BoxMember) 
     1054                                                else 
     1055                                                        otherBox.addDecl(memberDecl) 
     1056                                                memberDecl.mergedIntoPartialBox(otherBox) 
     1057                                        return otherDecl 
     1058                        else 
     1059                                .throwError(decl.token, '[Utils.capped(decl.englishName)] cannot be "partial".') 
     1060                if checkForDups 
     1061                        if ns.declForName(decl.name) 
     1062                                .throwError((decl to dynamic).token to IToken, 'The namespace "[ns.fullName]" already contains a declaration named "[decl.name]".')  # TODO: give an "error" for the location  
     1063                        if ns.unifiedNameSpace.declForName(decl.name) 
     1064                                .throwError((decl to dynamic).token to IToken, 'The namespace "[ns.fullName]" already contains a declaration named "[decl.name]" in another file.')  # TODO: give an "error" for the location  
    10351065                ns.addDecl(decl) 
     1066                return decl 
    10361067 
    10371068        def bodiedBoxMemberDecls(box as Box) 
     
    11751206                if name == curBox.name or Utils.capped(name) == curBox.name 
    11761207                        .throwError('Method names cannot be the same as their enclosing [curBox.englishName]. Use `def init` for creating an initializer/constructor or choose another name.')  # TODO list the enclosing types location 
    1177                 overload as MemberOverload? 
    1178                 other = curBox.declForName(name) 
    1179                 if other 
    1180                         if other inherits MemberOverload 
    1181                                 overload = other 
    1182                         else if other inherits AbstractMethod 
    1183                                 overload = MemberOverload(other) 
    1184                                 curBox.registerOverload(overload to !) 
    1185                         else 
    1186                                 .throwError('There is already another class member with the name "[name]".')  # TODO list its location and possibly what it is 
    1187                 else 
    1188                         other = curBox.declForName(name)  # TODO: should be a CI there for case-insensitive 
    1189                         if other 
    1190                                 .throwError('There is already another class member with the name "[other.name]". You must differentiate member names by more than just case.') 
    1191                         if name[0] in _uppercaseLetters 
    1192                                 .recordError('Method names must start with lowercase letters. ([name])') 
     1208                overload = _overloadIfNeeded(curBox, name)  # also checks for various errors 
    11931209 
    11941210                if opener.which in ['OPEN_CALL', 'OPEN_GENERIC'] 
     
    13511367                        params = .paramDecls(true, 'RBRACKET') 
    13521368                        name = r'[]' 
    1353                         other = curBox.declForName(name) 
    1354                         if other 
    1355                                 if other inherits MemberOverload 
    1356                                         overload = other 
    1357                                 else if other inherits ProperDexer 
    1358                                         overload = MemberOverload(other) 
    1359                                         curBox.registerOverload(overload to !) 
     1369                        overload = _overloadIfNeeded(curBox, name) 
    13601370                else 
    13611371                        name = .idOrKeyword.text 
     
    14831493                prop as ProperDexer? 
    14841494                token = .expect(if(getOrSet, 'SET', 'GET')) 
    1485                 overload as MemberOverload? = nil 
     1495                overload as MemberOverload? 
    14861496                if .optional('LBRACKET') 
    14871497                        params = .paramDecls(true, 'RBRACKET') 
    14881498                        name = r'[]' 
    1489                         other = curBox.declForName(name) 
    1490                         if other 
    1491                                 if other inherits MemberOverload 
    1492                                         overload = other 
    1493                                 else if other inherits ProperDexer 
    1494                                         overload = MemberOverload(other) 
    1495                                         curBox.registerOverload(overload to !) 
     1499                        overload = _overloadIfNeeded(curBox, name) 
    14961500                else 
    14971501                        name = .idOrKeyword.text 
     
    31883192                throw _makeError(token, msg)  # will get recorded in .parseSource if the exception actually "makes it out" (some parser logic catches errors) 
    31893193 
     3194        def _overloadIfNeeded(box as Box, name as String) as MemberOverload? 
     3195                """ 
     3196                Creates an overload for a new member going into box--if needed. 
     3197                May throw various appropriate errors. 
     3198                """ 
     3199                overload as MemberOverload? 
     3200                other = box.declForName(name) 
     3201                if other 
     3202                        if other inherits MemberOverload 
     3203                                overload = other 
     3204                        else if other inherits AbstractMethod or other inherits ProperDexer # CC: make this method generic on this type 
     3205                                overload = MemberOverload(other to BoxMember) 
     3206                                box.registerOverload(overload to !) 
     3207                        else 
     3208                                .throwError('There is already another class member with the name "[name]".')  # TODO list its location and possibly what it is 
     3209                else 
     3210                        other = box.declForName(name)  # TODO: should be a CI there for case-insensitive 
     3211                        if other 
     3212                                .throwError('There is already another class member with the name "[other.name]". You must differentiate member names by more than just case.') 
     3213                        if name[0] in _uppercaseLetters 
     3214                                .recordError('Method names must start with lowercase letters. ([name])') 
     3215                return overload 
     3216 
    31903217        def _makeError(token as IToken?, msg as String) as ParserException 
    31913218                if token 
  • cobra/trunk/Source/Container.cobra

    r1481 r1573  
    137137 
    138138        get parent as IParentSpace? 
    139                 if .parentBox 
    140                         return .parentBox 
    141                 if .parentNameSpace 
    142                         return .parentNameSpace 
     139                if .parentBox, return .parentBox 
     140                if .parentNameSpace, return .parentNameSpace 
    143141                return nil 
    144142 
  • cobra/trunk/Source/Enums.cobra

    r1446 r1573  
    101101                return m 
    102102 
     103        def mergedIntoPartialBox(newBox as Box) 
     104                require 
     105                        newBox is not .parentBox 
     106                        newBox.name == .parentBox.name 
     107                body 
     108                        _parentBox = newBox 
     109 
    103110        get sharpInit as String is override 
    104111                return .sharpRef + '.' + Utils.capped(_declsInOrder[0].name) 
  • cobra/trunk/Source/Members.cobra

    r1562 r1573  
    1111        """ 
    1212        get docString as String? 
     13        get parentBox as Box 
     14        def mergedIntoPartialBox(newBox as Box) 
     15                require 
     16                        newBox is not .parentBox 
     17                        newBox.name == .parentBox.name 
    1318 
    1419 
     
    4954        get attributes from _attribs 
    5055 
    51         get box from var 
     56        get box from var  # CC: axe in favor of using .parentBox 
     57 
     58        get parentBox from _box 
    5259 
    5360        get canHaveMatchingBaseMember as bool 
     
    174181                """ 
    175182                pass 
     183 
     184        def mergedIntoPartialBox(newBox as Box) 
     185                require 
     186                        newBox is not .box 
     187                        newBox.name == .box.name 
     188                body 
     189                        _box = newBox 
    176190 
    177191 
  • cobra/trunk/Source/NameSpace.cobra

    r1459 r1573  
    11interface INameSpaceMember 
    2         inherits IMember 
     2        inherits IMember, ISyntaxNode 
    33        """ 
    44        Anything that can be a member of a namespace should implement INameSpaceMember. 
     
    77 
    88        def extensionMemberFor(box as Box, name as String) as IMember? 
     9        get isNames as List<of String> 
    910 
    1011