From 6a8dc6f801cc08e1b92dce53fc8a3758c9b0718a Mon Sep 17 00:00:00 2001 From: Christopher Allan Webber Date: Mon, 26 Dec 2016 20:13:23 -0600 Subject: [PATCH] actors: Add new method of running REPL via REPL actor. Also adds new procedure to see if an actor is alive, and make use of it in the new REPL actor. * 8sync/actors.scm (actor-am-i-alive?): New procedure. (ez-run-hive): Remove #:repl-server keyword. * 8sync/repl.scm (, repl-manager-cleanup, repl-manager-init): New variables. * demos/ircbot.scm (parse-args): Add --repl command line option. (run-bot): Add and queue actor if appropriate. --- 8sync/actors.scm | 20 ++++++--------- 8sync/repl.scm | 53 +++++++++++++++++++++++++++------------- demos/ircbot.scm | 22 +++++++++++++++-- doc/8sync-new-manual.org | 33 +++++++++++++++++++++++++ 4 files changed, 96 insertions(+), 32 deletions(-) diff --git a/8sync/actors.scm b/8sync/actors.scm index 886e114..1927465 100644 --- a/8sync/actors.scm +++ b/8sync/actors.scm @@ -25,7 +25,6 @@ #:use-module (ice-9 match) #:use-module (ice-9 pretty-print) #:use-module (8sync agenda) - #:use-module (8sync repl) #:export (;; utilities... ought to go in their own module big-random-number big-random-number-string @@ -48,6 +47,8 @@ actor-id-hive actor-id-string + actor-am-i-alive? + build-actions define-simple-actor @@ -347,6 +348,9 @@ raise an exception if an error." (define %current-actor (make-parameter #f)) +(define (actor-am-i-alive? actor) + (hive-resolve-local-actor (actor-hive actor) (actor-id actor))) + ;;; Actor utilities @@ -694,21 +698,11 @@ Like create-actor, but permits supplying an id-cookie." ;;; 8sync bootstrap utilities ;;; ========================= -(define* (ez-run-hive hive initial-tasks #:key repl-server) - "Start up an agenda and run HIVE in it with INITIAL-TASKS. - -Should we start up a cooperative REPL for live hacking? REPL-SERVER -wants to know! You can pass it #t or #f, or if you want to specify a port, -an integer." +(define* (ez-run-hive hive initial-tasks) + "Start up an agenda and run HIVE in it with INITIAL-TASKS." (let* ((queue (list->q initial-tasks)) (agenda (make-agenda #:pre-unwind-handler print-error-and-continue #:queue queue))) - (cond - ;; If repl-server is an integer, we'll use that as the port - ((integer? repl-server) - (spawn-and-queue-repl-server! agenda repl-server)) - (repl-server - (spawn-and-queue-repl-server! agenda))) (start-agenda agenda))) (define (bootstrap-message hive to-id action . message-body-args) diff --git a/8sync/repl.scm b/8sync/repl.scm index bc68138..16e2466 100644 --- a/8sync/repl.scm +++ b/8sync/repl.scm @@ -17,23 +17,42 @@ ;;; License along with 8sync. If not, see . (define-module (8sync repl) - #:use-module (ice-9 q) - #:use-module (8sync agenda) + #:use-module (oop goops) + #:use-module (8sync) + #:use-module (system repl server) #:use-module (system repl coop-server) - #:export (make-coop-server-handler - spawn-and-queue-repl-server!)) + #:export ()) -(define (make-coop-server-handler coop-server) - (define (run-self) - (poll-coop-repl-server coop-server) - ;; queue ourselves again - (run-delay (run-self) (/ 1 30))) - run-self) +(define-class () + (path #:init-keyword #:path + #:init-value "/tmp/8sync-socket" + #:getter repl-manager-path) + (socket #:init-value #f + #:accessor repl-manager-socket) + (poll-every #:init-keyword #:poll-every + #:init-value (/ 1 30) + #:getter repl-manager-poll-every) + (actions #:allocation #:each-subclass + ;; @@: Should we add a stop action? + #:init-value (build-actions + (*cleanup* repl-manager-cleanup) + (init repl-manager-init)))) + +(define (repl-manager-cleanup repl-manager message) + ;; Close the socket, if open + (and=> (repl-manager-socket repl-manager) + close) + ;; Delete the file, if it exists + (when (file-exists? (repl-manager-path repl-manager)) + (delete-file (repl-manager-path repl-manager)))) + +(define (repl-manager-init repl-manager message) + (define socket + (make-unix-domain-server-socket #:path (repl-manager-path repl-manager))) + (define server + (spawn-coop-repl-server socket)) + (set! (repl-manager-socket repl-manager) socket) + (while (actor-am-i-alive? repl-manager) + (poll-coop-repl-server server) + (8sleep (repl-manager-poll-every repl-manager)))) -(define* (spawn-and-queue-repl-server! agenda #:optional port) - (let ((coop-server - (if port - (spawn-coop-repl-server port) - (spawn-coop-repl-server)))) - (enq! (agenda-queue agenda) - (make-coop-server-handler coop-server)))) diff --git a/demos/ircbot.scm b/demos/ircbot.scm index b97b572..eaae113 100755 --- a/demos/ircbot.scm +++ b/demos/ircbot.scm @@ -22,6 +22,7 @@ (use-modules (8sync) (8sync systems irc) + (8sync repl) (oop goops) (srfi srfi-37) (ice-9 format) @@ -86,7 +87,10 @@ (option '("channels") #t #f (lambda (opt name arg result) `(#:channels ,(string-split arg #\,) - ,@result)))) + ,@result))) + (option '("repl") #f #t + (lambda (opt name arg result) + `(#:repl ,(or arg #t) ,@result)))) (lambda (opt name arg result) (format #t "Unrecognized option `~a'\n" name) (exit 1)) @@ -104,8 +108,22 @@ #:username username #:server server #:channels channels)) + (define repl-manager + (cond + ((string? repl) + (hive-create-actor* hive "repl" + #:path repl)) + (repl + (hive-create-actor* hive "repl")))) + + (define initial-messages + (if repl + (list (bootstrap-message hive irc-bot 'init) + (bootstrap-message hive repl-manager 'init)) + (list (bootstrap-message hive irc-bot 'init)))) + ;; TODO: load REPL - (ez-run-hive hive (list (bootstrap-message hive irc-bot 'init)))) + (ez-run-hive hive initial-messages)) (define (main args) (define parsed-args (parse-args "ircbot.scm" args)) diff --git a/doc/8sync-new-manual.org b/doc/8sync-new-manual.org index e2bb333..51c670e 100644 --- a/doc/8sync-new-manual.org +++ b/doc/8sync-new-manual.org @@ -405,6 +405,39 @@ What cool commands can you add? ** An intermission: about live hacking +This section is optional, but highly recommended. +It requires that you're a user of GNU Emacs. +If you aren't, don't worry... you can forge ahead and come back in case +you ever do become an Emacs user. +(If you're more familiar with Vi/Vim style editing, I hear good things +about Spacemacs...) + +So you may have noticed while updating the last section that the +start/stop cycle of hacking isn't really ideal. +You might either edit a file in your editor, then run it, or +type the whole program into the REPL, but then you'll have to spend +extra time copying it to a file. +Wouldn't it be nice if it were possible to both write code in a +file and try it as you go? +And wouldn't it be even better if you could live edit a program +while it's running? + +Luckily, there's a great Emacs mode called Geiser which makes +editing and hacking and experimenting all happen in harmony. +And even better, 8sync is optimized for this experience. +8sync provides easy drop-in "cooperative REPL" support, and +most code can be simply redefined on the fly in 8sync through Geiser +and actors will immediately update their behavior, so you can test +and tweak things as you go. + + + + + +# Finally, show off pk + + + ** Battle bot! ** Adding a "rankings" web page -- 2.31.1