Page 1 of 2

Allow gosub in procedures

Posted: Mon Jan 21, 2008 3:05 am
by Mistrel
We can Goto out of a function but we can't Gosub. In my opinion Gosub would be much more useful and safer.

Yes, I agree that this is generally a bad thing to do, but it does have its uses. Gosub would sure beat the pants off of Gotoing out and Gotoing back in. :?

Re: Allow gosub in procedures

Posted: Mon Jan 21, 2008 3:22 am
by citystate
why not just use Procedures instead of subroutines - even safer than gosub

Re: Allow gosub in procedures

Posted: Mon Jan 21, 2008 3:31 am
by Mistrel
citystate wrote:why not just use Procedures instead of subroutines - even safer than gosub
It would just make my life easier for the code I'm working with. I don't have the option of modifying this code in that way.

Gosub would also be easier to jump around inside a function than Goto if you want to get back from where you started.

Posted: Mon Jan 21, 2008 4:30 am
by jack
Goto Gosub are OK if used judiciously, as long as you don't goto or gosub from one sub into another and another ..., I mean keep subs modular.

Posted: Mon Jan 21, 2008 3:28 pm
by jack
here's dirty hack that will allow gosub inside a procedure, use at your own risk.

Code: Select all

Global NewList gosublist.l() 
Global retaddress.l 

Macro _gosub(label,retrn) 
  AddElement(gosublist()) 
  gosublist()=?retrn 
  ! lea eax,[l_#label] 
  ! jmp eax 
EndMacro 

Macro _return 
  retaddress=gosublist() 
  DeleteElement(gosublist()) 
  ! jmp [v_retaddress] 
EndMacro 

Procedure test1() 
  Shared gosublist.l(),retaddress.l 
  i.l 
  For i=1 To 10 
    _gosub(factorial,l1) ;you need to supply a return label, in this case l1 
    PrintN("This never gets executed")
    l1: PrintN(Str(fac)) 
  Next 
  ProcedureReturn 
  factorial: 
    If fac.l=0 
      fac=1 
      n.l=1 
    EndIf 
    fac=fac*n 
    n=n+1 
  _return 

EndProcedure 



  OpenConsole() 
  test1() 
  Input() 
  CloseConsole() 
  End 
  

Posted: Mon Jan 21, 2008 6:01 pm
by freak
Gosub adjusts the stack, Goto doesn't. Thats why you can use the one inside procedures and not the other.

Posted: Mon Jan 21, 2008 6:32 pm
by netmaestro
I don't believe either one belongs in a modern variant of the Basic language. There's far more power in PB today than was ever in early Basic's, so much in fact that using primitive commands like these is not only pointless but it leads to seriously bad programming styles.

This is just one frog's opinion and I hope I haven't offended anyone by airing it. :)

Posted: Mon Jan 21, 2008 6:51 pm
by jack
I agree with the danger of writing bad code, but contrary to purest, I belive that goto and gosub can be useful if used judiciously, for example: don't goto or gosub out of a procedure and don't goto into or out of a sub, try not to nest gosub's.
personally, I would rather have local procedures instead.

Posted: Mon Jan 21, 2008 7:26 pm
by jack
another way, no asm needed.

Code: Select all

Macro _gosub(label,retrn) 
  AddElement(gosublist()) 
  gosublist()=?retrn 
  GoToEIP(?label)
EndMacro 

Macro _return 
  retaddress=gosublist() 
  DeleteElement(gosublist()) 
  GoToEIP(retaddress)
EndMacro 

Procedure test1() 
  NewList gosublist.l() 
  retaddress.l 
  i.l 
  For i=1 To 10 
    _gosub(factorial,l1) ;you need to supply a return label, in this case l1 
    PrintN("This never gets executed") 
    l1: PrintN(Str(fac)) 
  Next 
  ProcedureReturn 
  factorial: 
    If fac.l=0 
      fac=1 
      n.l=1 
    EndIf 
    fac=fac*n 
    n=n+1 
  _return 

EndProcedure 



  OpenConsole() 
  test1() 
  Input() 
  CloseConsole() 
  End 

Posted: Mon Jan 21, 2008 7:35 pm
by Mistrel
freak wrote:Gosub adjusts the stack, Goto doesn't. Thats why you can use the one inside procedures and not the other.
I didn't know this. DarkBasic allows Gosubing out of a function so I suspected that it was a design choice. :roll:

Posted: Mon Jan 21, 2008 7:42 pm
by Fluid Byte
Of course DarkBasic allows this, then again, it's rubbbish.

Posted: Mon Jan 21, 2008 7:48 pm
by Trond
Mistrel wrote:
freak wrote:Gosub adjusts the stack, Goto doesn't. Thats why you can use the one inside procedures and not the other.
I didn't know this. DarkBasic allows Gosubing out of a function so I suspected that it was a design choice. :roll:
DarkBasic is an interpreter.

Posted: Mon Jan 21, 2008 8:11 pm
by Demivec
jack wrote:I agree with the danger of writing bad code, but contrary to purest, I belive that goto and gosub can be useful if used judiciously, for example: don't goto or gosub out of a procedure and don't goto into or out of a sub, try not to nest gosub's.
I agree with those statements. Gosub inside a procedure would be used when there would be a benefit of reusing code with the added speed of not having to handle a procedure call because all operations would be performed on local variables. To quote the manual: "Gosub is useful when building fast structured code." It only has application in advanced cases, because beginners are never in a hurry. :wink:

Posted: Mon Jan 21, 2008 8:13 pm
by Trond
Demivec wrote:
jack wrote:I agree with the danger of writing bad code, but contrary to purest, I belive that goto and gosub can be useful if used judiciously, for example: don't goto or gosub out of a procedure and don't goto into or out of a sub, try not to nest gosub's.
I agree with those statements. Gosub inside a procedure would be used when there would be a benefit of reusing code with the added speed of not having to handle a procedure call because all operations would be performed on local variables. It only has application in advanced cases, because beginners are never in a hurry. :wink:
The problem is, that with gosub, it's not possible to re-use the local variables because gosub changes the stack offset, and local variables is access with a fixed stack offset. Adjusting this at run-time would bring a way greater speed penalty than using gosub could ever fix.

Posted: Mon Jan 21, 2008 8:19 pm
by Demivec
Trond wrote:The problem is, that with gosub, it's not possible to re-use the local variables because gosub changes the stack offset, and local variables is access with a fixed stack offset. Adjusting this at run-time would bring a way greater speed penalty than using gosub could ever fix.
That is a reason why something would have to be changed so it could be implemented. I didn't know that was a side-effect. I'm happy to be aware of it now.

On a side note, I'm interrested in a "On <indexvalue> ExecProc" kind of command as well. It would be used instead of the Select/Case. I think it has merits for speed and ease of reading. But that's another story.