On Jan 5, 2008 9:26 AM, Gustavo <[EMAIL PROTECTED]> wrote: > 2008/1/5, Justin Heyes-Jones <[EMAIL PROTECTED]>: > > > As it happens I've been playing with lispbuilder-sdl writing a > > component based engine. [...] > > > > What's nice is you can stop the game, add or remove objects and so on, > > and then restart the engine. When I'm using lispworks I can do that > > without stopping the engine using the repl in lispworks and starting > > the engine in emacs. Presumably theres some way to do that in slime > > and have to repl's on the same lisp? > > > Maybe you can use multiple threads? Threading is implementation dependent, > but there are some libraries that provide portable multi-threading (like > http://common-lisp.net/project/bordeaux-threads/) >
Unfortunately, CLISP does not have working threads and SBCL's threads only work on Unixy platforms as far as I know. In fact, I am not sure any of the major free implementations have threads working on all platforms (except ABCL and ECL, which I don't believe work with lispbuilder-sdl). I would use lispworks except I want to be able to create executables, and the professional edition is exceeding expensive. I am trying to find a workaround that would let me do both the game loop and REPL at the same time (in sequence that is). It should be theoretically possible in the main event loop to update the game, then read all available input without hanging, eval it if amounts to a complete form, for the entire duration of the game. After a bit of coding I managed to write a couple of functions to take input from the keyboard without hanging, and evaluate that input if it forms a complete expression. It's a little buggy, in that SBCL will freeze occasionally until the user presses enter in the repl (it seems to freeze whenever the user clicks the mouse or moves the mouse over the command prompt). In CLISP, the text entered into the repl won't show up until the user presses enter, and CLISP will only pick up one character per enter keystroke (so if one types "hello\n\n\n\n\n" CLISP reads "h\ne\nl\nl\no\n"). I can't get lispworks to load lispbuilder-sdl so I can't tell you how it works in lispworks. Comments and suggestions are welcome. Thanks for your time if you managed to get through reading all this. Here is my code (more or less): ;; Banner, prompt, and input line for REPL. (defvar *banner* "Welcome to the REPL.") (defvar *input-prompt* "~&[~a]> ") (defvar *input-line* 0) ;; Used to catch end-of-file conditions (e.g. when calling (read) on "(+ 2 2"; used to allow multiline input). (defun trap-eof-handler (condition) (throw 'trap-eofs (values nil nil))) (defmacro trap-eofs (&rest forms) `(catch 'trap-eofs (handler-bind ((end-of-file #'trap-eof-handler)) ,@forms))) ;; Wrap read and parse functions in closures. (let ((input-string "")) ;; Read without hanging, put input into input-string. (defun read-repl (&optional input-stream (eof-error-p t) eof-value recursive-p) (setf input-string (do* ((char (read-char-no-hang input-stream eof-error-p eof-value recursive-p) (read-char-no-hang input-stream eof-error-p eof-value recursive-p)) (input (if char (cons char nil) nil) (if char (cons char input) input))) ((not char) (concatenate 'string input-string (nreverse input)))))) ;; Parse contents of input-string if they form a complete input. ;; The second return value signals whether or not a complete input was recieved, to differentiate between user entered nil and no input. (defun parse-repl () (with-input-from-string (input-stream input-string) (trap-eofs (values (prog1 (read input-stream) (clear-repl) (read-repl input-stream nil)) t)))) ;; Clear input-string. (defun clear-repl () (setf input-string ""))) ;; Print banner and first prompt and exit. (defun enter-repl () (let ((package *package*)) ; (in-package :bt) ; Normally used to control eval environment (unwind-protect (progn (format t "~&~a~&" *banner*) (incf *input-line*) (format t *input-prompt* *input-line*) (force-output)) (setf *package* package)))) ;; Eval input and reprint prompt if complete, otherwise return immediately. (defun update-repl () (let ((package *package*)) ; (in-package :bt) ; Normally used to control eval environment (unwind-protect (progn (read-repl) (multiple-value-bind (input exists) (parse-repl) (when exists (trap-errors (format t "~&~s~&" (eval input))) (incf *input-line*) (format t *input-prompt* *input-line*) (force-output)))) (setf *package* package)))) So now my main function looks like this: (defvar *running* t) (defun main () (sdl:with-init (sdl:sdl-init-video) ; init code... (enter-repl) (sdl:with-events () (:key-down-event (:key key) (cond ((sdl:key= key :sdl-key-backquote) (setf *running* (not *running*))))) (:idle () (when *running* ; render, update, etc... ) (update-repl))))) -- Elliott Slaughter "Any road followed precisely to its end leads precisely nowhere." - Frank Herbert
_______________________________________________ application-builder mailing list application-builder@lispniks.com http://www.lispniks.com/mailman/listinfo/application-builder