;ELC ;;; Compiled ;;; in Emacs version 26.3 ;;; with all optimizations. ;;; This file uses dynamic docstrings, first added in Emacs 19.29. ;;; This file does not contain utf-8 non-ASCII characters, ;;; and so can be loaded in Emacs versions earlier than 23. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (require 'cl-lib) #@78 *Name of buffer for fsm debug messages. If nil, don't output debug messages. (defvar fsm-debug "*fsm-debug*" (#$ . -426)) #@144 *Timestamp format (a string) for `fsm-debug-output'. Default format is whatever `current-time-string' returns followed by a colon and a space. (defvar fsm-debug-timestamp-format nil (#$ . -555)) #@130 Append debug output to buffer named by the variable `fsm-debug'. FORMAT and ARGS are passed to `format'. (fn FORMAT &rest ARGS) (defalias 'fsm-debug-output #[385 "\205%r\302!q\210\212db\210 \203\303 !\202\304 \305P\306\307#\310\261*\207" [fsm-debug fsm-debug-timestamp-format get-buffer-create format-time-string current-time-string ": " apply format "\n"] 7 (#$ . 757)]) #@824 Define a state machine class called NAME. A function called start-NAME is created, which uses the argument list and body specified in the :start argument. BODY should return a list of the form (STATE STATE-DATA [TIMEOUT]), where STATE is the initial state (defined by `define-state'), STATE-DATA is any object, and TIMEOUT is the number of seconds before a :timeout event will be sent to the state machine. BODY may refer to the instance being created through the dynamically bound variable `fsm'. SLEEP-FUNCTION, if provided, takes one argument, the number of seconds to sleep while allowing events concerning this state machine to happen. There is probably no reason to change the default, which is accept-process-output with rearranged arguments. (fn NAME :start ((ARG ...) DOCSTRING BODY) [:sleep SLEEP-FUNCTION]) (defalias 'define-state-machine '(macro . #[385 "\300\301\"A@\300\302\"A@\211\2037\211@\303>\203 \211AA\262\202 \304>A@\203.\305\262\202 \306\307@\"\210\202 \210\310\311\312\"!\305\211A\203O\211A\262\242\202V\313\314\305GD\"\211A\262\242@:\203s@@\315=\203s\211A\262\242C\262\211;\204|\306\316!\210\317\320\321 D\322BB\320\321\fD\323BB\324\325 \326\327\321DE\330\331\332\333\334\335!\336BBBDDC\337\340\317B\320\331\341\321DF\342\343\320\331\302\206\307\344F\345BBBBBBBED\"BBBBF\266\203\266\202\207" [plist-member :start :sleep (:start :sleep :allow-other-keys) :allow-other-keys nil error "Keyword argument %s not one of (:start :sleep)" intern format "start-%s" signal wrong-number-of-arguments interactive "Docstring is not a string" progn put quote (:fsm-enter (make-hash-table :size 11 :test 'eq)) (:fsm-event (make-hash-table :size 11 :test 'eq)) defun append fsm-debug-output "Starting %s" let fsm cl-gensym concat "fsm-" symbol-name ("-") cl-destructuring-bind (state state-data &optional timeout) :name (put fsm :state nil) (put fsm :state-data nil) (lambda (secs) (accept-process-output nil secs)) ((put fsm :deferred nil) (fsm-update fsm state state-data timeout) fsm)] 31 (#$ . 1147)])) (put 'define-state-machine 'edebug-form-spec '(&define name :name start &rest &or [":start" (lambda-list [&optional ("interactive" interactive)] stringp def-body)] [":sleep" function-form])) #@1092 Define a state called STATE-NAME in the state machine FSM-NAME. ARGLIST and BODY make a function that gets called when the state machine receives an event in this state. The arguments are: FSM the state machine instance (treat it as opaque) STATE-DATA An object EVENT The occurred event, an object. CALLBACK A function of one argument that expects the response to this event, if any (often `ignore' is used) If the event should return a response, the state machine should arrange to call CALLBACK at some point in the future (not necessarily in this handler). The function should return a list of the form (NEW-STATE NEW-STATE-DATA TIMEOUT): NEW-STATE The next state, a symbol NEW-STATE-DATA An object TIMEOUT A number: send timeout event after this many seconds nil: cancel existing timer :keep: let existing timer continue Alternatively, the function may return the keyword :defer, in which case the event will be resent when the state machine enters another state. (fn FSM-NAME STATE-NAME ARGLIST &body BODY) (defalias 'define-state '(macro . #[899 "\300\301\302D\303\302D\304BBE\305BBE\207" [setf gethash quote get (:fsm-event) lambda] 10 (#$ . 3417)])) (put 'define-state 'edebug-form-spec '(&define name name :name handler lambda-list def-body)) #@569 Define a function to call when FSM-NAME enters the state STATE-NAME. ARGLIST and BODY make a function that gets called when the state machine enters this state. The arguments are: FSM the state machine instance (treat it as opaque) STATE-DATA An object The function should return a list of the form (NEW-STATE-DATA TIMEOUT): NEW-STATE-DATA An object TIMEOUT A number: send timeout event after this many seconds nil: cancel existing timer :keep: let existing timer continue (fn FSM-NAME STATE-NAME ARGLIST &body BODY) (defalias 'define-enter-state '(macro . #[899 "\300\301\302D\303\302D\304BBE\305BBE\207" [setf gethash quote get (:fsm-enter) lambda] 10 (#$ . 4760)])) (put 'define-enter-state 'edebug-form-spec '(&define name name :name enter lambda-list def-body)) #@847 Define a state machine class called NAME, along with its STATES. This macro is (further) syntatic sugar for `define-state-machine', `define-state' and `define-enter-state' macros, q.v. NAME is a symbol. Everything else is specified with a keyword arg. START and SLEEP are the same as for `define-state-machine'. STATES is a list, each element having the form (STATE-NAME . STATE-SPEC). STATE-NAME is a symbol. STATE-SPEC is an alist with keys `:event' or `:enter', and values a series of expressions representing the BODY of a `define-state' or `define-enter-state' call, respectively. FSM-NAME, STATE-DATA-NAME, CALLBACK-NAME, and EVENT-NAME are symbols, used to construct the state functions' arglists. (fn NAME &key START SLEEP STATES (FSM-NAME \='fsm) (STATE-DATA-NAME \='state-data) (CALLBACK-NAME \='callback) (EVENT-NAME \='event)) (defalias 'define-fsm '(macro . #[385 "\300\301\"A@\300\302\"A@\300\303\"A@\300\304\"\206\305A@\300\306\"\206$\307A@\300\310\"\206/\311A@\300\312\"\206:\313A@\211\203i\211@\314>\203Q\211AA\262\202>\315 >A@\203`\316\262\202>\317\320@\"\210\202>\210\321\322\n\301\n\302 \257\316\211\211:\203\315@\262\211A\262\242\262\323\236\211\203\246\324  DABBBBB\262\210\325\236\211\203\305\326  \fFABBBBB\262\210A\262\202{\211\237\266\204BB\207" [plist-member :start :sleep :states :fsm-name (nil fsm) :state-data-name (nil state-data) :callback-name (nil callback) :event-name (nil event) (:start :sleep :states :fsm-name :state-data-name :callback-name :event-name :allow-other-keys) :allow-other-keys nil error "Keyword argument %s not one of (:start :sleep :states :fsm-name :state-data-name :callback-name :event-name)" progn define-state-machine :enter define-enter-state :event define-state] 23 (#$ . 5590)])) #@247 Unbind functions related to fsm NAME (a symbol). Includes start-NAME, and each fsm-NAME-STATE and fsm-NAME-enter-STATE. Functions are `fmakunbound', which will probably give (fatal) pause to any state machines using them. Return nil. (fn NAME) (defalias 'fsm-goodbye-cruel-world #[257 "\300\301\302\303\"!!\210\304\305\306N\211\262!\203\307!\210\310\306\"\210\305\311N\211\262!\2032\307!\210\310\311\"\210\210\304\207" [fmakunbound intern format "start-%s" nil hash-table-p :fsm-event clrhash cl-remprop :fsm-enter] 6 (#$ . 7412) "SUnbind function definitions for fsm named: "]) #@178 Send a timeout event to FSM after SECS seconds. The timer is canceled if another event occurs before, unless the event handler explicitly asks to keep the timer. (fn FSM SECS) (defalias 'fsm-start-timer #[514 "\300!\210\301\302\303\304\305\302%#\207" [fsm-stop-timer put :timeout run-with-timer nil fsm-send-sync] 11 (#$ . 8012)]) #@42 Stop the timeout timer of FSM. (fn FSM) (defalias 'fsm-stop-timer #[257 "\211\300N\301!\205\302!\210\303\300\304#\207" [:timeout timerp cancel-timer put nil] 6 (#$ . 8355)]) #@65 Change the timer of FSM according to TIMEOUT. (fn FSM TIMEOUT) (defalias 'fsm-maybe-change-timer #[514 "\211\247\203\n\300\"\207\211?\205\301!\207" [fsm-start-timer fsm-stop-timer] 5 (#$ . 8541)]) #@174 Send EVENT to FSM asynchronously. If the state machine generates a response, eventually call CALLBACK with the response as only argument. (fn FSM EVENT &optional CALLBACK) (defalias 'fsm-send #[770 "\300\301\302\303&\207" [run-with-timer 0 nil fsm-send-sync] 10 (#$ . 8752)]) #@99 Update FSM with NEW-STATE, NEW-STATE-DATA and TIMEOUT. (fn FSM NEW-STATE NEW-STATE-DATA TIMEOUT) (defalias 'fsm-update #[1028 "\300N\301N\302\301#\210\302\303#\210\304\"\210\211=?\205\241\305\306#\210\307\310N\"\311!\203|\305\312#\210\3131r\211\"\211G\314U\203W\211A\262\242\202^\315\316\317GD\"@\302\n\303#\210\304\n\"\266\2030\202{\305\320 $\262\210\210\321N\237\302\321\317#\210\211\211\205\235\211@\322\323\n#\210A\266\202\202\211\262\262\207" [:name :state put :state-data fsm-maybe-change-timer fsm-debug-output "%s enters %s" gethash :fsm-enter functionp "Found enter function for %s/%s" (debug error) 2 signal wrong-number-of-arguments nil "%s/%s update didn't work: %S" :deferred apply fsm-send-sync] 14 (#$ . 9042)]) #@173 Send EVENT to FSM synchronously. If the state machine generates a response, eventually call CALLBACK with the response as only argument. (fn FSM EVENT &optional CALLBACK) (defalias 'fsm-send-sync #[770 "\300 \301\302\303\304\305!\306\"\307$\216\310N\311N\312N\313\314N\"\315\316\242\206'$\210\3171B\211  \206=\320$0\202G\321B\262\211\322=\203b\323N\324\n\323  DB#\262\202\337\211\204r\315\325 $\202\337\211\242\321=\203\207\315\326\327A!$\202\337\211<\203\327\330GX\203\327\211G\307X\203\327\211\211A\203\251\211A\262\242\202\260\331\332\333GD\"\211A\262\242\211A\262\242\203\313\331\332\333\307G\\D\"\210\334 $\266\204\202\337\315\335$\262\266\204)\207" [match-data make-byte-code 0 "\301\300\302\"\207" vconcat vector [set-match-data evaporate] 3 :name :state :state-data gethash :fsm-event fsm-debug-output "Sent %S to %s in state %s" (debug error) ignore :error-signaled :defer :deferred put "Warning: event %S ignored in state %s/%s" "Error in %s/%s: %s" error-message-string 2 signal wrong-number-of-arguments nil fsm-update "Incorrect return value in %s/%s: %S"] 18 (#$ . 9832)]) #@123 Send EVENT to FSM synchronously, and wait for a reply. Return the reply. `with-timeout' might be useful. (fn FSM EVENT) (defalias 'fsm-call #[514 "\300C\301\302\303\304\305\306!\307\"\310\311%#\210\211\242\204!\312\313\"\210\202\211\242@\207" [nil fsm-send-sync make-byte-code 257 "\300C\240\207" vconcat vector [] 3 "\n\n(fn R)" fsm-sleep 1] 12 (#$ . 11003)]) #@116 Return a filter function that sends events to FSM. Events sent are of the form (:filter PROCESS STRING). (fn FSM) (defalias 'fsm-make-filter #[257 "\211\300\301\302\303\304!\305\"\306\307%\207" [make-byte-code 514 "\301\300\302E\"\207" vconcat vector [fsm-send-sync :filter] 7 "\n\n(fn PROCESS STRING)"] 8 (#$ . 11382)]) #@120 Return a sentinel function that sends events to FSM. Events sent are of the form (:sentinel PROCESS STRING). (fn FSM) (defalias 'fsm-make-sentinel #[257 "\211\300\301\302\303\304!\305\"\306\307%\207" [make-byte-code 514 "\301\300\302E\"\207" vconcat vector [fsm-send-sync :sentinel] 7 "\n\n(fn PROCESS STRING)"] 8 (#$ . 11714)]) #@80 Sleep up to SECS seconds in a way that lets FSM receive events. (fn FSM SECS) (defalias 'fsm-sleep #[514 "\300N!\207" [:sleep] 4 (#$ . 12053)]) #@167 Return the state data of FSM. Note the absence of a set function. The fsm should manage its state data itself; other code should just send messages to it. (fn FSM) (defalias 'fsm-get-state-data #[257 "\211\300N\207" [:state-data] 3 (#$ . 12207)]) (provide 'fsm)