## A.19 library(pio): Pure I/O

This library provides pure list-based I/O processing for Prolog, where the communication to the actual I/O device is performed transparently through coroutining. This module itself is just an interface to the actual implementation modules.

### A.19.1 library(pure_input): Pure Input from files

author
  - Ulrich Neumerkel
  - Jan Wielemaker
To be done
  - Provide support for alternative input readers, e.g. reading terms, tokens, etc.
  - Support non-repositioning streams, such as sockets and pipes.

This module is part of `pio.pl`, dealing with pure input: processing input streams from the outside world using pure predicates, notably grammar rules (DCG). Using pure predicates makes non-deterministic processing of input much simpler.

Pure input uses coroutining (freeze/2) to read input from the external source into a list on demand. The overhead of lazy reading is more than compensated for by using block reads based on read_pending_input/3.

[nondet]phrase_from_file(:Grammar, +File)
  Process the content of File using the DCG rule Grammar. The space usage of this mechanism depends on the length of the not committed part of Grammar. Committed parts of the temporary list are reclaimed by the garbage collector, while the list is extended on demand. Here is a very simple definition for searching a string in a file:

      ... --> []|[_],... .

      file_contains(File, Pattern) :-
              phrase_from_file((..., Pattern, ...), File).

      match_count(File, Pattern, Count) :-
              findall(x, file_contains(File, Pattern), Xs),
              length(Xs, Count).

  This can be called as (note that the pattern must be a string (code list)):

      ?- match_count('pure_input.pl', "file", Count).

[nondet]phrase_from_file(:Grammar, +File, +Options)
  As phrase_from_file/2, providing additional Options. Options are passed to open/4, except for `buffer_size`, which is passed to set_stream/2. If not specified, the default buffer size is 512 bytes. Of particular importance are the open/4 options `type` and `encoding`.
phrase_from_stream(:Grammer, +Stream)
  Helper for phrase_from_file/3. This predicate cooperates with syntax_error/3 to generate syntax error locations for grammars.
syntax_error(+Error)`//`
  Throw the syntax error Error at the current location of the input. This predicate is designed to be called from the handler of phrase_from_file/3.
  throws
    `error(syntax_error(Error), Location)`
[det]lazy_list_location(-Location)`//`
  True when Location is an (error) location term that represents the current location in the DCG list.

  Location | is a term `file(Name, Line, LinePos, CharNo)` or `stream(Stream, Line, LinePos, CharNo)` if no file is associated to the stream RestLazyList. Finally, if the Lazy list is fully materialized (ends in `[]`), Location is unified with `end_of_file-CharCount`.

  See also
    lazy_list_character_count/3 only provides the character count.
lazy_list_character_count(-CharCount)`//`
  True when CharCount is the current character count in the Lazy list. The character count is computed by finding the distance to the next frozen tail of the lazy list. CharCount is one of:

  - An integer
  - A term end_of_file-Count
  See also
    lazy_list_location/3 provides full details of the location for error reporting.
[det]stream_to_lazy_list(+Stream, -List)
  Create a lazy list representing the character codes in Stream. It must be possible to reposition Stream. List is a list that ends in a delayed goal. List can be unified completely transparent to a (partial) list and processed transparently using DCGs, but please be aware that a lazy list is not the same as a materialized list in all respects.

  Typically, this predicate is used as a building block for more high level safe predicates such as phrase_from_file/2.

  To be done
    Enhance of lazy list throughout the system.