Author Topic: [dev build] Fixing an old bug regarding recursion in QB64 - Testers wanted!  (Read 39227 times)

0 Members and 1 Guest are viewing this topic.

FellippeHeitor

  • Guest

New development build available. Testers wanted.

As seen on https://www.qb64.org/forum/index.php?topic=704.msg5775#msg5775

So up until v1.5 QB64 contained a bug that wouldn't allow recursion involving a function without parameters. This was incompatible with our mother ship, QuickBASIC 4.5, and in the upcoming v1.6 we will have that behavior fixed.

Drawing from the post I linked above, the code...

Code: QB64: [Select]
  1. X = 5
  2.  
  3.     IF X = 0 THEN
  4.         F = 1
  5.     ELSE
  6.         PRINT "*"
  7.         X = X - 1
  8.         F = F
  9.     END IF
  10.  

...will now properly print 5 stars and the number 1 before it ends, because the assignment line F = F will properly call Function F, as one would expect.

This means you shouldn't work with the return variable of a function as a regular variable. The best practice/approach is to have a temporary variable in case you need to build the return value as the function is processed, and only in the end of the procedure do the functionName = returnValue assignment.

Let me know how the new dev build will deal with your existing code, while keeping the above observations in mind.

And thank you for flying QB64.
✈️

Offline RhoSigma

  • QB64 Developer
  • Forum Resident
  • Posts: 565
    • View Profile
This means you shouldn't work with the return variable of a function as a regular variable. The best practice/approach is to have a temporary variable in case you need to build the return value as the function is processed, and only in the end of the procedure do the functionName = returnValue assignment.

Well done Fellippe, although the above quoted condition will definitly give me some headaches and need to refactoring my GuiTools in some places.

Very good you pointed that out...
My Projects:   https://qb64forum.alephc.xyz/index.php?topic=809
GuiTools - A graphic UI framework (can do multiple UI forms/windows in one program)
Libraries - ImageProcess, StringBuffers (virt. files), MD5/SHA2-Hash, LZW etc.
Bonus - Blankers, QB64/Notepad++ setup pack

Offline RhoSigma

  • QB64 Developer
  • Forum Resident
  • Posts: 565
    • View Profile
Well, to clarify that condition somewhat better:
  • you can assign return values to the function name (ie. the function name is on the left side of the equal sign (=)) as often as you want and in any place within the function, eg. assigning different values from within different cases of a SELECT CASE block
  • however, if the function name appears in any arbitrary term/formula on the right side of the equal sign (=), then it will in fact be a recursive call of the function, and hence the result of that function call is injected into the term/formula, rather than any value assigned to the function name anywhere earlier within the function
  • if doing the latter, be aware that your function gets recursive calls and hence must define any suitable end condition to avoid stack overflow crashes
Is that so far correct @FellippeHeitor, or are there other points to be aware of?
My Projects:   https://qb64forum.alephc.xyz/index.php?topic=809
GuiTools - A graphic UI framework (can do multiple UI forms/windows in one program)
Libraries - ImageProcess, StringBuffers (virt. files), MD5/SHA2-Hash, LZW etc.
Bonus - Blankers, QB64/Notepad++ setup pack

Offline RhoSigma

  • QB64 Developer
  • Forum Resident
  • Posts: 565
    • View Profile
One more:

The last two points in the list of my previous post are not only valid for the function name used on the right side of the equal sign (=), but also if used as argument in other statements/function calls.
My Projects:   https://qb64forum.alephc.xyz/index.php?topic=809
GuiTools - A graphic UI framework (can do multiple UI forms/windows in one program)
Libraries - ImageProcess, StringBuffers (virt. files), MD5/SHA2-Hash, LZW etc.
Bonus - Blankers, QB64/Notepad++ setup pack

FellippeHeitor

  • Guest
Spot on, Rho.

Offline RhoSigma

  • QB64 Developer
  • Forum Resident
  • Posts: 565
    • View Profile
Spot on, Rho.

Well, then refactoring can begin,
guess this change has the potential to be a cuckoo egg in many different projects of many different people ;-)
My Projects:   https://qb64forum.alephc.xyz/index.php?topic=809
GuiTools - A graphic UI framework (can do multiple UI forms/windows in one program)
Libraries - ImageProcess, StringBuffers (virt. files), MD5/SHA2-Hash, LZW etc.
Bonus - Blankers, QB64/Notepad++ setup pack

FellippeHeitor

  • Guest
Exactly due to being a breaking change, we’re internally coming to final terms on bringing the version bump to 2.0.

FellippeHeitor

  • Guest
