summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--changelog.md4
-rw-r--r--compiler/options.nim2
-rw-r--r--compiler/semstmts.nim5
-rw-r--r--doc/manual.rst42
-rw-r--r--doc/manual_experimental.rst46
-rw-r--r--tests/macros/tforloop_macro1.nim2
6 files changed, 50 insertions, 51 deletions
diff --git a/changelog.md b/changelog.md
index 3865f1efb..58efc42e6 100644
--- a/changelog.md
+++ b/changelog.md
@@ -250,6 +250,10 @@ proc mydiv(a, b): int {.raises: [].} =
   `.noSideEffect` stricter. [See](manual_experimental.html#stricts-funcs)
   for more information.
 
+- "for-loop macros" (see [the manual](manual.html#macros-for-loop-macros)) are no longer
+  an experimental feature. In other words, you don't have to write pragma
+  `{.experimental: "forLoopMacros".}` if you want to use them.
+
 
 ## Compiler changes
 
diff --git a/compiler/options.nim b/compiler/options.nim
index 56b061358..14016495f 100644
--- a/compiler/options.nim
+++ b/compiler/options.nim
@@ -154,7 +154,7 @@ type
     destructor,
     notnil,
     dynamicBindSym,
-    forLoopMacros,
+    forLoopMacros, # not experimental anymore; remains here for backwards compatibility
     caseStmtMacros,
     codeReordering,
     compiletimeFFI,
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index 5599eb3ef..2c3ff2bea 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -890,9 +890,8 @@ proc handleCaseStmtMacro(c: PContext; n: PNode; flags: TExprFlags): PNode =
 
 proc semFor(c: PContext, n: PNode; flags: TExprFlags): PNode =
   checkMinSonsLen(n, 3, c.config)
-  if forLoopMacros in c.features:
-    result = handleForLoopMacro(c, n, flags)
-    if result != nil: return result
+  result = handleForLoopMacro(c, n, flags)
+  if result != nil: return result
   openScope(c)
   result = n
   n[^2] = semExprNoDeref(c, n[^2], {efWantIterator})
diff --git a/doc/manual.rst b/doc/manual.rst
index b78e11b32..fc4c11f50 100644
--- a/doc/manual.rst
+++ b/doc/manual.rst
@@ -5469,6 +5469,48 @@ powerful programming construct that still suffices. So the "check list" is:
 (4) Else: Use a macro.
 
 
+For loop macros
+---------------
+
+A macro that takes as its only input parameter an expression of the special
+type ``system.ForLoopStmt`` can rewrite the entirety of a ``for`` loop:
+
+.. code-block:: nim
+    :test: "nim c $1"
+
+  import macros
+
+  macro enumerate(x: ForLoopStmt): untyped =
+    expectKind x, nnkForStmt
+    # we strip off the first for loop variable and use
+    # it as an integer counter:
+    result = newStmtList()
+    result.add newVarStmt(x[0], newLit(0))
+    var body = x[^1]
+    if body.kind != nnkStmtList:
+      body = newTree(nnkStmtList, body)
+    body.add newCall(bindSym"inc", x[0])
+    var newFor = newTree(nnkForStmt)
+    for i in 1..x.len-3:
+      newFor.add x[i]
+    # transform enumerate(X) to 'X'
+    newFor.add x[^2][1]
+    newFor.add body
+    result.add newFor
+    # now wrap the whole macro in a block to create a new scope
+    result = quote do:
+      block: `result`
+
+  for a, b in enumerate(items([1, 2, 3])):
+    echo a, " ", b
+
+  # without wrapping the macro in a block, we'd need to choose different
+  # names for `a` and `b` here to avoid redefinition errors
+  for a, b in enumerate([1, 2, 3, 5]):
+    echo a, " ", b
+
+
+
 Special Types
 =============
 
diff --git a/doc/manual_experimental.rst b/doc/manual_experimental.rst
index 43aa84f20..913b771c2 100644
--- a/doc/manual_experimental.rst
+++ b/doc/manual_experimental.rst
@@ -1030,52 +1030,6 @@ but only the statement's selector expression is used to determine which
 macro to call.
 
 
-For loop macros
----------------
-
-A macro that takes as its only input parameter an expression of the special
-type ``system.ForLoopStmt`` can rewrite the entirety of a ``for`` loop:
-
-.. code-block:: nim
-    :test: "nim c $1"
-
-  import macros
-  {.experimental: "forLoopMacros".}
-
-  macro enumerate(x: ForLoopStmt): untyped =
-    expectKind x, nnkForStmt
-    # we strip off the first for loop variable and use
-    # it as an integer counter:
-    result = newStmtList()
-    result.add newVarStmt(x[0], newLit(0))
-    var body = x[^1]
-    if body.kind != nnkStmtList:
-      body = newTree(nnkStmtList, body)
-    body.add newCall(bindSym"inc", x[0])
-    var newFor = newTree(nnkForStmt)
-    for i in 1..x.len-3:
-      newFor.add x[i]
-    # transform enumerate(X) to 'X'
-    newFor.add x[^2][1]
-    newFor.add body
-    result.add newFor
-    # now wrap the whole macro in a block to create a new scope
-    result = quote do:
-      block: `result`
-
-  for a, b in enumerate(items([1, 2, 3])):
-    echo a, " ", b
-
-  # without wrapping the macro in a block, we'd need to choose different
-  # names for `a` and `b` here to avoid redefinition errors
-  for a, b in enumerate([1, 2, 3, 5]):
-    echo a, " ", b
-
-
-Currently for loop macros must be enabled explicitly
-via ``{.experimental: "forLoopMacros".}``.
-
-
 Term rewriting macros
 =====================
 
diff --git a/tests/macros/tforloop_macro1.nim b/tests/macros/tforloop_macro1.nim
index 49918563d..a8f45c7ac 100644
--- a/tests/macros/tforloop_macro1.nim
+++ b/tests/macros/tforloop_macro1.nim
@@ -12,7 +12,7 @@ discard """
 """
 
 import macros
-{.experimental: "forLoopMacros".}
+
 macro mymacro(): untyped =
   result = newLit([1, 2, 3])