1426 lines
		
	
	
		
			44 KiB
		
	
	
	
		
			Prolog
		
	
	
	
	
	
			
		
		
	
	
			1426 lines
		
	
	
		
			44 KiB
		
	
	
	
		
			Prolog
		
	
	
	
	
	
| :- module( r_session,
 | |
|           [
 | |
|                r_open/0, r_open/1,
 | |
|                r_close/0, r_close/1,
 | |
|                r_in/1, r_in/2,
 | |
|                r_push/1, r_push/2,
 | |
|                r_out/2, r_out/3,
 | |
|                r_err/3, r_err/4,
 | |
|                r_print/1, r_print/2,
 | |
|                r_lines_print/1, r_lines_print/2, r_lines_print/3,
 | |
|                r_lib/1, r_lib/2,
 | |
|                r_flush/0, r_flush/1,
 | |
|                r_flush_onto/2, r_flush_onto/3,
 | |
|                current_r_session/1, current_r_session/3,
 | |
|                default_r_session/1,
 | |
|                r_session_data/3, r_streams_data/3,
 | |
|                r_history/0, r_history/1, r_history/2,
 | |
|                r_session_version/1,
 | |
|                r_bin/1,
 | |
|                r_bin_version/1, r_bin_version/2,
 | |
|                r_verbosity/1,
 | |
|                op( 950, xfx, (<-) )
 | |
|           ] ).
 | |
| 
 | |
| :- use_module( library(lists) ).
 | |
| :- use_module( library(readutil) ). % read_line_to_codes/2.
 | |
| 
 | |
| :- ( current_predicate(r_verbosity_level/1) -> true;
 | |
|           assert(r_verbosity_level(0)) ).
 | |
| 
 | |
| :- dynamic( r_bin_location/1 ).
 | |
| :- dynamic( r_session/3 ).
 | |
| :- dynamic( r_session_history/2 ).
 | |
| :- dynamic( r_old_bin_warning_issued/1 ).
 | |
| :- dynamic( r_bin_takes_interactive/2 ).
 | |
| 
 | |
| % Yap declaration:
 | |
| :- ensure_loaded( library(system) ).         % exec/3, file_exists/1, directory_files/2.
 | |
| :- ensure_loaded( library(apply_macros) ).   % maplist/3
 | |
| % end of Yap declaration.
 | |
| 
 | |
| /** <module> R session
 | |
| 
 | |
| This library facilitates interaction with the R system for statistical
 | |
| computing.  It assumes an R executable in $PATH or can be given a location
 | |
| to a functioning R executable (see r_bin/1 and r_open/1 for details on how
 | |
| R is located). R is ran as a slave with Prolog writing on and reading from
 | |
| the associated streams. Multiple sessions can be managed simultaneously.
 | |
| Each has 3 main components: a name or alias, a term structure holding the
 | |
| communicating streams and a number of associated data items.
 | |
| 
 | |
| The library attempts to ease the translation between prolog terms and R
 | |
| inputs. Thus, Prolog term =|x <- c(1,2,3)|= is translated to atomic =|'x
 | |
| <- c(1,2,3)'|= which is then passed on to R. That is, =|<-|= is a
 | |
| defined/recognised operator. =|X <- c(1,2,3)|=, where X is a variable,
 | |
| instantiates X to the list =|[1,2,3]|=. Also 'Atom' <- [x1,...,xn]
 | |
| translates to R code: Atom <- c(x1,...,xn). Currently only vectors can be
 | |
| translated in this fashion.
 | |
| 
 | |
| Although the library is primarily meant to be used as a research tool,
 | |
| it still provides access to many functions of the R system that may render it 
 | |
| useful to a wider audience. The library provides access to R's plethora of vector and scalar
 | |
| functions. We adicipate that of particular interest to Prolog programmers might be the fact
 | |
| that the library can be used to create plots from Prolog objects.
 | |
| Notably creating plots from lists of numbers.
 | |
| 
 | |
| These capabilities are illustrated in the following example :
 | |
| 
 | |
| ==
 | |
| rtest :-
 | |
|      r_open,
 | |
|      r_in( y <- rnorm(50) ),
 | |
|      r_print( y ),
 | |
|      r_in( x <- rnorm(y) ),
 | |
|      r_in( x11(width=5,height=3.5) ),
 | |
|      r_in( plot(x,y)),
 | |
|      write( 'Press Return to continue...' ), nl,
 | |
|      read_line_to_codes( user, _ ),
 | |
|      r_print( 'dev.off()' ),
 | |
|      r_in( Y <- y ),
 | |
|      write( y(Y) ), nl,
 | |
|      Z = [1,2,3,4,5,6,7,8,9],
 | |
|      r_in( z <- Z ),
 | |
|      r_print( z ),
 | |
|      r_close.
 | |
| ==
 | |
| 
 | |
| @author 	Nicos Angelopoulos
 | |
| @version	0:0:4
 | |
| @copyright	Nicos Angelopoulos
 | |
| @license	YAP: Artistic
 | |
| @see		ensure_loaded(library('../doc/packages/examples/R/r_demo.pl'))
 | |
| @see		http://www.r-project.org/
 | |
| @author		Windows-compatibility is based on work by `JAB'
 | |
| */
 | |
| 
 | |
| %%% Section: Interface predicates
 | |
| 
 | |
| 
 | |
| %% r_bin( ?Rbin )
 | |
| %
 | |
| %   Register the default R location, +Rbin, or interrogate the current location: -Rbin.
 | |
| %   When interrogating Rbin is bound to the R binary that would be used by an r_open/0.
 | |
| %   The order of search is: registered location, environment variable 'R_BIN' and path defined.
 | |
| %   On unix systems path defined is the first R executable in $PATH. On MS wins it is the latest
 | |
| %   Rterm.exe found by expand_file_name( 'C:/Program Files/R/R-*/bin/Rterm.exe', Candidates ).
 | |
| %   The value Rbin == =retract= retracts the current registered location. 
 | |
| %   Rbin == =test=, succeeds if an R location has been registered.
 | |
| %
 | |
| r_bin( Rbin ) :-
 | |
|      var( Rbin ),
 | |
|      !,
 | |
|      ( r_bin_location(Rbin) ->
 | |
|           true
 | |
|           ;
 | |
|           ( locate_rbin_file(Rbin) ->
 | |
|                M = 'There is no registered R executable. Using the one found by searching.',
 | |
|                r_verbose( M, 1 )
 | |
|                ;
 | |
|                M = 'There is no registered or default R executatble. Use, r_bin(+Rbin).',
 | |
|                fail_term( M )
 | |
|           )
 | |
|      ).
 | |
| r_bin( retract ) :-
 | |
|      !,
 | |
|      retractall( r_bin_location(_) ).
 | |
| r_bin( test ) :-
 | |
|      !,
 | |
|      r_bin_location(_).
 | |
| r_bin( Rbin ) :-
 | |
|      retractall( r_bin_location(_) ),
 | |
|      assert( r_bin_location(Rbin) ).
 | |
| 
 | |
| %%	r_open
 | |
| %
 | |
| %	Open a new R session. Same as r_open( [] ).
 | |
| %
 | |
| r_open :-
 | |
|      r_open( [] ).
 | |
| 
 | |
| %% r_open( +Opts )
 | |
| %
 | |
| %   Open a new R session with optional list of arguments. Opts should be
 | |
| %   a list of the following
 | |
| %
 | |
| %       * alias(Alias)
 | |
| %	Name for the session. If absent or  a variable an opaque term is
 | |
| %	generated.
 | |
| %
 | |
| %       * assert(A)
 | |
| %	Assert token. By default session  opened   last  is  the default
 | |
| %	session (see default_r_session/1). Using A =   =z= will push the
 | |
| %	session to the bottom of the pile.
 | |
| %
 | |
| %	* at_r_halt(RHAction)
 | |
| %	R slaves used to halt when they encounter  an error. 
 | |
| %    This is no longer the case but this option is still present in case
 | |
| %    it is useful in the future. This option provides a handle to changing
 | |
| %    the  behaviour of the session when a halt of the R-slave occurs.
 | |
| %    RHAction should be one of =abort=, =fail=, call/1,
 | |
| %	call_ground/1, =reinstate= or =restart=. Default is =fail=. When
 | |
| %	RHAction is =reinstate=, the history of   the session is used to
 | |
| %	roll-back all the commands sent so far. At `restart' the session
 | |
| %	is restarted with same name  and   options,  but  history is not
 | |
| %	replayed.
 | |
| %
 | |
| %       * copy(CopyTo,CopyWhat)
 | |
| %	Records interaction with R to a   file/stream.  CopyTo should be
 | |
| %	one   of   =null=,   stream(Stream),   OpenStream,   AtomicFile,
 | |
| %	once(File) or many(File). In the  case   of  many(File), file is
 | |
| %	opened and closed at each write   operation.  CopyWhat should be
 | |
| %	one of =both=, =in=, =out= or =none=. Default is no recording
 | |
| %    (CopyTo = =null=).
 | |
| %
 | |
| %       * ssh(Host)
 | |
| %       * ssh(Host,Dir)
 | |
| %       Run R on Host with start directory Dir. Dir defaults to /tmp.
 | |
| %       Not supported on MS Windows.
 | |
| %
 | |
| %
 | |
| %       * rbin(Rbin)
 | |
| %       R executable location to use for this open operation.
 | |
| %       If the option is not present binary registered with r_bin/1 and
 | |
| %       environment variable R_BIN are examined for the full location of
 | |
| %       the R binary. In MS windows Rbin should point to Rterm.exe. Also see r_bin/1.
 | |
| %
 | |
| %       * with(With)
 | |
| %       With is in [environ,restore,save]. The   default behaviour is to
 | |
| %       start the R executable  with  flags =|--no-environ --no-restore
 | |
| %       --no-save|=. For each With value  found in Opts the corresponding
 | |
| %       =|--no-|= flag is removed.
 | |
| %
 | |
| r_open( Opts ) :-
 | |
|      r_open_1( Opts, _R, false ).
 | |
| 
 | |
| %%   r_close
 | |
| %
 | |
| %         Close the default R session.
 | |
| %
 | |
| r_close :-
 | |
|      ( default_r_session( Alias ) ->
 | |
|                r_close( Alias )
 | |
|                ;
 | |
|                fail_term( no_default_open_r_session_could_be_found_to_close )
 | |
|      ).
 | |
| 
 | |
| %%   r_close(+R)
 | |
| %
 | |
| %         Close the named R session.
 | |
| %
 | |
| r_close( All ) :-
 | |
|      All == all,
 | |
|      !,
 | |
|      findall( Alias, ( retract( r_session(Alias,Streams,Data) ),
 | |
|                        r_close_session( Alias, Streams, Data ) ), _AllAls ).
 | |
|      % write( closed_all(All) ), nl.
 | |
| r_close( Alias ) :-
 | |
|      ( retract( r_session(Alias,Streams,Data) ) ->
 | |
|           r_close_session( Alias, Streams, Data )
 | |
|           ;
 | |
|           fail_term( no_open_r_session_could_be_found_to_close_at:Alias )
 | |
|      ).
 | |
| 
 | |
| %%   r_in(+Rcmd)
 | |
| %
 | |
| %         Push Rcmd to the default R session. Output and Errors  will be
 | |
| %         printed to the terminal.
 | |
| %
 | |
| r_in( This ) :-
 | |
|      default_r_session( R ),
 | |
|      r_in( R, This, _ ).
 | |
| 
 | |
| %%   r_in(+R,+Rcmd)
 | |
| %
 | |
| %         As r_in/1 but for session R.
 | |
| %
 | |
| r_in( R, PrvThis ) :-
 | |
|      r_in( R, PrvThis, _ ).
 | |
| 
 | |
| %%   r_push(+Rcmd)
 | |
| %
 | |
| %         As r_in/1 but does not consume error or output streams.
 | |
| %
 | |
| r_push( This ) :-
 | |
|      default_r_session( R ),
 | |
|      r_push( R, This ).
 | |
| 
 | |
| %%   r_push(+R,+Rcmd)
 | |
| %
 | |
| %         As r_push/1 but for named session.
 | |
| %
 | |
| r_push( R, RCmd ) :-
 | |
|      current_r_session( R, Streams, Data ),
 | |
|      r_session_data( copy_to, Data, CopyTo ),
 | |
|      r_session_data( copy_this, Data, CopyThis ),
 | |
|      r_streams( input, Streams, Ri ),
 | |
|      r_input_normative( RCmd, RNrm ),
 | |
|      write( Ri, RNrm ), nl( Ri ),
 | |
|      r_record_term( CopyThis, CopyTo, RNrm ).
 | |
| 
 | |
| %%   r_out(+Rcmd,-Lines)
 | |
| %
 | |
| %         Push Rcmd to default R session and grab output lines Lines as
 | |
| %         a list of code lists.
 | |
| %
 | |
| r_out( This, Read ) :-
 | |
|      default_r_session( R ),
 | |
|      r_out( R, This, Read ).
 | |
| 
 | |
| %%   r_out(+R,+Rcmd,-Lines)
 | |
| %
 | |
| %         As r_out/2 but for named session R.
 | |
| %
 | |
| r_out( R, RCmd, RoLns ) :-
 | |
|      r_push( R, RCmd, Rplc, RoLns, ReLns, Halt, HCall ),
 | |
|      r_lines_print( ReLns, error, user_error ),
 | |
|      r_record_history( Halt, R, RCmd ),
 | |
|      r_out_halted_record( Halt, R, RoLns ),
 | |
|      replace_variables( Rplc ),
 | |
|      call( HCall ).
 | |
| 
 | |
| %%   r_err(+Rcmd,-Lines,-ErrLines)
 | |
| %
 | |
| %         Push Rcmd to default R session and grab output lines Lines as
 | |
| %         a list of code lists. Error lines are in ErrLines.
 | |
| %
 | |
| r_err( This, Read, ErrRead ) :-
 | |
|      default_r_session( R ),
 | |
|      r_err( R, This, Read, ErrRead ).
 | |
| 
 | |
| %%   r_err(+R,+Rcmd,-Lines, -ErrLines)
 | |
| %
 | |
| %         As r_err/3 but for named session R.
 | |
| %
 | |
| r_err( R, RCmd, RoLns, ReLns ) :-
 | |
|      r_push( R, RCmd, Rplc, RoLns, ReLns, Halt, HCall ),
 | |
|      r_lines_print( ReLns, error, user_error ),
 | |
|      r_record_history( Halt, R, RCmd ),
 | |
|      r_out_halted_record( Halt, R, RoLns ),
 | |
|      replace_variables( Rplc ),
 | |
|      call( HCall ).
 | |
| 
 | |
| %%   r_print(+X)
 | |
| %
 | |
| %         A shortcut for r_in( print(X) ).
 | |
| %
 | |
| r_print( This ) :-
 | |
|      default_r_session( R ),
 | |
|      r_print( R, This ).
 | |
| 
 | |
| %%   r_print(+R,+X)
 | |
| %
 | |
| %         As r_print/1 but for named session R.
 | |
| %
 | |
| r_print( R, This ) :-
 | |
|      r_out( R, This, Read ),
 | |
|      r_lines_print( Read, output ).
 | |
| 
 | |
| %%   r_lines_print( +Lines )
 | |
| %
 | |
| %         Print a list of code lists (Lines) to the user_output.
 | |
| %         Lines would normally be read of an R stream.
 | |
| %
 | |
| r_lines_print( Lines ) :-
 | |
|      r_lines_print( Lines, output, user_output ).
 | |
| 
 | |
| %%   r_lines_print( +Lines, +Type )
 | |
| %
 | |
| %         As r_lines_print/1 but Type declares whether to treat lines
 | |
| %         as output or error response. In the latter case they are written
 | |
| %         on user_error and prefixed with '!'.
 | |
| %
 | |
| r_lines_print( Lines, Type ) :-
 | |
|      r_lines_print_type_stream( Type, Stream ),
 | |
|      r_lines_print( Lines, Type, Stream ).
 | |
| 
 | |
| %%   r_lines_print( +Lines, +Type, +Stream )
 | |
| %
 | |
| %         As r_lines_print/3 but Lines are written on Stream.
 | |
| %
 | |
| r_lines_print( [], _Type, _Stream ).
 | |
| r_lines_print( [H|T], Type, Stream ) :-
 | |
|      atom_codes( Atm, H ),
 | |
|      r_lines_print_prefix( Type, Stream ),
 | |
|      write( Stream, Atm ), nl( Stream ),
 | |
|      r_lines_print( T, Type, Stream ).
 | |
| 
 | |
| %%   r_lib(+L)
 | |
| %
 | |
| %         A shortcut for r_in( library(X) ).
 | |
| %
 | |
| r_lib( Lib ) :-
 | |
|      default_r_session( R ),
 | |
|      r_lib( R, Lib ).
 | |
| 
 | |
| %%   r_lib(+R,+L)
 | |
| %
 | |
| %            As r_lib/1 but for named session R.
 | |
| %
 | |
| r_lib( R, Lib ) :-
 | |
|      r_in( R, library(Lib) ).
 | |
| 
 | |
| %%   r_flush
 | |
| %
 | |
| %         Flush default R's output and error on to the terminal.
 | |
| %
 | |
| r_flush :-
 | |
|      default_r_session( R ),
 | |
|      r_flush( R ).
 | |
| 
 | |
| %%   r_flush(+R)
 | |
| %
 | |
| %         As r_flush/0 but for session R.
 | |
| %
 | |
| r_flush( R ) :-
 | |
|      r_flush_onto( R, [output,error], [Li,Le] ),
 | |
|      r_lines_print( Li, output ),
 | |
|      r_lines_print( Le, error ).
 | |
| 
 | |
| %%   r_flush_onto(+SAliases,-Onto)
 | |
| %
 | |
| %         Flush stream aliases to code lists Onto. SAliases
 | |
| %         should be one of, or a list of, [output,error].
 | |
| %
 | |
| r_flush_onto( RinStreamS, OntoS ) :-
 | |
|      default_r_session( R ),
 | |
|      r_flush_onto( R, RinStreamS, OntoS ).
 | |
| 
 | |
| %% r_flush_onto(+R,+SAliases,-Onto)
 | |
| %
 | |
| %         As r_flush_onto/2 for specified session R.
 | |
| %
 | |
| r_flush_onto( R, RinStreams, Ontos ) :-
 | |
|      ( is_list(RinStreams) -> RStreams = RinStreams; RStreams=[RinStreams] ),
 | |
|      % to_list( RinStreamS, RinStreams ),
 | |
|      r_input_streams_list( RStreams ),
 | |
|      r_flush_onto_1( RStreams, R, ROntos ),
 | |
|      ( is_list(RinStreams) -> Ontos = ROntos; Ontos=[ROntos] ).
 | |
| 
 | |
| %%   current_r_session(?R)
 | |
| %         True if R is the name of current R session.
 | |
| %         Can be used to enumerate all open sessions.
 | |
| %
 | |
| current_r_session( R ) :-
 | |
|      var( R ),
 | |
|      !,
 | |
|      r_session( R, _Session, _Data ).
 | |
| current_r_session( R ) :-
 | |
|      r_session( R, _Session, _Data ),
 | |
|      !.
 | |
| current_r_session( R ) :-
 | |
|      fail_term( 'Could not find session':R ).
 | |
| 
 | |
| %%   current_r_session(?R,?S,?D)
 | |
| %
 | |
| %         True if R is an open session with streams S
 | |
| %         and data D (see introduction to the library).
 | |
| %
 | |
| current_r_session( Alias, R, Data ) :-
 | |
|      r_session( Alias, R, Data ).
 | |
| 
 | |
| %% default_r_session(?R)
 | |
| %
 | |
| %         True if R is the default session.
 | |
| %
 | |
| default_r_session( R ) :-
 | |
|      ( var(R) ->
 | |
|           ( r_session(R,_Cp1,_Wh1) ->
 | |
|                true
 | |
|                ;
 | |
|                fail_term( no_default_open_r_session_was_found )
 | |
|           )
 | |
|           ;
 | |
|           ( r_session(R,_Cp2,_Wh2) ->
 | |
|                true
 | |
|                ;
 | |
|                fail_term( no_open_r_session_at(R) )
 | |
|           )
 | |
|      ).
 | |
| 
 | |
| %%   r_streams_data(+SId,+Streams,-S)
 | |
| %         True if Streams is an R session streams
 | |
| %         structure and S is its stream corresponding
 | |
| %         to identifier SId, which should be one of
 | |
| %         [input,output,error].
 | |
| %
 | |
| r_streams_data( input,  r(Ri,_,_), Ri ).
 | |
| r_streams_data( output, r(_,Ro,_), Ro ).
 | |
| r_streams_data( error,  r(_,_,Re), Re ).
 | |
| 
 | |
| %% r_session_data(+DId,+Data,-Datum)
 | |
| %
 | |
| %         True if Data is a structure representing
 | |
| %         R session associated data and Datum is its
 | |
| %         data item corresponding to data identifier
 | |
| %         DId. DId should be in
 | |
| %         [copy_to,copy_this,at_r_halt,opts].
 | |
| %
 | |
| r_session_data( copy_to, rsdata(Copy,_,_,_), Copy ).
 | |
| r_session_data( copy_this, rsdata(_,This,_,_), This ).
 | |
| r_session_data( at_r_halt, rsdata(_,_,RHalt,_), RHalt ).
 | |
| r_session_data( opts, rsdata(_,_,_,Opts), Opts ).
 | |
| 
 | |
| %%   r_history
 | |
| %
 | |
| %         Print on user_output the history of the default session.
 | |
| %
 | |
| r_history :-
 | |
|      default_r_session( R ),
 | |
|      r_session_history( R, History ),
 | |
|      reverse( History, Hicory ),
 | |
|      write( history(R) ), nl, write('---' ), nl,
 | |
|      ( (member(H,Hicory),write(H),nl,fail) -> true; true ),
 | |
|      write( '---' ), nl.
 | |
| 
 | |
| %%   r_history(-H)
 | |
| %
 | |
| %         H unifies to the history list of the Rcmds fed into the default
 | |
| %         session. Most recent command appears at the head of the list.
 | |
| %
 | |
| r_history( History ) :-
 | |
|      default_r_session( R ),
 | |
|      r_session_history( R, History ).
 | |
| 
 | |
| %%   r_history(?R,-H)
 | |
| %         As r_history/1 but for named session R.
 | |
| %         It can be used to enumerate all histories.
 | |
| %         It fails when no session is open.
 | |
| %
 | |
| r_history( R, History ) :-
 | |
|      r_session_history( R, History ).
 | |
| 
 | |
| %%   r_session_version(-Version)
 | |
| %         Installed version. Version is of the form Major:Minor:Fix,
 | |
| %         where all three are integers.
 | |
| %
 | |
| r_session_version( 0:0:4 ).
 | |
| 
 | |
| %% r_verbose( What, CutOff )
 | |
| %
 | |
| r_verbose( What, CutOff ) :-
 | |
|      r_verbosity_level( Level ),
 | |
|      ( CutOff > Level ->
 | |
|           true
 | |
|           ;
 | |
|           write( What ), nl
 | |
|      ).
 | |
| 
 | |
| %% r_verbosity( ?Level )
 | |
| %
 | |
| %    Set, +Level, or interrogate, -Level, the verbosity level. +Level could be
 | |
| %    =false= (=0), =true= (=3) or an integer in {0,1,2,3}. 3 being the most verbose.
 | |
| %    The default is 0. -Level will instantiate to the current verbosity level,
 | |
| %    an integer in {0,1,2,3}.
 | |
| %
 | |
| r_verbosity( Level ) :-
 | |
|      var( Level ),
 | |
|      !,
 | |
|      r_verbosity_level( Level ).
 | |
| r_verbosity( Level ) :-
 | |
|      ( Level == true ->
 | |
|           Numeric is 3
 | |
|           ;
 | |
|           ( Level == false ->
 | |
|                Numeric is 0
 | |
|                ;
 | |
|                ( integer(Level) ->
 | |
|                     ( Level < 0 ->
 | |
|                          write( 'Adjusting verbosity level to = 0. ' ), nl,
 | |
|                          Numeric is 0
 | |
|                          ;
 | |
|                          ( Level > 3 ->
 | |
|                               write( 'Adjusting verbosity level to = 3. ' ), nl,
 | |
|                               Numeric is 3
 | |
|                               ;
 | |
|                               Numeric is Level
 | |
|                          )
 | |
|                     )
 | |
|                     ;
 | |
|                     fail_term( 'Unknown verbosity level. Use : true, false, 0-3' )
 | |
|                )
 | |
|           )
 | |
|      ),
 | |
|      retractall( r_verbosity_level(_) ),
 | |
|      assert( r_verbosity_level(Numeric) ).
 | |
| 
 | |
| %% r_bin_version( -Version)
 | |
| %
 | |
| %    Get the version of R binary identified by r_bin/1. Version will have the
 | |
| %    same structure as in r_session_version/1 ie M:N:F.
 | |
| %
 | |
| r_bin_version( Version ) :-
 | |
|      r_bin( R ), 
 | |
|      r_bin_version( R, Version ).
 | |
| 
 | |
| %% r_bin_version( +Rbin, -Version )
 | |
| %
 | |
| %    Get the version of R binary identified by +Rbin. Version will have the
 | |
| %    same structure as in r_session_version/1 ie M:N:F.
 | |
| %
 | |
| r_bin_version( R, Version ) :-
 | |
|      r_bin_version_pl( R, Version ).
 | |
| 
 | |
| %%% Section: Auxiliary predicates
 | |
| 
 | |
| % Rcv == true iff r_open_1/3 is called from recovery.
 | |
| %
 | |
| r_open_1( Opts, Alias, Rcv ) :-
 | |
|      ( options_have_ssh(Opts,Host,Dir) ->
 | |
|           ( current_prolog_flag(windows,true) ->
 | |
|                fail_term( ssh_option_not_supported_on_ms_windows )
 | |
|                ;
 | |
|                which( ssh, Ssh )
 | |
|           )
 | |
|           ;
 | |
|           true
 | |
|      ),
 | |
|      ( (memberchk(rbin(Rbin),Opts);locate_rbin(Ssh,Rbin)) ->
 | |
|           true
 | |
|           ;
 | |
|           fail_term( 'Use rbin/1 in r_open/n, or r_bin(\'Rbin\') or set R_BIN.' )
 | |
|      ),
 | |
|      r_bin_arguments( Opts, Rbin, OptRArgs ),
 | |
|      % ( var(Harg) -> RArgs = OptRArgs; RArgs = [Host,Harg|OptRArgs] ),
 | |
|      ( var(Ssh) ->
 | |
|           Exec = Rbin,
 | |
|           Args = OptRArgs
 | |
|           ;
 | |
|           Exec = Ssh,
 | |
|           % atoms_concat( [' "cd ',Dir,'; ',Rbin,'"'], Harg ),
 | |
|           atoms_concat( ['cd ',Dir,'; '], Cd ),
 | |
|           PreArgs = [Cd,Rbin|OptRArgs],
 | |
|           double_quote_on_yap( PreArgs, TailArgs ),
 | |
|           Args = [Host|TailArgs]
 | |
|           % atoms_concat( ['ssh ', Host,' "cd ',Dir,'; ',RBin,'"'], R )
 | |
|      ),
 | |
|      % atom_concat( PrvExec, RPsf, Exec ),
 | |
|      r_verbose( r_process( Exec, Args, Ri, Ro, Re ), 3 ),
 | |
|      r_process( Exec, Args, Ri, Ro, Re ),
 | |
|      RStreams = r(Ri,Ro,Re),
 | |
|      r_streams_set( Ri, Ro, Re ),
 | |
|      r_process_was_successful( Ri, Ro, Re ),
 | |
|      r_open_opt_copy( Opts, CpOn, CpWh, Rcv ),
 | |
|      r_open_opt_at_r_halt( Opts, RHalt ),
 | |
|      ( memberchk(alias(Alias),Opts) ->
 | |
|           ( var(Alias) ->
 | |
|                r_session_skolem( Alias, 1 )
 | |
|                ;
 | |
|                ( r_session(Alias,_,_) ->
 | |
|                     fail_term( 'Session already exists for alias':Alias )
 | |
|                     ;
 | |
|                     true
 | |
|                )
 | |
|           )
 | |
|           ;
 | |
|           r_session_skolem( Alias, 1 )
 | |
|      ),
 | |
|      RData = rsdata(CpOn,CpWh,RHalt,Opts),
 | |
|      ( memberchk(assert(Assert),Opts) ->
 | |
|           ( Assert == a ->
 | |
|                asserta( r_session(Alias,RStreams,RData) )
 | |
|                ;
 | |
|                ( Assert == z ->
 | |
|                     assertz( r_session(Alias,RStreams,RData) )
 | |
|                     ;
 | |
|                     fail_term( 'Cannot decipher argument to assert/1 option':Assert )
 | |
|                )
 | |
|           )
 | |
|           ;
 | |
|           asserta( r_session(Alias,RStreams,RData) )
 | |
|      ),
 | |
|      AtRH = at_r_halt(reinstate),
 | |
|      ( (memberchk(history(false),Opts),\+memberchk(AtRH,Opts)) ->
 | |
|                true
 | |
|                ;
 | |
|                retractall( r_session_history(Alias,_) ),
 | |
|                assert( r_session_history(Alias,[]) )
 | |
|      ).
 | |
| 
 | |
| r_close_session( Alias, Streams, Data ) :-
 | |
|      r_streams_data( input, Streams, Ri ),
 | |
|      r_streams_data( output,Streams, Ro ),
 | |
|      r_streams_data( error, Streams, Re ),
 | |
|      r_session_data( copy_to, Data, CopyTo ),
 | |
|      r_session_data( copy_this, Data, CopyThis ),
 | |
|      write( Ri, 'q()' ), nl( Ri ),
 | |
|      r_record_term( CopyThis, CopyTo, 'q()' ),
 | |
|      ( (CopyTo=stream(CopyS),stream_property(CopyS,file_name(CopyF)),CopyF\==user)->
 | |
|           close(CopyS)
 | |
|           ;
 | |
|           true
 | |
|      ),
 | |
|      close( Ri ),
 | |
|      close( Ro ),
 | |
|      close( Re ),
 | |
|      retractall( r_session_history(Alias,_) ).
 | |
| 
 | |
| r_in( R, RCmd, Halt ) :-
 | |
|      r_push( R, RCmd, Rplc, RoLns, ReLns, Halt, HCall ),
 | |
|      r_out_halted_record( Halt, R, RoLns ),
 | |
|      r_lines_print( RoLns, output, user_output ),
 | |
|      r_lines_print( ReLns, error, user_error ),
 | |
|      r_record_history( Halt, R, RCmd ),
 | |
|      replace_variables( Rplc ),
 | |
|      call( HCall ).
 | |
| 
 | |
| r_push( R, RCmd, Rplc, RoLns, ReLns, Halt, HCall ) :-
 | |
|      current_r_session( R, Streams, Data ),
 | |
|      r_session_data( copy_to, Data, CopyTo ),
 | |
|      r_session_data( copy_this, Data, CopyThis ),
 | |
|      r_streams( input, Streams, Ri ),
 | |
|      r_input_normative( RCmd, R, 0, RNrm, Rplc, _ ),
 | |
|      write( Ri, RNrm ), nl( Ri ),
 | |
|      r_record_term( CopyThis, CopyTo, RNrm ),
 | |
|      r_lines( Streams, error, ReLns ),
 | |
|      r_halted( ReLns, R, Halt, HCall ),
 | |
|      ( Halt == true ->
 | |
|           r_streams( output, Streams, Ro ),
 | |
|           r_read_lines( Ro, [], RoLns )
 | |
|           ;
 | |
|           r_lines( Streams, output, RoLns )
 | |
|      ),
 | |
|      r_record_lines( RoLns, output, CopyTo ),
 | |
|      r_record_lines( ReLns, error, CopyTo ),
 | |
|      ( (Halt==true,CopyTo=stream(Cl)) -> close(Cl); true ).
 | |
| 
 | |
| r_out_halted_record( true, _Alias, [] ).
 | |
| r_out_halted_record( false, _Alias, Lines ) :-
 | |
|      r_session_data( copy_this, Data, CopyThis ),
 | |
|      r_session_data( copy_to, Data, CopyTo ),
 | |
|      ( (CopyThis==out;CopyThis==both) ->
 | |
|           r_record_lines( Lines, output, CopyTo )
 | |
|           ;
 | |
|           true
 | |
|      ).
 | |
| 
 | |
| r_flush_onto_1( [], _R, [] ).
 | |
| r_flush_onto_1( [H|T], R, [HOn|TOns] ) :-
 | |
|      current_r_session( R, Streams, _ ),
 | |
|      r_lines( Streams, H, HOn ),
 | |
|      r_flush_onto_1( T, R, TOns ).
 | |
| 
 | |
| replace_variables( [] ).
 | |
| replace_variables( [arp(R,Pv,Rv)|T] ) :-
 | |
|      r_out( R, Rv, Lines ),
 | |
|      r_read_list( Lines, Pv ),
 | |
|      % r_lines_to_pl_var( Lines, Pv ),
 | |
|      replace_variables( T ).
 | |
| 
 | |
| % r_lines_to_pl_var( [], [] ).
 | |
| % r_lines_to_pl_var( [H|T], [] ) :-
 | |
|      % r_line_to_pl_var( [H|T], [] ) :-
 | |
|      % r_lines_to_pl_var( T, TPv ).
 | |
| 
 | |
| r_input_streams_list( Rins ) :-
 | |
|      ( select(output,Rins,NoInpIns) -> true; NoInpIns=Rins ),
 | |
|      ( select(error,NoInpIns,NoErrIns) -> true; NoErrIns=NoInpIns ),
 | |
|      ( NoErrIns = [] ->
 | |
|           true
 | |
|           ;
 | |
|           ( (memberchk(input,NoErrIns);memberchk(error,NoErrIns)) ->
 | |
|                     fail_term( 'duplicate entries in input streams list':Rins )
 | |
|                     ;
 | |
|                     fail_term( 'superfluous entries in input streams list':Rins )
 | |
|           )
 | |
|      ).
 | |
| 
 | |
| % succeds if Rcmd produces empty output, otherwise it fails
 | |
| ro_empty( R, Rcmd ) :-
 | |
|      r_out( R, Rcmd, [] ).
 | |
| 
 | |
| r_input_normative( (A;B), R, I, This, Rplc, OutI ) :-
 | |
|      !,
 | |
|      r_input_normative( A, R, I, ThisA, RplcA, NxI ),
 | |
|      r_input_normative( B, R, NxI, ThisB, RplcB, OutI ),
 | |
|      atoms_concat( [ThisA,'; ',ThisB], This ),
 | |
|      append( RplcA, RplcB, Rplc ).
 | |
| 
 | |
| % r_input_normative( Obj<-List, _R, I, This, Rplc, NxI ) :-
 | |
|      % % atomic( Obj ),
 | |
|      % is_list( List ),
 | |
|      % !,
 | |
|      % Rplc = [],
 | |
|      % NxI is I,
 | |
|      % pl_list_to_r_combine( List,
 | |
| 
 | |
| r_input_normative( Obj<-Call, R, I, This, Rplc, NxI ) :-
 | |
|      !,
 | |
|      ( var(Obj) ->
 | |
|           Rplc = [arp(R,Obj,ThisObj)],
 | |
|           number_codes( I, ICs ),
 | |
|           append( "pl_Rv_", ICs, RvCs ),
 | |
|           atom_codes( ThisObj, RvCs ),
 | |
|           NxI is I + 1
 | |
|           ;
 | |
|           Rplc = [],
 | |
|           r_input_normative( Obj, ThisObj ),
 | |
|           NxI is I
 | |
|      ),
 | |
|      r_input_normative( Call, ThisCall ),
 | |
|      atoms_concat( [ThisObj,' <- ',ThisCall], This ).
 | |
| r_input_normative( PrvThis, _R, I, This, [], I ) :-
 | |
|      r_input_normative( PrvThis, This ).
 | |
| 
 | |
| r_input_normative( Var, This ) :-
 | |
|      var(Var),
 | |
|      !,
 | |
|      This = Var.
 | |
| r_input_normative( Opt=Val, This ) :-
 | |
|      !,
 | |
|      r_input_normative( Opt, ThisOpt ),
 | |
|      r_input_normative( Val, ThisVal ),
 | |
|      atoms_concat( [ThisOpt,'=',ThisVal], This ).
 | |
| % 2008ac06, careful! we are changing behaviour here
 | |
| r_input_normative( List, This ) :-
 | |
|      is_list( List ),
 | |
|      pl_list_to_r_combine( List, This ),
 | |
|      !.
 | |
| r_input_normative( PrvThis, This ) :-
 | |
|      ( (\+ var(PrvThis),(PrvThis = [_|_];PrvThis=[])) ->
 | |
|           append( PrvThis, [0'"], ThisRight ),
 | |
|           atom_codes( This, [0'"|ThisRight] )
 | |
|           ;
 | |
|           ( compound(PrvThis) ->
 | |
|                PrvThis =.. [Name|Args],
 | |
|                ( (current_op(_Pres,Asc,Name),
 | |
|                   atom_codes(Asc,[_,0'f,_]),
 | |
|                   Args = [Arg1,Arg2]
 | |
|                ) ->
 | |
|                     r_input_normative( Arg1, Arg1Nrm ),
 | |
|                     r_input_normative( Arg2, Arg2Nrm ),
 | |
|                     atoms_concat( [Arg1Nrm,Name,Arg2Nrm], This )
 | |
|                     ;
 | |
|                     r_input_normative_tuple( Args, Tuple ),
 | |
|                     atoms_concat( [Name,'(',Tuple,')'], This )
 | |
|                )
 | |
|                ;
 | |
|                ( number(PrvThis) ->
 | |
|                     number_codes( PrvThis, ThisCs ),
 | |
|                     atom_codes( This, ThisCs )
 | |
|                     ;
 | |
|                     This = PrvThis
 | |
|                )
 | |
|           )
 | |
|      ).
 | |
| 
 | |
| r_input_normative_tuple( [], '' ).
 | |
| r_input_normative_tuple( [H|T], Tuple ) :-
 | |
|      r_input_normative_tuple( T, Psf ),
 | |
|      r_input_normative( H, HNorm ),
 | |
|      ( Psf == '' -> Tuple = HNorm
 | |
|         ; atoms_concat([HNorm,',',Psf], Tuple) ).
 | |
| 
 | |
| pl_list_to_r_combine( [H|T], This ) :-
 | |
|      number_atom_to_atom( H, Hatm ),
 | |
|      atom_concat( 'c(', Hatm, Pfx ),
 | |
|      pl_list_to_r_combine( T, Pfx, This ).
 | |
| 
 | |
| pl_list_to_r_combine( [], Pfx, This ) :-
 | |
|      atom_concat( Pfx, ')', This ).
 | |
| pl_list_to_r_combine( [H|T], Pfx, This ) :-
 | |
|      number_atom_to_atom( H, Hatm ),
 | |
|      atom_concat( Pfx, ',', PfxComma ),
 | |
|      atom_concat( PfxComma, Hatm, Nxt ),
 | |
|      pl_list_to_r_combine( T, Nxt, This ).
 | |
| 
 | |
| number_atom_to_atom( NorA, Atom ) :-
 | |
|      number_atom_to_codes( NorA, Codes ),
 | |
|      atom_codes( Atom, Codes ).
 | |
| 
 | |
| number_atom_to_codes( NorA, Codes ) :-
 | |
|      number( NorA ),
 | |
|      !,
 | |
|      number_codes( NorA, Codes ).
 | |
| number_atom_to_codes( NorA, Codes ) :-
 | |
|      atom( NorA ),
 | |
|      !,
 | |
|      atom_codes( NorA, Codes ).
 | |
| 
 | |
| r_read_lines( Ro, TermLine, Lines ) :-
 | |
|      read_line_to_codes( Ro, Line ),
 | |
|      r_read_lines_1( Line, TermLine, Ro, Lines ).
 | |
| 
 | |
| r_halted( Lines, R, Halted, HCall ) :-
 | |
|      last( Lines, "Execution halted" ),
 | |
|      !,
 | |
|      Halted = true,
 | |
|      findall( rs(Alias,Streams,Data), retract(r_session(Alias,Streams,Data)), Sessions),
 | |
|      \+ var(R),
 | |
|      r_halted_recovery( Sessions, R, HCall ).
 | |
| r_halted( _, _R, false, true ).
 | |
| 
 | |
| r_halted_recovery( [], R, Which ) :-
 | |
|      ( var(Which) ->
 | |
|           fail_term( internal_error_in_recovering_from_halt(R) )
 | |
|           ;
 | |
|           true
 | |
|      ).
 | |
| r_halted_recovery( [rs(AliasH,StreamsH,DataH)|T], R, Which ) :-
 | |
|      ( R == AliasH ->
 | |
|           r_session_data( at_r_halt, DataH, AtHalt ),
 | |
|           r_halted_recovery_action( AtHalt, AliasH, StreamsH, DataH, Which )
 | |
|           ;
 | |
|           assertz(r_session(AliasH,StreamsH,DataH))
 | |
|      ),
 | |
|      r_halted_recovery( T, R, Which ).
 | |
| 
 | |
| r_halted_recovery_action( restart, Alias, _Streams, Data, RecCall ) :-
 | |
|      Mess = 'at_r_halt(restart): restarting r_session ':Alias,
 | |
|      RecCall = (write( user_error, Mess ),nl( user_error )),
 | |
|      r_session_data( opts, Data, Opts ),
 | |
|      ( memberchk(copy(CopyTo,_),Opts) ->
 | |
|           r_halted_restart_copy(CopyTo)
 | |
|           ;
 | |
|           true
 | |
|      ),
 | |
|      r_open_1( Opts, Alias, true ),
 | |
|      current_r_session( Alias, Streams, _ ),
 | |
|      r_lines( Streams, output, _ReLines ).
 | |
| r_halted_recovery_action( reinstate, Alias, _Streams, Data, RecCall ) :-
 | |
|      ( r_session_history(Alias,History) ->
 | |
|           r_session_data( opts, Data, Opts ),
 | |
|           r_open_1( Opts, Alias, true ),
 | |
|           reverse( History, Hicory ),
 | |
|           r_halted_recovery_rollback( Hicory, Alias )
 | |
|           ;
 | |
|           fail_term( 'at_r_halt(reinstate): cannnot locate history for':Alias )
 | |
|      ),
 | |
|      Mess = 'at_r_halt(reinstate): reinstating r_session ':Alias,
 | |
|      RecCall = (write( user_error, Mess ), nl( user_error ) ).
 | |
| r_halted_recovery_action( abort, _Alias, _Streams, _Data, RecCall ) :-
 | |
|      Mess = 'at_r_halt(abort): R session halted by slave',
 | |
|      RecCall = (write( user_error, Mess ),nl( user_error ),abort).
 | |
| r_halted_recovery_action( fail, Alias, _Streams, _Data, Call ) :-
 | |
|      retractall( r_session_history(Alias,_) ),
 | |
|      % % r_session_data( copy_to, Data, CopyTo ),
 | |
|      % write( copy_to(CopyTo) ), nl,
 | |
|      % ( CopyTo = stream(Stream) ->
 | |
|           % close(Stream)
 | |
|           % ;
 | |
|           % true
 | |
|      % ),
 | |
|      L='at_r_halt(fail): failure due to execution halted by slave on r_session',
 | |
|      Call = fail_term( L:Alias ).
 | |
| r_halted_recovery_action( call(Call), _Alias, Streams, _Data, Call ) :-
 | |
|      Call = call( Call, Streams ).
 | |
| r_halted_recovery_action( call_ground(Call), _Alias, _Streams, _Data, Call) :-
 | |
|      Call = call( Call ).
 | |
| 
 | |
| r_halted_restart_copy( CopyTo ) :-
 | |
|      ((atomic(CopyTo),File=CopyTo);CopyTo=once(File)),
 | |
|      File \== user,      % you never known
 | |
|      !,
 | |
|      open( File, read, Dummy ),
 | |
|      stream_property( Dummy, file_name(Full) ),
 | |
|      close( Dummy ),
 | |
|      ( stream_property(OpenStream,file_name(Full)) ->
 | |
|           write( close(OpenStream) ), nl,
 | |
|           close( OpenStream )
 | |
|           ;
 | |
|           true
 | |
|      ).
 | |
| r_halted_restart_copy( _CopyTo ).
 | |
| 
 | |
| r_halted_recovery_rollback( [], _Alias ).
 | |
| r_halted_recovery_rollback( [H|T], Alias ) :-
 | |
|      r_in( Alias, H, _Halted ),
 | |
|      r_halted_recovery_rollback( T, Alias ).
 | |
| 
 | |
| 
 | |
| r_record_history( true, _Alias, _This ).
 | |
| r_record_history( false, Alias, This ) :-
 | |
|      r_session_history( Alias, Old ),
 | |
|      !,
 | |
|      retractall( r_session_history(Alias,_) ),
 | |
|      assert( r_session_history(Alias,[This|Old]) ).
 | |
| r_record_history( false, _, _ ). % fold with true if assumption is correct
 | |
| 
 | |
| r_read_lines_1( eof, _TermLine, _Ro, Lines ) :- !, Lines = [].
 | |
| r_read_lines_1( end_of_file, _TermLine, _Ro, Lines ) :- !, Lines = [].
 | |
| r_read_lines_1( [255], _TermLine, _Ro, Lines ) :- !, Lines = [].
 | |
|      % yap idiosyncrasy
 | |
| r_read_lines_1( TermLine, TermLine, _Ro, Lines ) :- !, Lines = [].
 | |
| r_read_lines_1( Line, TermLine, Ro, [Line|Lines] ) :-
 | |
|      read_line_to_codes( Ro, NewLine ),
 | |
|      r_read_lines_1( NewLine, TermLine, Ro, Lines ).
 | |
| 
 | |
| r_boolean( Boo, Rboo ) :-
 | |
|      ( memberchk(Boo,[t,true,'TRUE']) ->
 | |
|           Rboo = 'TRUE'
 | |
|           ;
 | |
|           memberchk(Boo,[f,false,'FALSE']),
 | |
|           Rboo = 'FALSE'
 | |
|      ).
 | |
| 
 | |
| r_read_list( [], [] ).
 | |
| r_read_list( [PreH|T], List ) :-
 | |
|      delete_leading( PreH, 0' , H ),
 | |
|      ( H = [0'[|Hrm] ->
 | |
|           break_list_on( Hrm, 0'], _, Hprv ),
 | |
|           delete_leading( Hprv, 0' , Hproper )
 | |
|           ;
 | |
|           Hproper = H
 | |
|      ),
 | |
|      r_read_list_line( Hproper, List, ConTail ),
 | |
|      r_read_list( T, ConTail ).
 | |
| 
 | |
| r_read_list_line( [], List, List ).
 | |
| r_read_list_line( [0' |RRead], List, ConTail ) :-
 | |
|      !,
 | |
|      r_read_list_line( RRead, List, ConTail ).
 | |
| r_read_list_line( [Fst|RRead], [H|List], ConTail ) :-
 | |
|      break_list_on( RRead, 0' , RemCs, RemNumCs ),
 | |
|      !,
 | |
|      number_codes( H, [Fst|RemCs] ),
 | |
|      r_read_list_line( RemNumCs, List, ConTail ).
 | |
| r_read_list_line( [Fst|RemCs], [H|List], List ) :-
 | |
|      number_codes( H, [Fst|RemCs] ).
 | |
| 
 | |
| r_streams( [], _R, [] ).
 | |
| r_streams( [H|T], R, [SH|ST] ) :-
 | |
|      !,
 | |
|      r_stream( H, R, SH ),
 | |
|      r_streams( T, R, ST ).
 | |
| 
 | |
| r_streams( Id, R, Stream ) :-
 | |
|      r_stream( Id, R, Stream ).
 | |
| 
 | |
| r_stream( H, R, SH ) :-
 | |
|      % current_r_session( R ),
 | |
|      ( var(H) ->
 | |
|           fail_term( variable_stream_identifier )
 | |
|           ;
 | |
|           true
 | |
|      ),
 | |
|      ( r_streams_data( H, R, SH ) ->
 | |
|           true
 | |
|           ;
 | |
|           fail_term( invalid_r_stream:H )
 | |
|      ).
 | |
| 
 | |
| /*
 | |
| r_terminator( r(Ri,Ro,_Re), Lines ) :-
 | |
|      write( Ri, 'print(\"prolog_eoc\")' ),
 | |
|      nl( Ri ),
 | |
|      r_read_lines_till( Ro, "[1] \"prolog_eoc\"", Lines ).
 | |
| 
 | |
| r_read_lines_till( Ro, Terminator, Lines ) :-
 | |
|      fget_line( Ro, Line ),
 | |
|      r_read_lines_till_1( Line, Terminator, Ro, Lines ).
 | |
| 
 | |
| r_read_lines_till_1( Line, Line, _Ro, Lines ) :-
 | |
|      !,
 | |
|      Lines = [].
 | |
| r_read_lines_till_1( Line, Terminator, Ro, [Line|Lines] ) :-
 | |
|      fget_line( Ro, NxLine ),
 | |
|      NxLine \== eof,
 | |
|      r_read_lines_till_1( NxLine, Terminator, Ro, Lines ).
 | |
| */
 | |
| 
 | |
| r_open_opt_copy( Opts, CpTerm, What, Rcv ) :-
 | |
|      ( (memberchk(copy(Cp,CpWh),Opts),Cp \== null) ->
 | |
|           % heere
 | |
|           ( ((catch(is_stream(Cp),_,fail),CpS=Cp);Cp=stream(CpS)) ->  % catch = yap bug
 | |
|                CpTerm = stream(CpS)
 | |
|                ;
 | |
|                ( atomic(Cp) ->
 | |
|                     ( Rcv==true -> Mode = append; Mode = write ),
 | |
|                     open( Cp, Mode, CpStream ),
 | |
|                     CpTerm = stream(CpStream)
 | |
|                     ;
 | |
|                     ( Cp = once(CpFile) ->
 | |
|                          ( Rcv==true -> Mode = append; Mode = write ),
 | |
|                          open( CpFile, Mode, CpStream ),
 | |
|                          CpTerm = stream(CpStream)
 | |
|                          ;
 | |
|                          ( Cp = many(CpFile) ->
 | |
|                               CpTerm = file(CpFile)
 | |
|                               ;
 | |
|                               fail_term( 'I cannot decipher 1st argument of copy/2 option':Cp )
 | |
|                          )
 | |
|                     )
 | |
|                )
 | |
|           ),
 | |
|           ( memberchk(CpWh,[both,none,in,out])->
 | |
|                What = CpWh
 | |
|                ;
 | |
|                fail_term( 'I cannot decipher 2nd arg. to copy/2 option':CpWh )
 | |
|           )
 | |
|           ;
 | |
|           CpTerm = null, What = none
 | |
|      ).
 | |
| 
 | |
| r_open_opt_at_r_halt( Opts, RHalt ) :-
 | |
|      ( memberchk(at_r_halt(RHalt),Opts) ->
 | |
|           Poss = [restart,reinstate,fail,abort,call(_),call_ground(_)],
 | |
|           ( memberchk(RHalt,Poss) ->
 | |
|                true
 | |
|                ;
 | |
|                fail_term( 'Cannot decipher argument to at_r_halt option':RHalt )
 | |
|           )
 | |
|           ;
 | |
|           RHalt = fail
 | |
|      ).
 | |
| 
 | |
| r_bin_arguments( Opts, _Rbin, _RArgs ) :-
 | |
|      member( with(With), Opts ),
 | |
|      \+ memberchk(With, [environ,restore,save] ),
 | |
|      !,
 | |
|      fail_term( 'Cannot decipher argument to option with/1': With ).
 | |
| r_bin_arguments( Opts, Rbin, Args ) :-
 | |
|      ( current_prolog_flag(windows,true) ->
 | |
|           Args = ['--ess','--slave'|RArgs]
 | |
|           ; % assuming unix here, --interactive is only supported on these
 | |
|           ( r_bin_takes_interactive(Rbin) ->
 | |
|                Args = ['--interactive','--slave'|RArgs]
 | |
|                ;
 | |
|                Args = ['--slave'|RArgs]
 | |
|           )
 | |
|      ),
 | |
|      findall( W, member(with(W),Opts), Ws ),
 | |
|      sort( Ws, Sr ),
 | |
|      length( Ws, WsL ),
 | |
|      length( Sr, SrL ),
 | |
|      ( WsL =:= SrL ->
 | |
|           r_bin_arguments_complement( [environ,restore,save], Ws, RArgs )
 | |
|           ;
 | |
|           fail_term( 'Multiple identical args in with/1 option': Ws )
 | |
|      ).
 | |
| 
 | |
| % r_opt_exec_no( [environ,restore,save], Ws, Pfx, Exec ) :-
 | |
| r_opt_exec_no( [], _Ws, [] ).
 | |
| r_opt_exec_no( [H|T], Ws, Exec ) :-
 | |
|      ( memberchk(H,Ws) ->
 | |
|           TExec=Exec
 | |
|           ;
 | |
|           atom_concat( '--no-', H, NoH ),
 | |
|           Exec=[NoH|TExec]
 | |
|      ),
 | |
|      r_opt_exec_no( T, Ws, TExec ).
 | |
| 
 | |
| r_bin_arguments_complement( [], _Ws, [] ).
 | |
| r_bin_arguments_complement( [H|T], Ws, Args ) :-
 | |
|      ( memberchk(H,Ws) ->
 | |
|           % we could add explicit --with- here ?
 | |
|           Args = TArgs
 | |
|           ;
 | |
|           atom_concat( '--no-', H, NoH ),
 | |
|           Args = [NoH|TArgs]
 | |
|      ),
 | |
|      r_bin_arguments_complement( T, Ws, TArgs ).
 | |
| 
 | |
| r_record_lines( [], _Type, _CopyTo ) :- !.
 | |
| r_record_lines( Lines, Type, CopyTo ) :-
 | |
|      ( CopyTo == null ->
 | |
|           true
 | |
|           ;
 | |
|           copy_stream_open( CopyTo, CopyStream ),
 | |
|           r_lines_print( Lines, Type, CopyStream )
 | |
|      ).
 | |
| 
 | |
| r_record_term( CopyThis, CopyTo, This ) :-
 | |
|      ( CopyThis == in; CopyThis == both),
 | |
|      CopyTo \== null,
 | |
|      !,
 | |
|      copy_stream_open( CopyTo, CopyOn ),
 | |
|      write( CopyOn, This ),
 | |
|      nl( CopyOn ),
 | |
|      copy_stream_close( CopyTo ).
 | |
| r_record_term( _CopyThis, _CopyTo, _This ).
 | |
| 
 | |
| copy_stream_open( stream(CopyStream), CopyStream ).
 | |
| copy_stream_open( file(File), CopyStream ) :-
 | |
|      open( File, append, CopyStream ).
 | |
| 
 | |
| copy_stream_close( Atom ) :-
 | |
|      atomic( Atom ),
 | |
|      !,
 | |
|      ( Atom == user ->
 | |
|           true
 | |
|           ;
 | |
|           close( Atom )
 | |
|      ).
 | |
| copy_stream_close( CopyTo ) :-
 | |
|      copy_stream_close_non_atomic( CopyTo ).
 | |
| 
 | |
| copy_stream_close_non_atomic( file(CopyTo) ) :- close( CopyTo ).
 | |
| copy_stream_close_non_atomic( once(CopyTo) ) :- close( CopyTo ).
 | |
| copy_stream_close_non_atomic( many(CopyTo) ) :- close( CopyTo ).
 | |
| copy_stream_close_non_atomic( stream(_) ).
 | |
| 
 | |
| /*
 | |
| write_list_to_comma_separated( [], _Sep, _Out ).
 | |
| write_list_to_comma_separated( [H|T], Sep, Out ) :-
 | |
|      write( Out, Sep ),
 | |
|      write( Out, H ),
 | |
|      write_list_to_comma_separated( T, ',', Out ).
 | |
|      */
 | |
| 
 | |
| fail_term( Term ) :-
 | |
|      ( Term = What:Which ->
 | |
|           write( user_error, What ),
 | |
|           write( user_error, ': ' ),
 | |
|           write( user_error, Which )
 | |
|           ;
 | |
|           write( user_error, Term )
 | |
|      ),
 | |
|      nl( user_error ), fail.
 | |
| 
 | |
| r_lines( Streams, ROstream, Lines ) :-
 | |
|      r_streams_data( input,  Streams, Ri ),
 | |
|      r_streams_data( ROstream,  Streams, Ro ),
 | |
|      ( ROstream == error ->
 | |
|           Mess = 'message("prolog_eoc")',
 | |
|           Trmn = "prolog_eoc"
 | |
|           ;
 | |
|           Mess = 'print("prolog_eoc")',
 | |
|           Trmn = "[1] \"prolog_eoc\""
 | |
|      ),
 | |
|      Excp = error(io_error(write, _), context(_,_)),
 | |
|      catch( (write(Ri,Mess),nl(Ri)), Excp, true ),
 | |
|      r_read_lines( Ro, Trmn, Lines ).
 | |
| 
 | |
| r_lines_print_type_stream( output, user_output ).
 | |
| r_lines_print_type_stream( error, user_error ).
 | |
| 
 | |
| r_lines_print_prefix( error, Stream ) :- write( Stream, '!  ' ).
 | |
| r_lines_print_prefix( output, _Stream ).
 | |
| 
 | |
| r_session_skolem( Alias, I ) :-
 | |
|      Alias = '$rsalias'(I),
 | |
|      \+ r_session( Alias, _, _ ),
 | |
|      !.
 | |
| r_session_skolem( Alias, I ) :-
 | |
|      NxI is I + 1,
 | |
|      r_session_skolem( Alias, NxI ).
 | |
| 
 | |
| r_process_was_successful( Ri, Ro, Re ) :-
 | |
|      Mess = 'message("prolog_eoc")',
 | |
|      Trmn = "prolog_eoc",
 | |
|      catch( (write(Ri,Mess),nl(Ri)), Excp, true ),
 | |
|      r_read_lines( Re, Trmn, Lines ),
 | |
|      r_lines_print( Lines, error, user_error ),
 | |
|      ( (var(Excp),Lines==[]) ->
 | |
|           true
 | |
|           ;
 | |
|           ( Excp = error(io_error(write, _), context(_,_)) ->
 | |
|                true
 | |
|                ;
 | |
|                print_message( error, Excp )
 | |
|           ),
 | |
|           close( Ri ), close( Ro ), close( Re ),
 | |
|           fail_term( failed_to_open_session )
 | |
|      ).
 | |
| 
 | |
| %%%%%%%%
 | |
| % break_list_on( +List, +Element, ?LeftPartition, ?RightPartition ).
 | |
| % Element does not appear in either the end of LeftPartition,
 | |
| % or as first element of RightPartition.
 | |
| % Only finds first partition so Element should be ground
 | |
| % | ?- break_list_on( L, El, [a], [c,b,d,b,e] ).
 | |
| %  = [a,El,c,b,d,b,e] ? ; no
 | |
| %
 | |
| break_list_on( [X|Xs], X, [], Xs ) :-
 | |
| 	!.
 | |
| break_list_on( [X|Xs], Xa, [X|XLa], XRa ) :-
 | |
| 	break_list_on( Xs, Xa, XLa, XRa ).
 | |
| 
 | |
| delete_leading( [], _Chop, [] ).
 | |
| delete_leading( [H|T], Chop, Clean ) :-
 | |
|      ( H == Chop ->
 | |
|           R = T,
 | |
|           Clean = TClean
 | |
|           ;
 | |
|           R = [],
 | |
|           Clean = [H|T]
 | |
|      ),
 | |
|      delete_leading( R, Chop, TClean ).
 | |
| 
 | |
| options_have_ssh( Opts, Host, Dir ) :-
 | |
|      ( memberchk(ssh(Host),Opts) ->
 | |
|           Dir = '/tmp'
 | |
|           ;
 | |
|           memberchk( ssh(Host,Dir), Opts )
 | |
|      ).
 | |
| 
 | |
| locate_rbin( Ssh, RBin ) :-
 | |
|      locate_rbin_file( File ),
 | |
|      ( var(Ssh) ->
 | |
| 	 (
 | |
| 	     current_prolog_flag(windows,true)
 | |
| 	 ->
 | |
| 		Exe='exe',
 | |
| 		file_name_extension( File, Exe, RBin )
 | |
| 	    ;
 | |
| 	    File = RBin
 | |
| 	)
 | |
|      ->
 | |
|         exists_file( RBin )
 | |
|     ;
 | |
|           % currently when we using ssh, there is no check for existance
 | |
|           % of the binary on the remote host
 | |
|           File = RBin
 | |
|      ),
 | |
|      r_verbose( using_R_bin(RBin), 1 ).
 | |
| 
 | |
| % order of clauses matters. only first existing one to succeed is considered.
 | |
| locate_rbin_file( RBin ) :-
 | |
|      % current_predicate( r_bin/1 ),
 | |
|      r_bin_location( RBin ).
 | |
| locate_rbin_file( RBin ) :-
 | |
|      environ( 'R_BIN', RBin ).
 | |
| locate_rbin_file( RBin ) :-
 | |
|      current_prolog_flag( unix, true ),
 | |
|      which( 'R', RBin ).
 | |
| locate_rbin_file( RBin ) :-
 | |
|      current_prolog_flag( windows, true ),
 | |
|      r_bin_wins( RBin ).
 | |
| 
 | |
| r_bin_wins( Rbin ) :-
 | |
|      r_expand_wins_rterm( Stem, Candidates ),
 | |
|      r_verbose( wins_candidates(Candidates), 3 ),
 | |
|      Candidates \== [],
 | |
|      ( Candidates = [Rbin] -> 
 | |
|           true
 | |
|           ;
 | |
|           maplist( atom_concat(Stem), Tails, Candidates ),
 | |
|           maplist( atom_codes, Tails, TailsCs ),
 | |
|           cur_tail_candidates_with_pair( TailsCs, Candidates, Pairs ),
 | |
|           keysort( Pairs, Sorted ),
 | |
|           reverse( Sorted, [_-Rbin|_] )
 | |
|      ),
 | |
|      !.
 | |
| 
 | |
| cur_tail_candidates_with_pair( [], [], [] ).
 | |
| cur_tail_candidates_with_pair( [H|T], [F|R], [Hnum-F|TPairs] ) :-
 | |
|      ( break_list_on( H, 0'/, Hlft, _ ) -> true; break_list_on( H, 0'\\, Hlft, _) ),
 | |
|      break_list_on( Hlft, 0'., MjCs, NonMjCs ),
 | |
|      break_list_on( NonMjCs, 0'., MnCs, FxCs ),
 | |
|      maplist( number_codes, Nums, [MjCs,MnCs,FxCs] ),
 | |
|      integers_list_to_integer( Nums, 2, 1000, 0, Hnum ),
 | |
|      cur_tail_candidates_with_pair( T, R, TPairs ).
 | |
| 
 | |
| integers_list_to_integer( [], _Pow, _Spc, Int, Int ).
 | |
| integers_list_to_integer( [H|T], Pow, Spc, Acc, Int ) :-
 | |
|      Nxt is Acc + ( H * (Spc ** Pow) ),
 | |
|      Red is Pow - 1,
 | |
|      integers_list_to_integer( T, Red, Spc, Nxt, Int ).
 | |
| 
 | |
| r_bin_warning :-
 | |
|      write('Flag --interactive which is used when starting R sessions,'),
 | |
|      nl,
 | |
|      write( 'is not behaving as expected on your installed R binary.' ), nl,
 | |
|      write( 'R sessions with this binary will be started without this flag.' ),
 | |
|      nl, 
 | |
|      write( 'As a result, graphic windows will suffer and the connection is' ),
 | |
|      write( ' more flaky.' ), nl,
 | |
|      write( 'If you want to overcome these limitations we strongly suggest' ),
 | |
|      nl,
 | |
|      write( 'the installation of R from sources.' ), nl, nl.
 | |
| 
 | |
| r_bin_takes_interactive( Rbin ) :-
 | |
|      r_bin_takes_interactive( Rbin, Bool ),
 | |
|      !,
 | |
|      Bool == true.
 | |
| r_bin_takes_interactive( Rbin ) :-
 | |
|      Args = ['--interactive','--slave','--no-environ','--no-restore','--no-save'],
 | |
|      r_process( Rbin, Args, Ri, Ro, Re ),
 | |
|      r_streams_set( Ri, Ro, Re ),
 | |
|      % Streams = r(Ri,Ro,Re),
 | |
|      write( Ri, 'print("whatever")' ), nl( Ri ),
 | |
|      % r_read_lines( Re, eof, RoLns ),
 | |
|      % read_line_to_codes( Re, _ReLns ),
 | |
|      % r_lines( Streams, error, ReLns ),
 | |
|      % r_lines( Streams, output, RoLns ),
 | |
|      read_line_to_codes( Ro, RoLn ),
 | |
|      ( append("print", _, RoLn ) ->
 | |
|           r_bin_warning,
 | |
|           Bool = false
 | |
|           ;
 | |
|           Bool = true
 | |
|      ),
 | |
|      assert( r_bin_takes_interactive(Rbin,Bool) ),
 | |
|      write( Ri, 'q()' ), nl( Ri ),
 | |
|      read_line_to_codes( Re, _ReLn ), 
 | |
|      % write( Ri, 'message("whatever")' ), nl( Ri ),
 | |
|      close( Ri ), close( Ro ), close( Re ),
 | |
|      Bool == true.
 | |
| 
 | |
| % Section: Yap Specifics.
 | |
| 
 | |
| atoms_concat( Atoms, Concat ) :-
 | |
|      atom_concat( Atoms, Concat ).
 | |
| 
 | |
| which( Which, This ) :-
 | |
|      SshStrs = [null,pipe(SshWhc),null],
 | |
|      atom_concat( 'which ', Which, ProcWhich ),
 | |
|      exec( ProcWhich, SshStrs, _ ),
 | |
|      read_line_to_codes( SshWhc, Codes),
 | |
|      atom_codes( This, Codes ),
 | |
|      r_verbose( which(Which,This), 2 ).
 | |
| 
 | |
| r_streams_set( _Ri, _Ro, _Re ).
 | |
| 
 | |
| r_process( Exec, Args, Ri, Ro, Re ) :-
 | |
|      space_out_by_atom( Args, SpcArgs ),
 | |
|      atoms_concat( [Exec,' '|SpcArgs], Full ),
 | |
|      Streams = [pipe(Ri),pipe(Ro),pipe(Re)], 
 | |
|      r_verbose( creating(Full,Streams), 3 ),
 | |
|      exec( Full, Streams, _ ).
 | |
| 
 | |
| r_bin_version_pl( R, Mj:Mn:Fx ) :-
 | |
|      Streams = [std,pipe(Ro),std],
 | |
|      atom_concat( R, ' --version', Rv ),
 | |
|      exec( Rv, Streams, _ ),
 | |
|      % read_line_to_codes( Ro, _ ),
 | |
|      read_line_to_codes( Ro, Codes ),
 | |
|      break_list_on( Codes, 0' , _R, Psf1 ),
 | |
|      break_list_on( Psf1, 0' , _V, Psf2 ),
 | |
|      break_list_on( Psf2, 0' , VersionCs, _ ),
 | |
|      break_list_on( VersionCs, 0'., MjCs, VPsf1Cs ),
 | |
|      break_list_on( VPsf1Cs, 0'., MnCs, FxCs ),
 | |
|      number_codes( Mj, MjCs ),
 | |
|      number_codes( Mn, MnCs ),
 | |
|      number_codes( Fx, FxCs ).
 | |
| 
 | |
| space_out_by_atom( [], [] ).
 | |
| space_out_by_atom( [A|T], R ) :-
 | |
|      ( T == [] ->
 | |
|           R = [A|M]
 | |
|           ;
 | |
|           R = [A,' '|M]
 | |
|      ),
 | |
|      space_out_by_atom( T, M ).
 | |
|  
 | |
| % r_bin_wins( _ ) :-
 | |
|      % r_expand_wins_rterm( _ ).
 | |
|      % fail.     % I don't know how to do this in Yap...
 | |
| 
 | |
| r_expand_wins_rterm( WinsStem, Candidates ) :-
 | |
|      PfsR = 'C:/Program Files/R/',
 | |
|      % WinsStem = 'C:\\Program Files\\R\\R-',          % yap 5-1-3
 | |
|      WinsStem = 'C:/Program Files/R/R-',               % yap 6-0-3
 | |
|      file_exists( PfsR ),                              % works for dirs as well in Yap
 | |
|      directory_files( PfsR, Files ),
 | |
|      Psf = '/bin/Rterm.exe',
 | |
|      sieve_r_term_containers( Files, PfsR, Psf, Candidates ).
 | |
| 
 | |
| sieve_r_term_containers( [], _Pfx, _Psf, [] ).
 | |
| sieve_r_term_containers( [H|T], Pfx, Psf, Cs ) :-
 | |
|      atom_concat( H, Psf, HPsf ),
 | |
|      atom_concat( Pfx, HPsf, C ),
 | |
|      ( file_exists(C) -> 
 | |
|           Cs = [C|TCs]
 | |
|           ;
 | |
|           Cs = TCs
 | |
|      ),
 | |
|      sieve_r_term_containers( T, Pfx, Psf, TCs ).
 | |
| 
 | |
| 
 | |
| exists_file( File ) :-
 | |
|      file_exists( File ).
 | |
| 
 | |
| double_quote_on_yap( InArgs, Args ) :-
 | |
|      append( ['"'|InArgs], ['"'], Args ).
 |