implicit invokation of items/pairs iterators

This commit is contained in:
Araq
2012-01-08 01:29:10 +01:00
parent 7f3b3298b4
commit 2ae78c0cfb
6 changed files with 72 additions and 30 deletions

View File

@@ -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

View File

@@ -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 =

View File

@@ -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:

View File

@@ -0,0 +1,4 @@
for x in [1, 2, 3, 4]:
echo x

View File

@@ -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
=============

View File

@@ -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*.