Hey Robert, looks like you get to learn about private stacks and recursion reduction . Basically you have to remove the recursion from your function completely and implement your own stack. Arrays work nice and allow for more flexibility. If you want to work on REALLY LARGE hunks of data then its time to look at the hard drive and streams to implement your process stack.

Its not too bad to implement a very basic private stack. Here is a simple example:
Recursive:[pascal]procedure DoSomething(HowManyTimes : Integer);
begin
while HowManyTimes > 0 do
begin
WriteLn(HowManyTimes);
dec(HowManyTimes);
DoSomething(HowManyTimes);
end;
end;[/pascal]

Now, revised with a private stack:[pascal]procedure DoSomething2(HowManyTimes : Integer);
const
AllocBy = 10;
var
myStack : Array of Integer;
dispVal, i,
stackSize : Integer;
procedure Push(AVal : Integer);
begin
if stackSize+1>length(myStack) then
SetLength(myStack, stackSize + AllocBy);
myStack[stackSize] := AVal;
inc(stackSize);
end;
function Pop : Integer;
begin
if stackSize > 0 then
result := myStack[stackSize-1]
else
begin
Writeln('Stack underflow');
Halt(255);
end;
dec(stackSize);
end;
begin
stackSize := 0;
for i := 1 to HowManyTimes do
Push(i);
while stackSize > 0 do
begin
dispVal := Pop;
Writeln(dispVal);
for i := 1 to dispVal-1 do
Push(i);
end;
end;[/pascal]

Basically I've taken the original code and unwrapped it a bit. First pushing our starting values onto the stack. Then while the stack isn't empty processing the last item on the stack. This coincidently may add new items to the end of the stack. And away we go

This type of private stack processing works very well in things like flood fill and mathematics as it can be done in a local variable (as shown above) or it can be done on the disk itself and using jumps to move/size the stack.

Anyways, hope it helps. In case your curious, here is a version that uses a file stream to perform the exact same thing as above:[pascal]procedure DoSomething(HowManyTimes : Integer);
var
myStack : TFileStream;
dispVal, i: Integer;
stackSize : Integer;
procedure Push(AVal : Integer);
begin
myStack.Seek((stackSize)*sizeof(AVal), soBeginning);
myStack.Write(AVal, sizeof(AVal));
inc(stackSize);
end;
function Pop : Integer;
begin
result := 0;
if stackSize > 0 then
begin
myStack.Seek((stackSize-1)*sizeof(result), soBeginning);
myStack.Read(result, sizeof(result));
end
else
begin
Writeln('Stack underflow');
Halt(255);
end;
dec(stackSize);
end;
begin
stackSize := 0;
myStack := TFileStream.Create('temp.stack', fmCreate);
try
for i := 1 to HowManyTimes do
Push(i);
while stackSize > 0 do
begin
dispVal := Pop;
Writeln(dispVal);
for i := 1 to dispVal-1 do
Push(i);
end;
finally
myStack.Free;
end;
if fileExists('temp.stack') then
DeleteFile('temp.stack');
end;[/pascal]

Granted that the last one is slower due to disk access, but it can process ANY size of number as long as you have the disk space for the stack

Finally, yes there are optimizations that could be put in place, but I left that for you to figure out