May 07, 2024, 10:46:17 AM

News:

IonicWind Snippit Manager 2.xx Released!  Install it on a memory stick and take it with you!  With or without IWBasic!


Gosub by string

Started by aurelCB, September 21, 2011, 08:31:37 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

aurelCB

Hi...
You probably know that is in Creative Basic possible to jump to
subroutine with string if subroutine name are prefixed by string sign $:
like this:
Def w1:window
def mysub:string
mysub="newsub"
'create main window
openWindow w1,0,0,500,400,@minbox,0,"MainGUI",&main
Setwindowcolor w1,rgb(220,220,220)
'--------------------------------------------------------
gosub $mysub


'---------------------------------------------------------
run=1
waituntil w1=0

end

'-------------------------------------------------------
sub newsub
move w1,20,20:print w1,"OK"
return
endsub

'------------------------------------------------------
Sub main
Select @class
Case @idclosewindow
closewindow w1
Case @idcreate
Centerwindow w1
ENDSELECT
RETURN
ENDSUB


But same program not work in EB/IWB.
Is there a way to do similiar thing in EB/IWB ?

Using this method we can avoid long select/case and directly jump to subroutine.
Any ideas ....?

Brian

Aurel,

If you have a SUB named "Aurel" it is enough in IWB just to call Aurel(), as in:

Aurel()

SUB Aurel
   Called from Aurel()
ENDSUB

Brian

LarryMc

Not sure what you are ultimately trying to do.

If you are wanting to call different routines at a single point in your program by setting a string to a value and then doing the call I suggest you look at the IWB Help file Language/Subroutines/Indirectly calling subroutines section.

And the indirect_functions.iwb example.

LarryMc
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

LarryMc

What Brian posted is also correct.
Your code modified where it works in IWB:

Def w1:window
'def mysub:string
'mysub="newsub"
'create main window
openWindow w1,0,0,500,400,@minbox,0,"MainGUI",&main
Setwindowcolor w1,rgb(220,220,220)
'--------------------------------------------------------
mysub()


'---------------------------------------------------------
run=1
waituntil w1=0

end

'-------------------------------------------------------
sub newsub
move w1,20,20:print w1,"OK"
return
endsub

'------------------------------------------------------
Sub main
Select @class
Case @idclosewindow
closewindow w1
Case @idcreate
Centerwindow w1
ENDSELECT
RETURN
ENDSUB


LarryMc
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

aurelCB

Brian i know this of course....
Yes Larry i want to call muliple subs from one point using string.
You probably see this simple example from CB.
I already look into this example but this works with adresses...

aurelCB

Maby i must be more clear.
So what i want to do is next:
Get sub name from hash table (dictionary) and use this string to call
subroutine.

LarryMc

Quote from: aurelCB on September 21, 2011, 11:18:16 AM
Maby i must be more clear.
So what i want to do is next:
Get sub name from hash table (dictionary) and use this string to call
subroutine.

The only way I know of doing that is creating a SELECT block; unless you can store a pointer to a subroutine in your hash instead of a string.

LarryMc
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

aurelCB

Uff yes Larry you right there is no way like in CB .
Hmm i dont know but i think that that i can store string pointer in hash.
I will try...

zaphod

hello,
you need to store an array of pointers like that :


DECLARE fnTemplate

Def w1:window
def mysub[2] as pointer 'string
mysub[0]=&newsub
mysub[1]=&newsub1
'create main window
openWindow w1,0,0,500,400,@minbox,0,"MainGUI",&main
Setwindowcolor w1,rgb(220,220,220)
'--------------------------------------------------------
!<fntemplate>mysub[0]()
!<fntemplate>mysub[1]()

'---------------------------------------------------------
run=1
waituntil w1=0

end

'-------------------------------------------------------
sub newsub
move w1,20,20:print w1,"OK"
return
endsub

sub newsub1
move w1,20,40:print w1,"O0K"
return
endsub
'------------------------------------------------------
Sub main
Select @class
Case @idclosewindow
closewindow w1
Case @idcreate
Centerwindow w1
ENDSELECT
RETURN
ENDSUB

aurelCB

Helo zaphod ...
good idea but not work.
i recive error -> invalid function pointer in this two lines:
!<fntemplate>mysub[0]()
!<fntemplate>mysub[1]()


Your code looks logical to me but still dont work...

LarryMc

Change
def mysub[2] as pointer 'string
to
def mysub[2] as UINT 'pointer 'string

and it should work.

LarryMc
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

aurelCB

September 22, 2011, 12:20:46 PM #11 Last Edit: September 22, 2011, 12:27:12 PM by aurelCB
Not work with strings...
hash table (dict) need string not UINT.

aurelCB

so i look into CB source code and find do_gosub structure.
But i simply do not uinderstand how misterP solve this thing:
if(*k=='$')
        {
                if(!(cv=find_var(k+1))) return(0);
                k = (TEXT *)cv->mem;


maby this piece of code is not for this place but im curious how this thing work
in CB.heck ...this looks like adventage of interpreter over compiler ::)

aurelCB

Well it seems that will work with tamplate. :)
Here is code which use hash table:
'by zapHod array of strings as template
DECLARE fn()
'create hash table (dictionary)
strHash=DICTCREATE (100)

Def w1:window
def mysub[2] as uint 'string
'set two uintegers
mysub[0]=&newsub
mysub[1]=&newsub1
'test
MESSAGEBOX 0,"Adrr:"+str$(mysub[0]),"Test sub adress!"

'fill hash with strings
DictAdd(strHash,"s0",str$(mysub[0]))
DictAdd(strHash,"s1",str$(mysub[1]))

'create main window
openWindow w1,0,0,500,400,@minbox,0,"MainGUI",&main
Setwindowcolor w1,rgb(220,220,220)
'--------------------------------------------------------
uint temp
string temp$

'get string from hash table
temp$ = DictLookup(strHash,"s1")
'check if is not empty
IF temp$ <> ""
'set temp variable with subroutine adress
temp=VAL(DictLookup(strHash,"s1"))
IF temp <> 0
'jump indirectly to subroutine
!<fn>temp()
ENDIF
ENDIF

'---------------------------------------------------------
run=1
waituntil w1=0

end

'-------------------------------------------------------
sub newsub
move w1,20,20:print w1,"OK"
return
endsub

sub newsub1
move w1,20,40:print w1,"O0K"
return
endsub
'------------------------------------------------------
Sub main
Select @class
Case @idclosewindow
closewindow w1
Case @idcreate
Centerwindow w1
ENDSELECT
RETURN
ENDSUB


I hope that this will be usefull for anyone of you which have program with
long select/case block . ;)

aurelCB

Just for info...
I don't know that this things exists in old implementation of FORTH language.
his is called direct threaded code (DTC).
from wikipaedia:
To save space, programmers squeezed the lists of subroutine calls into simple lists of subroutine addresses, and used a small loop to call each subroutine in turn.

billhsln

I am not 100% sure, but take a look at Indirectly calling subroutines, in the User's Guide.  It sounds like what you are looking to do.

Bill
When all else fails, get a bigger hammer.

aurelCB

Bill problem is solved and work fine ;)