Setting up development environment for swi prolog foreign predicates in Rust

Hi @matthijs

Could you offer a description how you set up developing a rust based foreign predicate – what IDE you are using and the like – so that one can efficiently develop and visually debug code on both sides – in Prolog and Rust?

Also, I happen to use Eclipse with the PDT plugin for Prolog, do you know if Eclipse can be used as well?

thanks,

Dan

1 Like

Hi there,

I’m probably not really the right person to ask, as my setup tends to be a bit spartan :).

I use emacs both for rust and for prolog development. For rust, i have the rustic package installed which does basic incremental compilation stuff, with red squiggly underlining in emacs of code that errors during compiles. For prolog, I use a prolog-mode package of murky origin that I once copied from @gavin.mendel.gleason, which is good enough for running SWI-Prolog inside emacs, evaluating buffers, recompiling files, having a REPL, etc. Maybe @gavin.mendel.gleason can provide some more details there.

I believe vscode is much more popular in the rust world for easy development, so you may want to look there instead. It’s been about a decade since I last touched eclipse so I’m definitely of no help there.

I’m not very experienced with debugging, let alone graphical debugging. I have however in the past used gdb to debug SWI-Prolog modules, and found that after loading your module you can simply set breakpoints in rust code normally. I’m sure it is like that for every debugger.

Sorry I cannot be of more help here.

Thank you.

My ideal development environment is an IDE with visual debugging – and when I am using two language side by side - e.g. swi prolog and rust – to have both source code visible in two windows in the IDE (typically, each on a separate monitor) – and i can step through the code across the languages.

If for example, if I would connect both programs via some messaging interface (e.g. websockets), then this can be achieved quite naturally: i could use vs.code to visually debug rust (with vs.code a preferred IDE for Rust), and eclipse PDT to run swi-prolog.

However, when this should be a true foreign predicate – i don’t know whether and how this could be configured.

The only way I see debugging possible is to resort to print statements to see (somewhere) what happens during binary execution – which I hope is an approach I don’t need to fall back to …

Dan

Right, i noticed, but how does one load a debug image of rust code in vs code into swi prolog running in the visual debugger in exclipse

Thanks.

I will check it out …

Thanks for checking – i haven’t tried it out …

My assumption was that it should be as fast as C/C++ – So, this is quite disappointing.

Edit:

There is apparently a bit of overhead for certain reference structures due to reference counting … which, i guess a C/C++ solution would need to also have, given similar needs.

printf is the only true debugging statement. :wink:

But seriously, I find that trace (or gtrace) is useful for understanding how some code works, as long as it doesn’t have complex data structures … at that point, strategic use of print (or debug/3 or similar) plus portray/1 is my go-to tool; sometimes using wrap_predicate/4.

One of these days, I’m going to write a conditional form of spy/1; but for now, adding a clause of the form

foo(X,Y,Z) :- ( some_condition(X,Y,Z) -> format('~q~n', [foo(X,Y,Z)]), fail ).

mostly does the job, even if it does require restarting the program.

PS: Is there a nice way to restart a goal that throws an exception? If a goal fails, it’s easy to do “r”, but there doesn’t seem to be the equivalent for an exception.

Thanks Peter,

I, i guess, I am a visual thinker – and like to see program step “state” in color and spatially described.

If needed, I also create visualization of complex data structures, so i can see what the program does, including context.

And i use from time to time such conditional expressions to start a (graphical) trace …

Dan

You don’t need WSL to get a rust install. There’s a perfectly fine installer for windows which you can get through rustup.rs. Not just windows actually, but all the major operating systems.

You’d also generally not directly compile rust files but use cargo, the package builder/management tool that comes with standard rust installs.

Rust’s debug builds are much, much slower than release builds:

$ rustc elevator.rs 
$ ./elevator 
elevator(100)=100
time=540
time=514
$ rustc -O elevator.rs 
$ ./elevator 
elevator(100)=100
time=0
time=0

wow, 0 ms! Unfortunately, that’s cause the rust compiler actually spots that the result of that elevator function is completely unused so the call just gets optimized away. I’ve not been able to mangle that elevator test in a way to prevent the optimizing-out in the five minutes I tried to do so. Just run your benchmarks of actual production code with optimizations enabled.

@grossdan, it may be helpful to know what OS you’re trying to get this to work on. I personally just do all my development on linux, and on linux, I don’t need to do anything special at all to get debug symbols from the rust module into my debugger. Any debugger I tried is just able to pick up on them if they’re there, which is for any build that doesn’t have optimizations, or release builds for which I explicitely enabled the debug symbols. I just need to start swipl in a debugger and since swipl ends up calling into my module, breakpoints and such will just work.

Thanks.

Perhaps, that’s my missing piece of knowledge – somehow i thought that trace runs on top of the VM and once a VMI calls external code its under the radar of the debugger.

I will give things a try shortly – and will understand things better.

re: OS

I am developing on Windows mainly because my broader work environment is windows based … although, once i start developing a foreign predicate I will likely need to switch to Ubuntu.