Skip to content

Commit f86b756

Browse files
authored
Merge pull request #22 from hamidb80/nested
fix Nested
2 parents 5fb9101 + 2a7fbba commit f86b756

File tree

5 files changed

+100
-51
lines changed

5 files changed

+100
-51
lines changed

iterrr.nimble

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Package
22

3-
version = "0.4.3"
3+
version = "0.4.5"
44
author = "hamidb80"
55
description = "iterate faster. functional style, lazy like, extensible iterator library"
66
license = "MIT"

src/iterrr.nim

Lines changed: 34 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -72,12 +72,14 @@ func genBracketExprOf(id: NimNode, len: int): seq[NimNode] =
7272
for i in 0 ..< len:
7373
result.add newTree(nnkBracketExpr, id, newIntLitNode i)
7474

75-
func replacedIteratorIdents(expr: NimNode, aliases: seq[NimNode]): NimNode =
75+
func replacedIteratorIdents(expr: NimNode,
76+
aliases: seq[NimNode], by: NimNode): NimNode =
77+
7678
case aliases.len:
77-
of 0: expr
78-
of 1: expr.replacedIdent(aliases[0], ident "it")
79+
of 0: expr.replacedIdent(ident "it", by)
80+
of 1: expr.replacedIdent(aliases[0], by)
7981
else:
80-
expr.replacedIdents(aliases, genBracketExprOf(ident"it", aliases.len))
82+
expr.replacedIdents(aliases, genBracketExprOf(by, aliases.len))
8183

8284
func toIterrrPack(calls: seq[NimNode]): IterrrPack =
8385
var hasReducer = false
@@ -120,14 +122,14 @@ func toIterrrPack(calls: seq[NimNode]): IterrrPack =
120122

121123
assert hasReducer, "must set reducer"
122124

123-
func detectTypeImpl(itrbl: NimNode, ttrfs: seq[TypeTransformer]): NimNode =
125+
func detectTypeImpl(itrbl, iterIdent: NimNode, ttrfs: seq[TypeTransformer]): NimNode =
124126
var cursor = inlineQuote default(typeof(`itrbl`))
125127

126128
for t in ttrfs:
127129
cursor =
128130
case t.kind:
129131
of hoMap:
130-
replacedIdent(t.expr, ident "it", cursor)
132+
replacedIdent(t.expr, iterIdent, cursor)
131133

132134
of hoCustom:
133135
newCall ident"default":
@@ -137,8 +139,8 @@ func detectTypeImpl(itrbl: NimNode, ttrfs: seq[TypeTransformer]): NimNode =
137139

138140
inlineQuote typeof(`cursor`)
139141

140-
func detectType(itrbl: NimNode, callChain: seq[HigherOrderCall]): NimNode =
141-
detectTypeImpl itrbl:
142+
func detectType(itrbl, iterIdent: NimNode, callChain: seq[HigherOrderCall]): NimNode =
143+
detectTypeImpl itrbl, iterIdent:
142144
var temp: seq[TypeTransformer]
143145
for c in callChain:
144146
case c.kind:
@@ -152,10 +154,10 @@ func detectType(itrbl: NimNode, callChain: seq[HigherOrderCall]): NimNode =
152154

153155
temp
154156

155-
func resolveIteratorAliases(ipack: var IterrrPack) =
157+
func resolveIteratorAliases(ipack: var IterrrPack, iterIdent: NimNode) =
156158
for c in ipack.callChain.mitems:
157159
if c.kind != hoCustom:
158-
c.expr = c.expr.replacedIteratorIdents(c.iteratorIdentAliases)
160+
c.expr = c.expr.replacedIteratorIdents(c.iteratorIdentAliases, iterIdent)
159161

160162
proc resolveUniqIdents(node: NimNode, by: string) =
161163
## appends `by` to every nnkAccQuote node recursively
@@ -168,17 +170,18 @@ proc resolveUniqIdents(node: NimNode, by: string) =
168170
proc iterrrImpl(itrbl: NimNode, calls: seq[NimNode],
169171
code: NimNode = nil): NimNode =
170172

173+
let uniqLoopIdent = ident "loopIdent_" & genUniqId()
174+
171175
# var ipack = toIterrrPack inspect calls
172176
var ipack = toIterrrPack calls
173-
resolveIteratorAliases ipack
177+
resolveIteratorAliases ipack, uniqLoopIdent
174178

175179
let
176180
hasCustomCode = code != nil
177181
noAcc = hasCustomCode and eqident(ipack.reducer.caller, "each")
178182
hasInplaceReducer = eqident(ipack.reducer.caller, "reduce")
179183

