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

Added partial classes.
ticket:10

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • 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