Btw, are you not on Discord for moral issues or are you just not a chat room guy? Your input in the dev lounge is always very welcome and appreciated.

Offline RhoSigma

  • QB64 Developer
  • Forum Resident
  • Posts: 565
    • View Profile
Exactly due to being a breaking change, we’re internally coming to final terms on bringing the version bump to 2.0.
I hope you made sure, that this change doesn't bite your own butt within QB64.bas and all the other basic source files involved, would be too bad, if QB64 breaks itself by enforcing the new behaviour.

At least for my GuiTools the impact is much higher than expected first, as things like assigning a result value through an intended argument side effect of a SUB call won't work anymore.

eg:
SetTag ButtonC$, "ERROR", classID$ + "::" + methodID$ + " -> missing required tags"

that's a typical line in GuiTools, ButtonC$ is the actual function name, and the final error tag assembled by the SetTag SUB was then returned in ButtonC$ as side effect, but now ButtonC$ would call the Button class instead.

I've to find a new elegant method now to do this in a similar way, as simply each time using a temp variable in the SetTag call and afterwards assigning that to the class its function name seems much to plumsy for me.

Btw, are you not on Discord for moral issues or are you just not a chat room guy? Your input in the dev lounge is always very welcome and appreciated.

Not a chat room guy, also with nursing my sick old mom (87y) no time to engage in (almost) real time discussions.
My Projects:   https://qb64forum.alephc.xyz/index.php?topic=809
GuiTools - A graphic UI framework (can do multiple UI forms/windows in one program)
Libraries - ImageProcess, StringBuffers (virt. files), MD5/SHA2-Hash, LZW etc.
Bonus - Blankers, QB64/Notepad++ setup pack

FellippeHeitor

  • Guest
Quote
I hope you made sure, that this change doesn't bite your own butt within QB64.bas and all the other basic source files involved, would be too bad, if QB64 breaks itself by enforcing the new behaviour.

So far so good with qb64 and several of my personal projects.

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
I’m running into the same issues with a lot of my stuff, particularly with regards to direct assignment issues.

FUNCTION foo$ (filehandle, line)
   SEEK #filehandle, 1
   FOR I = 1 TO line
      IF EOF(filehandle) THEN foo$ = “ERROR, PAST END OF FILE”: EXIT FUNCTION
      LINE INPUT #filehandle, foo$
   NEXT
END FUNCTION

Gets, puts, inputs, prints…. I have a ton of these which just referenced the function name as a variable name, which are going to need alterations.

I imagine we’re going to see a slew of reports about libraries erroring out with the next version update, and the librarians will need to check the code in the forum’s library area to test and make certain everything there works as advertised in the future. (The “Samples Gallery & Reference area now.)
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline Ryster

  • Newbie
  • Posts: 77
    • View Profile
Hello
What's the problem?.
For me it displays as a result of compilation: 5 stars and 1

Offline jack

  • Seasoned Forum Regular
  • Posts: 408
    • View Profile
will recursion still work?
Code: QB64: [Select]
  1. Print Factorial_Recursive&&(5)
  2.  
  3. Function Factorial_Recursive&& (n As Integer)
  4.     If n = 0 Then Factorial_Recursive&& = 1: Exit Function
  5.     Factorial_Recursive&& = n * Factorial_Recursive&&(n - 1)
  6.  

Offline RhoSigma

  • QB64 Developer
  • Forum Resident
  • Posts: 565
    • View Profile
I imagine we’re going to see a slew of reports about libraries erroring out with the next version update, and the librarians will need to check the code in the forum’s library area to test and make certain everything there works as advertised in the future. (The “Samples Gallery & Reference area now.)

Of course, somebody could argue, that the required amount of work needed to make existing code compliant to the changed behavior, just for the rare case that argumentless functions can be correctly called recursivly, is not worth the whole thing. In fact, this was my first thought too, but nevertheless I'm fully behind this change, as it's the logical behavior as you also find it in C/C++, Javascript, Perl etc., so let's do the changes now, before it gets even more painful.
My Projects:   https://qb64forum.alephc.xyz/index.php?topic=809
GuiTools - A graphic UI framework (can do multiple UI forms/windows in one program)
Libraries - ImageProcess, StringBuffers (virt. files), MD5/SHA2-Hash, LZW etc.
Bonus - Blankers, QB64/Notepad++ setup pack

Offline Ryster

  • Newbie
  • Posts: 77
    • View Profile

Is that a question for me?
If so, it displays the result 120 after compilation
« Last Edit: September 25, 2021, 01:46:58 pm by Ryster »