@@ -374,6 +374,41 @@ block gen_reduce(const char* varname, block source, block init, block body) {
374
374
gen_op_bound (LOADVN , res_var ));
375
375
}
376
376
377
+ block gen_foreach (const char * varname , block source , block init , block update , block extract ) {
378
+ block output = gen_op_targetlater (JUMP );
379
+ block state_var = gen_op_var_fresh (STOREV , "foreach" );
380
+ block loop = BLOCK (gen_op_simple (DUP ),
381
+ // get a value from the source expression:
382
+ source ,
383
+ // bind the $varname to that value for all the code in
384
+ // this block_bind() to see:
385
+ block_bind (gen_op_unbound (STOREV , varname ),
386
+ // load the loop state variable
387
+ BLOCK (gen_op_bound (LOADVN , state_var ),
388
+ // generate updated state
389
+ update ,
390
+ // save the updated state for value extraction
391
+ gen_op_simple (DUP ),
392
+ // save new state
393
+ gen_op_bound (STOREV , state_var ),
394
+ // extract an output...
395
+ extract ,
396
+ // ...and output it
397
+ output ),
398
+ OP_HAS_VARIABLE ));
399
+ block foreach = BLOCK (gen_op_simple (DUP ),
400
+ init ,
401
+ state_var ,
402
+ gen_op_target (FORK , loop ),
403
+ loop ,
404
+ // At this point `foreach`'s input will be on
405
+ // top of the stack, and we don't want to output
406
+ // it, so we backtrack.
407
+ gen_op_simple (BACKTRACK ));
408
+ inst_set_target (output , foreach );
409
+ return foreach ;
410
+ }
411
+
377
412
block gen_definedor (block a , block b ) {
378
413
// var found := false
379
414
block found_var = gen_op_var_fresh (STOREV , "found" );
0 commit comments