123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231 |
- %%% *************************************************************
- %%% Copyright (C) 2009-2013 Torsten Anders (www.torsten-anders.de)
- %%% This program is free software; you can redistribute it and/or
- %%% modify it under the terms of the GNU General Public License
- %%% as published by the Free Software Foundation; either version 2
- %%% of the License, or (at your option) any later version.
- %%% This program is distributed in the hope that it will be useful,
- %%% but WITHOUT ANY WARRANTY; without even the implied warranty of
- %%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- %%% GNU General Public License for more details.
- %%% *************************************************************
- %%
- %% This code implements the Oz-side of the Org-babel Oz interface. It
- %% creates a socket server (to which org-babel-oz.el then
- %% connects). Any input to this socket must be an Oz expression. The
- %% input is fed to the OPI oz compiler, and the results are send back
- %% via the socket.
- %%
- declare
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- %%
- %% Accessing the OPI compiler
- %%
- MyCompiler = Emacs.condSend.compiler
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- %%
- %% Socket interface
- %%
- %%
- %% Create socket
- %%
- MyPort = 6001
- %% !! Alternatively, let it assign automatically and output the port number..
- %%
- %% NOTE: for supporting multiple connections see http:
- proc {MakeServer Host PortNo ?MyServer ?MyClient}
- proc {Accept MyClient}
- thread H in % P
- %% suspends until a connection has been accepted
- {MyServer accept(host:H
- acceptClass:Open.socket
- accepted:?MyClient)}
- % {Myserver accept(host:H port:P)} % suspends until a connection has been accepted
- %% !!?? port number of client is usually created randomly..
- {System.showInfo "% connection accepted from host "#H}
- end
- %% !!???
- %% If Accept is called recursively, then server accepts multiple connections. These share the same compiler instance (e.g. variable bindings are shared). For multiple independent compiler instances call the OzServer application multiple times.
- %% However, how shall the output for multiple connections be sorted?? Would using the different client sockets created with the Server accept method work?
- %% NB: The number of clients accepted concurrently must be limited to the number set by {MyServer listen}
- % {Accept}
- end
- in
- MyServer = {New Open.socket init}
- %% To avoid problems with portnumbers, the port could be assigned automatically and then output..
- %%{MyServer bind(port:PortNo)}
- {MyServer bind(host:Host takePort:PortNo)}
- {MyServer listen}
- {System.showInfo "% OzServer started at host "#Host#" and port "#PortNo}
- MyClient = {Accept}
- end
- %%
- MySocket = {MakeServer localhost MyPort _}
- %%
- %% Read socket input
- %%
- declare
- %% Copied from OzServer/source/Socket.oz
- local
- proc {Aux Socket Size Stream}
- In = {Socket read(list:$
- size:Size)}
- in
- {Wait In}
- %% !! Is this the right way to stop the processing??
- %%
- %% abort condition when client stream ended (i.e. nothing was sent)
- if In == nil
- then {System.showInfo "socket stream ended"}
- Stream = nil
- else Stream = In | {Aux Socket Size}
- end
- end
- in
-
- proc {ReadToStream Socket Size Xs}
- thread {Aux Socket Size Xs} end
- end
- end
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- %%
- %% Send socket input to compiler and send results back to socket
- %%
- %% NOTE: Input code must be expression
- thread
- {ForAll {ReadToStream MySocket 1024}
- proc {$ Code}
- Result
- %% Catch any exception (so the will not cause blocking) and return nil in that case
- FullCode = {Accum ["try\n"
- % "skip\n" % do something in any case..
- Code
- "\ncatch E then {Error.printException E}\n"
- "error\n" % in case of an error, return 'error'
- "end\n"]
- List.append}
- in
- %% ?? Should I make setting switches etc atomic?
- {MyCompiler enqueue(setSwitch(expression true))}
- {MyCompiler enqueue(feedVirtualString(FullCode return(result: ?Result)))}
- {MyCompiler enqueue(setSwitch(expression false))}
- %%
- {Wait Result}
- {MySocket write(vs: if {VirtualString.is Result}
- then Result
- else {Value.toVirtualString Result 1000 1000}
- end)}
- {Show 'Org-babel result: '#Result}
- end}
- end
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- %%
- %% Aux defs
- %%
- proc {Accum Xs Fn Y}
- {List.foldL Xs.2 Fn Xs.1 Y}
- end
-
|