Skip to content

Commit 70c0ff1

Browse files
committed
manual: cleanup the documentation; document for-loop macros; ensure the examples compile
1 parent c08efb4 commit 70c0ff1

File tree

1 file changed

+114
-22
lines changed

1 file changed

+114
-22
lines changed

doc/manual.rst

Lines changed: 114 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3959,20 +3959,26 @@ Any statements following the ``defer`` in the current block will be considered
39593959
to be in an implicit try block:
39603960

39613961
.. code-block:: nim
3962-
var f = open("numbers.txt")
3963-
defer: close(f)
3964-
f.write "abc"
3965-
f.write "def"
3962+
:test: "nim c $1"
3963+
3964+
proc main =
3965+
var f = open("numbers.txt")
3966+
defer: close(f)
3967+
f.write "abc"
3968+
f.write "def"
39663969
39673970
Is rewritten to:
39683971

39693972
.. code-block:: nim
3970-
var f = open("numbers.txt")
3971-
try:
3972-
f.write "abc"
3973-
f.write "def"
3974-
finally:
3975-
close(f)
3973+
:test: "nim c $1"
3974+
3975+
proc main =
3976+
var f = open("numbers.txt")
3977+
try:
3978+
f.write "abc"
3979+
f.write "def"
3980+
finally:
3981+
close(f)
39763982
39773983
Top level ``defer`` statements are not supported
39783984
since it's unclear what such a statement should refer to.
@@ -4037,6 +4043,8 @@ to explicitly define which exceptions a proc/iterator/method/converter is
40374043
allowed to raise. The compiler verifies this:
40384044

40394045
.. code-block:: nim
4046+
:test: "nim c $1"
4047+
40404048
proc p(what: bool) {.raises: [IOError, OSError].} =
40414049
if what: raise newException(IOError, "IO")
40424050
else: raise newException(OSError, "OS")
@@ -4056,6 +4064,9 @@ A ``raises`` list can also be attached to a proc type. This affects type
40564064
compatibility:
40574065

40584066
.. code-block:: nim
4067+
:test: "nim c $1"
4068+
:status: 1
4069+
40594070
type
40604071
Callback = proc (s: string) {.raises: [IOError].}
40614072
var
@@ -4114,8 +4125,11 @@ exception is an *effect*. Other effects can also be defined. A user defined
41144125
effect is a means to *tag* a routine and to perform checks against this tag:
41154126

41164127
.. code-block:: nim
4128+
:test: "nim c $1"
4129+
:status: 1
4130+
41174131
type IO = object ## input/output effect
4118-
proc readLine(): string {.tags: [IO].}
4132+
proc readLine(): string {.tags: [IO].} = discard
41194133
41204134
proc no_IO_please() {.tags: [].} =
41214135
# the compiler prevents this:
@@ -4167,6 +4181,8 @@ introduce type parameters or to instantiate a generic proc, iterator or type.
41674181
The following example shows a generic binary tree can be modelled:
41684182

41694183
.. code-block:: nim
4184+
:test: "nim c $1"
4185+
41704186
type
41714187
BinaryTree*[T] = ref object # BinaryTree is a generic type with
41724188
# generic param ``T``
@@ -4175,7 +4191,7 @@ The following example shows a generic binary tree can be modelled:
41754191
41764192
proc newNode*[T](data: T): BinaryTree[T] =
41774193
# constructor for a node
4178-
result = BinaryTree(le: nil, ri: nil, data: data)
4194+
result = BinaryTree[T](le: nil, ri: nil, data: data)
41794195
41804196
proc add*[T](root: var BinaryTree[T], n: BinaryTree[T]) =
41814197
# insert a node into the tree
@@ -4611,6 +4627,8 @@ in any required way. For example, here is how one might define the classic
46114627
type is an instance of it:
46124628

46134629
.. code-block:: nim
4630+
:test: "nim c $1"
4631+
46144632
import future, typetraits
46154633
46164634
type
@@ -4815,6 +4833,8 @@ Open symbols are looked up in two different contexts: Both the context
48154833
at definition and the context at instantiation are considered:
48164834

48174835
.. code-block:: nim
4836+
:test: "nim c $1"
4837+
48184838
type
48194839
Index = distinct int
48204840
@@ -4837,6 +4857,8 @@ Mixin statement
48374857
A symbol can be forced to be open by a `mixin`:idx: declaration:
48384858

48394859
.. code-block:: nim
4860+
:test: "nim c $1"
4861+
48404862
proc create*[T](): ref T =
48414863
# there is no overloaded 'init' here, so we need to state that it's an
48424864
# open symbol explicitly:
@@ -4914,6 +4936,7 @@ performed before the expression is passed to the template. This means that for
49144936
example *undeclared* identifiers can be passed to the template:
49154937

