Remix.run Logo
AndyKelley 3 days ago

All Zig code is in one compilation unit, so the compiler has access to the entire function call graph. Cycles in the graph (recursion) cause an error. To break cycles in the graph, one must use a language builtin to call a function using a different stack (probably obtained via heap allocation).

dev-ns8 3 days ago | parent | next [-]

Does this mean it's impossible in Zig to do strictly Stack related recursion and just by the mere inclusion of a recursive function your implicitly getting heap allocations alongside?

AndyKelley 3 days ago | parent [-]

You can put a big buffer on the stack, and use this buffer to break your cycles. At some point you'll run out of this buffer and be forced to handle failure, rather than triggering a stack overflow segfault.

So it will be the same thing but with more (error handling) steps.

This annoyance can be avoided by avoiding recursion. Where recursion is useful, it can be done, you just have to handle failure properly, and then you'll have safety against stack overflow.

CJefferson 3 days ago | parent | next [-]

Wait, so how do I write mutually recursive functions, say for a parser? Do I have to manually do the recursion myself, and stick everything in one big uber-function?

eru 3 days ago | parent | prev [-]

Does Zig offer (guaranteed) tail call optimisation?

> Where recursion is useful, [...]

Recursion is so useful, most imperative languages even have special syntax constructs very specific special cases of recursion they call 'loops'.

messe 3 days ago | parent [-]

> Does Zig offer (guaranteed) tail call optimisation?

Yes[1]. You can use the @call builtin with the .always_tail modifier.

    @call(.always_tail, foo, { arg1, arg2, ... });
[1]: https://ziglang.org/documentation/master/#call
ants_everywhere 3 days ago | parent | prev | next [-]

> All Zig code is in one compilation unit

How do incremental compilation and distributed compilation work?

pyrolistical 3 days ago | parent | next [-]

Subtrees should be cacheable and parallelizable?

wavemode 3 days ago | parent | prev [-]

Single compilation unit does not imply that the results of the compilation of the different parts of that unit cannot be cached.

ants_everywhere 3 days ago | parent [-]

I see. So in some sense the actual unit of compilation is smaller and units can be combined or "linked" even if compiled at different times on different machines?

atmikemikeb 3 days ago | parent | prev [-]

what about extern functions?

AndyKelley 3 days ago | parent [-]

Zig's linker will calculate this information automatically in most cases when statically linking (via analysis of machine code disassembly). Otherwise, there is a default upper bound stack value, overridable via user annotation.