Skip to content

Commit 3dcb1d6

Browse files
authored
Update divIterators.js
1 parent 920adef commit 3dcb1d6

1 file changed

Lines changed: 71 additions & 15 deletions

File tree

static/extensions/Div/divIterators.js

Lines changed: 71 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,11 @@
3131
consumed = 0
3232
done = false;
3333

34-
constructor(kind = "Empty", state = {}, next = function*() {return {value: undefined, done: true}}) {
34+
constructor(kind = "Empty", state = {}, next = function*() {return {value: undefined, done: true}}, clonable = true) {
3535
this.kind = [].concat(kind);
3636
this.state = state;
3737
this.iterNext = next;
38+
this.clonable = clonable;
3839
}
3940

4041
jwArrayHandler() {
@@ -91,7 +92,7 @@
9192
return new IteratorType();
9293
}
9394

94-
chainIter(kind, state, next) {return new IteratorType(this.kind.concat(kind), state, next)}
95+
chainIter(kind, state, next, clonable) {return new IteratorType(this.kind.concat(kind), state, next, clonable)}
9596

9697
*next(thread, target, runtime, stage) {
9798
if(this.done) return divIterator.Done()
@@ -102,13 +103,42 @@
102103
}
103104

104105
clone() {
106+
if(!this.clonable) {
107+
console.error(`Iterator chain '${this.getIterChain}' is not clonable. Use 'branch' instead, or check before cloning.`)
108+
throw `Iterator chain '${this.getIterChain}' is not clonable.`
109+
}
105110
const state = Object.fromEntries(Object.entries(this.state).map(([key, val]) => [key,
106111
val instanceof IteratorType ? val.clone() : val
107112
]))
108113
const clone = new IteratorType(this.kind, state, this.iterNext);
109114
clone.consumed = this.consumed;
110115
return clone
111116
}
117+
118+
branch(n) {
119+
const buffers = Array(n).fill().map(() => []);
120+
let done = false;
121+
return buffers.map(buffer => this.chainIter({kind: "Branch", args: [n]},
122+
{iter: this}, function*(state, thread, target, runtime, stage) {
123+
console.log(buffer);
124+
if(buffer.length > 0) return divIterator.Item(buffer.shift());
125+
if(done) return divIterator.Done();
126+
const item = yield* state.iter.next(thread, target, runtime, stage);
127+
done = item.done; if(item.done) return divIterator.Done()
128+
buffers.forEach(b => b.push(item.value));
129+
return divIterator.Item(buffer.shift());
130+
}
131+
), false);
132+
}
133+
134+
// NOTE: Using this will give you unclonable iterators. Only use this
135+
// if you can't or don't want to make your iterator clonable
136+
fromNative(kind, itern, extra = function*(x) {return x}) {
137+
if(typeof itern[Symbol.iterator] !== 'function') throw `${kind} is not a native iterator.`
138+
if(typeof kind !== 'string' && typeof kind?.kind !== 'string' || !(kind?.args instanceof Array))
139+
kind = 'Native'
140+
return new IteratorType(kind, {}, () => extra(itern.next()), false)
141+
}
112142
}
113143

114144
const divIterator = {
@@ -134,7 +164,7 @@
134164
Iterables: {
135165
range(start, end) {
136166
const advance = n => n + (start < end ? 1 : -1);
137-
return new IteratorType("Range",
167+
return new IteratorType({kind: "Range", args: [start, end]},
138168
{curr: start}, function*(state){
139169
const {curr} = state;
140170
if(curr == advance(end)) return divIterator.Done()
@@ -177,7 +207,7 @@
177207
if(item.done) return item
178208
const mapped = yield* map(item.value, thread, target, runtime, stage);
179209
return divIterator.Item(mapped)
180-
})
210+
}, iter.clonable)
181211
},
182212
keep(iter, pred) {
183213
iter = IteratorType.toIterator(iter)
@@ -190,7 +220,7 @@
190220
bool = yield* pred(item.value, thread, target, runtime, stage);
191221
if(bool) return item
192222
}
193-
})
223+
}, iter.clonable)
194224
},
195225

196226
enum(iter) {
@@ -200,7 +230,7 @@
200230
const item = yield* state.iter.next(thread, target, runtime, stage);
201231
if(item.done) return item
202232
return divIterator.Item(new jwArray.Type([state.num++, item.value]))
203-
})
233+
}, iter.clonable)
204234
},
205235
cycle(iter) {
206236
iter = IteratorType.toIterator(iter)
@@ -214,7 +244,7 @@
214244
}
215245
state.buffer.push(item)
216246
return item;
217-
})
247+
}, iter.clonable)
218248
},
219249

