mthom / scryer-prolog

A modern Prolog implementation written mostly in Rust.
BSD 3-Clause "New" or "Revised" License
2.04k stars 118 forks source link

Windows scryer-prolog picking up .scryerrc? #2046

Open dougransom opened 1 year ago

dougransom commented 1 year ago

I would have expected an error or warning on startup that scryer-prolog isn't loading an .scryerrc file, or that it is invalid.

PS C:\Users\doug\code\life> cat ~/.scryerrc
gjsfd;gkdsf; dfgsfdgk
:- use_module(library(lists)).
:- use_module(library(dcgs)).
:- use_module(library(reif)).
:- use_module(library(clpz)).
:- write("hello").
hello("World").
:- set_prolog_flag(occurs_check, error).

hello("World").
:- set_prolog_flag(occurs_check, error).
PS C:\Users\doug\code\life> scryer-prolog.exe
?- hello(X).
   error(existence_error(procedure,hello/1),hello/1).
?-  

I would propose a feature scryer-prolog --verbose cargo:0.9.2, ~=c:\users\doug preload=c:\users\doug.scryerrc contains:

:- use_module(library(lists)).
:- use_module(library(dcgs)).
:- use_module(library(reif)).
:- use_module(library(clpz)).
:- write("hello").
hello("World").
:- set_prolog_flag(occurs_check, error).

Also, environment and command line overrides for the .scryerrc name and location.

More info:

PS C:\Users\doug\code\life> C:\users\doug\code\scryer-prolog\target\debug\scryer-prolog.exe -v
v0.9.2-94-g9114c982
PS C:\Users\doug\code\life>

and the folder appears correct for .scryerrc

PS C:\Users\doug\code\life> ls ~/.scr*    

    Directory: C:\Users\doug

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---          2023-09-26  9:32 AM           1254 .scryer_history
-a---          2023-09-26  9:23 AM            452 .scryerrc
triska commented 1 year ago

On OSX, with the ~/.scryerrc you posted, I get:

$ scryer-prolog
   error(permission_error(modify,static_procedure,(;)/2),load/1).

Note that an error occurs when loading the file. Maybe this error message is not correctly shown on Windows? Could you please try to construct a smaller example that also exhibits unintended behaviour?

For example, with ~/.scryerrc consisting of:

:- initialization(write_term("hello!", [double_quotes(true)])).

I get:

$ scryer-prolog
"hello!"
?- 

Can you reproduce this?

dougransom commented 1 year ago

No, that is why i tried putting syntax errors at the beginning. I get:

PS C:\Users\doug\code\life> scryer-prolog.exe 
?-

which makes me think scryer is failing to open the file on windows.

Can you please point me to the rust file that would load this file, and where it determines where my home folder is?

The .scryer_history seems to be updated correctly.

triska commented 1 year ago

.scryerrc is loaded by toplevel.pl, please see this section of the code:

https://github.com/mthom/scryer-prolog/blob/0bfb08e464a16407ac899935961d84a9f3c925e2/src/toplevel.pl#L18

I hope you can use this as a starting point for finding out more information about this issue!

dougransom commented 1 year ago

I am probably missing something required to run load_scryerrc or print_help?

PS C:\Users\doug> scryer-prolog.exe
?- load_scryerrc.
   error(existence_error(procedure,load_scryerrc/0),load_scryerrc/0).
?- print_help.
   error(existence_error(procedure,print_help/0),print_help/0).
?-

if you can let me know what to type at the ?- I can probably make some progress.

triska commented 1 year ago

Please try to track down the problem systematically: As a starting point, you can copy the definition of load_scryerrc/0 and put it in your own Prolog file, where you can also load the libraries that are needed to run the code.

On this custom definition, you can use the predicates from library(debug), notably ($)/1, to trace the execution of each goal that occurs in the definition of the predicate.

However, in this concrete case, debugging and interacting is complicated by the fact that a few predicates (namely exactly those starting with $...) that occur in the definition are internal predicates that cannot be debugged in this way, and also cannot be called interactively on the toplevel. To test them interactively, you have to define your own auxiliary predicates that you can invoke on the toplevel.

For example, we can define:

hd(HD) :- '$home_directory'(HD).

And in this way ask Scryer about the home directory:

?- hd(HD).

In your case, what is the answer to this query?

In this way, you can systematically find out more about the situation on your platform.

dougransom commented 1 year ago
?- X="C:/Users/doug/.scryerrc",atom_chars(Y,X),file_exists(X),use_module(Y).
   X = "C:/Users/doug/.scry ...", Y = 'C:/Users/doug/.scryerrc'.
