diff options
Diffstat (limited to 'doc/manual')
-rw-r--r-- | doc/manual/generics.txt | 97 | ||||
-rw-r--r-- | doc/manual/lexing.txt | 2 | ||||
-rw-r--r-- | doc/manual/pragmas.txt | 69 | ||||
-rw-r--r-- | doc/manual/procs.txt | 43 | ||||
-rw-r--r-- | doc/manual/syntax.txt | 17 | ||||
-rw-r--r-- | doc/manual/threads.txt | 42 | ||||
-rw-r--r-- | doc/manual/type_bound_ops.txt | 62 | ||||
-rw-r--r-- | doc/manual/typedesc.txt | 31 | ||||
-rw-r--r-- | doc/manual/types.txt | 6 |
9 files changed, 174 insertions, 195 deletions
diff --git a/doc/manual/generics.txt b/doc/manual/generics.txt index f3e7b7b4c..2736f88fb 100644 --- a/doc/manual/generics.txt +++ b/doc/manual/generics.txt @@ -60,7 +60,7 @@ Is operator ----------- The ``is`` operator checks for type equivalence at compile time. It is -therefore very useful for type specialization within generic code: +therefore very useful for type specialization within generic code: .. code-block:: nim type @@ -75,7 +75,7 @@ Type operator ------------- The ``type`` (in many other languages called `typeof`:idx:) operator can -be used to get the type of an expression: +be used to get the type of an expression: .. code-block:: nim var x = 0 @@ -88,7 +88,7 @@ other interpretations: .. code-block:: nim import strutils - + # strutils contains both a ``split`` proc and iterator, but since an # an iterator is the preferred interpretation, `y` has the type ``string``: var y: type("a b c".split) @@ -98,7 +98,7 @@ Type Classes ------------ A type class is a special pseudo-type that can be used to match against -types in the context of overload resolution or the ``is`` operator. +types in the context of overload resolution or the ``is`` operator. Nim supports the following built-in type classes: ================== =================================================== @@ -116,7 +116,7 @@ type class matches ``array`` any array type ``set`` any set type ``seq`` any seq type -``auto`` any type +``auto`` any type ================== =================================================== Furthermore, every generic type automatically creates a type class of the same @@ -134,7 +134,7 @@ more complex type classes: echo key, " = ", value Procedures utilizing type classes in such manner are considered to be -`implicitly generic`:idx:. They will be instantiated once for each unique +`implicitly generic`:idx:. They will be instantiated once for each unique combination of param types used within the program. Nim also allows for type classes and regular types to be specified @@ -142,7 +142,7 @@ as `type constraints`:idx: of the generic type parameter: .. code-block:: nim proc onlyIntOrString[T: int|string](x, y: T) = discard - + onlyIntOrString(450, 616) # valid onlyIntOrString(5.0, 0.0) # type mismatch onlyIntOrString("xy", 50) # invalid as 'T' cannot be both at the same time @@ -152,7 +152,7 @@ exactly one concrete type. Here is an example taken directly from the system module to illustrate this: .. code-block:: nim - proc `==`*(x, y: tuple): bool = + proc `==`*(x, y: tuple): bool = ## requires `x` and `y` to be of the same tuple type ## generic ``==`` operator for tuples that is lifted from the components ## of `x` and `y`. @@ -160,8 +160,8 @@ module to illustrate this: for a, b in fields(x, y): if a != b: result = false -Alternatively, the ``distinct`` type modifier can be applied to the type class -to allow each param matching the type class to bind to a different type. +Alternatively, the ``distinct`` type modifier can be applied to the type class +to allow each param matching the type class to bind to a different type. If a proc param doesn't have a type specified, Nim will use the ``distinct auto`` type class (also known as ``any``): @@ -178,7 +178,7 @@ the dot syntax: type Matrix[T, Rows, Columns] = object ... - proc `[]`(m: Matrix, row, col: int): Matrix.T = + proc `[]`(m: Matrix, row, col: int): Matrix.T = m.data[col * high(Matrix.Columns) + row] Alternatively, the `type` operator can be used over the proc params for similar @@ -189,7 +189,7 @@ type, this results in another more specific type class: .. code-block:: nim seq[ref object] # Any sequence storing references to any object type - + type T1 = auto proc foo(s: seq[T1], e: T1) # seq[T1] is the same as just `seq`, but T1 will be allowed to bind @@ -203,34 +203,33 @@ be inferred to have the equivalent of the `any` type class and thus they will match anything without discrimination. -User defined type classes -------------------------- +Concepts +-------- -**Note**: User defined type classes are still in development. +**Note**: Concepts are still in development. -The user-defined type classes are available in two flavours - declarative and -imperative. Both are used to specify an arbitrary set of requirements that the -matched type must satisfy. +Concepts, also known as "user-defined type classes", are used to specify an +arbitrary set of requirements that the matched type must satisfy. -Declarative type classes are written in the following form: +Concepts are written in the following form: .. code-block:: nim type - Comparable = generic x, y + Comparable = concept x, y (x < y) is bool - Container[T] = generic c - c.len is ordinal + Container[T] = concept c + c.len is Ordinal items(c) is iterator for value in c: type(value) is T -The type class will be matched if: +The concept is a match if: a) all of the expressions within the body can be compiled for the tested type b) all statically evaluatable boolean expressions in the body must be true -The identifiers following the `generic` keyword represent instances of the +The identifiers following the ``concept`` keyword represent instances of the currently matched type. These instances can act both as variables of the type, when used in contexts where a value is expected, and as the type itself when used in contexts where a type is expected. @@ -240,45 +239,21 @@ type signatures of the required operations, but since type inference and default parameters are still applied in the provided block, it's also possible to encode usage protocols that do not reveal implementation details. -As a special rule providing further convenience when writing type classes, any +As a special rule providing further convenience when writing concepts, any type value appearing in a callable expression will be treated as a variable of the designated type for overload resolution purposes, unless the type value was passed in its explicit ``typedesc[T]`` form: .. code-block:: nim type - OutputStream = generic S - write(var S, string) + OutputStream = concept s + write(var s, string) -Much like generics, the user defined type classes will be instantiated exactly -once for each tested type and any static code included within them will also be +Much like generics, concepts are instantiated exactly +once for each tested type and any static code included within them is also executed once. -Type inference with type classes --------------------------------- - -If a type class is used as the return type of a proc and it won't be bound to -a concrete type by some of the proc params, Nim will infer the return type -from the proc body. This is usually used with the ``auto`` type class: - -.. code-block:: nim - proc makePair(a, b): auto = (first: a, second: b) - -The return type will be treated as an additional generic param and can be -explicitly specified at call sites as any other generic param. - -Future versions of Nim may also support overloading based on the return type -of the overloads. In such settings, the expected result type at call sites may -also influence the inferred return type. - -.. - Likewise, if a type class is used in another position where Nim expects a - concrete type (e.g. a variable declaration or a type coercion), Nim will try - to infer the concrete type by applying the matching algorithm that also used - in overload resolution. - - Symbol lookup in generics ------------------------- @@ -293,12 +268,12 @@ at definition and the context at instantiation are considered: .. code-block:: nim type Index = distinct int - + proc `==` (a, b: Index): bool {.borrow.} - + var a = (0, 0.Index) var b = (0, 0.Index) - + echo a == b # works! In the example the generic ``==`` for tuples (as defined in the system module) @@ -307,7 +282,7 @@ the ``Index`` type is defined *after* the ``==`` for tuples; yet the example compiles as the instantiation takes the currently defined symbols into account too. -A symbol can be forced to be open by a `mixin`:idx: declaration: +A symbol can be forced to be open by a `mixin`:idx: declaration: .. code-block:: nim proc create*[T](): ref T = @@ -321,16 +296,16 @@ A symbol can be forced to be open by a `mixin`:idx: declaration: Bind statement -------------- -The ``bind`` statement is the counterpart to the ``mixin`` statement. It +The ``bind`` statement is the counterpart to the ``mixin`` statement. It can be used to explicitly declare identifiers that should be bound early (i.e. the identifiers should be looked up in the scope of the template/generic definition): .. code-block:: nim # Module A - var + var lastId = 0 - + template genId*: expr = bind lastId inc(lastId) @@ -339,7 +314,7 @@ definition): .. code-block:: nim # Module B import A - + echo genId() But a ``bind`` is rarely useful because symbol binding from the definition diff --git a/doc/manual/lexing.txt b/doc/manual/lexing.txt index e2f006f04..df6d85636 100644 --- a/doc/manual/lexing.txt +++ b/doc/manual/lexing.txt @@ -289,7 +289,7 @@ Numerical constants are of a single type and have the form:: INT32_LIT = INT_LIT ['\''] ('i' | 'I') '32' INT64_LIT = INT_LIT ['\''] ('i' | 'I') '64' - UINT8_LIT = INT_LIT ['\''] ('u' | 'U') + UINT_LIT = INT_LIT ['\''] ('u' | 'U') UINT8_LIT = INT_LIT ['\''] ('u' | 'U') '8' UINT16_LIT = INT_LIT ['\''] ('u' | 'U') '16' UINT32_LIT = INT_LIT ['\''] ('u' | 'U') '32' diff --git a/doc/manual/pragmas.txt b/doc/manual/pragmas.txt index 34428233f..39aebd826 100644 --- a/doc/manual/pragmas.txt +++ b/doc/manual/pragmas.txt @@ -14,7 +14,7 @@ deprecated pragma The deprecated pragma is used to mark a symbol as deprecated: -.. code-block:: nimrod +.. code-block:: nim proc p() {.deprecated.} var x {.deprecated.}: char @@ -22,7 +22,7 @@ It can also be used as a statement. Then it takes a list of *renamings*. The upcoming ``nimfix`` tool can automatically update the code and perform these renamings: -.. code-block:: nimrod +.. code-block:: nim type File = object Stream = ref object @@ -71,14 +71,13 @@ procedural variable. compileTime pragma ------------------ -The ``compileTime`` pragma is used to mark a proc to be used at compile -time only. No code will be generated for it. Compile time procs are useful -as helpers for macros. - +The ``compileTime`` pragma is used to mark a proc or variable to be used at +compile time only. No code will be generated for it. Compile time procs are +useful as helpers for macros. noReturn pragma --------------- -The ``noreturn`` pragma is used to mark a proc that never returns. +The ``noreturn`` pragma is used to mark a proc that never returns. acyclic pragma @@ -122,25 +121,25 @@ shallow pragma -------------- The ``shallow`` pragma affects the semantics of a type: The compiler is allowed to make a shallow copy. This can cause serious semantic issues and -break memory safety! However, it can speed up assignments considerably, -because the semantics of Nim require deep copying of sequences and strings. +break memory safety! However, it can speed up assignments considerably, +because the semantics of Nim require deep copying of sequences and strings. This can be expensive, especially if sequences are used to build a tree -structure: +structure: .. code-block:: nim type NodeKind = enum nkLeaf, nkInner Node {.final, shallow.} = object case kind: NodeKind - of nkLeaf: + of nkLeaf: strVal: string - of nkInner: + of nkInner: children: seq[Node] pure pragma ----------- -An object type can be marked with the ``pure`` pragma so that its type +An object type can be marked with the ``pure`` pragma so that its type field which is used for runtime type identification is omitted. This used to be necessary for binary compatibility with other compiled languages. @@ -163,12 +162,12 @@ error pragma ------------ The ``error`` pragma is used to make the compiler output an error message with the given content. Compilation does not necessarily abort after an error -though. +though. The ``error`` pragma can also be used to annotate a symbol (like an iterator or proc). The *usage* of the symbol then triggers a compile-time error. This is especially useful to rule out that some -operation is valid due to overloading and type conversions: +operation is valid due to overloading and type conversions: .. code-block:: nim ## check that underlying int values are compared and not the pointers: @@ -201,7 +200,7 @@ The ``line`` pragma can be used to affect line information of the annotated statement as seen in stack backtraces: .. code-block:: nim - + template myassert*(cond: expr, msg = "") = if not cond: # change run-time line information of the 'raise' statement: @@ -215,26 +214,26 @@ If the ``line`` pragma is used with a parameter, the parameter needs be a linearScanEnd pragma -------------------- -The ``linearScanEnd`` pragma can be used to tell the compiler how to +The ``linearScanEnd`` pragma can be used to tell the compiler how to compile a Nim `case`:idx: statement. Syntactically it has to be used as a statement: .. code-block:: nim case myInt - of 0: + of 0: echo "most common case" - of 1: + of 1: {.linearScanEnd.} echo "second most common case" of 2: echo "unlikely: use branch table" else: echo "unlikely too: use branch table for ", myInt -In the example, the case branches ``0`` and ``1`` are much more common than -the other cases. Therefore the generated assembler code should test for these -values first, so that the CPU's branch predictor has a good chance to succeed +In the example, the case branches ``0`` and ``1`` are much more common than +the other cases. Therefore the generated assembler code should test for these +values first, so that the CPU's branch predictor has a good chance to succeed (avoiding an expensive CPU pipeline stall). The other cases might be put into a jump table for O(1) overhead, but at the cost of a (very likely) pipeline -stall. +stall. The ``linearScanEnd`` pragma should be put into the last branch that should be tested against via linear scanning. If put into the last branch of the @@ -243,8 +242,8 @@ whole ``case`` statement, the whole ``case`` statement uses linear scanning. computedGoto pragma ------------------- -The ``computedGoto`` pragma can be used to tell the compiler how to -compile a Nim `case`:idx: in a ``while true`` statement. +The ``computedGoto`` pragma can be used to tell the compiler how to +compile a Nim `case`:idx: in a ``while true`` statement. Syntactically it has to be used as a statement inside the loop: .. code-block:: nim @@ -278,21 +277,21 @@ Syntactically it has to be used as a statement inside the loop: of enumE: break inc(pc) - + vm() As the example shows ``computedGoto`` is mostly useful for interpreters. If -the underlying backend (C compiler) does not support the computed goto +the underlying backend (C compiler) does not support the computed goto extension the pragma is simply ignored. unroll pragma ------------- The ``unroll`` pragma can be used to tell the compiler that it should unroll -a `for`:idx: or `while`:idx: loop for runtime efficiency: +a `for`:idx: or `while`:idx: loop for runtime efficiency: .. code-block:: nim - proc searchChar(s: string, c: char): int = + proc searchChar(s: string, c: char): int = for i in 0 .. s.high: {.unroll: 4.} if s[i] == c: return i @@ -440,7 +439,7 @@ Example: Please note that if a callable symbol is never used in this scenario, its body will never be compiled. This is the default behavior leading to best compilation - times, but if exhaustive compilation of all definitions is required, using + times, but if exhaustive compilation of all definitions is required, using ``nim check`` provides this option as well. Example: @@ -461,9 +460,9 @@ Example: pragma pragma ------------- -The ``pragma`` pragma can be used to declare user defined pragmas. This is -useful because Nim's templates and macros do not affect pragmas. User -defined pragmas are in a different module-wide scope than all other symbols. +The ``pragma`` pragma can be used to declare user defined pragmas. This is +useful because Nim's templates and macros do not affect pragmas. User +defined pragmas are in a different module-wide scope than all other symbols. They cannot be imported from a module. Example: @@ -473,8 +472,8 @@ Example: {.pragma: rtl, exportc, dynlib, cdecl.} else: {.pragma: rtl, importc, dynlib: "client.dll", cdecl.} - - proc p*(a, b: int): int {.rtl.} = + + proc p*(a, b: int): int {.rtl.} = result = a+b In the example a new pragma named ``rtl`` is introduced that either imports diff --git a/doc/manual/procs.txt b/doc/manual/procs.txt index 9b04bf518..9de984ecf 100644 --- a/doc/manual/procs.txt +++ b/doc/manual/procs.txt @@ -121,7 +121,7 @@ different; for this a special setter syntax is needed: .. code-block:: nim type - Socket* = object of RootObj + Socket* = ref object of RootObj FHost: int # cannot be accessed from the outside of the module # the `F` prefix is a convention to avoid clashes since # the accessors are named `host` @@ -134,8 +134,8 @@ different; for this a special setter syntax is needed: ## getter of hostAddr s.FHost - var - s: Socket + var s: Socket + new s s.host = 34 # same as `host=`(s, 34) @@ -351,32 +351,32 @@ dispatch. .. code-block:: nim type - Expression = object of RootObj ## abstract base class for an expression - Literal = object of Expression + Expression = ref object of RootObj ## abstract base class for an expression + Literal = ref object of Expression x: int - PlusExpr = object of Expression - a, b: ref Expression - - method eval(e: ref Expression): int = + PlusExpr = ref object of Expression + a, b: Expression + + method eval(e: Expression): int = # override this base method quit "to override!" - method eval(e: ref Literal): int = return e.x - - method eval(e: ref PlusExpr): int = + method eval(e: Literal): int = return e.x + + method eval(e: PlusExpr): int = # watch out: relies on dynamic binding result = eval(e.a) + eval(e.b) - proc newLit(x: int): ref Literal = + proc newLit(x: int): Literal = new(result) result.x = x - - proc newPlus(a, b: ref Expression): ref PlusExpr = + + proc newPlus(a, b: Expression): PlusExpr = new(result) result.a = a result.b = b - - echo eval(newPlus(newPlus(newLit(1), newLit(2)), newLit(4))) + +echo eval(newPlus(newPlus(newLit(1), newLit(2)), newLit(4))) In the example the constructors ``newLit`` and ``newPlus`` are procs because they should use static binding, but ``eval`` is a method because it @@ -387,8 +387,8 @@ dispatching: .. code-block:: nim type - Thing = object of RootObj - Unit = object of Thing + Thing = ref object of RootObj + Unit = ref object of Thing x: int method collide(a, b: Thing) {.inline.} = @@ -400,8 +400,9 @@ dispatching: method collide(a: Unit, b: Thing) {.inline.} = echo "2" - var - a, b: Unit + var a, b: Unit + new a + new b collide(a, b) # output: 2 diff --git a/doc/manual/syntax.txt b/doc/manual/syntax.txt index cf44eb588..24644bce2 100644 --- a/doc/manual/syntax.txt +++ b/doc/manual/syntax.txt @@ -15,8 +15,6 @@ Associativity Binary operators whose first character is ``^`` are right-associative, all other binary operators are left-associative. -Operators ending in ``>`` but longer than a single character are -called `arrow like`:idx:. Precedence @@ -33,9 +31,12 @@ as ``(@x).abc`` whereas ``$x.abc`` is parsed as ``$(x.abc)``. For binary operators that are not keywords the precedence is determined by the following rules: +Operators ending in either ``->``, ``~>`` or ``=>`` are called +`arrow like`:idx:, and have the lowest precedence of all operators. + If the operator ends with ``=`` and its first character is none of ``<``, ``>``, ``!``, ``=``, ``~``, ``?``, it is an *assignment operator* which -has the lowest precedence. +has the second lowest precedence. Otherwise precedence is determined by the first character. @@ -43,14 +44,14 @@ Otherwise precedence is determined by the first character. Precedence level Operators First character Terminal symbol ================ =============================================== ================== =============== 10 (highest) ``$ ^`` OP10 - 9 ``* / div mod shl shr %`` ``* % \ /`` OP9 - 8 ``+ -`` ``+ ~ |`` OP8 + 9 ``* / div mod shl shr %`` ``* % \ /`` OP9 + 8 ``+ -`` ``+ - ~ |`` OP8 7 ``&`` ``&`` OP7 6 ``..`` ``.`` OP6 - 5 ``== <= < >= > != in notin is isnot not of`` ``= < > !`` OP5 + 5 ``== <= < >= > != in notin is isnot not of`` ``= < > !`` OP5 4 ``and`` OP4 3 ``or xor`` OP3 - 2 ``@ : ?`` OP2 + 2 ``@ : ?`` OP2 1 *assignment operator* (like ``+=``, ``*=``) OP1 0 (lowest) *arrow like operator* (like ``->``, ``=>``) OP0 ================ =============================================== ================== =============== @@ -67,7 +68,7 @@ is still parsed as ``1 + (3 * 4)``, but ``1+3 * 4`` is parsed as ``(1+3) * 4``: .. code-block:: nim #! strongSpaces - if foo+4 * 4 == 8 and b&c | 9 ++ + if foo+4 * 4 == 8 and b&c | 9 ++ bar: echo "" # is parsed as diff --git a/doc/manual/threads.txt b/doc/manual/threads.txt index 245545f6f..fc3040c87 100644 --- a/doc/manual/threads.txt +++ b/doc/manual/threads.txt @@ -1,16 +1,16 @@ Threads ======= -To enable thread support the ``--threads:on`` command line switch needs to -be used. The ``system`` module then contains several threading primitives. -See the `threads <threads.html>`_ and `channels <channels.html>`_ modules +To enable thread support the ``--threads:on`` command line switch needs to +be used. The ``system`` module then contains several threading primitives. +See the `threads <threads.html>`_ and `channels <channels.html>`_ modules for the low level thread API. There are also high level parallelism constructs available. See `spawn`_ for further details. Nim's memory model for threads is quite different than that of other common -programming languages (C, Pascal, Java): Each thread has its own (garbage -collected) heap and sharing of memory is restricted to global variables. This -helps to prevent race conditions. GC efficiency is improved quite a lot, +programming languages (C, Pascal, Java): Each thread has its own (garbage +collected) heap and sharing of memory is restricted to global variables. This +helps to prevent race conditions. GC efficiency is improved quite a lot, because the GC never has to stop other threads and see what they reference. Memory allocation requires no lock at all! This design easily scales to massive multicore processors that are becoming the norm. @@ -22,10 +22,10 @@ Thread pragma A proc that is executed as a new thread of execution should be marked by the ``thread`` pragma for reasons of readability. The compiler checks for violations of the `no heap sharing restriction`:idx:\: This restriction implies -that it is invalid to construct a data structure that consists of memory +that it is invalid to construct a data structure that consists of memory allocated from different (thread local) heaps. -A thread proc is passed to ``createThread`` or ``spawn`` and invoked +A thread proc is passed to ``createThread`` or ``spawn`` and invoked indirectly; so the ``thread`` pragma implies ``procvar``. @@ -34,7 +34,7 @@ GC safety We call a proc ``p`` `GC safe`:idx: when it doesn't access any global variable that contains GC'ed memory (``string``, ``seq``, ``ref`` or a closure) either -directly or indirectly through a call to a GC unsafe proc. +directly or indirectly through a call to a GC unsafe proc. The `gcsafe`:idx: annotation can be used to mark a proc to be gcsafe, otherwise this property is inferred by the compiler. Note that ``noSideEfect`` @@ -45,10 +45,9 @@ contain a ``ref`` or ``closure`` type. This enforces the *no heap sharing restriction*. Routines that are imported from C are always assumed to be ``gcsafe``. -To enable the GC-safety checking the ``--threadAnalysis:on`` command line -switch must be used. This is a temporary workaround to ease the porting effort -from old code to the new threading model. In the future the thread analysis -will always be performed. +To disable the GC-safety checking the ``--threadAnalysis:off`` command line +switch can be used. This is a temporary workaround to ease the porting effort +from old code to the new threading model. Future directions: @@ -59,13 +58,13 @@ Future directions: Threadvar pragma ---------------- -A global variable can be marked with the ``threadvar`` pragma; it is +A global variable can be marked with the ``threadvar`` pragma; it is a `thread-local`:idx: variable then: .. code-block:: nim var checkpoints* {.threadvar.}: seq[string] -Due to implementation restrictions thread local variables cannot be +Due to implementation restrictions thread local variables cannot be initialized within the ``var`` section. (Every thread local variable needs to be replicated at thread creation.) @@ -73,7 +72,7 @@ be replicated at thread creation.) Threads and exceptions ---------------------- -The interaction between threads and exceptions is simple: A *handled* exception +The interaction between threads and exceptions is simple: A *handled* exception in one thread cannot affect any other thread. However, an *unhandled* exception in one thread terminates the whole *process*! @@ -82,7 +81,7 @@ in one thread terminates the whole *process*! Parallel & Spawn ================ -Nim has two flavors of parallelism: +Nim has two flavors of parallelism: 1) `Structured`:idx: parallelism via the ``parallel`` statement. 2) `Unstructured`:idx: parallelism via the standalone ``spawn`` statement. @@ -115,7 +114,7 @@ Spawn statement proc processLine(line: string) = discard "do some heavy lifting here" - + for x in lines("myinput.txt"): spawn processLine(x) sync() @@ -144,7 +143,7 @@ wait on multiple flow variables at the same time: .. code-block:: nim import threadpool, ... - + # wait until 2 out of 3 servers received the update: proc main = var responses = newSeq[RawFlowVar](3) @@ -203,8 +202,7 @@ restrictions / changes: the ``parallel`` section. This is called the *immutability check*. Currently it is not specified what exactly "complex location" means. We need to make this an optimization! -* Every array access has to be provably within bounds. This is called +* Every array access has to be provably within bounds. This is called the *bounds check*. * Slices are optimized so that no copy is performed. This optimization is not - yet performed for ordinary slices outside of a ``parallel`` section. Slices - are also special in that they currently do not support negative indexes! + yet performed for ordinary slices outside of a ``parallel`` section. diff --git a/doc/manual/type_bound_ops.txt b/doc/manual/type_bound_ops.txt index 59d55a6cd..c707979fe 100644 --- a/doc/manual/type_bound_ops.txt +++ b/doc/manual/type_bound_ops.txt @@ -21,27 +21,49 @@ helper distinct or object type has to be used for one pointer type. operator `=` ------------ -This operator is the assignment operator. Note that in the contexts -like ``let v = expr``, ``var v = expr``, ``parameter = defaultValue`` or for -parameter passing no assignment is performed. The ``override`` pragma is -optional for overriding ``=``. +This operator is the assignment operator. Note that in the contexts +``result = expr``, ``parameter = defaultValue`` or for +parameter passing no assignment is performed. For a type ``T`` that has an +overloaded assignment operator ``var v = T()`` is rewritten +to ``var v: T; v = T()``; in other words ``var`` and ``let`` contexts do count +as assignments. + +The assignment operator needs to be attached to an object or distinct +type ``T``. Its signature has to be ``(var T, T)``. Example: + +.. code-block:: nim + type + Concrete = object + a, b: string + + proc `=`(d: var Concrete; src: Concrete) = + shallowCopy(d.a, src.a) + shallowCopy(d.b, src.b) + echo "Concrete '=' called" + + var x, y: array[0..2, Concrete] + var cA, cB: Concrete + + var cATup, cBTup: tuple[x: int, ha: Concrete] + + x = y + cA = cB + cATup = cBTup -**Note**: Overriding of operator ``=`` is not yet implemented. destructors ----------- A destructor must have a single parameter with a concrete type (the name of a -generic type is allowed too). The name of the destructor has to be ``destroy`` -and it need to be annotated with the ``override`` pragma. +generic type is allowed too). The name of the destructor has to be ``=destroy``. -``destroy(v)`` will be automatically invoked for every local stack +``=destroy(v)`` will be automatically invoked for every local stack variable ``v`` that goes out of scope. -If a structured type features a field with destructable type and +If a structured type features a field with destructable type and the user has not provided an explicit implementation, a destructor for the -structured type will be automatically generated. Calls to any base class +structured type will be automatically generated. Calls to any base class destructors in both user-defined and generated destructors will be inserted. A destructor is attached to the type it destructs; expressions of this type @@ -52,13 +74,13 @@ can then only be used in *destructible contexts* and as parameters: MyObj = object x, y: int p: pointer - - proc destroy(o: var MyObj) {.override.} = + + proc `=destroy`(o: var MyObj) = if o.p != nil: dealloc o.p - + proc open: MyObj = result = MyObj(x: 1, y: 2, p: alloc(3)) - + proc work(o: MyObj) = echo o.x # No destructor invoked here for 'o' as 'o' is a parameter. @@ -68,7 +90,7 @@ can then only be used in *destructible contexts* and as parameters: var x = open() # valid: pass 'x' to some other proc: work(x) - + # Error: usage of a type with a destructor in a non destructible context echo open() @@ -85,7 +107,7 @@ be destructed at its scope exit. Later versions of the language will improve the support of destructors. Be aware that destructors are not called for objects allocated with ``new``. -This may change in future versions of language, but for now the ``finalizer`` +This may change in future versions of language, but for now the `finalizer`:idx: parameter to ``new`` has to be used. **Note**: Destructors are still experimental and the spec might change @@ -95,7 +117,7 @@ significantly in order to incorporate an escape analysis. deepCopy -------- -``deepCopy`` is a builtin that is invoked whenever data is passed to +``=deepCopy`` is a builtin that is invoked whenever data is passed to a ``spawn``'ed proc to ensure memory safety. The programmer can override its behaviour for a specific ``ref`` or ``ptr`` type ``T``. (Later versions of the language may weaken this restriction.) @@ -103,10 +125,10 @@ language may weaken this restriction.) The signature has to be: .. code-block:: nim - proc deepCopy(x: T): T {.override.} + proc `=deepCopy`(x: T): T -This mechanism is used by most data structures that support shared memory like -channels to implement thread safe automatic memory management. +This mechanism will be used by most data structures that support shared memory +like channels to implement thread safe automatic memory management. The builtin ``deepCopy`` can even clone closures and their environments. See the documentation of `spawn`_ for details. diff --git a/doc/manual/typedesc.txt b/doc/manual/typedesc.txt index 5087c1204..de1d84d7d 100644 --- a/doc/manual/typedesc.txt +++ b/doc/manual/typedesc.txt @@ -6,7 +6,7 @@ static[T] **Note**: static[T] is still in development. -As their name suggests, static params must be known at compile-time: +As their name suggests, static parameters must be known at compile-time: .. code-block:: nim @@ -23,23 +23,7 @@ As their name suggests, static params must be known at compile-time: For the purposes of code generation, all static params are treated as generic params - the proc will be compiled separately for each unique -supplied value (or combination of values). - -Furthermore, the system module defines a `semistatic[T]` type that can be -used to declare procs accepting both static and run-time values, which can -optimize their body according to the supplied param using the `isStatic(p)` -predicate: - -.. code-block:: nim - - # The following proc will be compiled once for each unique static - # value and also once for the case handling all run-time values: - - proc re(pattern: semistatic[string]): RegEx = - when isStatic(pattern): - result = precompiledRegex(pattern) - else: - result = compile(pattern) +supplied value (or combination of values). Static params can also appear in the signatures of generic types: @@ -61,7 +45,7 @@ typedesc -------- `typedesc` is a special type allowing one to treat types as compile-time values -(i.e. if types are compile-time values and all values have a type, then +(i.e. if types are compile-time values and all values have a type, then typedesc must be their type). When used as a regular proc param, typedesc acts as a type class. The proc @@ -82,9 +66,6 @@ When multiple typedesc params are present, they act like a distinct type class one can use a named alias or an explicit `typedesc` generic param: .. code-block:: nim - - # `type1` and `type2` are aliases for typedesc available from system.nim - proc acceptOnlyTypePairs(A, B: type1; C, D: type2) proc acceptOnlyTypePairs[T: typedesc, U: typedesc](A, B: T; C, D: U) Once bound, typedesc params can appear in the rest of the proc signature: @@ -100,7 +81,7 @@ When used with macros and .compileTime. procs on the other hand, the compiler does not need to instantiate the code multiple times, because types then can be manipulated using the unified internal symbol representation. In such context typedesc acts as any other type. One can create variables, store typedesc -values inside containers and so on. For example, here is how one can create +values inside containers and so on. For example, here is how one can create a type-safe wrapper for the unsafe `printf` function from C: .. code-block:: nim @@ -114,7 +95,7 @@ a type-safe wrapper for the unsafe `printf` function from C: of 's': string of 'p': pointer else: EOutOfRange - + var actualType = args[i].getType inc i @@ -123,7 +104,7 @@ a type-safe wrapper for the unsafe `printf` function from C: elif expectedType != actualType: error "type mismatch for argument ", i, ". expected type: ", expectedType.name, ", actual type: ", actualType.name - + # keep the original callsite, but use cprintf instead result = callsite() result[0] = newIdentNode(!"cprintf") diff --git a/doc/manual/types.txt b/doc/manual/types.txt index c78984db8..bdf51941d 100644 --- a/doc/manual/types.txt +++ b/doc/manual/types.txt @@ -568,7 +568,7 @@ the ``of`` operator can be used to determine the object's type. name*: string # the * means that `name` is accessible from other modules age: int # no * means that the field is hidden - Student = object of Person # a student is a person + Student = ref object of Person # a student is a person id: int # with an id field var @@ -864,7 +864,9 @@ Future directions: * Builtin regions like ``private``, ``global`` and ``local`` will prove very useful for the upcoming OpenCL target. * Builtin "regions" can model ``lent`` and ``unique`` pointers. - +* An assignment operator can be attached to a region so that proper write + barriers can be generated. This would imply that the GC can be implemented + completely in user-space. Procedural type |