Ticket #74: ticket74.patch
File ticket74.patch, 10.3 KB (added by eric.sellon, 15 years ago) |
---|
-
Source/Members.cobra
1435 1435 for member in _members 1436 1436 member.unNilReturnType 1437 1437 1438 def computeBestOverload(args as List<of Expr>, genericArgTypes as List<of IType>?, strictBindChecking as bool) as BoxMember 1439 # References: 1440 # http://blogs.msdn.com/ericlippert/archive/2007/11/05/c-3-0-return-type-inference-does-not-work-on-member-groups.aspx 1441 1442 # I cooked up the algorithm below as a quick way to fix some bugs caused by the previous 1443 # implementation of um, doing nothing. 1444 # But this likely needs to be rewritten. 1445 candidates = [] 1446 # handle generic arguments to the method 1447 if genericArgTypes and genericArgTypes.count 1448 members = List<of BoxMember>() 1449 for member as BoxMember? in .members 1450 if member inherits Method 1451 if member.containsGenericParameters 1452 if member.genericParams.count == genericArgTypes.count 1453 member = member.constructedMethodWith(genericArgTypes to !) 1454 else 1455 member = nil 1456 if member, members.add(member) 1457 else 1458 members = .members 1459 1460 for member in members 1461 score = -1000 1462 if member.params.count == args.count 1463 score = 0 1464 if member inherits Method and (member to Method).genericParams.count > 0, score += 1 1465 for i, param in member.params.numbered 1466 arg = args[i] 1467 if strictBindChecking and not arg.didBindImp 1468 trace arg 1469 trace arg.hasError 1470 if strictBindChecking and (arg.type == param.type or arg.type == param.type.nonNil) 1471 score += 20 1472 else if strictBindChecking and arg.canBeAssignedTo(param.type) 1473 score += 10 1474 else if strictBindChecking and arg.type.nonNil.isAssignableTo(param.type) 1475 # Cobra's code and data flow analysis sometimes leaves us with a nilable type that's not actually nil anymore 1476 # due to an assignment, possibly wrapped in an if statement. Eventually this will be corrected, but for now 1477 # compensate here. 1478 score += 1 1479 else if not strictBindChecking 1480 if arg.type is not nil 1481 if arg.type == param.type 1482 score += 20 1483 else if arg.type.isDynamic 1484 score += 10 1485 else 1486 score -= 100 1487 else 1488 score -= 100 1489 # print 'candidate:', score, member.name, member.serialNum, Utils.join(', ', (for param in member.params get param.type.name)) 1490 candidates.add([score, member]) 1491 1492 maxScore = -10_000 1493 winner = nil to BoxMember? 1494 for pair in candidates 1495 if false, print pair[0], (pair[1] to BoxMember).idString 1496 if pair[0] to int > maxScore 1497 maxScore = pair[0] to int 1498 winner = pair[1] to BoxMember 1499 1500 if false 1501 # detect overload invocation ambiguity 1502 # TODO: not ready for this yet 1503 count = 0 1504 for pair in candidates 1505 if pair[0] to int == maxScore 1506 count += 1 1507 if count > 1 1508 # TODO: do this for indexing too 1509 msg = 'The call is ambiguous between these methods: ' 1510 sep = '' 1511 for pair in candidates 1512 if pair[0] to int == maxScore 1513 msg += sep + (pair[1] to AbstractMethod).cobraSourceSignature(false) 1514 sep = ', ' 1515 .throwError(msg) 1516 1517 if false 1518 print 1519 trace .token.fileName 1520 trace maxScore, _name 1521 trace .token.toTechString 1522 trace winner 1523 print 'args:' 1524 for arg in args 1525 print ' [arg]' 1526 print 'params:' 1527 for param in winner.params 1528 print ' [param]' 1529 print 'overloads:' 1530 for member in .members 1531 print ' [member]' 1532 # print 'winner:', score, winner 1533 assert winner 1534 return winner to ! 1535 1438 1536 def _bindInt is override 1439 1537 base._bindInt 1440 1538 # sanity check that members all have the right name -
Source/Expr.cobra
590 590 # http://www.google.com/search?hl=en&q=C%23+overloaded+method+resolution 591 591 # TODO: handle type inference for generic members. See the C# spec for details. 592 592 593 winner = _computeBestOverload(definition, args)593 winner = definition.computeBestOverload(.args, .genericArgTypes, true) 594 594 sharp'definition = winner' 595 595 type = winner.resultType 596 596 else … … 695 695 .compiler.recordError(ne) 696 696 num += 1 697 697 698 def _computeBestOverload(definition as MemberOverload, args as List<of Expr>) as BoxMember699 # References:700 # http://blogs.msdn.com/ericlippert/archive/2007/11/05/c-3-0-return-type-inference-does-not-work-on-member-groups.aspx701 702 # I cooked up the algorithm below as a quick way to fix some bugs caused by the previous703 # implementation of um, doing nothing.704 # But this likely needs to be rewritten.705 candidates = []706 # handle generic arguments to the method707 genericArgTypes = .genericArgTypes708 if genericArgTypes and genericArgTypes.count709 members = List<of BoxMember>()710 for member as BoxMember? in definition.members711 if member inherits Method712 if member.containsGenericParameters713 if member.genericParams.count == genericArgTypes.count714 member = member.constructedMethodWith(genericArgTypes to !)715 else716 member = nil717 if member, members.add(member)718 else719 members = definition.members720 721 for member in members722 score = -1000723 if member.params.count == args.count724 score = 0725 if member inherits Method and (member to Method).genericParams.count > 0, score += 1726 for i, param in member.params.numbered727 arg = args[i]728 if not arg.didBindImp729 trace arg730 trace arg.hasError731 if arg.type == param.type or arg.type == param.type.nonNil732 score += 20733 else if arg.canBeAssignedTo(param.type)734 score += 10735 else if arg.type.nonNil.isAssignableTo(param.type)736 # Cobra's code and data flow analysis sometimes leaves us with a nilable type that's not actually nil anymore737 # due to an assignment, possibly wrapped in an if statement. Eventually this will be corrected, but for now738 # compensate here.739 score += 1740 else741 score -= 100742 # print 'candidate:', score, member.name, member.serialNum, Utils.join(', ', (for param in member.params get param.type.name))743 candidates.add([score, member])744 745 maxScore = -10_000746 winner = nil to BoxMember?747 for pair in candidates748 if false, print pair[0], (pair[1] to BoxMember).idString749 if pair[0] to int > maxScore750 maxScore = pair[0] to int751 winner = pair[1] to BoxMember752 753 if false754 # detect overload invocation ambiguity755 # TODO: not ready for this yet756 count = 0757 for pair in candidates758 if pair[0] to int == maxScore759 count += 1760 if count > 1761 # TODO: do this for indexing too762 msg = 'The call is ambiguous between these methods: '763 sep = ''764 for pair in candidates765 if pair[0] to int == maxScore766 msg += sep + (pair[1] to AbstractMethod).cobraSourceSignature(false)767 sep = ', '768 .throwError(msg)769 770 if false771 print772 trace .token.fileName773 trace maxScore, _name774 trace .token.toTechString775 trace winner776 print 'args:'777 for arg in args778 print ' [arg]'779 print 'params:'780 for param in winner.params781 print ' [param]'782 print 'overloads:'783 for member in definition.members784 print ' [member]'785 # print 'winner:', score, winner786 assert winner787 return winner to !788 789 698 def _didVariArgs(definition as BoxMember) as bool 790 699 hasVari = false 791 700 for param in definition.params … … 1762 1671 _type = .compiler.dynamicType 1763 1672 else if exprType inherits Box 1764 1673 _type = expr.receiverType # for example, an IdentifierExpr of 'SomeClass' has a .receiverType of that class 1674 _handleClassInitializer 1765 1675 else if exprType.isDynamic 1766 1676 _type = .compiler.nilableDynamicType 1767 1677 else if expr.definition inherits NameSpace … … 1846 1756 sb.append(')') 1847 1757 return sb.toString 1848 1758 1759 def _handleClassInitializer 1760 initCall as Initializer? 1761 if .args.count > 0 1762 theClass = .compiler.symbolForName(.name, true, false, true) to ClassOrStruct? 1763 if theClass is not nil 1764 possibleCalls = theClass.memberForName("cue.init") 1765 if possibleCalls is nil 1766 pass # TODO: determine if this is an error or if support for base class init functions need to be added 1767 else if possibleCalls inherits MemberOverload 1768 initCall = possibleCalls.computeBestOverload(.args, nil, false) to Initializer? 1769 else if possibleCalls inherits Initializer 1770 initCall = possibleCalls 1771 #else 1772 # TODO: determine if this is an error 1773 #print initCall 1774 if initCall is not nil and .args.count == initCall.params.count 1775 i = 0 1776 for arg in .args 1777 if arg.type is not nil and arg.type.isDynamic 1778 # set context type so that backend can type cast it correctly 1779 arg.contextType = initCall.params[i].type 1780 i += 1 1781 #else 1782 # TODO: warning or error? 1849 1783 1784 1850 1785 class RefExpr 1851 1786 is partial 1852 1787 inherits Expr -
Tests/500-dynamic/310-dynamic-init-params.cobra
1 class X 2 3 var _intvar as int 4 var _string1 as String 5 var _string2 as String 6 7 cue init(i as int) 8 .init(i, '', '') 9 10 cue init(i as int, s as String) 11 .init(i, s, '') 12 13 cue init(s as String, i as int) 14 .init(i, s, '') 15 16 cue init(i as int, s1 as String, s2 as String) 17 base.init 18 _intvar = i 19 _string1 = s1 20 _string2 = s2 21 22 cue init(s1 as String, i as int, s2 as String) 23 .init(i, s1, s2) 24 25 cue init(s1 as String, s2 as String, i as int) 26 .init(i, s1, s2) 27 28 def foo 29 print 'foo: [_intvar]; [_string1]; [_string2]' 30 31 class F 32 33 def main 34 myint = 5 35 mystr1 = 'mystr1' 36 mystr2 = 'mystr2' 37 dyint = 6 to dynamic 38 dystr1 = 'dystr1' to dynamic 39 dystr2 = 'dystr2' to dynamic 40 41 x = X(myint) 42 x.foo 43 x = X(dyint) 44 x.foo 45 x = X(myint, mystr1) 46 x.foo 47 x = X(dyint, mystr1) 48 x.foo 49 x = X(myint, dystr1) 50 x.foo 51 x = X(dyint to int, dystr1) 52 x.foo 53 x = X(dyint, dystr1 to String) 54 x.foo 55 x = X(mystr1, myint) 56 x.foo 57 x = X(dystr1, dyint to int) 58 x.foo 59 x = X(dyint to int, dystr1, mystr2) 60 x.foo 61 x = X(mystr1, dyint, mystr2) 62 x.foo 63 x = X(dystr1, dystr2, myint) 64 x.foo