This is the playground link:
example
@val external setTimeout: ((.unit) => unit, int) => int = "setTimeout"
let sleep = (time: int) => {
  Js.Promise.make((~resolve, ~reject) => {
    let _ = setTimeout((.) => {
      resolve(. ignore())
    }, time)
  })
}
let rec play = (index: int) => {
  Js.Promise.then_(_ => {
    play(index + 1)
  }, sleep(1000)) 
}
let rec normalRec = (index: int) => {
  Js.log2(`call with index: `, index)
  normalRec(index + 1)
}
// Generated by ReScript, PLEASE EDIT WITH CARE
'use strict';
function sleep(time) {
  return new Promise((function (resolve, reject) {
                setTimeout((function () {
                        return resolve(undefined);
                      }), time);
                
              }));
}
function play(index) {
  return sleep(1000).then(function (param) {
              return play(index + 1 | 0);
            });
}
function normalRec(_index) {
  while(true) {
    var index = _index;
    console.log("call with index: ", index);
    _index = index + 1 | 0;
    continue ;
  };
}
exports.sleep = sleep;
exports.play = play;
exports.normalRec = normalRec;
/* No side effect */
The recruise function play is not compiled into while loop, this may leads to some memory leak, is that can be comiled into while loop?