Merge branch 'master' of ssh://github.com/mthom/scryer-prolog

This commit is contained in:
Mark
2023-09-25 16:09:20 -06:00
3 changed files with 131 additions and 19 deletions

View File

@@ -14,6 +14,7 @@ jobs:
build-test:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- { os: windows-latest, rust-version: stable, shell: 'msys2 {0}', target: 'x86_64-pc-windows-gnu'}

View File

@@ -9,6 +9,7 @@
:- module(pio, [phrase_from_file/2,
phrase_from_file/3,
phrase_from_stream/2,
phrase_to_file/2,
phrase_to_file/3,
phrase_to_stream/2
@@ -17,16 +18,30 @@
:- use_module(library(dcgs)).
:- use_module(library(error)).
:- use_module(library(freeze)).
:- use_module(library(iso_ext), [setup_call_cleanup/3, partial_string/3]).
:- use_module(library(lists), [member/2, maplist/2]).
:- use_module(library(gensym)).
:- use_module(library(iso_ext), [
bb_get/2, bb_put/2, setup_call_cleanup/3, partial_string/3, partial_string_tail/2
]).
:- use_module(library(lists), [append/3, length/2, member/2, maplist/2]).
:- use_module(library(charsio), [get_n_chars/3]).
:- meta_predicate(phrase_from_file(2, ?)).
:- meta_predicate(phrase_from_file(2, ?, ?)).
:- meta_predicate(phrase_from_stream(2, ?)).
:- meta_predicate(phrase_to_file(2, ?)).
:- meta_predicate(phrase_to_file(2, ?, ?)).
:- meta_predicate(phrase_to_stream(2, ?)).
%% phrase_from_stream(+GRBody, +Stream)
%
% True if grammar rule body GRBody covers the contents of the stream,
% represented as a list of characters.
phrase_from_stream(GRBody, Stream) :-
stream_to_lazy_list(Stream, Ls),
phrase(GRBody, Ls).
%% phrase_from_file(+GRBody, +File)
%
% True if grammar rule body GRBody covers the contents of File,
@@ -48,24 +63,120 @@ phrase_from_file(NT, File, Options) :-
member(Type, [text,binary])
; Type = text
),
setup_call_cleanup(open(File, read, Stream, [reposition(true)|Options]),
( stream_to_lazy_list(Stream, Xs),
phrase(NT, Xs) ),
close(Stream))
setup_call_cleanup(
open(File, read, Stream, Options),
phrase_from_stream(NT, Stream),
close(Stream)
)
).
% How many chars to read from stream and buffer in each step
chars_to_read(4096).
stream_to_lazy_list(Stream, Xs) :-
stream_property(Stream, position(Pos)),
freeze(Xs, reader_step(Stream, Pos, Xs)).
stream_to_lazy_list(Stream, Ls) :-
get_stream_buffer_position(Stream, Pos),
freeze(Ls, render_step(Stream, Pos, Ls)).
reader_step(Stream, Pos, Xs0) :-
set_stream_position(Stream, Pos),
( at_end_of_stream(Stream)
-> Xs0 = []
; get_n_chars(Stream, 4096, Cs),
partial_string(Cs, Xs0, Xs),
stream_to_lazy_list(Stream, Xs)
render_step(Stream, Pos, Ls) :-
set_stream_buffer_position(Stream, Pos),
( buffer_at_end_of_stream(Stream) ->
Ls = []
; chars_to_read(CharsToRead),
buffer_get_n_chars(Stream, CharsToRead, Chars),
partial_string(Chars, Ls, Ls0),
stream_to_lazy_list(Stream, Ls0)
).
buffer_at_end_of_stream(Stream) :-
stream_bufferids(Stream, _, BufferPosId, _),
bb_get(BufferPosId, Pos),
Pos = eof.
get_stream_buffer_position(Stream, Pos) :-
stream_bufferids(Stream, _, BufferPosId, _),
bb_get(BufferPosId, Pos).
set_stream_buffer_position(Stream, Pos) :-
stream_bufferids(Stream, _, BufferPosId, _),
bb_put(BufferPosId, Pos).
buffer_get_n_chars(Stream, N, Chars) :-
stream_bufferids(Stream, BufferId, BufferPosId, BufferLenId),
buffer_prepare_for_n(Stream, BufferId, BufferPosId, BufferLenId, N),
bb_get(BufferId, Buffer),
bb_get(BufferPosId, BufferPos),
( BufferPos = eof ->
Chars = []
; string_get_n_chars(Buffer, BufferPos, N, Chars),
length(Chars, NChars),
( NChars = 0 ->
BufferPos1 = eof
; BufferPos1 is BufferPos + NChars
),
bb_put(BufferPosId, BufferPos1)
).
buffer_prepare_for_n(Stream, BufferId, BufferPosId, BufferLenId, N) :-
bb_get(BufferPosId, BufferPos),
bb_get(BufferLenId, BufferLen),
( BufferLen < BufferPos + N ->
bb_get(BufferId, Buffer),
(
( var(Buffer) ->
BufferTail = Buffer
; partial_string_last_tail(Buffer, BufferTail)
) ->
( at_end_of_stream(Stream) ->
BufferTail = [],
bb_put(BufferId, Buffer)
; chars_to_read(CharsToRead),
get_n_chars(Stream, CharsToRead, Chars),
length(Chars, NChars),
partial_string(Chars, BufferTail, _),
bb_put(BufferId, Buffer),
BufferLen1 is BufferLen + NChars,
bb_put(BufferLenId, BufferLen1),
buffer_prepare_for_n(Stream, BufferId, BufferPosId, BufferLenId, N)
)
; true
)
; true
).
partial_string_last_tail(PartialString, PartialStringTail) :-
partial_string_tail(PartialString, PartialStringTail0),
( var(PartialStringTail0) ->
PartialStringTail = PartialStringTail0
; partial_string_last_tail(PartialStringTail0, PartialStringTail)
).
string_get_n_chars(String, Pos, N, Chars) :-
'$skip_max_list'(_, Pos, String, String1),
'$skip_max_list'(N1, N, String1, _),
length(Chars, N1),
append(Chars, _, String1).
stream_bufferids(Stream, BufferId, BufferPosId, BufferLenId) :-
( bb_get(streams_buffers, _) ->
true
; bb_put(streams_buffers, [])
),
bb_get(streams_buffers, StreamsBuffers),
( member(
stream_buffer(Stream, BufferId, BufferPosId, BufferLenId),
StreamsBuffers
) ->
true
; gensym(buffer, BufferId),
gensym(buffer_pos, BufferPosId),
gensym(buffer_len, BufferLenId),
bb_put(
streams_buffers,
[stream_buffer(Stream, BufferId, BufferPosId, BufferLenId)|StreamsBuffers]
),
bb_put(BufferId, _),
bb_put(BufferPosId, 0),
bb_put(BufferLenId, 0)
).
%% phrase_to_stream(+GRBody, +Stream)

View File

@@ -132,7 +132,7 @@ macro_rules! hexadecimal_digit_char {
#[macro_export]
macro_rules! layout_char {
($c: expr) => {
$crate::char_class!($c, [' ', '\n', '\t', '\u{0B}', '\u{0C}'])
$crate::char_class!($c, [' ', '\r', '\n', '\t', '\u{0B}', '\u{0C}'])
};
}