Ticket #39: ref-lambda-type-inference.patch
File ref-lambda-type-inference.patch, 35.8 KB (added by hopscc, 14 years ago) |
---|
-
Source/Members.cobra
596 596 get shouldBeVirtual as bool is override 597 597 return false 598 598 599 def lambdaReturnTypeas IType599 def inferLambdaReturnType # as IType 600 600 """ This is a service method for LambdaExpr. """ 601 601 require .didBindInt and .didBindImp 602 602 stmt = _stmts[0] 603 603 if stmt inherits ReturnStmt 604 return stmt.expr.type to ! 604 if stmt.expr.type 605 _returnType = stmt.expr.type to ! 605 606 else 606 607 throw FallThroughException(stmt) 607 608 609 def inferReturnType 610 """ 611 Infer returntype from (first) return statement if type not already explicitly set. 612 This is a service method for AnonymousMethodExpr. 613 """ 614 require .didBindInt and .didBindImp 615 if _returnType == .compiler.passThroughType 616 for stmt in _stmts 617 if stmt inherits ReturnStmt 618 if stmt.expr.type 619 _returnType = stmt.expr.type to ! 620 break 621 608 622 def _bindInt is override 609 623 base._bindInt 610 624 if _returnTypeNode is nil 611 _returnType = .compiler.passThroughType # TODO: infer return type from return statement like C# does625 _returnType = .compiler.passThroughType 612 626 613 627 def _bindImp is override 614 628 base._bindImp … … 623 637 break 624 638 if hasYield, .throwError('Cannot yield inside an anonymous method.') 625 639 626 627 640 class AbstractMethod 628 641 is abstract, partial 629 642 inherits BoxMember -
Source/Expr.cobra
202 202 body 203 203 base._bindImp 204 204 205 def _matchingOrNewSig(aSig as MethodSig, container as Box, tag as String) as MethodSig 206 """ 207 Return a compatible matching Sig for asig in container or containers ancestor inheritance hierarchy 208 otherwise warn and insert (instantiate) aSig into container. 209 210 Support method for RefExpr and AnonymousMethod and lambdaExpr 211 """ 212 compatSig = container.sigForMethodSig(aSig) 213 if not compatSig 214 msg = 'No signature matching the signature of the [tag] ([aSig.toCobraSource]) in the inheritance tree or used namespaces.' 215 sugg = 'Did you leave out a sig statement in scope for this method reference?' 216 action = 'Adding generated sig "[aSig.toCobraSource]" to [container.name]' 217 .compiler.warning(this, '[msg]\n[sugg]\n[action]') 218 container.addDecl(aSig) 219 else 220 aSig = compatSig to ! 221 return aSig 222 205 223 def _suggestionsMessage(suggs as List<of String>) as String 206 224 """ 207 225 Shared by MemberExpr, CallExpr and IdentifierExpr to give suggestions in an error message about an unknown member. … … 320 338 base.addSubFields 321 339 .addField('params', .params) 322 340 341 def _makeAnonSig(tag as String, resultType as IType, isNames as String*) as MethodSig 342 """ 343 Make an anonymous methodSig for this anonymous expr (lambda or anonMethod) 344 and return a declared match for it or instantiate it into its containing box. 345 """ 346 sigToken = .token.copy('ID', 'sigFor[tag]') 347 nameToken = .token.copy('ID', 'SigFor[tag]_[.token.lineNum]_[.serialNum]') 348 docString = '' to ? 349 aSig = MethodSig(sigToken, nameToken, .curCodeMember.parentBox, nameToken.text, .params, 350 resultType, isNames, AttributeList(), docString) 351 aSig.bindInh 352 aSig.bindInt 353 aSig.bindImp 354 #print aSig 355 return _matchingOrNewSig(aSig, .curCodeMember.parentBox, tag) # in Expr 356 323 357 def toCobraSource as String is override 324 358 sb = StringBuilder('do(') 325 359 sep = '' … … 335 369 class AnonymousMethodExpr inherits AnonymousExpr is partial 336 370 implements HasAddStmt 337 371 """ 372 do(a as int, b as int) as int 373 ... 374 return a.compareTo(b) 375 338 376 Also called "closures". 339 377 """ 340 378 … … 354 392 355 393 def _bindImp is override 356 394 base._bindImp 357 _method = AnonymousMethod(.token, .curCodeMember, .params, _returnTypeProxy, if(.curCodeMember.isShared, ['shared'], List<of String>())) 395 isNames = if(.curCodeMember.isShared, ['shared'], List<of String>()) 396 _method = AnonymousMethod(.token, .curCodeMember, .params, _returnTypeProxy, isNames) 358 397 for stmt in .stmts, _method.addStmt(stmt) 359 398 _method.bindInt 360 399 _method.bindImp 361 _type = _method.resultType 400 _method.inferReturnType 401 #print .token.lineNum, _method.resultType 402 _type = _makeAnonSig('AnonMthd', _method.resultType, List<of String>()) 403 362 404 363 364 405 class LambdaExpr inherits AnonymousExpr is partial 365 406 """ 366 407 ... do(a as int, b as int)=a.compareTo(b) ... … … 392 433 393 434 def _bindImp is override 394 435 base._bindImp 395 _method = AnonymousMethod(.token, .curCodeMember, .params, .compiler.dynamicType, if(.curCodeMember.isShared, ['shared'], List<of String>())) 436 isNames = if(.curCodeMember.isShared, ['shared'], List<of String>()) 437 _method = AnonymousMethod(.token, .curCodeMember, .params, .compiler.dynamicType, isNames) 396 438 ret = ReturnStmt(.token.copy('RETURN', 'return'), .expr) 397 439 _method.addStmt(ret) 398 440 _method.bindInt 399 441 _method.bindImp 400 442 # the expression may have been transformed, but if so, only the containing ReturnStmt got the notice 401 443 _expr = ret.expr to ! 402 _type = .compiler.passThroughType # TODO: Set a real type such as .compiler.delegateType 403 # method.lambdaReturnType 444 _type = .compiler.passThroughType 445 _method.inferLambdaReturnType 446 _type = _makeAnonSig('Lambda', _method.resultType, isNames) 404 447 405 448 406 449 class AsExpr … … 1821 1864 ref obj.foo 1822 1865 ref _foo 1823 1866 """ 1824 1867 1825 1868 cue init(token as IToken, expr as Expr) 1826 1869 base.init(token) 1827 1870 # TODO: can the types of expressions be limited? … … 1855 1898 throw 1856 1899 finally 1857 1900 .compiler.refExprLevel -= 1 1901 _checkRefExpr 1902 _type = .compiler.passThroughType # something if refSig make signature fails 1903 refSig = _makeSignatureOfExpr 1904 if refSig 1905 refSig.bindInh 1906 refSig.bindInt 1907 refSig.bindImp 1908 _type = _matchingOrNewSig(refSig, .compiler.curCodeMember.parentBox, _expr.definition.name) # in Expr 1909 1910 def _checkRefExpr 1858 1911 if _expr inherits DotExpr 1859 1912 right = _expr.right 1860 1913 if right inherits MemberExpr … … 1870 1923 else 1871 1924 throw FallThroughException([this, _expr, right]) 1872 1925 else if _expr inherits IdentifierExpr 1873 if _expr.definition inherits AbstractMethod 1874 pass 1875 else 1926 if not ( _expr.definition inherits AbstractMethod ) 1876 1927 .throwError('Only methods can be referenced, not [Utils.pluralize(_expr.definition.englishName)].') 1877 1928 else 1878 1929 .throwError('Unexpected reference. Refer to methods after `ref` or remove `ref`.') 1879 _type = .compiler.passThroughType # TODO: Set a real type such as .compiler.delegateType 1880 # TODO: need to do something more sophisticated like overriding: def canBeAssignedTo(type as IType) as bool 1881 1930 1931 def _makeSignatureOfExpr as MethodSig? 1932 """Auto generate a signature for type of expression being 'ref'd""" 1933 if _expr inherits DotExpr 1934 right = _expr.right 1935 if right inherits MemberExpr 1936 if right.definition inherits AbstractMethod 1937 am = right.definition to AbstractMethod 1938 signature = _makeSig(am, _expr.right.token) 1939 else if right.definition inherits MemberOverload 1940 mo = right.definition to MemberOverload 1941 if mo.members[0] inherits AbstractMethod 1942 am = mo.members[0] to AbstractMethod 1943 signature = _makeSig(am, _expr.right.token) 1944 else if _expr inherits IdentifierExpr 1945 if _expr.definition inherits AbstractMethod 1946 am = _expr.definition to AbstractMethod 1947 signature = _makeSig(am, _expr.token) 1948 return signature 1949 1950 def _makeSig(am as AbstractMethod, token as IToken) as MethodSig 1951 """Make an (anonymously named) signature corresponding to the provided method""" 1952 sigToken= token.copy('ID', 'sigForRef') 1953 nameToken = token.copy 1954 container = .compiler.curCodeMember.parentBox 1955 name = 'SigFor_'+nameToken.value to String 1956 isNames = List<of String>() 1957 attribs = AttributeList() 1958 docString = '' to ? 1959 returnType = am.resultType 1960 params = List<of Param>(am.params) 1961 return MethodSig(sigToken, nameToken, container, name, params, returnType, isNames, attribs, docString) 1962 1882 1963 def toCobraSource as String is override 1883 1964 return 'ref ' + _expr.toCobraSource 1884 1965 -
Source/BackEndClr/ScanClrType.cobra
55 55 if type.isClass 56 56 if type.name.startsWith('Extend_') and type.name.count(c'_') >= 2 57 57 curNameSpace.addDecl(Extension(clrType)) 58 else if _shouldBeMethodSig(type) 59 #print curNameSpace.name, type.name 60 curNameSpace.addDecl(MethodSig(clrType)) 58 61 else 59 62 curNameSpace.addDecl(Class(clrType)) 60 63 else if type.isInterface … … 70 73 throw FallThroughException(type) 71 74 finally 72 75 _curModule = saveModule 76 77 def _shouldBeMethodSig(type as Type) as bool 78 if not type.isSubclassOf(System.MulticastDelegate) 79 return false 80 #if type.isGenericType 81 # print type.namespace, type.name 73 82 83 # Below delegates are generic types in System that are 'too' general re params and return types 84 # and give 'false' matches for simple common cases (min params and (no) return types) 85 # so we suppress them. 86 #Inferred uses will probably either need an explicit compatible signature or will get a warning generated... 87 if type.name in ['CrossAppDomainDelegate', 'Converter`2', 'Action`1', 'EventHandler`1'] 88 return false # other possible candidates include Predicate`1 89 return true 90 74 91 def fixNilableMemberSigs 75 92 # TODO: this really needs to go in a separate file that the compiler reads each time 76 93 … … 465 482 466 483 def _memberTypeProxy(clrType as Type?, notNullAttr as bool) as ITypeProxy 467 484 """ 468 Returns a type proxy for a member type such as a parameter type or me thod returntype.485 Returns a type proxy for a member type such as a parameter type or member type. 469 486 In CLR, reference types are nilable by default, but you can pass `true` for `notNullAttr` to indicate there was a NotNullAttribute in the DLL. 470 487 """ 471 488 if clrType is nil … … 481 498 482 499 def _memberTypeResultProxy(member as MemberInfo, clrType as Type?) as ITypeProxy 483 500 """ 484 Returns a type proxy for a member type such as a parametertype or method return type.501 Returns a type proxy for a member result type such as a property or field type or method return type. 485 502 In CLR, reference types are nilable by default. 486 503 """ 487 if clrType is nil 504 if clrType is nil or clrType is sharp'typeof(void)' # C# null data vs null code return 488 505 return .compiler.voidType 489 506 else if clrType.isValueType 490 507 return ClrTypeProxy(clrType) … … 571 588 # the first argument is implicit in an Extension 572 589 results = base._scanParams(paramInfos) 573 590 return results[1:] 591 592 class MethodSig 593 is partial 594 595 def _scanNativeType 596 base._scanNativeType 597 _scanIsNames 598 #_scanImplements 599 #_scanNestedTypes 600 #_scanFields 601 _scanInitializers 602 #_scanProperties 603 _scanMethods 604 #_scanEvents 605 606 # reflect on invoke method to find signature 607 methInfo = .clrType.getMethod('Invoke', BindingFlags(Instance, Static, DeclaredOnly, Public, NonPublic)) 608 if methInfo and _methOK(methInfo to !) 609 _params = _scanParams(methInfo.getParameters) 610 _returnTypeProxy = _memberTypeResultProxy(methInfo to !, methInfo.returnType) 611 #if .clrType.isGenericType 612 # print .name, methInfo.returnType, _params 613 614 def _methOK( methInfo as System.Reflection.MethodInfo) as bool 615 if methInfo.isSpecialName or methInfo.isAssembly or methInfo.isPrivate 616 return false 617 if methInfo.declaringType is not .clrType, return false 618 if _badRelatedType(methInfo.returnType) 619 return false 620 for paramInfo in methInfo.getParameters 621 if _badRelatedType(paramInfo.parameterType) 622 return false 623 return true -
Source/Boxes.cobra
417 417 _declsByName[ol.name] = ol 418 418 _declsByNameCI[ol.name.toLower] = ol 419 419 420 def addDecl(decl as IBoxMember) is override 421 base.addDecl(decl) 422 # overridden to explicitly store methodSigs separately 423 if decl inherits MethodSig 424 base.addSig(decl) 425 420 426 def addDeclFromOverload(decl as IBoxMember, ol as MemberOverload) 421 427 require 422 428 ol in .overloads … … 1501 1507 The "sig" keyword fits nicely with other declaration keywords like "var" "def" and "get". 1502 1508 And "sig" is a more platform neutral term should we have other non-CLI backends. 1503 1509 1504 MethodSigs are only created when parsing. When reading from a DLL, delegates are merely 1505 subclasses of Delegate or MulticastDelegate. 1510 MethodSigs are created when parsing. When reading from a DLL, delegates are merely 1511 subclasses of (class) Delegate but subclasses of MulticastDelegate are created as MethodSigs so that 1512 type inference and sig matching can be done if such a MethodSig is used as a type.. 1506 1513 1507 1514 Note that MethodSig is a subclass of Class and therefore both a Box and an IType. Also, it will 1508 1515 return true for .isDescendantOf(.compiler.delegateType). … … 1520 1527 _params = params 1521 1528 _returnTypeProxy = returnTypeProxy 1522 1529 1530 cue init(nativeType as NativeType) 1531 base.init(TokenFix.empty, TokenFix.empty, ClrTypeProxy.cobraNameForSharpBoxName(nativeType.name), 1532 List<of IType>(), List<of String>(), AttributeList(), 1533 LibraryTypeProxy('System.MulticastDelegate'), List<of ITypeProxy>(), 1534 List<of ITypeProxy>(), nil) 1535 _initNativeType(nativeType) 1536 # below are temp placeholders until _scanNativeType runs (no params, void returned) 1537 _params = List<of Param>() 1538 _returnTypeProxy = TypeProxy(.compiler.voidType) 1539 1523 1540 get params from var 1524 1541 1525 1542 get returnTypeProxy from var … … 1529 1546 get resultType as IType? is override 1530 1547 return .returnType 1531 1548 1549 def addRefFields 1550 base.addRefFields 1551 .addField('params', _params) 1552 .addField('returnType', _returnType) 1553 1532 1554 def _bindInh 1533 1555 base._bindInh 1534 1556 assert _baseClass 1535 1557 assert _baseClass.qualifiedName == 'System.MulticastDelegate' 1536 1558 assert .parentBox or .parentNameSpace 1537 1559 assert not _needScanNativeType 1560 1538 1561 def _bindInt 1539 returnType as ITypeProxy = .returnType ? .returnTypeProxy 1540 .addDecl(_makeMethod('invoke', .params.clone, returnType)) 1541 # dynamic type vari length param in list as placeholder for multiple params 1542 params = [Param('vParam', VariTypeIdentifier(.token, TypeIdentifier(.token, DynamicType())))] 1543 .addDecl(_makeMethod('beginInvoke', params, TypeIdentifier(.token.copy('ID', 'IAsyncResult')) to ITypeProxy)) 1544 .addDecl(_makeMethod('endInvoke', params, returnType )) 1562 if not .isFromBinaryLibrary # If From Assembly/Library these methods have already been inserted 1563 # TODO: push these down to _ScanClrType, platform specific. 1564 returnType as ITypeProxy = .returnType ? .returnTypeProxy 1565 .addDecl(_makeMethod('invoke', .params.clone, returnType)) 1566 # dynamic type vari length param in list as placeholder for multiple params 1567 params = [Param('vParam', VariTypeIdentifier(.token, TypeIdentifier(.token, DynamicType())))] 1568 .addDecl(_makeMethod('beginInvoke', params, TypeIdentifier(.token.copy('ID', 'IAsyncResult')) to ITypeProxy)) 1569 .addDecl(_makeMethod('endInvoke', params, returnType )) 1545 1570 base._bindInt 1546 1571 for param in .params 1547 1572 param.bindInt … … 1556 1581 # method body just to avoid a Cobra warning during .bindImp 1557 1582 m.statements.add(ThrowStmt(.token, PostCallExpr(.token, IdentifierExpr(.token, 'Exception'), List<of Expr>()))) 1558 1583 return m 1584 1585 def isAssignableTo(type as IType) as bool is override 1586 r = base.isAssignableTo(type) 1587 if not r 1588 if (nnt = type.nonNil) inherits MethodSig 1589 r = .isAnonymousMatch(nnt) 1590 return r 1591 1592 def isAnonymousMatch(aSig as MethodSig) as bool 1593 """ 1594 Indicate whether this methodSig is an anonymous match for the provided one. 1595 An anonymous match is one that ignores the name but succeeds if the sig returnType and 1596 the count, type and ordering of the parameters is the same. 1597 """ 1598 if .isFromBinaryLibrary 1599 # if from platform Assembly/Library do (minimal) bindings on-demand 1600 if not .didBindInh, .bindInh # TODO: optimise this more 1601 if not .didBindInt, .bindInt 1602 assert aSig.returnType 1603 assert .returnType 1604 #print ' [aSig.name] [.name] ReturnType', aSig.returnType.name, .returnType.name 1605 if not _matchesType(aSig.returnType to !, .returnType to !) 1606 return false 1607 params = .params 1608 otherParams = aSig.params 1609 #print ' ParamCount', otherParams.count, params.count 1610 if otherParams.count <> params.count 1611 return false 1612 for i in params.count 1613 #print ' param([i])', otherParams[i].type.name, params[i].type.name, otherParams[i].type, params[i].type 1614 if not _matchesType(otherParams[i].type, params[i].type) 1615 return false 1616 if otherParams[i].direction <> params[i].direction 1617 return false 1618 return true 1619 1620 def _matchesType(a as IType, b as IType) as bool 1621 if a.nonNil inherits GenericParam or b.nonNil inherits GenericParam 1622 return true 1623 # The above provides a mixed blessing of matches to generic delegates (delegates with generic params) 1624 # of which in 'use'ed assemblies (System specifically) there are a bunch that match common cases. 1625 # Good for Comparable implementations, erroneous hits for pretty much every other simple signature 1626 # See ScanClrType for how this is addressed. 1627 return a.isAssignableTo(b) # is this sufficient? 1628 1629 def toCobraSource as String 1630 s = StringBuilder() 1631 s.append('sig ' + .name ) 1632 if .params.count 1633 s.append('(') 1634 sep = '' 1635 for p in .params 1636 s.append(sep) 1637 sep = ', ' 1638 s.append(p.name) 1639 s.append(' as ') 1640 s.append(p.type.name) 1641 s.append(')') 1642 if .returnType <> .compiler.voidType 1643 s.append(' as ') 1644 s.append(.returnType.name) 1645 return s.toString 1559 1646 1560 1647 class GenericParam inherits CobraType is partial 1561 1648 """ -
Source/Container.cobra
25 25 May return nil if no such member exists. 26 26 Case-sensitive. 27 27 """ 28 29 def sigForMethodSig(msig as MethodSig) as MethodSig? 30 """ 31 Returns the first method signature of this container matching the provided signature, including 32 any inherited methodSignatures ( i.e follows inheritance chain). 33 A 'matching' signature has the same returnType, paramList size and paramList types in the same order. 34 May return nil if no such sig exists. 35 """ 28 36 # TODO: 29 37 # require 30 38 # # TODO: not .compiler.isParsing … … 83 91 var _declsInOrder as List<of TMember> 84 92 var _declsByName as Dictionary<of String, TMember> 85 93 var _declsByNameCI as Dictionary<of String, TMember> 94 var _sigsInOrder as List<of MethodSig> 86 95 var _docString as String 87 96 var _isNames as IList<of String> 88 97 … … 93 102 base.init(token, name) 94 103 _initParent(parent) 95 104 _declsInOrder = List<of TMember>() 105 _sigsInOrder = List<of MethodSig>() 96 106 _declsByName = Dictionary<of String, TMember>() 97 107 _declsByNameCI = Dictionary<of String, TMember>() 98 108 _isNames = isNames.toList … … 161 171 else 162 172 _declsByNameCI.add(decl.name.toLower, decl) 163 173 174 def addSig(signat as MethodSig) 175 _sigsInOrder.add(signat) 176 164 177 def declForName(name as String) as TMember? 165 178 require 166 179 name.length … … 345 358 346 359 def cloneCollections 347 360 _declsInOrder = List<of TMember>(_declsInOrder) 361 _sigsInOrder = List<of MethodSig>(_sigsInOrder) 348 362 _declsByName = Dictionary<of String, TMember>(_declsByName) 349 363 _declsByNameCI = Dictionary<of String, TMember>(_declsByNameCI) 350 351 364 365 def sigForMethodSig(ms as MethodSig) as MethodSig? 366 """ 367 Search inheritance tree for a MethodSig matching the given parameter. 368 Look in this containers siglist for a matching sig, If none recursively look in parent. 369 Return first matching sig or nil if none found 370 """ 371 aSig = _haveSigForMethodSig(ms) 372 if aSig 373 return aSig 374 375 if .parent 376 return .parent.sigForMethodSig(ms) 377 return nil 378 379 def _haveSigForMethodSig(ms as MethodSig) as MethodSig? 380 """Return first matching sig in this container matching the MethodSig parameter or nil if none.""" 381 for aSig in _sigsInOrder 382 #print ms.name, aSig.name 383 if aSig.isAnonymousMatch(ms) 384 return aSig 385 return nil 386 352 387 interface IMember 353 388 is partial 354 389 inherits INamedNode -
Source/BinaryOpExpr.cobra
373 373 _type = leftType 374 374 else if cannotMix 375 375 .throwError('Cannot mix types [_left.type.name] and [_right.type.name] for arithmetic.') 376 else if _left.isKindOf(.compiler.delegateType) 377 _type = tpassthrough # Not really but allows catching += -= below 378 376 379 if _type is nil 377 380 sugg = 'Try finding a method that performs this function.' 378 381 if leftType == rightType … … 404 407 base._bindImp 405 408 # TODO: does NumericPromoExpr cover everything we need? 406 409 # C# and other languages use += and -= on delegates and events, but Cobra does not. 407 if .left.type inherits MethodSig 408 # TODO: error 409 pass 410 else if .left.type.nonNil.isDescendantOf(.compiler.delegateType) 410 if .left.type inherits MethodSig or .left.type.nonNil.isDescendantOf(.compiler.delegateType) 411 411 leftSource = .left.toCobraSource 412 412 rightSource = .right.toCobraSource 413 413 if not .right inherits RefExpr, rightSource = 'ref ' + rightSource -
Source/NameSpace.cobra
264 264 for ud in _useDirectives 265 265 m = ud.extensionMemberFor(box, name) 266 266 if m, return m 267 return if(_superNameSpace, _superNameSpace._extensionMemberFromUseDirectives(box, name), nil) 267 if _superNameSpace 268 m = _superNameSpace._extensionMemberFromUseDirectives(box, name) 269 if m, return m 270 return nil 271 272 def sigForMethodSig(ms as MethodSig) as MethodSig? is override 273 """ 274 Search namespace and UseDirectives for a MethodSig matching the given parameter. 275 Return first matching sig or nil if none found. 276 """ 277 if not .isUnified 278 m = _unifiedNameSpace.sigForMethodSig(ms) 279 if m 280 #print 'MATCH (u-ns [.name])', m.name 281 return m 282 return _sigMethodFromUseDirectives(ms) 283 else 284 asig = _haveSigForMethodSig(ms) # from Container baseclass 285 if asig 286 #print 'MATCH (ns)', asig.name 287 return asig 288 if _superNameSpace 289 s = _superNameSpace._sigMethodFromUseDirectives(ms) 290 if s 291 #print 'MATCH (super-ns)', s.name 292 return s 293 #print 'NO-MATCH (ns [.name])', ms.name 294 return nil 268 295 296 297 def _sigMethodFromUseDirectives(ms as MethodSig) as MethodSig? 298 """ Look for MethodSig in namespaces referenced by the useDirectives""" 299 for ud in _useDirectives 300 #print 'USEDIR', ud.fullName 301 s = ud.sigMethodFor(ms) 302 if s 303 #print 'MATCH (usedir [ud.fullName])', s.name 304 return s 305 if _superNameSpace 306 s = _superNameSpace._sigMethodFromUseDirectives(ms) 307 if s 308 #print 'MATCH (ud super-ns)', s.name 309 return s 310 #print 'NO-MATCH (usedirs)', ms.name 311 return nil 312 313 269 314 def symbolForName(name as String) as IMember? 270 315 if not .isUnified 271 316 x = _unifiedNameSpace.symbolForName(name) … … 276 321 if members.count == 1 277 322 return List<of IMember>(members)[0] # TODO: feels silly. maybe Set should have a .only method with require .count==1 278 323 else if members.count > 1 279 membersList = List<of IMember>(members) 280 membersList.sort(do(a as IMember, b as IMember)) 281 return a.parentNameSpace.fullName.compareTo(b.parentNameSpace.fullName) 282 spaces = (for m in membersList get '"[m.parentNameSpace.fullName]"').join(', ', ' and ') 283 if .compiler and .compiler.nodeStack.peek inherits ISyntaxNode 284 node = .compiler.nodeStack.peek 285 else 286 node = this 287 node.throwError('Ambiguous reference "[name]" found in namespaces [spaces].') 324 _throwAmbiguousRefError(name, members) 288 325 else 289 326 # our decl? 290 327 # TODO: should this come before checking our name? what does C# do? … … 298 335 if x, return x 299 336 #/ 300 337 return nil 301 338 339 def _throwAmbiguousRefError(name as String, members as Set<of IMember>) 340 membersList = List<of IMember>(members) 341 membersList.sort(do(a as IMember, b as IMember)) 342 return a.parentNameSpace.fullName.compareTo(b.parentNameSpace.fullName) 343 spaces = (for m in membersList get '"[m.parentNameSpace.fullName]"').join(', ', ' and ') 344 if .compiler and .compiler.nodeStack.peek inherits ISyntaxNode 345 node = .compiler.nodeStack.peek 346 else 347 node = this 348 node.throwError('Ambiguous reference "[name]" found in namespaces [spaces].') 349 302 350 def _symbolsForNameFromUseDirectives(name as String, members as Set<of IMember>) 303 351 """ 304 352 Populates `members` with all symbols from `use` directives that match `name`. … … 308 356 if x, members.add(x) 309 357 if _superNameSpace 310 358 _superNameSpace._symbolsForNameFromUseDirectives(name, members) 311 359 312 360 def addDecl(decl as INameSpaceMember) is override 313 361 base.addDecl(decl) 314 362 if decl inherits NameSpace … … 332 380 pass 333 381 else 334 382 _unifiedNameSpace.addDecl(decl) 383 if decl inherits MethodSig 384 base.addSig(decl) 335 385 336 386 def addUseDirective(ud as UseDirective) 337 387 _useDirectives.add(ud) … … 403 453 .addField('boundNameSpace', _boundNameSpace) 404 454 405 455 get boundNameSpace from var 456 get fullName from var 406 457 407 458 def extensionMemberFor(box as Box, name as String) as IMember? 408 459 require .didBindUse … … 411 462 def findSymbol(name as String) as IMember? 412 463 require .didBindUse 413 464 return _boundNameSpace.symbolForName(name) 465 466 def sigMethodFor(ms as MethodSig) as MethodSig? 467 require .didBindUse 468 return _boundNameSpace.sigForMethodSig(ms) -
Source/CobraParser.cobra
1671 1671 possibleVarDef = .curBox.declForName(varName) 1672 1672 if not possibleVarDef 1673 1673 if not initExpr and not declVarType 1674 #TODO: hops support __varname as target 1674 1675 .throwError('There is no variable named "[varName]" to match the property "[name]".') 1675 1676 varDef = BoxVar(token, token, .curBox, varName, declVarType, List<of String>(_isNamesStack), initExpr, nil, 'Automatic backing var for property "[name]".') 1676 1677 .curBox.addDecl(varDef) -
Tests/120-classes/320-construct-prop-set.cobra
1 sig DoSomethingSig 2 # Signature hoisted for ref inference Jun-2010. 3 #Needs to be accessible to both class X and class Stuff 4 # (or add a Sig to class X compatible with one in class Stuff) 5 1 6 class X 2 7 3 8 shared … … 67 72 pro style from var 68 73 69 74 70 sig DoSomethingSig 75 # this sig needs to be accessible to both Stuff and X 76 #sig DoSomethingSig 71 77 72 78 pro doSomething from var as DoSomethingSig? 73 79 -
Tests/320-misc-two/820-anonymous-methods-aka-closures/210-anonymous-method-assign.cobra
1 class TestAnonMethodAssign 2 3 sig RetInt(a as int, b as int) as int 4 sig RetStr(a as int, b as int) as String 5 6 def main is shared 7 t = [4, 7, 1, 2, 3] 8 t1=t 9 10 # embedded closure 11 t.sort(do(a as int, b as int)) 12 return a.compareTo(b) 13 assert t == [1,2,3,4,7] 14 15 # store closure in local var 16 c as Comparison<of int> = do(a as int, b as int) 17 return a.compareTo(b) 18 t1.sort(c) 19 assert t1 == [1,2,3,4,7] 20 21 # this should work shouldnt it ? 22 /#c0 = do(a as int, b as int) as int 23 return a - b 24 t1.sort(c0) 25 print t1 26 print .x(c0) 27 #/ 28 29 # now try with various combinations of typing and inference 30 c1 as RetStr = do(a as int, b as int) as String 31 return '[a] - [b]' 32 assert .xs(c1) == '10 - 5' 33 34 # infer (and match to existing sig) variable type 35 c2 = do(a as int, b as int) as String 36 return '[a]xx - [b]xx' 37 assert c2.typeOf == RetStr 38 assert .xs(c2) == '10xx - 5xx' 39 40 c3 = do(a as int, b as int) #infer returnType 41 return '[a]xy - [b]xy' 42 assert c3.typeOf == RetStr 43 assert .xs(c3) == '10xy - 5xy' 44 45 def x( m as RetInt) as int is shared 46 return m(10, 5) 47 48 def xs( m as RetStr) as String is shared 49 return m(10, 5) 50 -
Tests/320-misc-two/830-lambdas/310-lambda-assign.cobra
1 class LambdaAssign 2 3 sig RetInt(a as int, b as int) as int 4 sig RetStr(a as int, b as int) as String 5 6 def main is shared 7 t = [4, 7, 1, 2, 3] 8 t1=t 9 10 # embedded closure 11 t.sort(do(a as int, b as int) = a.compareTo(b)) 12 assert t == [1,2,3,4,7] 13 14 # store closure in local var 15 c as Comparison<of int> = do(a as int, b as int) = a.compareTo(b) 16 t1.sort(c) 17 assert t1 == [1,2,3,4,7] 18 19 # this should work shouldnt it ? 20 # evidently not 21 /#c0 = do(a as int, b as int) = a - b 22 t1.sort(c0) 23 print t1 24 print .x(c0) 25 #/ 26 27 # now try with various combinations of typing and inference 28 c1 as RetStr = do(a as int, b as int) = '[a] - [b]' 29 assert .xs(c1) == '10 - 5' 30 31 c2 = do(a as int, b as int) = '[a]xx - [b]xx' 32 assert c2.typeOf == RetStr 33 assert .xs(c2) == '10xx - 5xx' 34 35 #infer returnType 36 c3 = do(a as int, b as int) = 10*a -b 37 assert c3.typeOf == RetInt 38 assert .x(c3) == 95 39 40 def x( m as RetInt) as int is shared 41 return m(10, 5) 42 43 def xs( m as RetStr) as String is shared 44 return m(10, 5) 45 -
Tests/220-delegates-etc/100-delegates/112-declare-sig-inside-class.cobra
32 32 33 33 class Program 34 34 35 # need this additional sig type now ref type inference is implemented 36 # and searching for compat sig only up inheritance tree and 37 # 'use'ed namespaces. 38 # Test is now that the sig types in each class are assignment compatible 39 sig BinaryOpP(a as int, b as int) as int 40 35 41 def main is shared 36 42 Program().run 37 43 -
Tests/220-delegates-etc/100-delegates/172-infer-ref-type-no-sig.cobra
1 # Ref type inference and methodSig auto generation and injection 2 class MyType 3 pass 4 5 class AutoGenMethodSig 6 #sig MethNoArg 7 8 # non simple signature that doesnt collide with any generic System delegates 9 # e.g System.Action (one arg, no return), 10 # System.EventHandler(2 args, no return), 11 # System.Comparison(2 args, int return) 12 def methUnknown(r as MyType, r1 as MyType) as MyType 13 return r 14 15 def methUnknown2(r as MyType, r1 as MyType) as MyType 16 return r1 17 18 def methAction0 19 pass 20 21 def methAction(r as MyType) 22 pass 23 24 def main is shared 25 c = AutoGenMethodSig() 26 27 meUnk = ref c.methUnknown # .warning. No signature matching 28 assert meUnk.typeOf == SigFor_methUnknown # autogen Sig and inserted 29 30 meUnk2 = ref c.methUnknown2 31 assert meUnk2.typeOf == SigFor_methUnknown # found autogen Sig 32 33 # was matchiung to CrossAppDomainDelegate 34 meAct0 = ref c.methAction0 # .warning. No signature matching 35 assert meAct0.typeOf == SigFor_methAction0 36 #assert meAct0.typeOf == MethNoArg 37 38 # was matching to Converter<to,> 39 meAct1 = ref c.methAction # .warning. No signature matching 40 print meAct1 41 -
Tests/220-delegates-etc/100-delegates/170-infer-ref-type.cobra
1 # Test Ref type inference and matching autogenerated ref sig 2 # to App or system MethodSigs 3 4 sig SigForMethOuter(s as String) 5 6 class RefType 7 8 sig SigForMethInner(a as int) 9 sig SigForDynamic(a as dynamic?) as bool 10 11 def meth(a as int) 12 print a 13 14 def methOuter(s as String) 15 print s 16 17 def methUnknown(r) 18 pass 19 20 def methConcDy(a as Object?) as bool 21 return false 22 23 # EventHandler 24 def handleEvent( src as Object, args as EventArgs) 25 pass 26 27 # ResolveEventHandler 28 def handleResolveEvent(sender as Object, args as ResolveEventArgs) as System.Reflection.Assembly? 29 return System.Reflection.Assembly.getExecutingAssembly 30 31 def chkMySig 32 me = ref .meth 33 assert me.typeOf == SigForMethInner 34 35 def main is shared 36 c = RefType() 37 c.chkMySig 38 39 me = ref c.meth # auto type me 40 assert me.typeOf == SigForMethInner 41 42 me1 = ref c.methOuter 43 assert me1.typeOf == SigForMethOuter 44 45 46 # equivalence Object? and dynamic arg 47 mdy = ref c.methConcDy 48 assert mdy.typeOf == SigForDynamic 49 50 # match to System MethodSigs (from use assembly/dll) 51 meh = ref c.handleEvent 52 assert meh.typeOf == System.EventHandler 53 54 meres = ref c.handleResolveEvent 55 assert meres.typeOf == System.ResolveEventHandler 56 57 # ticket 140 58 for x in [ref c.meth, ref c.meth] 59 assert x.typeOf == SigForMethInner 60 61 for y in [ref c.methOuter, ref c.methOuter] 62 assert y.typeOf == SigForMethOuter 63 64 #meUnk = ref c.methUnknown 65 #print 'me2', meUnk 66 67 -
Tests/220-delegates-etc/100-delegates/100-basics.cobra
1 sig SigCompareInt(a as int, b as int) as int 2 # Above Add for ref inference Jun-2010. Not find/match generic delegate 3 1 4 class X 2 5 3 6 def main is shared -
Developer/IntermediateReleaseNotes.text
60 60 61 61 * Enumeration members can now be placed on the same line separated by commas. 62 62 63 * Provide type inference on ref expressions (find matching Sigs for ref to method) : tickets:39,40,138 64 similarly also provide correct type inference (to a method sig) on lambdas and anon methods. tickets:204 63 65 64 66 ================================================================================ 65 67 Library