gren-lang / compiler

Compiler for the Gren programming language
https://gren-lang.org
Other
379 stars 23 forks source link

Compiler enforced tail calls #223

Open robinheghan opened 1 year ago

robinheghan commented 1 year ago

Gren will correctly optimize tail-recursive functions to avoid the possibility of stack overflow exceptions.

countDown : Int -> Int
countDown value =
  if value < 1 then 
    0
  else
    countDown (value - 1)

In the example above, countDown is recognized by the compiler as tail-recursive, and will be compiled into a while loop that doesn't consume stack space. However, if you were to somehow get this wrong then you'd get no warning from the compiler that your function isn't stack safe. For beginners, it's also not always apparent what is and isn't stack safe.

This proposal introduces the recur keyword, which is a hint to the compiler that the function is meant to be stack safe in the face of recursion. The compiler can then check, and potentially fail, if that doesn't turn out to be the case.

countDown : Int -> Int
countDown value =
  if value < 1 then
    0
  else
    recur (value - 1)

The recur keyword can also work in the face of optimizations such as tail recursion modulo cons, which makes it a bit harder to understand all the potential cases where recursion is stack safe.