All ch.8 tests pass except FibonacciElement. SOLVED.

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

All ch.8 tests pass except FibonacciElement. SOLVED.

shane
Hi fellow learners. I just spent a very long time finding a very silly issue so I figured I would attempt to document for future learners. I tried googling everything I could think of, emailing, reading, looking at others code, and it came down to something very simple.

Here was my problem:
-SimpleFunction=PASS
-NestedCall=PASS
-FibonacciElement=FAIL
-StaticsTest=PASS

Running my FibonacciElement.asm in the CPU emulator left a strange result with SP higher than the compare file. How could I have a stack skew for this test, but not the others?

Given the length of the resulting asm file from translating FibonacciElement/ I tried breaking down the problem in as many different ways as I could. Was it the writeCall function messing up or my writeInit? I traced out the stack and followed the various pointers according to my write functions.

While studying my code beyond the point of comprehension, my exhaustion finally caused me to take a step back and really try to see what was happening. I realized it must have something to do with the fact that this is the only test that calls a function recursively.

What was different about calling a function from within it's own definition that caused my translator to fail? I thought about this for more time than I am proud of and slowly realized that it really is no different than calling any other function from within the original function. The compiler, or translator, really has no idea that it's jumping to the same function over and over again. It just jumps to any address you program in.

What makes it recursive is the way the programmer uses the VM code. I don't know why I kept looking for something to be different about my code to "handle" recursive function calls in whatever special way they needed to be handled.

Of course my problem ended up being not specific to recursive function calls, but something much simpler that the earlier tests let through the cracks: vm files with multiple of the same function call.

The way my translator created the return address label during a function call used the function name instead of an index (RETURN_functionName) instead of (RETURN_returnCount).

Because FibonacciElement (Main.vm) calls Main.fibonacci twice in the file the Assembler NEEDS to have separate labels for the return addresses created at each function call. Since my translator did not uniquely label these beyond the name of the function, the two labels generated by the function calls were essentially the same to the Assembler.

So basically what was happening is the CPU gets to the second Main.fibonacci call, and actually pushes the return address for the first Main.fibonacci call onto the stack. Now the nonsensical output I was seeing is starting to make sense.

I honestly can't even picture what my CPU emulator was actually doing while running my code before. Hopping in and out and all over Main.vm in some crazy manner I suppose.

So tl;dr after changing my function calls to uniquely index all return address labels, my code passed the FibonacciElement test. Hope this helps somebody!
Reply | Threaded
Open this post in threaded view
|

Re: All ch.8 tests pass except FibonacciElement. SOLVED.

AlexShroyer
I had a nearly identical experience. One thing I still do not understand is that generating return address labels of this form works fine:
retAddr = "return_" + str(globalCounter)
globalCounter += 1  #increment when handling any command
However, generating a name which consists of the function name plus a "call counter" does not work:
retAddr = "return_" + functionName + str(functionCounter)
if handlingCall:
 functionCounter += 1 #increment only if handling a call command