A function or method in a high-level language can either be recursive or non-recursive.
A recursive function calls itself (directly or indirectly). E.g.
def fact(n):
if n == 1:
return 1
else:
return n * fact(n-1)
A non-recursive function does not call itself. E.g.
def fact(n):
factn = 1
for i in range(1,n+1):
factn *= i
return factn
The code for every function should be in one chunk, cleanly separated from the rest of the program. It should have only one entry point, but can have multiple exit points.
A function may call (or invoke) another function. The function that makes the call is the caller and the function that gets called is the callee.
The caller and callee communicate via a protocol.
A nonrecursive function call in python like
f(a, b)
gets translated into
li a <avalue>
li b <bvalue>
li cont afterCall
j f
afterCallL:
A recursive function needs to go through the same rigmarole that a non-recursive function does, and then more.
An extra thing that a recursive caller has to do is that before invoking a recursive callee, the caller must save all the registers that it is using and may be clobbered by the callee in some safe place (i.e., data memory). Also, after returning from the callee, the caller must load back all the values that it has saved prior to invoking the callee.
In this stack discipline the caller is responsible for saving and retrieving relevant registers. It is also possible that the callee is responsible for this work. In a real system, some registers are designated as caller-saved while others are callee-saved.
A recursive function call in python like
prest
recurse(n)
postst
gets translated into
prest
li n <nvalue>
li cont afterCall
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; statements to save working registers go here
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
j recurse
afterCallL:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; statements to retrieve working registers go here
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
postst