@@ -14,9 +14,37 @@ export versionInfo
14
14
15
15
const
16
16
Version* = asVersion(Major, Minor, Patch)
17
+ template exportSincePy* (major, minor: int , sym: typed ) =
18
+ bind PyMajor, PyMinor
19
+ when (PyMajor, PyMinor) >= (major, minor):
20
+ export sym
21
+
22
+ import std/ macros
23
+ proc newCallFrom(sym, params: NimNode): NimNode =
24
+ result = newCall(sym)
25
+ for i in 1 ..< params.len:
26
+ result .add params[i][0 ]
27
+
28
+ proc templWrapExportSincePyImpl(major, minor: int , sym: NimNode): NimNode =
29
+ let emptyn = newEmptyNode()
30
+ result = newNimNode nnkTemplateDef
31
+ let
32
+ impl = sym.getImpl()
33
+ params = impl[3 ]
34
+ var nparams = params.copyNimTree
35
+ nparams[0 ] = bindSym" untyped"
36
+ result .add(
37
+ postfix(sym, " *" ), emptyn, # term rewrite
38
+ impl[2 ], nparams,
39
+ emptyn, emptyn, # pragma, preversed
40
+ newStmtList sym.newCallFrom params
41
+ )
42
+
43
+ macro templWrapExportSincePy* (major, minor: static int , sym: typed ) =
44
+ # # generate `template sym*(...): untyped = sym(...)`
45
+ templWrapExportSincePyImpl(major, minor, sym)
17
46
18
47
when defined(nimdoc):
19
- import std/ macros
20
48
func preappendDoc(body: NimNode, doc: string ) =
21
49
let first = body[0 ]
22
50
if first.kind == nnkCommentStmt:
@@ -34,17 +62,47 @@ when defined(nimdoc):
34
62
# # as diagnosis tools like dumpTree just omit doc node of non-proc node
35
63
template descSince(ver: string ): string =
36
64
" .. admonition:: since Python " & ver & " \n\n "
65
+ func addDocImpl(major, minor: int ; def: NimNode): NimNode =
66
+ addDocImpl(asVersion(major, minor).descSince, def)
37
67
macro pysince* (major, minor: static int , def) =
38
68
if def.kind == nnkStmtList:
39
69
result = def
40
70
else :
41
- result = addDocImpl(asVersion(major, minor).descSince, def)
71
+ result = addDocImpl(major, minor, def)
72
+
73
+ proc genWrapCall(sym: NimNode): NimNode =
74
+ result = sym.getImpl()
75
+ var call = sym.newCallFrom result .params
76
+ case result .kind
77
+ of nnkIteratorDef:
78
+ call = quote do :
79
+ for i in `call`: yield i
80
+ of nnkMacroDef, nnkTemplateDef:
81
+ var nres = newNimNode nnkTemplateDef
82
+ nres.add postfix(ident result [0 ].strVal, " *" ) # get rid of
83
+ # Error: cannot use symbol of kind 'macro' as a 'template
84
+ for i in 1 ..< result .len- 1 : # skip body
85
+ nres.add result [i]
86
+ nres.add newEmptyNode()
87
+ result = nres
88
+ else : discard
89
+ result .body = newStmtList call
90
+
91
+ macro wrapExportSincePy* (major, minor: static int , sym: typed ) =
92
+ if sym.typeKind == ntyProc: # includes template, macro
93
+ let def = sym.genWrapCall()
94
+ result = addDocImpl(major, minor, def)
95
+ else :
96
+ result = newCall(bindSym" exportSincePy" , major.newLit, minor.newLit, sym)
42
97
43
98
else :
44
99
template pysince* (major, minor: int , def){.dirty.} =
45
100
bind PyMajor, PyMinor
46
101
when (PyMajor, PyMinor) >= (major, minor):
47
102
def
103
+ template wrapExportSincePy* (major, minor: int , sym: typed ) =
104
+ bind exportSincePy
105
+ exportSincePy(major, minor, sym)
48
106
49
107
type MajorMinorVersion = tuple [major, minor: int ]
50
108
0 commit comments