BBC BASIC for Windows
Programming >> BBC BASIC language >> Curious Code
http://bb4w.conforums.com/index.cgi?board=language&action=display&num=1397859327

Curious Code
Post by Andy Parkes on Apr 18th, 2014, 10:15pm

Hi folks,

A few days ago I spent a bit of time searching for a bug in a program. I found the bug, but I'm not sure exactly what is going on. The code below demonstrates the bug I created:

Code:
      PRINT "Test 1 - The following output is as intended:"
      PROC_test1
      PRINT "Press ANY KEY to see output from Test 2"
      K% = GET
      PROC_test2
      END

      DEF PROC_test1
      LOCAL I%, J%
      I% = 10
      WHILE I%
        J% = FN_getValue(I%)
        PROC_print(J%)
      ENDWHILE
      ENDPROC

      DEF PROC_test2
      LOCAL I%
      I% = 10
      WHILE I%
        PROC_print(FN_getValue(I%))
      ENDWHILE
      ENDPROC

      DEF PROC_print(I%)
      PRINT I%
      ENDPROC

      DEF FN_getValue(RETURN P%)
      LOCAL I%
      I% = P% * 2
      P% -= 1
      =I%
 


In this example, PROC_print() and FN_getValue() are analogous to routines that were INSTALLed from a library, and so my main program did not 'know' their implementation. I would have expected PROC_test2 to function exactly the same as PROC_test1. What do I need to understand to be able to foresee situations like this again?

Thanks very much

Andy
Re: Curious Code
Post by rtr on Apr 19th, 2014, 1:47pm

on Apr 18th, 2014, 10:15pm, Andy Parkes wrote:
I would have expected PROC_test2 to function exactly the same as PROC_test1.

Here are the salient statements:

Code:
      PROC_print(FN_getValue(I%))
...
      DEF PROC_print(I%) 

I% is a 'returned' parameter to FN_getValue(), so it may be modified on return from a call to that function. However I% is also a 'formal' parameter of PROC_print(), so it is saved on entry to that procedure and restored on exit.

Therefore although I% is indeed modified on return from FN_getValue(), you never see that new value because on return from PROC_print() I% (which was stored on the stack) is restored to the value it had initially.

This behaviour, whilst undesirable, is inevitable in an interpreted language which has neither true 'local' variables nor true 'passed by reference' parameters, in the sense that compiled languages do.

To avoid this situation occurring, if you define a function which has one or more RETURNed parameters you should never use that function itself as a parameter of another function or procedure.

Richard.
Re: Curious Code
Post by Andy Parkes on Apr 19th, 2014, 7:42pm

Thanks very much Richard, that`s very clear, and an easy rule to understand and adopt.

Regards

Andy