#: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
actor-id-hive
actor-id-string
+ actor-am-i-alive?
+
build-actions
define-simple-actor
(define %current-actor
(make-parameter #f))
+(define (actor-am-i-alive? actor)
+ (hive-resolve-local-actor (actor-hive actor) (actor-id actor)))
+
\f
;;; Actor utilities
;;; 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)
;;; License along with 8sync. If not, see <http://www.gnu.org/licenses/>.
(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 (<repl-manager>))
-(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 <repl-manager> (<actor>)
+ (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))))
(use-modules (8sync)
(8sync systems irc)
+ (8sync repl)
(oop goops)
(srfi srfi-37)
(ice-9 format)
(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))
#:username username
#:server server
#:channels channels))
+ (define repl-manager
+ (cond
+ ((string? repl)
+ (hive-create-actor* hive <repl-manager> "repl"
+ #:path repl))
+ (repl
+ (hive-create-actor* hive <repl-manager> "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))
** 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