?-

doesn't make available the predicates in .scryerrc . makes me suspect use_module/1 perhaps doesn't load files with a full path.

This is also suspicious though. I don't know what to make of it.

 X="C:\\Users\\doug\\.scryerrc",atom_chars(Y,X),file_exists(X),use_module(library(Y)).

   error(existence_error(source_sink,library('C:\\Users\\doug\\.scryerrc')),load/1).
?-
PS C:\Users\doug\code\life> ls C:\Users\doug\.scryerrc | Format-Table 

    Directory: C:\Users\doug

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---          2023-09-27  7:45 PM            250 .scryerrc

changing slashes doesn't help.

?- X="C:/Users/doug/.scryerrc",atom_chars(Y,X),file
_exists(X),use_module(library(Y)).
   error(existence_error(source_sink,library('C:/Users/doug/.scryerrc')),load/1).
?-
rujialiu commented 1 year ago

It looks like most scryer-prolog devs are not working on windows? I can take a look at this (but no guarantee when) since I work on Windows everyday (but I don't use .scryerrc so I didn't found this issue) @triska

rujialiu commented 1 year ago

I just tried and it looks like my scryer-prolog loads .scryerrc because :- initialization(write_term("hello!", [double_quotes(true)])). prints "hello" successfully, both in Power Shell and plain old cmd.exe. And probably a verbose mode @dougransom proposes is a good idea because if I'm facing this problem I would insert a log of println! to find out what's wrong, but for a non-rust user, it's almost impossible.

rujialiu commented 1 year ago

It looks like @dougransom built that exe himself. Is it possible that something wrong with its build process (because load_scryerrc is not found but it should be bundled)? Maybe some kind of "nightly binary download" can help in this case we can be sure we're testing exactly the same executable. @triska

rujialiu commented 1 year ago

My bad. load_scryerrc is bundled but not exposed. I cannot call it in toplevel either.

dougransom commented 1 year ago

I indeed am using a local build as it has the fix for whitespace.

triska commented 1 year ago

load_scryerrc/0 is local to the module $toplevel, you can invoke it as:

?- '$toplevel':load_scryerrc.

For easier debugging and testing, you can also simply copy its definition to your own program.

dougransom commented 1 year ago

I am giving up on this for now, and on scryer on windows for now also. I don't have the skills to help solve this issue. Seems pretty key that this works though, consider pulling the windows support completely for now - you may be more likely to have aggrevrated users who can't get many examples like those published online by @triska or than fans.

I do think there should be a warning for a nonexistant .sryerrrc since one cannot tell between silent failure and just saving the file as the wrong file name or location.

triska commented 1 year ago

The usefulness of the initialization file is currently also limited by #1775.

If you want, you can as a workaround invoke Scryer Prolog with the -g switch to load any libraries you need, in lieu of .scryerrc.

For instance:

$ scryer-prolog -g 'use_module(library(lists)),use_module(library(format))'
?- maplist(portray_clause, "hello").
h.
e.
l.
l.
o.
   true.

You can add this to a script so that Scryer is always started in this way.

mthom commented 11 months ago

I finally got VS Code working with Scryer in a Windows 11 virtualbox. Looking at it now. file_exists does not work on Windows.. or at least, it cannot find .scryerrc. It can't find hidden files.

EDIT: I was wrong, it can find hidden files! I had my .scryerrc as .scryerrc.txt.

@dougransom I can see you haven't fallen prey to this like I did. You've moved your .scryerrc to C:\Users\doug, so I'm not sure what is happening. Is your home directory pointing elsewhere? @triska pointed out how to use a custom hd/1 (home directory) predicate to print it to a string at the toplevel. To enter it:

$> cargo run
?- [user].
hd(X) :- '$home_directory'(X).
end_of_file.
?- hd(X).
% what is the answer here?

When I do it in my virtualbox Windows, I get:

?- hd(X).
X = "C:\\Users\\Mark".
dougransom commented 9 months ago

PS C:\Users\doug> cargo run error: could not findCargo.tomlinC:\Users\dougor any parent directory. So stuck there, I gather that is some rust issue. Yahk shaving…

I have since downloaded scryer-prolog 0.93, at least a i think i have, as -v reports `PS C:\Users\doug> scryer-prolog.exe -v

126d7bb-modified`.

dougransom commented 9 months ago

On windows there usually isn't a HOME or home_directory environment variable. I did add both to "%UserProfile%", doesn't seem to help loading .scryerrc.

