let unique =
let n = ref 0 in
fun () -> incr n; "__pa_forstep" ^ string_of_int !n
let forloop _loc var first df last e =
<:expr< for $var$ = $first$ $to:df$ $last$ do { $e$ } >>
let expand _loc var first df last step e =
match step with
None -> forloop _loc var first df last e
| Some <:expr< 1 >> when df -> forloop _loc var first true last e
| Some <:expr< -1 >> when not df -> forloop _loc var first false last e
| Some step ->
let counter = unique () in
let lastid = unique () in
let stepid = unique () in
let cmp =
if df then "<="
else ">=" in
<:expr<
let $lid:counter$ = ref ($first$ : int) in
let $lid:lastid$ = $last$ in
let $lid:stepid$ = $step$ in
while $lid:cmp$ $lid:counter$.val $lid:lastid$ do
{ let $lid:var$ = $lid:counter$.val in $e$;
$lid:counter$.val := $lid:counter$.val + $lid:stepid$ } >>
EXTEND
GLOBAL: Pcaml.expr;
Pcaml.expr: LEVEL "expr1" [
[ "for"; var = LIDENT; "="; first = SELF;
df = direction_flag; last = SELF;
step = OPT [ "step"; step = Pcaml.expr -> step ];
"do"; e = SELF; "done" ->
expand _loc var first df last step e ]
];
direction_flag: [
[ "to" -> true
| "downto" -> false ]
];
END