BBC BASIC for Windows
Programming >> BBC BASIC language >> Calling a procedure name as a string
http://bb4w.conforums.com/index.cgi?board=language&action=display&num=1453974800

Calling a procedure name as a string
Post by AlanRoberts on Jan 28th, 2016, 08:53am

Is it possible to call a procedure/function, using a text string as the function name? I want to be able to supply unknown number of program modules each to do something a user might want, but allowing him to load only the ones he needs.

Each module would have one function, named with the file name, so the program would need to be able to find the filename of the module (that's easy) and use that name to call the function.

E.g. - a module called Fred_Bloggs.addon' containing a function named DEFFNFred_Bloggs.

The program collects the filenames of all files with the '.addon' extension (there could be a dozen or more), and uses the filenames in dialog list boxes. The user chooses which he wants to call and the program then has to get the function name from the listing, which is actually the filename. So, at the time of writing the main program, I don't know what modules he has loaded.

A bit of a long-winded description, bit I'm struggling here.

Alan Robets
Re: Calling a procedure name as a string
Post by DDRM on Jan 28th, 2016, 3:12pm

Hi Alan,

The short answer is that I don't know any way to do that. It might be worth dropping a private email to Richard Russell - if anyone will know, he will - and he might even create a new one!

One approach that might help is the "indirect procedure and function calls" method described in the manual, where you allocate a pointer to the procedure, and then call that. Your "module" could include a standard procedure ("PROCinit"?) that sets the pointer(s) for its own other procedure(s), and passes them to the host program. Assuming you will load the modules as libraries, I think the most recent version of PROCinit loaded will be used, so as long as you ran that before loading the next module, each should set up links to its own procedures...

...but I'm struggling to visualise how your host program is going to call routines it knows nothing about, unless it is essentially a shell, which is virtually going to chain to the module - in which case can't you give all the modules the same core procedure names (PROCinit,PROCmain, etc), and then just use the standard name to get the custom action required? Or does the user need to be able to load "Fred_Bloggs" AND "Joe_Smith"?

Sorry, that's probably even more long-winded (and confusing!) than your question...

D
Re: Calling a procedure name as a string
Post by AlanRoberts on Jan 28th, 2016, 3:32pm

My program is about 20k lines long already, and deals with data from spectroradiometers. It needs to convert each weird format to a standard one so that they can be processed. At present, I have to issue a new version of the program each time I write a converter for a new spectroradiometer.

So, the current idea is to shift all the converter functions out into modules which get installed at start-up, At present there would be about 15 of them, but the list keeps growing. So it means that everybody using the software has to wade through an ever-increasing list of formats to find the only one they need. Having the converters as modules means that each user could download only the module he needed and not have all the spare converters to worry about.

So, I first thought that each converter would be in a module named by manufacturer/model of spectroradiometer. The sole function in each would also have that name. So I'd have to call it using the module's name, which I don't know at the time of writing the software.

Now, I think there's an easier way. Each module is named for the manufacturer/model, but the functions are simply listed (DFFNconvert_A, DEFFNconvert_B etc). Then it should be easy to collect all the modules and iterrogate each to find out what file type it converts and then simply call the function using an already known list of all possible versions. So I might not need to use a string as the function name. Clunky, but it should work.

I don't want to worry Richard about this, I know he's busy doing other things.

Thanks for you help.

Alan Roberts
Re: Calling a procedure name as a string
Post by Zaphod on Jan 28th, 2016, 4:02pm

How about using EVAL?

Code:
     A$= "FNtest"

      A$=EVAL(A$)

      END


      DEF FNtest
      PRINT "Well that was a surprise"
      =""
 


Z
Re: Calling a procedure name as a string
Post by AlanRoberts on Jan 28th, 2016, 4:25pm

Wow, now that really is a surprise. S'truth, you learn something new every day.

TA.
Re: Calling a procedure name as a string
Post by DDRM on Jan 29th, 2016, 08:08am

D***! I KNEW there was something like that! I looked at OSCLI, but even before I tried it I knew it was the wrong answer!

Glad SOMEONE is awake.

wink

D
Re: Calling a procedure name as a string
Post by JGHarston on Mar 17th, 2016, 10:13pm

Just as you can use EVAL to call functions whose names are only known at runtime, you can also use EVAL to create variables who names are only known at runtime. Using the following you can do, for example, V$="fred$":PROCVar_Assign(V$,"hello") which is the equivalent of doing fred$="hello".

Code:
  REM Var_Assign(Var$,Val$)
  REM Sets the variable in 'Var$' to the value in 'Val$'
  REM --------------------------------------------------
  :
  DEFPROCVar_Assign(Var$,Val$)
  IF RIGHT$(Var$,1)="$":A%=EVAL("FNVar_S("+Var$+","+Val$+")"):ENDPROC
  IF RIGHT$(Var$,1)="%":A%=EVAL("FNVar_I("+Var$+","+Val$+")"):ENDPROC
  IF RIGHT$(Var$,1)="&":A%=EVAL("FNVar_B("+Var$+","+Val$+")"):ENDPROC
  IF RIGHT$(Var$,1)="#":A%=EVAL("FNVar_F("+Var$+","+Val$+")"):ENDPROC
  A%=EVAL("FNVar_R("+Var$+","+Val$+")"):ENDPROC
  ENDPROC
  :
  DEFFNVar_S(RETURN a$,b$):a$=b$:=0
  DEFFNVar_I(RETURN a%,b%):a%=b%:=0
  DEFFNVar_B(RETURN a&,b&):a&=b&:=0
  DEFFNVar_F(RETURN a#,b#):a#=b#:=0
  DEFFNVar_R(RETURN a, b ):a =b :=0 


See:
http://mdfs.net/BLib/Variable.bbc
http://mdfs.net/BLib/Docs/Variable.txt

Re: Calling a procedure name as a string
Post by AlanRoberts on Mar 18th, 2016, 10:09am

The thing that amazed me is that I can pass a line like

result=EVAL(Cnv$(n%,0)+"(test$)", x,y)

... and get a result, including changes to values x and y from. -

DEFFNtest(a$, RETURN x, RETURN y)

That was a bit mind-blowing and extremely useful.