diff options
author | Araq <rumpf_a@web.de> | 2012-01-08 01:29:10 +0100 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2012-01-08 01:29:10 +0100 |
commit | 2ae78c0cfbdcc1a77d6536f360e20c67083da0c7 (patch) | |
tree | 1372102e69089aa1a696477ef9fa25fa65096f1c | |
parent | 7f3b3298b4dc2be10febebc383f42187f968135e (diff) | |
download | Nim-2ae78c0cfbdcc1a77d6536f360e20c67083da0c7.tar.gz |
implicit invokation of items/pairs iterators
-rwxr-xr-x | compiler/semexprs.nim | 3 | ||||
-rwxr-xr-x | compiler/semstmts.nim | 66 | ||||
-rwxr-xr-x | doc/manual.txt | 21 | ||||
-rw-r--r-- | tests/compile/timplicititems.nim | 4 | ||||
-rwxr-xr-x | todo.txt | 4 | ||||
-rwxr-xr-x | web/news.txt | 4 |
6 files changed, 72 insertions, 30 deletions
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 9d2397942..b11ff353c 100755 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -178,7 +178,8 @@ proc semCast(c: PContext, n: PNode): PNode = addSon(result, copyTree(n.sons[0])) addSon(result, semExprWithType(c, n.sons[1])) if not isCastable(result.typ, result.sons[1].Typ): - GlobalError(result.info, errExprCannotBeCastedToX, typeToString(result.Typ)) + GlobalError(result.info, errExprCannotBeCastedToX, + typeToString(result.Typ)) proc semLowHigh(c: PContext, n: PNode, m: TMagic): PNode = const diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 52a3853f2..6208f6bc9 100755 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -398,6 +398,39 @@ proc semForFields(c: PContext, n: PNode, m: TMagic): PNode = b.add(ast.emptyNode) stmts.add(b) +proc semForVars(c: PContext, n: PNode): PNode = + result = n + var length = sonsLen(n) + var iter = skipTypes(n.sons[length-2].typ, {tyGenericInst}) + # length == 3 means that there is one for loop variable + # and thus no tuple unpacking: + if iter.kind != tyTuple or length == 3: + if length != 3: GlobalError(n.info, errWrongNumberOfVariables) + var v = newSymS(skForVar, n.sons[0], c) + # BUGFIX: don't use `iter` here as that would strip away + # the ``tyGenericInst``! See ``tests/compile/tgeneric.nim`` + # for an example: + v.typ = n.sons[length-2].typ + n.sons[0] = newSymNode(v) + addDecl(c, v) + else: + if length-2 != sonsLen(iter): + GlobalError(n.info, errWrongNumberOfVariables) + for i in countup(0, length - 3): + var v = newSymS(skForVar, n.sons[i], c) + v.typ = iter.sons[i] + n.sons[i] = newSymNode(v) + addDecl(c, v) + Inc(c.p.nestedLoopCounter) + n.sons[length-1] = SemStmt(c, n.sons[length-1]) + Dec(c.p.nestedLoopCounter) + +proc implicitIterator(c: PContext, it: string, arg: PNode): PNode = + result = newNodeI(nkCall, arg.info) + result.add(newIdentNode(it.getIdent, arg.info)) + result.add(arg) + result = semExprNoDeref(c, result, {efWantIterator}) + proc semFor(c: PContext, n: PNode): PNode = result = n checkMinSonsLen(n, 3) @@ -407,33 +440,18 @@ proc semFor(c: PContext, n: PNode): PNode = var call = n.sons[length-2] if call.kind notin nkCallKinds or call.sons[0].kind != nkSym or call.sons[0].sym.kind != skIterator: - GlobalError(n.sons[length - 2].info, errIteratorExpected) + if length == 3: + n.sons[length-2] = implicitIterator(c, "items", n.sons[length-2]) + result = semForVars(c, n) + elif length == 4: + n.sons[length-2] = implicitIterator(c, "pairs", n.sons[length-2]) + result = semForVars(c, n) + else: + GlobalError(n.sons[length - 2].info, errIteratorExpected) elif call.sons[0].sym.magic != mNone: result = semForFields(c, n, call.sons[0].sym.magic) else: - var iter = skipTypes(n.sons[length-2].typ, {tyGenericInst}) - # length == 3 means that there is one for loop variable - # and thus no tuple unpacking: - if iter.kind != tyTuple or length == 3: - if length != 3: GlobalError(n.info, errWrongNumberOfVariables) - var v = newSymS(skForVar, n.sons[0], c) - # BUGFIX: don't use `iter` here as that would strip away - # the ``tyGenericInst``! See ``tests/compile/tgeneric.nim`` - # for an example: - v.typ = n.sons[length-2].typ - n.sons[0] = newSymNode(v) - addDecl(c, v) - else: - if length-2 != sonsLen(iter): - GlobalError(n.info, errWrongNumberOfVariables) - for i in countup(0, length - 3): - var v = newSymS(skForVar, n.sons[i], c) - v.typ = iter.sons[i] - n.sons[i] = newSymNode(v) - addDecl(c, v) - Inc(c.p.nestedLoopCounter) - n.sons[length-1] = SemStmt(c, n.sons[length-1]) - Dec(c.p.nestedLoopCounter) + result = semForVars(c, n) closeScope(c.tab) proc semRaise(c: PContext, n: PNode): PNode = diff --git a/doc/manual.txt b/doc/manual.txt index 97af7fe2a..e93e0ecf2 100755 --- a/doc/manual.txt +++ b/doc/manual.txt @@ -2328,7 +2328,7 @@ Iterators and the for statement Syntax:: - forStmt ::= 'for' symbol (comma symbol)* [comma] 'in' expr ['..' expr] ':' stmt + forStmt ::= 'for' symbol (comma symbol)* [comma] 'in' expr ':' stmt param ::= symbol (comma symbol)* [comma] ':' typeDesc paramList ::= ['(' [param (comma param)* [comma]] ')'] [':' typeDesc] @@ -2386,6 +2386,24 @@ as there are components in the tuple. The i'th iteration variable's type is the type of the i'th component. +Implict items/pairs invokations ++++++++++++++++++++++++++++++++ + +If the for loop expression ``e`` does not denote an iterator and the for loop +has exactly 1 variable, the for loop expression is rewritten to ``items(e)``; +ie. an ``items`` iterator is implicitely invoked: + +.. code-block:: nimrod + for x in [1,2,3]: echo x + +If the for loop has exactly 2 variables, a ``pairs`` iterator is implicitely +invoked. + +Symbol lookup of the identifiers ``items``/``pairs`` is performed after +the rewriting step, so that all overloadings of ``items``/``pairs`` are taken +into account. + + Type sections ~~~~~~~~~~~~~ @@ -3322,6 +3340,7 @@ strings automatically: Dynlib pragma for import ------------------------ With the `dynlib`:idx: pragma a procedure can be imported from + a dynamic library (``.dll`` files for Windows, ``lib*.so`` files for UNIX). The non-optional argument has to be the name of the dynamic library: diff --git a/tests/compile/timplicititems.nim b/tests/compile/timplicititems.nim new file mode 100644 index 000000000..dbe321cb6 --- /dev/null +++ b/tests/compile/timplicititems.nim @@ -0,0 +1,4 @@ + +for x in [1, 2, 3, 4]: + echo x + diff --git a/todo.txt b/todo.txt index 5a6990520..f80d2e5b1 100755 --- a/todo.txt +++ b/todo.txt @@ -1,10 +1,8 @@ version 0.8.14 ============== -- fix remaining generics bugs +- fix allocator bug - fix line info in assertions -- implicit invokation of `items`/`pairs` seems nice; ensure items(23) does - not compile though version 0.9.0 ============= diff --git a/web/news.txt b/web/news.txt index 670950519..a05d34520 100755 --- a/web/news.txt +++ b/web/news.txt @@ -10,7 +10,6 @@ Version 0.8.14 has been released! Get it `here <download.html>`_. Bugfixes -------- -- Boehm GC now works with ``--threads:on``. - Fixed a serious memory corruption concerning message passing. - Fixed a serious bug concerning different instantiations of a generic proc. - Fixed a newly introduced bug where a wrong ``EIO`` exception was raised for @@ -20,6 +19,7 @@ Bugfixes - Some more bugfixes for macros and compile-time evaluation. - The GC now takes into account interior pointers on the stack which may be introduced by aggressive C optimizers. +- Lots of other bugfixes: Too many to list them all. Changes affecting backwards compatibility @@ -77,6 +77,8 @@ Language Additions - ``bind`` (used for symbol binding in templates and generics) is now a declarative statement. - Nimrod now supports single assignment variables via the ``let`` statement. +- Iterators named ``items`` and ``pairs`` are implicitly invoked when + an explicit iterator is missing. - The slice assignment ``a[i..j] = b`` where ``a`` is a sequence or string now supports *splicing*. |