%==============================================================================
% Project:	Microcontroller Programming in Datalog
% Version:	0.4
% Filename:	util.pl
% Purpose:	Some General Utility Predicates
% Last Change:	29.03.2021
% Language:	Prolog (tested with SWI Prolog)
% Author:	Stefan Brass
% Email:	brass@informatik.uni-halle.de
% WWW:		http://www.informatik.uni-halle.de/~brass/
% Address:	Univ. Halle, Von-Seckendorff-Platz 1, D-06120 Halle, GERMANY
% Copyright:	(c) 2020-2021 by Stefan Brass
%==============================================================================

% For more information, see the main file: ctest.pl


%******************************************************************************
% Some General Utility Predicates:
%******************************************************************************


%==============================================================================
% Definitions of Standard Predicates (to increase Portability):
%==============================================================================


%------------------------------------------------------------------------------
% list_append(+List1, +List2, -List12):
%------------------------------------------------------------------------------

% Some Prolog implementations have append, others not.
% To increase portability, we define our own version here:

list_append([], L, L).

list_append([E|R], L, [E|RL]) :-
	list_append(R, L, RL).

%------------------------------------------------------------------------------
% list_member(-Elem, +List):
%------------------------------------------------------------------------------

list_member(Elem, [Elem|_]).

list_member(Elem, [_|Rest]) :-
	list_member(Elem, Rest).

%------------------------------------------------------------------------------
% list_length(+List, -Length):
%------------------------------------------------------------------------------

list_length(List, Length) :-
	list_length_aux(List, 0, Length).

% list_length_aux(+List, -LengthIn, +LengthOut) - Tail Recursive Version:

list_length_aux([], Length, Length).

list_length_aux([_|Rest], LengthIn, LengthOut) :-
	Length is LengthIn + 1,
	list_length_aux(Rest, Length, LengthOut).

%------------------------------------------------------------------------------
% delete_all(+Pred, +Arity):
%------------------------------------------------------------------------------

% Delete all facts from dynamic database matching Head:

delete_all(Pred, Arity) :-
	functor(Head, Pred, Arity),
	retractall(Head).

% Note that in some Prologs it is called retract_all.


%==============================================================================
% File Interface:
%==============================================================================


%------------------------------------------------------------------------------
% file_ropen(+FileName, -Stream):
%------------------------------------------------------------------------------

% Open a file in read mode.
% open generates an exception in SWI Prolog if file does not exist.
% access_file checks the accessibility and fails if the file does not exist.

file_ropen(FileName, Stream) :-
	access_file(FileName, read),
	open(FileName, read, Stream).

%------------------------------------------------------------------------------
% file_close(+Stream):
%------------------------------------------------------------------------------

file_close(Stream) :-
	close(Stream).

%------------------------------------------------------------------------------
% file_lineno(+Stream, -LineNo):
%------------------------------------------------------------------------------

% This retuns the current line number in the file.

file_lineno(Stream, LineNo) :-
	line_count(Stream, LineNo).

%------------------------------------------------------------------------------
% file_eof(+Stream):
%------------------------------------------------------------------------------

% Is the current reading position in the file at the end of file?

file_eof(Stream) :-
	at_end_of_stream(Stream).

%------------------------------------------------------------------------------
% file_peekc(+Stream, -Char):
%------------------------------------------------------------------------------

% Have a look at the next character in the input stream, but do not read it.
% The character is returned as a one-character Prolog atom.

file_peekc(Stream, Char) :-
	peek_char(Stream, Char).

%------------------------------------------------------------------------------
% file_getc(+Stream, -Char):
%------------------------------------------------------------------------------

% Read the next character from the input stream.
% The character is returned as a one-character Prolog atom.

file_getc(Stream, Char) :-
	get_char(Stream, Char).

