Show
Ignore:
Timestamp:
08/28/08 04:00:40 (4 months ago)
Author:
Chuck.Esterbrook
Message:

Added support for "extended initializers" which allow you to set properties of the object in the same call being used to create the object.

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • cobra/trunk/Source/Expr.cobra

    r1590 r1591  
    13531353        var _expr as Expr 
    13541354        var _args as List<of Expr> 
     1355        var _hasKeywordArg as bool  # such as Foo(1, a=2) 
     1356        var _isForAttribute as bool  # see Attributes.cobra 
     1357        var _helperMethod as Method? 
    13551358 
    13561359        def init(token as IToken, expr as Expr, args as List<of Expr>) 
     
    13641367                .addField('expr', _expr) 
    13651368                .addField('args', _args) 
     1369                .addField('hasKeywordArg', .hasKeywordArg) 
     1370                .addField('isForAttribute', .isForAttribute) 
    13661371 
    13671372        get expr from var 
     
    13691374        get args from var 
    13701375                has Subnodes 
     1376 
     1377        get hasKeywordArg from var 
     1378 
     1379        pro isForAttribute from var 
    13711380 
    13721381        get hasError as bool is override 
     
    14121421                                return                                   
    14131422 
    1414                 for arg in _args 
     1423                for arg in .args 
    14151424                        try 
    14161425                                if arg inherits AssignExpr 
     1426                                        _hasKeywordArg = true # uu 
     1427                                        # TODO: check that left side is an IdentfierExpr 
     1428                                        # TODO: check property name 
    14171429                                        arg.right.bindImp  # 'x=y' has special treatment in arguments 
    14181430                                else 
     1431                                        if _hasKeywordArg 
     1432                                                .throwError('Cannot have a non-keyword argument ("[arg.toCobraSource]") after a keyword argument. All positional arguments must come before all keyword arguments.') 
    14191433                                        arg.bindImp 
    14201434                        catch ne as NodeException 
     
    14481462                                assert false, expr 
    14491463 
     1464                if .hasKeywordArg and not .isForAttribute  # uu 
     1465                        _makeHelperMethod 
     1466                         
     1467        def _makeHelperMethod 
     1468                """ 
     1469                Add a private helper method to the current box to support extended initializer. 
     1470 
     1471                Foo(expr0, expr1, bar=expr2) --> 
     1472                        call: 
     1473                                _ch_ext_init_1207(expr0, expr1, expr2) 
     1474                        def: 
     1475                                def _ch_ext_init_1207(arg0 as int, arg1 as int, /#bar=#/arg2 as int) 
     1476                                        obj = Foo(arg0, arg1) 
     1477                                        obj.bar = arg2 
     1478                                        return obj 
     1479                """ 
     1480                box = .compiler.curBox 
     1481                paramsForDecl = List<of Param>() 
     1482                argsForInitCall = List<of Expr>()  # args to pass to `Foo(arg0, arg1)` 
     1483                propsToSet = List<of AssignExpr>()  # props to set as `obj.bar = arg2` etc. 
     1484                firstPropArg = -1 
     1485                i = 0 
     1486                for arg in .args 
     1487                        if arg inherits AssignExpr 
     1488                                propsToSet.add(arg) 
     1489                                if firstPropArg == -1, firstPropArg = i 
     1490                                arg = arg.right 
     1491                        else 
     1492                                argsForInitCall.add(arg) 
     1493                        paramsForDecl.add(Param(box.token.copy('ID', 'arg[i]'), arg.type)) 
     1494                        i += 1 
     1495                name = '_ch_ext_init_[.serialNum]'  # ch = class helper, ext = extended, init = initializer 
     1496                token = box.token.copy 
     1497                m = Method(token.copy('ID', name), box, name, paramsForDecl, _type, nil, ['shared'], AttributeList(), '') 
     1498                m.locals.add(LocalVar(token.copy('ID', 'obj'), .type)) 
     1499 
     1500                objId = IdentifierExpr(token.copy('ID', 'obj'), 'obj') 
     1501                callExpr = PostCallExpr(token.copy('ID', .type.name), IdentifierExpr(token.copy('ID', .type.name), .type), argsForInitCall) 
     1502                assign = AssignExpr(token.copy('ASSIGN', '='), 'ASSIGN', objId, callExpr) 
     1503                m.addStmt(assign) 
     1504 
     1505                i = firstPropArg 
     1506                for propSetExpr in propsToSet 
     1507                        propName = (propSetExpr.left to IdentifierExpr).name 
     1508                        memberExpr = DotExpr(token.copy('DOT', '.'), 'DOT', IdentifierExpr(token.copy('ID', 'obj')), MemberExpr(token.copy('ID', propName))) 
     1509                        assign = AssignExpr(token.copy('ASSIGN', '='), 'ASSIGN', memberExpr, IdentifierExpr(token.copy('ID', 'arg[i]'))) 
     1510                        m.addStmt(assign) 
     1511                        i += 1 
     1512 
     1513                retStmt = ReturnStmt(token.copy('RETURN', 'return'), IdentifierExpr(token.copy('ID', 'obj'), 'obj')) 
     1514                m.addStmt(retStmt) 
     1515 
     1516                m.bindAll 
     1517                box.addDecl(m) 
     1518                _helperMethod = m 
     1519 
    14501520        def toCobraSource as String is override 
    14511521                sb = StringBuilder() 
     
    14531523                sb.append('(') 
    14541524                sep = '' 
    1455                 for arg in _args 
     1525                for arg in .args 
    14561526                        sb.append(sep) 
    14571527                        sb.append(arg.toCobraSource)