Fixes#2815, see that issue for my investigation.
This is a one-line fix that I'm quite proud of :)
If the topmost query for `run_module_predicate` needs to backtrack,
then before this commit, one of the following two things may happen:
- A dangling OrFrame is read at stack offset 0
- An AndFrame was at stack offset 0 would be read as an OrFrame
This can be seen by either calling `run_module_predicate` with a
throwing predicate (encountering the second scenario) or a failing
predicate (encountering the first scenario), or by running the following
in the REPL, which triggers a `throw/1` within the error handler, propagating
it all the way up (and encountering the second scenario):
```prolog
?- current_output(S), open(stream(S), write, S0, [type(binary)]).
```
Currently, `Stack` is not equipped with tools to detect this incorrect
behavior, so it would instead try to read an OrFrame at offset 0, which
triggers UB, since transmuting between AndFramePrelude and OrFramePrelude
isn't legal.
In practice, since `AndFramePrelude` is smaller, the later fields of
`OrFramePrelude` would read from the cells following the `AndFramePrelude`,
and would contain nonsensical data, triggering the panic that led to
my investigation in #2815 and that is fairly reliable to witness.
Surprisingly, this wouldn't happen with `run_query`, which led me to
look at how they operate differently. It turns out that `run_query`
inserts an OrFrame at offset 0, which covers both problematic scenarios.
The fix is thus to simply add a call to `Machine::allocate_stub_choice_point`
in `run_module_predicate` :)
Fixes#2772.
The current implementation of `rnd_i` incorrectly casts `f` (an `f64`)
into an `i64`, before casting it into an `Integer`.
This fixes that issue by using `Integer::try_from(f)` instead,
and failing if `f` is infinite or NaN.
A fixme is left for a future PR to properly handle the resulting errors
in floor/1 and friends (right now they can only be triggered through FFI).
This fixes#2725, by making it so that `strip_module(Pred, M, P), call(M:P)`
doesn't throw an `instanciation_error` when `Pred` isn't in the form `module:predicate`.
Now, `strip_module(hello, M, P)` will call `load_context(M)`, which unifies `M`
with the topmost module (or `user`).
Two new test cases are added: issue2725.pl, which tests the minimal case id(X) --> X.
and the strip_module(P, M, _), call(M:P) scenario, and module_resolution,
which tests the behavior of strip_module in a few scenarios.
"returns" is not used in this way in logic programming. "return"
suggests that something went away and is now coming back, but this is
never the case in these situations. The arguments may be variables or
also fully known at the time of the call in most cases.
This reverts commit e185b626bd.
This change is now no longer needed, and the underlying issue is
apparently somewhere else entirely. See the description at:
https://github.com/mthom/scryer-prolog/issues/2732
Current master behaves differently from Scryer as it was at
099d9aaca6 (i.e., preceding
the commit that is now being reverted), even on the same file.
For an example, see:
dd41176b97
Scryer now works as expected, and compatibly with SICStus. We still
need to find out what fixed the root cause of this issue.
Some DCG constructs aren't supported and can't be expanded, here we
remove offending DCG rule and don't compile it at all – in a similar
fashion to what we do when incorrect goal was found – whole predicate
isn't getting compiled.
Fixes#2675
Examples:
?- portray_clause(((+) :- a=b,(-))).
(+) :-
a=b,
(-).
true.
?- portray_clause((a :- (b :- c))).
a :-
(b:-c).
true.
This addresses #2715.
Currently, more round brackets than needed are emitted. Ideally, a
better approach to solve the issue here and also in toplevel.pl is
found in the future.
This addresses #2713. Many thanks to @notoria for reporting this
excellent case!
Example:
?- portray_clause(A = @).
A= @ .
true.
At other positions the now inserted space is unnecessary, as in:
?- portray_clause((head:- @,b)).
head :-
@ ,
b.
true.
The toplevel has a similar issue:
?- C = # ; false.
C = # |<-- cursor is here; redundant space after #
There may be a way to solve this issue for all cases like this.