### Author Topic: QB64 does not interpret 0-place recursive function correctly  (Read 1780 times)

0 Members and 1 Guest are viewing this topic.

#### qbguy

• Newbie
• Posts: 12
##### QB64 does not interpret 0-place recursive function correctly
« on: October 15, 2018, 10:26:36 PM »
Code: QB64: [Select]
1. X = 5
2.
3. IF X = 0 THEN F = 1 ELSE PRINT "*": X = X - 1: F = F
4.

Expected behavior: prints five stars, then 1.
Actual behaviour: prints a single star, then a 0.

#### bplus

• Forum Resident
• Posts: 5897
• B+ Knot again!
##### Re: QB64 does not interpret 0-place recursive function correctly
« Reply #1 on: October 15, 2018, 10:41:51 PM »
Looks like F needs a dummy parameter:
Code: QB64: [Select]
1. X = 5
2. PRINT F(100)
3.
4. FUNCTION F (t)
5.     IF X = 0 THEN F = 1 ELSE PRINT "*";: X = X - 1: F = F(2)
6.
7.

#### qbguy

• Newbie
• Posts: 12
##### Re: QB64 does not interpret 0-place recursive function correctly
« Reply #2 on: October 15, 2018, 10:48:54 PM »
I know you can just avoid 0-argument functions but the above code works in QBASIC.

#### bplus

• Forum Resident
• Posts: 5897
• B+ Knot again!
##### Re: QB64 does not interpret 0-place recursive function correctly
« Reply #3 on: October 15, 2018, 11:11:58 PM »
Did QBASIC have the C++ middleman to feed? ;)

#### Petr

• Forum Resident
• Posts: 1536
• The best code is the DNA of the hops.
##### Re: QB64 does not interpret 0-place recursive function correctly
« Reply #4 on: October 16, 2018, 01:25:56 AM »
Code: QB64: [Select]
1.
2. X = 5
3. FOR result = 0 TO 5
4.
5.
6.     IF X = 0 THEN F = 1 ELSE PRINT "*": X = X - 1
7.
8.

The original behavior of the program is logical. The result was requested only once and additionally the function f returns the number, and there was only one pass. Therefore f was correctly zero.
« Last Edit: October 16, 2018, 01:32:55 AM by Petr »

#### SMcNeill

• QB64 Developer
• Forum Resident
• Posts: 3185
##### Re: QB64 does not interpret 0-place recursive function correctly
« Reply #5 on: October 16, 2018, 10:32:53 AM »
It's a known bug that's been around forever, but it's one which doesn't seem to affect many people, so it's always been a low priority issue.  I don't think many people use functions recursively, so most never experience the issue.

I've did a little digging into the problem before, and it seems as if it's a case of QB64 mistaking the name as a variable and not the function.  Under the hood, QB64 translates our code to C, then it compiles.  With the translation, variable names are changed slightly, so as to avoid confusion.

S = 2 may become SINGLE_S, or LONG_S, depending on the default variable type.  Functions are usually called FUNC_name (this is all if my memory isn't failing me again), and the issue is the line basically translates itself to:

FUNC_F = SINGLE_F - 1

When we use a parameter, QB64 correctly identifies the translation as a function, and all works as it should with FUNC_F = FUNC_F(dummyvalue) - 1...

***************

It sounds like a simple enough issue, but it's one that's hard to dig down and find inside QB64 itself.  To be honest, I'm not even 100% certain which part of QB64 does these exemptions/identifications for us...

Everyone needs to remember: Galleon was the one who originally wrote QB64, and all the rest of us are just trying to sort through someone else's long -- undocumented -- spaghetti code, and sometimes, some issues are difficult to track and correct, like this one.  :)
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

#### SMcNeill

• QB64 Developer
• Forum Resident
• Posts: 3185
##### Re: QB64 does not interpret 0-place recursive function correctly
« Reply #6 on: October 16, 2018, 01:10:32 PM »
Taking time to look at the output of the c-file for the original post problem, here's what we end up seeing:

*__SINGLE_X=*__SINGLE_X- 1 ;
*_FUNC_F_SINGLE_F=*_FUNC_F_SINGLE_F;

_FUNC_F_SINGLE_F is how QB64 stores the value of F while inside the function F, before it returns it to us.  What the line in question should read is:

*_FUNC_F_SINGLE_F=FUNC_F();

Make that change, run recompile_win.bat from inside the temp folder, and PRESTO -- output as expected...

The only issue is:

Does anyone know where inside QB64 to change our interpreter, so that it'll output that proper line for us??

Unfortunately, I haven't found it and sorted it out yet.  :(

The change seems simple enough, but where to make that change has me scratching my head ATM.  :P
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

#### TerryRitchie

• Forum Resident
• Posts: 611
• Semper Fidelis
##### Re: QB64 does not interpret 0-place recursive function correctly
« Reply #7 on: October 16, 2018, 01:12:56 PM »
Everyone needs to remember: Galleon was the one who originally wrote QB64, and all the rest of us are just trying to sort through someone else's long -- undocumented -- spaghetti code, and sometimes, some issues are difficult to track and correct, like this one.  :)

I can attest to that statement. One of the things that originally drew me to QB64 was the freely available source code ... until I had a look at it.  Spaghetti is an understatement. I was so disappointed to see the source code in the state it was in. I marvel at how others have taken the time to sort through and modify it for our benefit. They deserve a HUGE THANK YOU!
In order to understand recursion, one must first understand recursion.

#### SMcNeill

• QB64 Developer
• Forum Resident
• Posts: 3185
##### Re: QB64 does not interpret 0-place recursive function correctly
« Reply #8 on: October 22, 2018, 03:44:44 PM »
Heres a fix for this (though it's kinda a hack):

Open QB64.bas.
Scroll all the way to the end of FUNCTION setrefer.
Between the line where we build l\$ and the next line where we print it to file, insert this:

l\$ = r\$ + "=" + e\$ + ";"
Code: QB64: [Select]
1.         IF LEFT\$(r\$, 7) = "*_FUNC_" THEN 'if the left side is a FUNCTION = statement, we don't want its equivelant on the right side.  We want a function call instead.
2.             'This cures the issue below, which destroys recursive functions:
3.             'FUNCTION f
4.             'f = f
5.             'END FUNCTION
6.                 i = INSTR(e\$, r\$)
7.                     l1\$ = LEFT\$(r\$, i + 1)
8.                     i2 = INSTR(8, r\$, "_")
9.                     m1\$ = MID\$(r\$, 3, i2 - 3) + "()"
10.                     e\$ = LEFT\$(e\$, i - 1) + m1\$ + MID\$(e\$, i + LEN(r\$))
11.             LOOP UNTIL i = 0
12.             l\$ = r\$ + "=" + e\$ + ";"
PRINT #12, l\$

***************************
Sorting out the evaltype routine is beyond me, but here's the logic behind this simple fix:
If the translation on the left is a "FUNCTION_Variable = something" then we should never see that same variable on the right side of the equal sign.  Instead, we should see a call back to the function.

The above checks the output, looks for the glitch, and makes the substitution for us.

It's kinda a hack, but it works -- unless somebody has a more elegant solution?
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!