49164938
.. code-block:: nim
4939+
:test: "nim c $1"
49174940
49184941
template declareInt(x: untyped) =
49194942
var x: int
@@ -4923,6 +4946,8 @@ example *undeclared* identifiers can be passed to the template:
49234946
49244947
49254948
.. code-block:: nim
4949+
:test: "nim c $1"
4950+
:status: 1
49264951
49274952
template declareInt(x: typed) =
49284953
var x: int
@@ -4947,6 +4972,8 @@ You can pass a block of statements as a last parameter to a template via a
49474972
special ``:`` syntax:
49484973

49494974
.. code-block:: nim
4975+
:test: "nim c $1"
4976+
49504977
template withFile(f, fn, mode, actions: untyped): untyped =
49514978
var f: File
49524979
if open(f, fn, mode):
@@ -4970,6 +4997,9 @@ the block needs to be of type ``untyped``. Because symbol lookups are then
49704997
delayed until template instantiation time:
49714998

49724999
.. code-block:: nim
5000+
:test: "nim c $1"
5001+
:status: 1
5002+
49735003
template t(body: typed) =
49745004
block:
49755005
body
@@ -4992,6 +5022,8 @@ The same code works with ``untyped`` as the passed body is not required to be
49925022
type-checked:
49935023

49945024
.. code-block:: nim
5025+
:test: "nim c $1"
5026+
49955027
template t(body: untyped) =
49965028
block:
49975029
body
@@ -5012,6 +5044,8 @@ In addition to the ``untyped`` meta-type that prevents type checking there is
50125044
also ``varargs[untyped]`` so that not even the number of parameters is fixed:
50135045

50145046
.. code-block:: nim
5047+
:test: "nim c $1"
5048+
50155049
template hideIdentifiers(x: varargs[untyped]) = discard
50165050
50175051
hideIdentifiers(undeclared1, undeclared2)
@@ -5055,6 +5089,7 @@ Identifier construction
50555089
In templates identifiers can be constructed with the backticks notation:
50565090

50575091
.. code-block:: nim
5092+
:test: "nim c $1"
50585093
50595094
template typedef(name: untyped, typ: typedesc) =
50605095
type
@@ -5116,6 +5151,7 @@ Per default templates are `hygienic`:idx:\: Local identifiers declared in a
51165151
template cannot be accessed in the instantiation context:
51175152

51185153
.. code-block:: nim
5154+
:test: "nim c $1"
51195155
51205156
template newException*(exceptn: typedesc, message: string): untyped =
51215157
var
@@ -5173,6 +5209,9 @@ rewritten to ``f(x)``. Therefore the dot syntax has some limitations when it
51735209
is used to invoke templates/macros:
51745210

51755211
.. code-block:: nim
5212+
:test: "nim c $1"
5213+
:status: 1
5214+
51765215
template declareVar(name: untyped) =
51775216
const name {.inject.} = 45
51785217
@@ -5183,13 +5222,16 @@ is used to invoke templates/macros:
51835222
Another common example is this:
51845223

51855224
.. code-block:: nim
5225+
:test: "nim c $1"
5226+
:status: 1
5227+
51865228
from sequtils import toSeq
51875229
51885230
iterator something: string =
51895231
yield "Hello"
51905232
yield "World"
51915233
5192-
var info = toSeq(something())
5234+
var info = something().toSeq
51935235
51945236
The problem here is that the compiler already decided that ``something()`` as
51955237
an iterator is not callable in this context before ``toSeq`` gets its
@@ -5221,6 +5263,8 @@ The following example implements a powerful ``debug`` command that accepts a
52215263
variable number of arguments:
52225264

52235265
.. code-block:: nim
5266+
:test: "nim c $1"
5267+
52245268
# to work with Nim syntax trees, we need an API that is defined in the
52255269
# ``macros`` module:
52265270
import macros
@@ -5240,7 +5284,7 @@ variable number of arguments:
52405284
add(result, newCall("writeLine", newIdentNode("stdout"), n[i]))
52415285
52425286
var
5243-
a: array [0..10, int]
5287+
a: array[0..10, int]
52445288
x = "some string"
52455289
a[0] = 42
52465290
a[1] = 45
@@ -5278,6 +5322,8 @@ instantiating context. There is a way to use bound identifiers
52785322
builtin can be used for that:
52795323

