Why do not use GOTO inside a Select Statement?

Just starting out? Need help? Post your questions and find answers here.
SMaag
Enthusiast
Enthusiast
Posts: 330
Joined: Sat Jan 14, 2023 6:55 pm
Location: Bavaria/Germany

Why do not use GOTO inside a Select Statement?

Post by SMaag »

I'm converting some code for 3D-Surfacing from Fortran to Purebasic!

Fortran has a Jumplist command, what is like the classic On GOTO

Code: Select all


If X 21, 22, 23  ; this is the Jumplist command If X=1 jump to 21, if X=2 jump to 22 
  
21  y = 0
22  y = y +1
    Goto 50
23 y = y * y
50 z= z + y

; in Basic this would be  the On Goto, what do not exist in Purebasic
ON X Goto 21 22 23
now my first intention was to do the Jumplist with a Select Command

Code: Select all

Select X
  Case 1
    Goto m21
  Case 2
    Goto m22
  Case 3
    Goto m23
EndSelect

m21:

m22: 

m23:
But in the PB Help we can read the following notes for using Goto

Note: To safely exit a loop, you must always use Break instead of Goto, and never use it in a Select/EndSelect block (unless you have the ability to properly manage the stack yourself).
(!Retranslated from german help!)

Does this mean it can run into a Stack-Problem when I jump out of the Select Statement? Or does it mean it is only a problem when leaving loops
like For Next, While Wend ...
marc_256
Addict
Addict
Posts: 858
Joined: Thu May 06, 2010 10:16 am
Location: Belgium
Contact:

Re: Why do not use GOTO inside a Select Statement?

Post by marc_256 »

sMaag,

I had have the same problem ...
see following post.

https://www.purebasic.fr/english/viewtopic.php?t=82985



If you use If ... EndIf it will work very well in using PB 5.73 x64.

Marc
- every professional was once an amateur - greetings from Pajottenland - Belgium -
PS: sorry for my english I speak flemish ...
SMaag
Enthusiast
Enthusiast
Posts: 330
Joined: Sat Jan 14, 2023 6:55 pm
Location: Bavaria/Germany

Re: Why do not use GOTO inside a Select Statement?

Post by SMaag »

Seems to be a real problem using Goto inside a Select statement!

for the first I implemented the On Goto as a Macro, which seems to do the Job

Code: Select all

; Simulation of On Goto with 3 jumps.
Macro mac_OnGoto3(Switch, jmp1, jmp2, jmp3)
  If Switch = 1
    Goto jmp1
  ElseIf Switch = 2
    Goto jmp2
  ElseIf Switch = 3
    Goto jmp3
  EndIf
EndMacro

juergenkulow
Enthusiast
Enthusiast
Posts: 581
Joined: Wed Sep 25, 2019 10:18 am

Re: Why do not use GOTO inside a Select Statement?

Post by juergenkulow »

Code: Select all

; Select X
  PUSH   qword [v_X]
...

Code: Select all

_EndSelect1:
  ADD    rsp,8
; 
; m21:
l_m21:
The ASM backend uses the stack for Select and corrects the stack with Endselect. If you jump out of it, you must correct the stack yourself.
SMaag
Enthusiast
Enthusiast
Posts: 330
Joined: Sat Jan 14, 2023 6:55 pm
Location: Bavaria/Germany

Re: Why do not use GOTO inside a Select Statement?

Post by SMaag »

It seems this is not the only problem I have. In Fortran they regulary jump out from Loops (For Next) to anywhere.

So I guess I have to think about deeper changes of the Fortran code.

Here the original Code. See Label m100:
There is a jump to m130 where the m120 part is skiped when leaving the For Next.
This isn't possible to convert 1:1

Code: Select all


