Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.
|
Forum Index : Microcontroller and PC projects : MMBasic core: bug in cmd_gosub()
Author | Message | ||||
thwill Guru Joined: 16/09/2019 Location: United KingdomPosts: 3839 |
Peter, Geoff, You may not care, but: Currently: void cmd_gosub(void) { if(gosubindex >= MAXGOSUB) error("Too many nested GOSUB"); errorstack[gosubindex] = CurrentLinePtr; gosubstack[gosubindex++] = nextstmt; LocalIndex++; if(isnamestart(*cmdline)) nextstmt = findlabel(cmdline); else nextstmt = findline(getinteger(cmdline), true); IgnorePIN = false; CurrentLinePtr = nextstmt; } IMO it should be: void cmd_gosub(void) { if(gosubindex >= MAXGOSUB) error("Too many nested GOSUB"); const char *return_to = nextstmt; if(isnamestart(*cmdline)) nextstmt = findlabel(cmdline); else nextstmt = findline(getinteger(cmdline), true); IgnorePIN = false; errorstack[gosubindex = CurrentLinePtr; gosubstack[gosubindex++ = return_to; LocalIndex++; CurrentLinePtr = nextstmt; } This way if findlabel/findline fail (which they can) the stacks and the LocalIndex don't get clobbered. Observation: I didn't expect LocalIndex and LOCAL variables to work with GOSUB ... I don't mind, I just thought LOCAL was part of the SUB/FUNCTION structured programming rather than the older GOSUB style. Note that in general there is scope for clobbering here because no setjmp is installed to recover if you are skipping errors and call GOSUB. I'll leave it as an exercise for the reader (or not), as GOSUB isn't really something I would ever use with MMBasic. Best wishes, Tom Game*Mite, CMM2 Welcome Tape, Creaky old text adventures |
||||
matherp Guru Joined: 11/12/2012 Location: United KingdomPosts: 8574 |
Can you provide an example of how/where this matters and your change improves things? From the manual FYI Edited 2023-01-22 02:55 by matherp |
||||
thwill Guru Joined: 16/09/2019 Location: United KingdomPosts: 3839 |
Try this (demonstrated with MMB4W): > list Option Explicit On foo() End Sub foo() Local x% = 1 On Error Skip 1 Gosub no_such_label x% = 2 Print "Caught: " Mm.ErrMsg$ End Sub > run Caught: Error in line 9: Cannot find label Error in line 10: X is not declared Note that a) X is declared. b) if X hadn't been declared then its error should be the only one displayed before the program aborts. Also try commenting out line 10 "x% = 2" to see: > run Caught: Error in line 9: Cannot find label Caught: Error in line 9: Cannot find label MMB4L which contains my suggested fix produces this output for both cases: > run Caught: Error in line 9: Cannot find label The problem is because as-written cmd_gosub() updates the state as if the GOSUB had occurred before checking whether the GOSUB is even possible. It's not really very significant for the majority of users (possibly ALL-1 users) and I wouldn't have encountered it myself but for the fact that I am trying to write comprehensive tests for labels before switching MMB4L to use hash lookup for them. However I tell you about this stuff because I see it, and in this case I even have a simple fix for it, it's up to you and Geoff whether you act on it or not. I'm no longer so sure about that, I think I was letting myself get carried away with speculation, I should restrict myself to errors I have actually experienced . Yes, and makes sense, though if you removed them then you would lose compatibility with a host of legacy non-MMBasic programs. Best wishes, Tom Edited 2023-01-22 04:37 by thwill Game*Mite, CMM2 Welcome Tape, Creaky old text adventures |
||||
twofingers Guru Joined: 02/06/2014 Location: GermanyPosts: 1133 |
@Tom, in my opinion it's easy to replace with Sub/End Sub. For me "Gosub" is a dinosaur. Best regards Michael |
||||
thwill Guru Joined: 16/09/2019 Location: United KingdomPosts: 3839 |
Absolutely, it's a dinosaur, and it would make life simpler if it was removed from MMBasic ... however in those mythical sunlit uplands where a young person is pried from their phone/tablet/VR headset/vape and persuaded there might be some merit in typing in some creaky old BASIC program it might happen to contain a GOSUB statement as it is pretty much a BASIC staple [pun intended]. Best wishes, Tom Game*Mite, CMM2 Welcome Tape, Creaky old text adventures |
||||
twofingers Guru Joined: 02/06/2014 Location: GermanyPosts: 1133 |
I understand both sides, but I wouldn't be sad if it were removed. |
||||
Justplayin Guru Joined: 31/01/2014 Location: United StatesPosts: 308 |
I wish people would stop trying to turn BASIC into C. I believe GOSUB is a critical part of BASIC. BASIC is supposed to simple to use, which GOSUBs are and SUBs are not so much. Yes I do use SUBs but I prefer GOSUB when I'm doing a quick bit of code. I am not a Mad Scientist... It makes me happy inventing new ways to take over the world!! |
||||
Mixtel90 Guru Joined: 05/10/2019 Location: United KingdomPosts: 5712 |
Oh, I dunno - they are much of a muchness if you treat them similarly. It's just that you have the option of making SUBs more powerful - you don't need to. 'main routine myloop: do something here GOSUB asubroutine 'do something else GOTO myloop asubroutine: 'do something here RETURN --- or --- 'main routine DO 'do something here dothisroutine 'do something else LOOP SUB dothisroutine 'do something here END SUB Mick Zilog Inside! nascom.info for Nascom & Gemini Preliminary MMBasic docs & my PCB designs |
||||
Nimue Guru Joined: 06/08/2020 Location: United KingdomPosts: 367 |
The debate between (precise) historical preservation of (programming) languages vs reinterpreting old languages in light of more modern paradigms is an interesting one. Line numbers (either present or "hidden") are a good example. When I learned to program in BASIC, I was never really aware of what the point of line numbers was, just that I needed to use them. This persisted into my Spectrum / BBC Basic day - then QBasic rocked my world. BUT.... whilst Gosubbing to a "label" seemed so powerful, students ability to Return to a different part of the code than where it was called from pretty much reinvented spaghetti coding of the "GOTO" days. From what I remember back in the day students could not understand their own code 48hrs after it was written. So when we embraced SUB and CALL that tidied that up. Depending on the students (and teachers) I often use "LOGO" as a starting point for teaching "coding". Interesting LOGO has many calls/functions that are often missing / removed depending on the interpretation. For example, OPENREAD filename -- yes, LOGO has file i/o but this is often left out - presumably in an attempt to make LOGO even more beginner friendly. My point (clumsily made) is that teaching "structured programming" concepts (if/then/else, iteration, subroutines/functions) is what matters, not how to actually implement in a specific language. For the record - I've got no residual love for GOSUB. Nimue Entropy is not what it used to be |
||||
twofingers Guru Joined: 02/06/2014 Location: GermanyPosts: 1133 |
FYI: For me surprising: Gosub/Return is tree times faster than a Sub/End Sub. I don't mean to say that it has practical relevance in every case or very often! 'Test for execution time Gosub vs Sub() '-------------------------------------- Option explicit Dim float t, t_L, t_P Dim integer i, loops = 100000 Timer =0 For i = 1 To loops Next t= Timer Timer =0 For i = 1 To loops GoSub L_test Next t_L= Timer-t Timer =0 For i = 1 To loops P_test Next t_P= Timer-t Print "Time for "loops " loops" Print "empty loop || Gosub || Sub()" Print t, t_L, t_P End '----- Sub P_test' test procedure End Sub 'end test procedure '----- L_test: ' label test gosub Return ' return test gosub '----- End '****************************** Result: Time for 100000 loops empty loop || Gosub || Sub() 203.196 509.118 1437.068 Edited 2023-01-22 09:45 by twofingers |
||||
thwill Guru Joined: 16/09/2019 Location: United KingdomPosts: 3839 |
For me surprising: Gosub/Return is t[h]ree times faster than a Sub/End Sub ... Nice observation. SUB/END SUB does a great deal more book-keeping than GOSUB/RETURN because, for example, it needs to deal with the possibility of the SUB having parameters. Possibly it could be optimised ... possibly not. Of course you are testing an extreme case, if you were actually doing anything in the "subroutine" the relative difference due to the overhead would be much less. Best wishes, Tom Edited 2023-01-22 09:42 by thwill Game*Mite, CMM2 Welcome Tape, Creaky old text adventures |
||||
twofingers Guru Joined: 02/06/2014 Location: GermanyPosts: 1133 |
I see that exactly the same way! Kind regards Michael |
||||
Goksteroo Senior Member Joined: 15/03/2021 Location: AustraliaPosts: 110 |
Why the t_L= Timer-t and t_P= Timer-t since you have zeroed the timer before each test? Oops! Add some work to each routine and you get more 'real world' results. 'Test for execution time Gosub vs Sub() '-------------------------------------- Option explicit Dim float t, t_L, t_P Dim integer i,pp, loops = 100000 Timer =0 For i = 1 To loops pp=100 do inc pp,-1 loop until pp<1 Next t= Timer Timer =0 For i = 1 To loops GoSub L_test Next t_L= Timer Timer =0 For i = 1 To loops P_test Next t_P= Timer Print "Time for "loops " loops" Print "empty loop || Gosub || Sub()" Print t, t_L, t_P End '----- Sub P_test' test procedure pp=100 do inc pp,-1 loop until pp<1 End Sub 'end test procedure '----- L_test: ' label test gosub pp=100 do inc pp,-1 loop until pp<1 Return ' return test gosub '----- End '****************************** gives these results.... Time for 100000 loops empty loop || Gosub || Sub() 1528.6083 1524.8994 1549.1483 |
||||
DaveJacko Regular Member Joined: 25/07/2019 Location: United KingdomPosts: 52 |
Loosely related to this thread.. has anyone else noticed that.. you accidentally code 2 subs with the same name, MMBasic helps you, and throws an error - fab! if you are thick like me, and type two line labels with the same name, MMBasic just goes to the first one, no error! this set my OBD2 ELM 327 reader project back quite a bit. (is this called a hashing table thing issue?) Thanks you lot ! |
||||
Print this page |