summaryrefslogtreecommitdiff
path: root/src/gizmo/wasp-bless.el
blob: 109b2f353c1a621b5ecdf1789668a07df5b672e8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
;;; wasp-bless --- The Blessing -*- lexical-binding: t; -*-
;;; Commentary:
;;; Code:

(require 'cl-lib)
(require 'dash)
(require 's)
(require 'json)
(require 'wasp-chat)
(require 'wasp-model)

(defcustom w/bless-buffer " *wasp-bless*"
  "Name of buffer used to store Bless output."
  :type '(string)
  :group 'wasp)

(defun w/bless-error (e)
  "Report an error E."
  (message (alist-get 'message e)))

(defun w/bless-parse-value (j)
  "Construct an Emacs Lisp value representation of the value J."
  (let ((tag (alist-get 'tag j)))
    (cond
     ((s-equals? tag "ValueInteger") (alist-get 'contents j))
     ((s-equals? tag "ValueArray")
      (-map #'w/bless-parse-value (alist-get 'contents j)))
     (t (message "Unknown Bless tag: %s" tag)))))

(defun w/bless-parse-effect (j)
  "Construct an Emacs Lisp value representation of the effect J."
  (let ((tag (alist-get 'tag j))
        (c (alist-get 'contents j)))
  (cond
   ((s-equals? tag "EffectPrint") `(print ,(w/bless-parse-value c)))
   ((s-equals? tag "EffectPrintBackwards") `(print-backwards ,(w/bless-parse-value c)))
   ((s-equals? tag "EffectSoundboard") `(soundboard ,(w/bless-parse-value c)))
   ((s-equals? tag "EffectModelToggle") `(model-toggle ,(w/bless-parse-value c)))
   )))

(defun w/bless-parse-stack (j)
  "Construct an Emacs Lisp value representation of the stack J."
  (-map #'w/bless-parse-value j))

(defun w/bless-parse-effects (j)
  "Construct an Emacs Lisp value representation of the effects J."
  (-map #'w/bless-parse-effect j))

(defun w/bless-apply-effect (e)
  "Apply the list of side effects E."
  (cl-case (car e)
    (print (w/write-chat-event (format "%s" (cadr e))))
    (print-backwards (w/write-chat-event (reverse (format "%s" (cadr e)))))
    (soundboard (soundboard//play-clip (cadr e)))
    (model-toggle (w/model-toggle (cadr e)))
    (t (message "Unknown effect tag: %s" (car e)))))

(defun w/bless-eval (str k &optional fuel)
  "Bless STR according to the nature of the blessing.
Pass the result to K.
Optionally limit evaluation to FUEL steps."
  (let ((buf (generate-new-buffer w/bless-buffer)))
    (with-current-buffer buf
      (erase-buffer))
    (make-process
     :name "wasp-bless-eval"
     :buffer buf
     :command `("bless" "-j" "eval" ,@(if fuel (list "--fuel" (number-to-string fuel)) nil) ,str)
     :sentinel
     (lambda (_ _)
       (let* ((s (with-current-buffer buf (buffer-string)))
              (j (json-read-from-string s))
              (status (alist-get 'status j)))
         (kill-buffer buf)
         (if (s-equals? status "success")
             (funcall
              k
              (cons
               (w/bless-parse-stack (alist-get 'stack (alist-get 'data j)))
               (w/bless-parse-effects (alist-get 'effects (alist-get 'data j)))))
           (w/bless-error (alist-get 'data j))))))))

(defun w/bless (str &optional fuel)
  "Run the Bless program STR and apply its side effects.
Optionally limit evaluation to FUEL steps."
  (w/bless-eval
   str
   (lambda (res)
     (--each (cdr res)
       (w/bless-apply-effect it)))
   fuel))

(provide 'wasp-bless)
;;; wasp-bless.el ends here