forked from nim-lang/Nim
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
605: template non-ast param limited to lookup substitution r=zerbina a=saem ## Summary * non-ast params (excluding `typed` and `untyped`) are only substituted for usage positions * where a usage positionis is any syntactic position where a symbol is not intended to be introduced * in additition, the manual and semtempl module have some doc comments outlining the new direction for templates ## Details Starting with a motivating example, this now works after the change: ```nim template foo(data: int): untyped = proc bar(data: int): int = 2 * data bar(data) doAssert foo(2) == 4 ``` The reason this works now is `data` the template arg is a non-ast type, it's not substituted into `data` the proc param, and `data` the proc param is instead converted into a symbol. This means that when `data` the proc body usage is looked up, it's lexically resolved with `data` the proc param. Finally, when `data` the call argument's usage is looked up, the template param is found and substituted. ### Further Details Template parameters that are neither `typed` or `untyped` will no longer subsititute for definitional syntax positions, or syntax positions that meant to introduce routines, variables, types and other named definitions. For non-ast typed substitution lexical scope based lookups are used. AST typed template parameter substitutions continue to work as is, since they're arbitrary symbolic substitutions. This makes more sense given that we're substituting syntactic symbol usage as opposed to syntactic symbol introductions; but it also removes a vector by which symbol pollution can take place. As templates have lots of rough edges in implementation there are still many bugs, but these are almost entirely pre-existing. ### Overview of Concepts Introduced: This is a brief overview, see the module and docs for more info, also this is developing, these are still mostly in docs: * the concept of template substitution being policy being set by template output type has been introduced * a template body is to be thought of as an out parameter with the same type as the template output * additionally, a template body can be considered as a form of quasi quoting, where the type determines how we treat the substitution of various kinds of parameters (ast and non-ast types). Co-authored-by: saem <saemghani+github@gmail.com>
- Loading branch information
Showing
5 changed files
with
129 additions
and
49 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
25 changes: 25 additions & 0 deletions
25
tests/lang_callable/template/template_usage_substitution_nonast_typed_params.nim
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
discard """ | ||
description: ''' | ||
Templates parameters of non-AST type do not replace identifiers in new symbol | ||
definition positions. Meaning a template parameter that is not `untyped` or | ||
`typed` will not substitute for a matching identifier if defining things like | ||
variables, routines, parameters, types, fields, etc. | ||
''' | ||
""" | ||
|
||
block originally_this_did_not_work_now_it_does: | ||
# this was kept for historical reasons and can be replaced, when this was an | ||
# error it originated from https://github.com/nim-lang/nim/issues/3158 | ||
type | ||
MyData = object | ||
x: int | ||
|
||
template newDataWindow(data: ref MyData): untyped = | ||
proc testProc(data: ref MyData): string = | ||
"Hello, " & $data.x | ||
testProc(data) | ||
|
||
var d: ref MyData | ||
new(d) | ||
d.x = 10 | ||
doAssert newDataWindow(d) == "Hello, 10" |
This file was deleted.
Oops, something went wrong.