180184
accIdent = ident "acc"
181-
itIdent = ident "it"
182185
mainLoopIdent = ident "mainLoop"
183186
reducerStateUpdaterProcIdent = ipack.reducer.caller
184187
reducerFinalizerProcIdent = ipack.reducer.caller &. "Finalizer"
@@ -193,7 +196,7 @@ proc iterrrImpl(itrbl: NimNode, calls: seq[NimNode],
193196

194197
else:
195198
let
196-
dtype = detectType(itrbl, ipack.callChain)
199+
dtype = detectType(itrbl, uniqLoopIdent, ipack.callChain)
197200
reducerInitCall = newTree(nnkBracketExpr, reducerInitProcIdent,
198201
dtype).newCall.add:
199202
ipack.reducer.params
@@ -218,30 +221,36 @@ proc iterrrImpl(itrbl: NimNode, calls: seq[NimNode],
218221
var
219222
wrappers: seq[tuple[code: NimNode, dtype: NimNode, params: seq[NimNode],
220223
info: AdapterInfo]]
224+
221225
loopBody =
222226
if noAcc:
223-
code.replacedIteratorIdents(ipack.reducer.params)
227+
code.replacedIteratorIdents(ipack.reducer.params, uniqLoopIdent)
224228

225229
elif hasInplaceReducer:
226230
if ipack.reducer.idents.len == 2:
227231
let k = ipack.reducer.idents[1].kind
232+
228233
case k:
229234
of nnkIdent:
230-
code.replacedIdents(ipack.reducer.idents, [accIdent, itIdent])
235+
code.replacedIdents(ipack.reducer.idents, [accIdent, uniqLoopIdent])
236+
231237
of nnkTupleConstr:
232238
let
233239
customIdents = ipack.reducer.idents[1].toseq
234-
repls = genBracketExprOf(ident "it", customIdents.len)
235-
code.replacedIdents(ipack.reducer.idents[0] & customIdents, @[
236-
accIdent] & repls)
240+
repls = genBracketExprOf(uniqLoopIdent, customIdents.len)
241+
242+
code.replacedIdents(
243+
ipack.reducer.idents[0] & customIdents,
244+
@[accIdent] & repls)
245+
237246
else:
238247
err "invalid inplace reducer custom ident type. got: " & $k
239248
else:
240-
code
249+
code.replacedIdent ident"it", uniqLoopIdent
241250

242251
else:
243252
quote:
244-
if not `reducerStateUpdaterProcIdent`(`accIdent`, `itIdent`):
253+
if not `reducerStateUpdaterProcIdent`(`accIdent`, `uniqLoopIdent`):
245254
break `mainLoopIdent`
246255

247256

@@ -255,7 +264,7 @@ proc iterrrImpl(itrbl: NimNode, calls: seq[NimNode],
255264
of hoMap:
256265
quote:
257266
block:
258-
let `itIdent` = `p`
267+
let `uniqLoopIdent` = `p`
259268
`loopBody`
260269

261270
of hoFilter:
@@ -275,7 +284,7 @@ proc iterrrImpl(itrbl: NimNode, calls: seq[NimNode],
275284

276285
of hoCustom:
277286
let adptr = customAdapters[call.name.strval]
278-
var code = copy adptr.wrapperCode
287+
var code = adptr.wrapperCode.copy.replacedIdent(ident"it", uniqLoopIdent)
279288

280289
code.resolveUniqIdents $i
281290

@@ -288,23 +297,23 @@ proc iterrrImpl(itrbl: NimNode, calls: seq[NimNode],
288297
else:
289298
quote:
290299
block:
291-
let `itIdent` = `yval`
300+
let `uniqLoopIdent` = `yval`
292301
`loopBody`
293302

294303
wrappers.add:
295304
let dtype = # speed optimzation for adptr who don't use generic type. like `cycle` and `flatten`
296305
if adptr.iterTypePaths.len == 0:
297306
newEmptyNode()
298307
else:
299-
detectType(itrbl, ipack.callChain[0..i-1])
308+
detectType(itrbl, uniqLoopIdent, ipack.callChain[0..i-1])
300309

301310
(code, dtype, call.params, adptr)
302311

303312
code.getNode(adptr.loopPath)[ForBody]
304313

305314

306315
result = quote:
307-
for `itIdent` in `itrbl`:
316+
for `uniqLoopIdent` in `itrbl`:
308317
`loopBody`
309318

310319
for w in wrappers.ritems:

src/iterrr/adapters.nim

Lines changed: 45 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,51 @@
1-
import std/[macros, tables, sugar, strutils]
1+
import std/[macros, tables, strutils]
22
import macroplus
33
import helper
44

5+
6+
type AdapterInfo* = ref object
7+
wrapperCode*: NimNode
8+
loopPath*: NodePath
9+
iterTypePaths*, yeildPaths*, loopIterPaths*, argsValuePaths*: seq[NodePath]
10+
511
# impl ------------------------------------------
612

7-
type
8-
AdapterInfo* = ref object
9-
wrapperCode*: NimNode
10-
loopPath*: NodePath
11-
iterTypePaths*, yeildPaths*, argsValuePaths*: seq[NodePath]
13+
proc fillAdapterInfoImpl(a: var AdapterInfo, path: var NodePath,
14+
body: NimNode, itrType, loopName: NimNode) =
15+
16+
template goFurther: untyped =
17+
fillAdapterInfoImpl a, path, ch, itrType, loopName
18+
19+
for i, ch in body:
20+
path.add i
21+
if ch.kind == nnkYieldStmt:
22+
a.yeildPaths.add path
23+
24+
elif ch.eqIdent itrType:
25+
a.iterTypePaths.add path
26+
27+
elif ch.eqIdent ident "it":
28+
a.loopIterPaths.add path
29+
30+
elif ch.kind == nnkForStmt and eqIdent(ch[ForRange], loopName):
31+
if a.loopPath == @[]:
32+
a.loopPath = path
33+
goFurther()
34+
35+
else:
36+
err "there must be only one for loop over main iterable"
37+
38+
else:
39+
goFurther()
40+
41+
path.del path.high
42+
43+
proc fillAdapterInfo(avp: seq[NodePath], body: NimNode,
44+
itrType, loopName: NimNode): AdapterInfo =
45+
46+
var path: NodePath
47+
result = AdapterInfo(argsValuePaths: avp, wrapperCode: body)
48+
fillAdapterInfoImpl result, path, body, itrType, loopName
1249

1350
var customAdapters* {.compileTime.}: Table[string, AdapterInfo]
1451

@@ -34,19 +71,8 @@ macro adapter*(iterDef): untyped =
3471
body.insert 0, argsDef
3572

3673
let
37-
adptr = AdapterInfo(
38-
argsValuePaths: argsValuePathsAcc,
39-
wrapperCode: body,
40-
yeildPaths: findPaths(body, (n) => n.kind == nnkYieldStmt),
41-
iterTypePaths: findPaths(body, (n) => n.eqIdent itrblId[IdentDefType]),
42-
loopPath: (
43-
let temp = findPaths(body,
44-
(n) => n.kind == nnkForStmt and eqIdent(n[ForRange], itrblId[IdentDefName]))
45-
46-
assert temp.len == 1, "there must be only one for loop over main iterable"
47-
temp[0]
48-
))
49-
74+
adptr = fillAdapterInfo(argsValuePathsAcc, body,
75+
itrblId[IdentDefType], itrblId[IdentDefName])
5076
name = nimIdentNormalize getName iterdef[RoutineName]
5177
typename = block:
5278
let i = ident name & "Type"

src/iterrr/helper.nim

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ func getName*(node: NimNode): string =
2929
## extracts the name for ident and exported ident
3030
## `id` => "id"
3131
## `id`* => "id
32-
32+
3333
case node.kind:
3434
of nnkIdent:
3535
node.strVal
@@ -46,7 +46,7 @@ proc replacedIdents*(root: NimNode, targets, bys: openArray[NimNode]): NimNode =
4646
if root.kind == nnkIdent:
4747
for i, target in targets:
4848
if eqIdent(root, target):
49-
return bys[i]
49+
return bys[i] # FIXME
5050

5151
root
5252

@@ -138,3 +138,10 @@ func findPaths*(node: NimNode,
138138
fn: proc(node: NimNode): bool): seq[NodePath] {.inline.} =
139139

140140
findPathsImpl node, fn, @[], result
141+
142+
# ------------------------
143+
144+
var c {.compileTime.} = 0
145+
proc genUniqId*(): string =
146+
inc c
147+
$c

tests/test.nim

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,13 @@ suite "main entities":
3030
check "yes".items |> map((c, it)).do(inc c).toSeq() == @[(0, 'y'), (1, 'e'),
3131
(2, 's')]
3232

33+
test "nested":
34+
let r = @[@[1, 2], @[3, 4]].pairs |>
35+
map[ia, a](
36+
a.pairs |> map[ib, _]((ia, ib)).toseq()).toseq()
37+
38+
check r == @[@[(0, 0), (0, 1)], @[(1, 0), (1, 1)]]
39+
3340
suite "custom ident :: []":
3441
test "1":
3542
check (1..10) |> filter[i](i < 5).toSeq() == @[1, 2, 3, 4]
@@ -115,11 +122,11 @@ suite "non-operator":
115122
check ("hello".items.iterrr filter(it != 'l').count()) == 3
116123
check iterrr("hello".items, filter(it != 'l').count()) == 3
117124

118-
test "inplace reducer":
119-
let prod = (3..6).iterrr reduce(1):
120-
acc *= it
125+
# test "inplace reducer":
126+
# let prod = (3..6).iterrr reduce(1):
127+
# acc *= it
121128

122-
check prod == 3*4*5*6
129+
# check prod == 3*4*5*6
123130

124131
test "each":
125132
var acc: seq[int]

0 commit comments

Comments
 (0)