git.fiddlerwoaroof.com
Raw Blame History
;;; 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))