# stream input/output # FIXME: 'read' does not do blocking stuff yet : read-done? try read recover e_eof or-throw drop -1 leave endtry 0 ; "( -- atom ? )\tRead and return success state." doc # MAIN INTERPRETER LOOP # connect an atom generator and interpret until e_eof exception # is encountered on 'read' (e_eof on interpret, i.e. for parsing # words, is still an error) # NOTE: read has to work everywhere as 'read from current input'. # i use dynamic a binding stack for current input stream. # NOTE: abort is a property of the console. no console -> abort = quit # or global application error handler. # FIXME: as opposed to how it was before, the RS is not shielded. this # means it is not possible to perform task switches during # interpretation. # FIXME: the above is a nice example where dynamic-wind is needed: # 'read' uses the input stack as a dynamic variable. i probably need to # fix this because it prevents interpretation in a task context. # debug hook defer interpret-atom ' interpret is interpret-atom # ERROR REPORTING: the idea is to record the location of every 'read' # so ':' can gather this information to create error reporting data. # 'read' is a deferred word, which at boot contains 'read-boot' but by # the time it ends up here contains 'read-top@'. : interpret-current begin try read recover e_eof or-throw # e_eof is not an error here drop drop-input leave endtry try interpret-atom recover drop-input throw endtry again ; "Interprete current stream (input stack) till end. Drop input stack when done." doc # ABSTRACT GENRATOR INTERPRETATION : interpret-generator undef swap >input interpret-current ;; " ( xt -- )\tInterpret output of generator." doc # STREAM INTERPRETATION : interpret-stream stream>input interpret-current ;; "( stream -- )\tInterpret a stream." doc # LIST INTERPRETATION : read-current-list try pop recover e_underflow or-throw e_eof throw endtry ; # ( plist -- atom ) : interpret-list ['] read-current-list >input interpret-current ;; "( list -- )\tInterpret a list." doc # STRING INTERPRETATION : interpret-string open-string interpret-stream ;; # LOADING # save it on rs because script may modify ds : loadscript "r" open-file interpret-stream ; "( filename -- )\tLoad a script (don't search path) and interpret." doc # FIXME: record the packet before the primitives are recorded # or, record the plugin packet together with the primitive word. : loadregplugin loadplugin ` PLUGIN link-constant ; # problem: OSX doesn't like it when you load text files as a # library. the error seems to go undetected and messes up lots of # things. therefore, plugins no longer load using 'load', which is # reserved for scripts. # : loadany # >r r try loadregplugin # try to load as module # recover e_inval or-throw # recover inval error (wrong file type) # 2drop r> loadscript leave # try to load as script # endtry rdrop ; # system path () variable! path : >path path push ; homedir >path homedir "/plugins" concat >path homedir "/script" concat >path # ( filename -- pathified ) : pathify >r path head begin dup @ "/" concat r concat dup exists? if rdrop nip leave # return filename then drop follow dup null = until drop r> ; # ( filename -- ) : load dup exists? if loadscript leave then pathify loadscript ; : pfo dup exists? if loadregplugin leave then pathify loadregplugin ; # SOCKETS : open-listen 1 open-socket ;; "( host/port.list mode -- stream)\tOpen a TCP server socket for listening." doc : open-connect 0 open-socket ;; "( host/port.list mode -- stream)\tOpen a TCP client socket." doc : open-listen-unix 5 open-socket ;; "( node mode -- stream)\tOpen a UNIX server socket for listening." doc : open-connect-unix 4 open-socket ;; "( node mode -- stream)\tOpen a UNIX client socket." doc : open-server-udp 3 open-socket ;; "( host/port.list mode -- stream)\tOpen a UDP server socket for listening." doc : open-client-udp 2 open-socket ;; "( host/port.list mode -- stream)\tOpen a UDP client socket." doc # SELECT and STREAM BUFFERING : serialize string >r r string-write-atom0 "\n" r string-print-atom # newline terminated r> ; # select only input : select-input >r () () 3 list r> select-i/o/e # full posix select wrapper unpack >r drop drop unpack >r drop drop r> r> ; : @poll-input >r r @> 0 select-input r> ! ; "( listvar -- ready )\tUse '0 select-input' on all elements in a listvar, put back the ones that are not ready, and return the ones that are." doc : poll-stream 1 pack 0 select-input drop ; "( stream -- ready )\tPoll a single stream." doc # READ/WRITE single atom to file : write-file "w" open-file write-atom ; "( atom filename -- )\tSave an atom to a file. Can be loaded by 'read-file'." doc : read-file "r" open-file read-atom ; "( filename -- atom )\tLoad an atom from a file. This loads files wriiten by 'write-file'." doc # BLOCKING READERS : slurp (slurp) read-thing ; "( stream -- string )\tRead entire file." doc : read-packet 1 pack read-thing ; "( stream type -- packet)\tRead a raw packet." doc # PROGRAM PIPES : open-program >r ' >string map r> open-inferior ;; "( args mode -- stream )\Open the input or output of a subprocess. The command name and arguments are passed as the 'args' list." doc : shell> "r" open-program slurp ; "( args -- string )\tRun a shell command, return output string. Program name and arguments are in the 'args' list." doc # : >shell "w" open-program >output . output> close ; "( string list -- )\tRun a shell command, send input string. List is program + args" doc # MISC : run interpret-list ; : list>string { ' emit for-each } with-output-to-string ; : read-line (line) read-thing ; "( stream -- string )\tRead line from stream; strip newline character." doc # BLOCKING : open-accept >r dup block-read r> open-accept-nb ; "( serverstream mode -- stream )\tAccept the next connection from a server socket. (blocks task)." doc