diff options
-rw-r--r-- | compiler/parser.nim | 2 | ||||
-rw-r--r-- | doc/manual.rst | 64 | ||||
-rw-r--r-- | tests/destructor/t6434.nim | 19 | ||||
-rw-r--r-- | tests/iter/tchainediterators2.nim | 81 |
4 files changed, 141 insertions, 25 deletions
diff --git a/compiler/parser.nim b/compiler/parser.nim index 7667d3a0e..69e372e4e 100644 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -1517,7 +1517,7 @@ proc parseCase(p: var TParser): PNode = #| | IND{=} ofBranches) var b: PNode - inElif= false + inElif = false wasIndented = false result = newNodeP(nkCaseStmt, p) getTok(p) diff --git a/doc/manual.rst b/doc/manual.rst index 7946e88dd..6afc10473 100644 --- a/doc/manual.rst +++ b/doc/manual.rst @@ -3638,10 +3638,31 @@ Invocation of a multi-method cannot be ambiguous: collide 2 is preferred over collide 1 because the resolution works from left to right. In the example ``Unit, Thing`` is preferred over ``Thing, Unit``. -**Performance note**: Nim does not produce a virtual method table, but -generates dispatch trees. This avoids the expensive indirect branch for method -calls and enables inlining. However, other optimizations like compile time -evaluation or dead code elimination do not work with methods. +**Note**: Compile time evaluation is not (yet) supported for methods. + + +Inhibit dynamic method resolution via procCall +----------------------------------------------- + +Dynamic method resolution can be inhibited via the builtin `system.procCall`:idx:. +This is somewhat comparable to the `super`:idx: keyword that traditional OOP +languages offer. + +.. code-block:: nim + :test: "nim c $1" + + type + Thing = ref object of RootObj + Unit = ref object of Thing + x: int + + method m(a: Thing) {.base.} = + echo "base" + + method m(a: Unit) = + # Call the base method: + procCall m(Thing(a)) + echo "1" Iterators and the for statement @@ -6549,7 +6570,7 @@ preface definitions inside a module. .. NOTE: The following was documentation for the code reordering precursor, which was {.noForward.}. - + In this mode, procedure definitions may appear out of order and the compiler will postpone their semantic analysis and compilation until it actually needs to generate code using the definitions. In this regard, this mode is similar @@ -6672,18 +6693,12 @@ The deprecated pragma is used to mark a symbol as deprecated: 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()".} + proc thing(x: bool) {.deprecated: "use thong instead".} -It can also be used as a statement, in that case it takes a list of *renamings*. - -.. code-block:: nim - type - File = object - Stream = ref object - {.deprecated: [TFile: File, PStream: Stream].} noSideEffect pragma ------------------- + The ``noSideEffect`` pragma is used to mark a proc/iterator to have no side effects. This means that the proc/iterator only changes locations that are reachable from its parameters and the return value only depends on the @@ -7731,20 +7746,21 @@ documentation for details. These macros are no magic, they don't do anything you cannot do yourself by walking AST object representation. More examples with custom pragmas: - - Better serialization/deserialization control: - .. code-block:: nim - type MyObj = object - a {.dontSerialize.}: int - b {.defaultDeserialize: 5.}: int - c {.serializationKey: "_c".}: string +- Better serialization/deserialization control: + +.. code-block:: nim + type MyObj = object + a {.dontSerialize.}: int + b {.defaultDeserialize: 5.}: int + c {.serializationKey: "_c".}: string - - Adopting type for gui inspector in a game engine: +- Adopting type for gui inspector in a game engine: - .. code-block:: nim - type MyComponent = object - position {.editable, animatable.}: Vector3 - alpha {.editRange: [0.0..1.0], animatable.}: float32 +.. code-block:: nim + type MyComponent = object + position {.editable, animatable.}: Vector3 + alpha {.editRange: [0.0..1.0], animatable.}: float32 diff --git a/tests/destructor/t6434.nim b/tests/destructor/t6434.nim new file mode 100644 index 000000000..1657e90bc --- /dev/null +++ b/tests/destructor/t6434.nim @@ -0,0 +1,19 @@ +discard """ + exitcode: 0 + output: '''assingment +assingment +''' +""" + +type + Foo* = object + boo: int + +proc `=`(dest: var Foo, src: Foo) = + debugEcho "assingment" + +proc test(): auto = + var a,b : Foo + return (a, b) + +var (a, b) = test() \ No newline at end of file diff --git a/tests/iter/tchainediterators2.nim b/tests/iter/tchainediterators2.nim new file mode 100644 index 000000000..c2e5e6170 --- /dev/null +++ b/tests/iter/tchainediterators2.nim @@ -0,0 +1,81 @@ +discard """ + output: '''start +false +0 +1 +2 +end +@[2, 4, 6, 8, 10] +@[4, 8, 12, 16, 20]''' +""" + +# bug #3837 + +proc iter1(): (iterator: int) = + let coll = [0,1,2] + result = iterator: int {.closure.} = + for i in coll: + yield i + +proc iter2(it: (iterator: int)): (iterator: int) = + result = iterator: int {.closure.} = + echo finished(it) + for i in it(): + yield i + +echo "start" +let myiter1 = iter1() +let myiter2 = iter2(myiter1) +for i in myiter2(): + echo i +echo "end" +# start +# false +# end + + +from sequtils import toSeq + +type Iterable*[T] = (iterator: T) | Slice[T] + ## Everything that can be iterated over, iterators and slices so far. + +proc toIter*[T](s: Slice[T]): iterator: T = + ## Iterate over a slice. + iterator it: T {.closure.} = + for x in s.a..s.b: + yield x + return it + +proc toIter*[T](i: iterator: T): iterator: T = + ## Nop + i + +iterator map*[T,S](i: Iterable[T], f: proc(x: T): S): S = + let i = toIter(i) + for x in i(): + yield f(x) + +proc filter*[T](i: Iterable[T], f: proc(x: T): bool): iterator: T = + ## Iterates through an iterator and yields every item that fulfills the + ## predicate `f`. + ## + ## .. code-block:: nim + ## for x in filter(1..11, proc(x): bool = x mod 2 == 0): + ## echo x + let i = toIter(i) + iterator it: T {.closure.} = + for x in i(): + if f(x): + yield x + result = it + +iterator filter*[T](i: Iterable[T], f: proc(x: T): bool): T = + let i = toIter(i) + for x in i(): + if f(x): + yield x + +var it = toSeq(filter(2..10, proc(x: int): bool = x mod 2 == 0)) +echo it # @[2, 4, 6, 8, 10] +it = toSeq(map(filter(2..10, proc(x: int): bool = x mod 2 == 0), proc(x: int): int = x * 2)) +echo it # Expected output: @[4, 8, 12, 16, 20], Actual output: @[] |