Subroutine return type -- how to determine?

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

Subroutine return type -- how to determine?

sakumar
In Chapter 11, Pg 235 the text book says that if a called subroutine returns void, then the caller "must pop (and ignore) the returned value".

However, the symbol table does not keep any information about subroutines (should it?).

Also, the subroutine could be in another file, so how does the compiler determine the return type of the subroutine?
Reply | Threaded
Open this post in threaded view
|

Re: Subroutine return type -- how to determine?

cadet1620
Administrator
The symbol table does not need to hold the return type, although it could be useful for error checking.

Jack is an untyped language; it is the programmer's responsibility to use the return value from a function correctly. ALL functions return a one word result, including void functions. When a function returns to its caller, there will be a word on the stack that must be used or discarded.

--Mark
Reply | Threaded
Open this post in threaded view
|

Re: Subroutine return type -- how to determine?

sakumar
Thanks for the tip, Mark.

On going through the grammar again, I see that <subroutineCall> can occur in two places -- one as part of a do statement and another as part of a <term>. In the former case the return value should be discarded (popped); it should remain on the stack if the subroutine call is part of a <term> since the term's operation will pop it.

Further to your point about error checking, it is assumed that the type and number of arguments to a subroutine should match between calls and definition because the compiler specs don't call out that that check should be made. Of course, one of the enhancements could be to add a semantic analysis module to the compiler.
Reply | Threaded
Open this post in threaded view
|

Re: Subroutine return type -- how to determine?

cadet1620
Administrator
sakumar wrote
On going through the grammar again, I see that <subroutineCall> can occur in two places -- one as part of a do statement and another as part of a <term>. In the former case the return value should be discarded (popped); it should remain on the stack if the subroutine call is part of a <term> since the term's operation will pop it.
That is correct. Conversely, if you mistakenly call a void function in an expression, the 0 that it returns is on the stack and will be used in the continued computation. Although the result of the expression will be incorrect, the stack will not be skewed so the program will not crash when the current function returns. (Think about what would happen if the SP was off by one when the function popped the RIP and jumped to the value it got.)
Further to your point about error checking, it is assumed that the type and number of arguments to a subroutine should match between calls and definition because the compiler specs don't call out that that check should be made. Of course, one of the enhancements could be to add a semantic analysis module to the compiler.
In fact, the supplied compiler does some semantic analysis. Although I use my compiler since it generates better code, I usually also run my programs through the supplied compiler since it often finds argument and function/method mismatches mine misses.

Good error handling is a lot of work, and is often under budgeted in project schedules and is not considered early enough in design. It can be quite troublesome to add it late in the project. On my current work project, we're about 90% through the development and are just discovering the remaining 90% of the work, mostly related to error handling.... (Search the web for 90-90 rule.)

--Mark