How to know if you are calling a void function?

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

How to know if you are calling a void function?

peterxu422
I'm trying to figure out how to determine if I've just made a call to a void function at compile time. Any tips?
Reply | Threaded
Open this post in threaded view
|

Re: How to know if you are calling a void function?

peterxu422
In answering my own question, I believe that it can't be done. The reason I asked was to determine when to write the instruction 'pop temp 0' to ignore the void return value.

The conclusion I am coming to is that you handle this by only having the 'do' statements write 'pop temp 0' after making any subroutine call. The exception is Memory.alloc() which must pop to pointer 0 in the constructor. (I'm guessing outside of the constructor, if you use 'do Memory.alloc()' it will pop to temp 0 as well, but this command would be pretty useless because then you're throwing away the pointer to your block of memory).

And for 'let' statements, you would pop it to the variable that you are setting the right side to. But what about cases where you have 'let x = Xxx.yyy()' where Xxx.yyy() is a void subroutine? Should there ever be such a command like this? Because if it were allowed, wouldn't that mess up what's on the stack because you have an extra 0 on it the void return is pushed?

Would appreciate any feedback.
Reply | Threaded
Open this post in threaded view
|

Re: How to know if you are calling a void function?

cadet1620
Administrator
Subroutines always return with a value pushed on the stack, either the return value or 0 if the return type is void.

This means that do statements always pop the stack, regardless of the return type of the subroutine being called.

There is no "do Memory.alloc" call in constructor source code so you don't need to special case it. Memory.alloc is called as part of the subroutine entry VM code generated for the constructor.
    // let this = Memory.alloc(object-size)
    push object-size
    call Memory.alloc 1
    pop pointer 0
instead of the method entry code
    // let this = argument_0
    push argument 0
    pop pointer 0

In the case of "let x = voidFunction()" the 0 that the void function pushed instead of a return value is on the top of the stack so it gets popped into "x" just like the the return value from any other function.

This is the reason that void subroutines push 0 before returning -- this allows all subroutines to be treated the same way, regardless of return type, from the caller's perspective.
 
--Mark