Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MAIN subroutine

Scenario

Imagine that you have a module X whose functionalities are available to the user through a Command Line Interface. Such module doesn't do much in and of itself but it allows for other people to create plugin-like modules they can hook-up to module X. Ideally, the plugins could be used through X's CLI.

Thus my question:

What do you need to do in order to hook-up whatever functionality a plugin might provide to X's CLI?

This means the plugin would need to provide some structure describing the command, what needs to be called and hopefully a usage message for the plugin. Therefore, when you run X's CLI, the plugin's command and help message shows up in the regular X's CLI's help message.

Example

main.p6:

use Hello;
use Print;

multi MAIN('goodbye') {
    put 'goodbye'
}

lib/Hello.pm6:

unit module Hello;

our %command =  %(
    command => 'hello',
    routine => sub { return "Hello" },
    help    => 'print hello.'
);

lib/Print.pm6:

unit module Print;

our %command =  %(
    command => 'print',
    routine => sub { .print for 1..10 },
    help    => 'print numbers 1 through 10.'
);

The program main.p6 is a simplified version of this scenario. I'd like to integrate the information provided by both Hello.pm6 and Print.pm6 through their respective %command variables into two new MAIN subs in main.p6.

Is this possible? If so, how would I go about achieving it?

like image 716
Luis F. Uceta Avatar asked Jul 15 '19 13:07

Luis F. Uceta


People also ask

What are the two types of subroutine?

There are two types of subroutine: procedures. functions.

What is a subroutine example?

An example is a random number subroutine, available in many languages, that returns a different pseudo-random number each time it is called. The widespread use of subroutines with side effects is a characteristic of imperative programming languages.

What is main program and subroutine?

Main program and subroutine is a style that is fundamentally focused on functions. When presented with a system to model, you break up the overall functionality of the system into a main program and subroutines.

What is subroutine and its types?

Subroutines are program modules which can be called from other ABAP/4 programs or within the same program. Are introduced with form statement & ended with endform statement. you call subroutines from abap program using the perform statements. you can define subroutines in any abap program .


1 Answers

This looks kinda specific for a StackOverflow question, but I will give it a try anyway. There are a couple of issues here. First one is to register the commands as such, so that MAIN can issue a message saying "this does that", and second is to actually perform the command. If both can be known at compile time, this can probably be fixed. But let's see how the actual code would go. I'll just do the first part, and I leave the rest as an exercise.

The first thing is that %command needs somehow to be exported. You can't do it the way you are doing it now. First, because it's not explicitly exported; if it were, you would end up with several symbols with the same name in the outer scope. So we need to change that to a class, so that the actual symbols are lexical to the class, and don't pollute the outer scope.

unit class Hello;

has %.command =  %(
    command => 'hello',
    routine => sub { return "Hello" },
    help    => 'print hello.'
);

(Same would go for Print)

As long as we have that, the rest is not so difficult, only we have to use introspection to know what's actually there, as a small hack:

use Hello;
use Print;

my @packages=  MY::.keys.grep( /^^<upper> <lower>/ );
my @commands = do for @packages -> $p {
    my $foo = ::($p).new();
    $foo.command()<command>
};

multi MAIN( $command where * eq any(@commands) ) {
    say "We're doing $command";
}

We check the symbol table looking for packages that start with a capital letter, followed by other non-capital letter. It so happens that the only packages are the ones we're interested in, but of course, if you would want to use this as a plugin mechanism you should just use whatever pattern would be unique to them. We then create instances of these new packages, and call the command auto-generated method to get the name of the command. And that's precisely what we use to check if we're doing the correct command in the MAIN subroutine, by using the where signature to check if the string we're using is actually in the list of known commands.

Since the functions and the rest of the things are available also from @packages, actually calling them (or giving an additional message or whatever) is left as an exercise.

Update: you might want to check out this other StackOveflow answer as an alternative mechanism for signatures in modules.

like image 111
jjmerelo Avatar answered Oct 10 '22 13:10

jjmerelo