Optimising tail calls

Using, learning, programming and modding the Gigatron and anything related.
Forum rules
Be nice. No drama.
Post Reply
Cwiiis
Posts: 27
Joined: 14 May 2018, 09:04

Optimising tail calls

Post by Cwiiis »

I have a function 'ClearRect' in my program that does what you would expect - to save on bytes, I have a function 'ClearScreen' that sets up variables to clear the screen and then calls ClearRect.

Currently that looks like:

Code: Select all

[def {ClearScreen}
  push
  c=
  $0800 Pos= 40 Width= 120 Height=
  c ClearRect!
pop ret] ClearScreen=
I thought - what's the point in pushing to the stack, then popping and returning if the last op in the function is a call, so I could omit the 'push' and 'pop ret'... But that doesn't work...

Could anyone explain why this doesn't work? And if there is a possible optimisation here? I'd have thought that not pushing would mean that the return from ClearRect would actually return to whatever called ClearScreen, but that doesn't seem to be the case...
User avatar
marcelk
Posts: 488
Joined: 13 May 2018, 08:26

Re: Optimising tail calls

Post by marcelk »

The call to ClearRect places the return address into vLR, and later on 'ret' looks at vLR to know where to go back to. There is no stack at work at all there yet. But you need one once you have more than one level, because otherwise the inner call will clobber the return address of the outer call. So push/pop are then used to save and restore vLR. You do this explicitly.

To make a tail call you have to jump somewhere without changing vLR. I think there is no non-ugly way for that.
Cwiiis
Posts: 27
Joined: 14 May 2018, 09:04

Re: Optimising tail calls

Post by Cwiiis »

Ah, I see - I guess then if you wanted to split up a function across pages, you could push in the first, call the 2nd at the end, then pop ret in the 2nd function (and rely on nothing ever calling the 2nd function alone).
Post Reply