a1k0n : Andy Sloane's weblog

Lisp REPL in Vendetta Online

Vendetta Online has a Lisp environment (using SBCL) which controls much of its NPC behavior and will soon be in charge of generating player and NPC missions. Partly in order to get around some thread-safety issues, and partly for convenience we built an REPL into a secret chat channel. (it only responds to developer accounts)



It also handles errors by printing a quick and dirty stack trace:


Here's the code for the stack dump handler, for interested readers:
(defun trap-and-log-error-handler (condition)
  (format t "Error signalled: ~A~%" condition)
  ;; this (write-string (with-output-to-string (s) ...) thing is odd,
  ;; but seemingly necessary because print-frame-call seems
  ;; uncooperative when using t for a stream argument.
  (write-string (with-output-to-string (s)
		  (do ((frame (sb-di:top-frame) (sb-di:frame-down frame))
		       (i 0 (1+ i)))
		      ((null frame))
		    (format s "~a: " i)
		    (sb-debug::print-frame-call frame s)
		    (format s "~%")))))

(defmacro trap-and-log-errors (&body body)
  `(ignore-errors
     (handler-bind ((error #'trap-and-log-error-handler))
       ,@body)))

and here's the REPL code (trap-and-log-errors is somewhere upstream from where this is called)
;;; this is what interprets "eval" requests from developers; we have a
;;; simple color code tag involving the non-printable character 
;;; (code-char 127), so return values show up in red (like in SLIME)

(define-server-function eval (&rest cmd)
  (flet ((format-return-value (return-val)
	   (with-output-to-string (os)
	     (with-input-from-string (s (format nil "~s~&" return-val))
	       (loop for line = (read-line s nil)
		     while line do
		     (format os "~aff0000~a~%" (code-char 127) line))))))
    (let ((return-val (multiple-value-list (eval `(progn
						   (in-package :com.guildsoftware.deliverator)
						   ,@cmd)))))
      (format t "~&")
      (dolist (val return-val)
	(write-string (format-return-value val))))))


Why didn't I just use sb-debug:backtrace? I didn't know about it. I just looked at how SLIME did it.
permalink | | a1k0n.net