Wiki

Ticket #74: ticket74.patch

File ticket74.patch, 10.3 KB (added by eric.sellon, 8 years ago)
  • Source/Members.cobra

     
    14351435        for member in _members 
    14361436            member.unNilReturnType 
    14371437 
     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     
    14381536    def _bindInt is override 
    14391537        base._bindInt 
    14401538        # sanity check that members all have the right name 
  • Source/Expr.cobra

     
    590590                            # http://www.google.com/search?hl=en&q=C%23+overloaded+method+resolution 
    591591                            # TODO: handle type inference for generic members. See the C# spec for details. 
    592592                         
    593                             winner = _computeBestOverload(definition, args) 
     593                            winner = definition.computeBestOverload(.args, .genericArgTypes, true) 
    594594                            sharp'definition = winner' 
    595595                            type = winner.resultType 
    596596                        else 
     
    695695                .compiler.recordError(ne) 
    696696            num += 1 
    697697 
    698     def _computeBestOverload(definition as MemberOverload, args as List<of Expr>) as BoxMember 
    699         # References: 
    700         # http://blogs.msdn.com/ericlippert/archive/2007/11/05/c-3-0-return-type-inference-does-not-work-on-member-groups.aspx 
    701  
    702         # I cooked up the algorithm below as a quick way to fix some bugs caused by the previous  
    703         # implementation of um, doing nothing. 
    704         # But this likely needs to be rewritten. 
    705         candidates = [] 
    706         # handle generic arguments to the method 
    707         genericArgTypes = .genericArgTypes 
    708         if genericArgTypes and genericArgTypes.count 
    709             members = List<of BoxMember>() 
    710             for member as BoxMember? in definition.members 
    711                 if member inherits Method 
    712                     if member.containsGenericParameters 
    713                         if member.genericParams.count == genericArgTypes.count 
    714                             member = member.constructedMethodWith(genericArgTypes to !) 
    715                         else 
    716                             member = nil 
    717                 if member, members.add(member) 
    718         else 
    719             members = definition.members 
    720  
    721         for member in members 
    722             score = -1000 
    723             if member.params.count == args.count 
    724                 score = 0 
    725                 if member inherits Method and (member to Method).genericParams.count > 0, score += 1 
    726                 for i, param in member.params.numbered 
    727                     arg = args[i] 
    728                     if not arg.didBindImp 
    729                         trace arg 
    730                         trace arg.hasError 
    731                     if arg.type == param.type or arg.type == param.type.nonNil 
    732                         score += 20 
    733                     else if arg.canBeAssignedTo(param.type) 
    734                         score += 10 
    735                     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 anymore 
    737                         # due to an assignment, possibly wrapped in an if statement. Eventually this will be corrected, but for now 
    738                         # compensate here. 
    739                         score += 1 
    740                     else 
    741                         score -= 100 
    742             # 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_000 
    746         winner = nil to BoxMember? 
    747         for pair in candidates 
    748             if false, print pair[0], (pair[1] to BoxMember).idString 
    749             if pair[0] to int > maxScore 
    750                 maxScore = pair[0] to int 
    751                 winner = pair[1] to BoxMember 
    752  
    753         if false 
    754             # detect overload invocation ambiguity 
    755             # TODO: not ready for this yet 
    756             count = 0 
    757             for pair in candidates 
    758                 if pair[0] to int == maxScore 
    759                     count += 1 
    760             if count > 1 
    761                 # TODO: do this for indexing too 
    762                 msg = 'The call is ambiguous between these methods: ' 
    763                 sep = '' 
    764                 for pair in candidates 
    765                     if pair[0] to int == maxScore 
    766                         msg += sep + (pair[1] to AbstractMethod).cobraSourceSignature(false) 
    767                         sep = ', ' 
    768                 .throwError(msg) 
    769  
    770         if false 
    771             print 
    772             trace .token.fileName 
    773             trace maxScore, _name 
    774             trace .token.toTechString 
    775             trace winner 
    776             print 'args:' 
    777             for arg in args 
    778                 print '   [arg]' 
    779             print 'params:' 
    780             for param in winner.params 
    781                 print '   [param]' 
    782             print 'overloads:' 
    783             for member in definition.members 
    784                 print '   [member]' 
    785         # print 'winner:', score, winner 
    786         assert winner 
    787         return winner to ! 
    788  
    789698    def _didVariArgs(definition as BoxMember) as bool 
    790699        hasVari = false 
    791700        for param in definition.params 
     
    17621671                _type = .compiler.dynamicType 
    17631672            else if exprType inherits Box 
    17641673                _type = expr.receiverType  # for example, an IdentifierExpr of 'SomeClass' has a .receiverType of that class 
     1674                _handleClassInitializer 
    17651675            else if exprType.isDynamic 
    17661676                _type = .compiler.nilableDynamicType 
    17671677            else if expr.definition inherits NameSpace 
     
    18461756        sb.append(')') 
    18471757        return sb.toString 
    18481758 
     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? 
    18491783 
     1784 
    18501785class RefExpr 
    18511786    is partial 
    18521787    inherits Expr 
  • Tests/500-dynamic/310-dynamic-init-params.cobra

     
     1class 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 
     31class 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