Get-signature

GregTomkins

Active Member
I want to be able to dynamically discover the parameters of an external .P at run-time. In other words, I want to be able to run GET-SIGNATURE on a .P that hasn't yet been (and may never be) run persistently. This is analogous to reflection in Java. Has anyone figured out a way to do this?
 
I've not really thought about this very deeply, but:

Reflection in Java works with the class loader - you must load the class in order to work with reflection in the first place. The same principle would be true for a Progress procedure except that it is not derived from a class like an object. Therefore I don't see any other way than to run the procedure persistently in order to "discover" it at run time. The bad thing about this approach is that the code in the main block of the procedure will always be executed and therefore code might get executed that you don't need - or even worse may not be executed at all.

Heavy Regards, RealHeavyDude.
 
If the code is shipped as p code then I guess you could parse the file and work it out, but long-winded and relies on shipping p code.
 
Even for objects, reflection is not a strong suit for ABL. I wouldn't hold your breath on any enhancements for .ps.

But, perhaps you should tell us *why* you want to do this. I suspect there is a better way.
 
Actually, you can parse the .R code itself... it's not difficult, and it is arguably simpler and more reliable than parsing .P. However, it is also version-dependent.

The class loader in Java does not require any knowledge of the class to work, whereas running a .P to get its parameters requires knowing the parameters in the first place, which kind of defeats the purpose, hence the question.

Anyways, thank you all for confirming that there are no new or near-future plans to address this in 4GL.
 
The obvious place to hope for such an enhancement would be the RCODE-INFO system handle.

Extending the existing GET-SIGNATURE() method to work with RCODE-INFO would seem like a good way to get what you are after.
 
In the work-around corner you could put mini signature wrappers around code that needs to provide signatures:

normal.p
Code:
&IF DEFINED( GET-SIGNATURE ) &THEN
   PROCEDURE MainBlock:
&ENDIF


DEFINE INPUT PARAMETER i_cfoo AS CHARACTER   NO-UNDO.


&IF DEFINED( GET-SIGNATURE ) &THEN
   END PROCEDURE.
   RETURN THIS-PROCEDURE:GET-SIGNATURE( "MainBlock":U ).
&ELSE


      /* rest of code */


&ENDIF

normal.gs.p

Code:
&SCOPED-DEFINE GET-SIGNATURE
{normal.p}

If you need the signature of normal.p you then run normal.gs.p:

Code:
RUN normal.gs.p.

MESSAGE RETURN-VALUE VIEW-AS ALERT-BOX.
 
The problem is, we have hundreds of .P's that we want to do this too, and we don't want to touch any of them.

TamHas, these are generally reports, the running of which get managed by a 'report runner' that handles all sorts of gory details, but first needs to know their parameters. We achieve this today with a little wrapper in front of the real program that tells us its parameters. This is simple and works but has the fatal (IMHO) flaw that it forces us to repeat all the parameter details thus violating the DRY principle which I, personally, hold sacred above everything (beyond the damn thing actually working, and of course my paycheque).

TomB, yes, exactly, RCODE-INFO is not living up to its full potential !! Apparently not even in the most modern, non-obsolete and supported versions !!
 
I actually think that having a processing part of a report and a separate UI part of the report for gathering parameters is a useful structure. There are a bunch of thing one might want to do in the UI - suggestive layout, dependencies, combo-boxes of options, helpful hints, special pre-processing, whatever -- that would appropriately go in that front end and do not need to be in the report body. In fact, the parameters supplied by the user and the parameters supplied to the report don't need to be the same! So, even if you could do it, I don't know that you should.
 
How many parameters do these .p's have? You could probably brute force attack the parameters with the dynamic call object. Not sure about the speed, so it could be a good idea to store the results somewhere for future runs.

This would not work since you do not have any info on the names of the parameters - which I presume are necessary for knowing what to pass. Also the data types would be a bit of a guess since Progress does a bit of auto-converting of data types.
 
Your idea does work, depending on the requirements. I've done something similar to run external programs that have a small number of possible signatures, where each signature determines the version of the api. For instance version 1 had 2 parameters, version 2 added a 3rd parameter. So once you know it takes 2 or 3 parameters that's good enough.

If it's to the point where you have to know the names of the parameters that's not going to work. Easiest solution then is to use an xml file or something to map the program name to the calling signature.
 
In fact, by replacing every parameter set with a single object, where the object is then queried for the parameter values, every report can have the same signature.

But, it is still something of a hack.
 
Back
Top