diff options
author | metagn <metagngn@gmail.com> | 2024-08-28 21:51:13 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-08-28 20:51:13 +0200 |
commit | 770f8d551372893ed480550062a89e76c60ff4a8 (patch) | |
tree | 87f6e049aea09dfcd9bbed2fccb67f84d3172445 /doc | |
parent | d3af51e3ce968076bb3331087806312c0faba054 (diff) | |
download | Nim-770f8d551372893ed480550062a89e76c60ff4a8.tar.gz |
opensym for templates + move behavior of opensymchoice to itself (#24007)
fixes #15314, fixes #24002 The OpenSym behavior first added to generics in #23091 now also applies to templates, since templates can also capture symbols that are meant to be replaced by local symbols if the context imports symbols with the same name, as in the issue #24002. The experimental switch `templateOpenSym` is added to enable this behavior for templates only, and the experimental switch `openSym` is added to enable it for both templates and generics, and the documentation now mainly mentions this switch. Additionally the logic for `nkOpenSymChoice` nodes that were previously wrapped in `nkOpenSym` now apply to all `nkOpenSymChoice` nodes, and so these nodes aren't wrapped in `nkOpenSym` anymore. This means `nkOpenSym` can only have children of kind `nkSym` again, so it is more in line with the structure of symchoice nodes. As for why they aren't merged with `nkOpenSymChoice` nodes yet, we need some way to signal that the node shouldn't become ambiguous if other options exist at instantiation time, we already captured a symbol at the beginning and another symbol can only replace it if it's closer in scope and unambiguous.
Diffstat (limited to 'doc')
-rw-r--r-- | doc/manual_experimental.md | 57 |
1 files changed, 39 insertions, 18 deletions
diff --git a/doc/manual_experimental.md b/doc/manual_experimental.md index 34399e6f9..6998e313d 100644 --- a/doc/manual_experimental.md +++ b/doc/manual_experimental.md @@ -2522,33 +2522,40 @@ Notice we use the overload of `()` to have the same semantics in Nim, but on the This allows to easy interop with functions that accepts for example a `const` operator in its signature. -Injected symbols in generic procs -================================= +Injected symbols in generic procs and templates +=============================================== -With the experimental option `genericsOpenSym`, captured symbols in generic -routine bodies may be replaced by symbols injected locally by templates/macros -at instantiation time. `bind` may be used to keep the captured symbols over -the injected ones regardless of enabling the option, but other methods like +With the experimental option `openSym`, captured symbols in generic routine and +template bodies may be replaced by symbols injected locally by templates/macros +at instantiation time. `bind` may be used to keep the captured symbols over the +injected ones regardless of enabling the options, but other methods like renaming the captured symbols should be used instead so that the code is not affected by context changes. - + Since this change may affect runtime behavior, the experimental switch -`genericsOpenSym` needs to be enabled, and a warning is given in the case -where an injected symbol would replace a captured symbol not bound by `bind` -and the experimental switch isn't enabled. +`openSym`, or `genericsOpenSym` and `templateOpenSym` for only the respective +routines, needs to be enabled; and a warning is given in the case where an +injected symbol would replace a captured symbol not bound by `bind` and +the experimental switch isn't enabled. ```nim const value = "captured" -template foo(x: int, body: untyped) = +template foo(x: int, body: untyped): untyped = let value {.inject.} = "injected" body proc old[T](): string = foo(123): - return value # warning: a new `value` has been injected, use `bind` or turn on `experimental:genericsOpenSym` + return value # warning: a new `value` has been injected, use `bind` or turn on `experimental:openSym` echo old[int]() # "captured" -{.experimental: "genericsOpenSym".} +template oldTempl(): string = + block: + foo(123): + value # warning: a new `value` has been injected, use `bind` or turn on `experimental:openSym` +echo oldTempl() # "captured" + +{.experimental: "openSym".} # or {.experimental: "genericsOpenSym".} for just generic procs proc bar[T](): string = foo(123): @@ -2560,14 +2567,28 @@ proc baz[T](): string = foo(123): return value assert baz[int]() == "captured" + +# {.experimental: "templateOpenSym".} would be needed here if genericsOpenSym was used + +template barTempl(): string = + block: + foo(123): + value +assert barTempl() == "injected" # previously it would be "captured" + +template bazTempl(): string = + bind value + block: + foo(123): + value +assert bazTempl() == "captured" ``` This option also generates a new node kind `nnkOpenSym` which contains -exactly 1 of either an `nnkSym` or an `nnkOpenSymChoice` node. In the future -this might be merged with a slightly modified `nnkOpenSymChoice` node but -macros that want to support the experimental feature should still handle -`nnkOpenSym`, as the node kind would simply not be generated as opposed to -being removed. +exactly 1 `nnkSym` node. In the future this might be merged with a slightly +modified `nnkOpenSymChoice` node but macros that want to support the +experimental feature should still handle `nnkOpenSym`, as the node kind would +simply not be generated as opposed to being removed. VTable for methods |