;;; Guile object channel
;; Copyright (C) 2001, 2006, 2009, 2010 Free Software Foundation, Inc.
;;;; This library is free software; you can redistribute it and/or
;;;; modify it under the terms of the GNU Lesser General Public
;;;; License as published by the Free Software Foundation; either
;;;; version 3 of the License, or (at your option) any later version.
;;;;
;;;; This library 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
;;;; Lesser General Public License for more details.
;;;;
;;;; You should have received a copy of the GNU Lesser General Public
;;;; License along with this library; if not, write to the Free Software
;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
;;; Commentary:
;; Now you can use Guile's modules in Emacs Lisp like this:
;;
;; (guile-import current-module)
;; (guile-import module-ref)
;;
;; (setq assq (module-ref (current-module) 'assq))
;; => ("<guile>" %%1%% . "#<primitive-procedure assq>")
;;
;; (guile-use-modules (ice-9 documentation))
;;
;; (object-documentation assq)
;; =>
;; " - primitive: assq key alist
;; - primitive: assv key alist
;; - primitive: assoc key alist
;; Fetches the entry in ALIST that is associated with KEY. To decide
;; whether the argument KEY matches a particular entry in ALIST,
;; `assq' compares keys with `eq?', `assv' uses `eqv?' and `assoc'
;; uses `equal?'. If KEY cannot be found in ALIST (according to
;; whichever equality predicate is in use), then `#f' is returned.
;; These functions return the entire alist entry found (i.e. both the
;; key and the value)."
;;
;; Probably we can use GTK in Emacs Lisp. Can anybody try it?
;;
;; I have also implemented Guile Scheme mode and Scheme Interaction mode.
;; Just put the following lines in your ~/.emacs:
;;
;; (require 'guile-scheme)
;; (setq initial-major-mode 'scheme-interaction-mode)
;;
;; Currently, the following commands are available:
;;
;; M-TAB guile-scheme-complete-symbol
;; M-C-x guile-scheme-eval-define
;; C-x C-e guile-scheme-eval-last-sexp
;; C-c C-b guile-scheme-eval-buffer
;; C-c C-r guile-scheme-eval-region
;; C-c : guile-scheme-eval-expression
;;
;; I'll write more commands soon, or if you want to hack, please take
;; a look at the following files:
;;
;; guile-core/ice-9/channel.scm ;; object channel
;; guile-core/emacs/guile.el ;; object adapter
;; guile-core/emacs/guile-emacs.scm ;; Guile <-> Emacs channels
;; guile-core/emacs/guile-scheme.el ;; Guile Scheme mode
;;
;; As always, there are more than one bugs ;)
;;; Code:
(define-module (ice-9 channel)
:export (make-object-channel
channel-open
channel-print-value
channel-print-token))
;;;
;;; Channel type
;;;
(define channel-type
(make-record-type 'channel '(stdin stdout printer token-module)))
(define make-channel (record-constructor channel-type))
(define (make-object-channel printer)
(make-channel (current-input-port)
(current-output-port)
printer
(make-module)))
(define channel-stdin (record-accessor channel-type 'stdin))
(define channel-stdout (record-accessor channel-type 'stdout))
(define channel-printer (record-accessor channel-type 'printer))
(define channel-token-module (record-accessor channel-type 'token-module))
;;;
;;; Channel
;;;
(define (channel-open ch)
(let ((stdin (channel-stdin ch))
(stdout (channel-stdout ch))
(printer (channel-printer ch))
(token-module (channel-token-module ch)))
(let loop ()
(catch #t
(lambda ()
(channel:prompt stdout)
(let ((cmd (read stdin)))
(if (eof-object? cmd)
(throw 'quit)
(case cmd
((eval)
(module-use! (current-module) token-module)
(printer ch (eval (read stdin) (current-module))))
((destroy)
(let ((token (read stdin)))
(if (module-defined? token-module token)
(module-remove! token-module token)
(channel:error stdout "Invalid token: ~S" token))))
((quit)
(throw 'quit))
(else
(channel:error stdout "Unknown command: ~S" cmd)))))
(loop))
(lambda (key . args)
(case key
((quit) (throw 'quit))
(else
(format stdout "exception = ~S\n"
(list key (apply format #f (cadr args) (caddr args))))
(loop))))))))
(define (channel-print-value ch val)
(format (channel-stdout ch) "value = ~S\n" val))
(define (channel-print-token ch val)
(let* ((token (symbol-append (gensym "%%") '%%))
(pair (cons token (object->string val))))
(format (channel-stdout ch) "token = ~S\n" pair)
(module-define! (channel-token-module ch) token val)))
(define (channel:prompt port)
(display "channel> " port)
(force-output port))
(define (channel:error port msg . args)
(display "ERROR: " port)
(apply format port msg args)
(newline port))
;;;
;;; Guile 1.4 compatibility
;;;
(define guile:eval eval)
(define eval
(if (= (car (procedure-minimum-arity guile:eval)) 1)
(lambda (x e) (guile:eval x e))
guile:eval))
(define object->string
(if (defined? 'object->string)
object->string
(lambda (x) (format #f "~S" x))))
;;; channel.scm ends here