git.fiddlerwoaroof.com
runtime/io-primitives.scm
4e987026
 
 ;;; These are the IO primitives used by PreludeIOPrims
 
 ;;; Note: the box in write-string-stdout, write-string-file, and
 ;;;  append-string-file are due to the NoConversion in the .hi file.
 ;;; The problem is that NoConversion applies to everything, not just
 ;;; the input arg that the conversion is not needed or.
 
 
 (predefine (notify-input-request))
 
 (define *emacs-notified* '#f)
 (define *stdin-read* '#f)
 
 (define (initialize-io-system)
   (setf *emacs-notified* '#f)
   (setf *stdin-read* '#f))
 
 (define (io-success . res)
   (make-tagged-data 0
     (if (null? res)
 	(box 0)
 	(box (make-haskell-string (car res))))))
 
 (define (io-success/bin res)
   (make-tagged-data 0 (box res)))
 
 (define (io-success/lazy res)
   (make-tagged-data 0 res))
 
 (define (io-failure string)
   (make-tagged-data 1 (box (make-haskell-string string))))
 
 ; primReadStringFile
 (define (prim.read-string-file filename)
   (if (file-exists? filename)
       (let ((str (call-with-input-file filename
 		   (lambda (port)
 		     (port->string port)))))
 	(io-success str))
       (io-failure (format '#f "File not found: ~A~%" filename))))
 
 (define (port->string port)
   (call-with-output-string
    (lambda (string-port)
      (copy-till-eof port string-port))))
 
 (define (copy-till-eof in-port out-port)
   (do ((ch (read-char in-port) (read-char in-port)))
       ((eof-object? ch))
     (write-char ch out-port)))
 
 ; primWriteStringFile
 (define (prim.write-string-file filename contents state)
  (declare (ignore state))
  (box
   (let ((stream (lisp:open (haskell-string->string filename)
 			   :direction :output 
 			   :if-exists :overwrite
 			   :if-does-not-exist :create)))
     (print-haskell-string contents stream)
     (close-output-port stream)
     (io-success))))
         
 ;primAppendStringFile
 (define (prim.append-string-file filename contents state)
  (declare (ignore state))
  (box
   (let ((stream (lisp:open (haskell-string->string filename)
 			   :direction :output 
 			   :if-exists :append
 			   :if-does-not-exist '())))
     (cond ((not (eq? stream '()))
            (print-haskell-string contents stream)
            (close-output-port stream)
 	   (io-success))
           (else
 	   (io-failure "Can't open file"))))))
 
 ; primReadBinFile
 (define (prim.read-bin-file name)
   (let ((bin (lisp-read name)))
     (if (and (pair? bin) (eq? (car bin) ':binary))
 	(io-success/bin bin)
 	(io-failure "Not a bin file"))))
 
 ; primWriteBinFile
 (define (prim.write-bin-file name contents)
   (let ((stream (lisp:open name :direction :output 
 			   :if-exists :overwrite
 			   :if-does-not-exist :create)))
     (write (cons ':binary contents) stream)
     (close-output-port stream)
     (io-success)))
 
 ; primAppendBinFile
 (define (prim.append-bin-file name contents)
  (let ((bin (lisp-read name)))
    (if (and (pair? bin) (eq? (car bin) ':binary))
        (let ((stream (lisp:open name :direction :output :if-exists :overwrite)))
 	 (write (append bin contents) stream)
 	 (io-success))
        (io-failure "Can't open Bin file"))))
 
 ; primDeleteFile
 (define (prim.delete-file name)
   (if (file-exists? name)
       (if (lisp:delete-file name)
 	  (io-success)
 	  (io-failure "Can't delete file"))
       (io-failure "File not found")))
 
 ; primStatusFile
 (define (prim.status-file name)
   (if (file-exists? name)
       (io-success "frw")
       (io-failure (format '#f "File ~A not found" name))))
 
 ;primReadStdin
 (define (prim.read-string-stdin state)
   (declare (ignore state))
   (cond (*stdin-read*
 	 (haskell-runtime-error "Multiple ReadChan from stdin"))
 	(else
 	 (setf *stdin-read* '#t)
 	 (delay (read-next-char)))))
 
 (define (read-next-char)
   (when (and *emacs-mode* (not *emacs-notified*))
     (setf *emacs-notified* '#t)
     (notify-input-request))
   (let ((ch (read-char)))
     (if (eof-object? ch)
 	'()
 	(cons (box (char->integer ch))
 	      (delay (read-next-char))))))
 
 ; primWriteStdout
 (define (prim.write-string-stdout string state)
   (declare (ignore state))
   (print-haskell-string string (current-output-port))
   (box (io-success)))
 
 ; primReadBinStdin
 (define (prim.read-bin-stdin)
   (haskell-runtime-error  "ReadBinChan not implemented"))
 
 ; primWriteBinStdout
 (define (prim.write-bin-stdout bin)
   (declare (ignore bin))
   (haskell-runtime-error  "WriteBinChan not implemented"))
 
 ;;; %%% probably bogus
 ; primGetEnv
 (define (prim.getenv name)
   (io-success (getenv name)))
 
 (define (lisp-read file)
   (if (not (file-exists? file))
       'error
       (call-with-input-file file
         (lambda (port)
 	  (lisp:read port '#f 'error '#f)))))
 
 (define-integrable (prim.returnio x s)
   (declare (ignore s))
   x)
 
 (define-integrable (prim.getstate x)
   (declare (ignore x))
   'state)
 
 (define-integrable (prim.getres x)
   (force x))