bakaq commented 9 months ago

So stuck there, I gather that is some rust issue. Yahk shaving…

To compile and run Scryer from source, if that is what you were trying to do, you need to clone the repository to some folder and then run cargo run there, not in your home folder.

dougransom commented 1 month ago

It appears the path to the .scryerrc file on windows includes both back and forward slashes. That is part of the problem.

''' ?- hd(X),append(X,"/.scryerrc",F),write(F),file_exists(F),atomchars(FA,F),use module(FA),write(FA),use_module(FA). [C,:,\,U,s,e,r,s,\,d,o,u,g,/,.,s,c,r,y,e,r,r,c]C:\Users\doug/.scryerrc X = "C:\Users\doug", F = "C:\Users\doug/.scry ...", FA = 'C:\Users\doug/.scryerrc'. ?- '''

The other part is whatever errors produced by use_module are not being reported, they are swallowed somewhere in toplevel.

?- atom_chars(F,"c:/users/doug/.scryerrc"),file_exists(F),use_module(library(F)
).
   error(type_error(list,'c:/users/doug/.scryerrc'),can_be/2).
?-

Stuck here.

dougransom commented 1 month ago

So stuck there, I gather that is some rust issue. Yahk shaving…

To compile and run Scryer from source, if that is what you were trying to do, you need to clone the repository to some folder and then run cargo run there, not in your home folder.

I eventually did do that, thanks. Though I copy the binaries to a folder in PATH.

dougransom commented 1 month ago

A little progress.

?- F="c:/users/doug/.scryerrc",file_exists(F),atom_chars(G,F),H=library(G),use_
module(H).
   error(existence_error(source_sink,library('c:/users/doug/.scryerrc')),load/1).
hurufu commented 1 month ago

Does it also fail with backslashes: C:\users\doug.scryerrc? I don't have Windows machine to check it.

dougransom commented 1 month ago
?- F="c:/users/doug/.scryerrc",file_exists(F),atom_chars(G,F),H=library(G)
,loader:open_file(G,Stream).
   F = "c:/users/doug/.scry ...", G = 'c:/users/doug/.scryerrc', H = library('c:/users/doug/.scryerrc'), Stream = '$stream'(0x20da1167e60).
?-
triska commented 1 month ago

@dougransom: Could you please try to trace down the issue by starting from the source code that appears in Scryer Prolog? Please start with the definition of load_scryerrc that appears in toplevel.pl:

https://github.com/mthom/scryer-prolog/blob/0bfb08e464a16407ac899935961d84a9f3c925e2/src/toplevel.pl#L18

Could you please copy and paste this definition to a Prolog file, add $ from library(debug) in front of the goals to obtain a trace of the execution, and then execute the predicate? Thank you a lot!

dougransom commented 1 month ago

Doesn't give much information:

?- consult(foo).
   true.
?- $load_scryerrc.
call:user:load_scryerrc.
exit:user:load_scryerrc.
   true.
?-
dougransom commented 1 month ago

modified load_scryerrc to this, hard coding the path to .scryerrc:

    (  '$home_directory'(HomeDir) ->
       % append(HomeDir, "/.scryerrc", ScryerrcFile),
       ScryerrcFile="c:/users/doug/.scryerrc",
       (  file_exists(ScryerrcFile) ->
          atom_chars(ScryerrcFileAtom, ScryerrcFile),
          catch($use_module(ScryerrcFileAtom), E, $print_exception(E))
       ;  true
       )
    ;  true
    ).

Output:

?- $load_scryerrc.
call:user:load_scryerrc.
call:use_module('c:/users/doug/.scryerrc').
exit:use_module('c:/users/doug/.scryerrc').
exit:user:load_scryerrc.
   true.

Here is my current .scryerrc:

:- initialization(write_term("hello!", [double_quotes(true)])).
fish(X) :- X="Fish".
% hello_rc(X):- initialization(write_term("hello .scryerrrc!", [double_quotes(true)])),X.
% hello_doug(X) : X="Loaded RC".

hello not displayed, fish not in existence.

dougransom commented 1 month ago

It doesn't load .scryerrc at all. Would the intended behavior not to be to load .scryerrc, which in my case would define the fish predicate and write a message to the console?.

It doesn't work at all, errors encountered are not displayed, and I think there is also an issue with forward slashes vs back slashes that even when corrected, doesn't fix the problem.

dougransom commented 1 month ago

I think https://github.com/mthom/scryer-prolog/issues/2530 which may have been recently introduced, is confusing this issue.