summary refs log tree commit diff stats
path: root/doc/manual.rst
diff options
context:
space:
mode:
Diffstat (limited to 'doc/manual.rst')
-rw-r--r--doc/manual.rst188
1 files changed, 166 insertions, 22 deletions
diff --git a/doc/manual.rst b/doc/manual.rst
index 4f0530a8a..7946e88dd 100644
--- a/doc/manual.rst
+++ b/doc/manual.rst
@@ -17,8 +17,7 @@ About this document
 ===================
 
 **Note**: This document is a draft! Several of Nim's features may need more
-precise wording. This manual is constantly evolving until the 1.0 release and is
-not to be considered as the final proper specification.
+precise wording. This manual is constantly evolving into a proper specification.
 
 This document describes the lexis, the syntax, and the semantics of Nim.
 
@@ -433,7 +432,7 @@ Numerical constants are of a single type and have the form::
   UINT64_LIT = INT_LIT ['\''] ('u' | 'U') '64'
 
   exponent = ('e' | 'E' ) ['+' | '-'] digit ( ['_'] digit )*
-  FLOAT_LIT = digit (['_'] digit)* (('.' (['_'] digit)* [exponent]) |exponent)
+  FLOAT_LIT = digit (['_'] digit)* (('.' digit (['_'] digit)* [exponent]) |exponent)
   FLOAT32_SUFFIX = ('f' | 'F') ['32']
   FLOAT32_LIT = HEX_LIT '\'' FLOAT32_SUFFIX
               | (FLOAT_LIT | DEC_LIT | OCT_LIT | BIN_LIT) ['\''] FLOAT32_SUFFIX
@@ -504,7 +503,7 @@ following characters::
 These keywords are also operators:
 ``and or not xor shl shr div mod in notin is isnot of``.
 
-`=`:tok:, `:`:tok:, `::`:tok: are not available as general operators; they
+`.`:tok: `=`:tok:, `:`:tok:, `::`:tok: are not available as general operators; they
 are used for other notational purposes.
 
 ``*:`` is as a special case treated as the two tokens `*`:tok: and `:`:tok:
@@ -618,6 +617,55 @@ The grammar's start symbol is ``module``.
 
 
 
+Order of evaluation
+===================
+
+Order of evaluation is strictly left-to-right, inside-out as it is typical for most others
+imperative programming languages:
+
+.. code-block:: nim
+    :test: "nim c $1"
+
+  var s = ""
+
+  proc p(arg: int): int =
+    s.add $arg
+    result = arg
+
+  discard p(p(1) + p(2))
+
+  doAssert s == "123"
+
+
+Assignments are not special, the left-hand-side expression is evaluated before the
+right-hand side:
+
+.. code-block:: nim
+    :test: "nim c $1"
+
+  var v = 0
+  proc getI(): int =
+    result = v
+    inc v
+
+  var a, b: array[0..2, int]
+
+  proc someCopy(a: var int; b: int) = a = b
+
+  a[getI()] = getI()
+
+  doAssert a == [1, 0, 0]
+
+  v = 0
+  someCopy(b[getI()], getI())
+
+  doAssert b == [1, 0, 0]
+
+
+Rationale: Consistency with overloaded assignment or assignment-like operations,
+``a = b`` can be read as ``performSomeCopy(a, b)``.
+
+
 Types
 =====
 
@@ -888,8 +936,12 @@ Now the following holds::
   ord(south) == 2
   ord(west) == 3
 
+  # Also allowed:
+  ord(Direction.west) == 3
+
 Thus, north < east < south < west. The comparison operators can be used
-with enumeration types.
+with enumeration types. Instead of ``north`` etc, the enum value can also
+be qualified with the enum type that it resides in, ``Direction.north``.
 
 For better interfacing to other programming languages, the fields of enum
 types can be assigned an explicit ordinal value. However, the ordinal values
@@ -925,18 +977,25 @@ As can be seen from the example, it is possible to both specify a field's
 ordinal value and its string value by using a tuple. It is also
 possible to only specify one of them.
 
-An enum can be marked with the ``pure`` pragma so that it's fields are not
-added to the current scope, so they always need to be accessed
-via ``MyEnum.value``:
+An enum can be marked with the ``pure`` pragma so that it's fields are
+added to a special module specific hidden scope that is only queried
+as the last attempt. Only non-ambiguous symbols are added to this scope.
+But one can always access these via type qualification written
+as ``MyEnum.value``:
 
 .. code-block:: nim
 
   type
     MyEnum {.pure.} = enum
-      valueA, valueB, valueC, valueD
+      valueA, valueB, valueC, valueD, amb
 
-  echo valueA # error: Unknown identifier
-  echo MyEnum.valueA # works
+    OtherEnum {.pure.} = enum
+      valueX, valueY, valueZ, amb
+
+
+  echo valueA # MyEnum.valueA
+  echo amb    # Error: Unclear whether it's MyEnum.amb or OtherEnum.amb
+  echo MyEnum.amb # OK.
 
 
 String type
@@ -945,6 +1004,11 @@ All string literals are of the type ``string``. A string in Nim is very
 similar to a sequence of characters. However, strings in Nim are both
 zero-terminated and have a length field. One can retrieve the length with the
 builtin ``len`` procedure; the length never counts the terminating zero.
+
+The terminating zero cannot be accessed unless the string is converted
+to the ``cstring`` type first. The terminating zero assures that this
+conversion can be done in O(1) and without any allocations.
+
 The assignment operator for strings always copies the string.
 The ``&`` operator concatenates strings.
 
