Example of an .exe compiled by swi-prolog that can accept arguments
Asked Answered
J

2

5

I would appreciate your help after struggling 4 hours to the problem:

I need to create an exe file (on windows) from prolog script. For example, main.pl has inside:

day(monday).
day(tuesday).
day(wednesday).
day(thursday).
day(friday).    % let's stop here

I would like to compile this script, produce prog.exe file and then be able to do the following runs:

$ prog.exe --term sunday
 false
$ prog.exe --term monday
 true
$ prog.exe --goal day(friday)
 true
$ prog.exe --goal fun(foo)
 false

if flags are difficult non flag version with input goals will be also very helpful for me.

I tried to read compiling pages on swi-prolog page but got confused. I can not print anything on the standard output stream. Also I did not understand how flags works.

tried the example they have on swi-prolog site but I dont understand why nothing is printed. With the below script I can create exe file with command save(prog), but then while running prog.exe nothing is printed out.

:- ['main'].

main :-
        pce_main_loop(main).

main(Argv) :-
        write('hello word').

save(Exe) :-
        pce_autoload_all,
        pce_autoload_all,
        qsave_program(Exe,
                      [ emulator(swi('bin/xpce-stub.exe')),
                        stand_alone(true),
                        goal(main)
                      ]).
Joo answered 8/2, 2013 at 2:24 Comment(1)
My initial problem was to do the abovementioned task for the prolog script using xpce gui.Joo
C
4

I will refer to eight_puzzle.pl, the module I posted for another answer as test case. Then I write a new file (say p8.pl) with a test argument line usage, compile and run

:- use_module(eight_puzzle).

go :-
    current_prolog_flag(argv, Argv),
    writeln(argv:Argv),
    (   nth1(Test_id_flag, Argv, '--test_id'),
        Test_id_pos is Test_id_flag+1,
        nth1(Test_id_pos, Argv, Id)
    ->  atom_concat(test, Id, Func)
    ;   Func = test1
    ),
    forall(time(call(eight_puzzle:Func, R)), writeln(R)).

to compile I used the documentation section 2.10.2.4 from 2.10 Compilation

swipl -O --goal=go --stand_alone=true -o p8 -c p8.pl

and to run with specified option:

./p8 --test_id 0

I'm running Ubuntu, but there should be no differences on Windows.

argv:[./p8,--test_id,0]
% 4,757 inferences, 0.003 CPU in 0.003 seconds (100% CPU, 1865842 Lips)
[4,3,6,7,8]
% 9,970 inferences, 0.005 CPU in 0.005 seconds (100% CPU, 2065656 Lips)
[4,3,6,7,4,5,8,7,4,5,8,7,4,5,8]
...

HTH

Champac answered 8/2, 2013 at 10:9 Comment(2)
Thank you for your solution it works. Just to add some details: the solution doesn't work in case of scripts using gui components from xpce. For more details see: swi-prolog.org/FAQ/MakeExecutable.html or swi-prolog.org/FAQ/MakeExecutable.html for windows. @CapelliC's example helped me to know how to use Argv variable correctly, that was the point I was doing wrongly before.Joo
For running on Windows: the swipl command line gets you p8.exe which depends on the various DLL's which are installed with swipl.exe. It will work as advertised if (a) swipl folder is in your PATH (b) you copy these DLLs into the folder where p8 is sitting, etc.Microdot
A
6

SWI-Prolog contains the optparse library which you can use for commandline arguments parsing.

opts_spec(
    [ [opt(day), type(atom),
        shortflags([d]), longflags(['term', 'day']),
        help('name of day')]

    , [opt(goal),
        shortflags([g]), longflags([goal]),
        help('goal to be called')]
    ]
).

% days
day(monday).
day(tuesday).
day(wednesday).
day(thursday).
day(friday).


main :-
    opts_spec(OptsSpec),
    opt_arguments(OptsSpec, Opts, _PositionalArgs),
    writeln(Opts),
    memberchk(day(Day), Opts),
    memberchk(goal(Goal), Opts),
    (nonvar(Day) -> call_call(day(Day), Result), writeln(Result) ; true),
    (nonvar(Goal) -> call_call(Goal, Result), writeln(Result) ; true),
    halt.

call_call(Goal, true) :-
    call(Goal), !.

call_call(_Goal, false).

You can compile and use the above code like this. (Tested only on Ubuntu, sorry, I cannot help regarding Windows.)

$ swipl -o day.exe -g main -c day.pl

$ ./day.exe --term monday
[goal(_G997),day(monday)]
true

$ ./day.exe --goal "day(sunday)"
[day(_G1009),goal(day(sunday))]
false
Antisemite answered 13/2, 2013 at 13:24 Comment(0)
C
4

I will refer to eight_puzzle.pl, the module I posted for another answer as test case. Then I write a new file (say p8.pl) with a test argument line usage, compile and run

:- use_module(eight_puzzle).

go :-
    current_prolog_flag(argv, Argv),
    writeln(argv:Argv),
    (   nth1(Test_id_flag, Argv, '--test_id'),
        Test_id_pos is Test_id_flag+1,
        nth1(Test_id_pos, Argv, Id)
    ->  atom_concat(test, Id, Func)
    ;   Func = test1
    ),
    forall(time(call(eight_puzzle:Func, R)), writeln(R)).

to compile I used the documentation section 2.10.2.4 from 2.10 Compilation

swipl -O --goal=go --stand_alone=true -o p8 -c p8.pl

and to run with specified option:

./p8 --test_id 0

I'm running Ubuntu, but there should be no differences on Windows.

argv:[./p8,--test_id,0]
% 4,757 inferences, 0.003 CPU in 0.003 seconds (100% CPU, 1865842 Lips)
[4,3,6,7,8]
% 9,970 inferences, 0.005 CPU in 0.005 seconds (100% CPU, 2065656 Lips)
[4,3,6,7,4,5,8,7,4,5,8,7,4,5,8]
...

HTH

Champac answered 8/2, 2013 at 10:9 Comment(2)
Thank you for your solution it works. Just to add some details: the solution doesn't work in case of scripts using gui components from xpce. For more details see: swi-prolog.org/FAQ/MakeExecutable.html or swi-prolog.org/FAQ/MakeExecutable.html for windows. @CapelliC's example helped me to know how to use Argv variable correctly, that was the point I was doing wrongly before.Joo
For running on Windows: the swipl command line gets you p8.exe which depends on the various DLL's which are installed with swipl.exe. It will work as advertised if (a) swipl folder is in your PATH (b) you copy these DLLs into the folder where p8 is sitting, etc.Microdot

© 2022 - 2024 — McMap. All rights reserved.