source: trunk/j/src/org/armedbear/lisp/top-level.lisp @ 4056

Last change on this file since 4056 was 4056, checked in by piso, 20 years ago

Initial checkin.

File size: 5.2 KB
Line 
1;;; top-level.lisp
2;;;
3;;; Copyright (C) 2003 Peter Graves
4;;; $Id: top-level.lisp,v 1.1 2003-09-25 18:19:04 piso Exp $
5;;;
6;;; This program is free software; you can redistribute it and/or
7;;; modify it under the terms of the GNU General Public License
8;;; as published by the Free Software Foundation; either version 2
9;;; of the License, or (at your option) any later version.
10;;;
11;;; This program is distributed in the hope that it will be useful,
12;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
13;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14;;; GNU General Public License for more details.
15;;;
16;;; You should have received a copy of the GNU General Public License
17;;; along with this program; if not, write to the Free Software
18;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19
20;;; Adapted from SB-ACLREPL (originally written by Kevin Rosenberg).
21
22(in-package "TOP-LEVEL")
23
24(defparameter *command-char* #\:)
25
26(defvar *cmd-number* 1
27  "Number of the next command")
28
29(defun prompt-package-name ()
30  (car (sort (append
31              (package-nicknames cl:*package*)
32              (list (package-name cl:*package*)))
33             (lambda (a b) (< (length a) (length b))))))
34
35(defun repl-prompt-fun (stream)
36  (fresh-line stream)
37  (write-string (prompt-package-name) stream)
38  (write-string "(" stream)
39  (princ *cmd-number* stream)
40  (write-string "): " stream))
41
42(defparameter *repl-prompt-fun* #'repl-prompt-fun)
43
44(defvar *last-files-loaded* nil)
45
46(defun peek-char-non-whitespace (stream)
47  (loop
48    (let ((c (read-char stream nil)))
49      (unless (eql c #\Space)
50        (unread-char c stream)
51        (return c)))))
52
53(defun read-cmd (stream)
54  (let ((c (peek-char-non-whitespace stream)))
55    (if (eql c *command-char*)
56        (read-line stream)
57        (read stream nil))))
58
59(defun tokenize (string)
60  (do* ((res nil)
61        (string (string-left-trim " " string)
62                (string-left-trim " " (subseq string end)))
63        (end (position #\Space string) (position #\Space string)))
64       ((zerop (length string)) (nreverse res))
65    (unless end
66      (setf end (length string)))
67    (push (subseq string 0 end) res)))
68
69(defun process-cmd (form)
70  (when (and (stringp form) (> (length form) 1) (eql (char form 0) *command-char*))
71    (let* ((pos (position #\Space form))
72           (cmd (subseq form 1 pos))
73           (args (if pos (subseq form (1+ pos)) nil)))
74      (when args
75        (setf args (string-trim " " args))
76        (when (zerop (length args))
77          (setf args nil)))
78      (cond ((string= cmd "ld")
79             (let ((files (if args (tokenize args) *last-files-loaded*)))
80               (setf *last-files-loaded* files)
81               (dolist (file files)
82                 (load file)))
83             )
84            ((string= cmd "de")
85             (let ((obj (eval (read-from-string args))))
86               (describe obj)))
87            ((string= cmd "ap")
88             (apropos args))
89            ((string= cmd "pwd")
90             (format t "~A~%" *default-pathname-defaults*))
91            ((string= cmd "cd")
92             (cond ((or (null args) (string= args "~"))
93                    (setf args (namestring (user-homedir-pathname))))
94                   ((and (> (length args) 1) (string= (subseq args 0 2) "~/")
95                    (setf args (concatenate 'string
96                                            (namestring (user-homedir-pathname))
97                                            (subseq args 2))))))
98             (let ((dir (probe-directory args)))
99               (if dir
100                   (progn
101                     (setf *default-pathname-defaults* dir)
102                     (format *standard-output* "~A" (namestring *default-pathname-defaults*)))
103                   (format *standard-output* "Error: no such directory (~S).~%" args))))
104            ((string= cmd "ex")
105             (format t "Bye!~%")
106             (exit))
107            (t
108             (format *standard-output* "Unknown top-level command ~S.~%" cmd)
109             )))
110    (return-from process-cmd t))
111  nil)
112
113(defun repl-read-form-fun (in out)
114  (loop
115    (let ((form (read-cmd in)))
116      (setf (charpos out) 0)
117      (incf *cmd-number*)
118      (cond ((process-cmd form)
119             (funcall *repl-prompt-fun* *standard-output*)
120             (finish-output *standard-output*))
121            (t
122             (return form))))))
123
124(defparameter *repl-read-form-fun* #'repl-read-form-fun)
125
126(defun interactive-eval (form)
127  (setf - form)
128  (let ((results
129   (multiple-value-list (eval form))))
130    (setf /// //
131    // /
132    / results
133    *** **
134    ** *
135    * (car results)))
136  (setf +++ ++
137  ++ +
138  + -)
139  (values-list /))
140
141(defun repl-fun ()
142  (loop
143    (funcall *repl-prompt-fun* *standard-output*)
144    (finish-output *standard-output*)
145    (let* ((form (funcall *repl-read-form-fun*
146                          *standard-input*
147                          *standard-output*))
148           (results (multiple-value-list (interactive-eval form))))
149      (dolist (result results)
150        (fresh-line)
151        (prin1 result)))))
152
153(defvar *in-top-level-loop* nil)
154
155(defun top-level-loop ()
156  (setf *in-top-level-loop* t)
157  (loop
158    (catch 'top-level
159      (handler-case
160          (repl-fun)
161        (error (c) (format t "Error: ~S.~%" c) (throw 'top-level nil))))))
Note: See TracBrowser for help on using the repository browser.