#import std #import nat #import flo #import stt #comment -[ some routines to interface with command line interpreters Copyright (C) 2007-2010 Dennis Furey]- #library+ -------------------------------------------------------- constants --------------------------------------------------------- eof = 4%cOi& # end of file character ---------------------------------------------------- data structures -------------------------------------------------------- #optimize+ shell :: # interface specification of a command line interpreter opener %s # command to invoke the shell login %sLWL # password negotiation protocol, if required prompt %scLU # shell prompt to expect settings %sL # commands to be executed when the shell opens declarer %fOZ ~declarer||0!! # takes an assignment (n: m) to a client that binds the value of m to the symbol n releaser %fOZ ~releaser||0!! # takes an assignment (n: m) to a client that releases the storage for the symbol n closers %sL # commands to close the shell answerer %fOZ ~answerer||~&! # postprocessor for answers returned by the ask function, taking %ssLA nop %s # shell command that does nothing, used by ask, usually just the empty string wrapper %fOZ ~wrapper||~&! # postprocessor to the client generated by sh for anything not covered above ------------------------------------------- functions pertaining to protocols ------------------------------------------------ (# A protocol is represented as a list of pairs of lists of strings <(,)..>, such that the client sends the commands and waits for the prompts. If the last list of prompts is <>, the client will wait until the server closes the connection. If the last list of prompts is <''>, the client will close the connection upon sending the last command. Otherwise, the client will close the connection when the last prompt is received. This semantics is a consequence of the virtual machine's interact combinator calling conventions. #) handshake = ^|DrlXS(:/''+ ~&iNC,* --<''>+ ~&iNC) # takes a prompt string and a list of command strings to a protocol completing = ~&i&& ^lrNCT/~&y ~&\<>+ ~&zl # takes a protocol to one that waits for the server to close the connection closing = ~&i&& ^lrNCT/~&y ~&\<''>+ ~&zl # takes a protocol to one that ends with the client closing the connection -------------------------------------------------- functions of clients ----------------------------------------------------- watch = ~&iNHiF+ interact # takes a client to a verbose trace of type %scLULL exec = ~&Z&&+ !+ ~&NiX\<>+ ~&iNC # takes a string to a client that executes only one command expect = # takes a protocol to a client usable as an argument to the interact combinator %scLULWLMk; ~&i&& (~&?^\!+~&hr ~&l?\0!+ ~&l;+ =:+ ~&t)+ -+ %aaZscLULWXXLMk+ ~&a^& :^\~&fatPR ^/~&ahl ^\~&ahr ~&atihlPB, %ascLULWXLMk+ ^p\~& %aLMk+ ~&aahPNfatPRXfatPRNXQaaXqS+ ~&xrSPS+ zipp0*+ ~&ziD+ iol+- (# seq takes a prompt p to a function that takes a list of clients to their sequential composition in a shell with prompt p. If any client closes the connection, interaction with the next one starts immediately. If any client waits for the server to close the connection (with <>), the prompt <'',p> is expected instead (i.e., p preceded by a line break), any accompanying command from the client has a line break appended, and the interaction of the next client commences when <'',p> is received. If the initial output of the next client is a single string, a line break is appended to the command, and if its initial prompt is a single string, a line break is inserted in the prompt. #) seq = "p". :-0 ~&l?\~&r ~&r?\~&l ~&lNH?\~&r ~&rNH?\~&l ("f","g"). -!~&Z,~&ll==&l!-?( "f"+~&ilrPrXB; ~&?( <>?=rr(~&/&+ ~&\<'',"p">+ ~&rl,^|\~& ~&/&l), ! ^|(~&/&r,^|(~&t?/~& --<''>,-!~&ZtY,==<>!-?/~& ~&NiC)) "g" 0), &?=l(! ^|(~&/&r,^|(~&t?/~& --<''>,-!~&ZtY,==<>!-?/~& ~&NiC)) "g" 0,(~&i&& ^|\~& ~&/&r)+ "g"+ ~&lrPrX)) (# When used as a wrapper in a shell, prompt_counter substitutes \n in prompt strings with a count that's incremented each time starting from 1. #) prompt_counter = "f". -+ ~&r&& (~&i&& ~&r; any substring/'\n')?rr\~&lrlPXrrPX -+ %ngXsLWXMk+ ^/~&lrlPX ^/~&rrl ^H\~&rrr '\n'%=*+ ~&h+ %nP+ ~&l, %ngsLWXXMk+ ^\~&r ~&rrlihtYB?/successor+~&l ~&l+-, %ngsLWXXMk+ ~&?(^/~&ll "f"+ ~&lrPrX,! ~&NiX "f" 0)+- ------------------------------------------------------- specific shells ---------------------------------------------------- #optimize- bash = # system command line interpreter shell[ opener: 'bash --noediting', prompt: '$ ', settings: <'export PS1="$ " PS2="$ "','set +H'>, declarer: %sI?m( ("n","m"). exec 'export '--"n"--'="'--"m"--'"', ("n","m"). seq'$ ' < exec 'touch '--"n", (sh shell[opener: 'ed '--"n",settings: <'%d','a'>,closers: <'.','wq'>])/<> ~='.'*~ "m">), releaser: %sI?m/0! exec+ 'rm '--+ ~&n, closers: <'exit'>] psh = shell opener:='psh'! bash R = # statistical package shell[ opener: 'R -q', prompt: '> ', declarer: expect+ completing+ handshake/'> '+ -? %eLI+~&m: :^( ^T/~&n '=rep(0,'--+ --')'+ ~&h+ %nP+ length+ ~&m, ^D(~&n,num+~&m); * ^T/~&l ~&r; ^T('['--+ --']='+ ~&h+ %nP+ successor+ ~&l,printf/'%0.20e'+ ~&r)), %eLLI+~&m: :^( ^T/~&n '=matrix(0,'--+ --')'+ ^T(~&l,:/`,+ ~&r)+ ~&bh+ %nP~~+ length~~+ ~&m; ^/~& ~&z+ leql-<, ^D(~&n,num+~&m); *= -+ * ^T/~&l ~&r; ^T('['--+ --']'+ ^T/~&l :/`,+ ~&h+ %nP+ successor+ ~&rl,:/`=+ printf/'%0.20e'+ ~&rr), ^D/~&l ~&r; ^D\num+~&r ~&h+ %nP+ successor+~&l+-), %eI+~&m: ^TNC/~&n :/`=+ printf/'%0.20e'+ ~&m, -&~&,%sLI&-+~&m: :^(~&lrhPX; ^|T/~& ' <- '--,~&rt)+ ^lrNCT(~&y,--';'+ ~&z)+ ~&m, <'unknown R type'>!%?-, closers: <'q()'>] octave = # numerical package shell[ opener: 'octave --q --no-line-editing', prompt: '> ', settings: <'PS1=''> ''','PS2='' > ''','split_long_rows=0','format hex','PAGER="cat"'>, declarer: expect+ completing+ handshake/'> '+ -? %eLLI+~&m: :^/(^T/~&n '=eye('--+ --');'+ ^|T(~&,:/`,)+ ~&bh+ %nP~~+ length~~+ ~&mmhPX) ^D(~&n,num+~&m); *= -+ * ^T( ^T/~&l ~&r; '('--+ --')'+ ^T/~&l :/`,+ ~&h+ %nP+ successor+ ~&rl, ~&r; :/`=+ --';'+ printf/'%0.20e'+ ~&rr), ^D/~&l ~&r; ^D\num+~&r ~&h+ %nP+ successor+~&l+-, %eLI+~&m: :^/(^T/~&n '=(1:'--+ --')'';'+ ~&h+ %nP+ length+ ~&m) ^D(~&n,num+~&m); * ^T( ^|T/~& '('--+ --')'+ ~&h+ %nP+ successor+ ~&l, :/`=+ --';'+ printf/'%0.20e'+ ~&rr), %eI+~&m: ^TNC/~&n :/`=+ --';'+ printf/'%0.20e'+ ~&m, -&~&,%sLI&-+~&m: :^(~&nmhPX; ^|T/~& ' = '--,~&mt), <'unknown octave type'>!%?-, closers: <'quit'>, answerer: ||~& (substring/' ='+ ~&ihB)&& ~&itZBhiQ+ ~&F+ * sep` ; -+ ~&itZBhiQ+ octhex*, *~ eql/'0000000000000000'&& subset\digits--'abcdef'+-] gap = # group theory package shell[ opener: 'gap -b -n', prompt: 'gap> ', settings: <'ColorPrompt(false);'>, declarer: expect+ completing+ handshake/'> '+ -+ ^lrNCT(~&y,--';'+ ~&z)+ '<'%=*'['+ '>'%=*']', :^(~&lrhPX; ^|T/~& ':='--,~&rt)^/~&n ~&m; -| -|%nI&& %nP,%nLI&& %nLP,%nLLI&& %nLLP|-, -&%sLI,any substring/'function',~&i&-, ''''%=*'"'+ '"'%=*'\"'+ -|%sI&& %sP,%sLI&& %sLP,%sLLI&& %sLLP|-, ~&l?('/1'%=*''+ ~&r,~&r)+ -? %qI: ^\%qP ~&rr=='1', %qLI: ^\%qLP all ~&rr=='1', %qLLI: ^\%qLLP all all ~&rr=='1', <'unknown gap type'>!%?-|-+-, wrapper: //+ ||~& -& -&~&,~&r,~&rr==<'','gap> '>&-&& ~&rl; -&~&,~&t,~&ttZ,~&thZ&-&& ~&h; -&~&,~&z~=`;&-, &rlh:= --';'+ ~&rlh&-, closers: <'quit;'>] gp = # number theoretic computer algebra system shell[ opener: 'gp -q', prompt: '? ', settings: 'default'--* <'(colors,no)','(output,0)','(readline,0)','(prompt_cont,"? ")','(format,"e0.28")'>, declarer: expect+ completing+ handshake/''+ ^lrNCT(--'\'*+ ~&y,--';'+ ~&z)^C(^|T/~& ' = '--+ ~&h,~&rt)^/~&n ~&m; -| -?%nI: %nP,%qI: %qP,%eI: ~&iNC+ printf/'%0.20e',%EI: ~&iNC+ mpfr..mp2str,%sI: ~&iNC,0!?-, -?%nLI: ~&hS+ %nP*,%qLI: ~&hS+ %qP*,%eLI: printf/*'%0.20e',%ELI: * mpfr..mp2str,-&%sLI,all ~&wZ/`=&-: ~&,0!?-; ~&i&& -+ ^C\~&t '['--+ ~&h, ^lrNCT(--','*+ ~&y,--']'+ ~&z)+-, -?%nLLI: ~&hSS+ %nP**,%qLLI: ~&hSS+ %qP**,%eLLI: printf/**'%0.20e',%ELLI: mpfr..mp2str**,%sLLI: ~&,0!?-; ~&i&& -+ ^C('['--+ ~&h,~&t)+ ~&L+ ^lrNCT(~&y; * ^lrNCT/~&y --';'+ ~&z,~&z; ^lrNCT/~&y --']'+ ~&z), * ^lrNCT(--','*+ ~&y,~&z)+-, %sLI?/~& <'unknown gp type'>!%|-, closers: <'\q'>] maxima = # computer algebra shell[ opener: 'maxima --quiet --disable-readline', prompt: '(%i\n) ', settings: <'display2d: false;'>, declarer: expect+ completing+ handshake/''+ -+ ^lrNCT(~&y,--'$'+ ~&z)^C\~&rt ^|T/~& ': '--+ ~&h, ^/~&n ~&m; %sI?/~&iNC %sLI?/~& <'unknown maxima type'>!%+-, closers: <'quit();'>, nop: '0$', wrapper: prompt_counter; //+ ||~& -& -&~&,~&r,~&rr; -&~&,~&hZ,~&t,~&ttZ,~&t=]'(%i'&-&-&& ~&rl; -&~&,~&t,~&ttZ,~&thZ&-&& ~&h; -&~&,~&z~<';$'&-, &rlh:= --';'+ ~&rlh&-, answerer: ~&ihZBtiQ; =]'(%o'?ihB\~& :^\~&t ~&ritB+ ~=` -~+ ~&h] axiom = # computer algebra shell[ opener: 'axiom -noht -nogr -nogr -nox', prompt: '(\n) -> ', settings: <')set quit unprotected'>, declarer: expect+ completing+ handshake/''+ ^lrNCT(--'_'*+ ~&y,--';'+ ~&z)^C(^|T/~& ' := '--+ ~&h,~&rt)^/~&n ~&m; -| -?%nI: %nP,%qI: %qP,%eI: ~&iNC+ printf/'%0.20e',%EI: ~&iNC+ mpfr..mp2str,%sI: ~&iNC,0!?-, -?%nLI: ~&hS+ %nP*,%qLI: ~&hS+ %qP*,%eLI: printf/*'%0.20e',%ELI: * mpfr..mp2str,-&%sLI,all ~&wZ/`=&-: ~&,0!?-; ~&i&& -+ ^C\~&t '['--+ ~&h, ^lrNCT(--','*+ ~&y,--']'+ ~&z)+-, -?%nLLI: ~&hSS+ %nP**,%qLLI: ~&hSS+ %qP**,%eLLI: printf/**'%0.20e',%ELLI: mpfr..mp2str**,%sLLI: ~&,0!?-; ~&i&& -+ ^C('matrix['--+ ~&h,~&t)+ ~&L+ ^lrNCT(~&y; * ^lrNCT/~&y --','+ ~&z,~&z; ^lrNCT/~&y --']'+ ~&z), * ^C('['--+ ~&h,~&t)^lrNCT(--','*+ ~&y,--']'+ ~&z)+-, %sLI?/~& <'unknown axiom type'>!%|-, closers: <')quit'>, wrapper: "f". -+ ~&r&& (~&i&& ~&r; any substring/'\n')?rr\~&lrlPXrrPX -+ %ngXscLULWXMk+ ^/~&lrlPX ^/~&rrl ^H\~&rrr '\n'%=*+ ~&h+ %nP+ ~&l, %ngscLULWXXMk+ -!~&lZ,~&rrlihtihBPYB&& ~&rrlh; not -!=]')',=]'--',=]'++'!-!-?( ^/successor+~&l ~&r, ^/~&l ~&r; ^/~&l ~&r; ^/~&l ~&r; ~&i&& :^/~&h ~&t; ~&i&& ^llTrC\~&t :/13%cOi&+ ~&h)+-, %ngscLULWXXMk+ ~&?(^/~&ll "f"+ ~&lrPrX,! ~&NiX "f" 0)+-, answerer: -+ ~&a^& =]' Loading'?ah\~&a `.?=ahz/~&fatPR ~&fatitB2R, ~=13%cOi&*~*+ ~&rihZtiQB+ -~ ~&+-] scilab = # numerical package shell[ opener: 'scilab -nb -nw -nwni -nogui', prompt: '-->', declarer: expect+ completing+ handshake/'-->'+ ^C(^|T/~& ' = '--+ ~&h,~&rt)^/~&n ~&m; -| -? %nI: %nP, %qI: %qP, %eI: ~&iNC+ printf/'%0.20e', %EI: ~&iNC+ mpfr..mp2str, %bI: ~&?/<'%t'>! <'%f'>!, %sI: ~&iNC+ :/`'+ --'''', 0!?-, (~&i&& :/'['+ --<']'>)+ -? %nLI: ~&hS+ %nP*, %qLI: ~&hS+ %qP*, %eLI: printf/*'%0.20e', %ELI: * mpfr..mp2str, %bLI: * ~&?/'%t'! '%f'!, -&%sLI,all ~&wZ/`=&-: * :/`'+ --'''', 0!?-, (~&i&& ~&K7; :/'[['+ --<']]'>+ mat'][')+ -? %nLLI: ~&hSS+ %nP**, %qLLI: ~&hSS+ %qP**, %eLLI: printf/**'%0.20e', %ELLI: mpfr..mp2str**, %bLLI: * * ~&?/'%t'! '%f'!, %sLLI: * * :/`'+ --'''', 0!?-, %sLI?/~& <'unknown scilab type'>!%|-, answerer: ~=' '*~; `=?=ihBz\~& ~&t, closers: <'quit'>] ---------------------------------------------- functions operating on shells ------------------------------------------------ #optimize+ ssh = sh++ hop sask = ask++ hop sopen = open++ hop multihop = -++-+ hop* su = ("u","p"). shell$i[opener: ! 'su'-- (~&i&& :/` ) "u",login: ! <(<''>,<'word: '>),(<"p",''>,<' '>)>] bash hop = # takes a hostname ho and password p to a nestable function that makes a shell remote ("ho","p"). shell$i[ opener: ! 'ssh'-- (~&i&& :/` ) "ho", login: -+ //~&T <(<''>,<'word: '>),(<"p",''>,<=]'root@'?(':~# '!,':~$ '!) "ho">)>, "s". :/(<~opener "s",''>,<''>) ~login "s"+-] sh = # takes a shell specification to a function that takes an environment and a list of command strings to a client "s". ("e","c"). (~&?(~&,~&!) ~wrapper "s") (seq ~prompt "s") < expect :\~login"s" ^biNC(~opener,~login.&Z&& ~prompt) "s", expect completing handshake ~(prompt,settings) "s", (seq ~prompt "s") ~declarer"s"* "e", expect completing handshake (~prompt "s","c"), (seq ~prompt "s") ~releaser"s"* "e", expect closing handshake ~(prompt,closers) "s"> open = # takes a shell specification to a function taking an environment and a list of clients to a client "s". ("e","c"). (~&?(~&,~&!) ~wrapper "s") (seq ~prompt "s") < expect :\~login"s" ^biNC(~opener,~login.&Z&& ~prompt) "s", expect completing handshake ~(prompt,settings) "s", (seq ~prompt "s") ~&L <~declarer"s"* "e","c",~releaser"s"* "e">, expect closing handshake ~(prompt,closers) "s"> ask = # takes a shell to a function that takes an environment and a list of command strings to a result of type %sLm "s". -+ ^p(~&nS,~answerer"s"*+ ~&mS)+ ~&mF+ rlc~&rititZBPBZ; %sLLLMk; * %sLLCk ~&hihBPtihiyBPBPX; ^A/~&l ~&lrihBPEritBPrQ, %sLLMk+ ~&ritBitB+ ~=<~nop "s",''>-~+ ~&liyB+ ~=<~nop "s",''>~-+ watch+ sh"s"^|/~& :/~nop"s"+ --<~nop "s">+- ------------------------------------------------- functions using shells ---------------------------------------------------- (# now ignores its argument, octhex takes a hexadecimal string to a floating point number, choleski takes a positive definite matrix to a matrix, and eigen takes a symmetric matrix to a list of vectors and values. #) now = ~&hmh+ (ask bash)/<>+ <'date -R'>! octhex = block2; ~&x+ * -$characters ~&iiK0lrNCCS '0123456789abcdef' eigen = ~&itBthm2hmPpBx+ (ask octave)\<'[v,d]=eig(a);','diag(d)','v'>+ ~&ANC/'a' choleski = -|~&ihimitBiK7BPBPB,~&ihmPB&& ~&hm%|-+ (ask octave)\<'chol(a)'>+ ~&ANC/'a' stdmvnorm = # takes (,,<..>) to a standard multivariate normal probability using R -&~&,~&r,eql+~&lrlPX,eql+~&lrrPX,~&rr,eql+~&lrrh2X,~&rr; all_same length&-?\<'abnormal'>!% -+ math..strtod+ (~&i&& ~&z; substring/'Normal Completion')?/~&httt <'abnormal completion'>!%, =]'[1]'*~+ ~&zm+ (ask R)^/<.'lower':+ ~&l,'upper':+ ~&rl,'sigma':+ ~&rr> -+ :/'library(mvtnorm)'+ ~&iNC+ 'print(digits=16,pmvnorm(mean=rep(0,'--+ --'),lower,upper,sigma))', ~&h+ %nP+ length+ ~&l+-+- mvnorm = # takes (,,,<..>) to a multivariate normal probability using R -&~&,~&r,eql+~&lrlPX,eql+~&lrrl2X,~&rrr,eql+~&lrrrh3X,~&rrr; all_same length&-?\<'abnormal'>!% -+ math..strtod+ (~&i&& ~&z; substring/'Normal Completion')?/~&httt <'abnormal completion'>!%, =]'[1]'*~+ ~&zm+ -+ (ask R)\<'library(mvtnorm)','print(digits=16,pmvnorm(mean=means,lower,upper,sigma))'>, <.'lower':+ ~&l,'upper':+ ~&rl,'means':+ ~&rrl,'sigma':+ ~&rrr>+-+- axparse = # parses a list of strings returned by an axiom command of the form expression::InputForm to a tree of strings -&~&r==<'Type:','InputForm'>,~&l&-+ -+ ~&a^?\<'bad S-exp'>!% ')'?=ah/~&NaX '('?=ah\~&ahNVtX ~&NfatPJX; ~&rah~=')'->lxhdPtV2rat2X ~&lrffaRJPX; ~&ral2lCrfarPJPX, ~&itB+ ~&itB+ ~&itB+ ~&L; sep` ; *= rlc neither -='()'+-