@@ -2925,6 +2989,10 @@ name ``c`` should default to type ``Context``, ``n`` should default to
   proc bar(c, n, counter) = ...
   proc baz(c, n) = ...
 
+  proc mixedMode(c, n; x, y: int) =
+    # 'c' is inferred to be of the type 'Context'
+    # 'n' is inferred to be of the type 'Node'
+    # But 'x' and 'y' are of type 'int'.
 
 The ``using`` section uses the same indentation based grouping syntax as
 a ``var`` or ``let`` section.
@@ -2932,6 +3000,9 @@ a ``var`` or ``let`` section.
 Note that ``using`` is not applied for ``template`` since untyped template
 parameters default to the type ``system.untyped``.
 
+Mixing parameters that should use the ``using`` declaration with parameters
+that are explicitly typed is possible and requires a semicolon between them.
+
 
 If expression
 -------------
@@ -3045,6 +3116,19 @@ the address of variables, but one can't use it on variables declared through
   # Error: expression has no address
 
 
+The unsafeAddr operator
+-----------------------
+
+For easier interoperability with other compiled languages such as C, retrieving
+the address of a ``let`` variable, a parameter or a ``for`` loop variable, the
+``unsafeAddr`` operation can be used:
+
+.. code-block:: nim
+
+  let myArray = [1, 2, 3]
+  foreignProcThatTakesAnAddr(unsafeAddr myArray)
+
+
 Procedures
 ==========
 
@@ -4327,6 +4411,34 @@ be inferred to have the equivalent of the `any` type class and thus they will
 match anything without discrimination.
 
 
+Generic inference restrictions
+------------------------------
+
+The types ``var T`` and ``typedesc[T]`` cannot be inferred in a generic
+instantiation. The following is not allowed:
+
+.. code-block:: nim
+    :test: "nim c $1"
+    :status: 1
+
+  proc g[T](f: proc(x: T); x: T) =
+    f(x)
+
+  proc c(y: int) = echo y
+  proc v(y: var int) =
+    y += 100
+  var i: int
+
+  # allowed: infers 'T' to be of type 'int'
+  g(c, 42)
+
+  # not valid: 'T' is not inferred to be of type 'var int'
+  g(v, i)
+
+  # also not allowed: explict instantiation via 'var int'
+  g[var int](v, i)
+
+
 Concepts
 --------
 
@@ -4573,7 +4685,7 @@ type is an instance of it:
 .. code-block:: nim
     :test: "nim c $1"
 
-  import future, typetraits
+  import sugar, typetraits
 
   type
     Functor[A] = concept f
@@ -5399,12 +5511,17 @@ type ``system.ForLoopStmt`` can rewrite the entirety of a ``for`` loop:
     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
 
-  for a2, b2 in enumerate([1, 2, 3, 5]):
-    echo a2, " ", b2
+  # 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
@@ -5414,12 +5531,11 @@ via ``{.experimental: "forLoopMacros".}``.
 Case statement macros
 ---------------------
 
-A macro that needs to be called `match`:idx: can be used to
-rewrite ``case`` statements in order to
-implement `pattern matching`:idx: for certain types. The following
-example implements a simplistic form of pattern matching for tuples,
-leveraging the existing equality operator for tuples (as provided in
- ``system.==``):
+A macro that needs to be called `match`:idx: can be used to rewrite
+``case`` statements in order to implement `pattern matching`:idx: for
+certain types. The following example implements a simplistic form of
+pattern matching for tuples, leveraging the existing equality operator
+for tuples (as provided in ``system.==``):
 
 .. code-block:: nim
     :test: "nim c $1"
@@ -6553,6 +6669,11 @@ The deprecated pragma is used to mark a symbol as deprecated:
   proc p() {.deprecated.}
   var x {.deprecated.}: char
 
+This pragma can also take in an optional warning string to relay to developers.
+
+.. code-block:: nim
+  proc thing(x: bool) {.deprecated: "See arguments of otherThing()".}
+
 It can also be used as a statement, in that case it takes a list of *renamings*.
 
 .. code-block:: nim
@@ -6561,7 +6682,6 @@ It can also be used as a statement, in that case it takes a list of *renamings*.
     Stream = ref object
   {.deprecated: [TFile: File, PStream: Stream].}
 
-
 noSideEffect pragma
 -------------------
 The ``noSideEffect`` pragma is used to mark a proc/iterator to have no side
@@ -6998,12 +7118,36 @@ Example:
 .. code-block:: nim
   {.experimental: "parallel".}
 
-  proc useUsing(bar, foo) =
+  proc useParallel() =
     parallel:
       for i in 0..4:
         echo "echo in parallel"
 
 
+As a top level statement, the experimental pragma enables a feature for the
+rest of the module it's enabled in. This is problematic for macro and generic
+instantiations that cross a module scope. Currently these usages have to be
+put into a ``.push/pop`` environment:
+
+.. code-block:: nim
+
+  # client.nim
+  proc useParallel*[T](unused: T) =
+    # use a generic T here to show the problem.
+    {.push experimental: "parallel".}
+    parallel:
+      for i in 0..4:
+        echo "echo in parallel"
+
+    {.pop.}
+
+
+.. code-block:: nim
+
+  import client
+  useParallel(1)
+
+
 Implementation Specific Pragmas
 ===============================