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.
Comments
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]
#Execute set menuLineNum=0
do myMenu()myMenu(){
Set menu = $$^menu($zname)
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
}
}Going back to good old fashioned MUMPs this works for INTs:
CALLS(rtn) ;
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