i will do something similar to your second suggestion
procedure foreach();
var
i, e: integer;
s, code: string;
begin
e:=pars.count-2; // 3 parameters minimum (the check is outside)
code:=macroDequote(par(pars.count-1));
with TfastStringAppend.create do
try
for i:=1 to e do
begin
setVar(p, par(i));
s:=code;
applyMacrosAndSymbols(s, cbMacros, cbData);
append(s);
end;
result:=reset();
finally free end;
end; // foreach
procedure for_();
var
b, e, i, d: integer;
s, code: string;
begin
try
b:=strToInt(par(1));
e:=strToInt(par(2));
try
d:=strToInt(par(3));
code:=par(4);
except
d:=1;
code:=par(3);
end;
if d = 0 then exit;
if (e < b) and (d > 0) then d:=-d; // we care
code:=macroDequote(code);
with TfastStringAppend.create do
try
for i:=1 to (e-b) div d+1 do
begin
setVar(p, intToStr(b));
s:=code;
applyMacrosAndSymbols(s, cbMacros, cbData);
append(s);
inc(b, d);
end;
result:=reset();
finally free end;
except end;
end; // for_
ready for #286