220250
take(iter, count) {
@@ -226,7 +256,7 @@
226256
if(item.done) return item
227257
state.count--;
228258
return item;
229-
})
259+
}, iter.clonable)
230260
},
231261
skip(iter, count) {
232262
iter = IteratorType.toIterator(iter)
@@ -238,7 +268,7 @@
238268
state.count--;
239269
}
240270
return yield* state.iter.next(thread, target, runtime, stage)
241-
})
271+
}, iter.clonable)
242272
},
243273
stepBy(iter, step) {
244274
iter = IteratorType.toIterator(iter)
@@ -253,7 +283,7 @@
253283
if(item.done) return item
254284
}
255285
return yield* state.iter.next(thread, target, runtime, stage)
256-
})
286+
}, iter.clonable)
257287
},
258288

259289
chain(iter1, iter2) {
@@ -264,7 +294,7 @@
264294
const item1 = yield* state.iter1.next(thread, target, runtime, stage);
265295
if(!item1.done) return item1
266296
return yield* state.iter2.next(thread, target, runtime, stage)
267-
})
297+
}, iter1.clonable && iter2.clonable)
268298
},
269299
zip(iter1, iter2) {
270300
iter1 = IteratorType.toIterator(iter1)
@@ -276,7 +306,7 @@
276306
const item2 = yield* state.iter2.next(thread, target, runtime, stage);
277307
if(item2.done) return item2
278308
return divIterator.Item(new jwArray.Type([item1.value, item2.value]))
279-
})
309+
}, iter1.clonable && iter2.clonable)
280310
},
281311
cross(iter1, iter2) {
282312
iter1 = IteratorType.toIterator(iter1)
@@ -301,7 +331,7 @@
301331
}
302332
state.buffer.push(item1.value)
303333
return divIterator.Item(new jwArray.Type([item1.value, state.item2]));
304-
})
334+
}, iter1.clonable && iter2.clonable)
305335
},
306336

307337
inspect(iter, inspect) {
@@ -313,7 +343,7 @@
313343
if(item.done) return item
314344
yield* inspect(item.value, thread, target, runtime, stage);
315345
return item
316-
})
346+
}, iter.clonable)
317347
},
318348
},
319349
Terminators: {
@@ -533,6 +563,7 @@
533563
ITER: divIterator.Argument
534564
}
535565
},
566+
'---',
536567
{
537568
opcode: 'iterClone',
538569
text: 'clone [ITER]',
@@ -541,6 +572,25 @@
541572
},
542573
...divIterator.Block
543574
},
575+
{
576+
opcode: 'iterClonable',
577+
text: '[ITER] is clonable?',
578+
disableMonitor: true,
579+
blockType: BlockType.BOOLEAN,
580+
allowDropAnywhere: true,
581+
arguments: {
582+
ITER: divIterator.Argument
583+
}
584+
},
585+
{
586+
opcode: 'iterBranch',
587+
text: 'branch [ITER] into [NUM] branches',
588+
arguments: {
589+
ITER: divIterator.Argument,
590+
NUM: {type: ArgumentType.NUMBER, defaultValue: 2}
591+
},
592+
...jwArray.Block
593+
},
544594
'---',
545595
{
546596
opcode: 'iterTermForEach',
@@ -1044,7 +1094,7 @@
10441094

10451095
iterBuilder(node, compiler, imports) {
10461096
const state = compiler.descendInput(node.STATE).asUnknown();
1047-
const next = descendSubstack(compiler, node.NEXT, new imports.Frame(false, "_divIterBuilder", true))
1097+
const next = descendSubstack(compiler, node.NEXT, new imports.Frame(false, "_divIterBuilder"))
10481098
+`\nreturn vm.divIterator.Item("");\n`
10491099
return new imports.TypedInput(
10501100
/*js*/`vm.divIterator.Iterables.iterBuilder(\n`
@@ -1173,6 +1223,12 @@
11731223
iterClone({ITER}) {
11741224
return IteratorType.toIterator(ITER).clone()
11751225
}
1226+
iterClonable({ITER}) {
1227+
return IteratorType.toIterator(ITER).clonable
1228+
}
1229+
iterBranch({ITER, NUM}) {
1230+
return new jwArray.Type(IteratorType.toIterator(ITER).branch(NUM))
1231+
}
11761232

11771233
iterTermForEach() {
11781234
return "noop"

0 commit comments

Comments
 (0)