LoginLogin
Nintendo shutting down 3DS + Wii U online services, see our post

[fixed] Cannot RETURN from GOSUB inside DEF block.

Root / SmileBASIC Bug Reports / [.]

SquareFingersCreated:
It's not a bug, just an annoying consequence of the fact that RETURN has two different uses. GOSUB definitely doesn't act like GOTO inside a function; you can test this by doing something like:
TEST

DEF TEST
 @LOOP
 GOSUB @LOOP
END
which still gives a stack overflow error. I think a good solution is just to not use GOTO or GOSUB at all lol.

One use for RETURN is to return from a GOSUB subroutine. When there are several nested subroutines, a RETURN is associated with the most recently called subroutine that has not already returned. Another use for RETURN is to return from a user-defined DEF procedure. When there are several nested procedures, a RETURN is associated with the most recently called procedure that has not already returned. Given that, for RETURN not to be associated with the most recent of; subroutines that have not returned, and, procedures that have not returned, is fairly absurd. EDIT: Good point with the code that gives a stack overflow, though. In a DEF block, GOSUB gives nothing you would want, that GOTO doesn't, and it does give you something you don't want, useless memory wastage. Seems like a bug to me.

I don't understand how they can have both gosubs AND functions and yet they use a different system. They are essentially the same and SHOULD use the same call stack, so return should just... pop the last frame no matter if it's a gosub or a function. I guess it gets confusing since people can define labels within other functions, so it might just be a design decision rather than stupidity. Also, I'm sorry SF but the punctuation in your last sentence makes no sense.

Labels are local to functions, so you aren't able to jump between functions or any other crazy things. They could have let GOSUB work inside functions by making RETURN only end the function when the GOSUB stack is empty, but that could get annoying if you actually want to exit the function from within a GOSUB block. This problem shows that reusing keywords is a really bad idea, and it's not just limited to RETURN. You also can't END the program from inside a DEF, which doesn't seem like a problem at first (since STOP exists) but STOP and END aren't the same. (STOP prints "Break on _:_" which is annoying for things like smile tool replacements, and I think END will return from an EXEC'd slot.)

Reusing keywords, in the abstract, is a bad idea, absolutely, agreed. Because it can all too easily lead to concrete bugs, such as this one. There is a keyword allowed to be in use, here, which adds only bad effects. They could have chosen to disallow GOSUB in a DEF block, or they could have chosen for GOSUB to behave like a regular GOSUB no matter where it is in the code. Choosing the worst of both worlds, nothing reedeming at all, was just a terrible design decision.

I wouldn't be objected to the idea of adding an EXIT keyword to forcibly terminate the application, removes a lot of ambiguity; but in general, you shouldn't be killing the program in a local scope anyway. You're leaving a mess for the system to clean up (which doesn't matter here, but it's good to start that habit.)

This has been fixed in 3.5.2!
DEF EXAMPLE
 GOSUB @TEST
 RETURN 'returns from function
 
 @TEST
 RETURN 'returns from subroutine
END

Not so fixed. DEF EXAMPLE() GOSUB @TEST RETURN "666" @TEST RETURN END PRINT EXAMPLE() gives Uninitialized variable error

huh that's strange. if you do
DEF EXAMPLE()
 GOSUB @TEST
 RETURN "666"
 @TEST
 RETURN ""
END

PRINT EXAMPLE()
It works like it's meant to (returns "666")