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.
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
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.
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.
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
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.
Last edited by Demivec on Mon Jan 21, 2008 8:15 pm, edited 1 time in total.
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.
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.
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.