-
Notifications
You must be signed in to change notification settings - Fork 4
/
currying.nim
60 lines (54 loc) · 1.51 KB
/
currying.nim
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
import macros, sugar, sequtils
proc typedParams(params: NimNode): seq[NimNode] {.compileTime.} =
## (a, b: int, c: float)
## -> (a: int, b: int, c: float)
params.expectKind nnkFormalParams
result = newSeq[NimNode]()
for param in params:
case param.kind
of nnkIdentDefs:
let identType = param[param.len-2]
for i in 0..<param.len-2:
result.add(newIdentDefs(param[i], identType))
else:
result.add(param)
macro curried*(f: untyped): auto =
result = newStmtList()
var
genericParams = f[2]
originalParams = typedParams(f.params())
result.add(newNimNode(nnkProcDef).add(
f.name().copy(),
newEmptyNode(),
genericParams.copy(),
newNimNode(nnkFormalParams).add(
map(originalParams, param => param.copy())
),
newEmptyNode(),
newEmptyNode(),
f.body().copy()))
var baseParams = originalParams
baseParams[0] = newIdentNode("auto")
for i in countdown(baseParams.len-1, 2):
result.add(newNimNode(nnkProcDef).add(
f.name().copy(),
newEmptyNode(),
genericParams.copy(),
newNimNode(nnkFormalParams).add(
map(baseParams[0..i-1], param => param.copy())
),
newEmptyNode(),
newEmptyNode(),
newStmtList(
newProc(
params=[baseParams[0], baseParams[i]],
body=newStmtList(
newCall(
f.name().copy(),
map(baseParams[1..i], param => param[0].copy())
)
),
procType=nnkLambda
)
)
))