mirror of
https://github.com/nim-lang/Nim.git
synced 2026-01-04 20:17:42 +00:00
implicit invokation of items/pairs iterators
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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:
|
||||
|
||||
|
||||
4
tests/compile/timplicititems.nim
Normal file
4
tests/compile/timplicititems.nim
Normal file
@@ -0,0 +1,4 @@
|
||||
|
||||
for x in [1, 2, 3, 4]:
|
||||
echo x
|
||||
|
||||
4
todo.txt
4
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
|
||||
=============
|
||||
|
||||
@@ -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*.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user