Changeset 1704
- Timestamp:
- 10/25/08 00:42:49 (2 months ago)
- Location:
- cobra/trunk
- Files:
-
- 7 modified
-
Developer/IntermediateReleaseNotes.text (modified) (1 diff)
-
Source/CobraParser.cobra (modified) (7 diffs)
-
Source/Compiler.cobra (modified) (1 diff)
-
Source/Statements.cobra (modified) (3 diffs)
-
Source/Types.cobra (modified) (1 diff)
-
Tests/110-basics-two/910-multi-assign.cobra (modified) (3 diffs)
-
Tests/110-basics-two/912-multi-assign.cobra (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
cobra/trunk/Developer/IntermediateReleaseNotes.text
r1703 r1704 21 21 .code 22 22 a,b,c = ['val1', 'val2', 'val3'] 23 23 Also support such assignment in for statements for (generic) dictionaries and lists 24 .code 25 for key, value in aDictionary 26 trace key, value 27 for a, b in [[1, 2], [3, 4]] 28 print a + b 24 29 25 30 * Added support for a new compiler directive 'args' that takes command line options and applies them to the compilation environment from that point on. -
cobra/trunk/Source/CobraParser.cobra
r1702 r1704 1991 1991 """ 1992 1992 numeric for int x = 0 up to n step 2 1993 enumerable for Customer cust in customers 1993 enumerable for cust as Customer in customers 1994 for k, v in dict 1995 for i, j, k in listOfThrees 1994 1996 """ 1995 1997 token = .expect('FOR') 1996 1998 varr = .nameExpr 1999 if .optional('COMMA') # forStmt multiarg for v1,... 2000 args = .commaSepNameIds(['IN' ,'EOL']) 2001 if .last.which <> 'IN' 2002 .throwError("Comma separated nameId list in forStatement needs to terminate with an IN token ('in')") 2003 if args.count == 0 # "for v1, in ..." single multiarg variable 2004 .undo # 'in' token 2005 return .forStmt(token, varr) 2006 else 2007 args.insert(0, varr) 2008 what = .expression 2009 name = 'forEnumVar[what.serialNum]' # will get made more unique by For Stmt 2010 nameToken = token.copy('ID', name) 2011 varr = IdentifierExpr(nameToken, name) 2012 return ForEnumerableStmt(token, varr, args, what, .block) 2013 2014 # forStmt single variable assign - for v {in,=} ... 1997 2015 peek = .peek.which 1998 2016 if peek=='ASSIGN' … … 2704 2722 args = .commaSepIds(['ASSIGN', 'EOL']) 2705 2723 if .last.which <> 'ASSIGN' 2706 .throwError( "Comma separated multiArg identifier list needs to end with an assignment ('=')")2724 .throwError('Comma separated identifier list needs to end with an assignment ("=").') 2707 2725 assignTkn = .last 2708 2726 rhs = .expression … … 2746 2764 stmts.add(AssignExpr(assignTkn, assignTkn.which, id , idxExpr)) 2747 2765 count += 1 2748 #return BlockStmt(token.copy('INDENT', ''), stmts) 2749 # if prefer exception when nArgs > nRHSExprs Uncomment above line and lose lines below 2750 tryBlock = BlockStmt(token.copy('INDENT',''), stmts) 2751 catchBlocks = List<of CatchBlock>() 2752 catchStmts = List<of Stmt>() 2753 catchStmts.add(PassStmt(token.copy('PASS', 'pass'))) 2754 catchBlock = BlockStmt(token.copy('INDENT',''), catchStmts) 2755 catchType = TypeIdentifier(token.copy('ID', 'IndexOutOfRangeException')) 2756 catchBlocks.add(CatchBlock(token.copy('CATCH', 'catch'), catchType, catchBlock)) 2757 # 'IndexOutOfRangeException' for Arrays and Strings 2758 catchType = TypeIdentifier(token.copy('ID', 'ArgumentOutOfRangeException')) 2759 catchBlocks.add(CatchBlock(token.copy('CATCH', 'catch'), catchType, catchBlock)) 2760 # 'ArgumentOutOfRangeException' for others, probably something else yet to find 2761 return TryStmt(token.copy('TRY', 'try'), tryBlock, catchBlocks, nil, nil) 2766 return BlockStmt(token.copy('INDENT', ''), stmts) 2762 2767 2763 2768 def callExpr as Expr … … 2863 2868 return exprs 2864 2869 2865 def commaSepIds(terminators as IList<of String>) as List<of Expr> 2866 """ 2870 def commaSepNameIds(terminators as IList<of String>) as List<of Expr> 2871 return _commaSepLValues(terminators, true) 2872 2873 def commaSepIds(terminators as IList<of String>) as List<of Expr> 2874 return _commaSepLValues(terminators, false) 2875 2876 def _commaSepLValues(terminators as IList<of String>, expectingNameIds as bool ) as List<of Expr> 2877 """ 2878 pickup comma sep stream of Identifiers or NameIds 2867 2879 Example source 2868 2880 ... idexpr, TERMINATOR … … 2870 2882 ... idexpr, idexpr, ... TERMINATOR 2871 2883 Returns 2872 A list of Identifier Expressions ([DotExpr] IdentifiersExpr) 2873 Notes 2874 The terminator token is consumed, but can be examined with .last. 2884 A list of Identifier Expressions ([DotExpr] IdentifiersExpr) or NameIds 2875 2885 """ 2876 2886 expectSep = false … … 2888 2898 .newOpStack 2889 2899 try 2890 exprs.add(.idExpression(0, nil)) 2900 if expectingNameIds 2901 exprs.add(.nameExpr) 2902 else 2903 exprs.add(.idExpression(0,nil)) 2891 2904 finally 2892 2905 .delOpStack … … 3453 3466 state=1 3454 3467 else if token.which == 'ID' 3455 if not (token.text[0] == '_' or Utils.startsWithLowerLetter(token.text))3456 break3457 3468 state = 2 3458 3469 else if token.which == 'COMMA' -
cobra/trunk/Source/Compiler.cobra
r1696 r1704 1243 1243 return _libraryClass('System.Collections.Generic.List<of>') 1244 1244 1245 def idictionaryOfType as Class 1246 return _libraryClass('System.Collections.Generic.IDictionary<of,>') 1245 def idictionaryType as Box 1246 return _libraryBox('System.Collections.IDictionary') 1247 1248 def idictionaryOfType as Box 1249 return _libraryBox('System.Collections.Generic.IDictionary<of,>') 1247 1250 1248 1251 def dictionaryOfType as Class -
cobra/trunk/Source/Statements.cobra
r1699 r1704 522 522 var _what as Expr 523 523 var _varNumber as int 524 var _multiArgs as List<of Expr>? # actually contains NameExprs 524 525 525 526 def init(token as IToken, varr as NameExpr, what as Expr, block as BlockStmt) … … 527 528 _what = what 528 529 530 def init(token as IToken, varr as NameExpr, args as List<of Expr>, what as Expr, block as BlockStmt) 531 # multiArg assignment in for stmt 532 .init(token, varr, what, block) 533 _multiArgs = args 534 529 535 def addSubFields 530 536 base.addSubFields 531 537 .addField('_what', _what) 532 538 .addField('_varNumber', _varNumber) 539 .addField('_multiArgs', _multiArgs) 533 540 534 541 get what from var 535 542 536 543 get varNumber from var 544 545 get multiArgs from var 537 546 538 547 def _bindImp … … 546 555 else 547 556 _var = .bindVar(_varExpr) 557 if _multiArgs 558 _unpackMultiArgStmts 548 559 base._bindImp 549 560 _varNumber = .compiler.curBox.makeNextPrivateSerialNumber 550 561 _block.bindImp 551 562 563 def _unpackMultiArgStmts 564 """ 565 Handle expansion of statements for multiArg variables in for statements: 566 for k, v in <dict> # becomes 567 for varExpr_uniq in <dict> 568 k = varExpr_uniq.key 569 v = varExpr_uniq.value 570 and 571 for a, b, c in <IEnumerable (of triplets in this case)> becomes 572 for varExpr_uniq in <IEnumerable> 573 a = varExpr_uniq[0] 574 b = varExpr_uniq[1] 575 c = varExpr_uniq[2] 576 with rest of block following 577 """ 578 stmts = List<of Stmt>() 579 varName = _varExpr.name # "[_varExpr.name]_[.serialNum]" 580 token = _token.copy 581 count = 0 582 if .what.type.isDictionaryLike 583 # assume enumerator will return KeyValue so cant have other than 2 multiargs 584 if _multiArgs.count <> 2 585 .throwError('Cannot have other than two multiarg variables in a for statement as assignment targets from a Dictionary') 586 kvRHS = ['key', 'value'] 587 for id in _multiArgs 588 forVar = IdentifierExpr(token.copy('ID', varName), varName) 589 rhsToken = token.copy('ID', kvRHS[count]) 590 keyOrVal = MemberExpr(rhsToken ) 591 kvExpr = BinaryOpExpr.make(token.copy('DOT', '.'), 'DOT', forVar, keyOrVal) # forVar.{key,value} 592 assignTkn = token.copy('ASSIGN', '=') 593 # print id.toCobraSource, '=', kvExpr.toCobraSource 594 stmts.add(AssignExpr(assignTkn, assignTkn.which, id, kvExpr)) # id = forVar.{key,value} 595 count += 1 596 else # enumeration, each item of which is matching count sequence 597 # TODO: ? Add check varName.count <> multArgs.count throw RTException 598 for id in _multiArgs 599 intToken = token.copy('INTEGER_LIT', '[count]') 600 intToken.value = count 601 countIntLit = IntegerLit(intToken) 602 exprs = List<of Expr>() 603 exprs.add(countIntLit) 604 forVar = IdentifierExpr(token.copy('ID', varName), varName) 605 idxExpr = IndexExpr(token.copy('LBRACKET', r'['), forVar, exprs) # forVar[count] 606 assignTkn = token.copy('ASSIGN', '=') 607 stmts.add(AssignExpr(assignTkn, assignTkn.which, id, idxExpr)) 608 count += 1 609 _block.stmts.insertRange(0, stmts) 610 552 611 def inferredType as IType? is override 553 612 assert _what.type -
cobra/trunk/Source/Types.cobra
r1675 r1704 1603 1603 1604 1604 1605 extend IType 1606 1607 def isDictionaryLike as bool 1608 """ 1609 Returns true if the receiver is like a dictionary, such as being an actual dictionary type or a nilable version thereof. 1610 The dynamic type will also return true because at compile-time, dynamic is considered to be like everything. 1611 Requires Node.getCompiler 1612 """ 1613 type = this 1614 if type inherits NilableType 1615 return type.theWrappedType.isDictionaryLike 1616 tp = Node.getCompiler # TODO? expand ITypeProvider to cover idictionaryType, dictionaryOfType, idictionaryOfType 1617 if type.isDescendantOf(tp.idictionaryType) 1618 return true 1619 genericDict = tp.dictionaryOfType 1620 if type.isDescendantOf(genericDict) 1621 return true 1622 if type inherits Box 1623 if type.genericDef is genericDict 1624 return true 1625 genericIDict = tp.idictionaryOfType 1626 if type.isDescendantOf(genericIDict) 1627 return true 1628 if type inherits Box 1629 if type.genericDef is genericIDict 1630 return true 1631 if type.isDynamic 1632 return true 1633 return false 1634 1635 1605 1636 class TypeUtil 1606 1637 -
cobra/trunk/Tests/110-basics-two/910-multi-assign.cobra
r1669 r1704 88 88 89 89 def nonMatchCount 90 a, b, c = [11, 12] 90 expect ArgumentOutOfRangeException 91 a, b, c = [11, 12] 91 92 assert a == 11 92 93 assert b == 12 93 94 assert c == 0 # instantiated but unassigned 94 95 95 f, = [3, 4] 96 96 assert f == 3 … … 118 118 m = '' 119 119 c1 as Object = 'x' 120 l, m, n, c1 = @[1, 'Two', c'3'] 120 expect IndexOutOfRangeException 121 l, m, n, c1 = @[1, 'Two', c'3'] 121 122 122 123 assert l == 1 … … 125 126 assert c1 == 'x' 126 127 127 p, q, r = 'ab' 128 expect IndexOutOfRangeException 129 p, q, r = 'ab' 128 130 assert p == c'a' 129 131 assert q == c'b' -
cobra/trunk/Tests/110-basics-two/912-multi-assign.cobra
r1669 r1704 14 14 ma.nonLocalVar 15 15 ma.forIEnum 16 ma.forSwap 16 17 17 18 def nonLocalVar … … 41 42 42 43 def forIEnum 43 list = [1, 2, 3, 4] 44 list = [1, 2, 3, 4] # TODO: should be an error with too many elements 44 45 a, b = for k in list get k 45 46 assert a == 1 46 47 assert b == 2 48 49 def forSwap 50 # common variable swap idiom ( python a,b = b,a) 51 a = 99 52 b = 100 53 a, b = [b, a] 54 assert a == 100 55 assert b == 99
