From: Chris D. <ct...@so...> - 2008-08-27 02:54:51
|
How do I make a repl server that I can telnet into? The network plumbing is straight forward, but we would like a full repl with the sbcl debugger, etc. It's easy to make a naive version, but that only handles the basics. Presumably I use sb-impl::toplevel-repl, but I can't quite figure out how to do it. (In LispWorks I would use system::listener-top-level) For reference here is the naive repl loop I'm using: (defun run-remote-repl (socket) (let ((stream (sb-bsd-sockets:socket-make-stream socket :input t :output t :buffering :none))) (let ((*standard-output* stream)) (iter (fresh-line) (princ "> ") (for expr :in-stream stream) (iter (for res :in (multiple-value-list (eval expr))) (prin1 res)))))) Cheers, Chris Dean |
From: Pascal J. B. <pj...@in...> - 2008-08-27 07:10:10
|
Chris Dean writes: > > How do I make a repl server that I can telnet into? The network > plumbing is straight forward, but we would like a full repl with the sbcl > debugger, etc. It's easy to make a naive version, but that only > handles the basics. > > Presumably I use sb-impl::toplevel-repl, but I can't quite figure out > how to do it. > > (In LispWorks I would use system::listener-top-level) > > For reference here is the naive repl loop I'm using: > > (defun run-remote-repl (socket) > (let ((stream (sb-bsd-sockets:socket-make-stream socket > :input t :output t > :buffering :none))) > (let ((*standard-output* stream)) > (iter (fresh-line) > (princ "> ") > (for expr :in-stream stream) > (iter (for res :in (multiple-value-list (eval expr))) > (prin1 res)))))) For a basic, standard REPL: http://paste.lisp.org/display/18280 http://paste.lisp.org/display/57465 Now, you will need to also to bind more streams (*error-output*, *standard-input*, etc): (defmacro with-restricted-dynamic-environment (&body body) `(with-output-to-string (*standard-output*) (with-input-from-string (*standard-input* "") (let* ((*print-circle* t) (*print-readably* nil) (*error-output* *standard-output*) (*trace-output* *standard-output*) (*query-io* (MAKE-TWO-WAY-STREAM *standard-input* *standard-output*)) (*terminal-io* *query-io*) (*package* (find-package "RCL-USER")) (*read-eval* nil) (-)) (restart-case (progn ,@body) (abort () :report "Aborted") (continue () :report "Continued") (muffle-warning () :report "Warning muffled") (store-value (value) :report "Value stored") (use-value (value) :report "Value used")))))) And finally you have to decide whether you want to do the debugging on the server or on the client, and in the later case, include *debug-io*, and perhaps add some *debugger-hook*. -- __Pascal Bourguignon__ http://www.informatimago.com/ CONSUMER NOTICE: Because of the "uncertainty principle," it is impossible for the consumer to simultaneously know both the precise location and velocity of this product. |
From: Pascal J. B. <pj...@in...> - 2008-08-27 07:10:13
|
Chris Dean writes: > How do I make a repl server that I can telnet into? Oh, and of course, you can also use slime/swank instead. -- __Pascal_Bourguignon__ _ Software patents are endangering () ASCII ribbon against html email (o_ the computer industry all around /\ 1962:DO20I=1.100 //\ the world http://lpf.ai.mit.edu/ 2001:my($f)=`fortune`; V_/ http://petition.eurolinux.org/ |
From: Thomas F. B. <tbu...@gm...> - 2008-08-27 07:28:51
|
2008/8/27 Chris Dean <ct...@so...>: > > How do I make a repl server that I can telnet into? The network > plumbing is straight forward, but we would like a full repl with the sbcl > debugger, etc. It's easy to make a naive version, but that only > handles the basics. > > Presumably I use sb-impl::toplevel-repl, but I can't quite figure out > how to do it. Yep, you found the right function. To call it yourself, you should set up the standard stream variables (*standard-input*, *debugger-io*, etc) to be bound to your socket, the call (toplevel-repl nil). > (In LispWorks I would use system::listener-top-level) > > For reference here is the naive repl loop I'm using: > > (defun run-remote-repl (socket) > (let ((stream (sb-bsd-sockets:socket-make-stream socket > :input t :output t > :buffering :none))) > (let ((*standard-output* stream)) > (iter (fresh-line) > (princ "> ") > (for expr :in-stream stream) > (iter (for res :in (multiple-value-list (eval expr))) > (prin1 res)))))) > > Cheers, > Chris Dean > > ------------------------------------------------------------------------- > This SF.Net email is sponsored by the Moblin Your Move Developer's challenge > Build the coolest Linux based applications with Moblin SDK & win great prizes > Grand prize is a trip for two to an Open Source event anywhere in the world > http://moblin-contest.org/redirect.php?banner_id=100&url=/ > _______________________________________________ > Sbcl-help mailing list > Sbc...@li... > https://lists.sourceforge.net/lists/listinfo/sbcl-help > |
From: Chris D. <ct...@so...> - 2008-08-27 16:54:44
|
"Thomas F. Burdick" <tbu...@gm...> writes: >> Presumably I use sb-impl::toplevel-repl, but I can't quite figure out >> how to do it. > > Yep, you found the right function. To call it yourself, you should set > up the standard stream variables (*standard-input*, *debugger-io*, > etc) to be bound to your socket, the call (toplevel-repl nil). Great, thanks. Cheers, Chris Dean |
From: Chris D. <ct...@so...> - 2008-08-27 19:15:49
|
For archival purposes (for the next person searching the mailing lists), you also need to execute the repl in a sb-thread:with-new-session block. Here's one example: (defun run-remote-repl (socket) (with-open-stream (stream (sb-bsd-sockets:socket-make-stream socket :buffering :none :input t :output t)) (let ((*terminal-io* stream) (*standard-output* stream) (*standard-input* stream) (*error-output* stream) (*query-io* stream) (*debug-io* stream) (*trace-output* stream)) (format t "~&Welcome to ~a ~a~%" (lisp-implementation-type) (lisp-implementation-version)) (sb-thread:with-new-session () (sb-impl::toplevel-repl nil))))) Cheers, Chris Dean |