Changeset 1573
- Timestamp:
- 08/12/08 21:13:54 (3 months ago)
- Location:
- cobra/trunk
- Files:
-
- 7 added
- 8 modified
-
Developer/IntermediateReleaseNotes.text (modified) (1 diff)
-
Source/Attributes.cobra (modified) (1 diff)
-
Source/Boxes.cobra (modified) (2 diffs)
-
Source/CobraParser.cobra (modified) (7 diffs)
-
Source/Container.cobra (modified) (1 diff)
-
Source/Enums.cobra (modified) (1 diff)
-
Source/Members.cobra (modified) (3 diffs)
-
Source/NameSpace.cobra (modified) (2 diffs)
-
Tests/200-misc/820-partial (added)
-
Tests/200-misc/820-partial/100-partial-class.cobra (added)
-
Tests/200-misc/820-partial/110-partial-multi-file-1.cobra (added)
-
Tests/200-misc/820-partial/112-partial-multi-file-2.cobra (added)
-
Tests/200-misc/820-partial/120-partial-error-interface.cobra (added)
-
Tests/200-misc/820-partial/122-partial-error-type-mismatch.cobra (added)
-
Tests/200-misc/820-partial/124-partial-error-other-decl-not-partial.cobra (added)
Legend:
- Unmodified
- Added
- Removed
-
cobra/trunk/Developer/IntermediateReleaseNotes.text
r1572 r1573 1 1 Post 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 2 20 3 21 * 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 94 94 return 'assembly' 95 95 96 get isNames as List<of String> 97 return List<of String>() 98 96 99 get typeForIdentifier as IType? is override 97 100 assert false -
cobra/trunk/Source/Boxes.cobra
r1560 r1573 281 281 _nextPrivateSerialNumber += 1 282 282 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 283 290 284 291 get canAccessMemberForName as bool is override … … 568 575 try 569 576 if decl inherits BoxMember 570 if decl.box is not this 577 if decl.box is not this # TODO: when does this happen 571 578 continue 572 579 decl.bindInt -
cobra/trunk/Source/CobraParser.cobra
r1569 r1573 526 526 .throwError('Expecting use, assembly, namespace, class, interface or enum, but got [tok].[sugg]') 527 527 if what 528 _nameSpaceAddDecl(_module.topNameSpace, what)529 if what inherits Box530 assert what.parentNameSpace528 what = _nameSpaceAddDecl(_module.topNameSpace, what) 529 if what inherits Box 530 assert what.parentNameSpace 531 531 finally 532 532 _nameSpaceStack.pop … … 691 691 """ 692 692 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'] 694 694 names = List<of String>(_isNamesStack) 695 695 if .optional('IS') is nil … … 1028 1028 return firstNameSpace to ! 1029 1029 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 1035 1065 ns.addDecl(decl) 1066 return decl 1036 1067 1037 1068 def bodiedBoxMemberDecls(box as Box) … … 1175 1206 if name == curBox.name or Utils.capped(name) == curBox.name 1176 1207 .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 1193 1209 1194 1210 if opener.which in ['OPEN_CALL', 'OPEN_GENERIC'] … … 1351 1367 params = .paramDecls(true, 'RBRACKET') 1352 1368 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) 1360 1370 else 1361 1371 name = .idOrKeyword.text … … 1483 1493 prop as ProperDexer? 1484 1494 token = .expect(if(getOrSet, 'SET', 'GET')) 1485 overload as MemberOverload? = nil1495 overload as MemberOverload? 1486 1496 if .optional('LBRACKET') 1487 1497 params = .paramDecls(true, 'RBRACKET') 1488 1498 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) 1496 1500 else 1497 1501 name = .idOrKeyword.text … … 3188 3192 throw _makeError(token, msg) # will get recorded in .parseSource if the exception actually "makes it out" (some parser logic catches errors) 3189 3193 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 3190 3217 def _makeError(token as IToken?, msg as String) as ParserException 3191 3218 if token -
cobra/trunk/Source/Container.cobra
r1481 r1573 137 137 138 138 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 143 141 return nil 144 142 -
cobra/trunk/Source/Enums.cobra
r1446 r1573 101 101 return m 102 102 103 def mergedIntoPartialBox(newBox as Box) 104 require 105 newBox is not .parentBox 106 newBox.name == .parentBox.name 107 body 108 _parentBox = newBox 109 103 110 get sharpInit as String is override 104 111 return .sharpRef + '.' + Utils.capped(_declsInOrder[0].name) -
cobra/trunk/Source/Members.cobra
r1562 r1573 11 11 """ 12 12 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 13 18 14 19 … … 49 54 get attributes from _attribs 50 55 51 get box from var 56 get box from var # CC: axe in favor of using .parentBox 57 58 get parentBox from _box 52 59 53 60 get canHaveMatchingBaseMember as bool … … 174 181 """ 175 182 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 176 190 177 191 -
cobra/trunk/Source/NameSpace.cobra
r1459 r1573 1 1 interface INameSpaceMember 2 inherits IMember 2 inherits IMember, ISyntaxNode 3 3 """ 4 4 Anything that can be a member of a namespace should implement INameSpaceMember. … … 7 7 8 8 def extensionMemberFor(box as Box, name as String) as IMember? 9 get isNames as List<of String> 9 10 10 11
