f_do = {
const skipMarker = Symbol.for('SKIP');
const f_do = async (world, form) => {
console.log('DO');
const oldform = symbolp(car(form));
const once = cadr(form) === null;
const [nspecl, ntestl, ...nbody] = [...iter(form)];
const [ovar, oinit, ostep, otest, ...obody] = [...iter(form)];
const specs = oldform ? [list(ovar, oinit, ostep)] : [...nspecl];
const vars = specs.map(car);
const inits = await evalList(world, specs.map(cadr));
const steps = specs.map(s => (cddr(s) ? car(cddr(s)) : skipMarker));
const [ntest, ...nexitforms] = oldform ? [] : [...ntestl];
const test = once ? LSymbol.T : oldform ? otest : ntest;
const exitforms = oldform ? null : nexitforms;
const body = oldform ? obody : nbody;
const frame = new ApplyFrame(LSymbol.DO, null);
const do_do = async () => {
frame.applyBindings(vars, inits);
while (true) {
if (await world.eval(test)) {
return world.prognBody(exitforms || null);
}
await world.prognBody(body);
let i = 0;
const nvals = [];
for (const nvar of vars) {
const step = steps[i++];
if (step !== skipMarker) {
const nval = await world.eval(step);
if (nvar) {
nvals.push(nval);
}
}
}
frame.applyBindings(vars, nvals);
}
};
return world.withFrame(frame, do_do);
};
return f_do;
}