diff options
Diffstat (limited to 'doc/manual.rst')
-rw-r--r-- | doc/manual.rst | 188 |
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 =============================== |