Macro mac_OnSignGoto(Value, jmp_neg, jmp_null, jump_pos)
  
  CompilerIf Defined(_OnSignGoto, #PB_Variable)
  CompilerElse
    Protected _OnSignGoto.i    
  CompilerEndIf

  _OnSignGoto = Sign(value)
  
  If _OnSignGoto = <0  ; = -1
    Goto jmp_neg
  ElseIf _OnSignGoto = 0
    Goto jmp_null
  Else ; _OnSignGoto = 1
    Goto jump_pos
  EndIf
  
EndMacro

Macro mac_Max2(Result, Value1, Value2)
  If Value1 > Value2
    Result = Value1
  Else
    Result = Value2
  EndIf
EndMacro

Macro mac_Min2(Result, Value1, Value2)
  If Value1 < Value2
    Result = Value1
  Else
    Result = Value2
  EndIf
EndMacro

Procedure.d SIDE(U1.d, V1.d, U2.d, V2.d, U3.d, V3.d) ; As Double
;
;   STATEMENT FUNCTIONS.
;   SIDE(U1, V1, U2, V2, U3, V3) = (V3 - V1) * (U2 - U1) - (U3 - U1) * (V2 - V1)
;
    ; SIDE = (V3 - V1) * (U2 - U1) - (U3 - U1) * (V2 - V1)
   
   Protected SIDE.d
   SIDE = (V3 - V1) * (U2 - U1) - (U3 - U1) * (V2 - V1)
   ProcedureReturn SIDE
EndProcedure

Procedure ORDGR(Array XD.d(1), Array YD.d(1), NT, Array IPT(1), NXI, NYI, Array XI.d(1), Array YI.d(1), Array NGP(1), Array IGP(1))
;
;   IT ORGANIZES GRID POINTS FOR SURFACE RECONSTRUCTION BY
;   SORTING THEM ACCORDING TO THEIR BELONGING TO THE TRIANGLES.
;
;   THE INPUT PARAMETERS ARE
;     XD,YD = ARRAY OF DIMENSION N CONTAINING THE X AND Y COORDINATES
;             OF THE DATA POINTS, WHERE N IS THE NUMBER OF THE DATA
;             POINTS,
;     NT  =   NUMBER OF TRIANGLES,
;     IPT =   INTEGER ARRAY OF DIMENSION 3*NT CONTAINING THE INDICES OF
;             THE VERTEXES OF THE TRIANGLES,
;     NXI =   NUMBER OF GRID POINTS IN THE X COORDINATES,
;     NYI =   NUMBER OF GRID POINTS IN THE Y COORDINATES,
;     XI,YI = ARRAY OF DIMENSION NXI AND NYI CONTAINING THE X AND Y
;             COORDINATES OF THE GRID POINTS,RESPECTIVELY.
;
;   THE OUTPUT PARAMETERS ARE
;     NGP =   INTEGER ARRAY OF DIMENSION 2*NT WHERE THE NUMBER OF GRID
;             POINTS BELONGING TO EACH TRIANGLE IS TO BE STORED,
;     IGP =   INTEGER ARRAY OF DIMENSION NXI*NYI WHERE THE INDICES OF THE
;             GRID POINTS ARE TO BE STORED ACCORDING TO THEIR BELONGING
;             TO THE TRIANGLES CONSIDERED IN ASCENDING ORDER NUMBERS.
;
    Protected.i NT0, NXI0, NYI0, NXINYI, JNGP0, JNGP1, JIGP0, JIGP1, IT0
    Protected.i NGP0, NGP1, IT0T3, IP1, IP2, IP3, INSD, IXI, IYI, L, IZI
    Protected.i IXIMX, IXIMN, JIGP1I
    Protected.d x1, y1, x2, y2, X3, Y3, XII, XMN, XMX, YMN, YMX, YII
    Protected.d res     ; Intermediate result of calculations
;
    Protected.i N, I1, I2, I3
    
    For N = 1 To NT
        L = 3 * N
        I1 = IPT(L - 2)
        I2 = IPT(L - 1)
        I3 = IPT(L)
    Next N
;
    NT0 = NT
;
    ; PRELIMINARY PROCESSING.
    NXI0 = NXI
    NYI0 = NYI
    NXINYI = NXI0 * NYI0
;
    ; DETERMINES GRID POINTS INSIDE THE DATA AREA.
    JNGP0 = 0
    JNGP1 = 2 * NT0 + 1
    JIGP0 = 0
    JIGP1 = NXINYI + 1
    For IT0 = 1 To NT0
        NGP0 = 0
        NGP1 = 0
        IT0T3 = IT0 * 3
        IP1 = IPT(IT0T3 - 2)
        IP2 = IPT(IT0T3 - 1)
        IP3 = IPT(IT0T3)
        x1 = XD(IP1)
        y1 = YD(IP1)
        x2 = XD(IP2)
        y2 = YD(IP2)
        X3 = XD(IP3)
        Y3 = YD(IP3)
        
        ;XMN = DMIN1(x1, x2, X3)
        mac_Min2(XMN, x1, x2)
        mac_Min2(XMN, XMN, x3)
        
        ;XMX = DMAX1(x1, x2, X3)
        mac_Max2(XMX, x1, x2)
        mac_Max2(XMX, XMX, x3)
           
        ;YMN = DMIN1(y1, y2, Y3)
        mac_Min2(YMN, y1, y2)
        mac_Min2(YMN, YMN, y3)
        
        ;YMX = DMAX1(y1, y2, Y3)
        mac_Max2(YMX, y1, y2)
        mac_Max2(YMX, YMX, y3)
        
        INSD = 0
        For IXI = 1 To NXI0
            If (XI(IXI) >= XMN And XI(IXI) <= XMX) : Goto m010 : EndIf
            If (INSD = 0) : Goto m020 : EndIf
            IXIMX = IXI - 1
            Goto m030
m010:   :    If (INSD = 1) : Goto m020 : EndIf
            INSD = 1
            IXIMN = IXI
m020:      ; CONTINUE
        Next IXI
        If (INSD = 0) : Goto m150 : EndIf
        IXIMX = NXI0
m030: : For IYI = 1 To NYI0 ; DO 140
            YII = YI(IYI)
            If (YII < YMN Or YII > YMX) : Goto m140 : EndIf
            For IXI = IXIMN To IXIMX    ; DO 130
                XII = XI(IXI)
                L = 0
                ; On IF_ARI(SIDE(x1, y1, x2, y2, XII, YII)) Goto m130, m040, m050 ;IF (SIDE(X1,Y1,X2,Y2,XII,YII)) 130, 40, 50
                res = SIDE(x1, y1, x2, y2, XII, YII)
                mac_OnSignGoto(res, m130, m040, m050)
                
m040: :         L = 1

m050: :         ;On IF_ARI(SIDE(x2, y2, X3, Y3, XII, YII)) Goto m130, m060, m070 ;IF (SIDE(X2,Y2,X3,Y3,XII,YII)) 130, 60, 70
                res = SIDE(x2, y2, X3, Y3, XII, YII)
                mac_OnSignGoto(res, m130, m060, m070)
                
m060: :         L = 1

m070: :         ;On IF_ARI(SIDE(X3, Y3, x1, y1, XII, YII)) Goto m130, m080, m090 ;IF (SIDE(X3,Y3,X1,Y1,XII,YII)) 130, 80, 90
                res = SIDE(X3, Y3, x1, y1, XII, YII)
                mac_OnSignGoto(res, m130, m080, m090)
                
m080: :         L = 1

m090: :         IZI = NXI0 * (IYI - 1) + IXI
                If (L = 1) : Goto m100 : EndIf
                NGP0 = NGP0 + 1
                JIGP0 = JIGP0 + 1
                IGP(JIGP0) = IZI
                Goto m130
                
m100: :         If (JIGP1 > NXINYI) : Goto m120 : EndIf
                For JIGP1I = JIGP1 To NXINYI
                    If (IZI = IGP(JIGP1I)) : Goto m130 : EndIf
                Next JIGP1I
                
m120: :         NGP1 = NGP1 + 1
                JIGP1 = JIGP1 - 1
                IGP(JIGP1) = IZI
m130:        ; CONTINUE
            Next IXI
m140:     ; CONTINUE
        Next IYI
        
m150: : JNGP0 = JNGP0 + 1
        NGP(JNGP0) = NGP0
        JNGP1 = JNGP1 - 1
        NGP(JNGP1) = NGP1
    Next IT0
;
EndProcedure

marc_256
Addict
Addict
Posts: 858
Joined: Thu May 06, 2010 10:16 am
Location: Belgium
Contact:

Re: Why do not use GOTO inside a Select Statement?

Post by marc_256 »

sMaag,

You need to use [Break] out of a loop.

see examples (F1:help) and look under Break

Marc,
- every professional was once an amateur - greetings from Pajottenland - Belgium -
PS: sorry for my english I speak flemish ...
User_Russian
Addict
Addict
Posts: 1595
Joined: Wed Nov 12, 2008 5:01 pm
Location: Russia

Re: Why do not use GOTO inside a Select Statement?

Post by User_Russian »

It is not acceptable to use Goto to exit Select if used asm backend.
But C backend is more Goto-friendly and does not cause stack corruption (in current version 6.0x).
User avatar
jacdelad
Addict
Addict
Posts: 2035
Joined: Wed Feb 03, 2021 12:46 pm
Location: Riesa

Re: Why do not use GOTO inside a Select Statement?

Post by jacdelad »

TIL goto is still a thing...
https://en.m.wikipedia.org/wiki/COMEFROM
Good morning, that's a nice tnetennba!

PureBasic 6.21/Windows 11 x64/Ryzen 7900X/32GB RAM/3TB SSD
Synology DS1821+/DX517, 130.9TB+50.8TB+2TB SSD
User avatar
Caronte3D
Addict
Addict
Posts: 1377
Joined: Fri Jan 22, 2016 5:33 pm
Location: Some Universe

Re: Why do not use GOTO inside a Select Statement?

Post by Caronte3D »

GoTo is the worst basic language instruction. It's best not to use it if you can.
marc_256
Addict
Addict
Posts: 858
Joined: Thu May 06, 2010 10:16 am
Location: Belgium
Contact:

Re: Why do not use GOTO inside a Select Statement?

Post by marc_256 »

Caronte3D wrote: Fri Dec 08, 2023 4:34 pm GoTo is the worst basic language instruction. It's best not to use it if you can.
Since 1976 I programmed 100ts of ASM and BASIC programs,
as well as JMPs (in ASM) as GOTOs (in BASICs)
and till today they worked all very very well...

marc
- every professional was once an amateur - greetings from Pajottenland - Belgium -
PS: sorry for my english I speak flemish ...
AZJIO
Addict
Addict
Posts: 2228
Joined: Sun May 14, 2017 1:48 am

Re: Why do not use GOTO inside a Select Statement?

Post by AZJIO »

Imitation of Goto command

Code: Select all

Repeat
	
	Continue ; Goto Repeat
	
Until 1
Example 2

Code: Select all

GoToLabel()
Last edited by AZJIO on Fri Dec 08, 2023 4:55 pm, edited 1 time in total.
User avatar
Caronte3D
Addict
Addict
Posts: 1377
Joined: Fri Jan 22, 2016 5:33 pm
Location: Some Universe

Re: Why do not use GOTO inside a Select Statement?

Post by Caronte3D »

marc_256 wrote: Fri Dec 08, 2023 4:43 pm ...and till today they worked all very very well...
Yes, it works well, but the code becomes more and more spaghetti and... (at least) in PureBasic there is always a way to avoid it.
Asm is another topic.

Anyway you can use whatever you want :D
User avatar
luis
Addict
Addict
Posts: 3895
Joined: Wed Aug 31, 2005 11:09 pm
Location: Italy

Re: Why do not use GOTO inside a Select Statement?

Post by luis »

"GoTo is the worst basic language instruction"

ouch, I think Break followed by a number is a good contender !

"but the code becomes more and more spaghetti"

That's true if you use GOTO to jump back and forth or for looping, also if you jump very far away.
Then the code may become hard to follow and bugs may creep in.
If you use it to jump only forward (to skip sections of code) and inside the same scope (typically a procedure) it can have its place and can be even cleaner than using convoluted nested structured statements with dubious breaking rules. At least that's I how use it 99% of time.
Anyway, it's a subjective and controversial matter and it will ever be. :)
"Have you tried turning it off and on again ?"
User avatar
Caronte3D
Addict
Addict
Posts: 1377
Joined: Fri Jan 22, 2016 5:33 pm
Location: Some Universe

Re: Why do not use GOTO inside a Select Statement?

Post by Caronte3D »

you're right 100% :wink:
User avatar
Tenaja
Addict
Addict
Posts: 1959
Joined: Tue Nov 09, 2010 10:15 pm

Re: Why do not use GOTO inside a Select Statement?

Post by Tenaja »

Caronte3D wrote: Sat Dec 09, 2023 7:35 pm you're right 100% :wink:
That's right... in fact, I would argue that a simple Goto is (can be) more clear and readable than a Break that is mid level in a deeply nested code segment. Only because we now have block folding and highlighting in our IDE now are those even close to the simplicity of a simple single Goto.

It is extremely rare for me to use them, but when I do, it is because they make the code much better.
Post Reply