-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
explicit tail call syntax #694
Comments
This reminds me of clojure's I am curious about how the compiler currently handles tail calls in code like: fn r(x:u8) -> u8 {
if (x < 10) {
return r(x + 1);
} else {
return x;
}
} This is afaict never going to need any more than one stack frame. Would it currently use more than one? Is it possible / desirable to have the compiler identify tail call optimizable functions implicitly and what would / does that look like on the backend? Is the |
I am not sure about the proposed syntax. Instead of it having function wrapper syntax (complex), a simple In order to make use of tail calls, as in the |
This is actually implemented already in the form of @call. However this issue is still open because the detection of when to emit a compile error is not implemented yet. I do not plan to add any additional syntax or builtins. |
The @call syntax is perfectly fine, but it really needs to work, and it often doesn't now. |
The |
Maybe you can write a function to make it shorter to type, like it was attempted here? Lines 548 to 554 in 225ed65
|
The current explicit syntax is ugly/painful, but if it worked properly, I could certainly deal with it. The biggest problem is that it currently needs the type signatures of the caller and the target functions to match. All that should be required is that the return types match. The workaround is incredibly ugly, sometimes requiring horribly semantically invalid type casts, saving data in crazy places, or inlining code that should be in a function. Automatic detection may be a bit trickier (which may include what to do with error unions and defer). But for explicit use, requiring no outstanding Please, please, please fix the implementation of the explicit case! The availability of explicit tail-calls was one of the features that led me to using Zig. Rust may get this soonish (see: this Reddit comment) - I don't know if that link is relevant. |
As I said, I could live with the current syntax if it worked properly. However, ideally, I would like to see the normal return/call syntax retained. So,
|
Note that the type signatures matching requirement is inherited directly from LLVM: llvm/llvm-project#54964 |
Thanks, @Vexu for the comment... I've added a comment to that thread. |
I'm building a runtime and use tailcall extensively! The problem with debugging and tailcalls is that tracebacks aren't very useful... but I found a trick. I've mildly complained about
and then use that in all of my tailcalls. Then, if I need traceback, I simply define show_error_stack to be true, and all my tailcalls become normal calls and show up in the traceback. I wish I could do something similar for |
What would be very nice would be if |
Sorry to revive a zombie thread.
I'm doing the same for a project of mine. @dvmason do you have any strategy to tail call functions that do not have the same parameters as the caller ? |
Progress
Proposal:
The purpose of
@tailCall()
is to ensure that a tail call happens. If it cannot, the@tailCall()
produces a compile error.Here are some cases where a tail call is impossible:
@tailCall()
expression is not the operand of areturn
operator. e.g.return @tailCall(foo) - 1
.defer
statements that would run after the@tailCall()
. e.g.{defer bar(); return @tailCall(foo);}
.foo
returnsu8
and the caller returns?u8
.See also #157.
The text was updated successfully, but these errors were encountered: