% arrow_repl - Instantiate arrow system and drop into REPL.
%
% arrow_repl ::
%    arrow(_:arglist(N),_:arglist(M),S)  ~'arbitrary arrow',
%    {[N]->size}                         ~'sizes of inputs'
%    options {
%       gui      :: boolean/false ~'create Java GUI for viewables'
%    }
% -> _.
%
% This function provides a command line with access to a live
% system instantiated from the given arrow. The command line
% has the prompt 'unit>> ' to distinguish it from the normal
% Matlab prompt, but in other respects, is the same. The only
% commands that function differently are 'quit' and 'exit',
% which are trapped and behave as 'return' does, returning control
% to this function. Arbitrary values can be returned through to
% the called of arrow_repl using ret, eg
%   unit>> ret(get_state(),45);  
% returns two values: the current state of the system and the
% value 45.
%
% The environment contains the following variables of interest:
%    sys  :: arrow(A,B,S).          % the original arrow
%    unit :: unit(A,B,S).           % the live processing unit
%    get_state :: () -> S.          % returns the state of the system
%    set_state :: S -> action ().   % sets the state of the system
%
% Other useful functions which can operate on the live unit
% are: ugather, uiterate, ufold and utransfer.


function varargout=arrow_repl(sys,sizes_in,varargin)
	opts = prefs('gui',0,varargin{:});
	[varargout{1:nargout}]=with_arrow(sys,@unit_repl,sizes_in,opts,'keyboard',0,'pause',0);

	function varargout=unit_repl(unit)
		returns={};
		try
			fprintf('\n\nEntering REPL. Type "return","exit", or "quit" to finish.\n');
			fprintf('The function ret(..) sets return values.\n\n');
			cont=true;
			while cont,
				str=input('unit>> ','s');
				if strcmp(str,'quit') break; end
				if strcmp(str,'exit') break; end
				if strcmp(str,'return') break; end
				try, eval(str)
				catch ex
					fprintf('\n%s\n',getReport(ex));
				end
			end
		catch ex
			if ~isempty(uihandles), delete(uihandles); end
			rethrow(ex);
		end
		varargout=returns;

		function set_state(s), unit.set_state(s); end
		function s=get_state, s=unit.get_state(); end
		function ret(varargin), returns=varargin; cont=false; end
	end
end