52805324
.. code-block:: nim
5325+
:test: "nim c $1"
5326+
52815327
import macros
52825328
52835329
macro debug(n: varargs[typed]): untyped =
@@ -5289,7 +5335,7 @@ builtin can be used for that:
52895335
add(result, newCall(bindSym"writeLine", bindSym"stdout", x))
52905336
52915337
var
5292-
a: array [0..10, int]
5338+
a: array[0..10, int]
52935339
x = "some string"
52945340
a[0] = 42
52955341
a[1] = 45
@@ -5373,6 +5419,41 @@ This is a simple syntactic transformation into:
53735419
proc p() = discard
53745420
53755421
5422+
For loop macros
5423+
---------------
5424+
5425+
A macro that takes as its only input parameter an expression of the special
5426+
type ``system.ForLoopStmt`` can rewrite the entirety of a ``for`` loop:
5427+
5428+
.. code-block:: nim
5429+
:test: "nim c $1"
5430+
5431+
import macros
5432+
5433+
macro enumerate(x: ForLoopStmt): untyped =
5434+
expectKind x, nnkForStmt
5435+
# we strip off the first for loop variable and use
5436+
# it as an integer counter:
5437+
result = newStmtList()
5438+
result.add newVarStmt(x[0], newLit(0))
5439+
var body = x[^1]
5440+
if body.kind != nnkStmtList:
5441+
body = newTree(nnkStmtList, body)
5442+
body.add newCall(bindSym"inc", x[0])
5443+
var newFor = newTree(nnkForStmt)
5444+
for i in 1..x.len-3:
5445+
newFor.add x[i]
5446+
# transform enumerate(X) to 'X'
5447+
newFor.add x[^2][1]
5448+
newFor.add body
5449+
result.add newFor
5450+
5451+
for a, b in enumerate(items([1, 2, 3])):
5452+
echo a, " ", b
5453+
5454+
for a2, b2 in enumerate([1, 2, 3, 5]):
5455+
echo a2, " ", b2
5456+
53765457
53775458
Special Types
53785459
=============
@@ -5447,6 +5528,7 @@ one can use a named alias or an explicit `typedesc` generic param:
54475528
Once bound, typedesc params can appear in the rest of the proc signature:
54485529

54495530
.. code-block:: nim
5531+
:test: "nim c $1"
54505532
54515533
template declareVariableWithType(T: typedesc, value: T) =
54525534
var x: T = value
@@ -5458,13 +5540,15 @@ Overload resolution can be further influenced by constraining the set of
54585540
types that will match the typedesc param:
54595541

54605542
.. code-block:: nim
5543+
:test: "nim c $1"
54615544
54625545
template maxval(T: typedesc[int]): int = high(int)
54635546
template maxval(T: typedesc[float]): float = Inf
54645547
54655548
var i = int.maxval
54665549
var f = float.maxval
5467-
var s = string.maxval # error, maxval is not implemented for string
5550+
when false:
5551+
var s = string.maxval # error, maxval is not implemented for string
54685552
54695553
The constraint can be a concrete type or a type class.
54705554

@@ -5494,8 +5578,8 @@ the expression, where the unknown field or proc name is passed to
54945578
an ``untyped`` parameter:
54955579

54965580
.. code-block:: nim
5497-
a.b # becomes `.`(a, "b")
5498-
a.b(c, d) # becomes `.`(a, "b", c, d)
5581+
a.b # becomes `.`(a, b)
5582+
a.b(c, d) # becomes `.`(a, b, c, d)
54995583
55005584
The matched dot operators can be symbols of any callable kind (procs,
55015585
templates and macros), depending on the desired effect:
@@ -5525,7 +5609,7 @@ operator `.=`
55255609
This operator will be matched against assignments to missing fields.
55265610

55275611
.. code-block:: nim
5528-
a.b = c # becomes `.=`(a, "b", c)
5612+
a.b = c # becomes `.=`(a, b, c)
55295613
55305614
55315615
@@ -6086,6 +6170,9 @@ module name followed by an ``except`` list to prevent some symbols to be
60866170
imported:
60876171

60886172
.. code-block:: nim
6173+
:test: "nim c $1"
6174+
:status: 1
6175+
60896176
import strutils except `%`, toUpper
60906177
60916178
# doesn't work then:
@@ -6146,6 +6233,8 @@ an ``import`` to list the symbols one likes to use without explicit
61466233
full qualification:
61476234

61486235
.. code-block:: nim
6236+
:test: "nim c $1"
6237+
61496238
from strutils import `%`
61506239
61516240
echo "$1" % "abc"
@@ -6340,15 +6429,15 @@ collector to not consider objects of this type as part of a cycle:
63406429
.. code-block:: nim
63416430
type
63426431
Node = ref NodeObj
6343-
NodeObj {.acyclic, final.} = object
6432+
NodeObj {.acyclic.} = object
63446433
left, right: Node
63456434
data: string
63466435
63476436
Or if we directly use a ref object:
63486437

63496438
.. code-block:: nim
63506439
type
6351-
Node = ref object {.acyclic, final.}
6440+
Node = ref object {.acyclic.}
63526441
left, right: Node
63536442
data: string
63546443
@@ -6568,7 +6657,7 @@ factor.
65686657
immediate pragma
65696658
----------------
65706659

6571-
See `Typed vs untyped parameters`_.
6660+
The immediate pragma is obsolete. See `Typed vs untyped parameters`_.
65726661

65736662

65746663
compilation option pragmas
@@ -7814,8 +7903,11 @@ Parallel statement
78147903
Example:
78157904

78167905
.. code-block:: nim
7906+
:test: "nim c --threads:on $1"
7907+
78177908
# Compute PI in an inefficient way
78187909
import strutils, math, threadpool
7910+
{.experimental.}
78197911
78207912
proc term(k: float): float = 4 * math.pow(-1, k) / (2*k + 1)
78217913

0 commit comments

Comments
 (0)