summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2012-01-08 01:29:10 +0100
committerAraq <rumpf_a@web.de>2012-01-08 01:29:10 +0100
commit2ae78c0cfbdcc1a77d6536f360e20c67083da0c7 (patch)
tree1372102e69089aa1a696477ef9fa25fa65096f1c
parent7f3b3298b4dc2be10febebc383f42187f968135e (diff)
downloadNim-2ae78c0cfbdcc1a77d6536f360e20c67083da0c7.tar.gz
implicit invokation of items/pairs iterators
-rwxr-xr-xcompiler/semexprs.nim3
-rwxr-xr-xcompiler/semstmts.nim66
-rwxr-xr-xdoc/manual.txt21
-rw-r--r--tests/compile/timplicititems.nim4
-rwxr-xr-xtodo.txt4
-rwxr-xr-xweb/news.txt4
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*.