Function to list all written function in a Cache Routine
Hi Everyone,
Has anyone tried to write down a function in a routine that list all of possible function inside the routine?
I can only think of iterating through the routine line one by one and differentiate between function and function definition.
Is there any existing function that can be utilised? I think it should work similar to how
do function^routineName
works. I could not find the source for how "do" works, but I believe do will look at the list of function in the routine, and if it finds it, it will call the function, but if it does not find it, it will give an error?
Can someone please shed a light on this? Thank you.
EDIT:
My goal is to create a menu for a utility routine. This menu function should be able to detect all the function written in the routine automatically, so everytime a new function is added, calling the menu will show the new function I have written.
Manually, this is what I would do:
But this will require me to update the function every time.
With pure routines, this is an almost impossible attempt.
Since DO doesn't have a differentiator between calling a function or procedure, internal or public or just looping [ do {} while ]
If you do it inside a class you have all this information on functions and procedures in %Dictionary.*
So you can define exactly what you search. And using the code generator you may even do it at compile time.
%Compiler package can do that but it's not supported.
menu.mac
ROUTINE menu menu(routine) { Set rtn = ##class(%RoutineMgr).%OpenId(routine_".mac") Quit:'$IsObject(rtn) Set menu = "" While 'rtn.Code.AtEnd { Set line = rtn.Code.ReadLine() Continue:$Char(9,32,35)[$Extract(line) Continue:line'[" ; " Set label = $Piece($Piece(line, " "), "(") Set title = $Piece(line, " ; ", 2, *) Set menu = menu _ $Listbuild($Listbuild(label, title)) } Quit menu } asLine(menu, pos) public { Set menuItem = $Listget(menu, pos) Quit:menuItem="" """""" Set $Listbuild(label,title) = menuItem Quit "$Char(13,10)_""" _ $Justify(pos, 4) _ ". " _ title_ """" }
menu.inc
ROUTINE menu [Type=INC] #Execute Set menu = $$^menu(rtname) Write !,"--------Menu---------" write ##Expression($$asLine^menu(menu,$Increment(menuLineNum))) write ##Expression($$asLine^menu(menu,$Increment(menuLineNum))) write ##Expression($$asLine^menu(menu,$Increment(menuLineNum))) write ##Expression($$asLine^menu(menu,$Increment(menuLineNum))) write ##Expression($$asLine^menu(menu,$Increment(menuLineNum))) write ##Expression($$asLine^menu(menu,$Increment(menuLineNum))) write ##Expression($$asLine^menu(menu,$Increment(menuLineNum))) write ##Expression($$asLine^menu(menu,$Increment(menuLineNum))) write ##Expression($$asLine^menu(menu,$Increment(menuLineNum))) write ##Expression($$asLine^menu(menu,$Increment(menuLineNum))) write ##Expression($$asLine^menu(menu,$Increment(menuLineNum))) write ##Expression($$asLine^menu(menu,$Increment(menuLineNum))) write ##Expression($$asLine^menu(menu,$Increment(menuLineNum))) write ##Expression($$asLine^menu(menu,$Increment(menuLineNum))) write ##Expression($$asLine^menu(menu,$Increment(menuLineNum))) write ##Expression($$asLine^menu(menu,$Increment(menuLineNum))) write ##Expression($$asLine^menu(menu,$Increment(menuLineNum))) write ##Expression($$asLine^menu(menu,$Increment(menuLineNum))) Write !! do { Write $Char(13),"Option? ",*27,"[0K" Read menuOption Quit:menuOption="" Quit:"qQ"[$Extract(menuOption) Quit:$Listget(menu,+menuOption)'="" } while 1 Write ! if (+menuOption) { Set label = $Listget($Listget(menu, menuOption)) Do @label } Quit
And some routine which will have to have menu
ROUTINE test #; just include menu, at the place where you need it #Include menu quit task1 ; Task 1 Write !,"Some work 1" quit task2 ; Task 2 Write !,"Some work 2" quit task3 ; Task 3 Write !,"Some work 3" quit task4 ; Task 4 Write !,"Some work 4" quit task5 ; Task 5 Write !,"Some work 5" quit task6 ; Task 6 Write !,"Some work 6" quit task7 ; Task 7 Write !,"Some work 7" quit task8 ; Task 8 Write !,"Some work 8" quit task9 ; Task 9 Write !,"Some work 9" quit task10 ; Task 10 Write !,"Some work 10" quit
and call it
USER>d ^test --------Menu--------- 1. Task 1 2. Task 2 3. Task 3 4. Task 4 5. Task 5 6. Task 6 7. Task 7 8. Task 8 9. Task 9 10. Task 10 Option? 1 Some work 1
Menu list changed after compile, but routine should be saved as MAC.
The final INT code contains the generated menu.
Nice done Dmitriy!
I hardened your inc routine a bit so as not to change the variables in the mac routine:
ROUTINE menu [Type=INC]
Going back to good old fashioned MUMPs this works for INTs:
n NSP,EXT,VER,ROU,LAST,LINE
; NSP = namespace
; EXT = extension/type of routine e.g. INT
; VER = version, default is zero
; ROU = routine name
; LAST = last line or routine i.e. number of lines
s ROU=$g(rtn)
i ROU="" u 0 w !,"No routine reference supplied" q
s NSP="%SYS",EXT="INT",VER=0,LINE=""
s ROU=$g(rtn)_"."_EXT_"."_VER
; get last line
s LAST=$$LENGTH^%R(ROU,NSP)
i LAST>0 d
. f i=1:1:LAST d
. . s LINE=$$LINE^%R(ROU,i,NSP)
. . ; check first character of line against ASCII value
. . ; ignore anything below 48 which is zero
. . i $a($e(LINE,1))>47 u 0 w !,i,?10,LINE
q