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))
|